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:
parent
9d61e0f1ed
commit
b0787f57a2
@ -29,6 +29,7 @@ import webob
|
|||||||
from nova.api.openstack.placement.handlers import inventory
|
from nova.api.openstack.placement.handlers import inventory
|
||||||
from nova.api.openstack.placement.handlers import resource_provider
|
from nova.api.openstack.placement.handlers import resource_provider
|
||||||
from nova.api.openstack.placement.handlers import root
|
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.api.openstack.placement import util
|
||||||
from nova import exception
|
from nova import exception
|
||||||
|
|
||||||
@ -61,6 +62,9 @@ ROUTE_DECLARATIONS = {
|
|||||||
'PUT': inventory.update_inventory,
|
'PUT': inventory.update_inventory,
|
||||||
'DELETE': inventory.delete_inventory
|
'DELETE': inventory.delete_inventory
|
||||||
},
|
},
|
||||||
|
'/resource_providers/{uuid}/usages': {
|
||||||
|
'GET': usage.list_usages
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
55
nova/api/openstack/placement/handlers/usage.py
Normal file
55
nova/api/openstack/placement/handlers/usage.py
Normal 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
|
@ -18,6 +18,8 @@ from oslo_utils import uuidutils
|
|||||||
from nova.api.openstack.placement import deploy
|
from nova.api.openstack.placement import deploy
|
||||||
from nova import conf
|
from nova import conf
|
||||||
from nova import config
|
from nova import config
|
||||||
|
from nova import context
|
||||||
|
from nova import objects
|
||||||
from nova.tests import fixtures
|
from nova.tests import fixtures
|
||||||
|
|
||||||
|
|
||||||
@ -66,3 +68,34 @@ class APIFixture(fixture.GabbiFixture):
|
|||||||
self.main_db_fixture.cleanup()
|
self.main_db_fixture.cleanup()
|
||||||
if self.conf:
|
if self.conf:
|
||||||
self.conf.reset()
|
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()
|
||||||
|
@ -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: {}
|
@ -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
|
Loading…
Reference in New Issue
Block a user