# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from cinderclient import api_versions from osc_lib.cli import format_columns from osc_lib import exceptions from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes from openstackclient.volume.v3 import volume_attachment class TestVolumeAttachment(volume_fakes.TestVolume): def setUp(self): super().setUp() self.volumes_mock = self.app.client_manager.volume.volumes self.volumes_mock.reset_mock() self.volume_attachments_mock = \ self.app.client_manager.volume.attachments self.volume_attachments_mock.reset_mock() self.projects_mock = self.app.client_manager.identity.projects self.projects_mock.reset_mock() self.servers_mock = self.app.client_manager.compute.servers self.servers_mock.reset_mock() class TestVolumeAttachmentCreate(TestVolumeAttachment): volume = volume_fakes.create_one_volume() server = compute_fakes.FakeServer.create_one_server() volume_attachment = volume_fakes.create_one_volume_attachment( attrs={'instance': server.id, 'volume_id': volume.id}, ) columns = ( 'ID', 'Volume ID', 'Instance ID', 'Status', 'Attach Mode', 'Attached At', 'Detached At', 'Properties', ) data = ( volume_attachment.id, volume_attachment.volume_id, volume_attachment.instance, volume_attachment.status, volume_attachment.attach_mode, volume_attachment.attached_at, volume_attachment.detached_at, format_columns.DictColumn(volume_attachment.connection_info), ) def setUp(self): super().setUp() self.volumes_mock.get.return_value = self.volume self.servers_mock.get.return_value = self.server # VolumeAttachmentManager.create returns a dict self.volume_attachments_mock.create.return_value = \ self.volume_attachment.to_dict() self.cmd = volume_attachment.CreateVolumeAttachment(self.app, None) def test_volume_attachment_create(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.27') arglist = [ self.volume.id, self.server.id, ] verifylist = [ ('volume', self.volume.id), ('server', self.server.id), ('connect', False), ('initiator', None), ('ip', None), ('host', None), ('platform', None), ('os_type', None), ('multipath', False), ('mountpoint', None), ('mode', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.volumes_mock.get.assert_called_once_with(self.volume.id) self.servers_mock.get.assert_called_once_with(self.server.id) self.volume_attachments_mock.create.assert_called_once_with( self.volume.id, {}, self.server.id, None, ) self.assertEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_volume_attachment_create_with_connect(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.54') arglist = [ self.volume.id, self.server.id, '--connect', '--initiator', 'iqn.1993-08.org.debian:01:cad181614cec', '--ip', '192.168.1.20', '--host', 'my-host', '--platform', 'x86_64', '--os-type', 'linux2', '--multipath', '--mountpoint', '/dev/vdb', '--mode', 'null', ] verifylist = [ ('volume', self.volume.id), ('server', self.server.id), ('connect', True), ('initiator', 'iqn.1993-08.org.debian:01:cad181614cec'), ('ip', '192.168.1.20'), ('host', 'my-host'), ('platform', 'x86_64'), ('os_type', 'linux2'), ('multipath', True), ('mountpoint', '/dev/vdb'), ('mode', 'null'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) connect_info = dict([ ('initiator', 'iqn.1993-08.org.debian:01:cad181614cec'), ('ip', '192.168.1.20'), ('host', 'my-host'), ('platform', 'x86_64'), ('os_type', 'linux2'), ('multipath', True), ('mountpoint', '/dev/vdb'), ]) self.volumes_mock.get.assert_called_once_with(self.volume.id) self.servers_mock.get.assert_called_once_with(self.server.id) self.volume_attachments_mock.create.assert_called_once_with( self.volume.id, connect_info, self.server.id, 'null', ) self.assertEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_volume_attachment_create_pre_v327(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.26') arglist = [ self.volume.id, self.server.id, ] verifylist = [ ('volume', self.volume.id), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) exc = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-volume-api-version 3.27 or greater is required', str(exc)) def test_volume_attachment_create_with_mode_pre_v354(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.53') arglist = [ self.volume.id, self.server.id, '--mode', 'rw', ] verifylist = [ ('volume', self.volume.id), ('server', self.server.id), ('mode', 'rw'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) exc = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-volume-api-version 3.54 or greater is required', str(exc)) def test_volume_attachment_create_with_connect_missing_arg(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.54') arglist = [ self.volume.id, self.server.id, '--initiator', 'iqn.1993-08.org.debian:01:cad181614cec', ] verifylist = [ ('volume', self.volume.id), ('server', self.server.id), ('connect', False), ('initiator', 'iqn.1993-08.org.debian:01:cad181614cec'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) exc = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( 'You must specify the --connect option for any', str(exc)) class TestVolumeAttachmentDelete(TestVolumeAttachment): volume_attachment = volume_fakes.create_one_volume_attachment() def setUp(self): super().setUp() self.volume_attachments_mock.delete.return_value = None self.cmd = volume_attachment.DeleteVolumeAttachment(self.app, None) def test_volume_attachment_delete(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.27') arglist = [ self.volume_attachment.id, ] verifylist = [ ('attachment', self.volume_attachment.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.volume_attachments_mock.delete.assert_called_once_with( self.volume_attachment.id, ) self.assertIsNone(result) def test_volume_attachment_delete_pre_v327(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.26') arglist = [ self.volume_attachment.id, ] verifylist = [ ('attachment', self.volume_attachment.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) exc = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-volume-api-version 3.27 or greater is required', str(exc)) class TestVolumeAttachmentSet(TestVolumeAttachment): volume_attachment = volume_fakes.create_one_volume_attachment() columns = ( 'ID', 'Volume ID', 'Instance ID', 'Status', 'Attach Mode', 'Attached At', 'Detached At', 'Properties', ) data = ( volume_attachment.id, volume_attachment.volume_id, volume_attachment.instance, volume_attachment.status, volume_attachment.attach_mode, volume_attachment.attached_at, volume_attachment.detached_at, format_columns.DictColumn(volume_attachment.connection_info), ) def setUp(self): super().setUp() self.volume_attachments_mock.update.return_value = \ self.volume_attachment self.cmd = volume_attachment.SetVolumeAttachment(self.app, None) def test_volume_attachment_set(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.27') arglist = [ self.volume_attachment.id, '--initiator', 'iqn.1993-08.org.debian:01:cad181614cec', '--ip', '192.168.1.20', '--host', 'my-host', '--platform', 'x86_64', '--os-type', 'linux2', '--multipath', '--mountpoint', '/dev/vdb', ] verifylist = [ ('attachment', self.volume_attachment.id), ('initiator', 'iqn.1993-08.org.debian:01:cad181614cec'), ('ip', '192.168.1.20'), ('host', 'my-host'), ('platform', 'x86_64'), ('os_type', 'linux2'), ('multipath', True), ('mountpoint', '/dev/vdb'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) connect_info = dict([ ('initiator', 'iqn.1993-08.org.debian:01:cad181614cec'), ('ip', '192.168.1.20'), ('host', 'my-host'), ('platform', 'x86_64'), ('os_type', 'linux2'), ('multipath', True), ('mountpoint', '/dev/vdb'), ]) self.volume_attachments_mock.update.assert_called_once_with( self.volume_attachment.id, connect_info, ) self.assertEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_volume_attachment_set_pre_v327(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.26') arglist = [ self.volume_attachment.id, '--initiator', 'iqn.1993-08.org.debian:01:cad181614cec', ] verifylist = [ ('attachment', self.volume_attachment.id), ('initiator', 'iqn.1993-08.org.debian:01:cad181614cec'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) exc = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-volume-api-version 3.27 or greater is required', str(exc)) class TestVolumeAttachmentComplete(TestVolumeAttachment): volume_attachment = volume_fakes.create_one_volume_attachment() def setUp(self): super().setUp() self.volume_attachments_mock.complete.return_value = None self.cmd = volume_attachment.CompleteVolumeAttachment(self.app, None) def test_volume_attachment_complete(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.44') arglist = [ self.volume_attachment.id, ] verifylist = [ ('attachment', self.volume_attachment.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.volume_attachments_mock.complete.assert_called_once_with( self.volume_attachment.id, ) self.assertIsNone(result) def test_volume_attachment_complete_pre_v344(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.43') arglist = [ self.volume_attachment.id, ] verifylist = [ ('attachment', self.volume_attachment.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) exc = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-volume-api-version 3.44 or greater is required', str(exc)) class TestVolumeAttachmentList(TestVolumeAttachment): project = identity_fakes.FakeProject.create_one_project() volume_attachments = volume_fakes.create_volume_attachments() columns = ( 'ID', 'Volume ID', 'Server ID', 'Status', ) data = [ ( volume_attachment.id, volume_attachment.volume_id, volume_attachment.instance, volume_attachment.status, ) for volume_attachment in volume_attachments ] def setUp(self): super().setUp() self.projects_mock.get.return_value = self.project self.volume_attachments_mock.list.return_value = \ self.volume_attachments self.cmd = volume_attachment.ListVolumeAttachment(self.app, None) def test_volume_attachment_list(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.27') arglist = [] verifylist = [ ('project', None), ('all_projects', False), ('volume_id', None), ('status', None), ('marker', None), ('limit', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.volume_attachments_mock.list.assert_called_once_with( search_opts={ 'all_tenants': False, 'project_id': None, 'status': None, 'volume_id': None, }, marker=None, limit=None, ) self.assertEqual(self.columns, columns) self.assertCountEqual(tuple(self.data), data) def test_volume_attachment_list_with_options(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.27') arglist = [ '--project', self.project.name, '--volume-id', 'volume-id', '--status', 'attached', '--marker', 'volume-attachment-id', '--limit', '2', ] verifylist = [ ('project', self.project.name), ('all_projects', False), ('volume_id', 'volume-id'), ('status', 'attached'), ('marker', 'volume-attachment-id'), ('limit', 2), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.volume_attachments_mock.list.assert_called_once_with( search_opts={ 'all_tenants': True, 'project_id': self.project.id, 'status': 'attached', 'volume_id': 'volume-id', }, marker='volume-attachment-id', limit=2, ) self.assertEqual(self.columns, columns) self.assertCountEqual(tuple(self.data), data) def test_volume_attachment_list_pre_v327(self): self.app.client_manager.volume.api_version = \ api_versions.APIVersion('3.26') arglist = [] verifylist = [ ('project', None), ('all_projects', False), ('volume_id', None), ('status', None), ('marker', None), ('limit', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) exc = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-volume-api-version 3.27 or greater is required', str(exc))