diff --git a/novaclient/__init__.py b/novaclient/__init__.py index 956e139e6..0816b4f61 100644 --- a/novaclient/__init__.py +++ b/novaclient/__init__.py @@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1") # when client supported the max version, and bumped sequentially, otherwise # the client may break due to server side new version may include some # backward incompatible change. -API_MAX_VERSION = api_versions.APIVersion("2.40") +API_MAX_VERSION = api_versions.APIVersion("2.41") diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py index e6f749a51..f9da820c4 100644 --- a/novaclient/tests/unit/v2/fakes.py +++ b/novaclient/tests/unit/v2/fakes.py @@ -1703,7 +1703,7 @@ class FakeSessionClient(base_client.SessionClient): # def get_os_aggregates(self, *kw): - return (200, {}, {"aggregates": [ + response = (200, {}, {"aggregates": [ {'id': '1', 'name': 'test', 'availability_zone': 'nova1'}, @@ -1714,6 +1714,13 @@ class FakeSessionClient(base_client.SessionClient): 'name': 'test3', 'metadata': {'test': "dup", "none_key": "Nine"}}, ]}) + # microversion >= 2.41 returns the uuid in the response + if self.api_version >= api_versions.APIVersion('2.41'): + aggregates = response[2]['aggregates'] + aggregates[0]['uuid'] = '80785864-087b-45a5-a433-b20eac9b58aa' + aggregates[1]['uuid'] = '30827713-5957-4b68-8fd3-ccaddb568c24' + aggregates[2]['uuid'] = '9a651b22-ce3f-4a87-acd7-98446ef591c4' + return response def _return_aggregate(self): r = {'aggregate': self.get_os_aggregates()[2]['aggregates'][0]} diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py index 6a27175da..bb01344aa 100644 --- a/novaclient/tests/unit/v2/test_shell.py +++ b/novaclient/tests/unit/v2/test_shell.py @@ -1942,15 +1942,35 @@ class ShellTest(utils.TestCase): self.assert_called('GET', '/flavors/1', pos=-1) def test_aggregate_list(self): - self.run_command('aggregate-list') + out, err = self.run_command('aggregate-list') self.assert_called('GET', '/os-aggregates') + self.assertNotIn('UUID', out) + + def test_aggregate_list_v2_41(self): + out, err = self.run_command('aggregate-list', api_version='2.41') + self.assert_called('GET', '/os-aggregates') + self.assertIn('UUID', out) + self.assertIn('80785864-087b-45a5-a433-b20eac9b58aa', out) + self.assertIn('30827713-5957-4b68-8fd3-ccaddb568c24', out) + self.assertIn('9a651b22-ce3f-4a87-acd7-98446ef591c4', out) def test_aggregate_create(self): - self.run_command('aggregate-create test_name nova1') + out, err = self.run_command('aggregate-create test_name nova1') body = {"aggregate": {"name": "test_name", "availability_zone": "nova1"}} self.assert_called('POST', '/os-aggregates', body, pos=-2) self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertNotIn('UUID', out) + + def test_aggregate_create_v2_41(self): + out, err = self.run_command('aggregate-create test_name nova1', + api_version='2.41') + body = {"aggregate": {"name": "test_name", + "availability_zone": "nova1"}} + self.assert_called('POST', '/os-aggregates', body, pos=-2) + self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertIn('UUID', out) + self.assertIn('80785864-087b-45a5-a433-b20eac9b58aa', out) def test_aggregate_delete_by_id(self): self.run_command('aggregate-delete 1') @@ -1961,10 +1981,20 @@ class ShellTest(utils.TestCase): self.assert_called('DELETE', '/os-aggregates/1') def test_aggregate_update_by_id(self): - self.run_command('aggregate-update 1 --name new_name') + out, err = self.run_command('aggregate-update 1 --name new_name') body = {"aggregate": {"name": "new_name"}} self.assert_called('PUT', '/os-aggregates/1', body, pos=-2) self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertNotIn('UUID', out) + + def test_aggregate_update_by_id_v2_41(self): + out, err = self.run_command('aggregate-update 1 --name new_name', + api_version='2.41') + body = {"aggregate": {"name": "new_name"}} + self.assert_called('PUT', '/os-aggregates/1', body, pos=-2) + self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertIn('UUID', out) + self.assertIn('80785864-087b-45a5-a433-b20eac9b58aa', out) def test_aggregate_update_by_name(self): self.run_command('aggregate-update test --name new_name ') @@ -2011,10 +2041,20 @@ class ShellTest(utils.TestCase): self.assert_called('GET', '/os-aggregates/1', pos=-1) def test_aggregate_set_metadata_add_by_id(self): - self.run_command('aggregate-set-metadata 3 foo=bar') + out, err = self.run_command('aggregate-set-metadata 3 foo=bar') body = {"set_metadata": {"metadata": {"foo": "bar"}}} self.assert_called('POST', '/os-aggregates/3/action', body, pos=-2) self.assert_called('GET', '/os-aggregates/3', pos=-1) + self.assertNotIn('UUID', out) + + def test_aggregate_set_metadata_add_by_id_v2_41(self): + out, err = self.run_command('aggregate-set-metadata 3 foo=bar', + api_version='2.41') + body = {"set_metadata": {"metadata": {"foo": "bar"}}} + self.assert_called('POST', '/os-aggregates/3/action', body, pos=-2) + self.assert_called('GET', '/os-aggregates/3', pos=-1) + self.assertIn('UUID', out) + self.assertIn('9a651b22-ce3f-4a87-acd7-98446ef591c4', out) def test_aggregate_set_metadata_add_duplicate_by_id(self): cmd = 'aggregate-set-metadata 3 test=dup' @@ -2037,10 +2077,20 @@ class ShellTest(utils.TestCase): self.assert_called('GET', '/os-aggregates/1', pos=-1) def test_aggregate_add_host_by_id(self): - self.run_command('aggregate-add-host 1 host1') + out, err = self.run_command('aggregate-add-host 1 host1') body = {"add_host": {"host": "host1"}} self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertNotIn('UUID', out) + + def test_aggregate_add_host_by_id_v2_41(self): + out, err = self.run_command('aggregate-add-host 1 host1', + api_version='2.41') + body = {"add_host": {"host": "host1"}} + self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) + self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertIn('UUID', out) + self.assertIn('80785864-087b-45a5-a433-b20eac9b58aa', out) def test_aggregate_add_host_by_name(self): self.run_command('aggregate-add-host test host1') @@ -2049,10 +2099,20 @@ class ShellTest(utils.TestCase): self.assert_called('GET', '/os-aggregates/1', pos=-1) def test_aggregate_remove_host_by_id(self): - self.run_command('aggregate-remove-host 1 host1') + out, err = self.run_command('aggregate-remove-host 1 host1') body = {"remove_host": {"host": "host1"}} self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertNotIn('UUID', out) + + def test_aggregate_remove_host_by_id_v2_41(self): + out, err = self.run_command('aggregate-remove-host 1 host1', + api_version='2.41') + body = {"remove_host": {"host": "host1"}} + self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) + self.assert_called('GET', '/os-aggregates/1', pos=-1) + self.assertIn('UUID', out) + self.assertIn('80785864-087b-45a5-a433-b20eac9b58aa', out) def test_aggregate_remove_host_by_name(self): self.run_command('aggregate-remove-host test host1') @@ -2061,8 +2121,15 @@ class ShellTest(utils.TestCase): self.assert_called('GET', '/os-aggregates/1', pos=-1) def test_aggregate_show_by_id(self): - self.run_command('aggregate-show 1') + out, err = self.run_command('aggregate-show 1') self.assert_called('GET', '/os-aggregates/1') + self.assertNotIn('UUID', out) + + def test_aggregate_show_by_id_v2_41(self): + out, err = self.run_command('aggregate-show 1', api_version='2.41') + self.assert_called('GET', '/os-aggregates/1') + self.assertIn('UUID', out) + self.assertIn('80785864-087b-45a5-a433-b20eac9b58aa', out) def test_aggregate_show_by_name(self): self.run_command('aggregate-show test') @@ -3234,6 +3301,7 @@ class ShellTest(utils.TestCase): 37, # There are no versioned wrapped shell method changes for this 38, # doesn't require any changes in novaclient 39, # There are no versioned wrapped shell method changes for this + 41, # There are no version-wrapped shell method changes for this. ]) versions_supported = set(range(0, novaclient.API_MAX_VERSION.ver_minor + 1)) diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index 704e96705..055559a44 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -3737,6 +3737,8 @@ def do_aggregate_list(cs, args): """Print a list of all aggregates.""" aggregates = cs.aggregates.list() columns = ['Id', 'Name', 'Availability Zone'] + if cs.api_version >= api_versions.APIVersion('2.41'): + columns.append('UUID') utils.print_list(aggregates, columns) @@ -3750,7 +3752,7 @@ def do_aggregate_list(cs, args): def do_aggregate_create(cs, args): """Create a new aggregate with the specified details.""" aggregate = cs.aggregates.create(args.name, args.availability_zone) - _print_aggregate_details(aggregate) + _print_aggregate_details(cs, aggregate) @utils.arg( @@ -3804,7 +3806,7 @@ def do_aggregate_update(cs, args): aggregate = cs.aggregates.update(aggregate.id, updates) print(_("Aggregate %s has been successfully updated.") % aggregate.id) - _print_aggregate_details(aggregate) + _print_aggregate_details(cs, aggregate) @utils.arg( @@ -3833,7 +3835,7 @@ def do_aggregate_set_metadata(cs, args): aggregate = cs.aggregates.set_metadata(aggregate.id, metadata) print(_("Metadata has been successfully updated for aggregate %s.") % aggregate.id) - _print_aggregate_details(aggregate) + _print_aggregate_details(cs, aggregate) @utils.arg( @@ -3849,7 +3851,7 @@ def do_aggregate_add_host(cs, args): print(_("Host %(host)s has been successfully added for aggregate " "%(aggregate_id)s ") % {'host': args.host, 'aggregate_id': aggregate.id}) - _print_aggregate_details(aggregate) + _print_aggregate_details(cs, aggregate) @utils.arg( @@ -3865,7 +3867,7 @@ def do_aggregate_remove_host(cs, args): print(_("Host %(host)s has been successfully removed from aggregate " "%(aggregate_id)s ") % {'host': args.host, 'aggregate_id': aggregate.id}) - _print_aggregate_details(aggregate) + _print_aggregate_details(cs, aggregate) @utils.arg( @@ -3874,11 +3876,13 @@ def do_aggregate_remove_host(cs, args): def do_aggregate_show(cs, args): """Show details of the specified aggregate.""" aggregate = _find_aggregate(cs, args.aggregate) - _print_aggregate_details(aggregate) + _print_aggregate_details(cs, aggregate) -def _print_aggregate_details(aggregate): +def _print_aggregate_details(cs, aggregate): columns = ['Id', 'Name', 'Availability Zone', 'Hosts', 'Metadata'] + if cs.api_version >= api_versions.APIVersion('2.41'): + columns.append('UUID') def parser_metadata(fields): return utils.pretty_choice_dict(getattr(fields, 'metadata', {}) or {}) diff --git a/releasenotes/notes/microversion-v2_41-6df7a5a66a9ded35.yaml b/releasenotes/notes/microversion-v2_41-6df7a5a66a9ded35.yaml new file mode 100644 index 000000000..34d442d9e --- /dev/null +++ b/releasenotes/notes/microversion-v2_41-6df7a5a66a9ded35.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Added support for microversion 2.41 which shows the aggregate UUID in CLI + output when listing, creating, showing, updating, setting metadata, and + adding or removing hosts from an aggregate.