From dc85c089702a9819fdab7c951d427de838a3dcc6 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Sat, 15 Jul 2017 18:49:57 +0100 Subject: [PATCH] [placement] fix 500 error when allocating to bad class Adjust exception handling when calling set_allocations so that a KeyError in the usage_map raises an InvalidInventory. When making allocations against a resource provider with >1 resource classes and where one of those resource classes does not have inventory on the provider, we can attempt to get info out of the usage_map that is not there, and get a KeyError. This catches the KeyError and turns it into an InvalidInventory which eventually results in a 409 response, consistent with other responses to bad allocations. Since this is fixing a 500, no microversion required. NOTE(mriedem): The functional test required some tweaks for Ocata since we didn't have the 1.7 microversion in Ocata. In addition, inventories in early days required that max_unit be set, otherwise it would default to 0 and no allocations could be made. We might wish to consider that a bug in older versions that we should fix? Change-Id: I52fa02b56f8e62dfa206a3969a99fab250508760 Closes-Bug: #1704574 (cherry picked from commit 913149249cc00f50a6219d3ddc86f3600a610c00) --- nova/objects/resource_provider.py | 8 +- .../gabbits/allocation-bad-class.yaml | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml diff --git a/nova/objects/resource_provider.py b/nova/objects/resource_provider.py index 79c9af7131f2..feebbda84944 100644 --- a/nova/objects/resource_provider.py +++ b/nova/objects/resource_provider.py @@ -1032,7 +1032,13 @@ def _check_capacity_exceeded(conn, allocs): rc_id = _RC_CACHE.id_from_string(alloc.resource_class) rp_uuid = alloc.resource_provider.uuid key = (rp_uuid, rc_id) - usage = usage_map[key] + try: + usage = usage_map[key] + except KeyError: + # The resource class at rc_id is not in the usage map. + raise exception.InvalidInventory( + resource_class=alloc.resource_class, + resource_provider=rp_uuid) amount_needed = alloc.used allocation_ratio = usage['allocation_ratio'] min_unit = usage['min_unit'] diff --git a/nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml b/nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml new file mode 100644 index 000000000000..c91884f0a41d --- /dev/null +++ b/nova/tests/functional/api/openstack/placement/gabbits/allocation-bad-class.yaml @@ -0,0 +1,75 @@ + +fixtures: + - APIFixture + +defaults: + request_headers: + x-auth-token: admin + accept: application/json + content-type: application/json + OpenStack-API-Version: placement latest + +tests: + +- name: create a resource provider + POST: /resource_providers + data: + name: an rp + status: 201 + +- name: get resource provider + GET: $LOCATION + status: 200 + +- name: create a resource class + POST: /resource_classes + request_headers: + content-type: application/json + data: + name: CUSTOM_GOLD + status: 201 + +- name: add inventory to an rp + PUT: /resource_providers/$HISTORY['get resource provider'].$RESPONSE['$.uuid']/inventories + data: + resource_provider_generation: 0 + inventories: + VCPU: + total: 24 + max_unit: 9999 + CUSTOM_GOLD: + total: 5 + max_unit: 9999 + status: 200 + +- name: allocate some of it two + desc: this is the one that used to raise a 500 + PUT: /allocations/6d9f83db-6eb5-49f6-84b0-5d03c6aa9fc8 + data: + allocations: + - resource_provider: + uuid: $HISTORY['get resource provider'].$RESPONSE['$.uuid'] + resources: + DISK_GB: 5 + CUSTOM_GOLD: 1 + status: 409 + +- name: allocate some of it custom + PUT: /allocations/6d9f83db-6eb5-49f6-84b0-5d03c6aa9fc8 + data: + allocations: + - resource_provider: + uuid: $HISTORY['get resource provider'].$RESPONSE['$.uuid'] + resources: + CUSTOM_GOLD: 1 + status: 204 + +- name: allocate some of it standard + PUT: /allocations/6d9f83db-6eb5-49f6-84b0-5d03c6aa9fc8 + data: + allocations: + - resource_provider: + uuid: $HISTORY['get resource provider'].$RESPONSE['$.uuid'] + resources: + DISK_GB: 1 + status: 409