From 163cb01e46fc3f906154a7045fdbe9342cd446c7 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 3 Nov 2021 11:31:04 +0000 Subject: compute: Return details of attached volumes The API behind the 'server add volume' command returns details of the created volume attachment, however, we were dropping these results rather than displaying them to the user. Correct this. Change-Id: I3f7e121220d29422ccf4e6940de2f28bb8496c83 Signed-off-by: Stephen Finucane --- openstackclient/compute/v2/server.py | 22 +++++- .../tests/unit/compute/v2/test_server.py | 91 ++++++++++++++++++++-- 2 files changed, 103 insertions(+), 10 deletions(-) (limited to 'openstackclient') diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index c11f4b57..80bdc612 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -496,7 +496,7 @@ class AddServerSecurityGroup(command.Command): server.add_security_group(security_group['id']) -class AddServerVolume(command.Command): +class AddServerVolume(command.ShowOne): _description = _( "Add volume to server. " "Specify ``--os-compute-api-version 2.20`` or higher to add a volume " @@ -595,12 +595,30 @@ class AddServerVolume(command.Command): kwargs['delete_on_termination'] = False - compute_client.volumes.create_server_volume( + volume_attachment = compute_client.volumes.create_server_volume( server.id, volume.id, **kwargs ) + columns = ('id', 'serverId', 'volumeId', 'device') + column_headers = ('ID', 'Server ID', 'Volume ID', 'Device') + if compute_client.api_version >= api_versions.APIVersion('2.49'): + columns += ('tag',) + column_headers += ('Tag',) + if compute_client.api_version >= api_versions.APIVersion('2.79'): + columns += ('delete_on_termination',) + column_headers += ('Delete On Termination',) + + return ( + column_headers, + utils.get_item_properties( + volume_attachment, + columns, + mixed_case_fields=('serverId', 'volumeId'), + ) + ) + # TODO(stephenfin): Replace with 'MultiKeyValueAction' when we no longer # support '--nic=auto' and '--nic=none' diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index 3d8c17fd..585f49de 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -670,6 +670,11 @@ class TestServerVolume(TestServer): def test_server_add_volume(self): servers = self.setup_servers_mock(count=1) + volume_attachment = \ + compute_fakes.FakeVolumeAttachment.create_one_volume_attachment() + self.servers_volumes_mock.create_server_volume.return_value = \ + volume_attachment + arglist = [ '--device', '/dev/sdb', servers[0].id, @@ -683,11 +688,20 @@ class TestServerVolume(TestServer): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + expected_columns = ('ID', 'Server ID', 'Volume ID', 'Device') + expected_data = ( + volume_attachment.id, + volume_attachment.serverId, + volume_attachment.volumeId, + volume_attachment.device, + ) + + columns, data = self.cmd.take_action(parsed_args) self.servers_volumes_mock.create_server_volume.assert_called_once_with( servers[0].id, self.volume.id, device='/dev/sdb') - self.assertIsNone(result) + self.assertEqual(expected_columns, columns) + self.assertEqual(expected_data, data) def test_server_add_volume_with_tag(self): # requires API 2.49 or later @@ -695,6 +709,11 @@ class TestServerVolume(TestServer): '2.49') servers = self.setup_servers_mock(count=1) + volume_attachment = \ + compute_fakes.FakeVolumeAttachment.create_one_volume_attachment() + self.servers_volumes_mock.create_server_volume.return_value = \ + volume_attachment + arglist = [ '--device', '/dev/sdb', '--tag', 'foo', @@ -710,11 +729,21 @@ class TestServerVolume(TestServer): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + expected_columns = ('ID', 'Server ID', 'Volume ID', 'Device', 'Tag') + expected_data = ( + volume_attachment.id, + volume_attachment.serverId, + volume_attachment.volumeId, + volume_attachment.device, + volume_attachment.tag, + ) + + columns, data = self.cmd.take_action(parsed_args) self.servers_volumes_mock.create_server_volume.assert_called_once_with( servers[0].id, self.volume.id, device='/dev/sdb', tag='foo') - self.assertIsNone(result) + self.assertEqual(expected_columns, columns) + self.assertEqual(expected_data, data) def test_server_add_volume_with_tag_pre_v249(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( @@ -746,6 +775,11 @@ class TestServerVolume(TestServer): '2.79') servers = self.setup_servers_mock(count=1) + volume_attachment = \ + compute_fakes.FakeVolumeAttachment.create_one_volume_attachment() + self.servers_volumes_mock.create_server_volume.return_value = \ + volume_attachment + arglist = [ '--enable-delete-on-termination', '--device', '/dev/sdb', @@ -761,18 +795,41 @@ class TestServerVolume(TestServer): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + expected_columns = ( + 'ID', + 'Server ID', + 'Volume ID', + 'Device', + 'Tag', + 'Delete On Termination', + ) + expected_data = ( + volume_attachment.id, + volume_attachment.serverId, + volume_attachment.volumeId, + volume_attachment.device, + volume_attachment.tag, + volume_attachment.delete_on_termination, + ) + + columns, data = self.cmd.take_action(parsed_args) self.servers_volumes_mock.create_server_volume.assert_called_once_with( servers[0].id, self.volume.id, device='/dev/sdb', delete_on_termination=True) - self.assertIsNone(result) + self.assertEqual(expected_columns, columns) + self.assertEqual(expected_data, data) def test_server_add_volume_with_disable_delete_on_termination(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.79') servers = self.setup_servers_mock(count=1) + volume_attachment = \ + compute_fakes.FakeVolumeAttachment.create_one_volume_attachment() + self.servers_volumes_mock.create_server_volume.return_value = \ + volume_attachment + arglist = [ '--disable-delete-on-termination', '--device', '/dev/sdb', @@ -788,12 +845,30 @@ class TestServerVolume(TestServer): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - result = self.cmd.take_action(parsed_args) + expected_columns = ( + 'ID', + 'Server ID', + 'Volume ID', + 'Device', + 'Tag', + 'Delete On Termination', + ) + expected_data = ( + volume_attachment.id, + volume_attachment.serverId, + volume_attachment.volumeId, + volume_attachment.device, + volume_attachment.tag, + volume_attachment.delete_on_termination, + ) + + columns, data = self.cmd.take_action(parsed_args) self.servers_volumes_mock.create_server_volume.assert_called_once_with( servers[0].id, self.volume.id, device='/dev/sdb', delete_on_termination=False) - self.assertIsNone(result) + self.assertEqual(expected_columns, columns) + self.assertEqual(expected_data, data) def test_server_add_volume_with_enable_delete_on_termination_pre_v279( self, -- cgit v1.2.1