def _set_metadata(self, req, id, body): """Replaces the aggregate's existing metadata with new metadata.""" context = _get_context(req) authorize(context) if len(body) != 1: raise exc.HTTPBadRequest() try: metadata = body["metadata"] except KeyError: raise exc.HTTPBadRequest() # The metadata should be a dict if not isinstance(metadata, dict): msg = _('The value of metadata must be a dict') raise exc.HTTPBadRequest(explanation=msg) try: for key, value in metadata.items(): utils.check_string_length(key, "metadata.key", 1, 255) if value is not None: utils.check_string_length(value, "metadata.value", 0, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) try: aggregate = self.api.update_aggregate_metadata(context, id, metadata) except exception.AggregateNotFound: msg = _('Cannot set metadata %(metadata)s in aggregate' ' %(id)s') % {'metadata': metadata, 'id': id} raise exc.HTTPNotFound(explanation=msg) except exception.InvalidAggregateAction as e: raise exc.HTTPBadRequest(explanation=e.format_message()) return self._marshall_aggregate(aggregate)
def _check_extra_specs(self, specs): if type(specs) is not dict: msg = _('Bad extra_specs provided') raise exc.HTTPBadRequest(explanation=msg) try: flavors.validate_extra_spec_keys(specs.keys()) except TypeError: msg = _("Fail to validate provided extra specs keys. " "Expected string") raise exc.HTTPBadRequest(explanation=msg) except exception.InvalidInput as error: raise exc.HTTPBadRequest(explanation=error.format_message()) for key, value in six.iteritems(specs): try: utils.check_string_length(key, 'extra_specs key', min_length=1, max_length=255) # NOTE(dims): The following check was added for backwards # compatibility. if (isinstance(value, float) or type(value) in six.integer_types): value = six.text_type(value) utils.check_string_length(value, 'extra_specs value', max_length=255) except exception.InvalidInput as error: raise exc.HTTPBadRequest(explanation=error.format_message())
def _validate_input_body(self, body, entity_name): if not self.is_valid_body(body, entity_name): msg = _("the body is invalid.") raise jacket.compute.exception.InvalidInput(reason=msg) subbody = dict(body[entity_name]) expected_fields = ['name', 'policies'] for field in expected_fields: value = subbody.pop(field, None) if not value: msg = _("'%s' is either missing or empty.") % field raise jacket.compute.exception.InvalidInput(reason=msg) if field == 'name': utils.check_string_length(value, field, min_length=1, max_length=255) if not parameter_types.valid_name_regex_obj.search(value): msg = _("Invalid format for name: '%s'") % value raise jacket.compute.exception.InvalidInput(reason=msg) elif field == 'policies': if isinstance(value, list): [utils.check_string_length(v, field, min_length=1, max_length=255) for v in value] self._validate_policies(value) else: msg = _("'%s' is not a list") % value raise jacket.compute.exception.InvalidInput(reason=msg) if subbody: msg = _("unsupported fields: %s") % subbody.keys() raise jacket.compute.exception.InvalidInput(reason=msg)
def _check_string_length(self, value, name, max_length=None): try: if isinstance(value, six.string_types): value = value.strip() utils.check_string_length(value, name, min_length=1, max_length=max_length) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message())
def _is_valid_as_reason(self, reason): try: utils.check_string_length(reason.strip(), 'Disabled reason', min_length=1, max_length=255) except exception.InvalidInput: return False return True
def _check_extra_specs_value(self, specs): for key, value in six.iteritems(specs): try: if isinstance(value, (six.integer_types, float)): value = six.text_type(value) utils.check_string_length(value, 'extra_specs value', max_length=255) except exception.InvalidInput as error: raise webob.exc.HTTPBadRequest( explanation=error.format_message())
def validate_device_name(value): try: # NOTE (ndipanov): Do not allow empty device names # until assigning default values # is supported by compute.compute utils.check_string_length(value, 'Device name', min_length=1, max_length=255) except exception.InvalidInput: raise exception.InvalidBDMFormat( details=_("Device name empty or too long.")) if ' ' in value: raise exception.InvalidBDMFormat( details=_("Device name contains spaces."))
def validate_property(self, value, property, allowed): """Validate given security group property. :param value: the value to validate, as a string or unicode :param property: the property, either 'name' or 'description' :param allowed: the range of characters allowed, but not used because Neutron is allowing any characters. """ # NOTE: If using compute-network as the backend, min_length is 1. However # if using Neutron, Nova has allowed empty string as its history. # So this min_length should be 0 for passing the existing requests. utils.check_string_length(value, name=property, min_length=0, max_length=255)
def update(self, req, id, body): context = req.environ['compute.context'] authorize(context) try: utils.check_string_length(id, 'quota_class_name', min_length=1, max_length=255) except exception.InvalidInput as e: raise webob.exc.HTTPBadRequest(explanation=e.format_message()) quota_class = id bad_keys = [] if not self.is_valid_body(body, 'quota_class_set'): msg = _("quota_class_set not specified") raise webob.exc.HTTPBadRequest(explanation=msg) quota_class_set = body['quota_class_set'] for key in quota_class_set.keys(): if key not in self.supported_quotas: bad_keys.append(key) continue try: body['quota_class_set'][key] = utils.validate_integer( body['quota_class_set'][key], key, max_value=db.MAX_INT) except exception.InvalidInput as e: raise webob.exc.HTTPBadRequest(explanation=e.format_message()) if bad_keys: msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) try: # NOTE(alex_xu): back-compatible with compute layer hard-code admin # permission checks. This has to be left only for API v2.0 because # this version has to be stable even if it means that only admins # can call this method while the policy could be changed. jacket.context.require_admin_context(context) except exception.AdminRequired: raise webob.exc.HTTPForbidden() for key, value in quota_class_set.items(): try: db.quota_class_update(context, quota_class, key, value) except exception.QuotaClassNotFound: db.quota_class_create(context, quota_class, key, value) values = QUOTAS.get_class_quotas(context, quota_class) return self._format_quota_set(None, values)
def update(self, req, id, body): context = req.environ['compute.context'] authorize(context) try: utils.check_string_length(id, 'quota_class_name', min_length=1, max_length=255) except exception.InvalidInput as e: raise webob.exc.HTTPBadRequest( explanation=e.format_message()) quota_class = id bad_keys = [] if not self.is_valid_body(body, 'quota_class_set'): msg = _("quota_class_set not specified") raise webob.exc.HTTPBadRequest(explanation=msg) quota_class_set = body['quota_class_set'] for key in quota_class_set.keys(): if key not in self.supported_quotas: bad_keys.append(key) continue try: body['quota_class_set'][key] = utils.validate_integer( body['quota_class_set'][key], key, max_value=db.MAX_INT) except exception.InvalidInput as e: raise webob.exc.HTTPBadRequest( explanation=e.format_message()) if bad_keys: msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) try: # NOTE(alex_xu): back-compatible with compute layer hard-code admin # permission checks. This has to be left only for API v2.0 because # this version has to be stable even if it means that only admins # can call this method while the policy could be changed. jacket.context.require_admin_context(context) except exception.AdminRequired: raise webob.exc.HTTPForbidden() for key, value in quota_class_set.items(): try: db.quota_class_update(context, quota_class, key, value) except exception.QuotaClassNotFound: db.quota_class_create(context, quota_class, key, value) values = QUOTAS.get_class_quotas(context, quota_class) return self._format_quota_set(None, values)
def wrapped(self, req, id, body, *args, **kwargs): if len(body) != 1: msg = _('Only host parameter can be specified') raise exc.HTTPBadRequest(explanation=msg) elif 'host' not in body: msg = _('Host parameter must be specified') raise exc.HTTPBadRequest(explanation=msg) try: utils.check_string_length(body['host'], 'host', 1, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) host = body['host'] return fn(self, req, id, host, *args, **kwargs)
def wrapped(self, req, id, body, *args, **kwargs): if len(body) != 1: msg = _('Only host parameter can be specified') raise exc.HTTPBadRequest(explanation=msg) elif 'host' not in body: msg = _('Host parameter must be specified') raise exc.HTTPBadRequest(explanation=msg) try: utils.check_string_length(body['host'], 'host', 1, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) host = body['host'] return fn(self, req, id, host, *args, **kwargs)
def validate_device_name(value): try: # NOTE (ndipanov): Do not allow empty device names # until assigning default values # is supported by compute.compute utils.check_string_length(value, 'Device name', min_length=1, max_length=255) except exception.InvalidInput: raise exception.InvalidBDMFormat( details=_("Device name empty or too long.")) if ' ' in value: raise exception.InvalidBDMFormat( details=_("Device name contains spaces."))
def validate_property(self, value, property, allowed): """Validate given security group property. :param value: the value to validate, as a string or unicode :param property: the property, either 'name' or 'description' :param allowed: the range of characters allowed, but not used because Neutron is allowing any characters. """ # NOTE: If using compute-network as the backend, min_length is 1. However # if using Neutron, Nova has allowed empty string as its history. # So this min_length should be 0 for passing the existing requests. utils.check_string_length(value, name=property, min_length=0, max_length=255)
def update(self, req, id, body): context = req.environ['compute.context'] authorize(context, action='update', target={'quota_class': id}) try: utils.check_string_length(id, 'quota_class_name', min_length=1, max_length=255) except exception.InvalidInput as e: raise webob.exc.HTTPBadRequest( explanation=e.format_message()) quota_class = id for key, value in six.iteritems(body['quota_class_set']): try: db.quota_class_update(context, quota_class, key, value) except exception.QuotaClassNotFound: db.quota_class_create(context, quota_class, key, value) values = QUOTAS.get_class_quotas(context, quota_class) return self._format_quota_set(None, values)
def update(self, req, id, body): context = req.environ['compute.context'] authorize(context, action='update', target={'quota_class': id}) try: utils.check_string_length(id, 'quota_class_name', min_length=1, max_length=255) except exception.InvalidInput as e: raise webob.exc.HTTPBadRequest(explanation=e.format_message()) quota_class = id for key, value in six.iteritems(body['quota_class_set']): try: db.quota_class_update(context, quota_class, key, value) except exception.QuotaClassNotFound: db.quota_class_create(context, quota_class, key, value) values = QUOTAS.get_class_quotas(context, quota_class) return self._format_quota_set(None, values)
def update(self, req, id, body): """Updates the name and/or availability_zone of given aggregate.""" context = _get_context(req) authorize(context) if len(body) != 1: raise exc.HTTPBadRequest() try: updates = body["aggregate"] except KeyError: raise exc.HTTPBadRequest() if len(updates) < 1: raise exc.HTTPBadRequest() for key in updates.keys(): if key not in ["name", "availability_zone"]: raise exc.HTTPBadRequest() try: if 'name' in updates: utils.check_string_length(updates['name'], "Aggregate name", 1, 255) if updates.get("availability_zone") is not None: utils.check_string_length(updates['availability_zone'], "Availability_zone", 1, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) try: aggregate = self.api.update_aggregate(context, id, updates) except exception.AggregateNameExists as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.AggregateNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.InvalidAggregateAction as e: raise exc.HTTPBadRequest(explanation=e.format_message()) return self._marshall_aggregate(aggregate)
def update(self, req, id, body): """Updates the name and/or availability_zone of given aggregate.""" context = _get_context(req) authorize(context) if len(body) != 1: raise exc.HTTPBadRequest() try: updates = body["aggregate"] except KeyError: raise exc.HTTPBadRequest() if len(updates) < 1: raise exc.HTTPBadRequest() for key in updates.keys(): if key not in ["name", "availability_zone"]: raise exc.HTTPBadRequest() try: if 'name' in updates: utils.check_string_length(updates['name'], "Aggregate name", 1, 255) if updates.get("availability_zone") is not None: utils.check_string_length(updates['availability_zone'], "Availability_zone", 1, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) try: aggregate = self.api.update_aggregate(context, id, updates) except exception.AggregateNameExists as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.AggregateNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.InvalidAggregateAction as e: raise exc.HTTPBadRequest(explanation=e.format_message()) return self._marshall_aggregate(aggregate)
def create(self, req, body): """Creates an aggregate, given its name and optional availability zone. """ context = _get_context(req) authorize(context) if len(body) != 1: raise exc.HTTPBadRequest() try: host_aggregate = body["aggregate"] name = host_aggregate["name"] except KeyError: raise exc.HTTPBadRequest() avail_zone = host_aggregate.get("availability_zone") try: utils.check_string_length(name, "Aggregate name", 1, 255) if avail_zone is not None: utils.check_string_length(avail_zone, "Availability_zone", 1, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) try: aggregate = self.api.create_aggregate(context, name, avail_zone) except exception.AggregateNameExists as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InvalidAggregateAction as e: raise exc.HTTPBadRequest(explanation=e.format_message()) agg = self._marshall_aggregate(aggregate) # To maintain the same API result as before the changes for returning # compute objects were made. del agg['aggregate']['hosts'] del agg['aggregate']['metadata'] return agg
def create(self, req, body): """Creates an aggregate, given its name and optional availability zone. """ context = _get_context(req) authorize(context) if len(body) != 1: raise exc.HTTPBadRequest() try: host_aggregate = body["aggregate"] name = host_aggregate["name"] except KeyError: raise exc.HTTPBadRequest() avail_zone = host_aggregate.get("availability_zone") try: utils.check_string_length(name, "Aggregate name", 1, 255) if avail_zone is not None: utils.check_string_length(avail_zone, "Availability_zone", 1, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) try: aggregate = self.api.create_aggregate(context, name, avail_zone) except exception.AggregateNameExists as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InvalidAggregateAction as e: raise exc.HTTPBadRequest(explanation=e.format_message()) agg = self._marshall_aggregate(aggregate) # To maintain the same API result as before the changes for returning # compute objects were made. del agg['aggregate']['hosts'] del agg['aggregate']['metadata'] return agg
def _set_metadata(self, req, id, body): """Replaces the aggregate's existing metadata with new metadata.""" context = _get_context(req) authorize(context) if len(body) != 1: raise exc.HTTPBadRequest() try: metadata = body["metadata"] except KeyError: raise exc.HTTPBadRequest() # The metadata should be a dict if not isinstance(metadata, dict): msg = _('The value of metadata must be a dict') raise exc.HTTPBadRequest(explanation=msg) try: for key, value in metadata.items(): utils.check_string_length(key, "metadata.key", 1, 255) if value is not None: utils.check_string_length(value, "metadata.value", 0, 255) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) try: aggregate = self.api.update_aggregate_metadata( context, id, metadata) except exception.AggregateNotFound: msg = _('Cannot set metadata %(metadata)s in aggregate' ' %(id)s') % { 'metadata': metadata, 'id': id } raise exc.HTTPNotFound(explanation=msg) except exception.InvalidAggregateAction as e: raise exc.HTTPBadRequest(explanation=e.format_message()) return self._marshall_aggregate(aggregate)
def update(self, req, id, body): """Update an existing agent build.""" context = req.environ['compute.context'] authorize(context) # NOTE(alex_xu): back-compatible with db layer hard-code admin # permission checks. nova_context.require_admin_context(context) try: para = body['para'] url = para['url'] md5hash = para['md5hash'] version = para['version'] except (TypeError, KeyError) as ex: msg = _("Invalid request body: %s") % ex raise webob.exc.HTTPBadRequest(explanation=msg) try: utils.validate_integer(id, 'id') utils.check_string_length(url, 'url', max_length=255) utils.check_string_length(md5hash, 'md5hash', max_length=255) utils.check_string_length(version, 'version', max_length=255) except exception.InvalidInput as exc: raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) try: agent = objects.Agent(context=context, id=id) agent.obj_reset_changes() agent.version = version agent.url = url agent.md5hash = md5hash agent.save() except exception.AgentBuildNotFound as ex: raise webob.exc.HTTPNotFound(explanation=ex.format_message()) # NOTE(alex_xu): The agent_id should be integer that consistent with # create/index actions. But parameter 'id' is string type that parsed # from url. This is a bug, but because back-compatibility, it can't be # fixed for v2 API. This will be fixed in v2.1 API by Microversions in # the future. lp bug #1333494 return { "agent": { 'agent_id': id, 'version': version, 'url': url, 'md5hash': md5hash } }
def update(self, req, id, body): """Update an existing agent build.""" context = req.environ['compute.context'] authorize(context) # NOTE(alex_xu): back-compatible with db layer hard-code admin # permission checks. nova_context.require_admin_context(context) try: para = body['para'] url = para['url'] md5hash = para['md5hash'] version = para['version'] except (TypeError, KeyError) as ex: msg = _("Invalid request body: %s") % ex raise webob.exc.HTTPBadRequest(explanation=msg) try: utils.validate_integer(id, 'id') utils.check_string_length(url, 'url', max_length=255) utils.check_string_length(md5hash, 'md5hash', max_length=255) utils.check_string_length(version, 'version', max_length=255) except exception.InvalidInput as exc: raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) try: agent = objects.Agent(context=context, id=id) agent.obj_reset_changes() agent.version = version agent.url = url agent.md5hash = md5hash agent.save() except exception.AgentBuildNotFound as ex: raise webob.exc.HTTPNotFound(explanation=ex.format_message()) # NOTE(alex_xu): The agent_id should be integer that consistent with # create/index actions. But parameter 'id' is string type that parsed # from url. This is a bug, but because back-compatibility, it can't be # fixed for v2 API. This will be fixed in v2.1 API by Microversions in # the future. lp bug #1333494 return {"agent": {'agent_id': id, 'version': version, 'url': url, 'md5hash': md5hash}}
def create(self, req, body): """Creates a new agent build.""" context = req.environ['compute.context'] authorize(context) # NOTE(alex_xu): back-compatible with db layer hard-code admin # permission checks. nova_context.require_admin_context(context) try: agent = body['agent'] hypervisor = agent['hypervisor'] os = agent['os'] architecture = agent['architecture'] version = agent['version'] url = agent['url'] md5hash = agent['md5hash'] except (TypeError, KeyError) as ex: msg = _("Invalid request body: %s") % ex raise webob.exc.HTTPBadRequest(explanation=msg) try: utils.check_string_length(hypervisor, 'hypervisor', max_length=255) utils.check_string_length(os, 'os', max_length=255) utils.check_string_length(architecture, 'architecture', max_length=255) utils.check_string_length(version, 'version', max_length=255) utils.check_string_length(url, 'url', max_length=255) utils.check_string_length(md5hash, 'md5hash', max_length=255) except exception.InvalidInput as exc: raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) try: agent_obj = objects.Agent(context=context) agent_obj.hypervisor = hypervisor agent_obj.os = os agent_obj.architecture = architecture agent_obj.version = version agent_obj.url = url agent_obj.md5hash = md5hash agent_obj.create() agent['agent_id'] = agent_obj.id except exception.AgentBuildExists as ex: raise webob.exc.HTTPConflict(explanation=ex.format_message()) return {'agent': agent}
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 = parameter_types.valid_name_regex_obj.search(name) if not valid_name: msg = _("Flavor names can only contain printable characters " "and horizontal 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 = six.text_type(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")) flavor = objects.Flavor(context=context.get_admin_context(), **kwargs) flavor.create() return flavor
def create(self, req, body): """Creates a new agent build.""" context = req.environ['compute.context'] authorize(context) # NOTE(alex_xu): back-compatible with db layer hard-code admin # permission checks. nova_context.require_admin_context(context) try: agent = body['agent'] hypervisor = agent['hypervisor'] os = agent['os'] architecture = agent['architecture'] version = agent['version'] url = agent['url'] md5hash = agent['md5hash'] except (TypeError, KeyError) as ex: msg = _("Invalid request body: %s") % ex raise webob.exc.HTTPBadRequest(explanation=msg) try: utils.check_string_length(hypervisor, 'hypervisor', max_length=255) utils.check_string_length(os, 'os', max_length=255) utils.check_string_length(architecture, 'architecture', max_length=255) utils.check_string_length(version, 'version', max_length=255) utils.check_string_length(url, 'url', max_length=255) utils.check_string_length(md5hash, 'md5hash', max_length=255) except exception.InvalidInput as exc: raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) try: agent_obj = objects.Agent(context=context) agent_obj.hypervisor = hypervisor agent_obj.os = os agent_obj.architecture = architecture agent_obj.version = version agent_obj.url = url agent_obj.md5hash = md5hash agent_obj.create() agent['agent_id'] = agent_obj.id except exception.AgentBuildExists as ex: raise webob.exc.HTTPConflict(explanation=ex.format_message()) return {'agent': agent}