diff --git a/osc_placement/resources/inventory.py b/osc_placement/resources/inventory.py index ddb41d2..745acfb 100644 --- a/osc_placement/resources/inventory.py +++ b/osc_placement/resources/inventory.py @@ -26,6 +26,7 @@ from osc_placement import version BASE_URL = '/resource_providers/{uuid}/inventories' PER_CLASS_URL = BASE_URL + '/{resource_class}' RP_BASE_URL = '/resource_providers' +USAGES_BASE_URL = '/resource_providers/{uuid}/usages' INVENTORY_FIELDS = { 'allocation_ratio': { 'type': float, @@ -372,7 +373,18 @@ class ShowInventory(command.ShowOne): url = PER_CLASS_URL.format(uuid=parsed_args.uuid, resource_class=parsed_args.resource_class) resource = http.request('GET', url).json() - return FIELDS, utils.get_dict_properties(resource, FIELDS) + + # TODO(stephenfin): We should just include this information in the + # above API. Alternatively, we should add an API to retrieve usage for + # a single resource class + url = USAGES_BASE_URL.format(uuid=parsed_args.uuid) + resources = http.request('GET', url).json()['usages'] + + resource['used'] = resources[parsed_args.resource_class] + + fields = FIELDS + ('used', ) + + return fields, utils.get_dict_properties(resource, fields) class ListInventory(command.Lister): @@ -401,6 +413,14 @@ class ListInventory(command.Lister): for k, v in resources['inventories'].items() ] - fields = ('resource_class', ) + FIELDS + # TODO(stephenfin): We should just include this information in the + # above API + url = USAGES_BASE_URL.format(uuid=parsed_args.uuid) + resources = http.request('GET', url).json()['usages'] + + for inventory in inventories: + inventory['used'] = resources[inventory['resource_class']] + + fields = ('resource_class', ) + FIELDS + ('used', ) rows = (utils.get_dict_properties(i, fields) for i in inventories) return fields, rows diff --git a/osc_placement/tests/functional/base.py b/osc_placement/tests/functional/base.py index 13f6f2a..b69d860 100644 --- a/osc_placement/tests/functional/base.py +++ b/osc_placement/tests/functional/base.py @@ -290,15 +290,28 @@ class BaseTestCase(base.BaseTestCase): cmd = 'resource provider allocation delete ' + consumer_uuid return self.openstack(cmd) - def resource_inventory_show(self, uuid, resource_class): - cmd = 'resource provider inventory show {uuid} {rc}'.format( - uuid=uuid, rc=resource_class + def resource_inventory_show( + self, uuid, resource_class, *, include_used=False, + ): + resource = self.openstack( + f'resource provider inventory show {uuid} {resource_class}', + use_json=True, ) - return self.openstack(cmd, use_json=True) + if not include_used: + del resource['used'] - def resource_inventory_list(self, uuid): - return self.openstack('resource provider inventory list ' + uuid, - use_json=True) + return resource + + def resource_inventory_list(self, uuid, *, include_used=False): + resources = self.openstack( + f'resource provider inventory list {uuid}', + use_json=True, + ) + if not include_used: + for resource in resources: + del resource['used'] + + return resources def resource_inventory_delete(self, uuid, resource_class=None): cmd = 'resource provider inventory delete {uuid}'.format(uuid=uuid) diff --git a/osc_placement/tests/functional/test_inventory.py b/osc_placement/tests/functional/test_inventory.py index 9693113..1f372de 100644 --- a/osc_placement/tests/functional/test_inventory.py +++ b/osc_placement/tests/functional/test_inventory.py @@ -27,17 +27,24 @@ class TestInventory(base.BaseTestCase): def test_inventory_show(self): rp_uuid = self.rp['uuid'] - expected = {'min_unit': 1, - 'max_unit': 12, - 'reserved': 0, - 'step_size': 1, - 'total': 12, - 'allocation_ratio': 16.0} + updates = { + 'min_unit': 1, + 'max_unit': 12, + 'reserved': 0, + 'step_size': 1, + 'total': 12, + 'allocation_ratio': 16.0, + } + expected = updates.copy() + expected['used'] = 0 + args = ['VCPU:%s=%s' % (k, v) for k, v in updates.items()] - args = ['VCPU:%s=%s' % (k, v) for k, v in expected.items()] self.resource_inventory_set(rp_uuid, *args) - self.assertEqual(expected, - self.resource_inventory_show(rp_uuid, 'VCPU')) + + self.assertEqual( + expected, + self.resource_inventory_show(rp_uuid, 'VCPU', include_used=True), + ) def test_inventory_show_not_found(self): rp_uuid = self.rp['uuid'] @@ -48,6 +55,27 @@ class TestInventory(base.BaseTestCase): self.assertIn('No inventory of class VCPU for {}'.format(rp_uuid), six.text_type(exc)) + def test_inventory_list(self): + rp_uuid = self.rp['uuid'] + updates = { + 'min_unit': 1, + 'max_unit': 12, + 'reserved': 0, + 'step_size': 1, + 'total': 12, + 'allocation_ratio': 16.0, + } + expected = [updates.copy()] + expected[0]['resource_class'] = 'VCPU' + expected[0]['used'] = 0 + args = ['VCPU:%s=%s' % (k, v) for k, v in updates.items()] + + self.resource_inventory_set(rp_uuid, *args) + + self.assertEqual( + expected, self.resource_inventory_list(rp_uuid, include_used=True), + ) + def test_inventory_delete(self): rp_uuid = self.rp['uuid'] diff --git a/releasenotes/notes/show-usage-in-inventory-31eb87a6d243fc5a.yaml b/releasenotes/notes/show-usage-in-inventory-31eb87a6d243fc5a.yaml new file mode 100644 index 0000000..27d4b16 --- /dev/null +++ b/releasenotes/notes/show-usage-in-inventory-31eb87a6d243fc5a.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + The ``openstack resource provider inventory list`` and ``openstack resource + provider inventory show`` commands now include a ``used`` column providing + summary usage information for the specified resource(s).