def test_is_supported_max_version(self): req = fakes.HTTPRequest.blank('/fake', version='2.5') self.assertFalse(api_version_request.is_supported( req, max_version='2.4')) self.assertTrue(api_version_request.is_supported( req, max_version='2.5')) self.assertTrue(api_version_request.is_supported( req, max_version='2.6'))
def show(self, request, instance, extend_address=True): """Detailed view of a single instance.""" server = { "server": { "id": instance["uuid"], "name": instance["display_name"], "status": self._get_vm_status(instance), "tenant_id": instance.get("project_id") or "", "user_id": instance.get("user_id") or "", "metadata": self._get_metadata(instance), "hostId": self._get_host_id(instance) or "", # TODO(alex_xu): '_get_image' return {} when there image_ref # isn't existed in V3 API, we revert it back to return "" in # V2.1. "image": self._get_image(request, instance), "flavor": self._get_flavor(request, instance), "created": utils.isotime(instance["created_at"]), "updated": utils.isotime(instance["updated_at"]), "addresses": self._get_addresses(request, instance, extend_address), "links": self._get_links(request, instance["uuid"], self._collection_name), }, } if server["server"]["status"] in self._fault_statuses: _inst_fault = self._get_fault(request, instance) if _inst_fault: server['server']['fault'] = _inst_fault if server["server"]["status"] in self._progress_statuses: server["server"]["progress"] = instance.get("progress", 0) if api_version_request.is_supported(request, min_version="2.9"): server["server"]["locked"] = (True if instance["locked_by"] else False) if api_version_request.is_supported(request, min_version="2.19"): server["server"]["description"] = instance.get( "display_description") return server
def _format_server_group(self, context, group, req): # the id field has its value as the uuid of the server group # There is no 'uuid' key in server_group seen by clients. # In addition, clients see policies as a ["policy-name"] list; # and they see members as a ["server-id"] list. server_group = {} server_group['id'] = group.uuid server_group['name'] = group.name server_group['policies'] = group.policies or [] # NOTE(danms): This has been exposed to the user, but never used. # Since we can't remove it, just make sure it's always empty. server_group['metadata'] = {} members = [] if group.members: # Display the instances that are not deleted. filters = {'uuid': group.members, 'deleted': False} instances = objects.InstanceList.get_by_filters(context, filters=filters) members = [instance.uuid for instance in instances] server_group['members'] = members # Add project id information to the response data for # API version v2.13 if api_version_request.is_supported(req, min_version="2.13"): server_group['project_id'] = group.project_id server_group['user_id'] = group.user_id return server_group
def _evacuate(self, req, id, body): """Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["compute.context"] authorize(context) evacuate_body = body["evacuate"] host = evacuate_body.get("host") on_shared_storage = self._get_on_shared_storage(req, evacuate_body) if api_version_request.is_supported(req, min_version='2.14'): password = self._get_password_v214(req, evacuate_body) else: password = self._get_password(req, evacuate_body, on_shared_storage) if host is not None: try: self.host_api.service_get_by_compute_host(context, host) except exception.ComputeHostNotFound: msg = _("Compute host %s not found.") % host raise exc.HTTPNotFound(explanation=msg) instance = common.get_instance(self.compute_api, context, id) if instance.host == host: msg = _("The target host can't be the same one.") raise exc.HTTPBadRequest(explanation=msg) try: self.compute_api.evacuate(context, instance, host, on_shared_storage, password) except exception.InstanceUnknownCell as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'evacuate', id) except exception.ComputeServiceInUse as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if (not api_version_request.is_supported(req, min_version='2.14') and CONF.enable_instance_password): return {'adminPass': password} else: return None
def _evacuate(self, req, id, body): """Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["compute.context"] authorize(context) evacuate_body = body["evacuate"] host = evacuate_body.get("host") on_shared_storage = self._get_on_shared_storage(req, evacuate_body) if api_version_request.is_supported(req, min_version='2.14'): password = self._get_password_v214(req, evacuate_body) else: password = self._get_password(req, evacuate_body, on_shared_storage) if host is not None: try: self.host_api.service_get_by_compute_host(context, host) except exception.ComputeHostNotFound: msg = _("Compute host %s not found.") % host raise exc.HTTPNotFound(explanation=msg) instance = common.get_instance(self.compute_api, context, id) if instance.host == host: msg = _("The target host can't be the same one.") raise exc.HTTPBadRequest(explanation=msg) try: self.compute_api.evacuate(context, instance, host, on_shared_storage, password) except exception.InstanceUnknownCell as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state( state_error, 'evacuate', id) except exception.ComputeServiceInUse as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if (not api_version_request.is_supported(req, min_version='2.14') and CONF.enable_instance_password): return {'adminPass': password} else: return None
def update(self, req, id, body): """Perform service update""" if api_version_request.is_supported(req, min_version='2.11'): actions = self.actions.copy() actions["force-down"] = self._forced_down else: actions = self.actions return self._perform_action(req, id, body, actions)
def update(self, req, id, body): """Perform service update""" if api_version_request.is_supported(req, min_version='2.11'): actions = self.actions.copy() actions["force-down"] = self._forced_down else: actions = self.actions return self._perform_action(req, id, body, actions)
def index(self, req): """Return a list of all running services. Filter by host & service name """ if api_version_request.is_supported(req, min_version='2.11'): _services = self._get_services_list(req, ['forced_down']) else: _services = self._get_services_list(req) return {'services': _services}
def index(self, req): """Return all migrations in progress.""" context = req.environ['compute.context'] authorize(context, "index") migrations = self.compute_api.get_migrations(context, req.GET) if api_version_request.is_supported(req, min_version='2.23'): return {'migrations': self._output(req, migrations, True)} return {'migrations': self._output(req, migrations)}
def index(self, req): """Return all migrations in progress.""" context = req.environ['compute.context'] authorize(context, "index") migrations = self.compute_api.get_migrations(context, req.GET) if api_version_request.is_supported(req, min_version='2.23'): return {'migrations': self._output(req, migrations, True)} return {'migrations': self._output(req, migrations)}
def index(self, req): """Return a list of all running services. Filter by host & service name """ if api_version_request.is_supported(req, min_version='2.11'): _services = self._get_services_list(req, ['forced_down']) else: _services = self._get_services_list(req) return {'services': _services}
def show(self, request, instance, extend_address=True): """Detailed view of a single instance.""" server = { "server": { "id": instance["uuid"], "name": instance["display_name"], "status": self._get_vm_status(instance), "tenant_id": instance.get("project_id") or "", "user_id": instance.get("user_id") or "", "metadata": self._get_metadata(instance), "hostId": self._get_host_id(instance) or "", # TODO(alex_xu): '_get_image' return {} when there image_ref # isn't existed in V3 API, we revert it back to return "" in # V2.1. "image": self._get_image(request, instance), "flavor": self._get_flavor(request, instance), "created": utils.isotime(instance["created_at"]), "updated": utils.isotime(instance["updated_at"]), "addresses": self._get_addresses(request, instance, extend_address), "links": self._get_links(request, instance["uuid"], self._collection_name), }, } if server["server"]["status"] in self._fault_statuses: _inst_fault = self._get_fault(request, instance) if _inst_fault: server['server']['fault'] = _inst_fault if server["server"]["status"] in self._progress_statuses: server["server"]["progress"] = instance.get("progress", 0) if api_version_request.is_supported(request, min_version="2.9"): server["server"]["locked"] = (True if instance["locked_by"] else False) if api_version_request.is_supported(request, min_version="2.19"): server["server"]["description"] = instance.get( "display_description") return server
def _check_request_version(req, min_version, method, server_id, server_state): if not api_version_request.is_supported(req, min_version=min_version): exc_inv = exception.InstanceInvalidState( attr='vm_state', instance_uuid=server_id, state=server_state, method=method) common.raise_http_conflict_for_instance_invalid_state( exc_inv, method, server_id)
def _translate_vif_summary_view(req, vif): """Maps keys for VIF summary view.""" d = {} d['id'] = vif.uuid d['mac_address'] = vif.address if api_version_request.is_supported(req, min_version='2.12'): d['net_id'] = vif.net_uuid # NOTE(gmann): This is for v2.1 compatible mode where response should be # same as v2 one. if req.is_legacy_v2(): d['OS-EXT-VIF-NET:net_id'] = vif.net_uuid return d
def _translate_vif_summary_view(req, vif): """Maps keys for VIF summary view.""" d = {} d['id'] = vif.uuid d['mac_address'] = vif.address if api_version_request.is_supported(req, min_version='2.12'): d['net_id'] = vif.net_uuid # NOTE(gmann): This is for v2.1 compatible mode where response should be # same as v2 one. if req.is_legacy_v2(): d['OS-EXT-VIF-NET:net_id'] = vif.net_uuid return d
def _extend_server(self, context, server, req, bdms): volumes_attached = [] for bdm in bdms: if bdm.get('volume_id'): volume_attached = {'id': bdm['volume_id']} if api_version_request.is_supported(req, min_version='2.3'): volume_attached['delete_on_termination'] = ( bdm['delete_on_termination']) volumes_attached.append(volume_attached) # NOTE(mriedem): The os-extended-volumes prefix should not be used for # new attributes after v2.1. They are only in v2.1 for backward compat # with v2.0. key = "%s:volumes_attached" % ExtendedVolumes.alias server[key] = volumes_attached
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["compute.context"] authorize(context, action='migrate_live') host = body["os-migrateLive"]["host"] block_migration = body["os-migrateLive"]["block_migration"] if api_version_request.is_supported(req, min_version='2.25'): if block_migration == 'auto': block_migration = None else: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = None else: disk_over_commit = body["os-migrateLive"]["disk_over_commit"] block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) try: instance = common.get_instance(self.compute_api, context, id) self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) except exception.InstanceUnknownCell as e: raise exc.HTTPNotFound(explanation=e.format_message()) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.MigrationPreCheckError, exception.LiveMigrationWithOldNovaNotSafe, exception.LiveMigrationWithOldNovaNotSupported) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'os-migrateLive', id)
def show(self, req, resp_obj, id): context = req.environ['compute.context'] authorize_extend = False authorize_host_status = False if authorize(context): authorize_extend = True if (api_version_request.is_supported(req, min_version='2.16') and soft_authorize(context, action='show:host_status')): authorize_host_status = True if authorize_extend or authorize_host_status: server = resp_obj.obj['server'] db_instance = req.get_db_instance(server['id']) # server['id'] is guaranteed to be in the cache due to # the core API adding it in its 'show' method. if authorize_extend: self._extend_server(context, server, db_instance, req) if authorize_host_status: self._server_host_status(context, server, db_instance, req)
def show(self, req, resp_obj, id): context = req.environ['compute.context'] authorize_extend = False authorize_host_status = False if authorize(context): authorize_extend = True if (api_version_request.is_supported(req, min_version='2.16') and soft_authorize(context, action='show:host_status')): authorize_host_status = True if authorize_extend or authorize_host_status: server = resp_obj.obj['server'] db_instance = req.get_db_instance(server['id']) # server['id'] is guaranteed to be in the cache due to # the core API adding it in its 'show' method. if authorize_extend: self._extend_server(context, server, db_instance, req) if authorize_host_status: self._server_host_status(context, server, db_instance, req)
def _add_tenant_access(self, req, id, body): context = req.environ['compute.context'] authorize(context, action="add_tenant_access") vals = body['addTenantAccess'] tenant = vals['tenant'] flavor = common.get_flavor(context, id) try: if api_version_request.is_supported(req, min_version='2.7'): if flavor.is_public: exp = _("Can not add access to a public flavor.") raise webob.exc.HTTPConflict(explanation=exp) flavor.add_access(tenant) except exception.FlavorNotFound as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) except exception.FlavorAccessExists as err: raise webob.exc.HTTPConflict(explanation=err.format_message()) except exception.AdminRequired as e: raise webob.exc.HTTPForbidden(explanation=e.format_message()) return _marshall_flavor_access(flavor)
def _add_tenant_access(self, req, id, body): context = req.environ['compute.context'] authorize(context, action="add_tenant_access") vals = body['addTenantAccess'] tenant = vals['tenant'] flavor = common.get_flavor(context, id) try: if api_version_request.is_supported(req, min_version='2.7'): if flavor.is_public: exp = _("Can not add access to a public flavor.") raise webob.exc.HTTPConflict(explanation=exp) flavor.add_access(tenant) except exception.FlavorNotFound as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) except exception.FlavorAccessExists as err: raise webob.exc.HTTPConflict(explanation=err.format_message()) except exception.AdminRequired as e: raise webob.exc.HTTPForbidden(explanation=e.format_message()) return _marshall_flavor_access(flavor)
def _extend_server(self, context, server, instance, req): key = "OS-EXT-SRV-ATTR:hypervisor_hostname" server[key] = instance.node properties = ['host', 'name'] if api_version_request.is_supported(req, min_version='2.3'): # NOTE(mriedem): These will use the OS-EXT-SRV-ATTR prefix below # and that's OK for microversion 2.3 which is being compatible # with v2.0 for the ec2 API split out from Nova. After this, # however, new microversoins should not be using the # OS-EXT-SRV-ATTR prefix. properties += ['reservation_id', 'launch_index', 'hostname', 'kernel_id', 'ramdisk_id', 'root_device_name', 'user_data'] for attr in properties: if attr == 'name': key = "OS-EXT-SRV-ATTR:instance_%s" % attr else: # NOTE(mriedem): Nothing after microversion 2.3 should use the # OS-EXT-SRV-ATTR prefix for the attribute key name. key = "OS-EXT-SRV-ATTR:%s" % attr server[key] = instance[attr]
def _extend_server(self, context, server, instance, req): key = "OS-EXT-SRV-ATTR:hypervisor_hostname" server[key] = instance.node properties = ['host', 'name'] if api_version_request.is_supported(req, min_version='2.3'): # NOTE(mriedem): These will use the OS-EXT-SRV-ATTR prefix below # and that's OK for microversion 2.3 which is being compatible # with v2.0 for the ec2 API split out from Nova. After this, # however, new microversoins should not be using the # OS-EXT-SRV-ATTR prefix. properties += [ 'reservation_id', 'launch_index', 'hostname', 'kernel_id', 'ramdisk_id', 'root_device_name', 'user_data' ] for attr in properties: if attr == 'name': key = "OS-EXT-SRV-ATTR:instance_%s" % attr else: # NOTE(mriedem): Nothing after microversion 2.3 should use the # OS-EXT-SRV-ATTR prefix for the attribute key name. key = "OS-EXT-SRV-ATTR:%s" % attr server[key] = instance[attr]
def detail(self, req, resp_obj): context = req.environ['compute.context'] authorize_extend = False authorize_host_status = False if authorize(context): authorize_extend = True if (api_version_request.is_supported(req, min_version='2.16') and soft_authorize(context, action='show:host_status')): authorize_host_status = True if authorize_extend or authorize_host_status: servers = list(resp_obj.obj['servers']) if servers: instances = req.get_db_instances() # Instances is guaranteed to be in the cache due to # the core API adding it in its 'detail' method. if authorize_host_status: host_statuses = self.compute_api.get_instances_host_statuses( instances.values()) for server in servers: if authorize_extend: instance = instances[server['id']] self._extend_server(context, server, instance, req) if authorize_host_status: server['host_status'] = host_statuses[server['id']]
def detail(self, req, resp_obj): context = req.environ['compute.context'] authorize_extend = False authorize_host_status = False if authorize(context): authorize_extend = True if (api_version_request.is_supported(req, min_version='2.16') and soft_authorize(context, action='show:host_status')): authorize_host_status = True if authorize_extend or authorize_host_status: servers = list(resp_obj.obj['servers']) if servers: instances = req.get_db_instances() # Instances is guaranteed to be in the cache due to # the core API adding it in its 'detail' method. if authorize_host_status: host_statuses = self.compute_api.get_instances_host_statuses( instances.values()) for server in servers: if authorize_extend: instance = instances[server['id']] self._extend_server(context, server, instance, req) if authorize_host_status: server['host_status'] = host_statuses[server['id']]
def _get_on_shared_storage(self, req, evacuate_body): if api_version_request.is_supported(req, min_version='2.14'): return None else: return strutils.bool_from_string(evacuate_body["onSharedStorage"])
def _get_on_shared_storage(self, req, evacuate_body): if api_version_request.is_supported(req, min_version='2.14'): return None else: return strutils.bool_from_string(evacuate_body["onSharedStorage"])