Esempio n. 1
0
    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 specs.iteritems():
            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, (int, long, float))):
                    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())
Esempio n. 2
0
    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)
Esempio n. 3
0
    def _validate_input_body(self, body, entity_name):
        if not self.is_valid_body(body, entity_name):
            msg = _("the body is invalid.")
            raise patron.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 patron.exception.InvalidInput(reason=msg)
            if field == 'name':
                utils.check_string_length(value, field,
                                          min_length=1, max_length=255)
                if not common.VALID_NAME_REGEX.search(value):
                    msg = _("Invalid format for name: '%s'") % value
                    raise patron.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 patron.exception.InvalidInput(reason=msg)

        if subbody:
            msg = _("unsupported fields: %s") % subbody.keys()
            raise patron.exception.InvalidInput(reason=msg)
Esempio n. 4
0
 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())
Esempio n. 5
0
    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
Esempio n. 6
0
 def _check_extra_specs_value(self, specs):
     for key, value in specs.iteritems():
         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())
Esempio n. 7
0
    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
Esempio n. 8
0
 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())
Esempio n. 9
0
 def _check_extra_specs_value(self, specs):
     for key, value in specs.iteritems():
         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())
Esempio n. 10
0
def validate_device_name(value):
    try:
        # NOTE (ndipanov): Do not allow empty device names
        #                  until assigning default values
        #                  is supported by patron.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."))
Esempio n. 11
0
    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)
Esempio n. 12
0
    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)
Esempio n. 13
0
def validate_device_name(value):
    try:
        # NOTE (ndipanov): Do not allow empty device names
        #                  until assigning default values
        #                  is supported by patron.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."))
Esempio n. 14
0
 def test_check_string_length_noname(self):
     self.assertIsNone(utils.check_string_length(
                       'test', max_length=255))
     self.assertRaises(exception.InvalidInput,
                       utils.check_string_length,
                       11, max_length=255)
     self.assertRaises(exception.InvalidInput,
                       utils.check_string_length,
                       '', min_length=1)
     self.assertRaises(exception.InvalidInput,
                       utils.check_string_length,
                       'a' * 256, max_length=255)
Esempio n. 15
0
    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)
Esempio n. 16
0
    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)
Esempio n. 17
0
    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
        # patron objects were made.
        del agg['aggregate']['hosts']
        del agg['aggregate']['metadata']

        return agg
Esempio n. 18
0
    def _validate_input_body(self, body, entity_name):
        if not self.is_valid_body(body, entity_name):
            msg = _("the body is invalid.")
            raise patron.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 patron.exception.InvalidInput(reason=msg)
            if field == 'name':
                utils.check_string_length(value,
                                          field,
                                          min_length=1,
                                          max_length=255)
                if not common.VALID_NAME_REGEX.search(value):
                    msg = _("Invalid format for name: '%s'") % value
                    raise patron.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 patron.exception.InvalidInput(reason=msg)

        if subbody:
            msg = _("unsupported fields: %s") % subbody.keys()
            raise patron.exception.InvalidInput(reason=msg)
Esempio n. 19
0
    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
        # patron objects were made.
        del agg['aggregate']['hosts']
        del agg['aggregate']['metadata']

        return agg
Esempio n. 20
0
 def test_check_string_length_noname(self):
     self.assertIsNone(utils.check_string_length('test', max_length=255))
     self.assertRaises(exception.InvalidInput,
                       utils.check_string_length,
                       11,
                       max_length=255)
     self.assertRaises(exception.InvalidInput,
                       utils.check_string_length,
                       '',
                       min_length=1)
     self.assertRaises(exception.InvalidInput,
                       utils.check_string_length,
                       'a' * 256,
                       max_length=255)
Esempio n. 21
0
    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)
Esempio n. 22
0
    def update(self, req, id, body):
        """Update an existing agent build."""
        context = req.environ['patron.context']
        authorize(context)
        # NOTE(alex_xu): back-compatible with db layer hard-code admin
        # permission checks.
        patron_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.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 ValueError as ex:
            msg = _("Invalid request body: %s") % ex
            raise webob.exc.HTTPBadRequest(explanation=msg)
        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 after v3 API feature exposed by
        # micro-version in the future. lp bug #1333494
        return {
            "agent": {
                'agent_id': id,
                'version': version,
                'url': url,
                'md5hash': md5hash
            }
        }
Esempio n. 23
0
    def update(self, req, id, body):
        """Update an existing agent build."""
        context = req.environ['patron.context']
        authorize(context)
        # NOTE(alex_xu): back-compatible with db layer hard-code admin
        # permission checks.
        patron_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.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 ValueError as ex:
            msg = _("Invalid request body: %s") % ex
            raise webob.exc.HTTPBadRequest(explanation=msg)
        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 after v3 API feature exposed by
        # micro-version in the future. lp bug #1333494
        return {"agent": {'agent_id': id, 'version': version,
                'url': url, 'md5hash': md5hash}}
Esempio n. 24
0
    def create(self, req, body):
        """Creates a new agent build."""
        context = req.environ['patron.context']
        authorize(context)
        # NOTE(alex_xu): back-compatible with db layer hard-code admin
        # permission checks.
        patron_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}
Esempio n. 25
0
    def create(self, req, body):
        """Creates a new agent build."""
        context = req.environ['patron.context']
        authorize(context)
        # NOTE(alex_xu): back-compatible with db layer hard-code admin
        # permission checks.
        patron_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}
Esempio n. 26
0
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 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 = 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"))

    flavor = objects.Flavor(context=context.get_admin_context(), **kwargs)
    flavor.create()
    return flavor