def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, 'migrateLive') try: block_migration = body["os-migrateLive"]["block_migration"] disk_over_commit = body["os-migrateLive"]["disk_over_commit"] host = body["os-migrateLive"]["host"] except (TypeError, KeyError): msg = _("host, block_migration and disk_over_commit must " "be specified for live migration.") raise exc.HTTPBadRequest(explanation=msg) try: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=six.text_type(err)) instance = common.get_instance(self.compute_api, context, id, want_objects=True) try: self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.InstanceNotRunning, exception.MigrationPreCheckError, exception.LiveMigrationWithOldNovaNotSafe) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.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') except Exception: if host is None: msg = _("Live migration of instance %s to another host " "failed") % id else: msg = _("Live migration of instance %(id)s to host %(host)s " "failed") % { 'id': id, 'host': host } LOG.exception(msg) # Return messages from scheduler raise exc.HTTPBadRequest(explanation=msg) return webob.Response(status_int=202)
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, 'migrate_live') block_migration = body["os-migrateLive"]["block_migration"] disk_over_commit = body["os-migrateLive"]["disk_over_commit"] host = body["os-migrateLive"]["host"] 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, want_objects=True) self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.InstanceNotRunning, exception.MigrationPreCheckError) 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') return webob.Response(status_int=202)
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, 'migrateLive') try: block_migration = body["os-migrateLive"]["block_migration"] disk_over_commit = body["os-migrateLive"]["disk_over_commit"] host = body["os-migrateLive"]["host"] except (TypeError, KeyError): msg = _("host, block_migration and disk_over_commit must " "be specified for live migration.") raise exc.HTTPBadRequest(explanation=msg) try: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=six.text_type(err)) instance = common.get_instance(self.compute_api, context, id, want_objects=True) try: self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.InstanceNotRunning, exception.ComputeHostNotFound, exception.MigrationPreCheckError) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.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') except Exception: if host is None: msg = _("Live migration of instance %s to another host " "failed") % id else: msg = _("Live migration of instance %(id)s to host %(host)s " "failed") % {'id': id, 'host': host} LOG.exception(msg) # Return messages from scheduler raise exc.HTTPBadRequest(explanation=msg) return webob.Response(status_int=202)
def _validate(self, bdm_dict): """Basic data format validations.""" dict_fields = set(key for key, _ in bdm_dict.iteritems()) # Check that there are no bogus fields if not (dict_fields <= (self._fields | self._db_only_fields)): raise exception.InvalidBDMFormat( details=_("Some fields are invalid.")) if bdm_dict.get('no_device'): return # Check that all required fields are there if (self._required_fields and not ((dict_fields & self._required_fields) == self._required_fields)): raise exception.InvalidBDMFormat( details=_("Some required fields are missing")) if 'delete_on_termination' in bdm_dict: bdm_dict['delete_on_termination'] = strutils.bool_from_string( bdm_dict['delete_on_termination']) if bdm_dict.get('device_name') is not None: validate_device_name(bdm_dict['device_name']) validate_and_default_volume_size(bdm_dict) if bdm_dict.get('boot_index'): try: bdm_dict['boot_index'] = int(bdm_dict['boot_index']) except ValueError: raise exception.InvalidBDMFormat( details=_("Boot index is invalid."))
def create(self, req, body): """Creates a new snapshot.""" context = req.environ['nova.context'] authorize(context) if not self.is_valid_body(body, 'snapshot'): msg = _("snapshot not specified") raise exc.HTTPBadRequest(explanation=msg) snapshot = body['snapshot'] volume_id = snapshot['volume_id'] LOG.audit(_("Create snapshot from volume %s"), volume_id, context=context) force = snapshot.get('force', False) try: force = strutils.bool_from_string(force, strict=True) except ValueError: msg = _("Invalid value '%s' for force.") % force raise exc.HTTPBadRequest(explanation=msg) if force: create_func = self.volume_api.create_snapshot_force else: create_func = self.volume_api.create_snapshot new_snapshot = create_func(context, volume_id, snapshot.get('display_name'), snapshot.get('display_description')) retval = _translate_snapshot_detail_view(context, new_snapshot) return {'snapshot': retval}
def sync_instances(self, req, body): """Tell all cells to sync instance info.""" context = req.environ['nova.context'] authorize(context) project_id = body.pop('project_id', None) deleted = body.pop('deleted', False) updated_since = body.pop('updated_since', None) if body: msg = _("Only 'updated_since', 'project_id' and 'deleted' are " "understood.") raise exc.HTTPBadRequest(explanation=msg) if isinstance(deleted, six.string_types): try: deleted = strutils.bool_from_string(deleted, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=str(err)) if updated_since: try: timeutils.parse_isotime(updated_since) except ValueError: msg = _('Invalid changes-since value') raise exc.HTTPBadRequest(explanation=msg) self.cells_rpcapi.sync_instances(context, project_id=project_id, updated_since=updated_since, deleted=deleted)
def server_create(self, server_dict, create_kwargs): # min_count and max_count are optional. If they exist, they may come # in as strings. Verify that they are valid integers and > 0. # Also, we want to default 'min_count' to 1, and default # 'max_count' to be 'min_count'. min_count = server_dict.get(MIN_ATTRIBUTE_NAME, 1) max_count = server_dict.get(MAX_ATTRIBUTE_NAME, min_count) return_id = server_dict.get(RRID_ATTRIBUTE_NAME, False) try: min_count = utils.validate_integer(min_count, "min_count", min_value=1) max_count = utils.validate_integer(max_count, "max_count", min_value=1) return_id = strutils.bool_from_string(return_id, strict=True) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if min_count > max_count: msg = _('min_count must be <= max_count') raise exc.HTTPBadRequest(explanation=msg) create_kwargs['min_count'] = min_count create_kwargs['max_count'] = max_count create_kwargs['return_reservation_id'] = return_id
def _add_disk_config(self, context, images): for image in images: metadata = image['metadata'] if INTERNAL_DISK_CONFIG in metadata: raw_value = metadata[INTERNAL_DISK_CONFIG] value = strutils.bool_from_string(raw_value) image[API_DISK_CONFIG] = disk_config_to_api(value)
def sync_instances(self, req, body): """Tell all cells to sync instance info.""" context = req.environ['nova.context'] authorize(context) authorize(context, action="sync_instances") project_id = body.pop('project_id', None) deleted = body.pop('deleted', False) updated_since = body.pop('updated_since', None) if body: msg = _("Only 'updated_since', 'project_id' and 'deleted' are " "understood.") raise exc.HTTPBadRequest(explanation=msg) if isinstance(deleted, six.string_types): try: deleted = strutils.bool_from_string(deleted, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=str(err)) if updated_since: try: timeutils.parse_isotime(updated_since) except ValueError: msg = _('Invalid changes-since value') raise exc.HTTPBadRequest(explanation=msg) self.cells_rpcapi.sync_instances(context, project_id=project_id, updated_since=updated_since, deleted=deleted)
def create(self, req, body): """Creates a new snapshot.""" context = req.environ["nova.context"] authorize(context) if not self.is_valid_body(body, "snapshot"): raise exc.HTTPUnprocessableEntity() snapshot = body["snapshot"] volume_id = snapshot["volume_id"] LOG.audit(_("Create snapshot from volume %s"), volume_id, context=context) force = snapshot.get("force", False) try: force = strutils.bool_from_string(force, strict=True) except ValueError: msg = _("Invalid value '%s' for force.") % force raise exception.InvalidParameterValue(err=msg) if force: create_func = self.volume_api.create_snapshot_force else: create_func = self.volume_api.create_snapshot new_snapshot = create_func( context, volume_id, snapshot.get("display_name"), snapshot.get("display_description") ) retval = _translate_snapshot_detail_view(context, new_snapshot) return {"snapshot": retval}
def _validate(self, bdm_dict): """Basic data format validations.""" dict_fields = set(key for key, _ in bdm_dict.iteritems()) # Check that there are no bogus fields if not (dict_fields <= (self._fields | self._db_only_fields)): raise exception.InvalidBDMFormat( details="Some fields are invalid.") if bdm_dict.get('no_device'): return # Check that all required fields are there if (self._required_fields and not ((dict_fields & self._required_fields) == self._required_fields)): raise exception.InvalidBDMFormat( details="Some required fields are missing") if 'delete_on_termination' in bdm_dict: bdm_dict['delete_on_termination'] = strutils.bool_from_string( bdm_dict['delete_on_termination']) if bdm_dict.get('device_name') is not None: validate_device_name(bdm_dict['device_name']) validate_and_default_volume_size(bdm_dict) if bdm_dict.get('boot_index'): try: bdm_dict['boot_index'] = int(bdm_dict['boot_index']) except ValueError: raise exception.InvalidBDMFormat( details="Boot index is invalid.")
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, 'migrate_live') try: block_migration = body["migrate_live"]["block_migration"] disk_over_commit = body["migrate_live"]["disk_over_commit"] host = body["migrate_live"]["host"] except (TypeError, KeyError): msg = _("host, block_migration and disk_over_commit must " "be specified for live migration.") raise exc.HTTPBadRequest(explanation=msg) try: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=str(err)) try: instance = common.get_instance(self.compute_api, context, id, want_objects=True) self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.InstanceNotRunning, exception.MigrationPreCheckError) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'migrate_live') return webob.Response(status_int=202)
def _evacuate(self, req, id, body): """Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["nova.context"] authorize(context) if not self.is_valid_body(body, "evacuate"): raise exc.HTTPBadRequest(_("Malformed request body")) evacuate_body = body["evacuate"] try: host = evacuate_body["host"] on_shared_storage = strutils.bool_from_string( evacuate_body["onSharedStorage"]) except (TypeError, KeyError): msg = _("host and onSharedStorage must be specified.") raise exc.HTTPBadRequest(explanation=msg) password = None if 'adminPass' in evacuate_body: # check that if requested to evacuate server on shared storage # password not specified if on_shared_storage: msg = _("admin password can't be changed on existing disk") raise exc.HTTPBadRequest(explanation=msg) password = evacuate_body['adminPass'] elif not on_shared_storage: password = utils.generate_password() try: self.host_api.service_get_by_compute_host(context, host) except exception.NotFound: msg = _("Compute host %s not found.") % host raise exc.HTTPNotFound(explanation=msg) try: instance = self.compute_api.get(context, id, want_objects=True) if instance.host == host: msg = _("The target host can't be the same one.") raise exc.HTTPBadRequest(explanation=msg) self.compute_api.evacuate(context, instance, host, on_shared_storage, password) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state( state_error, 'evacuate') except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.ComputeServiceInUse as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if password: return {'adminPass': password}
def _evacuate(self, req, id, body): """Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["nova.context"] authorize(context) if not self.is_valid_body(body, "evacuate"): raise exc.HTTPBadRequest(_("Malformed request body")) evacuate_body = body["evacuate"] try: host = evacuate_body["host"] on_shared_storage = strutils.bool_from_string( evacuate_body["onSharedStorage"]) except (TypeError, KeyError): msg = _("host and onSharedStorage must be specified.") raise exc.HTTPBadRequest(explanation=msg) password = None if 'adminPass' in evacuate_body: # check that if requested to evacuate server on shared storage # password not specified if on_shared_storage: msg = _("admin password can't be changed on existing disk") raise exc.HTTPBadRequest(explanation=msg) password = evacuate_body['adminPass'] elif not on_shared_storage: password = utils.generate_password() try: self.host_api.service_get_by_compute_host(context, host) except exception.NotFound: msg = _("Compute host %s not found.") % host raise exc.HTTPNotFound(explanation=msg) try: instance = self.compute_api.get(context, id) if instance['host'] == host: msg = _("The target host can't be the same one.") raise exc.HTTPBadRequest(explanation=msg) self.compute_api.evacuate(context, instance, host, on_shared_storage, password) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'evacuate') except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.ComputeServiceInUse as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if password: return {'adminPass': password}
def server_xml_extract_server_deserialize(self, server_node, server_dict): res_id = server_node.getAttribute(RRID_ATTRIBUTE_NAME) if res_id: server_dict[RRID_ATTRIBUTE_NAME] = strutils.bool_from_string( res_id) min_count = server_node.getAttribute(MIN_ATTRIBUTE_NAME) if min_count: server_dict[MIN_ATTRIBUTE_NAME] = min_count max_count = server_node.getAttribute(MAX_ATTRIBUTE_NAME) if max_count: server_dict[MAX_ATTRIBUTE_NAME] = max_count
def should_use_agent(instance): sys_meta = utils.instance_sys_meta(instance) if USE_AGENT_SM_KEY not in sys_meta: return CONF.xenserver.use_agent_default else: use_agent_raw = sys_meta[USE_AGENT_SM_KEY] try: return strutils.bool_from_string(use_agent_raw, strict=True) except ValueError: LOG.warn(_("Invalid 'agent_present' value. " "Falling back to the default."), instance=instance) return CONF.xenserver.use_agent_default
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, 'migrate_live') try: block_migration = body["migrate_live"]["block_migration"] disk_over_commit = body["migrate_live"]["disk_over_commit"] host = body["migrate_live"]["host"] pclm = body["migrate_live"]["pclm"] except (TypeError, KeyError): msg = _("host, block_migration, disk_over_commit and pclm must " "be specified for live migration.") raise exc.HTTPBadRequest(explanation=msg) try: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=str(err)) try: instance = common.get_instance(self.compute_api, context, id, want_objects=True) self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host, pclm) except (exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.NoValidHost, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.MigrationPreCheckError) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'migrate_live') return webob.Response(status_int=202)
def required_by(instance): image_prop = utils.instance_sys_meta(instance).get( utils.SM_IMAGE_PROP_PREFIX + 'img_config_drive', 'optional') if image_prop not in ['optional', 'mandatory']: LOG.warn(_LW('Image config drive option %(image_prop)s is invalid ' 'and will be ignored') % {'image_prop': image_prop}, instance=instance) return (instance.get('config_drive') or 'always' == CONF.force_config_drive or strutils.bool_from_string(CONF.force_config_drive) or image_prop == 'mandatory')
def _untranslate_volume_summary_view(context, vol): """Maps keys for volumes summary view.""" d = {} d["id"] = vol.id d["status"] = vol.status d["size"] = vol.size d["availability_zone"] = vol.availability_zone d["created_at"] = vol.created_at d["shareable"] = vol.shareable # TODO(jdg): The calling code expects attach_time and # mountpoint to be set. When the calling # code is more defensive this can be # removed. d["attach_time"] = "" d["mountpoint"] = "" if vol.attachments: d["attachments"] = [] for attach in vol.attachments: a = { "attach_status": "attached", "attachment_id": attach["attachment_id"], "instance_uuid": attach["server_id"], "mountpoint": attach["device"], } d["attachments"].append(a) d["attach_status"] = "attached" else: d["attach_status"] = "detached" d["attachments"] = [] # NOTE(dzyu) volume(cinder) v2 API uses 'name' instead of 'display_name', # and use 'description' instead of 'display_description' for volume. if hasattr(vol, "display_name"): d["display_name"] = vol.display_name d["display_description"] = vol.display_description else: d["display_name"] = vol.name d["display_description"] = vol.description # TODO(jdg): Information may be lost in this translation d["volume_type_id"] = vol.volume_type d["snapshot_id"] = vol.snapshot_id d["bootable"] = strutils.bool_from_string(vol.bootable) d["volume_metadata"] = {} for key, value in vol.metadata.items(): d["volume_metadata"][key] = value if hasattr(vol, "volume_image_metadata"): d["volume_image_metadata"] = copy.deepcopy(vol.volume_image_metadata) return d
def _untranslate_volume_summary_view(context, vol): """Maps keys for volumes summary view.""" d = {} d['id'] = vol.id d['status'] = vol.status d['size'] = vol.size d['availability_zone'] = vol.availability_zone d['created_at'] = vol.created_at d['shareable'] = vol.shareable # TODO(jdg): The calling code expects attach_time and # mountpoint to be set. When the calling # code is more defensive this can be # removed. d['attach_time'] = "" d['mountpoint'] = "" if vol.attachments: d['attachments'] = [] for attach in vol.attachments: a = {'attach_status': 'attached', 'attachment_id': attach['attachment_id'], 'instance_uuid': attach['server_id'], 'mountpoint': attach['device'], } d['attachments'].append(a) d['attach_status'] = 'attached' else: d['attach_status'] = 'detached' d['attachments'] = [] # NOTE(dzyu) volume(cinder) v2 API uses 'name' instead of 'display_name', # and use 'description' instead of 'display_description' for volume. if hasattr(vol, 'display_name'): d['display_name'] = vol.display_name d['display_description'] = vol.display_description else: d['display_name'] = vol.name d['display_description'] = vol.description # TODO(jdg): Information may be lost in this translation d['volume_type_id'] = vol.volume_type d['snapshot_id'] = vol.snapshot_id d['bootable'] = strutils.bool_from_string(vol.bootable) d['volume_metadata'] = {} for key, value in vol.metadata.items(): d['volume_metadata'][key] = value if hasattr(vol, 'volume_image_metadata'): d['volume_image_metadata'] = copy.deepcopy(vol.volume_image_metadata) return d
def sync_instances(self, req, body): """Tell all cells to sync instance info.""" context = req.environ['nova.context'] authorize(context) authorize(context, action="sync_instances") project_id = body.pop('project_id', None) deleted = body.pop('deleted', False) updated_since = body.pop('updated_since', None) if isinstance(deleted, six.string_types): deleted = strutils.bool_from_string(deleted, strict=True) self.cells_rpcapi.sync_instances(context, project_id=project_id, updated_since=updated_since, deleted=deleted)
def _parse_is_public(self, is_public): """Parse is_public into something usable.""" if is_public is None: # preserve default value of showing only public flavors return True elif utils.is_none_string(is_public): return None else: try: return strutils.bool_from_string(is_public, strict=True) except ValueError: msg = _('Invalid is_public filter [%s]') % is_public raise webob.exc.HTTPBadRequest(explanation=msg)
def _evacuate(self, req, id, body): """Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["nova.context"] authorize(context) evacuate_body = body["evacuate"] host = evacuate_body.get("host") on_shared_storage = strutils.bool_from_string( evacuate_body["onSharedStorage"]) password = None if 'adminPass' in evacuate_body: # check that if requested to evacuate server on shared storage # password not specified if on_shared_storage: msg = _("admin password can't be changed on existing disk") raise exc.HTTPBadRequest(explanation=msg) password = evacuate_body['adminPass'] elif not on_shared_storage: password = utils.generate_password() if host is not None: try: self.host_api.service_get_by_compute_host(context, host) except exception.NotFound: msg = _("Compute host %s not found.") % host raise exc.HTTPNotFound(explanation=msg) instance = common.get_instance(self.compute_api, context, id, want_objects=True) 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.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 CONF.enable_instance_password: return {'adminPass': password} else: return {}
def update(self, req, id, body): context = req.environ['nova.context'] authorize_update(context) project_id = id params = urlparse.parse_qs(req.environ.get('QUERY_STRING', '')) user_id = params.get('user_id', [None])[0] quota_set = body['quota_set'] force_update = strutils.bool_from_string( quota_set.get('force', 'False')) try: settable_quotas = QUOTAS.get_settable_quotas(context, project_id, user_id=user_id) except exception.Forbidden: raise webob.exc.HTTPForbidden() LOG.debug("Force update quotas: %s", force_update) for key, value in body['quota_set'].iteritems(): if key == 'force' or (not value and value != 0): continue # validate whether already used and reserved exceeds the new # quota, this check will be ignored if admin want to force # update value = int(value) if not force_update: minimum = settable_quotas[key]['minimum'] maximum = settable_quotas[key]['maximum'] self._validate_quota_limit(key, value, minimum, maximum) try: objects.Quotas.create_limit(context, project_id, key, value, user_id=user_id) except exception.QuotaExists: objects.Quotas.update_limit(context, project_id, key, value, user_id=user_id) except exception.AdminRequired: raise webob.exc.HTTPForbidden() return self._format_quota_set( id, self._get_quotas(context, id, user_id=user_id))
def required_by(instance): image_prop = utils.instance_sys_meta(instance).get(utils.SM_IMAGE_PROP_PREFIX + "img_config_drive", "optional") if image_prop not in ["optional", "mandatory"]: LOG.warn( _LW("Image config drive option %(image_prop)s is invalid " "and will be ignored") % {"image_prop": image_prop}, instance=instance, ) return ( instance.get("config_drive") or "always" == CONF.force_config_drive or strutils.bool_from_string(CONF.force_config_drive) or image_prop == "mandatory" )
def _evacuate(self, req, id, body): """ Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["nova.context"] authorize(context) try: if len(body) != 1: raise exc.HTTPBadRequest(_("Malformed request body")) evacuate_body = body["evacuate"] host = evacuate_body["host"] on_shared_storage = strutils.bool_from_string( evacuate_body["onSharedStorage"]) password = None if 'adminPass' in evacuate_body: # check that if requested to evacuate server on shared storage # password not specified if on_shared_storage: msg = _("admin password can't be changed on existing disk") raise exc.HTTPBadRequest(explanation=msg) password = evacuate_body['adminPass'] elif not on_shared_storage: password = utils.generate_password() except (TypeError, KeyError): msg = _("host and onSharedStorage must be specified.") raise exc.HTTPBadRequest(explanation=msg) try: instance = self.compute_api.get(context, id) self.compute_api.evacuate(context, instance, host, on_shared_storage, password) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state( state_error, 'evacuate') except Exception as e: msg = _("Error in evacuate, %s") % e LOG.exception(msg, instance=instance) raise exc.HTTPBadRequest(explanation=msg) if password: return {'adminPass': password}
def _evacuate(self, req, id, body): """ Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["nova.context"] authorize(context) try: if len(body) != 1: raise exc.HTTPBadRequest(_("Malformed request body")) evacuate_body = body["evacuate"] host = evacuate_body["host"] on_shared_storage = strutils.bool_from_string( evacuate_body["onSharedStorage"]) password = None if 'adminPass' in evacuate_body: # check that if requested to evacuate server on shared storage # password not specified if on_shared_storage: msg = _("admin password can't be changed on existing disk") raise exc.HTTPBadRequest(explanation=msg) password = evacuate_body['adminPass'] elif not on_shared_storage: password = utils.generate_password() except (TypeError, KeyError): msg = _("host and onSharedStorage must be specified.") raise exc.HTTPBadRequest(explanation=msg) try: instance = self.compute_api.get(context, id) self.compute_api.evacuate(context, instance, host, on_shared_storage, password) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'evacuate') except Exception as e: msg = _("Error in evacuate, %s") % e LOG.exception(msg, instance=instance) raise exc.HTTPBadRequest(explanation=msg) if password: return {'adminPass': password}
def _evacuate(self, req, id, body): """Permit admins to evacuate a server from a failed host to a new one. """ context = req.environ["nova.context"] authorize(context) evacuate_body = body["evacuate"] host = evacuate_body["host"] on_shared_storage = strutils.bool_from_string( evacuate_body["on_shared_storage"]) password = None if 'admin_password' in evacuate_body: # check that if requested to evacuate server on shared storage # password not specified if on_shared_storage: msg = _("admin password can't be changed on existing disk") raise exc.HTTPBadRequest(explanation=msg) password = evacuate_body['admin_password'] elif not on_shared_storage: password = utils.generate_password() try: self.host_api.service_get_by_compute_host(context, host) except exception.NotFound: msg = _("Compute host %s not found.") % host raise exc.HTTPNotFound(explanation=msg) instance = common.get_instance(self.compute_api, context, id) try: self.compute_api.evacuate(context, instance, host, on_shared_storage, password) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state( state_error, 'evacuate') except exception.ComputeServiceInUse as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if CONF.enable_instance_password: return {'admin_password': password} else: return {}
def from_image(cls, image_id, image_meta=None): """Returns VMwareImage, the subset of properties the driver uses. :param image_id - image id of image :param image_meta - image metadata we are working with :return: vmware image object :rtype: nova.virt.vmwareapi.vmware_images.VmwareImage """ if image_meta is None: image_meta = {} properties = image_meta.get("properties", {}) # calculate linked_clone flag, allow image properties to override the # global property set in the configurations. image_linked_clone = properties.get(LINKED_CLONE_PROPERTY, CONF.vmware.use_linked_clone) # catch any string values that need to be interpreted as boolean values linked_clone = strutils.bool_from_string(image_linked_clone) props = { 'image_id': image_id, 'linked_clone': linked_clone } if 'size' in image_meta: props['file_size'] = image_meta['size'] if 'disk_format' in image_meta: props['file_type'] = image_meta['disk_format'] props_map = { 'vmware_ostype': 'os_type', 'vmware_adaptertype': 'adapter_type', 'vmware_disktype': 'disk_type', 'hw_vif_model': 'vif_model' } for k, v in props_map.iteritems(): if k in properties: props[v] = properties[k] return cls(**props)
def index(self, req): """Return a list of floating ips.""" context = req.environ['nova.context'] authorize(context) all_tenants = False if 'all_tenants' in req.GET: try: if strutils.bool_from_string(req.GET['all_tenants'], True): authorize_all_tenants(context) all_tenants = True except ValueError as err: raise webob.exc.HTTPBadRequest(explanation=str(err)) floating_ips = self.network_api.get_floating_ips(context, all_tenants) for floating_ip in floating_ips: self._normalize_ip(floating_ip) return _translate_floating_ips_view(floating_ips)
def from_image(cls, image_id, image_meta=None): """Returns VMwareImage, the subset of properties the driver uses. :param image_id - image id of image :param image_meta - image metadata we are working with :return: vmware image object :rtype: nova.virt.vmwareapi.vmware_images.VmwareImage """ if image_meta is None: image_meta = {} properties = image_meta.get("properties", {}) # calculate linked_clone flag, allow image properties to override the # global property set in the configurations. image_linked_clone = properties.get(LINKED_CLONE_PROPERTY, CONF.vmware.use_linked_clone) # catch any string values that need to be interpreted as boolean values linked_clone = strutils.bool_from_string(image_linked_clone) props = {'image_id': image_id, 'linked_clone': linked_clone} if 'size' in image_meta: props['file_size'] = image_meta['size'] if 'disk_format' in image_meta: props['file_type'] = image_meta['disk_format'] props_map = { 'vmware_ostype': 'os_type', 'vmware_adaptertype': 'adapter_type', 'vmware_disktype': 'disk_type', 'hw_vif_model': 'vif_model' } for k, v in props_map.iteritems(): if k in properties: props[v] = properties[k] return cls(**props)
def _untranslate_volume_summary_view(context, vol): """Maps keys for volumes summary view.""" d = {} d['id'] = vol.id d['status'] = vol.status d['size'] = vol.size d['availability_zone'] = vol.availability_zone d['created_at'] = vol.created_at # TODO(jdg): The calling code expects attach_time and # mountpoint to be set. When the calling # code is more defensive this can be # removed. d['attach_time'] = "" d['mountpoint'] = "" if vol.attachments: att = vol.attachments[0] d['attach_status'] = 'attached' d['instance_uuid'] = att['server_id'] d['mountpoint'] = att['device'] else: d['attach_status'] = 'detached' d['display_name'] = vol.display_name d['display_description'] = vol.display_description # TODO(jdg): Information may be lost in this translation d['volume_type_id'] = vol.volume_type d['snapshot_id'] = vol.snapshot_id d['bootable'] = strutils.bool_from_string(vol.bootable) d['volume_metadata'] = {} for key, value in vol.metadata.items(): d['volume_metadata'][key] = value if hasattr(vol, 'volume_image_metadata'): d['volume_image_metadata'] = copy.deepcopy(vol.volume_image_metadata) return d
def server_create(self, server_dict, create_kwargs, body_deprecated_param): block_device_mapping = server_dict.get(ATTRIBUTE_NAME, []) block_device_mapping_v2 = server_dict.get(ATTRIBUTE_NAME_V2, []) if block_device_mapping and block_device_mapping_v2: expl = _('Using different block_device_mapping syntaxes ' 'is not allowed in the same request.') raise exc.HTTPBadRequest(explanation=expl) for bdm in block_device_mapping: try: block_device.validate_device_name(bdm.get("device_name")) block_device.validate_and_default_volume_size(bdm) except exception.InvalidBDMFormat as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if 'delete_on_termination' in bdm: bdm['delete_on_termination'] = strutils.bool_from_string( bdm['delete_on_termination']) if block_device_mapping: create_kwargs['block_device_mapping'] = block_device_mapping # Sets the legacy_bdm flag if we got a legacy block device mapping. create_kwargs['legacy_bdm'] = True
def update(self, req, id, body): context = req.environ['nova.context'] authorize_update(context) project_id = id params = urlparse.parse_qs(req.environ.get('QUERY_STRING', '')) user_id = params.get('user_id', [None])[0] bad_keys = [] force_update = False if not self.is_valid_body(body, 'quota_set'): msg = _("quota_set not specified") raise webob.exc.HTTPBadRequest(explanation=msg) quota_set = body['quota_set'] for key, value in quota_set.items(): if key not in QUOTAS and key != 'force': bad_keys.append(key) continue if key == 'force': force_update = strutils.bool_from_string(value) elif key != 'force' and value: try: value = int(value) except (ValueError, TypeError): msg = _("Quota value for key '%(key)s' should be an " "integer. It is actually type '%(vtype)s'.") msg = msg % {'key': key, 'vtype': type(value)} LOG.warn(msg) raise webob.exc.HTTPBadRequest(explanation=msg) if len(bad_keys) > 0: msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) try: settable_quotas = QUOTAS.get_settable_quotas(context, project_id, user_id=user_id) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() try: quotas = self._get_quotas(context, id, user_id=user_id, usages=True) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() LOG.debug(_("Force update quotas: %s"), force_update) for key, value in body['quota_set'].iteritems(): if key == 'force' or (not value and value != 0): continue # validate whether already used and reserved exceeds the new # quota, this check will be ignored if admin want to force # update value = int(value) if force_update is not True and value >= 0: quota_value = quotas.get(key) if quota_value and quota_value['limit'] >= 0: quota_used = (quota_value['in_use'] + quota_value['reserved']) LOG.debug( _("Quota %(key)s used: %(quota_used)s, " "value: %(value)s."), { 'key': key, 'quota_used': quota_used, 'value': value }) if quota_used > value: msg = (_("Quota value %(value)s for %(key)s are " "less than already used and reserved " "%(quota_used)s") % { 'value': value, 'key': key, 'quota_used': quota_used }) raise webob.exc.HTTPBadRequest(explanation=msg) minimum = settable_quotas[key]['minimum'] maximum = settable_quotas[key]['maximum'] self._validate_quota_limit(value, minimum, maximum) try: db.quota_create(context, project_id, key, value, user_id=user_id) except exception.QuotaExists: db.quota_update(context, project_id, key, value, user_id=user_id) except exception.AdminRequired: raise webob.exc.HTTPForbidden() return self._format_quota_set( id, self._get_quotas(context, id, user_id=user_id))
def update(self, req, id, body): context = req.environ['nova.context'] authorize_update(context) project_id = id bad_keys = [] # By default, we can force update the quota if the extended # is not loaded force_update = True extended_loaded = False if self.ext_mgr.is_loaded('os-extended-quotas'): # force optional has been enabled, the default value of # force_update need to be changed to False extended_loaded = True force_update = False for key, value in body['quota_set'].items(): if (key not in QUOTAS and key not in NON_QUOTA_KEYS): bad_keys.append(key) continue if key == 'force' and extended_loaded: # only check the force optional when the extended has # been loaded force_update = strutils.bool_from_string(value) elif key not in NON_QUOTA_KEYS and value: try: value = int(value) except (ValueError, TypeError): msg = _("Quota '%(value)s' for %(key)s should be " "integer.") % locals() LOG.warn(msg) raise webob.exc.HTTPBadRequest(explanation=msg) self._validate_quota_limit(value) LOG.debug(_("force update quotas: %s") % force_update) if len(bad_keys) > 0: msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) try: project_quota = self._get_quotas(context, id, True) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() for key, value in body['quota_set'].items(): if key in NON_QUOTA_KEYS or not value: continue # validate whether already used and reserved exceeds the new # quota, this check will be ignored if admin want to force # update value = int(value) if force_update is not True and value >= 0: quota_value = project_quota.get(key) if quota_value and quota_value['limit'] >= 0: quota_used = (quota_value['in_use'] + quota_value['reserved']) LOG.debug( _("Quota %(key)s used: %(quota_used)s, " "value: %(value)s."), { 'key': key, 'quota_used': quota_used, 'value': value }) if quota_used > value: msg = (_("Quota value %(value)s for %(key)s are " "greater than already used and reserved " "%(quota_used)s") % { 'value': value, 'key': key, 'quota_used': quota_used }) raise webob.exc.HTTPBadRequest(explanation=msg) try: db.quota_update(context, project_id, key, value) except exception.ProjectQuotaNotFound: db.quota_create(context, project_id, key, value) except exception.AdminRequired: raise webob.exc.HTTPForbidden() return {'quota_set': self._get_quotas(context, id)}
def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None, swap=0, rxtx_factor=1.0, is_public=True): """Creates flavors.""" if not flavorid: flavorid = uuid.uuid4() kwargs = { 'memory_mb': memory, 'vcpus': vcpus, 'root_gb': root_gb, 'ephemeral_gb': ephemeral_gb, 'swap': swap, 'rxtx_factor': rxtx_factor, } if isinstance(name, six.string_types): name = name.strip() # ensure name do not exceed 255 characters utils.check_string_length(name, 'name', min_length=1, max_length=255) # ensure name does not contain any special characters valid_name = VALID_NAME_REGEX.search(name) if not valid_name: msg = _("Flavor names can only contain alphanumeric characters, " "periods, dashes, underscores and spaces.") raise exception.InvalidInput(reason=msg) # NOTE(vish): Internally, flavorid is stored as a string but it comes # in through json as an integer, so we convert it here. flavorid = unicode(flavorid) # ensure leading/trailing whitespaces not present. if flavorid.strip() != flavorid: msg = _("id cannot contain leading and/or trailing whitespace(s)") raise exception.InvalidInput(reason=msg) # ensure flavor id does not exceed 255 characters utils.check_string_length(flavorid, 'id', min_length=1, max_length=255) # ensure flavor id does not contain any special characters valid_flavor_id = VALID_ID_REGEX.search(flavorid) if not valid_flavor_id: msg = _("Flavor id can only contain letters from A-Z (both cases), " "periods, dashes, underscores and spaces.") raise exception.InvalidInput(reason=msg) # NOTE(wangbo): validate attributes of the creating flavor. # ram and vcpus should be positive ( > 0) integers. # disk, ephemeral and swap should be non-negative ( >= 0) integers. flavor_attributes = { 'memory_mb': ('ram', 1), 'vcpus': ('vcpus', 1), 'root_gb': ('disk', 0), 'ephemeral_gb': ('ephemeral', 0), 'swap': ('swap', 0) } for key, value in flavor_attributes.items(): kwargs[key] = utils.validate_integer(kwargs[key], value[0], value[1], db.MAX_INT) # rxtx_factor should be a positive float try: kwargs['rxtx_factor'] = float(kwargs['rxtx_factor']) if (kwargs['rxtx_factor'] <= 0 or kwargs['rxtx_factor'] > SQL_SP_FLOAT_MAX): raise ValueError() except ValueError: msg = (_("'rxtx_factor' argument must be a float between 0 and %g") % SQL_SP_FLOAT_MAX) raise exception.InvalidInput(reason=msg) kwargs['name'] = name kwargs['flavorid'] = flavorid # ensure is_public attribute is boolean try: kwargs['is_public'] = strutils.bool_from_string(is_public, strict=True) except ValueError: raise exception.InvalidInput(reason=_("is_public must be a boolean")) try: return db.flavor_create(context.get_admin_context(), kwargs) except db_exc.DBError as e: LOG.exception(_LE('DB error: %s'), e) raise exception.FlavorCreateFailed()
def _get_sys_meta_key(self, key): sys_meta = utils.instance_sys_meta(self.instance) raw_value = sys_meta.get(key, 'False') return strutils.bool_from_string(raw_value, strict=False)
def _action_rebuild(self, req, id, body): """Rebuild an instance with the given attributes.""" try: rebuild_dict = body['rebuild'] except (KeyError, TypeError): msg = _('Invalid request body') raise exc.HTTPBadRequest(explanation=msg) try: image_href = rebuild_dict["image_ref"] except (KeyError, TypeError): msg = _("Could not parse image_ref from request.") raise exc.HTTPBadRequest(explanation=msg) image_href = self._image_uuid_from_href(image_href) password = self._get_server_admin_password(rebuild_dict) context = req.environ['nova.context'] instance = self._get_server(context, req, id) attr_map = { 'name': 'display_name', 'metadata': 'metadata', } rebuild_kwargs = {} if 'name' in rebuild_dict: self._validate_server_name(rebuild_dict['name']) if 'preserve_ephemeral' in rebuild_dict: rebuild_kwargs['preserve_ephemeral'] = strutils.bool_from_string( rebuild_dict['preserve_ephemeral'], strict=True) if list(self.rebuild_extension_manager): self.rebuild_extension_manager.map(self._rebuild_extension_point, rebuild_dict, rebuild_kwargs) for request_attribute, instance_attribute in attr_map.items(): try: rebuild_kwargs[instance_attribute] = rebuild_dict[ request_attribute] except (KeyError, TypeError): pass try: self.compute_api.rebuild(context, instance, image_href, password, **rebuild_kwargs) 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, 'rebuild') except exception.InstanceNotFound: msg = _("Instance could not be found") raise exc.HTTPNotFound(explanation=msg) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.ImageNotFound: msg = _("Cannot find image for rebuild") raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) instance = self._get_server(context, req, id) view = self._view_builder.show(req, instance) # Add on the admin_password attribute since the view doesn't do it # unless instance passwords are disabled if CONF.enable_instance_password: view['server']['admin_password'] = password robj = wsgi.ResponseObject(view) return self._add_location(robj)
def update(self, req, id, body): context = req.environ["nova.context"] authorize_update(context) project_id = id bad_keys = [] # By default, we can force update the quota if the extended # is not loaded force_update = True extended_loaded = False if self.ext_mgr.is_loaded("os-extended-quotas"): # force optional has been enabled, the default value of # force_update need to be changed to False extended_loaded = True force_update = False user_id = None if self.ext_mgr.is_loaded("os-user-quotas"): # Update user quotas only if the extended is loaded params = urlparse.parse_qs(req.environ.get("QUERY_STRING", "")) user_id = params.get("user_id", [None])[0] try: settable_quotas = QUOTAS.get_settable_quotas(context, project_id, user_id=user_id) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() if not self.is_valid_body(body, "quota_set"): msg = _("quota_set not specified") raise webob.exc.HTTPBadRequest(explanation=msg) quota_set = body["quota_set"] for key, value in quota_set.items(): if key not in QUOTAS and key not in NON_QUOTA_KEYS: bad_keys.append(key) continue if key == "force" and extended_loaded: # only check the force optional when the extended has # been loaded force_update = strutils.bool_from_string(value) elif key not in NON_QUOTA_KEYS and value: try: value = utils.validate_integer(value, key) except exception.InvalidInput as e: LOG.warn(e.format_message()) raise webob.exc.HTTPBadRequest(explanation=e.format_message()) LOG.debug(_("force update quotas: %s") % force_update) if len(bad_keys) > 0: msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) try: quotas = self._get_quotas(context, id, user_id=user_id, usages=True) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() for key, value in quota_set.items(): if key in NON_QUOTA_KEYS or (not value and value != 0): continue # validate whether already used and reserved exceeds the new # quota, this check will be ignored if admin want to force # update value = int(value) if force_update is not True and value >= 0: quota_value = quotas.get(key) if quota_value and quota_value["limit"] >= 0: quota_used = quota_value["in_use"] + quota_value["reserved"] LOG.debug( _("Quota %(key)s used: %(quota_used)s, " "value: %(value)s."), {"key": key, "quota_used": quota_used, "value": value}, ) if quota_used > value: msg = _( "Quota value %(value)s for %(key)s are " "less than already used and reserved " "%(quota_used)s" ) % {"value": value, "key": key, "quota_used": quota_used} raise webob.exc.HTTPBadRequest(explanation=msg) minimum = settable_quotas[key]["minimum"] maximum = settable_quotas[key]["maximum"] self._validate_quota_limit(value, minimum, maximum) try: db.quota_create(context, project_id, key, value, user_id=user_id) except exception.QuotaExists: db.quota_update(context, project_id, key, value, user_id=user_id) except exception.AdminRequired: raise webob.exc.HTTPForbidden() return {"quota_set": self._get_quotas(context, id, user_id=user_id)}
def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None, swap=0, rxtx_factor=1.0, is_public=True): """Creates flavors.""" if not flavorid: flavorid = uuid.uuid4() kwargs = { "memory_mb": memory, "vcpus": vcpus, "root_gb": root_gb, "ephemeral_gb": ephemeral_gb, "swap": swap, "rxtx_factor": rxtx_factor, } # ensure name do not exceed 255 characters utils.check_string_length(name, "name", min_length=1, max_length=255) # ensure name does not contain any special characters invalid_name = INVALID_NAME_REGEX.search(name) if invalid_name: msg = _("names can only contain [a-zA-Z0-9_.- ]") raise exception.InvalidInput(reason=msg) # Some attributes are positive ( > 0) integers for option in ["memory_mb", "vcpus"]: try: assert int(str(kwargs[option])) > 0 kwargs[option] = int(kwargs[option]) except (ValueError, AssertionError, TypeError): msg = _("'%s' argument must be a positive integer") % option raise exception.InvalidInput(reason=msg) # Some attributes are non-negative ( >= 0) integers for option in ["root_gb", "ephemeral_gb", "swap"]: try: assert int(str(kwargs[option])) >= 0 kwargs[option] = int(kwargs[option]) except (ValueError, AssertionError, TypeError): msg = _("'%s' argument must be an integer greater than or" " equal to 0") % option raise exception.InvalidInput(reason=msg) # rxtx_factor should be a positive float try: kwargs["rxtx_factor"] = float(kwargs["rxtx_factor"]) assert kwargs["rxtx_factor"] > 0 except (ValueError, AssertionError): msg = _("'rxtx_factor' argument must be a positive float") raise exception.InvalidInput(reason=msg) kwargs["name"] = name # NOTE(vish): Internally, flavorid is stored as a string but it comes # in through json as an integer, so we convert it here. kwargs["flavorid"] = unicode(flavorid) # ensure is_public attribute is boolean try: kwargs["is_public"] = strutils.bool_from_string(is_public, strict=True) except ValueError: raise exception.InvalidInput(reason=_("is_public must be a boolean")) try: return db.instance_type_create(context.get_admin_context(), kwargs) except db_exc.DBError as e: LOG.exception(_("DB error: %s") % e) raise exception.InstanceTypeCreateFailed()
def update(self, req, id, body): context = req.environ['nova.context'] authorize_update(context) project_id = id params = urlparse.parse_qs(req.environ.get('QUERY_STRING', '')) user_id = params.get('user_id', [None])[0] bad_keys = [] force_update = False if not self.is_valid_body(body, 'quota_set'): msg = _("quota_set not specified") raise webob.exc.HTTPBadRequest(explanation=msg) quota_set = body['quota_set'] for key, value in quota_set.items(): if ((key not in QUOTAS or key in FILTERED_QUOTAS) and key != 'force'): bad_keys.append(key) continue if key == 'force': force_update = strutils.bool_from_string(value) elif key != 'force' and value: try: value = utils.validate_integer( value, key) except exception.InvalidInput as e: LOG.warn(e.format_message()) raise webob.exc.HTTPBadRequest( explanation=e.format_message()) if len(bad_keys) > 0: msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) try: settable_quotas = QUOTAS.get_settable_quotas(context, project_id, user_id=user_id) except exception.Forbidden: raise webob.exc.HTTPForbidden() try: quotas = self._get_quotas(context, id, user_id=user_id, usages=True) except exception.Forbidden: raise webob.exc.HTTPForbidden() LOG.debug("Force update quotas: %s", force_update) for key, value in body['quota_set'].iteritems(): if key == 'force' or (not value and value != 0): continue # validate whether already used and reserved exceeds the new # quota, this check will be ignored if admin want to force # update value = int(value) if force_update is not True and value >= 0: quota_value = quotas.get(key) if quota_value and quota_value['limit'] >= 0: quota_used = (quota_value['in_use'] + quota_value['reserved']) LOG.debug("Quota %(key)s used: %(quota_used)s, " "value: %(value)s.", {'key': key, 'quota_used': quota_used, 'value': value}) if quota_used > value: msg = (_("Quota value %(value)s for %(key)s are " "less than already used and reserved " "%(quota_used)s") % {'value': value, 'key': key, 'quota_used': quota_used}) raise webob.exc.HTTPBadRequest(explanation=msg) minimum = settable_quotas[key]['minimum'] maximum = settable_quotas[key]['maximum'] self._validate_quota_limit(value, minimum, maximum) try: db.quota_create(context, project_id, key, value, user_id=user_id) except exception.QuotaExists: db.quota_update(context, project_id, key, value, user_id=user_id) except exception.AdminRequired: raise webob.exc.HTTPForbidden() return self._format_quota_set(id, self._get_quotas(context, id, user_id=user_id))
def update(self, req, id, body): context = req.environ['nova.context'] authorize_update(context) project_id = id bad_keys = [] # By default, we can force update the quota if the extended # is not loaded force_update = True extended_loaded = False if self.ext_mgr.is_loaded('os-extended-quotas'): # force optional has been enabled, the default value of # force_update need to be changed to False extended_loaded = True force_update = False user_id = None if self.ext_mgr.is_loaded('os-user-quotas'): # Update user quotas only if the extended is loaded params = urlparse.parse_qs(req.environ.get('QUERY_STRING', '')) user_id = params.get('user_id', [None])[0] try: settable_quotas = QUOTAS.get_settable_quotas(context, project_id, user_id=user_id) except exception.Forbidden: raise webob.exc.HTTPForbidden() if not self.is_valid_body(body, 'quota_set'): msg = _("quota_set not specified") raise webob.exc.HTTPBadRequest(explanation=msg) quota_set = body['quota_set'] for key, value in quota_set.items(): if (key not in QUOTAS and key not in NON_QUOTA_KEYS): bad_keys.append(key) continue if key == 'force' and extended_loaded: # only check the force optional when the extended has # been loaded force_update = strutils.bool_from_string(value) elif key not in NON_QUOTA_KEYS and value: try: value = utils.validate_integer(value, key) except exception.InvalidInput as e: raise webob.exc.HTTPBadRequest( explanation=e.format_message()) LOG.debug("force update quotas: %s", force_update) if len(bad_keys) > 0: msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) try: quotas = self._get_quotas(context, id, user_id=user_id, usages=True) except exception.Forbidden: raise webob.exc.HTTPForbidden() for key, value in quota_set.items(): if key in NON_QUOTA_KEYS or (not value and value != 0): continue # validate whether already used and reserved exceeds the new # quota, this check will be ignored if admin want to force # update value = int(value) if force_update is not True and value >= 0: quota_value = quotas.get(key) if quota_value and quota_value['limit'] >= 0: quota_used = (quota_value['in_use'] + quota_value['reserved']) LOG.debug( "Quota %(key)s used: %(quota_used)s, " "value: %(value)s.", { 'key': key, 'quota_used': quota_used, 'value': value }) if quota_used > value: msg = (_("Quota value %(value)s for %(key)s are " "less than already used and reserved " "%(quota_used)s") % { 'value': value, 'key': key, 'quota_used': quota_used }) raise webob.exc.HTTPBadRequest(explanation=msg) minimum = settable_quotas[key]['minimum'] maximum = settable_quotas[key]['maximum'] self._validate_quota_limit(value, minimum, maximum) try: db.quota_create(context, project_id, key, value, user_id=user_id) except exception.QuotaExists: db.quota_update(context, project_id, key, value, user_id=user_id) except exception.AdminRequired: raise webob.exc.HTTPForbidden() return {'quota_set': self._get_quotas(context, id, user_id=user_id)}
def required_by(instance): return (instance.get('config_drive') or 'always' == CONF.force_config_drive or strutils.bool_from_string(CONF.force_config_drive))
def _get_servers(self, req, is_detail): """Returns a list of servers, based on any search options specified.""" search_opts = {} search_opts.update(req.GET) context = req.environ['nova.context'] remove_invalid_options(context, search_opts, self._get_server_search_options()) # Verify search by 'status' contains a valid status. # Convert it to filter by vm_state or task_state for compute_api. status = search_opts.pop('status', None) if status is not None: vm_state, task_state = common.task_and_vm_state_from_status(status) if not vm_state and not task_state: return {'servers': []} search_opts['vm_state'] = vm_state # When we search by vm state, task state will return 'default'. # So we don't need task_state search_opt. if 'default' not in task_state: search_opts['task_state'] = task_state if 'changes_since' in search_opts: try: parsed = timeutils.parse_isotime(search_opts['changes_since']) except ValueError: msg = _('Invalid changes_since value') raise exc.HTTPBadRequest(explanation=msg) search_opts['changes_since'] = parsed # By default, compute's get_all() will return deleted instances. # If an admin hasn't specified a 'deleted' search option, we need # to filter out deleted instances by setting the filter ourselves. # ... Unless 'changes_since' is specified, because 'changes_since' # should return recently deleted images according to the API spec. if 'deleted' not in search_opts: if 'changes_since' not in search_opts: # No 'changes_since', so we only want non-deleted servers search_opts['deleted'] = False if 'changes_since' in search_opts: search_opts['changes-since'] = search_opts.pop('changes_since') if search_opts.get("vm_state") == ['deleted']: if context.is_admin: search_opts['deleted'] = True else: msg = _("Only administrators may list deleted instances") raise exc.HTTPBadRequest(explanation=msg) # If tenant_id is passed as a search parameter this should # imply that all_tenants is also enabled unless explicitly # disabled. Note that the tenant_id parameter is filtered out # by remove_invalid_options above unless the requestor is an # admin. if 'tenant_id' in search_opts and not 'all_tenants' in search_opts: # We do not need to add the all_tenants flag if the tenant # id associated with the token is the tenant id # specified. This is done so a request that does not need # the all_tenants flag does not fail because of lack of # policy permission for compute:get_all_tenants when it # doesn't actually need it. if context.project_id != search_opts.get('tenant_id'): search_opts['all_tenants'] = 1 # If all tenants is passed with 0 or false as the value # then remove it from the search options. Nothing passed as # the value for all_tenants is considered to enable the feature all_tenants = search_opts.get('all_tenants') if all_tenants: try: if not strutils.bool_from_string(all_tenants, True): del search_opts['all_tenants'] except ValueError as err: raise exception.InvalidInput(str(err)) if 'all_tenants' in search_opts: policy.enforce(context, 'compute:get_all_tenants', { 'project_id': context.project_id, 'user_id': context.user_id }) del search_opts['all_tenants'] else: if context.project_id: search_opts['project_id'] = context.project_id else: search_opts['user_id'] = context.user_id limit, marker = common.get_limit_and_marker(req) try: instance_list = self.compute_api.get_all( context, search_opts=search_opts, limit=limit, marker=marker, want_objects=True, expected_attrs=['pci_devices']) except exception.MarkerNotFound: msg = _('marker [%s] not found') % marker raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: log_msg = _("Flavor '%s' could not be found ") LOG.debug(log_msg, search_opts['flavor']) instance_list = [] if is_detail: instance_list.fill_faults() response = self._view_builder.detail(req, instance_list) else: response = self._view_builder.index(req, instance_list) req.cache_db_instances(instance_list) return response
def _get_servers(self, req, is_detail): """Returns a list of servers, based on any search options specified.""" search_opts = {} search_opts.update(req.GET) context = req.environ['nova.context'] remove_invalid_options(context, search_opts, self._get_server_search_options()) # Verify search by 'status' contains a valid status. # Convert it to filter by vm_state or task_state for compute_api. status = search_opts.pop('status', None) if status is not None: vm_state, task_state = common.task_and_vm_state_from_status(status) if not vm_state and not task_state: return {'servers': []} search_opts['vm_state'] = vm_state # When we search by vm state, task state will return 'default'. # So we don't need task_state search_opt. if 'default' not in task_state: search_opts['task_state'] = task_state if 'changes_since' in search_opts: try: parsed = timeutils.parse_isotime(search_opts['changes_since']) except ValueError: msg = _('Invalid changes_since value') raise exc.HTTPBadRequest(explanation=msg) search_opts['changes_since'] = parsed # By default, compute's get_all() will return deleted instances. # If an admin hasn't specified a 'deleted' search option, we need # to filter out deleted instances by setting the filter ourselves. # ... Unless 'changes_since' is specified, because 'changes_since' # should return recently deleted images according to the API spec. if 'deleted' not in search_opts: if 'changes_since' not in search_opts: # No 'changes_since', so we only want non-deleted servers search_opts['deleted'] = False if 'changes_since' in search_opts: search_opts['changes-since'] = search_opts.pop('changes_since') if search_opts.get("vm_state") == ['deleted']: if context.is_admin: search_opts['deleted'] = True else: msg = _("Only administrators may list deleted instances") raise exc.HTTPBadRequest(explanation=msg) # If tenant_id is passed as a search parameter this should # imply that all_tenants is also enabled unless explicitly # disabled. Note that the tenant_id parameter is filtered out # by remove_invalid_options above unless the requestor is an # admin. if 'tenant_id' in search_opts and not 'all_tenants' in search_opts: # We do not need to add the all_tenants flag if the tenant # id associated with the token is the tenant id # specified. This is done so a request that does not need # the all_tenants flag does not fail because of lack of # policy permission for compute:get_all_tenants when it # doesn't actually need it. if context.project_id != search_opts.get('tenant_id'): search_opts['all_tenants'] = 1 # If all tenants is passed with 0 or false as the value # then remove it from the search options. Nothing passed as # the value for all_tenants is considered to enable the feature all_tenants = search_opts.get('all_tenants') if all_tenants: try: if not strutils.bool_from_string(all_tenants, True): del search_opts['all_tenants'] except ValueError as err: raise exception.InvalidInput(str(err)) if 'all_tenants' in search_opts: policy.enforce(context, 'compute:get_all_tenants', {'project_id': context.project_id, 'user_id': context.user_id}) del search_opts['all_tenants'] else: if context.project_id: search_opts['project_id'] = context.project_id else: search_opts['user_id'] = context.user_id limit, marker = common.get_limit_and_marker(req) try: instance_list = self.compute_api.get_all(context, search_opts=search_opts, limit=limit, marker=marker, want_objects=True, expected_attrs=['pci_devices']) except exception.MarkerNotFound: msg = _('marker [%s] not found') % marker raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: log_msg = _("Flavor '%s' could not be found ") LOG.debug(log_msg, search_opts['flavor']) instance_list = [] if is_detail: instance_list.fill_faults() response = self._view_builder.detail(req, instance_list) else: response = self._view_builder.index(req, instance_list) req.cache_db_instances(instance_list) return response
def _action_rebuild(self, req, id, body): """Rebuild an instance with the given attributes.""" try: rebuild_dict = body['rebuild'] except (KeyError, TypeError): msg = _('Invalid request body') raise exc.HTTPBadRequest(explanation=msg) try: image_href = rebuild_dict["image_ref"] except (KeyError, TypeError): msg = _("Could not parse image_ref from request.") raise exc.HTTPBadRequest(explanation=msg) image_href = self._image_uuid_from_href(image_href) password = self._get_server_admin_password(rebuild_dict) context = req.environ['nova.context'] instance = self._get_server(context, req, id) attr_map = { 'name': 'display_name', 'metadata': 'metadata', } rebuild_kwargs = {} if 'name' in rebuild_dict: self._validate_server_name(rebuild_dict['name']) if 'preserve_ephemeral' in rebuild_dict: rebuild_kwargs['preserve_ephemeral'] = strutils.bool_from_string( rebuild_dict['preserve_ephemeral'], strict=True) if list(self.rebuild_extension_manager): self.rebuild_extension_manager.map(self._rebuild_extension_point, rebuild_dict, rebuild_kwargs) for request_attribute, instance_attribute in attr_map.items(): try: rebuild_kwargs[instance_attribute] = rebuild_dict[ request_attribute] except (KeyError, TypeError): pass try: self.compute_api.rebuild(context, instance, image_href, password, **rebuild_kwargs) 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, 'rebuild') except exception.InstanceNotFound: msg = _("Instance could not be found") raise exc.HTTPNotFound(explanation=msg) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.ImageNotFound: msg = _("Cannot find image for rebuild") raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) instance = self._get_server(context, req, id) view = self._view_builder.show(req, instance) # Add on the admin_password attribute since the view doesn't do it # unless instance passwords are disabled if CONF.enable_instance_password: view['server']['admin_password'] = password robj = wsgi.ResponseObject(view) return self._add_location(robj)
def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None, swap=0, rxtx_factor=1.0, is_public=True): """Creates flavors.""" if not flavorid: flavorid = uuid.uuid4() kwargs = { 'memory_mb': memory, 'vcpus': vcpus, 'root_gb': root_gb, 'ephemeral_gb': ephemeral_gb, 'swap': swap, 'rxtx_factor': rxtx_factor, } # ensure name do not exceed 255 characters utils.check_string_length(name, 'name', min_length=1, max_length=255) # ensure name does not contain any special characters valid_name = VALID_NAME_OR_ID_REGEX.search(name) if not valid_name: msg = _("names can only contain [a-zA-Z0-9_.- ]") raise exception.InvalidInput(reason=msg) # NOTE(vish): Internally, flavorid is stored as a string but it comes # in through json as an integer, so we convert it here. flavorid = unicode(flavorid) # ensure leading/trailing whitespaces not present. if flavorid.strip() != flavorid: msg = _("id cannot contain leading and/or trailing whitespace(s)") raise exception.InvalidInput(reason=msg) # ensure flavor id does not exceed 255 characters utils.check_string_length(flavorid, 'id', min_length=1, max_length=255) # ensure flavor id does not contain any special characters valid_flavor_id = VALID_NAME_OR_ID_REGEX.search(flavorid) if not valid_flavor_id: msg = _("id can only contain [a-zA-Z0-9_.- ]") raise exception.InvalidInput(reason=msg) # Some attributes are positive ( > 0) integers for option in ['memory_mb', 'vcpus']: kwargs[option] = utils.validate_integer(kwargs[option], option, 1, sys.maxint) # Some attributes are non-negative ( >= 0) integers for option in ['root_gb', 'ephemeral_gb', 'swap']: kwargs[option] = utils.validate_integer(kwargs[option], option, 0, sys.maxint) # rxtx_factor should be a positive float try: kwargs['rxtx_factor'] = float(kwargs['rxtx_factor']) if kwargs['rxtx_factor'] <= 0: raise ValueError() except ValueError: msg = _("'rxtx_factor' argument must be a positive float") raise exception.InvalidInput(reason=msg) kwargs['name'] = name kwargs['flavorid'] = flavorid # ensure is_public attribute is boolean try: kwargs['is_public'] = strutils.bool_from_string( is_public, strict=True) except ValueError: raise exception.InvalidInput(reason=_("is_public must be a boolean")) try: return db.flavor_create(context.get_admin_context(), kwargs) except db_exc.DBError as e: LOG.exception(_('DB error: %s') % e) raise exception.InstanceTypeCreateFailed()
def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None, swap=0, rxtx_factor=1.0, is_public=True): """Creates flavors.""" if not flavorid: flavorid = uuid.uuid4() kwargs = { 'memory_mb': memory, 'vcpus': vcpus, 'root_gb': root_gb, 'ephemeral_gb': ephemeral_gb, 'swap': swap, 'rxtx_factor': rxtx_factor, } if isinstance(name, six.string_types): name = name.strip() # ensure name do not exceed 255 characters utils.check_string_length(name, 'name', min_length=1, max_length=255) # ensure name does not contain any special characters valid_name = VALID_NAME_OR_ID_REGEX.search(name) if not valid_name: msg = _("names can only contain [a-zA-Z0-9_.- ]") raise exception.InvalidInput(reason=msg) # NOTE(vish): Internally, flavorid is stored as a string but it comes # in through json as an integer, so we convert it here. flavorid = unicode(flavorid) # ensure leading/trailing whitespaces not present. if flavorid.strip() != flavorid: msg = _("id cannot contain leading and/or trailing whitespace(s)") raise exception.InvalidInput(reason=msg) # ensure flavor id does not exceed 255 characters utils.check_string_length(flavorid, 'id', min_length=1, max_length=255) # ensure flavor id does not contain any special characters valid_flavor_id = VALID_NAME_OR_ID_REGEX.search(flavorid) if not valid_flavor_id: msg = _("id can only contain [a-zA-Z0-9_.- ]") raise exception.InvalidInput(reason=msg) # Some attributes are positive ( > 0) integers for option in ['memory_mb', 'vcpus']: kwargs[option] = utils.validate_integer(kwargs[option], option, 1, sys.maxint) # Some attributes are non-negative ( >= 0) integers for option in ['root_gb', 'ephemeral_gb', 'swap']: kwargs[option] = utils.validate_integer(kwargs[option], option, 0, sys.maxint) # rxtx_factor should be a positive float try: kwargs['rxtx_factor'] = float(kwargs['rxtx_factor']) if kwargs['rxtx_factor'] <= 0: raise ValueError() except ValueError: msg = _("'rxtx_factor' argument must be a positive float") raise exception.InvalidInput(reason=msg) kwargs['name'] = name kwargs['flavorid'] = flavorid # ensure is_public attribute is boolean try: kwargs['is_public'] = strutils.bool_from_string( is_public, strict=True) except ValueError: raise exception.InvalidInput(reason=_("is_public must be a boolean")) try: return db.flavor_create(context.get_admin_context(), kwargs) except db_exc.DBError as e: LOG.exception(_('DB error: %s') % e) raise exception.InstanceTypeCreateFailed()