Merge "[placement] POST /allocations to set allocations for >1 consumers"
This commit is contained in:
commit
19ae741b0e
nova
api/openstack/placement
tests
functional/api/openstack/placement
unit/api/openstack/placement
placement-api-ref/source
releasenotes/notes
@ -100,9 +100,12 @@ ROUTE_DECLARATIONS = {
|
||||
'/resource_providers/{uuid}/allocations': {
|
||||
'GET': allocation.list_for_resource_provider,
|
||||
},
|
||||
'/allocations': {
|
||||
'POST': allocation.set_allocations,
|
||||
},
|
||||
'/allocations/{consumer_uuid}': {
|
||||
'GET': allocation.list_for_consumer,
|
||||
'PUT': allocation.set_allocations,
|
||||
'PUT': allocation.set_allocations_for_consumer,
|
||||
'DELETE': allocation.delete_allocations,
|
||||
},
|
||||
'/allocation_candidates': {
|
||||
|
@ -138,6 +138,24 @@ ALLOCATION_SCHEMA_V1_12 = {
|
||||
}
|
||||
|
||||
|
||||
# POST to /allocations, added in microversion 1.13, uses the
|
||||
# POST_ALLOCATIONS_V1_13 schema to allow multiple allocations
|
||||
# from multiple consumers in one request. It is a dict, keyed by
|
||||
# consumer uuid, using the form of PUT allocations from microversion
|
||||
# 1.12. In POST the allocations can be empty, so DELETABLE_ALLOCATIONS
|
||||
# modifies ALLOCATION_SCHEMA_V1_12 accordingly.
|
||||
DELETABLE_ALLOCATIONS = copy.deepcopy(ALLOCATION_SCHEMA_V1_12)
|
||||
DELETABLE_ALLOCATIONS['properties']['allocations']['minProperties'] = 0
|
||||
POST_ALLOCATIONS_V1_13 = {
|
||||
"type": "object",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": False,
|
||||
"patternProperties": {
|
||||
"^[0-9a-fA-F-]{36}$": DELETABLE_ALLOCATIONS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def _allocations_dict(allocations, key_fetcher, resource_provider=None,
|
||||
want_version=None):
|
||||
"""Turn allocations into a dict of resources keyed by key_fetcher."""
|
||||
@ -277,7 +295,42 @@ def list_for_resource_provider(req):
|
||||
return req.response
|
||||
|
||||
|
||||
def _set_allocations(req, schema):
|
||||
def _new_allocations(context, resource_provider_uuid, consumer_uuid,
|
||||
resources, project_id, user_id):
|
||||
"""Create new allocation objects for a set of resources
|
||||
|
||||
Returns a list of Allocation objects.
|
||||
|
||||
:param context: The placement context.
|
||||
:param resource_provider_uuid: The uuid of the resource provider that
|
||||
has the resources.
|
||||
:param consumer_uuid: The uuid of the consumer of the resources.
|
||||
:param resources: A dict of resource classes and values.
|
||||
:param project_id: The project consuming the resources.
|
||||
:param user_id: The user consuming the resources.
|
||||
"""
|
||||
allocations = []
|
||||
try:
|
||||
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
||||
context, resource_provider_uuid)
|
||||
except exception.NotFound:
|
||||
raise webob.exc.HTTPBadRequest(
|
||||
_("Allocation for resource provider '%(rp_uuid)s' "
|
||||
"that does not exist.") %
|
||||
{'rp_uuid': resource_provider_uuid})
|
||||
for resource_class in resources:
|
||||
allocation = rp_obj.Allocation(
|
||||
resource_provider=resource_provider,
|
||||
consumer_id=consumer_uuid,
|
||||
resource_class=resource_class,
|
||||
project_id=project_id,
|
||||
user_id=user_id,
|
||||
used=resources[resource_class])
|
||||
allocations.append(allocation)
|
||||
return allocations
|
||||
|
||||
|
||||
def _set_allocations_for_consumer(req, schema):
|
||||
context = req.environ['placement.context']
|
||||
consumer_uuid = util.wsgi_path_item(req.environ, 'consumer_uuid')
|
||||
data = util.extract_json(req.body, schema)
|
||||
@ -299,25 +352,13 @@ def _set_allocations(req, schema):
|
||||
# that does not exist, raise a 400.
|
||||
allocation_objects = []
|
||||
for resource_provider_uuid, allocation in allocation_data.items():
|
||||
try:
|
||||
resource_provider = rp_obj.ResourceProvider.get_by_uuid(
|
||||
context, resource_provider_uuid)
|
||||
except exception.NotFound:
|
||||
raise webob.exc.HTTPBadRequest(
|
||||
_("Allocation for resource provider '%(rp_uuid)s' "
|
||||
"that does not exist.") %
|
||||
{'rp_uuid': resource_provider_uuid})
|
||||
|
||||
resources = allocation['resources']
|
||||
for resource_class in resources:
|
||||
allocation = rp_obj.Allocation(
|
||||
resource_provider=resource_provider,
|
||||
consumer_id=consumer_uuid,
|
||||
resource_class=resource_class,
|
||||
project_id=data.get('project_id'),
|
||||
user_id=data.get('user_id'),
|
||||
used=resources[resource_class])
|
||||
allocation_objects.append(allocation)
|
||||
new_allocations = _new_allocations(context,
|
||||
resource_provider_uuid,
|
||||
consumer_uuid,
|
||||
allocation['resources'],
|
||||
data.get('project_id'),
|
||||
data.get('user_id'))
|
||||
allocation_objects.extend(new_allocations)
|
||||
|
||||
allocations = rp_obj.AllocationList(
|
||||
context, objects=allocation_objects)
|
||||
@ -349,22 +390,84 @@ def _set_allocations(req, schema):
|
||||
@wsgi_wrapper.PlacementWsgify
|
||||
@microversion.version_handler('1.0', '1.7')
|
||||
@util.require_content('application/json')
|
||||
def set_allocations(req):
|
||||
return _set_allocations(req, ALLOCATION_SCHEMA)
|
||||
def set_allocations_for_consumer(req):
|
||||
return _set_allocations_for_consumer(req, ALLOCATION_SCHEMA)
|
||||
|
||||
|
||||
@wsgi_wrapper.PlacementWsgify # noqa
|
||||
@microversion.version_handler('1.8', '1.11')
|
||||
@util.require_content('application/json')
|
||||
def set_allocations(req):
|
||||
return _set_allocations(req, ALLOCATION_SCHEMA_V1_8)
|
||||
def set_allocations_for_consumer(req):
|
||||
return _set_allocations_for_consumer(req, ALLOCATION_SCHEMA_V1_8)
|
||||
|
||||
|
||||
@wsgi_wrapper.PlacementWsgify # noqa
|
||||
@microversion.version_handler('1.12')
|
||||
@util.require_content('application/json')
|
||||
def set_allocations_for_consumer(req):
|
||||
return _set_allocations_for_consumer(req, ALLOCATION_SCHEMA_V1_12)
|
||||
|
||||
|
||||
@wsgi_wrapper.PlacementWsgify
|
||||
@microversion.version_handler('1.13')
|
||||
@util.require_content('application/json')
|
||||
def set_allocations(req):
|
||||
return _set_allocations(req, ALLOCATION_SCHEMA_V1_12)
|
||||
context = req.environ['placement.context']
|
||||
data = util.extract_json(req.body, POST_ALLOCATIONS_V1_13)
|
||||
|
||||
# Create a sequence of allocation objects to be used in an
|
||||
# AllocationList.create_all() call, which will mean all the changes
|
||||
# happen within a single transaction and with resource provider
|
||||
# generations check all in one go.
|
||||
allocation_objects = []
|
||||
|
||||
for consumer_uuid in data:
|
||||
project_id = data[consumer_uuid]['project_id']
|
||||
user_id = data[consumer_uuid]['user_id']
|
||||
allocations = data[consumer_uuid]['allocations']
|
||||
if allocations:
|
||||
for resource_provider_uuid in allocations:
|
||||
resources = allocations[resource_provider_uuid]['resources']
|
||||
new_allocations = _new_allocations(context,
|
||||
resource_provider_uuid,
|
||||
consumer_uuid,
|
||||
resources,
|
||||
project_id,
|
||||
user_id)
|
||||
allocation_objects.extend(new_allocations)
|
||||
else:
|
||||
# The allocations are empty, which means wipe them out.
|
||||
# Internal to the allocation object this is signalled by a
|
||||
# used value of 0.
|
||||
allocations = rp_obj.AllocationList.get_all_by_consumer_id(
|
||||
context, consumer_uuid)
|
||||
for allocation in allocations:
|
||||
allocation.used = 0
|
||||
allocation_objects.append(allocation)
|
||||
|
||||
allocations = rp_obj.AllocationList(
|
||||
context, objects=allocation_objects)
|
||||
|
||||
try:
|
||||
allocations.create_all()
|
||||
LOG.debug("Successfully wrote allocations %s", allocations)
|
||||
except exception.NotFound as exc:
|
||||
raise webob.exc.HTTPBadRequest(
|
||||
_("Unable to allocate inventory %(error)s") % {'error': exc})
|
||||
except exception.InvalidInventory as exc:
|
||||
# InvalidInventory is a parent for several exceptions that
|
||||
# indicate either that Inventory is not present, or that
|
||||
# capacity limits have been exceeded.
|
||||
raise webob.exc.HTTPConflict(
|
||||
_('Unable to allocate inventory: %(error)s') % {'error': exc})
|
||||
except exception.ConcurrentUpdateDetected as exc:
|
||||
raise webob.exc.HTTPConflict(
|
||||
_('Inventory changed while attempting to allocate: %(error)s') %
|
||||
{'error': exc})
|
||||
|
||||
req.response.status = 204
|
||||
req.response.content_type = None
|
||||
return req.response
|
||||
|
||||
|
||||
@wsgi_wrapper.PlacementWsgify
|
||||
|
@ -52,6 +52,7 @@ VERSIONS = [
|
||||
'1.12', # Add project_id and user_id to GET /allocations/{consumer_uuid}
|
||||
# and PUT to /allocations/{consumer_uuid} in the same dict form
|
||||
# as GET
|
||||
'1.13', # Adds POST /allocations to set allocations for multiple consumers
|
||||
]
|
||||
|
||||
|
||||
|
@ -172,3 +172,9 @@ response body. Because the `PUT` request requires `user_id` and
|
||||
response. In addition, the response body for ``GET /allocation_candidates``
|
||||
is updated so the allocations in the ``alocation_requests`` object work
|
||||
with the new `PUT` format.
|
||||
|
||||
1.13 POST multiple allocations to /allocations
|
||||
----------------------------------------------
|
||||
|
||||
Version 1.13 gives the ability to set or clear allocations for more than
|
||||
one consumer uuid with a request to ``POST /allocations``.
|
||||
|
@ -80,6 +80,11 @@ class APIFixture(fixture.GabbiFixture):
|
||||
os.environ['CUSTOM_RES_CLASS'] = 'CUSTOM_IRON_NFV'
|
||||
os.environ['PROJECT_ID'] = uuidutils.generate_uuid()
|
||||
os.environ['USER_ID'] = uuidutils.generate_uuid()
|
||||
os.environ['PROJECT_ID_ALT'] = uuidutils.generate_uuid()
|
||||
os.environ['USER_ID_ALT'] = uuidutils.generate_uuid()
|
||||
os.environ['INSTANCE_UUID'] = uuidutils.generate_uuid()
|
||||
os.environ['MIGRATION_UUID'] = uuidutils.generate_uuid()
|
||||
os.environ['CONSUMER_UUID'] = uuidutils.generate_uuid()
|
||||
|
||||
def stop_fixture(self):
|
||||
self.api_db_fixture.cleanup()
|
||||
|
@ -0,0 +1,288 @@
|
||||
# Test that it possible to POST multiple allocations to /allocations to
|
||||
# simultaneously make changes, including removing resources for a consumer if
|
||||
# the allocations are empty.
|
||||
|
||||
fixtures:
|
||||
- APIFixture
|
||||
|
||||
defaults:
|
||||
request_headers:
|
||||
x-auth-token: admin
|
||||
accept: application/json
|
||||
content-type: application/json
|
||||
openstack-api-version: placement 1.13
|
||||
|
||||
tests:
|
||||
|
||||
- name: create compute one
|
||||
POST: /resource_providers
|
||||
data:
|
||||
name: compute01
|
||||
status: 201
|
||||
|
||||
- name: rp compute01
|
||||
desc: provide a reference for later reuse
|
||||
GET: $LOCATION
|
||||
|
||||
- name: create compute two
|
||||
POST: /resource_providers
|
||||
data:
|
||||
name: compute02
|
||||
status: 201
|
||||
|
||||
- name: rp compute02
|
||||
desc: provide a reference for later reuse
|
||||
GET: $LOCATION
|
||||
|
||||
- name: create shared disk
|
||||
POST: /resource_providers
|
||||
data:
|
||||
name: storage01
|
||||
status: 201
|
||||
|
||||
- name: rp storage01
|
||||
desc: provide a reference for later reuse
|
||||
GET: $LOCATION
|
||||
|
||||
- name: inventory compute01
|
||||
PUT: $HISTORY['rp compute01'].$RESPONSE['links[?rel = "inventories"].href']
|
||||
data:
|
||||
resource_provider_generation: 0
|
||||
inventories:
|
||||
VCPU:
|
||||
total: 16
|
||||
MEMORY_MB:
|
||||
total: 2048
|
||||
|
||||
- name: inventory compute02
|
||||
PUT: $HISTORY['rp compute02'].$RESPONSE['links[?rel = "inventories"].href']
|
||||
data:
|
||||
resource_provider_generation: 0
|
||||
inventories:
|
||||
VCPU:
|
||||
total: 16
|
||||
MEMORY_MB:
|
||||
total: 2048
|
||||
|
||||
- name: inventory storage01
|
||||
PUT: $HISTORY['rp storage01'].$RESPONSE['links[?rel = "inventories"].href']
|
||||
data:
|
||||
resource_provider_generation: 0
|
||||
inventories:
|
||||
DISK_GB:
|
||||
total: 4096
|
||||
|
||||
- name: confirm only POST
|
||||
GET: /allocations
|
||||
status: 405
|
||||
response_headers:
|
||||
allow: POST
|
||||
|
||||
- name: 404 on older 1.12 microversion post
|
||||
POST: /allocations
|
||||
request_headers:
|
||||
openstack-api-version: placement 1.12
|
||||
status: 404
|
||||
|
||||
- name: post allocations two consumers
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute02'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
$HISTORY['rp storage01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
DISK_GB: 5
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
$ENVIRON['MIGRATION_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
status: 204
|
||||
|
||||
- name: confirm usages
|
||||
GET: /usages?project_id=$ENVIRON['PROJECT_ID']
|
||||
response_json_paths:
|
||||
$.usages.DISK_GB: 5
|
||||
$.usages.VCPU: 4
|
||||
$.usages.MEMORY_MB: 2048
|
||||
|
||||
- name: clear and set allocations
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute02'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
$HISTORY['rp storage01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
DISK_GB: 5
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
$ENVIRON['MIGRATION_UUID']:
|
||||
allocations: {}
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
status: 204
|
||||
|
||||
- name: confirm usages after clear
|
||||
GET: /usages?project_id=$ENVIRON['PROJECT_ID']
|
||||
response_json_paths:
|
||||
$.usages.DISK_GB: 5
|
||||
$.usages.VCPU: 2
|
||||
$.usages.MEMORY_MB: 1024
|
||||
|
||||
- name: post allocations two users
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute02'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
$HISTORY['rp storage01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
DISK_GB: 5
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
# We must use a fresh consumer id with the alternate project id info.
|
||||
# A previously seen consumer id will be assumed to always have the same
|
||||
# project and user.
|
||||
$ENVIRON['CONSUMER_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
project_id: $ENVIRON['PROJECT_ID_ALT']
|
||||
user_id: $ENVIRON['USER_ID_ALT']
|
||||
status: 204
|
||||
|
||||
- name: confirm usages user a
|
||||
GET: /usages?project_id=$ENVIRON['PROJECT_ID']
|
||||
response_json_paths:
|
||||
$.usages.`len`: 3
|
||||
$.usages.DISK_GB: 5
|
||||
$.usages.VCPU: 2
|
||||
$.usages.MEMORY_MB: 1024
|
||||
|
||||
- name: confirm usages user b
|
||||
GET: /usages?project_id=$ENVIRON['PROJECT_ID_ALT']
|
||||
response_json_paths:
|
||||
$.usages.`len`: 2
|
||||
$.usages.VCPU: 2
|
||||
$.usages.MEMORY_MB: 1024
|
||||
|
||||
- name: fail allocations over capacity
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute02'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
$HISTORY['rp storage01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
DISK_GB: 5
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
$ENVIRON['CONSUMER_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 2049
|
||||
VCPU: 2
|
||||
project_id: $ENVIRON['PROJECT_ID_ALT']
|
||||
user_id: $ENVIRON['USER_ID_ALT']
|
||||
status: 409
|
||||
response_strings:
|
||||
- The requested amount would exceed the capacity
|
||||
|
||||
- name: fail allocations deep schema violate
|
||||
desc: no schema yet
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute02'].$RESPONSE['uuid']:
|
||||
cow: moo
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
status: 400
|
||||
|
||||
- name: fail allocations shallow schema violate
|
||||
desc: no schema yet
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
cow: moo
|
||||
status: 400
|
||||
|
||||
- name: fail resource provider not exist
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
# this rp does not exist
|
||||
'c42def7b-498b-4442-9502-c7970b14bea4':
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
$HISTORY['rp storage01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
DISK_GB: 5
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
status: 400
|
||||
response_strings:
|
||||
- that does not exist
|
||||
|
||||
- name: fail resource class not in inventory
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute02'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
PCI_DEVICE: 1
|
||||
$HISTORY['rp storage01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
DISK_GB: 5
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
status: 409
|
||||
response_strings:
|
||||
- "Inventory for 'PCI_DEVICE' on"
|
||||
|
||||
- name: fail resource class not exist
|
||||
POST: /allocations
|
||||
data:
|
||||
$ENVIRON['INSTANCE_UUID']:
|
||||
allocations:
|
||||
$HISTORY['rp compute02'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
MEMORY_MB: 1024
|
||||
VCPU: 2
|
||||
CUSTOM_PONY: 1
|
||||
$HISTORY['rp storage01'].$RESPONSE['uuid']:
|
||||
resources:
|
||||
DISK_GB: 5
|
||||
project_id: $ENVIRON['PROJECT_ID']
|
||||
user_id: $ENVIRON['USER_ID']
|
||||
status: 400
|
||||
response_strings:
|
||||
- No such resource class CUSTOM_PONY
|
@ -14,11 +14,11 @@ defaults:
|
||||
|
||||
tests:
|
||||
|
||||
- name: get allocations no consumer is 404
|
||||
- name: get allocations no consumer is 405
|
||||
GET: /allocations
|
||||
status: 404
|
||||
status: 405
|
||||
response_json_paths:
|
||||
$.errors[0].title: Not Found
|
||||
$.errors[0].title: Method Not Allowed
|
||||
|
||||
- name: get allocations is empty dict
|
||||
GET: /allocations/599ffd2d-526a-4b2e-8683-f13ad25f9958
|
||||
|
@ -39,13 +39,13 @@ tests:
|
||||
response_json_paths:
|
||||
$.errors[0].title: Not Acceptable
|
||||
|
||||
- name: latest microversion is 1.12
|
||||
- name: latest microversion is 1.13
|
||||
GET: /
|
||||
request_headers:
|
||||
openstack-api-version: placement latest
|
||||
response_headers:
|
||||
vary: /OpenStack-API-Version/
|
||||
openstack-api-version: placement 1.12
|
||||
openstack-api-version: placement 1.13
|
||||
|
||||
- name: other accept header bad version
|
||||
GET: /
|
||||
|
@ -74,7 +74,7 @@ class TestMicroversionIntersection(test.NoDBTestCase):
|
||||
# if you add two different versions of method 'foobar' the
|
||||
# number only goes up by one if no other version foobar yet
|
||||
# exists. This operates as a simple sanity check.
|
||||
TOTAL_VERSIONED_METHODS = 15
|
||||
TOTAL_VERSIONED_METHODS = 16
|
||||
|
||||
def test_methods_versioned(self):
|
||||
methods_data = microversion.VERSIONED_METHODS
|
||||
|
@ -7,6 +7,51 @@ and used by some consumer of that resource. They indicate the amount
|
||||
of a particular resource that has been allocated to a given consumer
|
||||
of that resource from a particular resource provider.
|
||||
|
||||
Manage allocations
|
||||
==================
|
||||
|
||||
Create, update or delete allocations for multiple consumers in a single
|
||||
request. This allows a client to atomically set or swap allocations for
|
||||
multiple consumers as may be required during a migration or move type
|
||||
operation.
|
||||
|
||||
The allocations for an individual consumer uuid mentioned in the request
|
||||
can be removed by setting the `allocations` to an empty object (see the
|
||||
example below).
|
||||
|
||||
**Available as of microversion 1.13.**
|
||||
|
||||
.. rest_method:: POST /allocations
|
||||
|
||||
Normal response codes: 204
|
||||
|
||||
Error response codes: badRequest(400), conflict(409)
|
||||
|
||||
* `409 Conflict` if there is no available inventory in any of the
|
||||
resource providers for any specified resource classes or inventories
|
||||
are updated by another thread while attempting the operation.
|
||||
|
||||
Request
|
||||
-------
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
- consumer_uuid: consumer_uuid_body
|
||||
- project_id: project_id_body
|
||||
- user_id: user_id_body
|
||||
- allocations: allocations_dict_empty
|
||||
- resources: resources
|
||||
|
||||
Request Example
|
||||
|
||||
.. literalinclude:: manage-allocations-request.json
|
||||
:language: javascript
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
No body content is returned after a successful request
|
||||
|
||||
List allocations
|
||||
================
|
||||
|
||||
|
31
placement-api-ref/source/manage-allocations-request.json
Normal file
31
placement-api-ref/source/manage-allocations-request.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"30328d13-e299-4a93-a102-61e4ccabe474": {
|
||||
"project_id": "131d4efb-abc0-4872-9b92-8c8b9dc4320f",
|
||||
"user_id": "131d4efb-abc0-4872-9b92-8c8b9dc4320f",
|
||||
"allocations": {
|
||||
"e10927c4-8bc9-465d-ac60-d2f79f7e4a00": {
|
||||
"resources": {
|
||||
"VCPU": 2,
|
||||
"MEMORY_MB": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"71921e4e-1629-4c5b-bf8d-338d915d2ef3": {
|
||||
"project_id": "131d4efb-abc0-4872-9b92-8c8b9dc4320f",
|
||||
"user_id": "131d4efb-abc0-4872-9b92-8c8b9dc4320f",
|
||||
"allocations": {}
|
||||
},
|
||||
"48c1d40f-45d8-4947-8d46-52b4e1326df8": {
|
||||
"project_id": "131d4efb-abc0-4872-9b92-8c8b9dc4320f",
|
||||
"user_id": "131d4efb-abc0-4872-9b92-8c8b9dc4320f",
|
||||
"allocations": {
|
||||
"e10927c4-8bc9-465d-ac60-d2f79f7e4a00": {
|
||||
"resources": {
|
||||
"VCPU": 4,
|
||||
"MEMORY_MB": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
# variables in path
|
||||
consumer_uuid:
|
||||
consumer_uuid: &consumer_uuid
|
||||
type: string
|
||||
in: path
|
||||
required: true
|
||||
@ -147,19 +147,29 @@ allocations_by_resource_provider:
|
||||
required: true
|
||||
description: >
|
||||
A dictionary of allocations keyed by resource provider uuid.
|
||||
allocations_dict:
|
||||
allocations_dict: &allocations_dict
|
||||
type: object
|
||||
in: body
|
||||
required: true
|
||||
min_version: 1.12
|
||||
description: >
|
||||
A dictionary of resource allocations keyed by resource provider uuid.
|
||||
allocations_dict_empty:
|
||||
<<: *allocations_dict
|
||||
description: >
|
||||
A dictionary of resource allocations keyed by resource provider uuid.
|
||||
If this is an empty object, allocations for this consumer will be
|
||||
removed.
|
||||
min_version: null
|
||||
capacity:
|
||||
type: integer
|
||||
in: body
|
||||
required: true
|
||||
description: >
|
||||
The amount of the resource that the provider can accommodate.
|
||||
consumer_uuid_body:
|
||||
<<: *consumer_uuid
|
||||
in: body
|
||||
inventories:
|
||||
type: object
|
||||
in: body
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Microversion 1.13 of the Placement API gives the ability to set or clear
|
||||
allocations for more than one consumer uuid with a request to
|
||||
``POST /allocations``.
|
Loading…
x
Reference in New Issue
Block a user