def create_resource_provider(req):
    """POST to create a resource provider.

    On success return a 201 response with an empty body
    (microversions 1.0 - 1.19) or a 200 response with a
    payload representing the newly created resource provider
    (microversions 1.20 - latest), and a location header
    pointing to the resource provider.
    """
    context = req.environ['placement.context']
    context.can(policies.CREATE)
    schema = rp_schema.POST_RESOURCE_PROVIDER_SCHEMA
    want_version = req.environ[microversion.MICROVERSION_ENVIRON]
    if want_version.matches((1, 14)):
        schema = rp_schema.POST_RP_SCHEMA_V1_14
    data = util.extract_json(req.body, schema)

    if data.get('uuid'):
        # Normalize UUID with no proper dashes into dashed one
        # with format {8}-{4}-{4}-{4}-{12}
        data['uuid'] = str(uuidlib.UUID(data['uuid']))
    else:
        data['uuid'] = uuidutils.generate_uuid()
    data["generation"] = 0

    try:
        resource_provider = rp_obj.ResourceProvider(context, **data)
        resource_provider.create()
    except db.ClientError as e:
        if "ConstraintValidationFailed" in str(e):
            if "property `uuid`" in str(e):
                duplicate = "uuid: %s" % data.get("uuid")
            else:
                duplicate = "name: %s" % data.get("name")
            raise webob.exc.HTTPConflict("Conflicting resource provider "
                    "%(duplicate)s already exists." % {'duplicate': duplicate},
                    comment=errors.DUPLICATE_NAME)
        else:
            raise webob.exc.HTTPBadRequest("Unable to create resource "
                    "provider '%(rp_uuid)s': %(error)s" %
                    {"rp_uuid": data.get("uuid"), "error": e})
    except exception.ObjectActionError as exc:
        raise webob.exc.HTTPBadRequest(
            'Unable to create resource provider "%(name)s", %(rp_uuid)s: '
            '%(error)s' %
            {'name': data['name'], 'rp_uuid': data['uuid'], 'error': exc})

    req.response.location = util.resource_provider_url(
        req.environ, resource_provider)
    if want_version.matches(min_version=(1, 20)):
        req.response.body = encodeutils.to_utf8(jsonutils.dumps(
            _serialize_provider(req.environ, resource_provider, want_version)))
        req.response.content_type = 'application/json'
        modified = util.pick_last_modified(None, resource_provider)
        req.response.last_modified = modified
        req.response.cache_control = 'no-cache'
    else:
        req.response.status = 201
        req.response.content_type = None
    return req.response
def create_resource_tree(req):
    """This method accepts a nested dict that describes a tree-like
    relationship among resource providers. Each node on the tree should contain
    the following keys:
        name: the name given to the resource. If not supplied, no name is set.
        uuid: the resource's UUID. If not supplied, one will be generated.
        resources: a dict of resources that this node provides directly. Each
            member should be of the form `resource_class: amount`
        traits: a list of traits to apply to this node.
        children: a list of nodes representing the children of this node. Each
            child node should be the same format dict as described here.

        returns: the UUID of the root of the newly-created tree
    There is no limit to the level of nesting for child resource providers.
    """
    context = req.environ["placement.context"]
    context.can(policies.UPDATE)
    schema = rp_schema.POST_RP_TREE
    want_version = req.environ[microversion.MICROVERSION_ENVIRON]
    data = util.extract_json(req.body, schema)
    root_rp = rp_obj.ResourceProvider.create_tree(context, data)
    
    response = req.response
    response.status = 200
    req.response.location = util.resource_provider_url(req.environ, root_rp)
    req.response.body = encodeutils.to_utf8(
            jsonutils.dumps(
            _serialize_provider(req.environ, root_rp, want_version)))
    req.response.content_type = "application/json"
    req.response.cache_control = "no-cache"
Exemple #3
0
 def test_resource_provider_url_prefix(self):
     # SCRIPT_NAME represents the mount point of a WSGI
     # application when it is hosted at a path/prefix.
     environ = {'SCRIPT_NAME': '/placement'}
     expected_url = ('/placement/resource_providers/%s'
                     % uuidsentinel.rp_uuid)
     self.assertEqual(expected_url, util.resource_provider_url(
         environ, self.resource_provider))
