From dee5bffb286f4bbc403b22d1185dd552a7074545 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 17 Jul 2019 16:35:19 +0100 Subject: [PATCH] Include usage in 'inventory list', 'inventory show' The 'resource provider inventory list' and 'resource provider inventory show' commands describe everything about some given inventory *except* their usage, which is a pretty important metric in quickly assessing availability of a given resource. Instead, usage is hidden behind the 'resource provider usage show' command. There doesn't appear to be any reason for this to the case, aside from wanting to directly map to the placement API which shouldn't be a goal. Make these commands more friendly by including usage information. We may want to consider deprecating the 'resource provider usage show' command in the future, but that's left for another day. Change-Id: Iafedac3ff7a5ae60e6027741c44904babf64d3f1 Signed-off-by: Stephen Finucane --- osc_placement/resources/inventory.py | 24 +++++++++- osc_placement/tests/functional/base.py | 27 ++++++++--- .../tests/functional/test_inventory.py | 46 +++++++++++++++---- ...w-usage-in-inventory-31eb87a6d243fc5a.yaml | 6 +++ 4 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 releasenotes/notes/show-usage-in-inventory-31eb87a6d243fc5a.yaml 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 a40c291..969a766 100644 --- a/osc_placement/tests/functional/base.py +++ b/osc_placement/tests/functional/base.py @@ -289,15 +289,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).