Merge "[placement] make PUT inventory consistent with GET"

This commit is contained in:
Jenkins 2016-09-13 00:07:07 +00:00 committed by Gerrit Code Review
commit 09870549c9
3 changed files with 35 additions and 24 deletions

View File

@ -22,7 +22,7 @@ from nova.api.openstack.placement import util
from nova import exception from nova import exception
from nova import objects from nova import objects
RESOURCE_CLASS_IDENTIFIER = "^[A-Z0-9_]+$"
BASE_INVENTORY_SCHEMA = { BASE_INVENTORY_SCHEMA = {
"type": "object", "type": "object",
"properties": { "properties": {
@ -57,10 +57,12 @@ BASE_INVENTORY_SCHEMA = {
POST_INVENTORY_SCHEMA = copy.deepcopy(BASE_INVENTORY_SCHEMA) POST_INVENTORY_SCHEMA = copy.deepcopy(BASE_INVENTORY_SCHEMA)
POST_INVENTORY_SCHEMA['properties']['resource_class'] = { POST_INVENTORY_SCHEMA['properties']['resource_class'] = {
"type": "string", "type": "string",
"pattern": "^[A-Z0-9_]+$" "pattern": RESOURCE_CLASS_IDENTIFIER,
} }
POST_INVENTORY_SCHEMA['required'].append('resource_class') POST_INVENTORY_SCHEMA['required'].append('resource_class')
POST_INVENTORY_SCHEMA['required'].remove('resource_provider_generation') POST_INVENTORY_SCHEMA['required'].remove('resource_provider_generation')
PUT_INVENTORY_RECORD_SCHEMA = copy.deepcopy(BASE_INVENTORY_SCHEMA)
PUT_INVENTORY_RECORD_SCHEMA['required'].remove('resource_provider_generation')
PUT_INVENTORY_SCHEMA = { PUT_INVENTORY_SCHEMA = {
"type": "object", "type": "object",
"properties": { "properties": {
@ -68,8 +70,10 @@ PUT_INVENTORY_SCHEMA = {
"type": "integer" "type": "integer"
}, },
"inventories": { "inventories": {
"type": "array", "type": "object",
"items": POST_INVENTORY_SCHEMA "patternProperties": {
RESOURCE_CLASS_IDENTIFIER: PUT_INVENTORY_RECORD_SCHEMA,
}
} }
}, },
"required": [ "required": [
@ -130,17 +134,17 @@ def _extract_inventories(body, schema):
"""Extract and validate multiple inventories from JSON body.""" """Extract and validate multiple inventories from JSON body."""
data = _extract_json(body, schema) data = _extract_json(body, schema)
inventories = [] inventories = {}
for raw_inventory in data['inventories']: for res_class, raw_inventory in data['inventories'].items():
inventory_data = copy.copy(INVENTORY_DEFAULTS) inventory_data = copy.copy(INVENTORY_DEFAULTS)
inventory_data.update(raw_inventory) inventory_data.update(raw_inventory)
inventories.append(inventory_data) inventories[res_class] = inventory_data
data['inventories'] = inventories data['inventories'] = inventories
return data return data
def _make_inventory_object(resource_provider, **data): def _make_inventory_object(resource_provider, resource_class, **data):
"""Single place to catch malformed Inventories.""" """Single place to catch malformed Inventories."""
# TODO(cdent): Some of the validation checks that are done here # TODO(cdent): Some of the validation checks that are done here
# could be done via JSONschema (using, for example, "minimum": # could be done via JSONschema (using, for example, "minimum":
@ -148,11 +152,12 @@ def _make_inventory_object(resource_provider, **data):
# duplication or decoupling so leaving it as this for now. # duplication or decoupling so leaving it as this for now.
try: try:
inventory = objects.Inventory( inventory = objects.Inventory(
resource_provider=resource_provider, **data) resource_provider=resource_provider,
resource_class=resource_class, **data)
except (ValueError, TypeError) as exc: except (ValueError, TypeError) as exc:
raise webob.exc.HTTPBadRequest( raise webob.exc.HTTPBadRequest(
'Bad inventory %s for resource provider %s: %s' 'Bad inventory %s for resource provider %s: %s'
% (data['resource_class'], resource_provider.uuid, exc), % (resource_class, resource_provider.uuid, exc),
json_formatter=util.json_error_formatter) json_formatter=util.json_error_formatter)
return inventory return inventory
@ -210,8 +215,11 @@ def create_inventory(req):
resource_provider = objects.ResourceProvider.get_by_uuid( resource_provider = objects.ResourceProvider.get_by_uuid(
context, uuid) context, uuid)
data = _extract_inventory(req.body, POST_INVENTORY_SCHEMA) data = _extract_inventory(req.body, POST_INVENTORY_SCHEMA)
resource_class = data.pop('resource_class')
inventory = _make_inventory_object(resource_provider, **data) inventory = _make_inventory_object(resource_provider,
resource_class,
**data)
try: try:
resource_provider.add_inventory(inventory) resource_provider.add_inventory(inventory)
@ -228,7 +236,7 @@ def create_inventory(req):
response = req.response response = req.response
response.location = util.inventory_url( response.location = util.inventory_url(
req.environ, resource_provider, data['resource_class']) req.environ, resource_provider, resource_class)
return _send_inventory(response, resource_provider, inventory, return _send_inventory(response, resource_provider, inventory,
status=201) status=201)
@ -335,9 +343,9 @@ def set_inventories(req):
json_formatter=util.json_error_formatter) json_formatter=util.json_error_formatter)
inv_list = [] inv_list = []
for inventory_data in data['inventories']: for res_class, inventory_data in data['inventories'].items():
inventory = _make_inventory_object( inventory = _make_inventory_object(
resource_provider, **inventory_data) resource_provider, res_class, **inventory_data)
inv_list.append(inventory) inv_list.append(inventory)
inventories = objects.InventoryList(objects=inv_list) inventories = objects.InventoryList(objects=inv_list)
@ -383,8 +391,9 @@ def update_inventory(req):
'resource provider generation conflict', 'resource provider generation conflict',
json_formatter=util.json_error_formatter) json_formatter=util.json_error_formatter)
data['resource_class'] = resource_class inventory = _make_inventory_object(resource_provider,
inventory = _make_inventory_object(resource_provider, **data) resource_class,
**data)
try: try:
resource_provider.update_inventory(inventory) resource_provider.update_inventory(inventory)

View File

@ -266,9 +266,9 @@ tests:
# of other changes # of other changes
resource_provider_generation: 0 resource_provider_generation: 0
inventories: inventories:
- resource_class: VCPU VCPU:
total: 32 total: 32
- resource_class: DISK_GB DISK_GB:
total: 10 total: 10
- name: set inventory on rp2 - name: set inventory on rp2
@ -280,9 +280,9 @@ tests:
# of other changes # of other changes
resource_provider_generation: 0 resource_provider_generation: 0
inventories: inventories:
- resource_class: VCPU VCPU:
total: 16 total: 16
- resource_class: DISK_GB DISK_GB:
total: 20 total: 20
status: 200 status: 200

View File

@ -160,6 +160,8 @@ tests:
resource_class: NO_CLASS_14 resource_class: NO_CLASS_14
total: 2048 total: 2048
status: 400 status: 400
response_strings:
- Bad inventory NO_CLASS_14 for resource provider $ENVIRON['RP_UUID']
- name: post inventory duplicated resource class - name: post inventory duplicated resource class
desc: DISK_GB was already created above desc: DISK_GB was already created above
@ -258,9 +260,9 @@ tests:
data: data:
resource_provider_generation: 0 resource_provider_generation: 0
inventories: inventories:
- resource_class: IPV4_ADDRESS IPV4_ADDRESS:
total: 253 total: 253
- resource_class: DISK_GB DISK_GB:
total: 1024 total: 1024
status: 200 status: 200
response_json_paths: response_json_paths:
@ -287,7 +289,7 @@ tests:
data: data:
resource_provider_generation: 99 resource_provider_generation: 99
inventories: inventories:
- resource_class: IPV4_ADDRESS IPV4_ADDRESS:
total: 253 total: 253
status: 409 status: 409
response_strings: response_strings:
@ -302,7 +304,7 @@ tests:
data: data:
resource_provider_generation: 6 resource_provider_generation: 6
inventories: inventories:
- resource_class: IPV4_ADDRESS IPV4_ADDRESS:
total: 253 total: 253
reserved: 512 reserved: 512
status: 400 status: 400