Added support for OpenStack Ocata to NovaManager
This commit updates NovaManager for supporting the Ocata version BUG: #1704801 Change-Id: Icad9c14b14f34d16861caf82845b0e847085556c Sem-Ver: feature
This commit is contained in:
parent
94456be8fc
commit
5f28805ca7
@ -11,12 +11,6 @@ rate = 1
|
||||
# this allows Synergy to not check the whole queue when looking for VMs to start
|
||||
backfill_depth = 100
|
||||
|
||||
# set the notification topic used by Nova for informing listeners about the state
|
||||
# changes of the VMs. In case some other service (e.g. Ceilometer) is listening
|
||||
# on the default Nova topic (i.e. "notifications"), please define a new topic
|
||||
specific for Synergy (e.g. notification_topics = notifications,synergy_notifications)
|
||||
notification_topic = notifications
|
||||
|
||||
|
||||
[FairShareManager]
|
||||
autostart = True
|
||||
@ -139,7 +133,13 @@ conductor_topic = conductor
|
||||
compute_topic = compute
|
||||
|
||||
# set the Nova scheduler topic (default: scheduler)
|
||||
|
||||
scheduler_topic = scheduler
|
||||
# set the notification topic used by Nova for informing listeners about the state
|
||||
# changes of the VMs. In case some other service (e.g. Ceilometer) is listening
|
||||
# on the default Nova topic (i.e. "notifications"), please define a new topic
|
||||
specific for Synergy (e.g. notification_topics = notifications,synergy_notifications)
|
||||
notification_topic = notification
|
||||
|
||||
# set the Nova database connection
|
||||
db_connection=DIALECT+DRIVER://USER:PASSWORD@DB_HOST/nova
|
||||
|
@ -26,160 +26,122 @@ permissions and limitations under the License."""
|
||||
class Request(object):
|
||||
|
||||
def __init__(self):
|
||||
self.id = None
|
||||
self.user_id = None
|
||||
self.project_id = None
|
||||
self.action = None
|
||||
self.data = None
|
||||
self.context = None
|
||||
self.instance = None
|
||||
self.image = None
|
||||
self.filter_properties = None
|
||||
self.admin_password = None
|
||||
self.injected_files = None
|
||||
self.requested_networks = None
|
||||
self.security_groups = None
|
||||
self.block_device_mapping = None
|
||||
self.legacy_bdm = None
|
||||
self.server = None
|
||||
self.retry = None
|
||||
self.created_at = None
|
||||
|
||||
def getAdminPassword(self):
|
||||
return self.admin_password
|
||||
|
||||
def getId(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["uuid"]
|
||||
|
||||
return None
|
||||
|
||||
def getInstance(self):
|
||||
return self.instance
|
||||
|
||||
def getServer(self):
|
||||
server = None
|
||||
|
||||
if self.instance:
|
||||
instance_data = self.instance["nova_object.data"]
|
||||
flavor_data = instance_data["flavor"]["nova_object.data"]
|
||||
|
||||
flavor = Flavor()
|
||||
flavor.setId(flavor_data["flavorid"])
|
||||
flavor.setName(flavor_data["name"])
|
||||
flavor.setMemory(flavor_data["memory_mb"])
|
||||
flavor.setVCPUs(flavor_data["vcpus"])
|
||||
flavor.setStorage(flavor_data["root_gb"])
|
||||
|
||||
server = Server()
|
||||
server.setFlavor(flavor)
|
||||
server.setId(instance_data["uuid"])
|
||||
server.setUserId(instance_data["user_id"])
|
||||
server.setProjectId(instance_data["project_id"])
|
||||
server.setCreatedAt(instance_data["created_at"])
|
||||
server.setMetadata(instance_data["metadata"])
|
||||
server.setKeyName(instance_data["key_name"])
|
||||
|
||||
if "user_data" in instance_data:
|
||||
user_data = instance_data["user_data"]
|
||||
if user_data:
|
||||
server.setUserData(utils.decodeBase64(user_data))
|
||||
|
||||
return server
|
||||
|
||||
def getImage(self):
|
||||
return self.image
|
||||
|
||||
def getUserId(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["user_id"]
|
||||
|
||||
return None
|
||||
|
||||
def getProjectId(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["project_id"]
|
||||
|
||||
return None
|
||||
def getAction(self):
|
||||
return self.action
|
||||
|
||||
def getContext(self):
|
||||
return self.context
|
||||
|
||||
def getCreatedAt(self):
|
||||
if self.instance:
|
||||
created_at = self.instance["nova_object.data"]["created_at"]
|
||||
timestamp = datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%SZ")
|
||||
return timestamp
|
||||
return self.created_at
|
||||
|
||||
return 0
|
||||
def getData(self):
|
||||
return self.data
|
||||
|
||||
def getMetadata(self):
|
||||
if self.instance:
|
||||
return self.instance["nova_object.data"]["metadata"]
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
return None
|
||||
def getServer(self):
|
||||
return self.server
|
||||
|
||||
def getUserId(self):
|
||||
return self.user_id
|
||||
|
||||
def getProjectId(self):
|
||||
return self.project_id
|
||||
|
||||
def getRetry(self):
|
||||
if self.filter_properties:
|
||||
return self.filter_properties.get("retry", None)
|
||||
|
||||
return None
|
||||
|
||||
def getFilterProperties(self):
|
||||
return self.filter_properties
|
||||
|
||||
def getInjectedFiles(self):
|
||||
return self.injected_files
|
||||
|
||||
def getRequestedNetworks(self):
|
||||
return self.requested_networks
|
||||
|
||||
def getSecurityGroups(self):
|
||||
return self.security_groups
|
||||
|
||||
def getBlockDeviceMapping(self):
|
||||
return self.block_device_mapping
|
||||
|
||||
def getLegacyBDM(self):
|
||||
return self.legacy_bdm
|
||||
return self.retry
|
||||
|
||||
def toDict(self):
|
||||
request = {}
|
||||
request['action'] = self.action
|
||||
request['context'] = self.context
|
||||
request['instance'] = self.instance
|
||||
request['image'] = self.image
|
||||
request['filter_properties'] = self.filter_properties
|
||||
request['admin_password'] = self.admin_password
|
||||
request['injected_files'] = self.injected_files
|
||||
request['requested_networks'] = self.requested_networks
|
||||
request['security_groups'] = self.security_groups
|
||||
request['block_device_mapping'] = self.block_device_mapping
|
||||
request['legacy_bdm'] = self.legacy_bdm
|
||||
request['data'] = self.data
|
||||
|
||||
return request
|
||||
|
||||
@classmethod
|
||||
def fromDict(cls, request_dict):
|
||||
request = Request()
|
||||
request.context = request_dict['context']
|
||||
request.instance = request_dict['instance']
|
||||
request.image = request_dict['image']
|
||||
request.filter_properties = request_dict['filter_properties']
|
||||
request.admin_password = request_dict['admin_password']
|
||||
request.injected_files = request_dict['injected_files']
|
||||
request.requested_networks = request_dict['requested_networks']
|
||||
request.security_groups = request_dict['security_groups']
|
||||
request.block_device_mapping = request_dict['block_device_mapping']
|
||||
request.legacy_bdm = request_dict['legacy_bdm']
|
||||
|
||||
return request
|
||||
|
||||
@classmethod
|
||||
def build(cls, context, instance, image, filter_properties,
|
||||
admin_password, injected_files, requested_networks,
|
||||
security_groups, block_device_mapping=None, legacy_bdm=True):
|
||||
request = Request()
|
||||
request.context = context
|
||||
request.instance = instance
|
||||
request.image = image
|
||||
request.filter_properties = filter_properties
|
||||
request.admin_password = admin_password
|
||||
request.injected_files = injected_files
|
||||
request.requested_networks = requested_networks
|
||||
request.security_groups = security_groups
|
||||
request.block_device_mapping = block_device_mapping
|
||||
request.legacy_bdm = legacy_bdm
|
||||
request.data = request_dict["data"]
|
||||
request.action = request_dict["action"]
|
||||
request.context = request_dict["context"]
|
||||
|
||||
if "instances" in request.data:
|
||||
instance = request.data["instances"][0]
|
||||
else:
|
||||
build_request = request.data["build_requests"][0]
|
||||
instance = build_request["nova_object.data"]["instance"]
|
||||
|
||||
instance_data = instance["nova_object.data"]
|
||||
|
||||
request.id = instance_data["uuid"]
|
||||
request.user_id = instance_data["user_id"]
|
||||
request.project_id = instance_data["project_id"]
|
||||
|
||||
created_at = instance_data["created_at"]
|
||||
request.created_at = datetime.strptime(created_at,
|
||||
"%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
flavor_data = instance_data["flavor"]["nova_object.data"]
|
||||
flavor = Flavor()
|
||||
flavor.setId(flavor_data["flavorid"])
|
||||
flavor.setName(flavor_data["name"])
|
||||
flavor.setMemory(flavor_data["memory_mb"])
|
||||
flavor.setVCPUs(flavor_data["vcpus"])
|
||||
flavor.setStorage(flavor_data["root_gb"])
|
||||
|
||||
server = Server()
|
||||
server.setFlavor(flavor)
|
||||
server.setId(instance_data["uuid"])
|
||||
server.setUserId(instance_data["user_id"])
|
||||
server.setProjectId(instance_data["project_id"])
|
||||
server.setCreatedAt(instance_data["created_at"])
|
||||
server.setMetadata(instance_data["metadata"])
|
||||
server.setKeyName(instance_data["key_name"])
|
||||
|
||||
user_data = instance_data.get("user_data", None)
|
||||
if user_data:
|
||||
try:
|
||||
data = utils.decodeBase64(user_data)
|
||||
quota = utils.getConfigParameter(data, "quota", "synergy")
|
||||
if not quota:
|
||||
quota = utils.getConfigParameter(data, "quota")
|
||||
|
||||
metadata = instance_data.get("metadata", {})
|
||||
|
||||
if quota is None or quota == "private" or quota != "shared":
|
||||
server.setType("permanent")
|
||||
metadata["quota"] = "private"
|
||||
|
||||
elif quota == "shared":
|
||||
server.setType("ephemeral")
|
||||
metadata["quota"] = "shared"
|
||||
except Exception:
|
||||
server.setType("permanent")
|
||||
metadata["quota"] = "private"
|
||||
request.server = server
|
||||
|
||||
if "filter_properties" in request.data:
|
||||
filter_properties = request.data["filter_properties"]
|
||||
request.retry = filter_properties["retry"]
|
||||
else:
|
||||
request_spec = request.data["request_specs"][0]
|
||||
nova_object = request_spec["nova_object.data"]
|
||||
request.retry = nova_object["retry"]
|
||||
|
||||
if not request.retry:
|
||||
request.retry = {}
|
||||
|
||||
return request
|
||||
|
@ -42,18 +42,101 @@ LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class ServerEventHandler(object):
|
||||
|
||||
def __init__(self, nova_manager):
|
||||
super(ServerEventHandler, self).__init__()
|
||||
|
||||
self.nova_manager = nova_manager
|
||||
|
||||
def _makeServer(self, server_info):
|
||||
if not server_info:
|
||||
return
|
||||
|
||||
flavor = Flavor()
|
||||
flavor.setMemory(server_info["memory_mb"])
|
||||
flavor.setVCPUs(server_info["vcpus"])
|
||||
flavor.setStorage(server_info["root_gb"])
|
||||
|
||||
if "instance_type" in server_info:
|
||||
flavor.setName(server_info["instance_type"])
|
||||
|
||||
server = Server()
|
||||
server.setFlavor(flavor)
|
||||
server.setUserId(server_info["user_id"])
|
||||
server.setMetadata(server_info["metadata"])
|
||||
server.setDeletedAt(server_info["deleted_at"])
|
||||
server.setTerminatedAt(server_info["terminated_at"])
|
||||
|
||||
if "host" in server_info:
|
||||
server.setHost(server_info["host"])
|
||||
|
||||
if "uuid" in server_info:
|
||||
server.setId(server_info["uuid"])
|
||||
elif "instance_id" in server_info:
|
||||
server.setId(server_info["instance_id"])
|
||||
|
||||
if "project_id" in server_info:
|
||||
server.setProjectId(server_info["project_id"])
|
||||
elif "tenant_id" in server_info:
|
||||
server.setProjectId(server_info["tenant_id"])
|
||||
|
||||
if "vm_state" in server_info:
|
||||
server.setState(server_info["vm_state"])
|
||||
elif "state" in server_info:
|
||||
server.setState(server_info["state"])
|
||||
|
||||
return server
|
||||
|
||||
def info(self, ctxt, publisher_id, event_type, payload, metadata):
|
||||
LOG.debug("Notification INFO: event_type=%s payload=%s"
|
||||
% (event_type, payload))
|
||||
|
||||
if payload is None or "state" not in payload:
|
||||
return
|
||||
|
||||
state = payload["state"]
|
||||
|
||||
event_types = ["compute.instance.create.end",
|
||||
"compute.instance.delete.end",
|
||||
"compute.instance.update",
|
||||
"scheduler.run_instance"]
|
||||
|
||||
if event_type not in event_types:
|
||||
return
|
||||
|
||||
server_info = None
|
||||
|
||||
if event_type == "scheduler.run_instance":
|
||||
server_info = payload["request_spec"]["instance_type"]
|
||||
else:
|
||||
server_info = payload
|
||||
|
||||
server = self._makeServer(server_info)
|
||||
|
||||
self.nova_manager.notify(event_type="SERVER_EVENT", server=server,
|
||||
event=event_type, state=state)
|
||||
|
||||
def warn(self, ctxt, publisher_id, event_type, payload, metadata):
|
||||
LOG.debug("Notification WARN: event_type=%s, payload=%s metadata=%s"
|
||||
% (event_type, payload, metadata))
|
||||
|
||||
def error(self, ctxt, publisher_id, event_type, payload, metadata):
|
||||
LOG.debug("Notification ERROR: event_type=%s, payload=%s metadata=%s"
|
||||
% (event_type, payload, metadata))
|
||||
|
||||
|
||||
class NovaConductorComputeAPI(object):
|
||||
|
||||
def __init__(self, topic, scheduler_manager, keystone_manager, msg):
|
||||
self.topic = topic
|
||||
self.scheduler_manager = scheduler_manager
|
||||
self.keystone_manager = keystone_manager
|
||||
self.target = msg.getTarget(topic=topic + "_synergy",
|
||||
def __init__(self, synergy_topic, conductor_topic, nova_manager, msg):
|
||||
self.nova_manager = nova_manager
|
||||
|
||||
self.target = msg.getTarget(topic=synergy_topic,
|
||||
namespace="compute_task",
|
||||
version="1.10")
|
||||
version="1.16")
|
||||
|
||||
self.client = msg.getRPCClient(
|
||||
target=msg.getTarget(topic=topic,
|
||||
target=msg.getTarget(topic=conductor_topic,
|
||||
namespace="compute_task",
|
||||
version="1.10"))
|
||||
|
||||
@ -62,66 +145,75 @@ class NovaConductorComputeAPI(object):
|
||||
security_groups, block_device_mapping=None,
|
||||
legacy_bdm=True):
|
||||
for instance in instances:
|
||||
data = {'instances': [instance],
|
||||
'image': image,
|
||||
'filter_properties': filter_properties,
|
||||
'admin_password': admin_password,
|
||||
'injected_files': injected_files,
|
||||
'requested_networks': requested_networks,
|
||||
'security_groups': security_groups,
|
||||
'block_device_mapping': block_device_mapping,
|
||||
'legacy_bdm': legacy_bdm}
|
||||
|
||||
req = {"context": context, "data": data,
|
||||
"action": "build_instances"}
|
||||
try:
|
||||
request = Request.build(context, instance, image,
|
||||
filter_properties, admin_password,
|
||||
injected_files, requested_networks,
|
||||
security_groups, block_device_mapping,
|
||||
legacy_bdm)
|
||||
request = Request.fromDict(req)
|
||||
|
||||
self.scheduler_manager.processRequest(request)
|
||||
self.nova_manager.notify(event_type="SERVER_CREATE",
|
||||
request=request)
|
||||
except Exception as ex:
|
||||
LOG.error("Exception has occured", exc_info=1)
|
||||
LOG.error(ex)
|
||||
LOG.info(ex)
|
||||
|
||||
def build_instance(self, context, instance, image, filter_properties,
|
||||
admin_password, injected_files, requested_networks,
|
||||
security_groups, block_device_mapping=None,
|
||||
legacy_bdm=True):
|
||||
kw = {'instances': [instance],
|
||||
'image': image,
|
||||
'filter_properties': filter_properties,
|
||||
'admin_password': admin_password,
|
||||
'injected_files': injected_files,
|
||||
'requested_networks': requested_networks,
|
||||
'security_groups': security_groups}
|
||||
def schedule_and_build_instances(self, context, build_requests,
|
||||
request_specs, image,
|
||||
admin_password, injected_files,
|
||||
requested_networks, block_device_mapping):
|
||||
index = 0
|
||||
|
||||
for build_request in build_requests:
|
||||
request_spec = request_specs[index]
|
||||
|
||||
index += 1
|
||||
|
||||
data = {'build_requests': [build_request],
|
||||
'request_specs': [request_spec],
|
||||
'image': image,
|
||||
'admin_password': admin_password,
|
||||
'injected_files': injected_files,
|
||||
'requested_networks': requested_networks,
|
||||
'block_device_mapping': block_device_mapping}
|
||||
|
||||
req = {"context": context, "data": data,
|
||||
"action": "schedule_and_build_instances"}
|
||||
|
||||
request = Request.fromDict(req)
|
||||
|
||||
self.nova_manager.notify(event_type="SERVER_CREATE",
|
||||
request=request)
|
||||
|
||||
def build_instance(self, context, action, data):
|
||||
try:
|
||||
cctxt = self.client.prepare()
|
||||
cctxt.cast(context, action, **data)
|
||||
except Exception as ex:
|
||||
LOG.info(ex)
|
||||
|
||||
def migrate_server(self, context, **kwargs):
|
||||
cctxt = self.client.prepare()
|
||||
cctxt.cast(context, 'build_instances', **kw)
|
||||
|
||||
def migrate_server(self, context, instance, scheduler_hint, live, rebuild,
|
||||
flavor, block_migration, disk_over_commit,
|
||||
reservations=None, clean_shutdown=True,
|
||||
request_spec=None):
|
||||
kw = {'instance': instance, 'scheduler_hint': scheduler_hint,
|
||||
'live': live, 'rebuild': rebuild, 'flavor': flavor,
|
||||
'block_migration': block_migration,
|
||||
'disk_over_commit': disk_over_commit,
|
||||
'reservations': reservations,
|
||||
'clean_shutdown': clean_shutdown,
|
||||
'request_spec': request_spec,
|
||||
}
|
||||
return cctxt.call(context, 'migrate_server', **kwargs)
|
||||
|
||||
def unshelve_instance(self, context, **kwargs):
|
||||
cctxt = self.client.prepare()
|
||||
return cctxt.call(context, 'migrate_server', **kw)
|
||||
cctxt.cast(context, 'unshelve_instance', **kwargs)
|
||||
|
||||
def unshelve_instance(self, context, instance):
|
||||
cctxt = self.client.prepare(version='1.3')
|
||||
cctxt.cast(context, 'unshelve_instance', instance=instance)
|
||||
def rebuild_instance(self, ctxt, **kwargs):
|
||||
cctxt = self.client.prepare()
|
||||
cctxt.cast(ctxt, 'rebuild_instance', **kwargs)
|
||||
|
||||
def rebuild_instance(self, ctxt, instance, new_pass, injected_files,
|
||||
image_ref, orig_image_ref, orig_sys_metadata, bdms,
|
||||
recreate=False, on_shared_storage=False, host=None,
|
||||
preserve_ephemeral=False, kwargs=None):
|
||||
cctxt = self.client.prepare(version='1.8')
|
||||
cctxt.cast(ctxt, 'rebuild_instance',
|
||||
instance=instance, new_pass=new_pass,
|
||||
injected_files=injected_files, image_ref=image_ref,
|
||||
orig_image_ref=orig_image_ref,
|
||||
orig_sys_metadata=orig_sys_metadata, bdms=bdms,
|
||||
recreate=recreate, on_shared_storage=on_shared_storage,
|
||||
preserve_ephemeral=preserve_ephemeral,
|
||||
host=host)
|
||||
def resize_instance(self, ctxt, **kwargs):
|
||||
cctxt = self.client.prepare()
|
||||
cctxt.cast(ctxt, 'resize_instance', **kwargs)
|
||||
|
||||
|
||||
class NovaManager(Manager):
|
||||
@ -170,6 +262,10 @@ class NovaManager(Manager):
|
||||
help="the Synergy topic",
|
||||
default="synergy",
|
||||
required=False),
|
||||
cfg.StrOpt("notification_topic",
|
||||
help="the notifiction topic",
|
||||
default="notifications",
|
||||
required=False),
|
||||
cfg.StrOpt("conductor_topic",
|
||||
help="the conductor topic",
|
||||
default="conductor",
|
||||
@ -231,7 +327,6 @@ class NovaManager(Manager):
|
||||
raise Exception("SchedulerManager not found!")
|
||||
|
||||
self.keystone_manager = self.getManager("KeystoneManager")
|
||||
self.scheduler_manager = self.getManager("SchedulerManager")
|
||||
|
||||
amqp_url = self.getParameter("amqp_url")
|
||||
|
||||
@ -257,6 +352,8 @@ class NovaManager(Manager):
|
||||
|
||||
synergy_topic = self.getParameter("synergy_topic")
|
||||
|
||||
notification_topic = self.getParameter("notification_topic")
|
||||
|
||||
conductor_topic = self.getParameter("conductor_topic")
|
||||
|
||||
self.getParameter("metadata_proxy_shared_secret", fallback=True)
|
||||
@ -275,9 +372,9 @@ class NovaManager(Manager):
|
||||
exchange=amqp_exchange)
|
||||
|
||||
self.novaConductorComputeAPI = NovaConductorComputeAPI(
|
||||
synergy_topic,
|
||||
conductor_topic,
|
||||
self.scheduler_manager,
|
||||
self.keystone_manager,
|
||||
self,
|
||||
self.messaging)
|
||||
|
||||
self.conductor_rpc = self.messaging.getRPCServer(
|
||||
@ -286,13 +383,23 @@ class NovaManager(Manager):
|
||||
endpoints=[self.novaConductorComputeAPI])
|
||||
|
||||
self.conductor_rpc.start()
|
||||
|
||||
self.serverEventHandler = ServerEventHandler(self)
|
||||
|
||||
target = self.messaging.getTarget(topic=notification_topic,
|
||||
exchange=amqp_exchange)
|
||||
|
||||
self.listener = self.messaging.getNotificationListener(
|
||||
targets=[target], endpoints=[self.serverEventHandler])
|
||||
|
||||
self.listener.start()
|
||||
except Exception as ex:
|
||||
LOG.error("Exception has occured", exc_info=1)
|
||||
LOG.error("NovaManager initialization failed! %s" % (ex))
|
||||
raise ex
|
||||
|
||||
def execute(self, command, *args, **kargs):
|
||||
raise Exception("command=%r not supported!" % command)
|
||||
raise Exception("command %r not supported!" % command)
|
||||
|
||||
def task(self):
|
||||
pass
|
||||
@ -496,36 +603,11 @@ class NovaManager(Manager):
|
||||
|
||||
return server
|
||||
|
||||
def buildServer(self, request, compute=None):
|
||||
if compute:
|
||||
reqId = request.getId()
|
||||
|
||||
self.novaComputeAPI.build_and_run_instance(
|
||||
request.getContext(),
|
||||
request.getInstance(),
|
||||
compute.getHost(),
|
||||
request.getImage(),
|
||||
request.getInstance(),
|
||||
request.getFilterProperties(),
|
||||
admin_password=request.getAdminPassword(),
|
||||
injected_files=request.getInjectedFiles(),
|
||||
requested_networks=request.getRequestedNetworks(),
|
||||
security_groups=request.getSecurityGroups(),
|
||||
block_device_mapping=self.getBlockDeviceMappingList(reqId),
|
||||
node=compute.getNodeName(),
|
||||
limits=compute.getLimits())
|
||||
else:
|
||||
self.novaConductorComputeAPI.build_instance(
|
||||
context=request.getContext(),
|
||||
instance=request.getInstance(),
|
||||
image=request.getImage(),
|
||||
filter_properties=request.getFilterProperties(),
|
||||
admin_password=request.getAdminPassword(),
|
||||
injected_files=request.getInjectedFiles(),
|
||||
requested_networks=request.getRequestedNetworks(),
|
||||
security_groups=request.getSecurityGroups(),
|
||||
block_device_mapping=request.getBlockDeviceMapping(),
|
||||
legacy_bdm=request.getLegacyBDM())
|
||||
def buildServer(self, request):
|
||||
self.novaConductorComputeAPI.build_instance(
|
||||
request.getContext(),
|
||||
request.getAction(),
|
||||
request.getData())
|
||||
|
||||
def deleteServer(self, server):
|
||||
if not server:
|
||||
@ -564,33 +646,6 @@ class NovaManager(Manager):
|
||||
|
||||
return response_data
|
||||
|
||||
def setQuotaTypeServer(self, server):
|
||||
if not server:
|
||||
return
|
||||
|
||||
QUERY = "insert into nova.instance_metadata (created_at, `key`, " \
|
||||
"`value`, instance_uuid) values (%s, 'quota', %s, %s)"
|
||||
|
||||
connection = self.db_engine.connect()
|
||||
trans = connection.begin()
|
||||
|
||||
quota_type = "private"
|
||||
|
||||
if server.isEphemeral():
|
||||
quota_type = "shared"
|
||||
|
||||
try:
|
||||
connection.execute(QUERY,
|
||||
[server.getCreatedAt(), quota_type,
|
||||
server.getId()])
|
||||
|
||||
trans.commit()
|
||||
except SQLAlchemyError as ex:
|
||||
trans.rollback()
|
||||
raise Exception(ex.message)
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
def stopServer(self, server):
|
||||
if not server:
|
||||
return
|
||||
|
@ -1,9 +1,7 @@
|
||||
import logging
|
||||
|
||||
from common.flavor import Flavor
|
||||
from common.quota import SharedQuota
|
||||
from common.request import Request
|
||||
from common.server import Server
|
||||
from oslo_config import cfg
|
||||
from synergy.common.manager import Manager
|
||||
from synergy.exception import SynergyError
|
||||
@ -32,125 +30,6 @@ CONF = cfg.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Notifications(object):
|
||||
|
||||
def __init__(self, projects, nova_manager):
|
||||
super(Notifications, self).__init__()
|
||||
|
||||
self.projects = projects
|
||||
self.nova_manager = nova_manager
|
||||
|
||||
def _makeServer(self, server_info):
|
||||
if not server_info:
|
||||
return
|
||||
|
||||
flavor = Flavor()
|
||||
flavor.setMemory(server_info["memory_mb"])
|
||||
flavor.setVCPUs(server_info["vcpus"])
|
||||
flavor.setStorage(server_info["root_gb"])
|
||||
|
||||
if "instance_type" in server_info:
|
||||
flavor.setName(server_info["instance_type"])
|
||||
|
||||
server = Server()
|
||||
server.setFlavor(flavor)
|
||||
server.setUserId(server_info["user_id"])
|
||||
server.setMetadata(server_info["metadata"])
|
||||
server.setDeletedAt(server_info["deleted_at"])
|
||||
server.setTerminatedAt(server_info["terminated_at"])
|
||||
|
||||
if "host" in server_info:
|
||||
server.setHost(server_info["host"])
|
||||
|
||||
if "uuid" in server_info:
|
||||
server.setId(server_info["uuid"])
|
||||
elif "instance_id" in server_info:
|
||||
server.setId(server_info["instance_id"])
|
||||
|
||||
if "project_id" in server_info:
|
||||
server.setProjectId(server_info["project_id"])
|
||||
elif "tenant_id" in server_info:
|
||||
server.setProjectId(server_info["tenant_id"])
|
||||
|
||||
if "vm_state" in server_info:
|
||||
server.setState(server_info["vm_state"])
|
||||
elif "state" in server_info:
|
||||
server.setState(server_info["state"])
|
||||
|
||||
return server
|
||||
|
||||
def info(self, ctxt, publisher_id, event_type, payload, metadata):
|
||||
LOG.debug("Notification INFO: event_type=%s payload=%s"
|
||||
% (event_type, payload))
|
||||
|
||||
if payload is None or "state" not in payload:
|
||||
return
|
||||
|
||||
state = payload["state"]
|
||||
|
||||
event_types = ["compute.instance.create.end",
|
||||
"compute.instance.delete.end",
|
||||
"compute.instance.update",
|
||||
"scheduler.run_instance"]
|
||||
|
||||
if event_type not in event_types:
|
||||
return
|
||||
|
||||
server_info = None
|
||||
|
||||
if event_type == "scheduler.run_instance":
|
||||
server_info = payload["request_spec"]["instance_type"]
|
||||
else:
|
||||
server_info = payload
|
||||
|
||||
server = self._makeServer(server_info)
|
||||
server_id = server.getId()
|
||||
host = server.getHost()
|
||||
|
||||
if server.getProjectId() not in self.projects:
|
||||
return
|
||||
|
||||
if event_type == "compute.instance.create.end" and \
|
||||
state == "active":
|
||||
LOG.info("the server %s is now active on host %s"
|
||||
% (server_id, host))
|
||||
else:
|
||||
quota = self.projects[server.getProjectId()].getQuota()
|
||||
|
||||
if event_type == "compute.instance.delete.end":
|
||||
LOG.info("the server %s has been deleted on host %s"
|
||||
% (server_id, host))
|
||||
try:
|
||||
quota.release(server)
|
||||
except Exception as ex:
|
||||
LOG.warn("cannot release server %s "
|
||||
"(reason=%s)" % (server_id, ex))
|
||||
elif state == "error":
|
||||
LOG.info("error occurred on server %s (host %s)"
|
||||
% (server_id, host))
|
||||
|
||||
if not server.getTerminatedAt() and not server.getDeletedAt():
|
||||
try:
|
||||
self.nova_manager.deleteServer(server)
|
||||
except Exception as ex:
|
||||
LOG.error("cannot delete server %s: %s"
|
||||
% (server_id, ex))
|
||||
|
||||
try:
|
||||
quota.release(server)
|
||||
except Exception as ex:
|
||||
LOG.warn("cannot release server %s "
|
||||
"(reason=%s)" % (server_id, ex))
|
||||
|
||||
def warn(self, ctxt, publisher_id, event_type, payload, metadata):
|
||||
LOG.debug("Notification WARN: event_type=%s, payload=%s metadata=%s"
|
||||
% (event_type, payload, metadata))
|
||||
|
||||
def error(self, ctxt, publisher_id, event_type, payload, metadata):
|
||||
LOG.debug("Notification ERROR: event_type=%s, payload=%s metadata=%s"
|
||||
% (event_type, payload, metadata))
|
||||
|
||||
|
||||
class Worker(Thread):
|
||||
|
||||
def __init__(self, name, queue, project_manager, nova_manager,
|
||||
@ -259,8 +138,8 @@ class Worker(Thread):
|
||||
try:
|
||||
self.nova_manager.buildServer(request)
|
||||
|
||||
LOG.info("building server %s (user_id=%s prj_id=%s quo"
|
||||
"ta=shared)" % (server_id, user_id, prj_id))
|
||||
LOG.info("building server %s user_id=%s prj_id=%s quo"
|
||||
"ta=shared" % (server_id, user_id, prj_id))
|
||||
|
||||
found = True
|
||||
except SynergyError as ex:
|
||||
@ -290,7 +169,6 @@ class SchedulerManager(Manager):
|
||||
super(SchedulerManager, self).__init__("SchedulerManager")
|
||||
|
||||
self.config_opts = [
|
||||
cfg.StrOpt("notification_topic", default="notifications"),
|
||||
cfg.IntOpt("backfill_depth", default=100),
|
||||
]
|
||||
self.workers = []
|
||||
@ -321,9 +199,6 @@ class SchedulerManager(Manager):
|
||||
self.fairshare_manager = self.getManager("FairShareManager")
|
||||
self.project_manager = self.getManager("ProjectManager")
|
||||
self.backfill_depth = CONF.SchedulerManager.backfill_depth
|
||||
self.notification_topic = CONF.SchedulerManager.notification_topic
|
||||
self.projects = {}
|
||||
self.listener = None
|
||||
self.exit = False
|
||||
self.configured = False
|
||||
|
||||
@ -354,25 +229,62 @@ class SchedulerManager(Manager):
|
||||
|
||||
self.workers.append(dynamic_worker)
|
||||
|
||||
self.notifications = Notifications(self.projects, self.nova_manager)
|
||||
|
||||
target = self.nova_manager.getTarget(topic=self.notification_topic,
|
||||
exchange="nova")
|
||||
|
||||
self.listener = self.nova_manager.getNotificationListener(
|
||||
targets=[target],
|
||||
endpoints=[self.notifications])
|
||||
|
||||
self.quota_manager.deleteExpiredServers()
|
||||
|
||||
self.listener.start()
|
||||
self.configured = True
|
||||
|
||||
def destroy(self):
|
||||
for queue_worker in self.workers:
|
||||
queue_worker.destroy()
|
||||
|
||||
def processRequest(self, request):
|
||||
def doOnEvent(self, event_type, *args, **kwargs):
|
||||
if event_type == "SERVER_EVENT":
|
||||
server = kwargs["server"]
|
||||
event = kwargs["event"]
|
||||
state = kwargs["state"]
|
||||
|
||||
self._processServerEvent(server, event, state)
|
||||
elif event_type == "SERVER_CREATE":
|
||||
self._processServerCreate(kwargs["request"])
|
||||
|
||||
def _processServerEvent(self, server, event, state):
|
||||
if event == "compute.instance.create.end" and state == "active":
|
||||
LOG.info("the server %s is now active on host %s"
|
||||
% (server.getId(), server.getHost()))
|
||||
else:
|
||||
project = self.project_manager.getProject(id=server.getProjectId())
|
||||
|
||||
if not project:
|
||||
return
|
||||
|
||||
quota = project.getQuota()
|
||||
|
||||
if event == "compute.instance.delete.end":
|
||||
LOG.info("the server %s has been deleted on host %s"
|
||||
% (server.getId(), server.getHost()))
|
||||
try:
|
||||
quota.release(server)
|
||||
except Exception as ex:
|
||||
LOG.warn("cannot release server %s "
|
||||
"(reason=%s)" % (server.getId(), ex))
|
||||
elif state == "error":
|
||||
LOG.info("error occurred on server %s (host %s)"
|
||||
% (server.getId(), server.getHost()))
|
||||
|
||||
if not server.getTerminatedAt() and not server.getDeletedAt():
|
||||
try:
|
||||
self.nova_manager.deleteServer(server)
|
||||
except Exception as ex:
|
||||
LOG.error("cannot delete server %s: %s"
|
||||
% (server.getId(), ex))
|
||||
|
||||
try:
|
||||
quota.release(server)
|
||||
except Exception as ex:
|
||||
LOG.warn("cannot release server %s "
|
||||
"(reason=%s)" % (server.getId(), ex))
|
||||
|
||||
def _processServerCreate(self, request):
|
||||
server = request.getServer()
|
||||
|
||||
project = self.project_manager.getProject(id=request.getProjectId())
|
||||
@ -391,8 +303,8 @@ class SchedulerManager(Manager):
|
||||
if 0 < num_attempts < 3:
|
||||
self.nova_manager.buildServer(request)
|
||||
|
||||
LOG.info("retrying to build the server %s (user_id"
|
||||
"=%s prj_id=%s, num_attempts=%s, reason=%s)"
|
||||
LOG.info("retrying to build the server %s user_id"
|
||||
"=%s prj_id=%s, num_attempts=%s, reason=%s"
|
||||
% (request.getId(), request.getUserId(),
|
||||
request.getProjectId(), num_attempts, reason))
|
||||
return
|
||||
@ -405,10 +317,10 @@ class SchedulerManager(Manager):
|
||||
request.getProjectId()))
|
||||
|
||||
self.nova_manager.buildServer(request)
|
||||
LOG.info("building server %s (user_id=%s prj_id=%s "
|
||||
"quota=private)" % (server.getId(),
|
||||
request.getUserId(),
|
||||
request.getProjectId()))
|
||||
LOG.info("building server %s user_id=%s prj_id=%s "
|
||||
"quota=private" % (server.getId(),
|
||||
request.getUserId(),
|
||||
request.getProjectId()))
|
||||
else:
|
||||
self.nova_manager.deleteServer(server)
|
||||
LOG.info("request rejected (quota exceeded): "
|
||||
|
@ -13,18 +13,14 @@
|
||||
from mock import create_autospec
|
||||
from mock import MagicMock
|
||||
from sqlalchemy.engine.base import Engine
|
||||
from synergy_scheduler_manager.common.flavor import Flavor
|
||||
from synergy_scheduler_manager.common.project import Project
|
||||
from synergy_scheduler_manager.common.queue import QueueDB
|
||||
from synergy_scheduler_manager.common.queue import QueueItem
|
||||
from synergy_scheduler_manager.common.quota import SharedQuota
|
||||
from synergy_scheduler_manager.common.server import Server
|
||||
from synergy_scheduler_manager.project_manager import ProjectManager
|
||||
from synergy_scheduler_manager.scheduler_manager import Notifications
|
||||
from synergy_scheduler_manager.scheduler_manager import Worker
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
|
||||
"""
|
||||
class TestNotifications(base.TestCase):
|
||||
|
||||
def test_info_quota(self):
|
||||
@ -120,6 +116,7 @@ class TestNotifications(base.TestCase):
|
||||
|
||||
self.assertEqual(0, SharedQuota.getUsage('vcpus'))
|
||||
self.assertEqual(0, SharedQuota.getUsage('memory'))
|
||||
"""
|
||||
|
||||
|
||||
class TestWorker(base.TestCase):
|
||||
|
@ -10,6 +10,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from datetime import datetime
|
||||
from synergy_scheduler_manager.common.request import Request
|
||||
from synergy_scheduler_manager.tests.unit import base
|
||||
|
||||
@ -18,414 +19,278 @@ class TestRequest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRequest, self).setUp()
|
||||
request_specs = [{
|
||||
'nova_object.version': '1.8',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.name': u'RequestSpec',
|
||||
'nova_object.data': {
|
||||
'requested_destination': None,
|
||||
'instance_uuid': '999',
|
||||
'retry': {
|
||||
'num_attempts': 1,
|
||||
'hosts': []},
|
||||
'num_instances': 1,
|
||||
'pci_requests': {
|
||||
'nova_object.version': '1.1',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.name': 'InstancePCIRequests',
|
||||
'nova_object.data': {'requests': []},
|
||||
'nova_object.changes': ['requests']},
|
||||
'limits': {
|
||||
'nova_object.version': '1.0',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.name': 'SchedulerLimits',
|
||||
'nova_object.data': {
|
||||
'vcpu': None,
|
||||
'memory_mb': None,
|
||||
'numa_topology': None,
|
||||
'disk_gb': None},
|
||||
'nova_object.changes': [
|
||||
'vcpu', 'memory_mb', 'numa_topology', 'disk_gb']},
|
||||
'availability_zone': 'nova',
|
||||
'force_nodes': None,
|
||||
'image': {
|
||||
'nova_object.version': '1.8',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.name': 'ImageMeta',
|
||||
'nova_object.data': {
|
||||
'status': 'active',
|
||||
'properties': {
|
||||
'nova_object.version': '1.16',
|
||||
'nova_object.name': 'ImageMetaProps',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {}},
|
||||
'name': 'cirros',
|
||||
'container_format': 'bare',
|
||||
'created_at': '2017-05-19T12:18:46Z',
|
||||
'disk_format': 'qcow2',
|
||||
'updated_at': '2017-05-19T12:18:47Z',
|
||||
'id': '03d54ef8-f0ac-4ad2-92a0-95835d77d2b5',
|
||||
'owner': u'01ab8de5387547d093aa8ae6b85bd8b1',
|
||||
'checksum': 'f8ab98ff5e73ebab884d80c9dc9c7290',
|
||||
'min_disk': 0,
|
||||
'min_ram': 0,
|
||||
'size': 13267968},
|
||||
'nova_object.changes': [
|
||||
'status', 'name', 'container_format', 'created_at',
|
||||
'disk_format', 'updated_at', 'properties', 'owner',
|
||||
'min_ram', 'checksum', 'min_disk', 'id', 'size']},
|
||||
'instance_group': None,
|
||||
'force_hosts': None,
|
||||
'numa_topology': None,
|
||||
'scheduler_hints': {},
|
||||
'flavor': {
|
||||
'nova_object.version': '1.1',
|
||||
'nova_object.name': 'Flavor',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {
|
||||
'memory_mb': 512,
|
||||
'root_gb': 1,
|
||||
'deleted_at': None,
|
||||
'name': 'm1.tiny',
|
||||
'deleted': False,
|
||||
'created_at': '2017-05-23T09:36:21Z',
|
||||
'ephemeral_gb': 0,
|
||||
'updated_at': None,
|
||||
'disabled': False,
|
||||
'vcpus': 1,
|
||||
'extra_specs': {},
|
||||
'swap': 0,
|
||||
'rxtx_factor': 1.0,
|
||||
'is_public': True,
|
||||
'flavorid': '5cdecdda',
|
||||
'vcpu_weight': 0,
|
||||
'id': 1}},
|
||||
'project_id': u'01ab8de5387547d093aa8ae6b85bd8b1',
|
||||
'id': 126,
|
||||
'security_groups': {
|
||||
'nova_object.version': '1.0',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.name': 'SecurityGroupList',
|
||||
'nova_object.data': {
|
||||
'objects': [{
|
||||
'nova_object.version': '1.2',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.name': 'SecurityGroup',
|
||||
'nova_object.data': {'uuid': 'f5b58bc9'},
|
||||
'nova_object.changes': ['uuid']}]},
|
||||
'nova_object.changes': ['objects']},
|
||||
'ignore_hosts': None},
|
||||
'nova_object.changes': ['limits', 'image', 'pci_requests']}]
|
||||
|
||||
req_dict = {
|
||||
'legacy_bdm': True,
|
||||
'requested_networks': None,
|
||||
'injected_files': [],
|
||||
'block_device_mapping': None,
|
||||
'image': {
|
||||
u'status': u'active',
|
||||
u'created_at': u'2016-03-23T16:47:10.000000',
|
||||
u'name': u'cirros',
|
||||
u'deleted': False,
|
||||
u'container_format': u'bare',
|
||||
u'min_ram': 0,
|
||||
u'disk_format': u'qcow2',
|
||||
u'updated_at': u'2016-03-23T16:47:10.000000',
|
||||
u'properties': {},
|
||||
u'owner': u'1a6edd87f9ec41d8aa64c8f23d719c2a',
|
||||
u'checksum': u'ee1eca47dc88f4879d8a229cc70a07c6',
|
||||
u'min_disk': 0,
|
||||
u'is_public': True,
|
||||
u'deleted_at': None,
|
||||
u'id': u'5100f480-a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'size': 13287936},
|
||||
'filter_properties': {
|
||||
u'instance_type': {
|
||||
u'nova_object.version': u'1.1',
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'memory_mb': 512,
|
||||
u'root_gb': 1,
|
||||
u'deleted_at': None,
|
||||
u'name': u'm1.tiny',
|
||||
u'deleted': False,
|
||||
u'created_at': None,
|
||||
u'ephemeral_gb': 0,
|
||||
u'updated_at': None,
|
||||
u'disabled': False,
|
||||
u'vcpus': 1,
|
||||
u'extra_specs': {},
|
||||
u'swap': 0,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'is_public': True,
|
||||
u'flavorid': u'1',
|
||||
u'vcpu_weight': 0,
|
||||
u'id': 2}},
|
||||
u'scheduler_hints': {}},
|
||||
'instance': {
|
||||
u'nova_object.version': u'2.0',
|
||||
u'nova_object.name': u'Instance',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'vm_state': u'building',
|
||||
u'pci_requests': {
|
||||
u'nova_object.version': u'1.1',
|
||||
u'nova_object.name': u'InstancePCIRequests',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'instance_uuid': u'e3a7770a-8875e2ccc68b',
|
||||
u'requests': []}},
|
||||
u'availability_zone': None,
|
||||
u'terminated_at': None,
|
||||
u'ephemeral_gb': 0,
|
||||
u'instance_type_id': 2,
|
||||
u'user_data': None,
|
||||
u'numa_topology': None,
|
||||
u'cleaned': False,
|
||||
u'vm_mode': None,
|
||||
u'flavor': {
|
||||
u'nova_object.version': u'1.1',
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'memory_mb': 512,
|
||||
u'root_gb': 1,
|
||||
u'deleted_at': None,
|
||||
u'name': u'm1.tiny',
|
||||
u'deleted': False,
|
||||
u'created_at': None,
|
||||
u'ephemeral_gb': 0,
|
||||
u'updated_at': None,
|
||||
u'disabled': False,
|
||||
u'vcpus': 1,
|
||||
u'extra_specs': {},
|
||||
u'swap': 0,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'is_public': True,
|
||||
u'flavorid': u'1',
|
||||
u'vcpu_weight': 0,
|
||||
u'id': 2}},
|
||||
u'deleted_at': None,
|
||||
u'reservation_id': u'r-s9v032d0',
|
||||
u'id': 830,
|
||||
u'security_groups': {
|
||||
u'nova_object.version': u'1.0',
|
||||
u'nova_object.name': u'SecurityGroupList',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'objects': []}},
|
||||
u'disable_terminate': False,
|
||||
u'root_device_name': None,
|
||||
u'display_name': u'user_b1',
|
||||
u'uuid': u'e3a7770a-dbf6-4b63-8f9a-8875e2ccc68b',
|
||||
u'default_swap_device': None,
|
||||
u'info_cache': {
|
||||
u'nova_object.version': u'1.5',
|
||||
u'nova_object.name': u'InstanceInfoCache',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.data': {
|
||||
u'instance_uuid': u'e3a7-8875e2ccc68b',
|
||||
u'deleted': False,
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'updated_at': None,
|
||||
u'network_info': u'[]',
|
||||
u'deleted_at': None}},
|
||||
u'hostname': u'user-b1',
|
||||
u'launched_on': None,
|
||||
u'display_description': u'user_b1',
|
||||
u'key_data': None,
|
||||
u'deleted': False,
|
||||
u'power_state': 0,
|
||||
u'key_name': None,
|
||||
u'default_ephemeral_device': None,
|
||||
u'progress': 0,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'launched_at': None,
|
||||
u'metadata': {
|
||||
u'quota': u'dynamic',
|
||||
u'persistent': u'False'},
|
||||
u'node': None,
|
||||
u'ramdisk_id': u'',
|
||||
u'access_ip_v6': None,
|
||||
u'access_ip_v4': None,
|
||||
u'kernel_id': u'',
|
||||
u'old_flavor': None,
|
||||
u'updated_at': None,
|
||||
u'host': None,
|
||||
u'root_gb': 1,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'system_metadata': {
|
||||
u'image_min_disk': u'1',
|
||||
u'image_min_ram': u'0',
|
||||
u'image_disk_format': u'qcow2',
|
||||
u'image_base_image_ref': u'5100f480-a25e7bf09e',
|
||||
u'image_container_format': u'bare'},
|
||||
u'task_state': u'scheduling',
|
||||
u'shutdown_terminate': False,
|
||||
u'cell_name': None,
|
||||
u'ephemeral_key_uuid': None,
|
||||
u'locked': False,
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'locked_by': None,
|
||||
u'launch_index': 0,
|
||||
u'memory_mb': 512,
|
||||
u'vcpus': 1,
|
||||
u'image_ref': u'a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'architecture': None,
|
||||
u'auto_disk_config': False,
|
||||
u'os_type': None,
|
||||
u'config_drive': u'',
|
||||
u'new_flavor': None}},
|
||||
'admin_password': u'URijD456Cezi',
|
||||
'context': {
|
||||
u'domain': None,
|
||||
u'project_domain': None,
|
||||
u'auth_token': u'f9d8458ef4ae454dad75f4636304079c',
|
||||
u'resource_uuid': None,
|
||||
u'read_only': False,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'user_identity': u'fa60841a78a865da63b2399de - - -',
|
||||
u'tenant': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'instance_lock_checked': False,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'user_name': u'user_b1',
|
||||
u'project_name': u'prj_b',
|
||||
u'timestamp': u'2016-09-02T14:01:39.284558',
|
||||
u'remote_address': u'10.64.31.19',
|
||||
u'quota_class': None,
|
||||
u'is_admin': False,
|
||||
u'user': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'service_catalog': [],
|
||||
u'read_deleted': u'no',
|
||||
u'show_deleted': False,
|
||||
u'roles': [u'user'],
|
||||
u'request_id': u'req-69c9e7e6-62b2fee1d6e8',
|
||||
u'user_domain': None},
|
||||
'security_groups': [u'default']}
|
||||
build_requests = [{
|
||||
'nova_object.version': '1.2',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.name': 'BuildRequest',
|
||||
'nova_object.data': {
|
||||
'instance_uuid': '999',
|
||||
'created_at': '2017-07-20T12:09:27Z',
|
||||
'updated_at': None,
|
||||
'instance': {
|
||||
'nova_object.version': '2.3',
|
||||
'nova_object.name': 'Instance',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {
|
||||
'vm_state': 'building',
|
||||
'keypairs': {
|
||||
'nova_object.version': '1.3',
|
||||
'nova_object.name': 'KeyPairList',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {'objects': []}},
|
||||
'pci_requests': {
|
||||
'nova_object.version': '1.1',
|
||||
'nova_object.name': 'InstancePCIRequests',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {'requests': []}},
|
||||
'availability_zone': 'nova',
|
||||
'terminated_at': None,
|
||||
'ephemeral_gb': 0,
|
||||
'old_flavor': None,
|
||||
'updated_at': None,
|
||||
'numa_topology': None,
|
||||
'vm_mode': None,
|
||||
'flavor': {
|
||||
'nova_object.version': '1.1',
|
||||
'nova_object.name': 'Flavor',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {
|
||||
'memory_mb': 512,
|
||||
'root_gb': 1,
|
||||
'deleted_at': None,
|
||||
'name': 'm1.tiny',
|
||||
'deleted': False,
|
||||
'created_at': '2017-05-23T09:36:21Z',
|
||||
'ephemeral_gb': 0,
|
||||
'updated_at': None,
|
||||
'disabled': False,
|
||||
'vcpus': 1,
|
||||
'extra_specs': {},
|
||||
'swap': 0,
|
||||
'rxtx_factor': 1.0,
|
||||
'is_public': True,
|
||||
'flavorid': '5cdecdda',
|
||||
'vcpu_weight': 0,
|
||||
'id': 1}},
|
||||
'reservation_id': 'r-uavrcsgg',
|
||||
'security_groups': {
|
||||
'nova_object.version': '1.0',
|
||||
'nova_object.name': 'SecurityGroupList',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {'objects': []}},
|
||||
'disable_terminate': False,
|
||||
'user_id': '4469ff06d1e',
|
||||
'uuid': '999',
|
||||
'new_flavor': None,
|
||||
'info_cache': {
|
||||
'nova_object.version': '1.5',
|
||||
'nova_object.name': 'InstanceInfoCache',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {
|
||||
'instance_uuid': '999',
|
||||
'network_info': '[]'}},
|
||||
'hostname': 'lisa',
|
||||
'launched_on': None,
|
||||
'display_description': 'Lisa',
|
||||
'key_data': None,
|
||||
'deleted': False,
|
||||
'power_state': 0,
|
||||
'progress': 0,
|
||||
'project_id': '1111111',
|
||||
'launched_at': None,
|
||||
'config_drive': '',
|
||||
'node': None,
|
||||
'ramdisk_id': '',
|
||||
'access_ip_v6': None,
|
||||
'access_ip_v4': None,
|
||||
'kernel_id': '',
|
||||
'key_name': 'mykey',
|
||||
'user_data': None,
|
||||
'host': None,
|
||||
'ephemeral_key_uuid': None,
|
||||
'architecture': None,
|
||||
'display_name': 'Lisa',
|
||||
'system_metadata': {
|
||||
'image_min_disk': '1',
|
||||
'image_min_ram': '0',
|
||||
'image_disk_format': 'qcow2',
|
||||
'image_base_image_ref': '03d54ef8',
|
||||
'image_container_format': 'bare'},
|
||||
'task_state': 'scheduling',
|
||||
'shutdown_terminate': False,
|
||||
'tags': {
|
||||
'nova_object.version': '1.1',
|
||||
'nova_object.name': 'TagList',
|
||||
'nova_object.namespace': 'nova',
|
||||
'nova_object.data': {u'objects': []}},
|
||||
'cell_name': None,
|
||||
'root_gb': 1,
|
||||
'locked': False,
|
||||
'instance_type_id': 1,
|
||||
'locked_by': None,
|
||||
'launch_index': 0,
|
||||
'memory_mb': 512,
|
||||
'vcpus': 1,
|
||||
'image_ref': '03d54ef8',
|
||||
'root_device_name': None,
|
||||
'auto_disk_config': True,
|
||||
'os_type': None,
|
||||
'metadata': {'quota': 'shared'},
|
||||
'created_at': '2017-07-20T12:09:27Z'}},
|
||||
'project_id': '1111111',
|
||||
'id': 63},
|
||||
'nova_object.changes': [u'block_device_mappings']}]
|
||||
|
||||
self.req = Request.fromDict(req_dict)
|
||||
data = {"build_requests": build_requests,
|
||||
"request_specs": request_specs}
|
||||
|
||||
def test_get_AdminPassword(self):
|
||||
self.assertEqual(u'URijD456Cezi', self.req.getAdminPassword())
|
||||
req = {"context": {},
|
||||
"data": data,
|
||||
"action": "schedule_and_build_instances"}
|
||||
|
||||
def test_get_Id(self):
|
||||
self.assertEqual(
|
||||
u'e3a7770a-dbf6-4b63-8f9a-8875e2ccc68b',
|
||||
self.req.getId())
|
||||
self.req = Request.fromDict(req)
|
||||
|
||||
def test_get_Instance(self):
|
||||
ist = {
|
||||
u'nova_object.data': {
|
||||
u'access_ip_v4': None,
|
||||
u'access_ip_v6': None,
|
||||
u'architecture': None,
|
||||
u'auto_disk_config': False,
|
||||
u'availability_zone': None,
|
||||
u'cell_name': None,
|
||||
u'cleaned': False,
|
||||
u'config_drive': u'',
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'default_ephemeral_device': None,
|
||||
u'default_swap_device': None,
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disable_terminate': False,
|
||||
u'display_description': u'user_b1',
|
||||
u'display_name': u'user_b1',
|
||||
u'ephemeral_gb': 0,
|
||||
u'ephemeral_key_uuid': None,
|
||||
u'flavor': {
|
||||
u'nova_object.data': {
|
||||
u'created_at': None,
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disabled': False,
|
||||
u'ephemeral_gb': 0,
|
||||
u'extra_specs': {},
|
||||
u'flavorid': u'1',
|
||||
u'id': 2,
|
||||
u'is_public': True,
|
||||
u'memory_mb': 512,
|
||||
u'name': u'm1.tiny',
|
||||
u'root_gb': 1,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'swap': 0,
|
||||
u'updated_at': None,
|
||||
u'vcpu_weight': 0,
|
||||
u'vcpus': 1},
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.1'},
|
||||
u'host': None,
|
||||
u'hostname': u'user-b1',
|
||||
u'id': 830,
|
||||
u'image_ref': u'a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'info_cache': {
|
||||
u'nova_object.data': {
|
||||
u'created_at': u'2016-09-02T14:01:39Z',
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'instance_uuid': u'e3a7-8875e2ccc68b',
|
||||
u'network_info': u'[]',
|
||||
u'updated_at': None},
|
||||
u'nova_object.name': u'InstanceInfoCache',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.5'},
|
||||
u'instance_type_id': 2,
|
||||
u'kernel_id': u'',
|
||||
u'key_data': None,
|
||||
u'key_name': None,
|
||||
u'launch_index': 0,
|
||||
u'launched_at': None,
|
||||
u'launched_on': None,
|
||||
u'locked': False,
|
||||
u'locked_by': None,
|
||||
u'memory_mb': 512,
|
||||
u'metadata': {
|
||||
u'persistent': u'False',
|
||||
u'quota': u'dynamic'},
|
||||
u'new_flavor': None,
|
||||
u'node': None,
|
||||
u'numa_topology': None,
|
||||
u'old_flavor': None,
|
||||
u'os_type': None,
|
||||
u'pci_requests': {
|
||||
u'nova_object.data': {
|
||||
u'instance_uuid': u'e3a7770a-8875e2ccc68b',
|
||||
u'requests': []},
|
||||
u'nova_object.name': u'InstancePCIRequests',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.1'},
|
||||
u'power_state': 0,
|
||||
u'progress': 0,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'ramdisk_id': u'',
|
||||
u'reservation_id': u'r-s9v032d0',
|
||||
u'root_device_name': None,
|
||||
u'root_gb': 1,
|
||||
u'security_groups': {
|
||||
u'nova_object.data': {
|
||||
u'objects': []},
|
||||
u'nova_object.name': u'SecurityGroupList',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.0'},
|
||||
u'shutdown_terminate': False,
|
||||
u'system_metadata': {
|
||||
u'image_base_image_ref': u'5100f480-a25e7bf09e',
|
||||
u'image_container_format': u'bare',
|
||||
u'image_disk_format': u'qcow2',
|
||||
u'image_min_disk': u'1',
|
||||
u'image_min_ram': u'0'},
|
||||
u'task_state': u'scheduling',
|
||||
u'terminated_at': None,
|
||||
u'updated_at': None,
|
||||
u'user_data': None,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'uuid': u'e3a7770a-dbf6-4b63-8f9a-8875e2ccc68b',
|
||||
u'vcpus': 1,
|
||||
u'vm_mode': None,
|
||||
u'vm_state': u'building'},
|
||||
u'nova_object.name': u'Instance',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'2.0'}
|
||||
def test_request(self):
|
||||
self.assertIsNotNone(self.req)
|
||||
|
||||
self.assertEqual(ist, self.req.getInstance())
|
||||
def test_getId(self):
|
||||
self.assertEqual('999', self.req.getId())
|
||||
|
||||
def test_get_Image(self):
|
||||
im = {u'checksum': u'ee1eca47dc88f4879d8a229cc70a07c6',
|
||||
u'container_format': u'bare',
|
||||
u'created_at': u'2016-03-23T16:47:10.000000',
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disk_format': u'qcow2',
|
||||
u'id': u'5100f480-a40c-46cd-b8b6-ea2e5e7bf09e',
|
||||
u'is_public': True,
|
||||
u'min_disk': 0,
|
||||
u'min_ram': 0,
|
||||
u'name': u'cirros',
|
||||
u'owner': u'1a6edd87f9ec41d8aa64c8f23d719c2a',
|
||||
u'properties': {},
|
||||
u'size': 13287936,
|
||||
u'status': u'active',
|
||||
u'updated_at': u'2016-03-23T16:47:10.000000'}
|
||||
def test_getUserId(self):
|
||||
self.assertEqual('4469ff06d1e', self.req.getUserId())
|
||||
|
||||
self.assertEqual(im, self.req.getImage())
|
||||
def test_getProjectId(self):
|
||||
self.assertEqual('1111111', self.req.getProjectId())
|
||||
|
||||
def test_get_Context(self):
|
||||
cont = {u'auth_token': u'f9d8458ef4ae454dad75f4636304079c',
|
||||
u'domain': None,
|
||||
u'instance_lock_checked': False,
|
||||
u'is_admin': False,
|
||||
u'project_domain': None,
|
||||
u'project_id': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'project_name': u'prj_b',
|
||||
u'quota_class': None,
|
||||
u'read_deleted': u'no',
|
||||
u'read_only': False,
|
||||
u'remote_address': u'10.64.31.19',
|
||||
u'request_id': u'req-69c9e7e6-62b2fee1d6e8',
|
||||
u'resource_uuid': None,
|
||||
u'roles': [u'user'],
|
||||
u'service_catalog': [],
|
||||
u'show_deleted': False,
|
||||
u'tenant': u'd20ac1ffa60841a78a865da63b2399de',
|
||||
u'timestamp': u'2016-09-02T14:01:39.284558',
|
||||
u'user': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'user_domain': None,
|
||||
u'user_id': u'4cb9f71a47914d0c8b78a471fd8f7015',
|
||||
u'user_identity': u'fa60841a78a865da63b2399de - - -',
|
||||
u'user_name': u'user_b1'}
|
||||
def test_getAction(self):
|
||||
self.assertEqual('schedule_and_build_instances', self.req.getAction())
|
||||
|
||||
self.assertEqual(cont, self.req.getContext())
|
||||
def test_getContext(self):
|
||||
self.assertEqual({}, self.req.getContext())
|
||||
|
||||
def test_get_FilterProperties(self):
|
||||
filt = {u'instance_type': {
|
||||
u'nova_object.data': {u'created_at': None,
|
||||
u'deleted': False,
|
||||
u'deleted_at': None,
|
||||
u'disabled': False,
|
||||
u'ephemeral_gb': 0,
|
||||
u'extra_specs': {},
|
||||
u'flavorid': u'1',
|
||||
u'id': 2,
|
||||
u'is_public': True,
|
||||
u'memory_mb': 512,
|
||||
u'name': u'm1.tiny',
|
||||
u'root_gb': 1,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'swap': 0,
|
||||
u'updated_at': None,
|
||||
u'vcpu_weight': 0,
|
||||
u'vcpus': 1},
|
||||
u'nova_object.name': u'Flavor',
|
||||
u'nova_object.namespace': u'nova',
|
||||
u'nova_object.version': u'1.1'},
|
||||
u'scheduler_hints': {}}
|
||||
def test_getRetry(self):
|
||||
self.assertEqual({'num_attempts': 1, 'hosts': []}, self.req.getRetry())
|
||||
|
||||
self.assertEqual(filt, self.req.getFilterProperties())
|
||||
def test_getServer(self):
|
||||
server = self.req.getServer()
|
||||
self.assertIsNotNone(server)
|
||||
self.assertEqual('999', server.getId())
|
||||
self.assertEqual(datetime(2017, 7, 20, 12, 9, 27),
|
||||
server.getCreatedAt())
|
||||
self.assertEqual('4469ff06d1e', server.getUserId())
|
||||
self.assertEqual('1111111', server.getProjectId())
|
||||
self.assertEqual('mykey', server.getKeyName())
|
||||
self.assertEqual({'quota': 'shared'}, server.getMetadata())
|
||||
self.assertFalse(server.isPermanent())
|
||||
|
||||
def test_get_InjectedFiles(self):
|
||||
self.assertEqual([], self.req.getInjectedFiles())
|
||||
flavor = server.getFlavor()
|
||||
self.assertEqual('5cdecdda', flavor.getId())
|
||||
self.assertEqual('m1.tiny', flavor.getName())
|
||||
self.assertEqual(512, flavor.getMemory())
|
||||
self.assertEqual(1, flavor.getVCPUs())
|
||||
self.assertEqual(1, flavor.getStorage())
|
||||
|
||||
def test_get_RequestedNetworks(self):
|
||||
self.assertEqual(None, self.req.getRequestedNetworks())
|
||||
|
||||
def test_get_SecurityGroups(self):
|
||||
self.assertEqual([u'default'], self.req.getSecurityGroups())
|
||||
|
||||
def test_get_BlockDeviceMapping(self):
|
||||
self.assertEqual(None, self.req.getBlockDeviceMapping())
|
||||
|
||||
def test_get_LegacyBDM(self):
|
||||
self.assertEqual(True, self.req.getLegacyBDM())
|
||||
|
||||
def test_get_Server(self):
|
||||
prjId = self.req.getServer().getProjectId()
|
||||
self.assertEqual('d20ac1ffa60841a78a865da63b2399de', prjId)
|
||||
|
||||
def test_from_to_Dict(self):
|
||||
def test_toDict(self):
|
||||
rq_dict = self.req.toDict()
|
||||
self.assertEqual(True, rq_dict['legacy_bdm'])
|
||||
self.assertIn("action", rq_dict)
|
||||
self.assertIn("data", rq_dict)
|
||||
self.assertIn("context", rq_dict)
|
||||
|
Loading…
x
Reference in New Issue
Block a user