Exemple #4
0
def create_resource_provider(req):
    """POST to create a resource provider.

    On success return a 201 response with an empty body
    (microversions 1.0 - 1.19) or a 200 response with a
    payload representing the newly created resource provider
    (microversions 1.20 - latest), and a location header
    pointing to the resource provider.
    """
    context = req.environ['placement.context']
    context.can(policies.CREATE)
    schema = rp_schema.POST_RESOURCE_PROVIDER_SCHEMA
    want_version = req.environ[microversion.MICROVERSION_ENVIRON]
    if want_version.matches((1, 14)):
        schema = rp_schema.POST_RP_SCHEMA_V1_14
    data = util.extract_json(req.body, schema)

    try:
        if data.get('uuid'):
            # Normalize UUID with no proper dashes into dashed one
            # with format {8}-{4}-{4}-{4}-{12}
            data['uuid'] = str(uuidlib.UUID(data['uuid']))
        else:
            data['uuid'] = uuidutils.generate_uuid()

        resource_provider = rp_obj.ResourceProvider(context, **data)
        resource_provider.create()
    except db_exc.DBDuplicateEntry as exc:
        # Whether exc.columns has one or two entries (in the event
        # of both fields being duplicates) appears to be database
        # dependent, so going with the complete solution here.
        duplicate = ', '.join(
            ['%s: %s' % (column, data[column]) for column in exc.columns])
        raise webob.exc.HTTPConflict(
            'Conflicting resource provider %(duplicate)s already exists.' %
            {'duplicate': duplicate},
            comment=errors.DUPLICATE_NAME)
    except exception.ObjectActionError as exc:
        raise webob.exc.HTTPBadRequest(
            'Unable to create resource provider "%(name)s", %(rp_uuid)s: '
            '%(error)s' %
            {'name': data['name'], 'rp_uuid': data['uuid'], 'error': exc})

    req.response.location = util.resource_provider_url(
        req.environ, resource_provider)
    if want_version.matches(min_version=(1, 20)):
        req.response.body = encodeutils.to_utf8(jsonutils.dumps(
            _serialize_provider(req.environ, resource_provider, want_version)))
        req.response.content_type = 'application/json'
        modified = util.pick_last_modified(None, resource_provider)
        req.response.last_modified = modified
        req.response.cache_control = 'no-cache'
    else:
        req.response.status = 201
        req.response.content_type = None
    return req.response
def _serialize_links(environ, resource_provider):
    url = util.resource_provider_url(environ, resource_provider)
    links = [{'rel': 'self', 'href': url}]
    rel_types = ['inventories', 'usages']
    want_version = environ[microversion.MICROVERSION_ENVIRON]
    if want_version >= (1, 1):
        rel_types.append('aggregates')
    if want_version >= (1, 6):
        rel_types.append('traits')
    if want_version >= (1, 11):
        rel_types.append('allocations')
    for rel in rel_types:
        links.append({'rel': rel, 'href': '%s/%s' % (url, rel)})
    return links
def create_resource_provider(req):
    """POST to create a resource provider.

    On success return a 201 response with an empty body and a location
    header pointing to the newly created resource provider.
    """
    context = req.environ['placement.context']
    schema = rp_schema.POST_RESOURCE_PROVIDER_SCHEMA
    want_version = req.environ[microversion.MICROVERSION_ENVIRON]
    if want_version.matches((1, 14)):
        schema = rp_schema.POST_RP_SCHEMA_V1_14
    data = util.extract_json(req.body, schema)

    try:
        uuid = data.setdefault('uuid', uuidutils.generate_uuid())
        resource_provider = rp_obj.ResourceProvider(context, **data)
        resource_provider.create()
    except db_exc.DBDuplicateEntry as exc:
        # Whether exc.columns has one or two entries (in the event
        # of both fields being duplicates) appears to be database
        # dependent, so going with the complete solution here.
        duplicate = ', '.join(['%s: %s' % (column, data[column])
                          for column in exc.columns])
        raise webob.exc.HTTPConflict(
            _('Conflicting resource provider %(duplicate)s already exists.') %
            {'duplicate': duplicate})
    except exception.ObjectActionError as exc:
        raise webob.exc.HTTPBadRequest(
            _('Unable to create resource provider "%(name)s", %(rp_uuid)s: '
              '%(error)s') %
            {'name': data['name'], 'rp_uuid': uuid, 'error': exc})

    req.response.location = util.resource_provider_url(
        req.environ, resource_provider)
    if want_version.matches(min_version=(1, 20)):
        req.response.body = encodeutils.to_utf8(jsonutils.dumps(
            _serialize_provider(req.environ, resource_provider, want_version)))
        req.response.content_type = 'application/json'
        modified = util.pick_last_modified(None, resource_provider)
        req.response.last_modified = modified
        req.response.cache_control = 'no-cache'
    else:
        req.response.status = 201
        req.response.content_type = None
    return req.response
