diff --git a/cinderclient/tests/unit/v3/test_attachments.py b/cinderclient/tests/unit/v3/test_attachments.py index 2ac64862c..1802334ec 100644 --- a/cinderclient/tests/unit/v3/test_attachments.py +++ b/cinderclient/tests/unit/v3/test_attachments.py @@ -26,7 +26,8 @@ class AttachmentsTest(utils.TestCase): att = cs.attachments.create( 'e84fda45-4de4-4ce4-8f39-fc9d3b0aa05e', {}, - '557ad76c-ce54-40a3-9e91-c40d21665cc3') + '557ad76c-ce54-40a3-9e91-c40d21665cc3', + 'null') cs.assert_called('POST', '/attachments') self.assertEqual(fakes.fake_attachment['attachment'], att) diff --git a/cinderclient/tests/unit/v3/test_shell.py b/cinderclient/tests/unit/v3/test_shell.py index 43fb097bf..cdf1f368f 100644 --- a/cinderclient/tests/unit/v3/test_shell.py +++ b/cinderclient/tests/unit/v3/test_shell.py @@ -324,6 +324,49 @@ class ShellTest(utils.TestCase): self.assertTrue(mock_find_volume.called) self.assert_called('POST', '/attachments', body=expected) + @ddt.data({'cmd': '1234 1233', + 'body': {'instance_uuid': '1233', + 'connector': {}, + 'volume_uuid': '1234', + 'mode': 'ro'}}, + {'cmd': '1234 1233 ' + '--connect True ' + '--ip 10.23.12.23 --host server01 ' + '--platform x86_xx ' + '--ostype 123 ' + '--multipath true ' + '--mountpoint /123 ' + '--initiator aabbccdd', + 'body': {'instance_uuid': '1233', + 'connector': {'ip': '10.23.12.23', + 'host': 'server01', + 'os_type': '123', + 'multipath': 'true', + 'mountpoint': '/123', + 'initiator': 'aabbccdd', + 'platform': 'x86_xx'}, + 'volume_uuid': '1234', + 'mode': 'ro'}}, + {'cmd': 'abc 1233', + 'body': {'instance_uuid': '1233', + 'connector': {}, + 'volume_uuid': '1234', + 'mode': 'ro'}}) + @mock.patch('cinderclient.utils.find_resource') + @ddt.unpack + def test_attachment_create_with_mode(self, mock_find_volume, cmd, body): + mock_find_volume.return_value = volumes.Volume(self, + {'id': '1234'}, + loaded=True) + command = ('--os-volume-api-version 3.54 ' + 'attachment-create ' + '--mode ro ') + command += cmd + self.run_command(command) + expected = {'attachment': body} + self.assertTrue(mock_find_volume.called) + self.assert_called('POST', '/attachments', body=expected) + @mock.patch.object(volumes.VolumeManager, 'findall') def test_attachment_create_duplicate_name_vol(self, mock_findall): found = [volumes.Volume(self, {'id': '7654', 'name': 'abc'}, diff --git a/cinderclient/v3/attachments.py b/cinderclient/v3/attachments.py index e18bf9842..a0732a3b7 100644 --- a/cinderclient/v3/attachments.py +++ b/cinderclient/v3/attachments.py @@ -27,11 +27,14 @@ class VolumeAttachmentManager(base.ManagerWithFind): resource_class = VolumeAttachment @api_versions.wraps('3.27') - def create(self, volume_id, connector, instance_id): + def create(self, volume_id, connector, instance_id, mode='null'): """Create a attachment for specified volume.""" body = {'attachment': {'volume_uuid': volume_id, 'instance_uuid': instance_id, 'connector': connector}} + if self.api_version >= api_versions.APIVersion("3.54"): + if mode and mode != 'null': + body['attachment']['mode'] = mode retval = self._create('/attachments', body, 'attachment') return retval.to_dict() diff --git a/cinderclient/v3/shell.py b/cinderclient/v3/shell.py index fc74399dc..d5114e122 100644 --- a/cinderclient/v3/shell.py +++ b/cinderclient/v3/shell.py @@ -2164,6 +2164,13 @@ def do_attachment_show(cs, args): metavar='', default=None, help='Mountpoint volume will be attached at. Default=None.') +@utils.arg('--mode', + metavar='', + default='null', + start_version='3.54', + help='Mode of attachment, rw, ro and null, where null ' + 'indicates we want to honor any existing ' + 'admin-metadata settings. Default=null.') def do_attachment_create(cs, args): """Create an attachment for a cinder volume.""" @@ -2178,9 +2185,12 @@ def do_attachment_create(cs, args): 'multipath': args.multipath, 'mountpoint': args.mountpoint} volume = utils.find_volume(cs, args.volume) + mode = getattr(args, 'mode', 'null') attachment = cs.attachments.create(volume.id, connector, - args.server_id) + args.server_id, + mode) + connector_dict = attachment.pop('connection_info', None) utils.print_dict(attachment) if connector_dict: