Add support for usages in the placement API

GET /resources_providers/{uuid}/usages returns a dictionary of resource
usage by resource class.

Change-Id: I3ad0d16594301635966bd9e9352bc3f1f29dab14
Partially-Implements: blueprint generic-resource-pools
This commit is contained in:
Chris Dent 2016-08-18 13:19:24 +00:00
parent 51afe54246
commit 8aa87b348c
5 changed files with 151 additions and 0 deletions

View File

@ -29,6 +29,7 @@ import webob
from nova.api.openstack.placement.handlers import inventory
from nova.api.openstack.placement.handlers import resource_provider
from nova.api.openstack.placement.handlers import root
from nova.api.openstack.placement.handlers import usage
from nova.api.openstack.placement import util
from nova import exception
@ -61,6 +62,9 @@ ROUTE_DECLARATIONS = {
'PUT': inventory.update_inventory,
'DELETE': inventory.delete_inventory
},
'/resource_providers/{uuid}/usages': {
'GET': usage.list_usages
},
}

View File

@ -0,0 +1,55 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Placement API handlers for usage information."""
from oslo_serialization import jsonutils
import webob
from nova.api.openstack.placement import util
from nova import objects
def _serialize_usages(resource_provider, usage):
usage_dict = {resource.resource_class: resource.usage
for resource in usage}
return {'resource_provider_generation': resource_provider.generation,
'usages': usage_dict}
@webob.dec.wsgify
@util.check_accept('application/json')
def list_usages(req):
"""GET a dictionary of resource provider usage by resource class.
If the resource provider does not exist return a 404.
On success return a 200 with an application/json representation of
the usage dictionary.
"""
context = req.environ['placement.context']
uuid = util.wsgi_path_item(req.environ, 'uuid')
# Resource provider object needed for two things: If it is
# NotFound we'll get a 404 here, which needs to happen because
# get_all_by_resource_provider_uuid can return an empty list.
# It is also needed for the generation, used in the outgoing
# representation.
resource_provider = objects.ResourceProvider.get_by_uuid(
context, uuid)
usage = objects.UsageList.get_all_by_resource_provider_uuid(
context, uuid)
response = req.response
response.body = jsonutils.dumps(
_serialize_usages(resource_provider, usage))
req.response.content_type = 'application/json'
return req.response

View File

@ -18,6 +18,8 @@ from oslo_utils import uuidutils
from nova.api.openstack.placement import deploy
from nova import conf
from nova import config
from nova import context
from nova import objects
from nova.tests import fixtures
@ -66,3 +68,34 @@ class APIFixture(fixture.GabbiFixture):
self.main_db_fixture.cleanup()
if self.conf:
self.conf.reset()
class AllocationFixture(APIFixture):
"""An APIFixture that has some pre-made Allocations."""
def start_fixture(self):
super(AllocationFixture, self).start_fixture()
self.context = context.get_admin_context()
# Stealing from the super
rp_name = os.environ['RP_NAME']
rp_uuid = os.environ['RP_UUID']
rp = objects.ResourceProvider(
self.context, name=rp_name, uuid=rp_uuid)
rp.create()
inventory = objects.Inventory(
self.context, resource_provider=rp,
resource_class='DISK_GB', total=2048)
inventory.obj_set_defaults()
rp.add_inventory(inventory)
allocation = objects.Allocation(
self.context, resource_provider=rp,
resource_class='DISK_GB',
consumer_id=uuidutils.generate_uuid(),
used=512)
allocation.create()
allocation = objects.Allocation(
self.context, resource_provider=rp,
resource_class='DISK_GB',
consumer_id=uuidutils.generate_uuid(),
used=512)
allocation.create()

View File

@ -0,0 +1,34 @@
# More interesting tests for usages are in with_allocations
fixtures:
- APIFixture
defaults:
request_headers:
x-auth-token: admin
tests:
- name: fail to get usages for missing provider
GET: /resource_providers/fae14fa3-4b43-498c-a33c-4a1d00edb577/usages
status: 404
- name: create provider
POST: /resource_providers
request_headers:
content-type: application/json
data:
name: a name
status: 201
- name: check provider exists
GET: $LOCATION
response_json_paths:
name: a name
- name: get empty usages
GET: $LAST_URL/usages
request_headers:
content-type: application/json
response_json_paths:
usages: {}

View File

@ -0,0 +1,25 @@
fixtures:
- AllocationFixture
defaults:
request_headers:
x-auth-token: admin
tests:
- name: confirm inventories
GET: /resource_providers/$ENVIRON['RP_UUID']/inventories
response_json_paths:
$.inventories.DISK_GB.total: 2048
$.inventories.DISK_GB.reserved: 0
- name: get usages
GET: /resource_providers/$ENVIRON['RP_UUID']/usages
response_headers:
# use a regex here because charset, which is not only not
# required but superfluous, is present
content-type: /application/json/
response_json_paths:
$.resource_provider_generation: 1
$.usages.DISK_GB: 1024