Exemple #7
0
 def test_resource_provider_url(self):
     environ = {}
     expected_url = '/resource_providers/%s' % uuidsentinel.rp_uuid
     self.assertEqual(
         expected_url,
         util.resource_provider_url(environ, self.resource_provider))
def create_resource_provider(req):
    """POST to create a resource provider.

    On success return a 201 response with an empty body
    (microversions 1.0 - 1.19) or a 200 response with a
    payload representing the newly created resource provider
    (microversions 1.20 - latest), and a location header
    pointing to the resource provider.
    """
    context = req.environ['placement.context']
    context.can(policies.CREATE)
    schema = rp_schema.POST_RESOURCE_PROVIDER_SCHEMA
    want_version = req.environ[microversion.MICROVERSION_ENVIRON]
    if want_version.matches((1, 14)):
        schema = rp_schema.POST_RP_SCHEMA_V1_14
    data = util.extract_json(req.body, schema)

    try:
        if data.get('uuid'):
            # Normalize UUID with no proper dashes into dashed one
            # with format {8}-{4}-{4}-{4}-{12}
            data['uuid'] = str(uuidlib.UUID(data['uuid']))
        else:
            data['uuid'] = uuidutils.generate_uuid()

        resource_provider = rp_obj.ResourceProvider(context, **data)
        resource_provider.create()
    except db_exc.DBDuplicateEntry as exc:
        # Whether exc.columns has one or two entries (in the event
        # of both fields being duplicates) appears to be database
        # dependent, so going with the complete solution here.
        duplicates = []
        for column in exc.columns:
            # For MySQL, this is error 1062:
            #
            #   Duplicate entry '%s' for key %d
            #
            # The 'key' value is captured in 'DBDuplicateEntry.columns'.
            # Despite the name, this isn't always a column name. While MySQL
            # 5.x does indeed use the name of the column, 8.x uses the name of
            # the constraint. oslo.db should probably fix this, but until that
            # happens we need to handle both cases
            if column == 'uniq_resource_providers0uuid':
                duplicates.append(f'uuid: {data["uuid"]}')
            elif column == 'uniq_resource_providers0name':
                duplicates.append(f'name: {data["name"]}')
            else:
                duplicates.append(f'{column}: {data[column]}')
        raise webob.exc.HTTPConflict(
            'Conflicting resource provider %(duplicate)s already exists.' %
            {'duplicate': ', '.join(duplicates)},
            comment=errors.DUPLICATE_NAME)
    except exception.ObjectActionError as exc:
        raise webob.exc.HTTPBadRequest(
            'Unable to create resource provider "%(name)s", %(rp_uuid)s: '
            '%(error)s' % {
                'name': data['name'],
                'rp_uuid': data['uuid'],
                'error': exc
            })

    req.response.location = util.resource_provider_url(req.environ,
                                                       resource_provider)
    if want_version.matches(min_version=(1, 20)):
        req.response.body = encodeutils.to_utf8(
            jsonutils.dumps(
                _serialize_provider(req.environ, resource_provider,
                                    want_version)))
        req.response.content_type = 'application/json'
        modified = util.pick_last_modified(None, resource_provider)
        req.response.last_modified = modified
        req.response.cache_control = 'no-cache'
    else:
        req.response.status = 201
        req.response.content_type = None
    return req.response