def test_check_volume_type_for_lun_qos_not_supported(self, get_specs): get_specs.return_value = { 'specs': 's', 'netapp:qos_policy_group': 'qos' } mock_lun = block_base.NetAppLun('handle', 'name', '1', { 'Volume': 'name', 'Path': '/vol/lun' }) self.assertRaises(exception.ManageExistingVolumeTypeMismatch, self.library._check_volume_type_for_lun, {'vol': 'vol'}, mock_lun, {'ref': 'ref'}) get_specs.assert_called_once_with({'vol': 'vol'})
def setUp(self): super(NetAppBlockStorageCmodeLibraryTestCase, self).setUp() kwargs = {'configuration': self.get_config_cmode()} self.library = block_cmode.NetAppBlockStorageCmodeLibrary( 'driver', 'protocol', **kwargs) self.library.zapi_client = mock.Mock() self.zapi_client = self.library.zapi_client self.library.perf_library = mock.Mock() self.library.ssc_library = mock.Mock() self.library.vserver = mock.Mock() self.fake_lun = block_base.NetAppLun(fake.LUN_HANDLE, fake.LUN_NAME, fake.SIZE, None) self.fake_snapshot_lun = block_base.NetAppLun( fake.SNAPSHOT_LUN_HANDLE, fake.SNAPSHOT_NAME, fake.SIZE, None) self.mock_object(self.library, 'lun_table') self.library.lun_table = { fake.LUN_NAME: self.fake_lun, fake.SNAPSHOT_NAME: self.fake_snapshot_lun, } self.mock_object(block_base.NetAppBlockStorageLibrary, 'delete_volume')
def test_create_cloned_volume(self): fake_lun = block_base.NetAppLun(fake.LUN_HANDLE, fake.LUN_ID, fake.LUN_SIZE, fake.LUN_METADATA) mock_get_lun_from_table = self.mock_object(self.library, '_get_lun_from_table') mock_get_lun_from_table.return_value = fake_lun mock_do_clone = self.mock_object(self.library, '_clone_source_to_destination') source = {'name': fake_lun.name, 'size': fake.VOLUME_REF['size']} self.library.create_cloned_volume(fake.VOLUME, fake.VOLUME_REF) mock_do_clone.assert_has_calls([mock.call(source, fake.VOLUME)])
def test_check_volume_type_for_lun_fail(self, get_ssc, get_vols): self.library.ssc_vols = ['vol'] fake_extra_specs = {'specs': 's'} get_vols.return_value = [ssc_cmode.NetAppVolume(name='name', vserver='vs')] mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Volume': 'fake', 'Path': '/vol/lun'}) self.assertRaises(exception.ManageExistingVolumeTypeMismatch, self.library._check_volume_type_for_lun, {'vol': 'vol'}, mock_lun, {'ref': 'ref'}, fake_extra_specs) get_vols.assert_called_with(['vol'], {'specs': 's'}) self.assertEqual(1, get_ssc.call_count)
def test_manage_existing_lun_same_name(self): mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Path': '/vol/vol1/name'}) self.library._get_existing_vol_with_manage_ref = mock.Mock( return_value=mock_lun) self.library._check_volume_type_for_lun = mock.Mock() self.library._add_lun_to_table = mock.Mock() self.zapi_client.move_lun = mock.Mock() self.library.manage_existing({'name': 'name'}, {'ref': 'ref'}) self.library._get_existing_vol_with_manage_ref.assert_called_once_with( {'ref': 'ref'}) self.assertEqual(1, self.library._check_volume_type_for_lun.call_count) self.assertEqual(1, self.library._add_lun_to_table.call_count) self.assertEqual(0, self.zapi_client.move_lun.call_count)
def _clone_lun(self, name, new_name, space_reserved=None, qos_policy_group_name=None, src_block=0, dest_block=0, block_count=0, source_snapshot=None, is_snapshot=False): """Clone LUN with the given handle to the new name. :param: is_snapshot Not used, present for method signature consistency """ if not space_reserved: space_reserved = self.lun_space_reservation if qos_policy_group_name is not None: msg = _('Data ONTAP operating in 7-Mode does not support QoS ' 'policy groups.') raise exception.VolumeDriverException(msg) metadata = self._get_lun_attr(name, 'metadata') path = metadata['Path'] (parent, _splitter, name) = path.rpartition('/') clone_path = '%s/%s' % (parent, new_name) self.zapi_client.clone_lun(path, clone_path, name, new_name, space_reserved, src_block=src_block, dest_block=dest_block, block_count=block_count, source_snapshot=source_snapshot) self.vol_refresh_voluntary = True luns = self.zapi_client.get_lun_by_args(path=clone_path) cloned_lun = luns[0] self.zapi_client.set_space_reserve(clone_path, space_reserved) clone_meta = self._create_lun_meta(cloned_lun) handle = self._create_lun_handle(clone_meta) self._add_lun_to_table( block_base.NetAppLun(handle, new_name, cloned_lun.get_child_content('size'), clone_meta))
def setUp(self): super(NetAppBlockStorageCmodeLibraryTestCase, self).setUp() # Inject fake netapp_lib module classes. netapp_api.mock_netapp_lib([block_cmode]) kwargs = {'configuration': self.get_config_cmode()} self.library = block_cmode.NetAppBlockStorageCmodeLibrary( 'driver', 'protocol', **kwargs) self.library.zapi_client = mock.Mock() self.zapi_client = self.library.zapi_client self.library.vserver = mock.Mock() self.library.ssc_vols = None self.fake_lun = block_base.NetAppLun(fake.LUN_HANDLE, fake.LUN_NAME, fake.SIZE, None) self.mock_object(self.library, 'lun_table') self.library.lun_table = {fake.LUN_NAME: self.fake_lun} self.mock_object(block_base.NetAppBlockStorageLibrary, 'delete_volume')
def test_manage_existing_lun_new_path(self): mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Path': '/vol/FAKE_CMODE_VOL1/name'}) self.library._get_existing_vol_with_manage_ref = mock.Mock( return_value=mock_lun) self.mock_object(na_utils, 'get_volume_extra_specs') self.mock_object(na_utils, 'log_extra_spec_warnings') self.library._check_volume_type_for_lun = mock.Mock() self.library._add_lun_to_table = mock.Mock() self.zapi_client.move_lun = mock.Mock() self.library.manage_existing({'name': 'volume'}, {'ref': 'ref'}) self.assertEqual( 2, self.library._get_existing_vol_with_manage_ref.call_count) self.assertEqual(1, self.library._check_volume_type_for_lun.call_count) self.assertEqual(1, self.library._add_lun_to_table.call_count) self.zapi_client.move_lun.assert_called_once_with( '/vol/FAKE_CMODE_VOL1/name', '/vol/FAKE_CMODE_VOL1/volume')
def _clone_lun(self, name, new_name, space_reserved=None, qos_policy_group_name=None, src_block=0, dest_block=0, block_count=0, source_snapshot=None, is_snapshot=False, qos_policy_group_is_adaptive=False): """Clone LUN with the given handle to the new name.""" if not space_reserved: space_reserved = self.lun_space_reservation metadata = self._get_lun_attr(name, 'metadata') volume = metadata['Volume'] self.zapi_client.clone_lun( volume, name, new_name, space_reserved, qos_policy_group_name=qos_policy_group_name, src_block=src_block, dest_block=dest_block, block_count=block_count, source_snapshot=source_snapshot, is_snapshot=is_snapshot, qos_policy_group_is_adaptive=qos_policy_group_is_adaptive) LOG.debug("Cloned LUN with new name %s", new_name) lun = self.zapi_client.get_lun_by_args(vserver=self.vserver, path='/vol/%s/%s' % (volume, new_name)) if len(lun) == 0: msg = _("No cloned LUN named %s found on the filer") raise exception.VolumeBackendAPIException(data=msg % new_name) clone_meta = self._create_lun_meta(lun[0]) self._add_lun_to_table( block_base.NetAppLun( '%s:%s' % (clone_meta['Vserver'], clone_meta['Path']), new_name, lun[0].get_child_content('size'), clone_meta))
def test_create_group_snapshot(self): self.mock_object(volume_utils, 'is_group_a_cg_snapshot_type', return_value=False) fake_lun = block_base.NetAppLun(fake.LUN_HANDLE, fake.LUN_ID, fake.LUN_SIZE, fake.LUN_METADATA) self.mock_object(self.library, '_get_lun_from_table', return_value=fake_lun) mock__clone_lun = self.mock_object(self.library, '_clone_lun') model_update, snapshots_model_update = ( self.library.create_group_snapshot(fake.VOLUME_GROUP, [fake.SNAPSHOT])) self.assertIsNone(model_update) self.assertIsNone(snapshots_model_update) mock__clone_lun.assert_called_once_with(fake_lun.name, fake.SNAPSHOT['name'], space_reserved='false', is_snapshot=True)
def _clone_lun(self, name, new_name, space_reserved='true', src_block=0, dest_block=0, block_count=0): """Clone LUN with the given handle to the new name.""" metadata = self._get_lun_attr(name, 'metadata') path = metadata['Path'] (parent, _splitter, name) = path.rpartition('/') clone_path = '%s/%s' % (parent, new_name) self.zapi_client.clone_lun(path, clone_path, name, new_name, space_reserved, src_block=0, dest_block=0, block_count=0) self.vol_refresh_voluntary = True luns = self.zapi_client.get_lun_by_args(path=clone_path) cloned_lun = luns[0] self.zapi_client.set_space_reserve(clone_path, space_reserved) clone_meta = self._create_lun_meta(cloned_lun) handle = self._create_lun_handle(clone_meta) self._add_lun_to_table( block_base.NetAppLun(handle, new_name, cloned_lun.get_child_content('size'), clone_meta))
def test__extend_volume_clone(self): current_size = fake.LUN_SIZE current_size_bytes = current_size * units.Gi new_size = fake.LUN_SIZE * 20 new_size_bytes = new_size * units.Gi max_size = fake.LUN_SIZE * 10 max_size_bytes = max_size * units.Gi fake_volume = copy.copy(fake.VOLUME) fake_volume['size'] = new_size fake_lun = block_base.NetAppLun(fake.LUN_HANDLE, fake.LUN_ID, current_size_bytes, fake.LUN_METADATA) mock_get_lun_from_table = self.mock_object( self.library, '_get_lun_from_table', mock.Mock(return_value=fake_lun)) fake_lun_geometry = {'max_resize': six.text_type(max_size_bytes)} mock_get_lun_geometry = self.mock_object( self.library.zapi_client, 'get_lun_geometry', mock.Mock(return_value=fake_lun_geometry)) mock_do_direct_resize = self.mock_object(self.library.zapi_client, 'do_direct_resize') mock_do_sub_clone_resize = self.mock_object(self.library, '_do_sub_clone_resize') self.library.lun_table = {fake.VOLUME['name']: fake_lun} self.library._extend_volume(fake.VOLUME, new_size, 'fake_qos_policy') mock_get_lun_from_table.assert_called_once_with(fake.VOLUME['name']) mock_get_lun_geometry.assert_called_once_with( fake.LUN_METADATA['Path']) self.assertFalse(mock_do_direct_resize.called) mock_do_sub_clone_resize.assert_called_once_with( fake.LUN_METADATA['Path'], six.text_type(new_size_bytes), qos_policy_group_name='fake_qos_policy') self.assertEqual(six.text_type(new_size_bytes), self.library.lun_table[fake.VOLUME['name']].size)
def _clone_lun(self, name, new_name, space_reserved='true', src_block=0, dest_block=0, block_count=0): """Clone LUN with the given handle to the new name.""" metadata = self._get_lun_attr(name, 'metadata') volume = metadata['Volume'] self.zapi_client.clone_lun(volume, name, new_name, space_reserved, src_block=0, dest_block=0, block_count=0) LOG.debug("Cloned LUN with new name %s" % new_name) lun = self.zapi_client.get_lun_by_args(vserver=self.vserver, path='/vol/%s/%s' % (volume, new_name)) if len(lun) == 0: msg = _("No cloned LUN named %s found on the filer") raise exception.VolumeBackendAPIException(data=msg % new_name) clone_meta = self._create_lun_meta(lun[0]) self._add_lun_to_table( block_base.NetAppLun('%s:%s' % (clone_meta['Vserver'], clone_meta['Path']), new_name, lun[0].get_child_content('size'), clone_meta)) self._update_stale_vols( volume=ssc_cmode.NetAppVolume(volume, self.vserver))
def test_manage_existing_lun_same_name(self): mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Path': '/vol/FAKE_CMODE_VOL1/name'}) self.library._get_existing_vol_with_manage_ref = mock.Mock( return_value=mock_lun) self.mock_object(na_utils, 'get_volume_extra_specs') self.mock_object(na_utils, 'log_extra_spec_warnings') self.library._check_volume_type_for_lun = mock.Mock() self.library._setup_qos_for_volume = mock.Mock() self.mock_object(na_utils, 'get_qos_policy_group_name_from_info', mock.Mock(return_value=fake.QOS_POLICY_GROUP_NAME)) self.library._add_lun_to_table = mock.Mock() self.zapi_client.move_lun = mock.Mock() mock_set_lun_qos_policy_group = self.mock_object( self.zapi_client, 'set_lun_qos_policy_group') self.library.manage_existing({'name': 'name'}, {'ref': 'ref'}) self.library._get_existing_vol_with_manage_ref.assert_called_once_with( {'ref': 'ref'}) self.assertEqual(1, self.library._check_volume_type_for_lun.call_count) self.assertEqual(1, self.library._add_lun_to_table.call_count) self.assertEqual(0, self.zapi_client.move_lun.call_count) self.assertEqual(1, mock_set_lun_qos_policy_group.call_count)
class NetAppBlockStorageLibraryTestCase(test.TestCase): def setUp(self): super(NetAppBlockStorageLibraryTestCase, self).setUp() # Inject fake netapp_lib module classes. netapp_api.mock_netapp_lib([block_base]) kwargs = {'configuration': mock.Mock()} self.library = block_base.NetAppBlockStorageLibrary( 'driver', 'protocol', **kwargs) self.library.zapi_client = mock.Mock() self.zapi_client = self.library.zapi_client self.mock_request = mock.Mock() def tearDown(self): super(NetAppBlockStorageLibraryTestCase, self).tearDown() @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr', mock.Mock(return_value={'Volume': 'vol1'})) def test_get_pool(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual('vol1', pool) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr', mock.Mock(return_value=None)) def test_get_pool_no_metadata(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(None, pool) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr', mock.Mock(return_value=dict())) def test_get_pool_volume_unknown(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(None, pool) def test_create_volume(self): volume_size_in_bytes = int(fake.SIZE) * units.Gi self.mock_object(na_utils, 'get_volume_extra_specs') self.mock_object(na_utils, 'log_extra_spec_warnings') self.mock_object(block_base, 'LOG') self.mock_object(volume_utils, 'extract_host', mock.Mock(return_value=fake.POOL_NAME)) self.mock_object(self.library, '_setup_qos_for_volume', mock.Mock(return_value=None)) self.mock_object(self.library, '_create_lun') self.mock_object(self.library, '_create_lun_handle') self.mock_object(self.library, '_add_lun_to_table') self.mock_object(self.library, '_mark_qos_policy_group_for_deletion') self.library.create_volume(fake.VOLUME) self.library._create_lun.assert_called_once_with( fake.POOL_NAME, fake.LUN_NAME, volume_size_in_bytes, fake.LUN_METADATA, None) self.assertEqual( 0, self.library._mark_qos_policy_group_for_deletion.call_count) self.assertEqual(0, block_base.LOG.error.call_count) def test_create_volume_no_pool(self): self.mock_object(volume_utils, 'extract_host', mock.Mock(return_value=None)) self.assertRaises(exception.InvalidHost, self.library.create_volume, fake.VOLUME) def test_create_volume_exception_path(self): self.mock_object(block_base, 'LOG') self.mock_object(na_utils, 'get_volume_extra_specs') self.mock_object(self.library, '_setup_qos_for_volume', mock.Mock(return_value=None)) self.mock_object(self.library, '_create_lun', mock.Mock(side_effect=Exception)) self.mock_object(self.library, '_mark_qos_policy_group_for_deletion') self.assertRaises(exception.VolumeBackendAPIException, self.library.create_volume, fake.VOLUME) self.assertEqual( 1, self.library._mark_qos_policy_group_for_deletion.call_count) self.assertEqual(1, block_base.LOG.exception.call_count) def test_create_volume_no_pool_provided_by_scheduler(self): fake_volume = copy.deepcopy(fake.VOLUME) # Set up fake volume whose 'host' field is missing pool information. fake_volume['host'] = '%s@%s' % (fake.HOST_NAME, fake.BACKEND_NAME) self.assertRaises(exception.InvalidHost, self.library.create_volume, fake_volume) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') def test_map_lun(self, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' self.library.host_type = 'linux' mock_get_lun_attr.return_value = {'Path': fake.LUN_PATH, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') self.zapi_client.map_lun.return_value = '1' lun_id = self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) self.assertEqual('1', lun_id) mock_get_or_create_igroup.assert_called_once_with( fake.FC_FORMATTED_INITIATORS, protocol, os) self.zapi_client.map_lun.assert_called_once_with(fake.LUN_PATH, fake.IGROUP1_NAME, lun_id=None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_map_lun_mismatch_host_os(self, mock_get_or_create_igroup, mock_get_lun_attr): os = 'windows' protocol = 'fcp' self.library.host_type = 'linux' mock_get_lun_attr.return_value = {'Path': fake.LUN_PATH, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) mock_get_or_create_igroup.assert_called_once_with( fake.FC_FORMATTED_INITIATORS, protocol, self.library.host_type) self.zapi_client.map_lun.assert_called_once_with(fake.LUN_PATH, fake.IGROUP1_NAME, lun_id=None) self.assertEqual(1, block_base.LOG.warning.call_count) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_find_mapped_lun_igroup') def test_map_lun_preexisting(self, mock_find_mapped_lun_igroup, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' mock_get_lun_attr.return_value = {'Path': fake.LUN_PATH, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') mock_find_mapped_lun_igroup.return_value = (fake.IGROUP1_NAME, '2') self.zapi_client.map_lun.side_effect = netapp_api.NaApiError lun_id = self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) self.assertEqual('2', lun_id) mock_find_mapped_lun_igroup.assert_called_once_with( fake.LUN_PATH, fake.FC_FORMATTED_INITIATORS) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_find_mapped_lun_igroup') def test_map_lun_api_error(self, mock_find_mapped_lun_igroup, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' mock_get_lun_attr.return_value = {'Path': fake.LUN_PATH, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') mock_find_mapped_lun_igroup.return_value = (None, None) self.zapi_client.map_lun.side_effect = netapp_api.NaApiError self.assertRaises(netapp_api.NaApiError, self.library._map_lun, 'fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_find_mapped_lun_igroup') def test_unmap_lun(self, mock_find_mapped_lun_igroup): mock_find_mapped_lun_igroup.return_value = (fake.IGROUP1_NAME, 1) self.library._unmap_lun(fake.LUN_PATH, fake.FC_FORMATTED_INITIATORS) self.zapi_client.unmap_lun.assert_called_once_with( fake.LUN_PATH, fake.IGROUP1_NAME) def test_find_mapped_lun_igroup(self): self.assertRaises(NotImplementedError, self.library._find_mapped_lun_igroup, fake.LUN_PATH, fake.FC_FORMATTED_INITIATORS) def test_has_luns_mapped_to_initiators(self): self.zapi_client.has_luns_mapped_to_initiators.return_value = True self.assertTrue( self.library._has_luns_mapped_to_initiators( fake.FC_FORMATTED_INITIATORS)) self.zapi_client.has_luns_mapped_to_initiators.assert_called_once_with( fake.FC_FORMATTED_INITIATORS) def test_get_or_create_igroup_preexisting(self): self.zapi_client.get_igroup_by_initiators.return_value = [fake.IGROUP1] self.library._create_igroup_add_initiators = mock.Mock() igroup_name, host_os, ig_type = self.library._get_or_create_igroup( fake.FC_FORMATTED_INITIATORS, 'fcp', 'linux') self.assertEqual(fake.IGROUP1_NAME, igroup_name) self.assertEqual('linux', host_os) self.assertEqual('fcp', ig_type) self.zapi_client.get_igroup_by_initiators.assert_called_once_with( fake.FC_FORMATTED_INITIATORS) self.assertEqual(0, self.library._create_igroup_add_initiators.call_count) @mock.patch.object(uuid, 'uuid4', mock.Mock(return_value=fake.UUID1)) def test_get_or_create_igroup_none_preexisting(self): """This method also tests _create_igroup_add_initiators.""" self.zapi_client.get_igroup_by_initiators.return_value = [] igroup_name, os, ig_type = self.library._get_or_create_igroup( fake.FC_FORMATTED_INITIATORS, 'fcp', 'linux') self.assertEqual('openstack-' + fake.UUID1, igroup_name) self.zapi_client.create_igroup.assert_called_once_with( igroup_name, 'fcp', 'linux') self.assertEqual(len(fake.FC_FORMATTED_INITIATORS), self.zapi_client.add_igroup_initiator.call_count) self.assertEqual('linux', os) self.assertEqual('fcp', ig_type) def test_get_fc_target_wwpns(self): self.assertRaises(NotImplementedError, self.library._get_fc_target_wwpns) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_build_initiator_target_map') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_map_lun') def test_initialize_connection_fc(self, mock_map_lun, mock_build_initiator_target_map): self.maxDiff = None mock_map_lun.return_value = '1' mock_build_initiator_target_map.return_value = (fake.FC_TARGET_WWPNS, fake.FC_I_T_MAP, 4) target_info = self.library.initialize_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO) mock_map_lun.assert_called_once_with('fake_volume', fake.FC_FORMATTED_INITIATORS, 'fcp', None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_build_initiator_target_map') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_map_lun') def test_initialize_connection_fc_no_wwpns( self, mock_map_lun, mock_build_initiator_target_map): mock_map_lun.return_value = '1' mock_build_initiator_target_map.return_value = (None, None, 0) self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_fc, fake.FC_VOLUME, fake.FC_CONNECTOR) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_has_luns_mapped_to_initiators') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_unmap_lun') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') def test_terminate_connection_fc(self, mock_get_lun_attr, mock_unmap_lun, mock_has_luns_mapped_to_initiators): mock_get_lun_attr.return_value = {'Path': fake.LUN_PATH} mock_unmap_lun.return_value = None mock_has_luns_mapped_to_initiators.return_value = True target_info = self.library.terminate_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO_EMPTY) mock_unmap_lun.assert_called_once_with(fake.LUN_PATH, fake.FC_FORMATTED_INITIATORS) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_build_initiator_target_map') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_has_luns_mapped_to_initiators') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_unmap_lun') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') def test_terminate_connection_fc_no_more_luns( self, mock_get_lun_attr, mock_unmap_lun, mock_has_luns_mapped_to_initiators, mock_build_initiator_target_map): mock_get_lun_attr.return_value = {'Path': fake.LUN_PATH} mock_unmap_lun.return_value = None mock_has_luns_mapped_to_initiators.return_value = False mock_build_initiator_target_map.return_value = (fake.FC_TARGET_WWPNS, fake.FC_I_T_MAP, 4) target_info = self.library.terminate_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO_UNMAP) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_fc_target_wwpns') def test_build_initiator_target_map_no_lookup_service( self, mock_get_fc_target_wwpns): self.library.lookup_service = None mock_get_fc_target_wwpns.return_value = fake.FC_FORMATTED_TARGET_WWPNS (target_wwpns, init_targ_map, num_paths) = \ self.library._build_initiator_target_map(fake.FC_CONNECTOR) self.assertSetEqual(set(fake.FC_TARGET_WWPNS), set(target_wwpns)) self.assertDictEqual(fake.FC_I_T_MAP_COMPLETE, init_targ_map) self.assertEqual(0, num_paths) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_fc_target_wwpns') def test_build_initiator_target_map_with_lookup_service( self, mock_get_fc_target_wwpns): self.library.lookup_service = mock.Mock() self.library.lookup_service.get_device_mapping_from_network.\ return_value = fake.FC_FABRIC_MAP mock_get_fc_target_wwpns.return_value = fake.FC_FORMATTED_TARGET_WWPNS (target_wwpns, init_targ_map, num_paths) = \ self.library._build_initiator_target_map(fake.FC_CONNECTOR) self.assertSetEqual(set(fake.FC_TARGET_WWPNS), set(target_wwpns)) self.assertDictEqual(fake.FC_I_T_MAP, init_targ_map) self.assertEqual(4, num_paths) @mock.patch.object(na_utils, 'check_flags') def test_do_setup_san_configured(self, mock_check_flags): self.library.configuration.netapp_lun_ostype = 'windows' self.library.configuration.netapp_host_type = 'solaris' self.library.configuration.netapp_lun_space_reservation = 'disabled' self.library.do_setup(mock.Mock()) self.assertTrue(mock_check_flags.called) self.assertEqual('windows', self.library.lun_ostype) self.assertEqual('solaris', self.library.host_type) @mock.patch.object(na_utils, 'check_flags') def test_do_setup_san_unconfigured(self, mock_check_flags): self.library.configuration.netapp_lun_ostype = None self.library.configuration.netapp_host_type = None self.library.configuration.netapp_lun_space_reservation = 'enabled' self.library.do_setup(mock.Mock()) self.assertTrue(mock_check_flags.called) self.assertEqual('linux', self.library.lun_ostype) self.assertEqual('linux', self.library.host_type) def test_do_setup_space_reservation_disabled(self): self.mock_object(na_utils, 'check_flags') self.library.configuration.netapp_lun_ostype = None self.library.configuration.netapp_host_type = None self.library.configuration.netapp_lun_space_reservation = 'disabled' self.library.do_setup(mock.Mock()) self.assertEqual('false', self.library.lun_space_reservation) def test_do_setup_space_reservation_enabled(self): self.mock_object(na_utils, 'check_flags') self.library.configuration.netapp_lun_ostype = None self.library.configuration.netapp_host_type = None self.library.configuration.netapp_lun_space_reservation = 'enabled' self.library.do_setup(mock.Mock()) self.assertEqual('true', self.library.lun_space_reservation) def test_get_existing_vol_manage_missing_id_path(self): self.assertRaises(exception.ManageExistingInvalidReference, self.library._get_existing_vol_with_manage_ref, {}) def test_get_existing_vol_manage_not_found(self): self.zapi_client.get_lun_by_args.return_value = [] self.assertRaises(exception.ManageExistingInvalidReference, self.library._get_existing_vol_with_manage_ref, { 'source-id': 'src_id', 'source-name': 'lun_path' }) self.assertEqual(1, self.zapi_client.get_lun_by_args.call_count) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_extract_lun_info', mock.Mock(return_value=block_base.NetAppLun( 'lun0', 'lun0', '3', {'UUID': 'src_id'}))) def test_get_existing_vol_manage_lun(self): self.zapi_client.get_lun_by_args.return_value = ['lun0', 'lun1'] lun = self.library._get_existing_vol_with_manage_ref({ 'source-id': 'src_id', 'path': 'lun_path' }) self.assertEqual(1, self.zapi_client.get_lun_by_args.call_count) self.library._extract_lun_info.assert_called_once_with('lun0') self.assertEqual('lun0', lun.name) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_existing_vol_with_manage_ref', mock.Mock(return_value=block_base.NetAppLun( 'handle', 'name', '1073742824', {}))) def test_manage_existing_get_size(self): size = self.library.manage_existing_get_size({'id': 'vol_id'}, {'ref': 'ref'}) self.assertEqual(2, size) self.library._get_existing_vol_with_manage_ref.assert_called_once_with( {'ref': 'ref'}) @mock.patch.object(block_base.LOG, 'info') def test_unmanage(self, log): mock_lun = block_base.NetAppLun('handle', 'name', '1', { 'Path': 'p', 'UUID': 'uuid' }) self.library._get_lun_from_table = mock.Mock(return_value=mock_lun) self.library.unmanage({'name': 'vol'}) self.library._get_lun_from_table.assert_called_once_with('vol') self.assertEqual(1, log.call_count) def test_check_vol_type_for_lun(self): self.assertRaises(NotImplementedError, self.library._check_volume_type_for_lun, 'vol', 'lun', 'existing_ref', {}) def test_is_lun_valid_on_storage(self): self.assertTrue(self.library._is_lun_valid_on_storage('lun')) def test_initialize_connection_iscsi(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = ( target_details_list) self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list', mock.Mock(return_value=target_details_list[1])) self.zapi_client.get_iscsi_service_details.return_value = ( fake.ISCSI_SERVICE_IQN) self.mock_object( na_utils, 'get_iscsi_connection_properties', mock.Mock(return_value=fake.ISCSI_CONNECTION_PROPERTIES)) target_info = self.library.initialize_connection_iscsi( volume, connector) self.assertEqual(fake.ISCSI_CONNECTION_PROPERTIES, target_info) block_base.NetAppBlockStorageLibrary._map_lun.assert_called_once_with( fake.ISCSI_VOLUME['name'], [fake.ISCSI_CONNECTOR['initiator']], 'iscsi', None) self.zapi_client.get_iscsi_target_details.assert_called_once_with() block_base.NetAppBlockStorageLibrary._get_preferred_target_from_list\ .assert_called_once_with( target_details_list) self.zapi_client.get_iscsi_service_details.assert_called_once_with() def test_initialize_connection_iscsi_no_target_list(self): volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = None self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list') self.mock_object( na_utils, 'get_iscsi_connection_properties', mock.Mock(return_value=fake.ISCSI_CONNECTION_PROPERTIES)) self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_iscsi, volume, connector) self.assertEqual( 0, block_base.NetAppBlockStorageLibrary. _get_preferred_target_from_list.call_count) self.assertEqual(0, self.zapi_client.get_iscsi_service_details.call_count) self.assertEqual(0, na_utils.get_iscsi_connection_properties.call_count) def test_initialize_connection_iscsi_no_preferred_target(self): volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = None self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list', mock.Mock(return_value=None)) self.mock_object(na_utils, 'get_iscsi_connection_properties') self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_iscsi, volume, connector) self.assertEqual(0, self.zapi_client.get_iscsi_service_details.call_count) self.assertEqual(0, na_utils.get_iscsi_connection_properties.call_count) def test_initialize_connection_iscsi_no_iscsi_service_details(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = ( target_details_list) self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list', mock.Mock(return_value=target_details_list[1])) self.zapi_client.get_iscsi_service_details.return_value = None self.mock_object(na_utils, 'get_iscsi_connection_properties') self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_iscsi, volume, connector) block_base.NetAppBlockStorageLibrary._map_lun.assert_called_once_with( fake.ISCSI_VOLUME['name'], [fake.ISCSI_CONNECTOR['initiator']], 'iscsi', None) self.zapi_client.get_iscsi_target_details.assert_called_once_with() block_base.NetAppBlockStorageLibrary._get_preferred_target_from_list\ .assert_called_once_with(target_details_list) def test_get_target_details_list(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(target_details_list[0], result) def test_get_preferred_target_from_empty_list(self): target_details_list = [] result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(None, result) def test_get_preferred_target_from_list_with_one_interface_disabled(self): target_details_list = copy.deepcopy(fake.ISCSI_TARGET_DETAILS_LIST) target_details_list[0]['interface-enabled'] = 'false' result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(target_details_list[1], result) def test_get_preferred_target_from_list_with_all_interfaces_disabled(self): target_details_list = copy.deepcopy(fake.ISCSI_TARGET_DETAILS_LIST) for target in target_details_list: target['interface-enabled'] = 'false' result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(target_details_list[0], result) def test_get_preferred_target_from_list_with_filter(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST filter = [ target_detail['address'] for target_detail in target_details_list[1:] ] result = self.library._get_preferred_target_from_list( target_details_list, filter) self.assertEqual(target_details_list[1], result) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_setup_error_invalid_lun_os(self): self.library.configuration.netapp_lun_ostype = 'unknown' self.library.do_setup(mock.Mock()) self.assertRaises(exception.NetAppDriverException, self.library.check_for_setup_error) msg = _("Invalid value for NetApp configuration" " option netapp_lun_ostype.") block_base.LOG.error.assert_called_once_with(msg) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_setup_error_invalid_host_type(self): self.library.configuration.netapp_lun_ostype = 'linux' self.library.configuration.netapp_host_type = 'future_os' self.library.do_setup(mock.Mock()) self.assertRaises(exception.NetAppDriverException, self.library.check_for_setup_error) msg = _("Invalid value for NetApp configuration" " option netapp_host_type.") block_base.LOG.error.assert_called_once_with(msg) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) def test_check_for_setup_error_both_config(self): self.library.configuration.netapp_lun_ostype = 'linux' self.library.configuration.netapp_host_type = 'linux' self.library.do_setup(mock.Mock()) self.zapi_client.get_lun_list.return_value = ['lun1'] self.library._extract_and_populate_luns = mock.Mock() self.library.check_for_setup_error() self.library._extract_and_populate_luns.assert_called_once_with( ['lun1']) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) def test_check_for_setup_error_no_os_host(self): self.library.configuration.netapp_lun_ostype = None self.library.configuration.netapp_host_type = None self.library.do_setup(mock.Mock()) self.zapi_client.get_lun_list.return_value = ['lun1'] self.library._extract_and_populate_luns = mock.Mock() self.library.check_for_setup_error() self.library._extract_and_populate_luns.assert_called_once_with( ['lun1']) def test_delete_volume(self): mock_get_lun_attr = self.mock_object(self.library, '_get_lun_attr') mock_get_lun_attr.return_value = fake.LUN_METADATA self.library.zapi_client = mock.Mock() self.library.lun_table = fake.LUN_TABLE self.library.delete_volume(fake.VOLUME) mock_get_lun_attr.assert_called_once_with(fake.LUN_NAME, 'metadata') self.library.zapi_client.destroy_lun.assert_called_once_with(fake.PATH) def test_delete_volume_no_metadata(self): self.mock_object(self.library, '_get_lun_attr', mock.Mock(return_value=None)) self.library.zapi_client = mock.Mock() self.mock_object(self.library, 'zapi_client') self.library.delete_volume(fake.VOLUME) self.library._get_lun_attr.assert_called_once_with( fake.LUN_NAME, 'metadata') self.assertEqual(0, self.library.zapi_client.destroy_lun.call_count) self.assertEqual( 0, self.zapi_client.mark_qos_policy_group_for_deletion.call_count) def test_clone_source_to_destination(self): self.mock_object(na_utils, 'get_volume_extra_specs', mock.Mock(return_value=fake.EXTRA_SPECS)) self.mock_object(self.library, '_setup_qos_for_volume', mock.Mock(return_value=fake.QOS_POLICY_GROUP_INFO)) self.mock_object(self.library, '_clone_lun') self.mock_object(self.library, 'extend_volume') self.mock_object(self.library, 'delete_volume') self.mock_object(self.library, '_mark_qos_policy_group_for_deletion') self.library.lun_space_reservation = 'false' self.library._clone_source_to_destination(fake.CLONE_SOURCE, fake.CLONE_DESTINATION) na_utils.get_volume_extra_specs.assert_called_once_with( fake.CLONE_DESTINATION) self.library._setup_qos_for_volume.assert_called_once_with( fake.CLONE_DESTINATION, fake.EXTRA_SPECS) self.library._clone_lun.assert_called_once_with( fake.CLONE_SOURCE_NAME, fake.CLONE_DESTINATION_NAME, space_reserved='false', qos_policy_group_name=fake.QOS_POLICY_GROUP_NAME) self.library.extend_volume.assert_called_once_with( fake.CLONE_DESTINATION, fake.CLONE_DESTINATION_SIZE, qos_policy_group_name=fake.QOS_POLICY_GROUP_NAME) self.assertEqual(0, self.library.delete_volume.call_count) self.assertEqual( 0, self.library._mark_qos_policy_group_for_deletion.call_count) def test_clone_source_to_destination_exception_path(self): self.mock_object(na_utils, 'get_volume_extra_specs', mock.Mock(return_value=fake.EXTRA_SPECS)) self.mock_object(self.library, '_setup_qos_for_volume', mock.Mock(return_value=fake.QOS_POLICY_GROUP_INFO)) self.mock_object(self.library, '_clone_lun') self.mock_object(self.library, 'extend_volume', mock.Mock(side_effect=Exception)) self.mock_object(self.library, 'delete_volume') self.mock_object(self.library, '_mark_qos_policy_group_for_deletion') self.library.lun_space_reservation = 'true' self.assertRaises(exception.VolumeBackendAPIException, self.library._clone_source_to_destination, fake.CLONE_SOURCE, fake.CLONE_DESTINATION) na_utils.get_volume_extra_specs.assert_called_once_with( fake.CLONE_DESTINATION) self.library._setup_qos_for_volume.assert_called_once_with( fake.CLONE_DESTINATION, fake.EXTRA_SPECS) self.library._clone_lun.assert_called_once_with( fake.CLONE_SOURCE_NAME, fake.CLONE_DESTINATION_NAME, space_reserved='true', qos_policy_group_name=fake.QOS_POLICY_GROUP_NAME) self.library.extend_volume.assert_called_once_with( fake.CLONE_DESTINATION, fake.CLONE_DESTINATION_SIZE, qos_policy_group_name=fake.QOS_POLICY_GROUP_NAME) self.assertEqual(1, self.library.delete_volume.call_count) self.assertEqual( 1, self.library._mark_qos_policy_group_for_deletion.call_count) def test_create_lun(self): self.assertRaises(NotImplementedError, self.library._create_lun, fake.VOLUME_ID, fake.LUN_ID, fake.SIZE, fake.LUN_METADATA) def test_clone_lun(self): self.assertRaises(NotImplementedError, self.library._clone_lun, fake.VOLUME_ID, 'new-' + fake.VOLUME_ID) def test_create_volume_from_snapshot(self): mock_do_clone = self.mock_object(self.library, '_clone_source_to_destination') source = { 'name': fake.SNAPSHOT['name'], 'size': fake.SNAPSHOT['volume_size'] } self.library.create_volume_from_snapshot(fake.VOLUME, fake.SNAPSHOT) mock_do_clone.assert_has_calls([mock.call(source, fake.VOLUME)]) def test_create_cloned_volume(self): fake_lun = block_base.NetAppLun(fake.LUN_HANDLE, fake.LUN_ID, fake.LUN_SIZE, fake.LUN_METADATA) mock_get_lun_from_table = self.mock_object(self.library, '_get_lun_from_table') mock_get_lun_from_table.return_value = fake_lun mock_do_clone = self.mock_object(self.library, '_clone_source_to_destination') source = {'name': fake_lun.name, 'size': fake.VOLUME_REF['size']} self.library.create_cloned_volume(fake.VOLUME, fake.VOLUME_REF) mock_do_clone.assert_has_calls([mock.call(source, fake.VOLUME)])
class NetAppBlockStorageLibraryTestCase(test.TestCase): def setUp(self): super(NetAppBlockStorageLibraryTestCase, self).setUp() kwargs = {'configuration': mock.Mock()} self.library = block_lib('driver', 'protocol', **kwargs) self.library.zapi_client = mock.Mock() self.zapi_client = self.library.zapi_client self.mock_request = mock.Mock() def tearDown(self): super(NetAppBlockStorageLibraryTestCase, self).tearDown() @mock.patch.object(block_lib, '_get_lun_attr', mock.Mock(return_value={'Volume': 'vol1'})) def test_get_pool(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(pool, 'vol1') @mock.patch.object(block_lib, '_get_lun_attr', mock.Mock(return_value=None)) def test_get_pool_no_metadata(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(pool, None) @mock.patch.object(block_lib, '_get_lun_attr', mock.Mock(return_value=dict())) def test_get_pool_volume_unknown(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(pool, None) @mock.patch.object(block_lib, '_create_lun', mock.Mock()) @mock.patch.object(block_lib, '_create_lun_handle', mock.Mock()) @mock.patch.object(block_lib, '_add_lun_to_table', mock.Mock()) @mock.patch.object(na_utils, 'get_volume_extra_specs', mock.Mock(return_value=None)) @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_create_volume(self): self.library.zapi_client.get_lun_by_args.return_value = ['lun'] self.library.create_volume({ 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend#vol1' }) self.library._create_lun.assert_called_once_with( 'vol1', 'lun1', 107374182400, mock.ANY, None) self.assertEqual(0, block_base.LOG.warning.call_count) def test_create_volume_no_pool_provided_by_scheduler(self): self.assertRaises( exception.InvalidHost, self.library.create_volume, { 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend' }) # missing pool @mock.patch.object(block_lib, '_get_lun_attr') @mock.patch.object(block_lib, '_get_or_create_igroup') def test_map_lun(self, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' mock_get_lun_attr.return_value = {'Path': fake.LUN1, 'OsType': os} mock_get_or_create_igroup.return_value = fake.IGROUP1_NAME self.zapi_client.map_lun.return_value = '1' lun_id = self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) self.assertEqual(lun_id, '1') mock_get_or_create_igroup.assert_called_once_with( fake.FC_FORMATTED_INITIATORS, protocol, os) self.zapi_client.map_lun.assert_called_once_with(fake.LUN1, fake.IGROUP1_NAME, lun_id=None) @mock.patch.object(block_lib, '_get_lun_attr') @mock.patch.object(block_lib, '_get_or_create_igroup') @mock.patch.object(block_lib, '_find_mapped_lun_igroup') def test_map_lun_preexisting(self, mock_find_mapped_lun_igroup, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' mock_get_lun_attr.return_value = {'Path': fake.LUN1, 'OsType': os} mock_get_or_create_igroup.return_value = fake.IGROUP1_NAME mock_find_mapped_lun_igroup.return_value = (fake.IGROUP1_NAME, '2') self.zapi_client.map_lun.side_effect = NaApiError lun_id = self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) self.assertEqual(lun_id, '2') mock_find_mapped_lun_igroup.assert_called_once_with( fake.LUN1, fake.FC_FORMATTED_INITIATORS) @mock.patch.object(block_lib, '_get_lun_attr') @mock.patch.object(block_lib, '_get_or_create_igroup') @mock.patch.object(block_lib, '_find_mapped_lun_igroup') def test_map_lun_api_error(self, mock_find_mapped_lun_igroup, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' mock_get_lun_attr.return_value = {'Path': fake.LUN1, 'OsType': os} mock_get_or_create_igroup.return_value = fake.IGROUP1_NAME mock_find_mapped_lun_igroup.return_value = (None, None) self.zapi_client.map_lun.side_effect = NaApiError self.assertRaises(NaApiError, self.library._map_lun, 'fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) @mock.patch.object(block_lib, '_find_mapped_lun_igroup') def test_unmap_lun(self, mock_find_mapped_lun_igroup): mock_find_mapped_lun_igroup.return_value = (fake.IGROUP1_NAME, 1) self.library._unmap_lun(fake.LUN1, fake.FC_FORMATTED_INITIATORS) self.zapi_client.unmap_lun.assert_called_once_with( fake.LUN1, fake.IGROUP1_NAME) def test_find_mapped_lun_igroup(self): self.assertRaises(NotImplementedError, self.library._find_mapped_lun_igroup, fake.LUN1, fake.FC_FORMATTED_INITIATORS) def test_has_luns_mapped_to_initiators(self): self.zapi_client.has_luns_mapped_to_initiators.return_value = True self.assertTrue( self.library._has_luns_mapped_to_initiators( fake.FC_FORMATTED_INITIATORS)) self.zapi_client.has_luns_mapped_to_initiators.assert_called_once_with( fake.FC_FORMATTED_INITIATORS) def test_get_or_create_igroup_preexisting(self): self.zapi_client.get_igroup_by_initiators.return_value = [fake.IGROUP1] igroup_name = self.library._get_or_create_igroup( fake.FC_FORMATTED_INITIATORS, 'fcp', 'linux') self.assertEqual(igroup_name, fake.IGROUP1_NAME) self.zapi_client.get_igroup_by_initiators.assert_called_once_with( fake.FC_FORMATTED_INITIATORS) @mock.patch.object(uuid, 'uuid4', mock.Mock(return_value=fake.UUID1)) def test_get_or_create_igroup_none_preexisting(self): self.zapi_client.get_igroup_by_initiators.return_value = [] igroup_name = self.library._get_or_create_igroup( fake.FC_FORMATTED_INITIATORS, 'fcp', 'linux') self.assertEqual(igroup_name, 'openstack-' + fake.UUID1) self.zapi_client.create_igroup.assert_called_once_with( igroup_name, 'fcp', 'linux') self.assertEqual(len(fake.FC_FORMATTED_INITIATORS), self.zapi_client.add_igroup_initiator.call_count) def test_get_fc_target_wwpns(self): self.assertRaises(NotImplementedError, self.library._get_fc_target_wwpns) @mock.patch.object(block_lib, '_build_initiator_target_map') @mock.patch.object(block_lib, '_map_lun') def test_initialize_connection_fc(self, mock_map_lun, mock_build_initiator_target_map): self.maxDiff = None mock_map_lun.return_value = '1' mock_build_initiator_target_map.return_value = (fake.FC_TARGET_WWPNS, fake.FC_I_T_MAP, 4) target_info = self.library.initialize_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO) mock_map_lun.assert_called_once_with('fake_volume', fake.FC_FORMATTED_INITIATORS, 'fcp', None) @mock.patch.object(block_lib, '_build_initiator_target_map') @mock.patch.object(block_lib, '_map_lun') def test_initialize_connection_fc_no_wwpns( self, mock_map_lun, mock_build_initiator_target_map): mock_map_lun.return_value = '1' mock_build_initiator_target_map.return_value = (None, None, 0) self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_fc, fake.FC_VOLUME, fake.FC_CONNECTOR) @mock.patch.object(block_lib, '_has_luns_mapped_to_initiators') @mock.patch.object(block_lib, '_unmap_lun') @mock.patch.object(block_lib, '_get_lun_attr') def test_terminate_connection_fc(self, mock_get_lun_attr, mock_unmap_lun, mock_has_luns_mapped_to_initiators): mock_get_lun_attr.return_value = {'Path': fake.LUN1} mock_unmap_lun.return_value = None mock_has_luns_mapped_to_initiators.return_value = True target_info = self.library.terminate_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO_EMPTY) mock_unmap_lun.assert_called_once_with(fake.LUN1, fake.FC_FORMATTED_INITIATORS) @mock.patch.object(block_lib, '_build_initiator_target_map') @mock.patch.object(block_lib, '_has_luns_mapped_to_initiators') @mock.patch.object(block_lib, '_unmap_lun') @mock.patch.object(block_lib, '_get_lun_attr') def test_terminate_connection_fc_no_more_luns( self, mock_get_lun_attr, mock_unmap_lun, mock_has_luns_mapped_to_initiators, mock_build_initiator_target_map): mock_get_lun_attr.return_value = {'Path': fake.LUN1} mock_unmap_lun.return_value = None mock_has_luns_mapped_to_initiators.return_value = False mock_build_initiator_target_map.return_value = (fake.FC_TARGET_WWPNS, fake.FC_I_T_MAP, 4) target_info = self.library.terminate_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO_UNMAP) @mock.patch.object(block_lib, '_get_fc_target_wwpns') def test_build_initiator_target_map_no_lookup_service( self, mock_get_fc_target_wwpns): self.library.lookup_service = None mock_get_fc_target_wwpns.return_value = fake.FC_FORMATTED_TARGET_WWPNS (target_wwpns, init_targ_map, num_paths) = \ self.library._build_initiator_target_map(fake.FC_CONNECTOR) self.assertSetEqual(set(fake.FC_TARGET_WWPNS), set(target_wwpns)) self.assertDictEqual(fake.FC_I_T_MAP_COMPLETE, init_targ_map) self.assertEqual(0, num_paths) @mock.patch.object(block_lib, '_get_fc_target_wwpns') def test_build_initiator_target_map_with_lookup_service( self, mock_get_fc_target_wwpns): self.library.lookup_service = mock.Mock() self.library.lookup_service.get_device_mapping_from_network.\ return_value = fake.FC_FABRIC_MAP mock_get_fc_target_wwpns.return_value = fake.FC_FORMATTED_TARGET_WWPNS (target_wwpns, init_targ_map, num_paths) = \ self.library._build_initiator_target_map(fake.FC_CONNECTOR) self.assertSetEqual(set(fake.FC_TARGET_WWPNS), set(target_wwpns)) self.assertDictEqual(fake.FC_I_T_MAP, init_targ_map) self.assertEqual(4, num_paths) @mock.patch.object(block_lib, '_create_lun', mock.Mock()) @mock.patch.object(block_lib, '_create_lun_handle', mock.Mock()) @mock.patch.object(block_lib, '_add_lun_to_table', mock.Mock()) @mock.patch.object(na_utils, 'LOG', mock.Mock()) @mock.patch.object(na_utils, 'get_volume_extra_specs', mock.Mock(return_value={'netapp:raid_type': 'raid4'})) def test_create_volume_obsolete_extra_spec(self): self.library.zapi_client.get_lun_by_args.return_value = ['lun'] self.library.create_volume({ 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend#vol1' }) warn_msg = 'Extra spec netapp:raid_type is obsolete. ' \ 'Use netapp_raid_type instead.' na_utils.LOG.warning.assert_called_once_with(warn_msg) @mock.patch.object(block_lib, '_create_lun', mock.Mock()) @mock.patch.object(block_lib, '_create_lun_handle', mock.Mock()) @mock.patch.object(block_lib, '_add_lun_to_table', mock.Mock()) @mock.patch.object(na_utils, 'LOG', mock.Mock()) @mock.patch.object( na_utils, 'get_volume_extra_specs', mock.Mock(return_value={'netapp_thick_provisioned': 'true'})) def test_create_volume_deprecated_extra_spec(self): self.library.zapi_client.get_lun_by_args.return_value = ['lun'] self.library.create_volume({ 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend#vol1' }) warn_msg = 'Extra spec netapp_thick_provisioned is deprecated. ' \ 'Use netapp_thin_provisioned instead.' na_utils.LOG.warning.assert_called_once_with(warn_msg) @mock.patch.object(na_utils, 'check_flags') def test_do_setup(self, mock_check_flags): self.library.do_setup(mock.Mock()) self.assertTrue(mock_check_flags.called) def test_get_existing_vol_manage_missing_id_path(self): self.assertRaises(exception.ManageExistingInvalidReference, self.library._get_existing_vol_with_manage_ref, {}) def test_get_existing_vol_manage_not_found(self): self.zapi_client.get_lun_by_args.return_value = [] self.assertRaises(exception.ManageExistingInvalidReference, self.library._get_existing_vol_with_manage_ref, { 'source-id': 'src_id', 'source-name': 'lun_path' }) self.assertEqual(1, self.zapi_client.get_lun_by_args.call_count) @mock.patch.object(block_lib, '_extract_lun_info', mock.Mock(return_value=block_base.NetAppLun( 'lun0', 'lun0', '3', {'UUID': 'src_id'}))) def test_get_existing_vol_manage_lun(self): self.zapi_client.get_lun_by_args.return_value = ['lun0', 'lun1'] lun = self.library._get_existing_vol_with_manage_ref({ 'source-id': 'src_id', 'path': 'lun_path' }) self.assertEqual(1, self.zapi_client.get_lun_by_args.call_count) self.library._extract_lun_info.assert_called_once_with('lun0') self.assertEqual('lun0', lun.name) @mock.patch.object(block_lib, '_get_existing_vol_with_manage_ref', mock.Mock(return_value=block_base.NetAppLun( 'handle', 'name', '1073742824', {}))) def test_manage_existing_get_size(self): size = self.library.manage_existing_get_size({'id': 'vol_id'}, {'ref': 'ref'}) self.assertEqual(2, size) self.library._get_existing_vol_with_manage_ref.assert_called_once_with( {'ref': 'ref'}) @mock.patch.object(block_base.LOG, 'info') def test_unmanage(self, log): mock_lun = block_base.NetAppLun('handle', 'name', '1', { 'Path': 'p', 'UUID': 'uuid' }) self.library._get_lun_from_table = mock.Mock(return_value=mock_lun) self.library.unmanage({'name': 'vol'}) self.library._get_lun_from_table.assert_called_once_with('vol') self.assertEqual(1, log.call_count) def test_manage_existing_lun_same_name(self): mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Path': '/vol/vol1/name'}) self.library._get_existing_vol_with_manage_ref = mock.Mock( return_value=mock_lun) self.library._check_volume_type_for_lun = mock.Mock() self.library._add_lun_to_table = mock.Mock() self.zapi_client.move_lun = mock.Mock() self.library.manage_existing({'name': 'name'}, {'ref': 'ref'}) self.library._get_existing_vol_with_manage_ref.assert_called_once_with( {'ref': 'ref'}) self.assertEqual(1, self.library._check_volume_type_for_lun.call_count) self.assertEqual(1, self.library._add_lun_to_table.call_count) self.assertEqual(0, self.zapi_client.move_lun.call_count) def test_manage_existing_lun_new_path(self): mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Path': '/vol/vol1/name'}) self.library._get_existing_vol_with_manage_ref = mock.Mock( return_value=mock_lun) self.library._check_volume_type_for_lun = mock.Mock() self.library._add_lun_to_table = mock.Mock() self.zapi_client.move_lun = mock.Mock() self.library.manage_existing({'name': 'volume'}, {'ref': 'ref'}) self.assertEqual( 2, self.library._get_existing_vol_with_manage_ref.call_count) self.assertEqual(1, self.library._check_volume_type_for_lun.call_count) self.assertEqual(1, self.library._add_lun_to_table.call_count) self.zapi_client.move_lun.assert_called_once_with( '/vol/vol1/name', '/vol/vol1/volume') def test_check_vol_type_for_lun(self): self.assertRaises(NotImplementedError, self.library._check_volume_type_for_lun, 'vol', 'lun', 'existing_ref') def test_is_lun_valid_on_storage(self): self.assertTrue(self.library._is_lun_valid_on_storage('lun'))
class NetAppBlockStorageLibraryTestCase(test.TestCase): def setUp(self): super(NetAppBlockStorageLibraryTestCase, self).setUp() kwargs = {'configuration': mock.Mock()} self.library = block_base.NetAppBlockStorageLibrary( 'driver', 'protocol', **kwargs) self.library.zapi_client = mock.Mock() self.zapi_client = self.library.zapi_client self.mock_request = mock.Mock() def tearDown(self): super(NetAppBlockStorageLibraryTestCase, self).tearDown() @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr', mock.Mock(return_value={'Volume': 'vol1'})) def test_get_pool(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(pool, 'vol1') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr', mock.Mock(return_value=None)) def test_get_pool_no_metadata(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(pool, None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr', mock.Mock(return_value=dict())) def test_get_pool_volume_unknown(self): pool = self.library.get_pool({'name': 'volume-fake-uuid'}) self.assertEqual(pool, None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_create_lun', mock.Mock()) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_create_lun_handle', mock.Mock()) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_add_lun_to_table', mock.Mock()) @mock.patch.object(na_utils, 'get_volume_extra_specs', mock.Mock(return_value=None)) @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_create_volume(self): self.library.zapi_client.get_lun_by_args.return_value = ['lun'] self.library.create_volume({ 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend#vol1' }) self.library._create_lun.assert_called_once_with( 'vol1', 'lun1', 107374182400, mock.ANY, None) self.assertEqual(0, block_base.LOG.warning.call_count) def test_create_volume_no_pool_provided_by_scheduler(self): self.assertRaises( exception.InvalidHost, self.library.create_volume, { 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend' }) # missing pool @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') def test_map_lun(self, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' self.library.host_type = 'linux' mock_get_lun_attr.return_value = {'Path': fake.LUN1, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') self.zapi_client.map_lun.return_value = '1' lun_id = self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) self.assertEqual(lun_id, '1') mock_get_or_create_igroup.assert_called_once_with( fake.FC_FORMATTED_INITIATORS, protocol, os) self.zapi_client.map_lun.assert_called_once_with(fake.LUN1, fake.IGROUP1_NAME, lun_id=None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_map_lun_mismatch_host_os(self, mock_get_or_create_igroup, mock_get_lun_attr): os = 'windows' protocol = 'fcp' self.library.host_type = 'linux' mock_get_lun_attr.return_value = {'Path': fake.LUN1, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) mock_get_or_create_igroup.assert_called_once_with( fake.FC_FORMATTED_INITIATORS, protocol, self.library.host_type) self.zapi_client.map_lun.assert_called_once_with(fake.LUN1, fake.IGROUP1_NAME, lun_id=None) self.assertEqual(1, block_base.LOG.warning.call_count) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_find_mapped_lun_igroup') def test_map_lun_preexisting(self, mock_find_mapped_lun_igroup, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' mock_get_lun_attr.return_value = {'Path': fake.LUN1, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') mock_find_mapped_lun_igroup.return_value = (fake.IGROUP1_NAME, '2') self.zapi_client.map_lun.side_effect = netapp_api.NaApiError lun_id = self.library._map_lun('fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) self.assertEqual(lun_id, '2') mock_find_mapped_lun_igroup.assert_called_once_with( fake.LUN1, fake.FC_FORMATTED_INITIATORS) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_or_create_igroup') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_find_mapped_lun_igroup') def test_map_lun_api_error(self, mock_find_mapped_lun_igroup, mock_get_or_create_igroup, mock_get_lun_attr): os = 'linux' protocol = 'fcp' mock_get_lun_attr.return_value = {'Path': fake.LUN1, 'OsType': os} mock_get_or_create_igroup.return_value = (fake.IGROUP1_NAME, os, 'iscsi') mock_find_mapped_lun_igroup.return_value = (None, None) self.zapi_client.map_lun.side_effect = netapp_api.NaApiError self.assertRaises(netapp_api.NaApiError, self.library._map_lun, 'fake_volume', fake.FC_FORMATTED_INITIATORS, protocol, None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_find_mapped_lun_igroup') def test_unmap_lun(self, mock_find_mapped_lun_igroup): mock_find_mapped_lun_igroup.return_value = (fake.IGROUP1_NAME, 1) self.library._unmap_lun(fake.LUN1, fake.FC_FORMATTED_INITIATORS) self.zapi_client.unmap_lun.assert_called_once_with( fake.LUN1, fake.IGROUP1_NAME) def test_find_mapped_lun_igroup(self): self.assertRaises(NotImplementedError, self.library._find_mapped_lun_igroup, fake.LUN1, fake.FC_FORMATTED_INITIATORS) def test_has_luns_mapped_to_initiators(self): self.zapi_client.has_luns_mapped_to_initiators.return_value = True self.assertTrue( self.library._has_luns_mapped_to_initiators( fake.FC_FORMATTED_INITIATORS)) self.zapi_client.has_luns_mapped_to_initiators.assert_called_once_with( fake.FC_FORMATTED_INITIATORS) def test_get_or_create_igroup_preexisting(self): self.zapi_client.get_igroup_by_initiators.return_value = [fake.IGROUP1] self.library._create_igroup_add_initiators = mock.Mock() igroup_name, host_os, ig_type = self.library._get_or_create_igroup( fake.FC_FORMATTED_INITIATORS, 'fcp', 'linux') self.assertEqual(fake.IGROUP1_NAME, igroup_name) self.assertEqual('linux', host_os) self.assertEqual('fcp', ig_type) self.zapi_client.get_igroup_by_initiators.assert_called_once_with( fake.FC_FORMATTED_INITIATORS) self.assertEqual(0, self.library._create_igroup_add_initiators.call_count) @mock.patch.object(uuid, 'uuid4', mock.Mock(return_value=fake.UUID1)) def test_get_or_create_igroup_none_preexisting(self): """This method also tests _create_igroup_add_initiators.""" self.zapi_client.get_igroup_by_initiators.return_value = [] igroup_name, os, ig_type = self.library._get_or_create_igroup( fake.FC_FORMATTED_INITIATORS, 'fcp', 'linux') self.assertEqual(igroup_name, 'openstack-' + fake.UUID1) self.zapi_client.create_igroup.assert_called_once_with( igroup_name, 'fcp', 'linux') self.assertEqual(len(fake.FC_FORMATTED_INITIATORS), self.zapi_client.add_igroup_initiator.call_count) self.assertEqual('linux', os) self.assertEqual('fcp', ig_type) def test_get_fc_target_wwpns(self): self.assertRaises(NotImplementedError, self.library._get_fc_target_wwpns) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_build_initiator_target_map') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_map_lun') def test_initialize_connection_fc(self, mock_map_lun, mock_build_initiator_target_map): self.maxDiff = None mock_map_lun.return_value = '1' mock_build_initiator_target_map.return_value = (fake.FC_TARGET_WWPNS, fake.FC_I_T_MAP, 4) target_info = self.library.initialize_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO) mock_map_lun.assert_called_once_with('fake_volume', fake.FC_FORMATTED_INITIATORS, 'fcp', None) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_build_initiator_target_map') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_map_lun') def test_initialize_connection_fc_no_wwpns( self, mock_map_lun, mock_build_initiator_target_map): mock_map_lun.return_value = '1' mock_build_initiator_target_map.return_value = (None, None, 0) self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_fc, fake.FC_VOLUME, fake.FC_CONNECTOR) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_has_luns_mapped_to_initiators') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_unmap_lun') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') def test_terminate_connection_fc(self, mock_get_lun_attr, mock_unmap_lun, mock_has_luns_mapped_to_initiators): mock_get_lun_attr.return_value = {'Path': fake.LUN1} mock_unmap_lun.return_value = None mock_has_luns_mapped_to_initiators.return_value = True target_info = self.library.terminate_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO_EMPTY) mock_unmap_lun.assert_called_once_with(fake.LUN1, fake.FC_FORMATTED_INITIATORS) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_build_initiator_target_map') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_has_luns_mapped_to_initiators') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_unmap_lun') @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_lun_attr') def test_terminate_connection_fc_no_more_luns( self, mock_get_lun_attr, mock_unmap_lun, mock_has_luns_mapped_to_initiators, mock_build_initiator_target_map): mock_get_lun_attr.return_value = {'Path': fake.LUN1} mock_unmap_lun.return_value = None mock_has_luns_mapped_to_initiators.return_value = False mock_build_initiator_target_map.return_value = (fake.FC_TARGET_WWPNS, fake.FC_I_T_MAP, 4) target_info = self.library.terminate_connection_fc( fake.FC_VOLUME, fake.FC_CONNECTOR) self.assertDictEqual(target_info, fake.FC_TARGET_INFO_UNMAP) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_fc_target_wwpns') def test_build_initiator_target_map_no_lookup_service( self, mock_get_fc_target_wwpns): self.library.lookup_service = None mock_get_fc_target_wwpns.return_value = fake.FC_FORMATTED_TARGET_WWPNS (target_wwpns, init_targ_map, num_paths) = \ self.library._build_initiator_target_map(fake.FC_CONNECTOR) self.assertSetEqual(set(fake.FC_TARGET_WWPNS), set(target_wwpns)) self.assertDictEqual(fake.FC_I_T_MAP_COMPLETE, init_targ_map) self.assertEqual(0, num_paths) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_fc_target_wwpns') def test_build_initiator_target_map_with_lookup_service( self, mock_get_fc_target_wwpns): self.library.lookup_service = mock.Mock() self.library.lookup_service.get_device_mapping_from_network.\ return_value = fake.FC_FABRIC_MAP mock_get_fc_target_wwpns.return_value = fake.FC_FORMATTED_TARGET_WWPNS (target_wwpns, init_targ_map, num_paths) = \ self.library._build_initiator_target_map(fake.FC_CONNECTOR) self.assertSetEqual(set(fake.FC_TARGET_WWPNS), set(target_wwpns)) self.assertDictEqual(fake.FC_I_T_MAP, init_targ_map) self.assertEqual(4, num_paths) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_create_lun', mock.Mock()) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_create_lun_handle', mock.Mock()) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_add_lun_to_table', mock.Mock()) @mock.patch.object(na_utils, 'LOG', mock.Mock()) @mock.patch.object(na_utils, 'get_volume_extra_specs', mock.Mock(return_value={'netapp:raid_type': 'raid4'})) def test_create_volume_obsolete_extra_spec(self): self.library.zapi_client.get_lun_by_args.return_value = ['lun'] self.library.create_volume({ 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend#vol1' }) warn_msg = 'Extra spec netapp:raid_type is obsolete. ' \ 'Use netapp_raid_type instead.' na_utils.LOG.warning.assert_called_once_with(warn_msg) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_create_lun', mock.Mock()) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_create_lun_handle', mock.Mock()) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_add_lun_to_table', mock.Mock()) @mock.patch.object(na_utils, 'LOG', mock.Mock()) @mock.patch.object( na_utils, 'get_volume_extra_specs', mock.Mock(return_value={'netapp_thick_provisioned': 'true'})) def test_create_volume_deprecated_extra_spec(self): self.library.zapi_client.get_lun_by_args.return_value = ['lun'] self.library.create_volume({ 'name': 'lun1', 'size': 100, 'id': uuid.uuid4(), 'host': 'hostname@backend#vol1' }) warn_msg = 'Extra spec netapp_thick_provisioned is deprecated. ' \ 'Use netapp_thin_provisioned instead.' na_utils.LOG.warning.assert_called_once_with(warn_msg) @mock.patch.object(na_utils, 'check_flags') def test_do_setup_san_configured(self, mock_check_flags): self.library.configuration.netapp_lun_ostype = 'windows' self.library.configuration.netapp_host_type = 'solaris' self.library.do_setup(mock.Mock()) self.assertTrue(mock_check_flags.called) self.assertEqual('windows', self.library.lun_ostype) self.assertEqual('solaris', self.library.host_type) @mock.patch.object(na_utils, 'check_flags') def test_do_setup_san_unconfigured(self, mock_check_flags): self.library.configuration.netapp_lun_ostype = None self.library.configuration.netapp_host_type = None self.library.do_setup(mock.Mock()) self.assertTrue(mock_check_flags.called) self.assertEqual('linux', self.library.lun_ostype) self.assertEqual('linux', self.library.host_type) def test_get_existing_vol_manage_missing_id_path(self): self.assertRaises(exception.ManageExistingInvalidReference, self.library._get_existing_vol_with_manage_ref, {}) def test_get_existing_vol_manage_not_found(self): self.zapi_client.get_lun_by_args.return_value = [] self.assertRaises(exception.ManageExistingInvalidReference, self.library._get_existing_vol_with_manage_ref, { 'source-id': 'src_id', 'source-name': 'lun_path' }) self.assertEqual(1, self.zapi_client.get_lun_by_args.call_count) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_extract_lun_info', mock.Mock(return_value=block_base.NetAppLun( 'lun0', 'lun0', '3', {'UUID': 'src_id'}))) def test_get_existing_vol_manage_lun(self): self.zapi_client.get_lun_by_args.return_value = ['lun0', 'lun1'] lun = self.library._get_existing_vol_with_manage_ref({ 'source-id': 'src_id', 'path': 'lun_path' }) self.assertEqual(1, self.zapi_client.get_lun_by_args.call_count) self.library._extract_lun_info.assert_called_once_with('lun0') self.assertEqual('lun0', lun.name) @mock.patch.object(block_base.NetAppBlockStorageLibrary, '_get_existing_vol_with_manage_ref', mock.Mock(return_value=block_base.NetAppLun( 'handle', 'name', '1073742824', {}))) def test_manage_existing_get_size(self): size = self.library.manage_existing_get_size({'id': 'vol_id'}, {'ref': 'ref'}) self.assertEqual(2, size) self.library._get_existing_vol_with_manage_ref.assert_called_once_with( {'ref': 'ref'}) @mock.patch.object(block_base.LOG, 'info') def test_unmanage(self, log): mock_lun = block_base.NetAppLun('handle', 'name', '1', { 'Path': 'p', 'UUID': 'uuid' }) self.library._get_lun_from_table = mock.Mock(return_value=mock_lun) self.library.unmanage({'name': 'vol'}) self.library._get_lun_from_table.assert_called_once_with('vol') self.assertEqual(1, log.call_count) def test_manage_existing_lun_same_name(self): mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Path': '/vol/vol1/name'}) self.library._get_existing_vol_with_manage_ref = mock.Mock( return_value=mock_lun) self.library._check_volume_type_for_lun = mock.Mock() self.library._add_lun_to_table = mock.Mock() self.zapi_client.move_lun = mock.Mock() self.library.manage_existing({'name': 'name'}, {'ref': 'ref'}) self.library._get_existing_vol_with_manage_ref.assert_called_once_with( {'ref': 'ref'}) self.assertEqual(1, self.library._check_volume_type_for_lun.call_count) self.assertEqual(1, self.library._add_lun_to_table.call_count) self.assertEqual(0, self.zapi_client.move_lun.call_count) def test_manage_existing_lun_new_path(self): mock_lun = block_base.NetAppLun('handle', 'name', '1', {'Path': '/vol/vol1/name'}) self.library._get_existing_vol_with_manage_ref = mock.Mock( return_value=mock_lun) self.library._check_volume_type_for_lun = mock.Mock() self.library._add_lun_to_table = mock.Mock() self.zapi_client.move_lun = mock.Mock() self.library.manage_existing({'name': 'volume'}, {'ref': 'ref'}) self.assertEqual( 2, self.library._get_existing_vol_with_manage_ref.call_count) self.assertEqual(1, self.library._check_volume_type_for_lun.call_count) self.assertEqual(1, self.library._add_lun_to_table.call_count) self.zapi_client.move_lun.assert_called_once_with( '/vol/vol1/name', '/vol/vol1/volume') def test_check_vol_type_for_lun(self): self.assertRaises(NotImplementedError, self.library._check_volume_type_for_lun, 'vol', 'lun', 'existing_ref') def test_is_lun_valid_on_storage(self): self.assertTrue(self.library._is_lun_valid_on_storage('lun')) def test_initialize_connection_iscsi(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = ( target_details_list) self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list', mock.Mock(return_value=target_details_list[1])) self.zapi_client.get_iscsi_service_details.return_value = ( fake.ISCSI_SERVICE_IQN) self.mock_object( na_utils, 'get_iscsi_connection_properties', mock.Mock(return_value=fake.ISCSI_CONNECTION_PROPERTIES)) target_info = self.library.initialize_connection_iscsi( volume, connector) self.assertEqual(fake.ISCSI_CONNECTION_PROPERTIES, target_info) block_base.NetAppBlockStorageLibrary._map_lun.assert_called_once_with( fake.ISCSI_VOLUME['name'], [fake.ISCSI_CONNECTOR['initiator']], 'iscsi', None) self.zapi_client.get_iscsi_target_details.assert_called_once_with() block_base.NetAppBlockStorageLibrary._get_preferred_target_from_list\ .assert_called_once_with( target_details_list) self.zapi_client.get_iscsi_service_details.assert_called_once_with() def test_initialize_connection_iscsi_no_target_list(self): volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = None self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list') self.mock_object( na_utils, 'get_iscsi_connection_properties', mock.Mock(return_value=fake.ISCSI_CONNECTION_PROPERTIES)) self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_iscsi, volume, connector) self.assertEqual( 0, block_base.NetAppBlockStorageLibrary. _get_preferred_target_from_list.call_count) self.assertEqual(0, self.zapi_client.get_iscsi_service_details.call_count) self.assertEqual(0, na_utils.get_iscsi_connection_properties.call_count) def test_initialize_connection_iscsi_no_preferred_target(self): volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = None self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list', mock.Mock(return_value=None)) self.mock_object(na_utils, 'get_iscsi_connection_properties') self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_iscsi, volume, connector) self.assertEqual(0, self.zapi_client.get_iscsi_service_details.call_count) self.assertEqual(0, na_utils.get_iscsi_connection_properties.call_count) def test_initialize_connection_iscsi_no_iscsi_service_details(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST volume = fake.ISCSI_VOLUME connector = fake.ISCSI_CONNECTOR self.mock_object(block_base.NetAppBlockStorageLibrary, '_map_lun', mock.Mock(return_value=fake.ISCSI_LUN['lun_id'])) self.zapi_client.get_iscsi_target_details.return_value = ( target_details_list) self.mock_object(block_base.NetAppBlockStorageLibrary, '_get_preferred_target_from_list', mock.Mock(return_value=target_details_list[1])) self.zapi_client.get_iscsi_service_details.return_value = None self.mock_object(na_utils, 'get_iscsi_connection_properties') self.assertRaises(exception.VolumeBackendAPIException, self.library.initialize_connection_iscsi, volume, connector) block_base.NetAppBlockStorageLibrary._map_lun.assert_called_once_with( fake.ISCSI_VOLUME['name'], [fake.ISCSI_CONNECTOR['initiator']], 'iscsi', None) self.zapi_client.get_iscsi_target_details.assert_called_once_with() block_base.NetAppBlockStorageLibrary._get_preferred_target_from_list\ .assert_called_once_with(target_details_list) def test_get_target_details_list(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(target_details_list[0], result) def test_get_preferred_target_from_empty_list(self): target_details_list = [] result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(None, result) def test_get_preferred_target_from_list_with_one_interface_disabled(self): target_details_list = copy.deepcopy(fake.ISCSI_TARGET_DETAILS_LIST) target_details_list[0]['interface-enabled'] = 'false' result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(target_details_list[1], result) def test_get_preferred_target_from_list_with_all_interfaces_disabled(self): target_details_list = copy.deepcopy(fake.ISCSI_TARGET_DETAILS_LIST) for target in target_details_list: target['interface-enabled'] = 'false' result = self.library._get_preferred_target_from_list( target_details_list) self.assertEqual(target_details_list[0], result) def test_get_preferred_target_from_list_with_filter(self): target_details_list = fake.ISCSI_TARGET_DETAILS_LIST filter = [ target_detail['address'] for target_detail in target_details_list[1:] ] result = self.library._get_preferred_target_from_list( target_details_list, filter) self.assertEqual(target_details_list[1], result) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_setup_error_invalid_lun_os(self): self.library.configuration.netapp_lun_ostype = 'unknown' self.library.do_setup(mock.Mock()) self.assertRaises(exception.NetAppDriverException, self.library.check_for_setup_error) msg = _("Invalid value for NetApp configuration" " option netapp_lun_ostype.") block_base.LOG.error.assert_called_once_with(msg) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) @mock.patch.object(block_base, 'LOG', mock.Mock()) def test_setup_error_invalid_host_type(self): self.library.configuration.netapp_lun_ostype = 'linux' self.library.configuration.netapp_host_type = 'future_os' self.library.do_setup(mock.Mock()) self.assertRaises(exception.NetAppDriverException, self.library.check_for_setup_error) msg = _("Invalid value for NetApp configuration" " option netapp_host_type.") block_base.LOG.error.assert_called_once_with(msg) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) def test_check_for_setup_error_both_config(self): self.library.configuration.netapp_lun_ostype = 'linux' self.library.configuration.netapp_host_type = 'linux' self.library.do_setup(mock.Mock()) self.zapi_client.get_lun_list.return_value = ['lun1'] self.library._extract_and_populate_luns = mock.Mock() self.library.check_for_setup_error() self.library._extract_and_populate_luns.assert_called_once_with( ['lun1']) @mock.patch.object(na_utils, 'check_flags', mock.Mock()) def test_check_for_setup_error_no_os_host(self): self.library.configuration.netapp_lun_ostype = None self.library.configuration.netapp_host_type = None self.library.do_setup(mock.Mock()) self.zapi_client.get_lun_list.return_value = ['lun1'] self.library._extract_and_populate_luns = mock.Mock() self.library.check_for_setup_error() self.library._extract_and_populate_luns.assert_called_once_with( ['lun1'])