cinder/cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax_masking.py

1233 lines
62 KiB
Python

# Copyright (c) 2017-2019 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# 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 copy import deepcopy
from unittest import mock
from cinder import exception
from cinder import test
from cinder.tests.unit.volume.drivers.dell_emc.powermax import (
powermax_data as tpd)
from cinder.tests.unit.volume.drivers.dell_emc.powermax import (
powermax_fake_objects as tpfo)
from cinder.volume.drivers.dell_emc.powermax import common
from cinder.volume.drivers.dell_emc.powermax import masking
from cinder.volume.drivers.dell_emc.powermax import provision
from cinder.volume.drivers.dell_emc.powermax import rest
from cinder.volume.drivers.dell_emc.powermax import utils
from cinder.volume import volume_utils
class PowerMaxMaskingTest(test.TestCase):
def setUp(self):
self.data = tpd.PowerMaxData()
super(PowerMaxMaskingTest, self).setUp()
volume_utils.get_max_over_subscription_ratio = mock.Mock()
self.replication_device = self.data.sync_rep_device
configuration = tpfo.FakeConfiguration(
None, 'MaskingTests', 1, 1, san_ip='1.1.1.1',
san_login='smc', vmax_array=self.data.array, vmax_srp='SRP_1',
san_password='smc', san_api_port=8443,
vmax_port_groups=[self.data.port_group_name_f],
replication_device=self.replication_device)
self._gather_info = common.PowerMaxCommon._gather_info
common.PowerMaxCommon._get_u4p_failover_info = mock.Mock()
common.PowerMaxCommon._gather_info = mock.Mock()
rest.PowerMaxRest._establish_rest_session = mock.Mock(
return_value=tpfo.FakeRequestsSession())
driver = common.PowerMaxCommon(
'iSCSI', self.data.version, configuration=configuration)
driver_fc = common.PowerMaxCommon(
'FC', self.data.version, configuration=configuration)
self.driver = driver
self.driver_fc = driver_fc
self.mask = self.driver.masking
self.extra_specs = deepcopy(self.data.extra_specs)
self.extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_i
self.maskingviewdict = self.driver._populate_masking_dict(
self.data.test_volume, self.data.connector, self.extra_specs)
self.maskingviewdict['extra_specs'] = self.extra_specs
self.maskingviewdict[utils.IS_MULTIATTACH] = False
self.device_id = self.data.device_id
self.volume_name = self.data.volume_details[0]['volume_identifier']
def tearDown(self):
super(PowerMaxMaskingTest, self).tearDown()
common.PowerMaxCommon._gather_info = self._gather_info
def test_sanity_port_group_check_none(self):
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver.masking._sanity_port_group_check,
None, self.data.array)
@mock.patch.object(rest.PowerMaxRest, 'get_portgroup', return_value=None)
def test_sanity_port_group_check_invalid_portgroup(self, mock_pg):
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver.masking._sanity_port_group_check,
None, self.data.array)
@mock.patch.object(rest.PowerMaxRest, 'get_portgroup',
return_value=tpd.PowerMaxData.portgroup)
def test_sanity_port_group_check(self, mock_pg):
self.driver.masking._sanity_port_group_check(
self.data.port_group_name_f, self.data.array)
@mock.patch.object(masking.PowerMaxMasking,
'get_or_create_masking_view_and_map_lun')
def test_setup_masking_view(self, mock_get_or_create_mv):
self.driver.masking.setup_masking_view(
self.data.array, self.data.test_volume,
self.maskingviewdict, self.extra_specs)
mock_get_or_create_mv.assert_called_once()
@mock.patch.object(masking.PowerMaxMasking,
'_check_adding_volume_to_storage_group')
@mock.patch.object(masking.PowerMaxMasking, '_move_vol_from_default_sg',
return_value=None)
@mock.patch.object(masking.PowerMaxMasking, '_get_or_create_masking_view',
side_effect=[None, 'Error in masking view retrieval',
exception.VolumeBackendAPIException])
@mock.patch.object(rest.PowerMaxRest, 'get_element_from_masking_view',
side_effect=[tpd.PowerMaxData.port_group_name_i,
Exception('Exception')])
def test_get_or_create_masking_view_and_map_lun(
self, mock_masking_view_element, mock_masking, mock_move,
mock_add_volume):
rollback_dict = (
self.driver.masking.get_or_create_masking_view_and_map_lun(
self.data.array, self.data.test_volume,
self.maskingviewdict['maskingview_name'],
self.maskingviewdict, self.extra_specs))
self.assertEqual(self.maskingviewdict, rollback_dict)
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver.masking.get_or_create_masking_view_and_map_lun,
self.data.array, self.data.test_volume,
self.maskingviewdict['maskingview_name'],
self.maskingviewdict, self.extra_specs)
self.maskingviewdict['slo'] = None
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver.masking.get_or_create_masking_view_and_map_lun,
self.data.array, self.data.test_volume,
self.maskingviewdict['maskingview_name'],
self.maskingviewdict, self.extra_specs)
@mock.patch.object(masking.PowerMaxMasking,
'_check_adding_volume_to_storage_group',
return_value=None)
@mock.patch.object(
rest.PowerMaxRest, 'move_volume_between_storage_groups',
side_effect=[None, exception.VolumeBackendAPIException(data='')])
@mock.patch.object(rest.PowerMaxRest, 'is_volume_in_storagegroup',
side_effect=[True, False, True])
def test_move_vol_from_default_sg(
self, mock_volume_in_sg, mock_move_volume, mock_add):
msg = None
for x in range(0, 2):
msg = self.driver.masking._move_vol_from_default_sg(
self.data.array, self.device_id, self.volume_name,
self.data.defaultstoragegroup_name,
self.data.storagegroup_name_i, self.extra_specs)
mock_move_volume.assert_called_once()
mock_add.assert_called_once()
self.assertIsNone(msg)
msg = self.driver.masking._move_vol_from_default_sg(
self.data.array, self.device_id, self.volume_name,
self.data.defaultstoragegroup_name,
self.data.storagegroup_name_i, self.extra_specs)
self.assertIsNotNone(msg)
@mock.patch.object(rest.PowerMaxRest, 'modify_storage_group',
return_value=(200, tpfo.tpd.PowerMaxData.job_list[0]))
@mock.patch.object(rest.PowerMaxRest, 'remove_child_sg_from_parent_sg')
@mock.patch.object(masking.PowerMaxMasking, 'get_parent_sg_from_child',
side_effect=[None, tpd.PowerMaxData.parent_sg_f])
@mock.patch.object(
rest.PowerMaxRest, 'get_num_vols_in_sg', side_effect=[2, 1, 1])
def test_move_volume_between_storage_groups(
self, mock_num, mock_parent, mock_rm, mck_mod):
for x in range(0, 3):
self.driver.masking.move_volume_between_storage_groups(
self.data.array, self.data.device_id,
self.data.storagegroup_name_i, self.data.storagegroup_name_f,
self.data.extra_specs)
mock_rm.assert_called_once()
ref_payload = (
{"executionOption": "ASYNCHRONOUS",
"editStorageGroupActionParam": {
"moveVolumeToStorageGroupParam": {
"volumeId": [self.data.device_id],
"storageGroupId": self.data.storagegroup_name_f,
"force": 'false'}}})
mck_mod.assert_called_with(
self.data.array, self.data.storagegroup_name_i, ref_payload)
@mock.patch.object(rest.PowerMaxRest, 'remove_child_sg_from_parent_sg')
@mock.patch.object(masking.PowerMaxMasking, 'get_parent_sg_from_child',
side_effect=[None, tpd.PowerMaxData.parent_sg_f])
@mock.patch.object(rest.PowerMaxRest, 'move_volume_between_storage_groups')
@mock.patch.object(
rest.PowerMaxRest, 'get_num_vols_in_sg', return_value=1)
def test_force_move_volume_between_storage_groups(
self, mock_num, mock_move, mock_parent, mock_rm):
self.driver.masking.move_volume_between_storage_groups(
self.data.array, self.data.device_id,
self.data.storagegroup_name_i, self.data.storagegroup_name_f,
self.data.extra_specs, force=True)
mock_move.assert_called_once_with(
self.data.array, self.data.device_id,
self.data.storagegroup_name_i, self.data.storagegroup_name_f,
self.data.extra_specs, True)
@mock.patch.object(rest.PowerMaxRest, 'get_masking_view',
side_effect=[tpd.PowerMaxData.maskingview,
tpd.PowerMaxData.maskingview, None])
@mock.patch.object(
masking.PowerMaxMasking, '_validate_existing_masking_view',
side_effect=[(tpd.PowerMaxData.maskingview[1]['storageGroupId'],
None), (None, 'Error Message')])
@mock.patch.object(masking.PowerMaxMasking, '_create_new_masking_view',
return_value=None)
def test_get_or_create_masking_view(self, mock_create_mv, mock_validate_mv,
mock_get_mv):
for x in range(0, 3):
self.driver.masking._get_or_create_masking_view(
self.data.array, self.maskingviewdict,
self.data.defaultstoragegroup_name, self.extra_specs)
mock_create_mv.assert_called_once()
@mock.patch.object(
masking.PowerMaxMasking, '_get_or_create_initiator_group',
side_effect=[(None, 'Initiator group error'), (None, None),
(None, None), (None, None), (None, None),
(None, None), (None, None), (None, None)])
@mock.patch.object(
masking.PowerMaxMasking, '_get_or_create_storage_group',
side_effect=['Storage group not found', None,
'Storage group not found', 'Storage group not found',
None, None, None, None, None, None, None])
@mock.patch.object(
masking.PowerMaxMasking, '_move_vol_from_default_sg',
side_effect=['Storage group error', None, 'Storage group error',
None])
@mock.patch.object(
masking.PowerMaxMasking, 'create_masking_view', return_value=None)
def test_create_new_masking_view(
self, mock_create_mv, mock_move, mock_create_SG, mock_create_IG):
for x in range(0, 6):
self.driver.masking._create_new_masking_view(
self.data.array, self.maskingviewdict,
self.maskingviewdict['maskingview_name'],
self.data.defaultstoragegroup_name, self.extra_specs)
mock_create_mv.assert_called_once()
@mock.patch.object(
masking.PowerMaxMasking, '_check_existing_storage_group',
side_effect=[(tpd.PowerMaxData.storagegroup_name_i, None),
(tpd.PowerMaxData.storagegroup_name_i, None),
(None, 'Error Checking existing storage group')])
@mock.patch.object(
rest.PowerMaxRest, 'get_element_from_masking_view',
return_value=tpd.PowerMaxData.port_group_name_i)
@mock.patch.object(
masking.PowerMaxMasking, '_check_port_group',
side_effect=[(None, None), (None, 'Error checking pg')])
@mock.patch.object(
masking.PowerMaxMasking, '_check_existing_initiator_group',
return_value=(tpd.PowerMaxData.initiatorgroup_name_i, None))
def test_validate_existing_masking_view(
self, mock_check_ig, mock_check_pg, mock_get_mv_element,
mock_check_sg):
for x in range(0, 3):
self.driver.masking._validate_existing_masking_view(
self.data.array, self.maskingviewdict,
self.maskingviewdict['maskingview_name'],
self.data.defaultstoragegroup_name, self.extra_specs)
self.assertEqual(3, mock_check_sg.call_count)
mock_get_mv_element.assert_called_with(
self.data.array, self.maskingviewdict['maskingview_name'],
portgroup=True)
mock_check_ig.assert_called_once()
@mock.patch.object(
rest.PowerMaxRest, 'get_storage_group',
side_effect=[tpd.PowerMaxData.storagegroup_name_i, None,
tpd.PowerMaxData.storagegroup_name_i])
@mock.patch.object(
provision.PowerMaxProvision, 'create_storage_group',
side_effect=[tpd.PowerMaxData.storagegroup_name_i, None])
def test_get_or_create_storage_group(self, mock_sg, mock_get_sg):
for x in range(0, 2):
self.driver.masking._get_or_create_storage_group(
self.data.array, self.maskingviewdict,
self.data.storagegroup_name_i, self.extra_specs)
self.assertEqual(3, mock_get_sg.call_count)
self.assertEqual(1, mock_sg.call_count)
@mock.patch.object(
rest.PowerMaxRest, 'get_storage_group',
side_effect=[None, tpd.PowerMaxData.storagegroup_name_i])
@mock.patch.object(
provision.PowerMaxProvision, 'create_storage_group',
side_effect=[tpd.PowerMaxData.storagegroup_name_i])
def test_get_or_create_storage_group_is_parent(self, mock_sg, mock_get_sg):
self.driver.masking._get_or_create_storage_group(
self.data.array, self.maskingviewdict,
self.data.storagegroup_name_i, self.extra_specs, True)
self.assertEqual(2, mock_get_sg.call_count)
self.assertEqual(1, mock_sg.call_count)
@mock.patch.object(masking.PowerMaxMasking, '_move_vol_from_default_sg',
return_value=None)
@mock.patch.object(masking.PowerMaxMasking, '_get_or_create_storage_group',
return_value=None)
@mock.patch.object(rest.PowerMaxRest, 'get_element_from_masking_view',
return_value=tpd.PowerMaxData.parent_sg_i)
@mock.patch.object(rest.PowerMaxRest, 'is_child_sg_in_parent_sg',
side_effect=[True, False])
@mock.patch.object(masking.PowerMaxMasking,
'_check_add_child_sg_to_parent_sg', return_value=None)
def test_check_existing_storage_group_success(
self, mock_add_sg, mock_is_child, mock_get_mv_element,
mock_create_sg, mock_move):
masking_view_dict = deepcopy(self.data.masking_view_dict)
masking_view_dict['extra_specs'] = self.data.extra_specs
with mock.patch.object(
self.driver.rest, 'get_storage_group',
side_effect=[tpd.PowerMaxData.parent_sg_i,
tpd.PowerMaxData.storagegroup_name_i]):
_, msg = (self.driver.masking._check_existing_storage_group(
self.data.array, self.maskingviewdict['maskingview_name'],
self.data.defaultstoragegroup_name, masking_view_dict,
self.data.extra_specs))
self.assertIsNone(msg)
mock_create_sg.assert_not_called()
with mock.patch.object(self.driver.rest, 'get_storage_group',
side_effect=[
tpd.PowerMaxData.parent_sg_i, None]):
_, msg = (self.driver.masking._check_existing_storage_group(
self.data.array, self.maskingviewdict['maskingview_name'],
self.data.defaultstoragegroup_name, masking_view_dict,
self.data.extra_specs))
self.assertIsNone(msg)
mock_create_sg.assert_called_once_with(
self.data.array, masking_view_dict,
tpd.PowerMaxData.storagegroup_name_f,
self.data.extra_specs)
@mock.patch.object(masking.PowerMaxMasking, '_move_vol_from_default_sg',
side_effect=[None, 'Error Message'])
@mock.patch.object(rest.PowerMaxRest, 'is_child_sg_in_parent_sg',
side_effect=[True, False, False])
@mock.patch.object(rest.PowerMaxRest, 'get_element_from_masking_view',
return_value=tpd.PowerMaxData.parent_sg_i)
@mock.patch.object(rest.PowerMaxRest, 'get_storage_group',
side_effect=[
None, tpd.PowerMaxData.parent_sg_i, None,
tpd.PowerMaxData.parent_sg_i, None,
tpd.PowerMaxData.parent_sg_i, None])
def test_check_existing_storage_group_failed(
self, mock_get_sg, mock_get_mv_element, mock_child, mock_move):
masking_view_dict = deepcopy(self.data.masking_view_dict)
masking_view_dict['extra_specs'] = self.data.extra_specs
for x in range(0, 4):
_, msg = (self.driver.masking._check_existing_storage_group(
self.data.array, self.maskingviewdict['maskingview_name'],
self.data.defaultstoragegroup_name, masking_view_dict,
self.data.extra_specs))
self.assertIsNotNone(msg)
self.assertEqual(7, mock_get_sg.call_count)
self.assertEqual(1, mock_move.call_count)
@mock.patch.object(
rest.PowerMaxRest, 'get_portgroup',
side_effect=([tpd.PowerMaxData.port_group_name_i, None]))
def test_check_port_group(
self, mock_get_pg):
for x in range(0, 2):
_, msg = self.driver.masking._check_port_group(
self.data.array, self.maskingviewdict['maskingview_name'])
self.assertIsNotNone(msg)
self.assertEqual(2, mock_get_pg.call_count)
@mock.patch.object(
masking.PowerMaxMasking, '_find_initiator_group',
side_effect=[tpd.PowerMaxData.initiatorgroup_name_i, None, None])
@mock.patch.object(
masking.PowerMaxMasking, '_create_initiator_group',
side_effect=([tpd.PowerMaxData.initiatorgroup_name_i, None]))
def test_get_or_create_initiator_group(self, mock_create_ig, mock_find_ig):
self.driver.masking._get_or_create_initiator_group(
self.data.array, self.data.initiatorgroup_name_i,
self.data.connector, self.extra_specs)
mock_create_ig.assert_not_called()
found_init_group, msg = (
self.driver.masking._get_or_create_initiator_group(
self.data.array, self.data.initiatorgroup_name_i,
self.data.connector, self.extra_specs))
self.assertIsNone(msg)
found_init_group, msg = (
self.driver.masking._get_or_create_initiator_group(
self.data.array, self.data.initiatorgroup_name_i,
self.data.connector, self.extra_specs))
self.assertIsNotNone(msg)
def test_check_existing_initiator_group(self):
with mock.patch.object(
rest.PowerMaxRest, 'get_element_from_masking_view',
return_value=tpd.PowerMaxData.inititiatorgroup):
ig_from_mv, msg = (
self.driver.masking._check_existing_initiator_group(
self.data.array, self.maskingviewdict['maskingview_name'],
self.maskingviewdict, self.data.storagegroup_name_i,
self.data.port_group_name_i, self.extra_specs))
self.assertEqual(self.data.inititiatorgroup, ig_from_mv)
def test_check_adding_volume_to_storage_group(self):
with mock.patch.object(
masking.PowerMaxMasking, '_create_initiator_group'):
with mock.patch.object(
rest.PowerMaxRest, 'is_volume_in_storagegroup',
side_effect=[True, False]):
msg = (
self.driver.masking._check_adding_volume_to_storage_group(
self.data.array, self.device_id,
self.data.storagegroup_name_i,
self.maskingviewdict[utils.VOL_NAME],
self.maskingviewdict[utils.EXTRA_SPECS]))
self.assertIsNone(msg)
msg = (
self.driver.masking._check_adding_volume_to_storage_group(
self.data.array, self.device_id,
self.data.storagegroup_name_i,
self.maskingviewdict[utils.VOL_NAME],
self.maskingviewdict[utils.EXTRA_SPECS]))
@mock.patch.object(rest.PowerMaxRest, 'add_vol_to_sg')
def test_add_volume_to_storage_group(self, mock_add_volume):
self.driver.masking.add_volume_to_storage_group(
self.data.array, self.device_id, self.data.storagegroup_name_i,
self.volume_name, self.extra_specs)
mock_add_volume.assert_called_once()
@mock.patch.object(rest.PowerMaxRest, 'remove_vol_from_sg')
def test_remove_vol_from_storage_group(self, mock_remove_volume):
with mock.patch.object(
rest.PowerMaxRest, 'is_volume_in_storagegroup',
side_effect=[False, True]):
self.driver.masking.remove_vol_from_storage_group(
self.data.array, self.device_id, self.data.storagegroup_name_i,
self.volume_name, self.extra_specs)
mock_remove_volume.assert_called_once()
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver.masking.remove_vol_from_storage_group,
self.data.array, self.device_id, self.data.storagegroup_name_i,
self.volume_name, self.extra_specs)
def test_find_initiator_names(self):
foundinitiatornames = self.driver.masking.find_initiator_names(
self.data.connector)
self.assertEqual(self.data.connector['initiator'],
foundinitiatornames[0])
foundinitiatornames = self.driver_fc.masking.find_initiator_names(
self.data.connector)
self.assertEqual(self.data.connector['wwpns'][0],
foundinitiatornames[0])
connector = {'ip': self.data.ip, 'initiator': None, 'host': 'HostX'}
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver.masking.find_initiator_names, connector)
self.assertRaises(
exception.VolumeBackendAPIException,
self.driver_fc.masking.find_initiator_names, connector)
def test_find_initiator_group_found(self):
with mock.patch.object(
rest.PowerMaxRest, 'get_initiator_list',
return_value=self.data.initiator_list[2]['initiatorId']):
with mock.patch.object(
rest.PowerMaxRest, 'get_initiator_group_from_initiator',
return_value=self.data.initiator_list):
found_init_group_nam = (
self.driver.masking._find_initiator_group(
self.data.array, ['FA-1D:4:123456789012345']))
self.assertEqual(self.data.initiator_list,
found_init_group_nam)
def test_find_initiator_group_not_found(self):
with mock.patch.object(
rest.PowerMaxRest, 'get_initiator_list',
return_value=self.data.initiator_list[2]['initiatorId']):
with mock.patch.object(
rest.PowerMaxRest, 'get_initiator_group_from_initiator',
return_value=None):
found_init_group_nam = (
self.driver.masking._find_initiator_group(
self.data.array, ['Error']))
self.assertIsNone(found_init_group_nam)
def test_create_masking_view(self):
with mock.patch.object(rest.PowerMaxRest, 'create_masking_view',
side_effect=[None, Exception]):
error_message = self.driver.masking.create_masking_view(
self.data.array, self.maskingviewdict['maskingview_name'],
self.data.storagegroup_name_i, self.data.port_group_name_i,
self.data.initiatorgroup_name_i, self.extra_specs)
self.assertIsNone(error_message)
error_message = self.driver.masking.create_masking_view(
self.data.array, self.maskingviewdict['maskingview_name'],
self.data.storagegroup_name_i, self.data.port_group_name_i,
self.data.initiatorgroup_name_i, self.extra_specs)
self.assertIsNotNone(error_message)
@mock.patch.object(masking.PowerMaxMasking,
'_return_volume_to_fast_managed_group')
@mock.patch.object(masking.PowerMaxMasking, '_check_ig_rollback')
def test_check_if_rollback_action_for_masking_required(
self, mock_check_ig, mock_return):
with mock.patch.object(rest.PowerMaxRest,
'get_storage_groups_from_volume',
side_effect=[
exception.VolumeBackendAPIException,
self.data.storagegroup_list,
self.data.storagegroup_list, None,
None, ]):
self.assertRaises(
exception.VolumeBackendAPIException,
self.mask.check_if_rollback_action_for_masking_required,
self.data.array, self.data.test_volume,
self.device_id, self.maskingviewdict)
with mock.patch.object(masking.PowerMaxMasking,
'remove_and_reset_members'):
self.maskingviewdict[
'default_sg_name'] = self.data.defaultstoragegroup_name
self.mask.check_if_rollback_action_for_masking_required(
self.data.array, self.data.test_volume,
self.device_id, self.maskingviewdict)
# Multiattach case
self.mask.check_if_rollback_action_for_masking_required(
self.data.array, self.data.test_volume,
self.device_id, self.data.masking_view_dict_multiattach)
mock_return.assert_called_once()
@mock.patch.object(rest.PowerMaxRest, 'delete_masking_view')
@mock.patch.object(rest.PowerMaxRest, 'delete_initiator_group')
@mock.patch.object(rest.PowerMaxRest, 'get_initiator_group')
@mock.patch.object(
masking.PowerMaxMasking, '_find_initiator_group',
return_value=tpd.PowerMaxData.initiatorgroup_name_i)
def test_verify_initiator_group_from_masking_view(
self, mock_find_ig, mock_get_ig, mock_delete_ig, mock_delete_mv):
self.mask._verify_initiator_group_from_masking_view(
self.data.array, self.maskingviewdict['maskingview_name'],
self.maskingviewdict, self.data.initiatorgroup_name_i,
self.data.storagegroup_name_i, self.data.port_group_name_i,
self.extra_specs)
mock_get_ig.assert_not_called()
mock_get_ig.return_value = False
self.mask._verify_initiator_group_from_masking_view(
self.data.array, self.maskingviewdict['maskingview_name'],
self.maskingviewdict, 'OS-Wrong-Host-I-IG',
self.data.storagegroup_name_i, self.data.port_group_name_i,
self.extra_specs)
mock_get_ig.assert_called()
@mock.patch.object(rest.PowerMaxRest, 'delete_masking_view')
@mock.patch.object(rest.PowerMaxRest, 'delete_initiator_group')
@mock.patch.object(rest.PowerMaxRest, 'get_initiator_group',
return_value=True)
@mock.patch.object(
masking.PowerMaxMasking, '_find_initiator_group',
return_value=tpd.PowerMaxData.initiatorgroup_name_i)
def test_verify_initiator_group_from_masking_view2(
self, mock_find_ig, mock_get_ig, mock_delete_ig, mock_delete_mv):
mock_delete_mv.side_effect = [None, Exception]
self.mask._verify_initiator_group_from_masking_view(
self.data.array, self.maskingviewdict['maskingview_name'],
self.maskingviewdict, 'OS-Wrong-Host-I-IG',
self.data.storagegroup_name_i, self.data.port_group_name_i,
self.extra_specs)
mock_delete_mv.assert_called()
_, found_ig_from_connector = (
self.mask._verify_initiator_group_from_masking_view(
self.data.array, self.maskingviewdict['maskingview_name'],
self.maskingviewdict, 'OS-Wrong-Host-I-IG',
self.data.storagegroup_name_i, self.data.port_group_name_i,
self.extra_specs))
self.assertEqual(self.data.initiatorgroup_name_i,
found_ig_from_connector)
@mock.patch.object(rest.PowerMaxRest, 'create_initiator_group')
def test_create_initiator_group(self, mock_create_ig):
initiator_names = self.mask.find_initiator_names(self.data.connector)
ret_init_group_name = self.mask._create_initiator_group(
self.data.array, self.data.initiatorgroup_name_i, initiator_names,
self.extra_specs)
self.assertEqual(self.data.initiatorgroup_name_i, ret_init_group_name)
@mock.patch.object(rest.PowerMaxRest, 'create_initiator_group',
side_effect=([exception.VolumeBackendAPIException(
masking.CREATE_IG_ERROR)]))
def test_create_initiator_group_exception(self, mock_create_ig):
initiator_names = self.mask.find_initiator_names(self.data.connector)
self.assertRaises(
exception.VolumeBackendAPIException,
self.mask._create_initiator_group,
self.data.array, self.data.initiatorgroup_name_i, initiator_names,
self.extra_specs)
@mock.patch.object(masking.PowerMaxMasking,
'_last_volume_delete_initiator_group')
def test_check_ig_rollback(self, mock_last_volume):
with mock.patch.object(
masking.PowerMaxMasking, '_find_initiator_group',
side_effect=[None, 'FAKE-I-IG',
self.data.initiatorgroup_name_i]):
for x in range(0, 2):
self.mask._check_ig_rollback(self.data.array,
self.data.initiatorgroup_name_i,
self.data.connector)
mock_last_volume.assert_not_called()
self.mask._check_ig_rollback(
self.data.array, self.data.initiatorgroup_name_i,
self.data.connector)
mock_last_volume.assert_called()
@mock.patch.object(masking.PowerMaxMasking, '_cleanup_deletion')
def test_remove_and_reset_members(self, mock_cleanup):
self.mask.remove_and_reset_members(
self.data.array, self.device_id, self.data.test_volume,
self.volume_name, self.extra_specs, reset=False)
mock_cleanup.assert_called_once()
@mock.patch.object(
rest.PowerMaxRest, 'get_storage_groups_from_volume',
side_effect=[[tpd.PowerMaxData.storagegroup_name_i],
[tpd.PowerMaxData.storagegroup_name_i],
[tpd.PowerMaxData.storagegroup_name_i,
tpd.PowerMaxData.storagegroup_name_f]])
@mock.patch.object(masking.PowerMaxMasking, 'remove_volume_from_sg')
@mock.patch.object(masking.PowerMaxMasking,
'add_volume_to_default_storage_group')
def test_cleanup_deletion(self, mock_add, mock_remove_vol, mock_get_sg):
self.mask._cleanup_deletion(
self.data.array, self.data.test_volume, self.device_id,
self.volume_name, self.extra_specs, None, True, None)
mock_add.assert_not_called()
self.mask._cleanup_deletion(
self.data.array, self.data.test_volume, self.device_id,
self.volume_name, self.extra_specs,
self.data.connector, True, None)
mock_add.assert_not_called()
self.mask._cleanup_deletion(
self.data.array, self.data.test_volume, self.device_id,
self.volume_name, self.extra_specs, None, True, None)
mock_add.assert_called_once_with(
self.data.array, self.device_id,
self.volume_name, self.extra_specs, volume=self.data.test_volume)
@mock.patch.object(masking.PowerMaxMasking, '_last_vol_in_sg')
@mock.patch.object(masking.PowerMaxMasking, '_multiple_vols_in_sg')
def test_remove_volume_from_sg(self, mock_multiple_vols, mock_last_vol):
with mock.patch.object(
rest.PowerMaxRest, 'get_masking_views_from_storage_group',
return_value=None):
with mock.patch.object(
rest.PowerMaxRest, 'get_num_vols_in_sg',
side_effect=[2, 1]):
self.mask.remove_volume_from_sg(
self.data.array, self.device_id, self.volume_name,
self.data.defaultstoragegroup_name, self.extra_specs)
mock_last_vol.assert_not_called()
self.mask.remove_volume_from_sg(
self.data.array, self.device_id, self.volume_name,
self.data.defaultstoragegroup_name, self.extra_specs)
mock_last_vol.assert_called()
@mock.patch.object(masking.PowerMaxMasking, '_last_vol_in_sg')
@mock.patch.object(masking.PowerMaxMasking, '_multiple_vols_in_sg')
def test_remove_volume_from_sg_2(self, mock_multiple_vols, mock_last_vol):
with mock.patch.object(rest.PowerMaxRest, 'is_volume_in_storagegroup',
return_value=True):
with mock.patch.object(
rest.PowerMaxRest, 'get_masking_views_from_storage_group',
return_value=[self.data.masking_view_name_i]):
with mock.patch.object(
rest.PowerMaxRest, 'get_num_vols_in_sg',
side_effect=[2, 1]):
self.mask.remove_volume_from_sg(
self.data.array, self.device_id, self.volume_name,
self.data.storagegroup_name_i, self.extra_specs)
mock_last_vol.assert_not_called()
self.mask.remove_volume_from_sg(
self.data.array, self.device_id, self.volume_name,
self.data.storagegroup_name_i, self.extra_specs)
mock_last_vol.assert_called()
@mock.patch.object(masking.PowerMaxMasking, '_last_vol_masking_views',
return_value=True)
@mock.patch.object(masking.PowerMaxMasking, '_last_vol_no_masking_views',
return_value=True)
def test_last_vol_in_sg(self, mock_no_mv, mock_mv):
mv_list = [self.data.masking_view_name_i,
self.data.masking_view_name_f]
with mock.patch.object(rest.PowerMaxRest,
'get_masking_views_from_storage_group',
side_effect=[mv_list, []]):
for x in range(0, 2):
self.mask._last_vol_in_sg(
self.data.array, self.device_id, self.volume_name,
self.data.storagegroup_name_i, self.extra_specs,
self.data.connector)
self.assertEqual(1, mock_mv.call_count)
self.assertEqual(1, mock_no_mv.call_count)
@mock.patch.object(masking.PowerMaxMasking,
'_remove_last_vol_and_delete_sg')
@mock.patch.object(masking.PowerMaxMasking,
'_delete_cascaded_storage_groups')
@mock.patch.object(rest.PowerMaxRest, 'get_num_vols_in_sg',
side_effect=[1, 3])
@mock.patch.object(rest.PowerMaxRest, 'delete_storage_group')
@mock.patch.object(masking.PowerMaxMasking, 'get_parent_sg_from_child',
side_effect=[None, 'parent_sg_name', 'parent_sg_name'])
def test_last_vol_no_masking_views(
self, mock_get_parent, mock_delete, mock_num_vols,
mock_delete_casc, mock_remove):
for x in range(0, 3):
self.mask._last_vol_no_masking_views(
self.data.array, self.data.storagegroup_name_i,
self.device_id, self.volume_name, self.extra_specs,
False)
self.assertEqual(1, mock_delete.call_count)
self.assertEqual(1, mock_delete_casc.call_count)
self.assertEqual(1, mock_remove.call_count)
@mock.patch.object(masking.PowerMaxMasking,
'_remove_last_vol_and_delete_sg')
@mock.patch.object(masking.PowerMaxMasking, '_delete_mv_ig_and_sg')
@mock.patch.object(masking.PowerMaxMasking, '_get_num_vols_from_mv',
side_effect=[(1, 'parent_name'), (3, 'parent_name')])
def test_last_vol_masking_views(
self, mock_num_vols, mock_delete_all, mock_remove):
for x in range(0, 2):
self.mask._last_vol_masking_views(
self.data.array, self.data.storagegroup_name_i,
[self.data.masking_view_name_i], self.device_id,
self.volume_name, self.extra_specs, self.data.connector,
True)
self.assertEqual(1, mock_delete_all.call_count)
self.assertEqual(1, mock_remove.call_count)
@mock.patch.object(masking.PowerMaxMasking,
'add_volume_to_default_storage_group')
@mock.patch.object(rest.PowerMaxRest, 'get_num_vols_in_sg')
@mock.patch.object(masking.PowerMaxMasking,
'remove_vol_from_storage_group')
def test_multiple_vols_in_sg(self, mock_remove_vol, mock_get_volumes,
mock_add):
self.mask._multiple_vols_in_sg(
self.data.array, self.device_id, self.data.storagegroup_name_i,
self.volume_name, self.extra_specs, False)
mock_remove_vol.assert_called_once()
self.mask._multiple_vols_in_sg(
self.data.array, self.device_id, self.data.storagegroup_name_i,
self.volume_name, self.extra_specs, True)
mock_add.assert_called_once()
@mock.patch.object(rest.PowerMaxRest, 'get_element_from_masking_view')
@mock.patch.object(masking.PowerMaxMasking,
'_last_volume_delete_masking_view')
@mock.patch.object(masking.PowerMaxMasking,
'_last_volume_delete_initiator_group')
@mock.patch.object(masking.PowerMaxMasking,
'_delete_cascaded_storage_groups')
def test_delete_mv_ig_and_sg(self, mock_delete_sg, mock_delete_ig,
mock_delete_mv, mock_get_element):
self.mask._delete_mv_ig_and_sg(
self.data.array, self.data.device_id,
self.data.masking_view_name_i,
self.data.storagegroup_name_i, self.data.parent_sg_i,
self.data.connector, True, self.data.extra_specs)
mock_delete_sg.assert_called_once()
@mock.patch.object(rest.PowerMaxRest, 'delete_masking_view')
def test_last_volume_delete_masking_view(self, mock_delete_mv):
self.mask._last_volume_delete_masking_view(
self.data.array, self.data.masking_view_name_i)
mock_delete_mv.assert_called_once()
@mock.patch.object(masking.PowerMaxMasking,
'return_volume_to_volume_group')
@mock.patch.object(rest.PowerMaxRest, 'move_volume_between_storage_groups')
@mock.patch.object(masking.PowerMaxMasking,
'get_or_create_default_storage_group')
@mock.patch.object(masking.PowerMaxMasking, 'add_volume_to_storage_group')
def test_add_volume_to_default_storage_group(
self, mock_add_sg, mock_get_sg, mock_move, mock_return):
self.mask.add_volume_to_default_storage_group(
self.data.array, self.device_id, self.volume_name,
self.extra_specs)
mock_add_sg.assert_called_once()
self.mask.add_volume_to_default_storage_group(
self.data.array, self.device_id, self.volume_name,
self.extra_specs, src_sg=self.data.storagegroup_name_i)
mock_move.assert_called_once()
vol_grp_member = deepcopy(self.data.test_volume)
vol_grp_member.group_id = self.data.test_vol_grp_name_id_only
self.mask.add_volume_to_default_storage_group(
self.data.array, self.device_id, self.volume_name,
self.extra_specs, volume=vol_grp_member)
mock_return.assert_called_once()
def test_add_volume_to_default_storage_group_next_gen(self):
extra_specs = deepcopy(self.data.extra_specs)
extra_specs.pop(utils.IS_RE, None)
with mock.patch.object(rest.PowerMaxRest, 'is_next_gen_array',
return_value=True):
with mock.patch.object(
self.mask,
'get_or_create_default_storage_group') as mock_get:
self.mask.add_volume_to_default_storage_group(
self.data.array, self.device_id, self.volume_name,
extra_specs)
mock_get.assert_called_once_with(
self.data.array, self.data.srp,
extra_specs[utils.SLO],
'NONE', extra_specs, False, False, None)
@mock.patch.object(provision.PowerMaxProvision, 'create_storage_group')
def test_get_or_create_default_storage_group(self, mock_create_sg):
with mock.patch.object(
rest.PowerMaxRest, 'get_vmax_default_storage_group',
return_value=(None, self.data.storagegroup_name_i)):
storage_group_name = self.mask.get_or_create_default_storage_group(
self.data.array, self.data.srp, self.data.slo,
self.data.workload, self.extra_specs)
self.assertEqual(self.data.storagegroup_name_i, storage_group_name)
with mock.patch.object(
rest.PowerMaxRest, 'get_vmax_default_storage_group',
return_value=('test_sg', self.data.storagegroup_name_i)):
with mock.patch.object(
rest.PowerMaxRest, 'get_masking_views_from_storage_group',
return_value=self.data.masking_view_name_i):
self.assertRaises(
exception.VolumeBackendAPIException,
self.mask.get_or_create_default_storage_group,
self.data.array, self.data.srp, self.data.slo,
self.data.workload, self.extra_specs)
@mock.patch.object(masking.PowerMaxMasking,
'add_volume_to_default_storage_group')
@mock.patch.object(rest.PowerMaxRest, 'remove_child_sg_from_parent_sg')
@mock.patch.object(rest.PowerMaxRest, 'delete_storage_group')
@mock.patch.object(masking.PowerMaxMasking,
'remove_vol_from_storage_group')
def test_remove_last_vol_and_delete_sg(self, mock_vol_sg,
mock_delete_sg, mock_rm, mock_add):
self.mask._remove_last_vol_and_delete_sg(
self.data.array, self.device_id, self.volume_name,
self.data.storagegroup_name_i, self.extra_specs)
self.mask._remove_last_vol_and_delete_sg(
self.data.array, self.device_id, self.volume_name,
self.data.storagegroup_name_i, self.extra_specs,
self.data.parent_sg_i, True)
self.assertEqual(2, mock_delete_sg.call_count)
self.assertEqual(1, mock_vol_sg.call_count)
self.assertEqual(1, mock_rm.call_count)
self.assertEqual(1, mock_add.call_count)
@mock.patch.object(rest.PowerMaxRest, 'delete_initiator_group')
def test_last_volume_delete_initiator_group(self, mock_delete_ig):
self.mask._last_volume_delete_initiator_group(
self.data.array, self.data.initiatorgroup_name_f, 'Wrong_Host')
mock_delete_ig.assert_not_called()
self.mask._last_volume_delete_initiator_group(
self.data.array, self.data.initiatorgroup_name_f, None)
mock_delete_ig.assert_not_called()
mv_list = [self.data.masking_view_name_i,
self.data.masking_view_name_f]
with mock.patch.object(
rest.PowerMaxRest, 'get_masking_views_by_initiator_group',
side_effect=[mv_list, []]):
self.mask._last_volume_delete_initiator_group(
self.data.array, self.data.initiatorgroup_name_i,
self.data.connector['host'])
mock_delete_ig.assert_not_called()
self.mask._last_volume_delete_initiator_group(
self.data.array, self.data.initiatorgroup_name_i,
self.data.connector['host'])
mock_delete_ig.assert_called_once()
def test_populate_masking_dict_init_check_false(self):
extra_specs = deepcopy(self.data.extra_specs)
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
connector = self.data.connector
with mock.patch.object(self.driver, '_get_initiator_check_flag',
return_value=False):
masking_view_dict = self.driver._populate_masking_dict(
self.data.test_volume, connector, extra_specs)
self.assertFalse(masking_view_dict['initiator_check'])
def test_populate_masking_dict_init_check_true(self):
extra_specs = deepcopy(self.data.extra_specs)
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
connector = self.data.connector
with mock.patch.object(self.driver, '_get_initiator_check_flag',
return_value=True):
masking_view_dict = self.driver._populate_masking_dict(
self.data.test_volume, connector, extra_specs)
self.assertTrue(masking_view_dict['initiator_check'])
def test_check_existing_initiator_group_verify_true(self):
mv_dict = deepcopy(self.data.masking_view_dict)
mv_dict['initiator_check'] = True
with mock.patch.object(
rest.PowerMaxRest, 'get_element_from_masking_view',
return_value=tpd.PowerMaxData.initiatorgroup_name_f):
with mock.patch.object(
self.mask, '_verify_initiator_group_from_masking_view',
return_value=(
True,
self.data.initiatorgroup_name_f)) as mock_verify:
self.mask._check_existing_initiator_group(
self.data.array, self.data.masking_view_name_f,
mv_dict, self.data.storagegroup_name_f,
self.data.port_group_name_f, self.data.extra_specs)
mock_verify.assert_called_once_with(
self.data.array, self.data.masking_view_name_f,
mv_dict, self.data.initiatorgroup_name_f,
self.data.storagegroup_name_f,
self.data.port_group_name_f, self.data.extra_specs)
@mock.patch.object(
masking.PowerMaxMasking, 'add_child_sg_to_parent_sg',
side_effect=[None, exception.VolumeBackendAPIException])
@mock.patch.object(rest.PowerMaxRest, 'is_child_sg_in_parent_sg',
side_effect=[True, False, False])
def test_check_add_child_sg_to_parent_sg(self, mock_is_child, mock_add):
for x in range(0, 3):
message = self.mask._check_add_child_sg_to_parent_sg(
self.data.array, self.data.storagegroup_name_i,
self.data.parent_sg_i, self.data.extra_specs)
self.assertIsNotNone(message)
@mock.patch.object(rest.PowerMaxRest, 'add_child_sg_to_parent_sg')
@mock.patch.object(rest.PowerMaxRest, 'is_child_sg_in_parent_sg',
side_effect=[True, False])
def test_add_child_sg_to_parent_sg(self, mock_is_child, mock_add):
for x in range(0, 2):
self.mask.add_child_sg_to_parent_sg(
self.data.array, self.data.storagegroup_name_i,
self.data.parent_sg_i, self.data.extra_specs)
self.assertEqual(1, mock_add.call_count)
def test_get_parent_sg_from_child(self):
with mock.patch.object(self.driver.rest, 'get_storage_group',
side_effect=[None, self.data.sg_details[1]]):
sg_name = self.mask.get_parent_sg_from_child(
self.data.array, self.data.storagegroup_name_i)
self.assertIsNone(sg_name)
sg_name2 = self.mask.get_parent_sg_from_child(
self.data.array, self.data.storagegroup_name_f)
self.assertEqual(self.data.parent_sg_f, sg_name2)
@mock.patch.object(rest.PowerMaxRest, 'get_element_from_masking_view',
return_value='parent_sg')
@mock.patch.object(rest.PowerMaxRest, 'get_num_vols_in_sg',
return_value=2)
def test_get_num_vols_from_mv(self, mock_num, mock_element):
num_vols, sg = self.mask._get_num_vols_from_mv(
self.data.array, self.data.masking_view_name_f)
self.assertEqual(2, num_vols)
@mock.patch.object(masking.PowerMaxMasking,
'add_volume_to_default_storage_group')
@mock.patch.object(rest.PowerMaxRest, 'delete_storage_group')
def test_delete_cascaded(self, mock_delete, mock_add):
self.mask._delete_cascaded_storage_groups(
self.data.array, self.data.masking_view_name_f,
self.data.parent_sg_f, self.data.extra_specs,
self.data.device_id, False)
self.assertEqual(2, mock_delete.call_count)
mock_add.assert_not_called()
# Delete legacy masking view, parent sg = child sg
mock_delete.reset_mock()
self.mask._delete_cascaded_storage_groups(
self.data.array, self.data.masking_view_name_f,
self.data.masking_view_name_f, self.data.extra_specs,
self.data.device_id, True)
self.assertEqual(1, mock_delete.call_count)
mock_add.assert_called_once()
@mock.patch.object(masking.PowerMaxMasking,
'add_volumes_to_storage_group')
def test_add_remote_vols_to_volume_group(self, mock_add):
self.mask.add_remote_vols_to_volume_group(
[self.data.test_volume], self.data.test_rep_group,
self.data.rep_extra_specs)
mock_add.assert_called_once()
@mock.patch.object(masking.PowerMaxMasking,
'add_remote_vols_to_volume_group')
@mock.patch.object(masking.PowerMaxMasking,
'_check_adding_volume_to_storage_group')
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type',
return_value=True)
@mock.patch.object(volume_utils, 'is_group_a_type',
side_effect=[False, False, True, True])
def test_return_volume_to_volume_group(self, mock_type, mock_cg,
mock_check, mock_add):
vol_grp_member = deepcopy(self.data.test_volume)
vol_grp_member.group_id = self.data.test_vol_grp_name_id_only
vol_grp_member.group = self.data.test_group
for x in range(0, 2):
self.mask.return_volume_to_volume_group(
self.data.array, vol_grp_member, self.data.device_id,
self.data.test_volume.name, self.data.extra_specs)
mock_add.assert_called_once()
@mock.patch.object(masking.PowerMaxMasking,
'_return_volume_to_fast_managed_group')
def test_pre_multiattach(self, mock_return):
mv_dict = self.mask.pre_multiattach(
self.data.array, self.data.device_id,
self.data.masking_view_dict_multiattach,
self.data.extra_specs)
mock_return.assert_not_called()
self.assertEqual(self.data.storagegroup_name_f,
mv_dict[utils.FAST_SG])
with mock.patch.object(
self.mask, 'move_volume_between_storage_groups',
side_effect=exception.CinderException):
self.assertRaises(
exception.VolumeBackendAPIException,
self.mask.pre_multiattach, self.data.array,
self.data.device_id, self.data.masking_view_dict_multiattach,
self.data.extra_specs)
mock_return.assert_called_once()
def test_pre_multiattach_next_gen(self):
with mock.patch.object(utils.PowerMaxUtils, 'truncate_string',
return_value='DiamondDSS'):
self.mask.pre_multiattach(
self.data.array, self.data.device_id,
self.data.masking_view_dict_multiattach,
self.data.extra_specs)
utils.PowerMaxUtils.truncate_string.assert_called_once_with(
'DiamondDSS', 10)
@mock.patch.object(masking.PowerMaxMasking,
'_clean_up_child_storage_group')
@mock.patch.object(masking.PowerMaxMasking,
'move_volume_between_storage_groups')
@mock.patch.object(masking.PowerMaxMasking,
'_return_volume_to_fast_managed_group')
def test_pre_multiattach_pool_none_workload(self, mock_return, mck_move,
mck_clean):
with mock.patch.object(utils.PowerMaxUtils, 'truncate_string',
return_value='OptimdNONE'):
self.mask.pre_multiattach(
self.data.array, self.data.device_id,
self.data.masking_view_dict_multiattach,
self.data.extra_specs_optimized)
utils.PowerMaxUtils.truncate_string.assert_called_once_with(
'OptimizedNONE', 10)
@mock.patch.object(
rest.PowerMaxRest, 'get_storage_group_list',
side_effect=[
{'storageGroupId': [tpd.PowerMaxData.no_slo_sg_name]}, {}])
@mock.patch.object(masking.PowerMaxMasking,
'_return_volume_to_fast_managed_group')
def test_check_return_volume_to_fast_managed_group(
self, mock_return, mock_sg):
for x in range(0, 2):
self.mask.return_volume_to_fast_managed_group(
self.data.array, self.data.device_id,
self.data.extra_specs)
no_slo_specs = deepcopy(self.data.extra_specs)
no_slo_specs[utils.SLO] = None
self.mask.return_volume_to_fast_managed_group(
self.data.array, self.data.device_id, no_slo_specs)
mock_return.assert_called_once()
@mock.patch.object(masking.PowerMaxMasking, '_move_vol_from_default_sg')
@mock.patch.object(masking.PowerMaxMasking,
'_clean_up_child_storage_group')
@mock.patch.object(masking.PowerMaxMasking, 'add_child_sg_to_parent_sg')
@mock.patch.object(masking.PowerMaxMasking, '_get_or_create_storage_group')
@mock.patch.object(
rest.PowerMaxRest, 'get_storage_groups_from_volume',
side_effect=[[tpd.PowerMaxData.no_slo_sg_name],
[tpd.PowerMaxData.storagegroup_name_f]])
def test_return_volume_to_fast_managed_group(
self, mock_sg, mock_get, mock_add, mock_clean, mock_move):
for x in range(0, 2):
self.mask._return_volume_to_fast_managed_group(
self.data.array, self.data.device_id,
self.data.parent_sg_f, self.data.storagegroup_name_f,
self.data.no_slo_sg_name, self.data.extra_specs)
mock_get.assert_called_once()
mock_clean.assert_called_once()
@mock.patch.object(rest.PowerMaxRest, 'delete_storage_group')
@mock.patch.object(rest.PowerMaxRest, 'remove_child_sg_from_parent_sg')
@mock.patch.object(rest.PowerMaxRest, 'is_child_sg_in_parent_sg',
side_effect=[False, True])
@mock.patch.object(rest.PowerMaxRest, 'get_num_vols_in_sg',
side_effect=[2, 0, 0])
@mock.patch.object(rest.PowerMaxRest, 'get_storage_group', side_effect=[
None, 'child_sg', 'child_sg', 'child_sg'])
def test_clean_up_child_storage_group(
self, mock_sg, mock_num, mock_child, mock_rm, mock_del):
# Storage group not found
self.mask._clean_up_child_storage_group(
self.data.array, self.data.storagegroup_name_f,
self.data.parent_sg_f, self.data.extra_specs)
mock_num.assert_not_called()
# Storage group not empty
self.mask._clean_up_child_storage_group(
self.data.array, self.data.storagegroup_name_f,
self.data.parent_sg_f, self.data.extra_specs)
mock_child.assert_not_called()
# Storage group not child
self.mask._clean_up_child_storage_group(
self.data.array, self.data.storagegroup_name_f,
self.data.parent_sg_f, self.data.extra_specs)
mock_rm.assert_not_called()
# Storage group is child, and empty
self.mask._clean_up_child_storage_group(
self.data.array, self.data.storagegroup_name_f,
self.data.parent_sg_f, self.data.extra_specs)
mock_rm.assert_called_once()
self.assertEqual(2, mock_del.call_count)
@mock.patch.object(utils.PowerMaxUtils, 'verify_tag_list')
def test_add_tags_to_storage_group_disabled(self, mock_verify):
self.mask._add_tags_to_storage_group(
self.data.array, self.data.add_volume_sg_info_dict,
self.data.extra_specs)
mock_verify.assert_not_called()
@mock.patch.object(utils.PowerMaxUtils, 'verify_tag_list')
def test_add_tags_to_storage_group_enabled(self, mock_verify):
self.mask._add_tags_to_storage_group(
self.data.array, self.data.add_volume_sg_info_dict,
self.data.extra_specs_tags)
mock_verify.assert_called()
@mock.patch.object(utils.PowerMaxUtils, 'get_new_tags')
def test_add_tags_to_storage_group_existing_tags(self, mock_inter):
self.mask._add_tags_to_storage_group(
self.data.array, self.data.storage_group_with_tags,
self.data.extra_specs_tags)
mock_inter.assert_called()
@mock.patch.object(rest.PowerMaxRest, 'add_storage_group_tag',
side_effect=[exception.VolumeBackendAPIException])
def test_add_tags_to_storage_group_exception(self, mock_except):
self.mask._add_tags_to_storage_group(
self.data.array, self.data.add_volume_sg_info_dict,
self.data.extra_specs_tags)
mock_except.assert_called()
@mock.patch.object(rest.PowerMaxRest,
'get_masking_views_from_storage_group',
return_value=[tpd.PowerMaxData.masking_view_name_f])
def test_get_host_and_port_group_labels(self, mock_mv):
host_label, port_group_label = (
self.mask._get_host_and_port_group_labels(
self.data.array, self.data.parent_sg_f))
self.assertEqual('HostX', host_label)
self.assertEqual('OS-fibre-PG', port_group_label)
@mock.patch.object(rest.PowerMaxRest,
'get_masking_views_from_storage_group',
return_value=['OS-HostX699ea-I-p-name3b02c-MV'])
def test_get_host_and_port_group_labels_complex(self, mock_mv):
host_label, port_group_label = (
self.mask._get_host_and_port_group_labels(
self.data.array, self.data.parent_sg_f))
self.assertEqual('HostX699ea', host_label)
self.assertEqual('p-name3b02c', port_group_label)
@mock.patch.object(rest.PowerMaxRest,
'get_masking_views_from_storage_group',
return_value=['OS-myhost-I-myportgroup-MV'])
def test_get_host_and_port_group_labels_plain(self, mock_mv):
host_label, port_group_label = (
self.mask._get_host_and_port_group_labels(
self.data.array, self.data.parent_sg_f))
self.assertEqual('myhost', host_label)
self.assertEqual('myportgroup', port_group_label)
@mock.patch.object(rest.PowerMaxRest,
'get_masking_views_from_storage_group',
return_value=[
'OS-host-with-dash-I-portgroup-with-dashes-MV'])
def test_get_host_and_port_group_labels_dashes(self, mock_mv):
host_label, port_group_label = (
self.mask._get_host_and_port_group_labels(
self.data.array, self.data.parent_sg_f))
self.assertEqual('host-with-dash', host_label)
self.assertEqual('portgroup-with-dashes', port_group_label)
@mock.patch.object(
rest.PowerMaxRest, 'is_child_sg_in_parent_sg', return_value=False)
@mock.patch.object(
rest.PowerMaxRest, 'add_child_sg_to_parent_sg')
@mock.patch.object(
rest.PowerMaxRest, 'get_storage_group',
side_effect=[None, tpd.PowerMaxData.sg_details[1],
tpd.PowerMaxData.sg_details[2]])
@mock.patch.object(
provision.PowerMaxProvision, 'create_storage_group')
def test_check_child_storage_group_exists_false(
self, mock_create, mock_get, mock_add, mock_check):
self.mask._check_child_storage_group_exists(
self.data.device_id, self.data.array,
self.data.storagegroup_name_i, self.data.extra_specs,
self.data.parent_sg_i)
mock_create.assert_called_once()
mock_add.assert_called_once()
@mock.patch.object(
rest.PowerMaxRest, 'is_child_sg_in_parent_sg', return_value=True)
@mock.patch.object(
rest.PowerMaxRest, 'add_child_sg_to_parent_sg')
@mock.patch.object(
rest.PowerMaxRest, 'get_storage_group',
side_effect=[tpd.PowerMaxData.sg_details[1],
tpd.PowerMaxData.sg_details[3]])
@mock.patch.object(
provision.PowerMaxProvision, 'create_storage_group')
def test_check_child_storage_group_exists_true(
self, mock_create, mock_get, mock_add, mock_check):
self.mask._check_child_storage_group_exists(
self.data.device_id, self.data.array,
self.data.storagegroup_name_i, self.data.extra_specs,
self.data.parent_sg_i)
mock_create.assert_not_called
mock_add.assert_not_called()