Merge "VMAX driver - seamless upgrade from SMI-S to REST"
This commit is contained in:
commit
2a27fe404a
@ -143,6 +143,20 @@ class VMAXCommonData(object):
|
|||||||
provider_location3 = {'array': six.text_type(remote_array),
|
provider_location3 = {'array': six.text_type(remote_array),
|
||||||
'device_id': device_id2}
|
'device_id': device_id2}
|
||||||
|
|
||||||
|
legacy_provider_location = {
|
||||||
|
'classname': 'Symm_StorageVolume',
|
||||||
|
'keybindings': {'CreationClassName': u'Symm_StorageVolume',
|
||||||
|
'SystemName': u'SYMMETRIX+000197800123',
|
||||||
|
'DeviceID': device_id,
|
||||||
|
'SystemCreationClassName': u'Symm_StorageSystem'}}
|
||||||
|
|
||||||
|
legacy_provider_location2 = {
|
||||||
|
'classname': 'Symm_StorageVolume',
|
||||||
|
'keybindings': {'CreationClassName': u'Symm_StorageVolume',
|
||||||
|
'SystemName': u'SYMMETRIX+000197800123',
|
||||||
|
'DeviceID': device_id2,
|
||||||
|
'SystemCreationClassName': u'Symm_StorageSystem'}}
|
||||||
|
|
||||||
snap_location = {'snap_name': '12345',
|
snap_location = {'snap_name': '12345',
|
||||||
'source_id': device_id}
|
'source_id': device_id}
|
||||||
|
|
||||||
@ -156,6 +170,12 @@ class VMAXCommonData(object):
|
|||||||
volume_type=test_volume_type, host=fake_host,
|
volume_type=test_volume_type, host=fake_host,
|
||||||
replication_driver_data=six.text_type(provider_location3))
|
replication_driver_data=six.text_type(provider_location3))
|
||||||
|
|
||||||
|
test_legacy_vol = fake_volume.fake_volume_obj(
|
||||||
|
context=ctx, name='vol1', size=2, provider_auth=None,
|
||||||
|
provider_location=six.text_type(legacy_provider_location),
|
||||||
|
replication_driver_data=six.text_type(legacy_provider_location2),
|
||||||
|
host=fake_host, volume_type=test_volume_type)
|
||||||
|
|
||||||
test_clone_volume = fake_volume.fake_volume_obj(
|
test_clone_volume = fake_volume.fake_volume_obj(
|
||||||
context=ctx, name='vol1', size=2, provider_auth=None,
|
context=ctx, name='vol1', size=2, provider_auth=None,
|
||||||
provider_location=six.text_type(provider_location2),
|
provider_location=six.text_type(provider_location2),
|
||||||
@ -166,6 +186,11 @@ class VMAXCommonData(object):
|
|||||||
provider_location=six.text_type(snap_location),
|
provider_location=six.text_type(snap_location),
|
||||||
host=fake_host, volume=test_volume)
|
host=fake_host, volume=test_volume)
|
||||||
|
|
||||||
|
test_legacy_snapshot = fake_snapshot.fake_snapshot_obj(
|
||||||
|
context=ctx, id='12345', name='my_snap', size=2,
|
||||||
|
provider_location=six.text_type(legacy_provider_location),
|
||||||
|
host=fake_host, volume=test_volume)
|
||||||
|
|
||||||
test_failed_snap = fake_snapshot.fake_snapshot_obj(
|
test_failed_snap = fake_snapshot.fake_snapshot_obj(
|
||||||
context=ctx, id='12345', name=failed_resource, size=2,
|
context=ctx, id='12345', name=failed_resource, size=2,
|
||||||
provider_location=six.text_type(snap_location),
|
provider_location=six.text_type(snap_location),
|
||||||
@ -262,7 +287,7 @@ class VMAXCommonData(object):
|
|||||||
'parent_sg_name': parent_sg_f,
|
'parent_sg_name': parent_sg_f,
|
||||||
'srp': srp,
|
'srp': srp,
|
||||||
'storagetype:disablecompression': False,
|
'storagetype:disablecompression': False,
|
||||||
'port_group_name': port_group_name_f,
|
utils.PORTGROUPNAME: port_group_name_f,
|
||||||
'slo': slo,
|
'slo': slo,
|
||||||
'storagegroup_name': storagegroup_name_f,
|
'storagegroup_name': storagegroup_name_f,
|
||||||
'volume_name': test_volume.name,
|
'volume_name': test_volume.name,
|
||||||
@ -1172,6 +1197,15 @@ class VMAXUtilsTest(test.TestCase):
|
|||||||
is_fo3 = self.utils.is_volume_failed_over(None)
|
is_fo3 = self.utils.is_volume_failed_over(None)
|
||||||
self.assertFalse(is_fo3)
|
self.assertFalse(is_fo3)
|
||||||
|
|
||||||
|
def test_add_legacy_pools(self):
|
||||||
|
pools = [{'pool_name': "Diamond+None+SRP_1+000197800111"},
|
||||||
|
{'pool_name': "Diamond+OLTP+SRP_1+000197800111"}]
|
||||||
|
new_pools = self.utils.add_legacy_pools(pools)
|
||||||
|
ref_pools = [{'pool_name': "Diamond+None+SRP_1+000197800111"},
|
||||||
|
{'pool_name': "Diamond+OLTP+SRP_1+000197800111"},
|
||||||
|
{'pool_name': "Diamond+SRP_1+000197800111"}]
|
||||||
|
self.assertEqual(ref_pools, new_pools)
|
||||||
|
|
||||||
def test_update_volume_group_name(self):
|
def test_update_volume_group_name(self):
|
||||||
group = self.data.test_group_1
|
group = self.data.test_group_1
|
||||||
ref_group_name = self.data.test_vol_grp_name
|
ref_group_name = self.data.test_vol_grp_name
|
||||||
@ -2919,6 +2953,10 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
model_update = self.common.create_volume_from_snapshot(
|
model_update = self.common.create_volume_from_snapshot(
|
||||||
self.data.test_clone_volume, self.data.test_snapshot)
|
self.data.test_clone_volume, self.data.test_snapshot)
|
||||||
self.assertEqual(ref_model_update, model_update)
|
self.assertEqual(ref_model_update, model_update)
|
||||||
|
# Test from legacy snapshot
|
||||||
|
model_update = self.common.create_volume_from_snapshot(
|
||||||
|
self.data.test_clone_volume, self.data.test_legacy_snapshot)
|
||||||
|
self.assertEqual(ref_model_update, model_update)
|
||||||
|
|
||||||
def test_cloned_volume(self):
|
def test_cloned_volume(self):
|
||||||
ref_model_update = (
|
ref_model_update = (
|
||||||
@ -2953,12 +2991,18 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
|
|
||||||
def test_delete_snapshot_not_found(self):
|
def test_delete_snapshot_not_found(self):
|
||||||
with mock.patch.object(self.common, '_parse_snap_info',
|
with mock.patch.object(self.common, '_parse_snap_info',
|
||||||
return_value=(None, None)):
|
return_value=(None, 'Something')):
|
||||||
with mock.patch.object(self.provision, 'delete_volume_snap'):
|
with mock.patch.object(self.provision, 'delete_volume_snap'):
|
||||||
self.common.delete_snapshot(self.data.test_snapshot,
|
self.common.delete_snapshot(self.data.test_snapshot,
|
||||||
self.data.test_volume)
|
self.data.test_volume)
|
||||||
self.provision.delete_volume_snap.assert_not_called()
|
self.provision.delete_volume_snap.assert_not_called()
|
||||||
|
|
||||||
|
def test_delete_legacy_snap(self):
|
||||||
|
with mock.patch.object(self.common, '_delete_volume') as mock_del:
|
||||||
|
self.common.delete_snapshot(self.data.test_legacy_snapshot,
|
||||||
|
self.data.test_legacy_vol)
|
||||||
|
mock_del.assert_called_once_with(self.data.test_legacy_snapshot)
|
||||||
|
|
||||||
def test_remove_members(self):
|
def test_remove_members(self):
|
||||||
array = self.data.array
|
array = self.data.array
|
||||||
device_id = self.data.device_id
|
device_id = self.data.device_id
|
||||||
@ -2978,7 +3022,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
device_id = self.data.device_id
|
device_id = self.data.device_id
|
||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
connector = self.data.connector
|
connector = self.data.connector
|
||||||
with mock.patch.object(self.common, '_remove_members'):
|
with mock.patch.object(self.common, '_remove_members'):
|
||||||
self.common._unmap_lun(volume, connector)
|
self.common._unmap_lun(volume, connector)
|
||||||
@ -3010,7 +3054,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
connector = self.data.connector
|
connector = self.data.connector
|
||||||
extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
masking_view_dict = self.common._populate_masking_dict(
|
masking_view_dict = self.common._populate_masking_dict(
|
||||||
volume, connector, extra_specs)
|
volume, connector, extra_specs)
|
||||||
with mock.patch.object(self.common, 'find_host_lun_id',
|
with mock.patch.object(self.common, 'find_host_lun_id',
|
||||||
@ -3028,7 +3072,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
connector = self.data.connector
|
connector = self.data.connector
|
||||||
extra_specs = deepcopy(self.data.extra_specs)
|
extra_specs = deepcopy(self.data.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
masking_view_dict = self.common._populate_masking_dict(
|
masking_view_dict = self.common._populate_masking_dict(
|
||||||
volume, connector, extra_specs)
|
volume, connector, extra_specs)
|
||||||
host_lun = (self.data.maskingview[0]['maskingViewConnection'][0]
|
host_lun = (self.data.maskingview[0]['maskingViewConnection'][0]
|
||||||
@ -3039,7 +3083,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
'device_id': self.data.device_id}
|
'device_id': self.data.device_id}
|
||||||
with mock.patch.object(self.masking, 'setup_masking_view',
|
with mock.patch.object(self.masking, 'setup_masking_view',
|
||||||
return_value={
|
return_value={
|
||||||
'port_group_name':
|
utils.PORTGROUPNAME:
|
||||||
self.data.port_group_name_f}):
|
self.data.port_group_name_f}):
|
||||||
device_info_dict, pg = self.common._attach_volume(
|
device_info_dict, pg = self.common._attach_volume(
|
||||||
volume, connector, extra_specs, masking_view_dict)
|
volume, connector, extra_specs, masking_view_dict)
|
||||||
@ -3049,7 +3093,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
connector = self.data.connector
|
connector = self.data.connector
|
||||||
extra_specs = deepcopy(self.data.extra_specs)
|
extra_specs = deepcopy(self.data.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
masking_view_dict = self.common._populate_masking_dict(
|
masking_view_dict = self.common._populate_masking_dict(
|
||||||
volume, connector, extra_specs)
|
volume, connector, extra_specs)
|
||||||
with mock.patch.object(self.masking, 'setup_masking_view',
|
with mock.patch.object(self.masking, 'setup_masking_view',
|
||||||
@ -3084,7 +3128,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
device_id = self.data.device_id
|
device_id = self.data.device_id
|
||||||
new_size = self.data.test_volume.size
|
new_size = self.data.test_volume.size
|
||||||
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||||
ref_extra_specs['port_group_name'] = self.data.port_group_name_f
|
ref_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
with mock.patch.object(self.rest, 'is_vol_in_rep_session',
|
with mock.patch.object(self.rest, 'is_vol_in_rep_session',
|
||||||
return_value=(False, False, None)):
|
return_value=(False, False, None)):
|
||||||
self.common.extend_volume(volume, new_size)
|
self.common.extend_volume(volume, new_size)
|
||||||
@ -3166,6 +3210,13 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
volume, extra_specs)
|
volume, extra_specs)
|
||||||
self.assertIsNone(founddevice_id)
|
self.assertIsNone(founddevice_id)
|
||||||
|
|
||||||
|
def test_find_legacy_device_on_array(self):
|
||||||
|
volume = self.data.test_legacy_vol
|
||||||
|
extra_specs = self.data.extra_specs
|
||||||
|
ref_device_id = self.data.device_id
|
||||||
|
founddevice_id = self.common._find_device_on_array(volume, extra_specs)
|
||||||
|
self.assertEqual(ref_device_id, founddevice_id)
|
||||||
|
|
||||||
def test_find_host_lun_id_attached(self):
|
def test_find_host_lun_id_attached(self):
|
||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
extra_specs = self.data.extra_specs
|
extra_specs = self.data.extra_specs
|
||||||
@ -3222,7 +3273,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
def test_initial_setup_success(self):
|
def test_initial_setup_success(self):
|
||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||||
ref_extra_specs['port_group_name'] = self.data.port_group_name_f
|
ref_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
extra_specs = self.common._initial_setup(volume)
|
extra_specs = self.common._initial_setup(volume)
|
||||||
self.assertEqual(ref_extra_specs, extra_specs)
|
self.assertEqual(ref_extra_specs, extra_specs)
|
||||||
|
|
||||||
@ -3237,7 +3288,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
connector = self.data.connector
|
connector = self.data.connector
|
||||||
extra_specs = deepcopy(self.data.extra_specs)
|
extra_specs = deepcopy(self.data.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
ref_mv_dict = self.data.masking_view_dict
|
ref_mv_dict = self.data.masking_view_dict
|
||||||
masking_view_dict = self.common._populate_masking_dict(
|
masking_view_dict = self.common._populate_masking_dict(
|
||||||
volume, connector, extra_specs)
|
volume, connector, extra_specs)
|
||||||
@ -3251,7 +3302,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
'workload': None,
|
'workload': None,
|
||||||
'srp': self.data.srp,
|
'srp': self.data.srp,
|
||||||
'array': self.data.array,
|
'array': self.data.array,
|
||||||
'port_group_name': self.data.port_group_name_f}
|
utils.PORTGROUPNAME: self.data.port_group_name_f}
|
||||||
ref_mv_dict = self.data.masking_view_dict_no_slo
|
ref_mv_dict = self.data.masking_view_dict_no_slo
|
||||||
masking_view_dict = self.common._populate_masking_dict(
|
masking_view_dict = self.common._populate_masking_dict(
|
||||||
volume, connector, extra_specs)
|
volume, connector, extra_specs)
|
||||||
@ -3261,7 +3312,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
connector = self.data.connector
|
connector = self.data.connector
|
||||||
extra_specs = deepcopy(self.data.extra_specs)
|
extra_specs = deepcopy(self.data.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
extra_specs[utils.DISABLECOMPRESSION] = "true"
|
extra_specs[utils.DISABLECOMPRESSION] = "true"
|
||||||
ref_mv_dict = self.data.masking_view_dict_compression_disabled
|
ref_mv_dict = self.data.masking_view_dict_compression_disabled
|
||||||
masking_view_dict = self.common._populate_masking_dict(
|
masking_view_dict = self.common._populate_masking_dict(
|
||||||
@ -3364,7 +3415,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
device_id = self.data.device_id
|
device_id = self.data.device_id
|
||||||
volume_name = self.data.test_volume.name
|
volume_name = self.data.test_volume.name
|
||||||
ref_extra_specs = self.data.extra_specs_intervals_set
|
ref_extra_specs = self.data.extra_specs_intervals_set
|
||||||
ref_extra_specs['port_group_name'] = self.data.port_group_name_f
|
ref_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
with mock.patch.object(self.common, '_sync_check'):
|
with mock.patch.object(self.common, '_sync_check'):
|
||||||
with mock.patch.object(self.common, '_delete_from_srp'):
|
with mock.patch.object(self.common, '_delete_from_srp'):
|
||||||
@ -3432,7 +3483,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
extra_specs = self.common._set_vmax_extra_specs(
|
extra_specs = self.common._set_vmax_extra_specs(
|
||||||
self.data.vol_type_extra_specs, srp_record)
|
self.data.vol_type_extra_specs, srp_record)
|
||||||
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||||
ref_extra_specs['port_group_name'] = self.data.port_group_name_f
|
ref_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
self.assertEqual(ref_extra_specs, extra_specs)
|
self.assertEqual(ref_extra_specs, extra_specs)
|
||||||
|
|
||||||
def test_set_vmax_extra_specs_no_srp_name(self):
|
def test_set_vmax_extra_specs_no_srp_name(self):
|
||||||
@ -3449,7 +3500,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
extra_specs = self.common._set_vmax_extra_specs(
|
extra_specs = self.common._set_vmax_extra_specs(
|
||||||
self.data.vol_type_extra_specs_compr_disabled, srp_record)
|
self.data.vol_type_extra_specs_compr_disabled, srp_record)
|
||||||
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||||
ref_extra_specs['port_group_name'] = self.data.port_group_name_f
|
ref_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
ref_extra_specs[utils.DISABLECOMPRESSION] = "true"
|
ref_extra_specs[utils.DISABLECOMPRESSION] = "true"
|
||||||
self.assertEqual(ref_extra_specs, extra_specs)
|
self.assertEqual(ref_extra_specs, extra_specs)
|
||||||
|
|
||||||
@ -3459,15 +3510,15 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
extra_specs = self.common._set_vmax_extra_specs(
|
extra_specs = self.common._set_vmax_extra_specs(
|
||||||
self.data.vol_type_extra_specs_compr_disabled, srp_record)
|
self.data.vol_type_extra_specs_compr_disabled, srp_record)
|
||||||
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||||
ref_extra_specs['port_group_name'] = self.data.port_group_name_f
|
ref_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
self.assertEqual(ref_extra_specs, extra_specs)
|
self.assertEqual(ref_extra_specs, extra_specs)
|
||||||
|
|
||||||
def test_set_vmax_extra_specs_portgroup_as_spec(self):
|
def test_set_vmax_extra_specs_portgroup_as_spec(self):
|
||||||
srp_record = self.utils.parse_file_to_get_array_map(
|
srp_record = self.utils.parse_file_to_get_array_map(
|
||||||
self.fake_xml)
|
self.fake_xml)
|
||||||
extra_specs = self.common._set_vmax_extra_specs(
|
extra_specs = self.common._set_vmax_extra_specs(
|
||||||
{'port_group_name': 'extra_spec_pg'}, srp_record)
|
{utils.PORTGROUPNAME: 'extra_spec_pg'}, srp_record)
|
||||||
self.assertEqual('extra_spec_pg', extra_specs['port_group_name'])
|
self.assertEqual('extra_spec_pg', extra_specs[utils.PORTGROUPNAME])
|
||||||
|
|
||||||
def test_set_vmax_extra_specs_no_portgroup_set(self):
|
def test_set_vmax_extra_specs_no_portgroup_set(self):
|
||||||
fake_xml = FakeXML().create_fake_config_file(
|
fake_xml = FakeXML().create_fake_config_file(
|
||||||
@ -3698,8 +3749,21 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
extra_specs)
|
extra_specs)
|
||||||
mock_break.assert_called_with(
|
mock_break.assert_called_with(
|
||||||
array, target, device_id, snap_name, extra_specs)
|
array, target, device_id, snap_name, extra_specs)
|
||||||
mock_delete.assert_called_with(
|
mock_delete.assert_called_with(array, snap_name, device_id)
|
||||||
array, snap_name, device_id)
|
# Delete legacy temp snap
|
||||||
|
mock_delete.reset_mock()
|
||||||
|
snap_name2 = 'EMC_SMI_12345'
|
||||||
|
sessions = [{'source_vol': device_id,
|
||||||
|
'snap_name': snap_name2,
|
||||||
|
'target_vol_list': []}]
|
||||||
|
with mock.patch.object(self.rest, 'find_snap_vx_sessions',
|
||||||
|
return_value=sessions):
|
||||||
|
with mock.patch.object(self.rest, 'get_volume_snap',
|
||||||
|
return_value=snap_name2):
|
||||||
|
self.common._sync_check(array, device_id, volume_name,
|
||||||
|
extra_specs)
|
||||||
|
mock_delete.assert_called_once_with(
|
||||||
|
array, snap_name2, device_id)
|
||||||
|
|
||||||
@mock.patch.object(
|
@mock.patch.object(
|
||||||
provision.VMAXProvision,
|
provision.VMAXProvision,
|
||||||
@ -3828,7 +3892,7 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
device_id = self.data.device_id
|
device_id = self.data.device_id
|
||||||
volume_name = self.data.test_volume.name
|
volume_name = self.data.test_volume.name
|
||||||
extra_specs = self.data.extra_specs_intervals_set
|
extra_specs = self.data.extra_specs_intervals_set
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
volume = self.data.test_volume
|
volume = self.data.test_volume
|
||||||
new_type = {'extra_specs': {}}
|
new_type = {'extra_specs': {}}
|
||||||
host = {'host': self.data.new_host}
|
host = {'host': self.data.new_host}
|
||||||
@ -4369,6 +4433,10 @@ class VMAXFCTest(test.TestCase):
|
|||||||
zoning_mappings = self.driver._get_zoning_mappings(
|
zoning_mappings = self.driver._get_zoning_mappings(
|
||||||
self.data.test_volume, self.data.connector)
|
self.data.test_volume, self.data.connector)
|
||||||
self.assertEqual(ref_mappings, zoning_mappings)
|
self.assertEqual(ref_mappings, zoning_mappings)
|
||||||
|
# Legacy vol
|
||||||
|
zoning_mappings2 = self.driver._get_zoning_mappings(
|
||||||
|
self.data.test_legacy_vol, self.data.connector)
|
||||||
|
self.assertEqual(ref_mappings, zoning_mappings2)
|
||||||
|
|
||||||
def test_get_zoning_mappings_no_mv(self):
|
def test_get_zoning_mappings_no_mv(self):
|
||||||
ref_mappings = {'port_group': None,
|
ref_mappings = {'port_group': None,
|
||||||
@ -4748,7 +4816,7 @@ class VMAXMaskingTest(test.TestCase):
|
|||||||
self.driver_fc = driver_fc
|
self.driver_fc = driver_fc
|
||||||
self.mask = self.driver.masking
|
self.mask = self.driver.masking
|
||||||
self.extra_specs = self.data.extra_specs
|
self.extra_specs = self.data.extra_specs
|
||||||
self.extra_specs['port_group_name'] = self.data.port_group_name_i
|
self.extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_i
|
||||||
self.maskingviewdict = self.driver._populate_masking_dict(
|
self.maskingviewdict = self.driver._populate_masking_dict(
|
||||||
self.data.test_volume, self.data.connector, self.extra_specs)
|
self.data.test_volume, self.data.connector, self.extra_specs)
|
||||||
self.maskingviewdict['extra_specs'] = self.extra_specs
|
self.maskingviewdict['extra_specs'] = self.extra_specs
|
||||||
@ -5662,7 +5730,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_replicated_volume(self):
|
def test_create_replicated_volume(self):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
vol_identifier = self.utils.get_volume_element_name(
|
vol_identifier = self.utils.get_volume_element_name(
|
||||||
self.data.test_volume.id)
|
self.data.test_volume.id)
|
||||||
with mock.patch.object(self.common, '_replicate_volume',
|
with mock.patch.object(self.common, '_replicate_volume',
|
||||||
@ -5675,7 +5743,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_cloned_replicated_volume(self):
|
def test_create_cloned_replicated_volume(self):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
with mock.patch.object(self.common, '_replicate_volume',
|
with mock.patch.object(self.common, '_replicate_volume',
|
||||||
return_value={}) as mock_rep:
|
return_value={}) as mock_rep:
|
||||||
self.common.create_cloned_volume(
|
self.common.create_cloned_volume(
|
||||||
@ -5687,7 +5755,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
|
|
||||||
def test_create_replicated_volume_from_snap(self):
|
def test_create_replicated_volume_from_snap(self):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
with mock.patch.object(self.common, '_replicate_volume',
|
with mock.patch.object(self.common, '_replicate_volume',
|
||||||
return_value={}) as mock_rep:
|
return_value={}) as mock_rep:
|
||||||
self.common.create_volume_from_snapshot(
|
self.common.create_volume_from_snapshot(
|
||||||
@ -5731,7 +5799,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
return_value=True)
|
return_value=True)
|
||||||
def test_unmap_lun_volume_failed_over(self, mock_fo, mock_es, mock_rm):
|
def test_unmap_lun_volume_failed_over(self, mock_fo, mock_es, mock_rm):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
rep_config = self.utils.get_replication_config(
|
rep_config = self.utils.get_replication_config(
|
||||||
[self.replication_device])
|
[self.replication_device])
|
||||||
self.common._unmap_lun(self.data.test_volume, self.data.connector)
|
self.common._unmap_lun(self.data.test_volume, self.data.connector)
|
||||||
@ -5741,9 +5809,9 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
return_value=True)
|
return_value=True)
|
||||||
def test_initialize_connection_vol_failed_over(self, mock_fo):
|
def test_initialize_connection_vol_failed_over(self, mock_fo):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
rep_extra_specs = deepcopy(VMAXCommonData.rep_extra_specs)
|
rep_extra_specs = deepcopy(VMAXCommonData.rep_extra_specs)
|
||||||
rep_extra_specs['port_group_name'] = self.data.port_group_name_f
|
rep_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
rep_config = self.utils.get_replication_config(
|
rep_config = self.utils.get_replication_config(
|
||||||
[self.replication_device])
|
[self.replication_device])
|
||||||
with mock.patch.object(self.common, '_get_replication_extra_specs',
|
with mock.patch.object(self.common, '_get_replication_extra_specs',
|
||||||
@ -5755,7 +5823,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
@mock.patch.object(common.VMAXCommon, '_sync_check')
|
@mock.patch.object(common.VMAXCommon, '_sync_check')
|
||||||
def test_extend_volume_rep_enabled(self, mock_sync):
|
def test_extend_volume_rep_enabled(self, mock_sync):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
volume_name = self.data.test_volume.name
|
volume_name = self.data.test_volume.name
|
||||||
with mock.patch.object(self.rest, 'is_vol_in_rep_session',
|
with mock.patch.object(self.rest, 'is_vol_in_rep_session',
|
||||||
return_value=(False, False, None)):
|
return_value=(False, False, None)):
|
||||||
@ -5773,7 +5841,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
|
|
||||||
def test_populate_masking_dict_is_re(self):
|
def test_populate_masking_dict_is_re(self):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
masking_dict = self.common._populate_masking_dict(
|
masking_dict = self.common._populate_masking_dict(
|
||||||
self.data.test_volume, self.data.connector, extra_specs)
|
self.data.test_volume, self.data.connector, extra_specs)
|
||||||
self.assertTrue(masking_dict['replication_enabled'])
|
self.assertTrue(masking_dict['replication_enabled'])
|
||||||
@ -5785,7 +5853,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
return_value={})
|
return_value={})
|
||||||
def test_manage_existing_is_replicated(self, mock_rep):
|
def test_manage_existing_is_replicated(self, mock_rep):
|
||||||
extra_specs = deepcopy(self.extra_specs)
|
extra_specs = deepcopy(self.extra_specs)
|
||||||
extra_specs['port_group_name'] = self.data.port_group_name_f
|
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
external_ref = {u'source-name': u'00002'}
|
external_ref = {u'source-name': u'00002'}
|
||||||
volume_name = self.utils.get_volume_element_name(
|
volume_name = self.utils.get_volume_element_name(
|
||||||
self.data.test_volume.id)
|
self.data.test_volume.id)
|
||||||
@ -5822,7 +5890,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
@mock.patch.object(common.VMAXCommon, '_cleanup_remote_target')
|
@mock.patch.object(common.VMAXCommon, '_cleanup_remote_target')
|
||||||
def test_cleanup_lun_replication_success(self, mock_clean, mock_rm):
|
def test_cleanup_lun_replication_success(self, mock_clean, mock_rm):
|
||||||
rep_extra_specs = deepcopy(self.data.rep_extra_specs)
|
rep_extra_specs = deepcopy(self.data.rep_extra_specs)
|
||||||
rep_extra_specs['port_group_name'] = self.data.port_group_name_f
|
rep_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
self.common.cleanup_lun_replication(
|
self.common.cleanup_lun_replication(
|
||||||
self.data.test_volume, "1", self.data.device_id,
|
self.data.test_volume, "1", self.data.device_id,
|
||||||
self.extra_specs)
|
self.extra_specs)
|
||||||
@ -5833,6 +5901,14 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
mock_rm.assert_called_once_with(
|
mock_rm.assert_called_once_with(
|
||||||
self.data.remote_array, self.data.device_id2, "1",
|
self.data.remote_array, self.data.device_id2, "1",
|
||||||
rep_extra_specs, False)
|
rep_extra_specs, False)
|
||||||
|
# Cleanup legacy replication
|
||||||
|
self.common.cleanup_lun_replication(
|
||||||
|
self.data.test_legacy_vol, "1", self.data.device_id,
|
||||||
|
self.extra_specs)
|
||||||
|
mock_clean.assert_called_once_with(
|
||||||
|
self.data.array, self.data.remote_array, self.data.device_id,
|
||||||
|
self.data.device_id2, self.data.rdf_group_no, "1",
|
||||||
|
rep_extra_specs)
|
||||||
|
|
||||||
@mock.patch.object(common.VMAXCommon, '_cleanup_remote_target')
|
@mock.patch.object(common.VMAXCommon, '_cleanup_remote_target')
|
||||||
def test_cleanup_lun_replication_no_target(self, mock_clean):
|
def test_cleanup_lun_replication_no_target(self, mock_clean):
|
||||||
@ -5928,6 +6004,19 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
self.data.test_volume, False, self.extra_specs)
|
self.data.test_volume, False, self.extra_specs)
|
||||||
self.assertEqual(ref_model_update2, model_update2)
|
self.assertEqual(ref_model_update2, model_update2)
|
||||||
|
|
||||||
|
def test_failover_legacy_volume(self):
|
||||||
|
ref_model_update = {
|
||||||
|
'volume_id': self.data.test_volume.id,
|
||||||
|
'updates':
|
||||||
|
{'replication_status': fields.ReplicationStatus.FAILED_OVER,
|
||||||
|
'replication_driver_data': six.text_type(
|
||||||
|
self.data.legacy_provider_location),
|
||||||
|
'provider_location': six.text_type(
|
||||||
|
self.data.legacy_provider_location2)}}
|
||||||
|
model_update = self.common._failover_volume(
|
||||||
|
self.data.test_legacy_vol, True, self.extra_specs)
|
||||||
|
self.assertEqual(ref_model_update, model_update)
|
||||||
|
|
||||||
def test_failover_volume_exception(self):
|
def test_failover_volume_exception(self):
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
self.provision, 'failover_volume',
|
self.provision, 'failover_volume',
|
||||||
@ -6056,13 +6145,13 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
extra_specs1 = deepcopy(self.extra_specs)
|
extra_specs1 = deepcopy(self.extra_specs)
|
||||||
extra_specs1[utils.DISABLECOMPRESSION] = "true"
|
extra_specs1[utils.DISABLECOMPRESSION] = "true"
|
||||||
ref_specs1 = deepcopy(self.data.rep_extra_specs)
|
ref_specs1 = deepcopy(self.data.rep_extra_specs)
|
||||||
ref_specs1['port_group_name'] = self.data.port_group_name_f
|
ref_specs1[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
rep_extra_specs1 = self.common._get_replication_extra_specs(
|
rep_extra_specs1 = self.common._get_replication_extra_specs(
|
||||||
extra_specs1, rep_config)
|
extra_specs1, rep_config)
|
||||||
self.assertEqual(ref_specs1, rep_extra_specs1)
|
self.assertEqual(ref_specs1, rep_extra_specs1)
|
||||||
# Path two - disable compression, not all flash
|
# Path two - disable compression, not all flash
|
||||||
ref_specs2 = deepcopy(self.data.rep_extra_specs)
|
ref_specs2 = deepcopy(self.data.rep_extra_specs)
|
||||||
ref_specs2['port_group_name'] = self.data.port_group_name_f
|
ref_specs2[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||||
with mock.patch.object(self.rest, 'is_compression_capable',
|
with mock.patch.object(self.rest, 'is_compression_capable',
|
||||||
return_value=False):
|
return_value=False):
|
||||||
rep_extra_specs2 = self.common._get_replication_extra_specs(
|
rep_extra_specs2 = self.common._get_replication_extra_specs(
|
||||||
|
@ -281,11 +281,16 @@ class VMAXCommon(object):
|
|||||||
"""
|
"""
|
||||||
LOG.debug("Entering create_volume_from_snapshot.")
|
LOG.debug("Entering create_volume_from_snapshot.")
|
||||||
model_update = {}
|
model_update = {}
|
||||||
extra_specs = self._initial_setup(snapshot)
|
extra_specs = self._initial_setup(volume)
|
||||||
|
|
||||||
|
# Check if legacy snapshot
|
||||||
|
sourcedevice_id = self._find_device_on_array(
|
||||||
|
snapshot, extra_specs)
|
||||||
|
from_snapvx = False if sourcedevice_id else True
|
||||||
|
|
||||||
clone_dict = self._create_cloned_volume(
|
clone_dict = self._create_cloned_volume(
|
||||||
volume, snapshot, extra_specs, is_snapshot=False,
|
volume, snapshot, extra_specs, is_snapshot=False,
|
||||||
from_snapvx=True)
|
from_snapvx=from_snapvx)
|
||||||
|
|
||||||
# Set-up volume replication, if enabled
|
# Set-up volume replication, if enabled
|
||||||
if self.utils.is_replication_enabled(extra_specs):
|
if self.utils.is_replication_enabled(extra_specs):
|
||||||
@ -305,7 +310,7 @@ class VMAXCommon(object):
|
|||||||
:returns: model_update, dict
|
:returns: model_update, dict
|
||||||
"""
|
"""
|
||||||
model_update = {}
|
model_update = {}
|
||||||
extra_specs = self._initial_setup(source_volume)
|
extra_specs = self._initial_setup(clone_volume)
|
||||||
clone_dict = self._create_cloned_volume(clone_volume, source_volume,
|
clone_dict = self._create_cloned_volume(clone_volume, source_volume,
|
||||||
extra_specs)
|
extra_specs)
|
||||||
|
|
||||||
@ -381,7 +386,15 @@ class VMAXCommon(object):
|
|||||||
extra_specs = self._initial_setup(volume)
|
extra_specs = self._initial_setup(volume)
|
||||||
sourcedevice_id, snap_name = self._parse_snap_info(
|
sourcedevice_id, snap_name = self._parse_snap_info(
|
||||||
extra_specs[utils.ARRAY], snapshot)
|
extra_specs[utils.ARRAY], snapshot)
|
||||||
if not sourcedevice_id or not snap_name:
|
if not sourcedevice_id and not snap_name:
|
||||||
|
# Check if legacy snapshot
|
||||||
|
sourcedevice_id = self._find_device_on_array(
|
||||||
|
snapshot, extra_specs)
|
||||||
|
if sourcedevice_id:
|
||||||
|
self._delete_volume(snapshot)
|
||||||
|
else:
|
||||||
|
LOG.info("No snapshot found on the array")
|
||||||
|
elif not sourcedevice_id or not snap_name:
|
||||||
LOG.info("No snapshot found on the array")
|
LOG.info("No snapshot found on the array")
|
||||||
else:
|
else:
|
||||||
self.provision.delete_volume_snap_check_for_links(
|
self.provision.delete_volume_snap_check_for_links(
|
||||||
@ -589,7 +602,7 @@ class VMAXCommon(object):
|
|||||||
raise exception.VolumeBackendAPIException(
|
raise exception.VolumeBackendAPIException(
|
||||||
data=exception_message)
|
data=exception_message)
|
||||||
|
|
||||||
return device_info_dict, rollback_dict['port_group_name']
|
return device_info_dict, rollback_dict[utils.PORTGROUPNAME]
|
||||||
|
|
||||||
def terminate_connection(self, volume, connector):
|
def terminate_connection(self, volume, connector):
|
||||||
"""Disallow connection from connector.
|
"""Disallow connection from connector.
|
||||||
@ -761,7 +774,7 @@ class VMAXCommon(object):
|
|||||||
self.utils.get_default_oversubscription_ratio(
|
self.utils.get_default_oversubscription_ratio(
|
||||||
max_oversubscription_ratio))
|
max_oversubscription_ratio))
|
||||||
pools.append(pool)
|
pools.append(pool)
|
||||||
|
pools = self.utils.add_legacy_pools(pools)
|
||||||
data = {'vendor_name': "Dell EMC",
|
data = {'vendor_name': "Dell EMC",
|
||||||
'driver_version': self.version,
|
'driver_version': self.version,
|
||||||
'storage_protocol': 'unknown',
|
'storage_protocol': 'unknown',
|
||||||
@ -861,10 +874,12 @@ class VMAXCommon(object):
|
|||||||
if isinstance(loc, six.string_types):
|
if isinstance(loc, six.string_types):
|
||||||
name = ast.literal_eval(loc)
|
name = ast.literal_eval(loc)
|
||||||
array = extra_specs[utils.ARRAY]
|
array = extra_specs[utils.ARRAY]
|
||||||
try:
|
if name.get('device_id'):
|
||||||
device_id = name['device_id']
|
device_id = name['device_id']
|
||||||
except KeyError:
|
elif name.get('keybindings'):
|
||||||
device_id = name['keybindings']['DeviceID']
|
device_id = name['keybindings']['DeviceID']
|
||||||
|
else:
|
||||||
|
device_id = None
|
||||||
element_name = self.utils.get_volume_element_name(
|
element_name = self.utils.get_volume_element_name(
|
||||||
volume_name)
|
volume_name)
|
||||||
admin_metadata = {}
|
admin_metadata = {}
|
||||||
@ -1212,8 +1227,13 @@ class VMAXCommon(object):
|
|||||||
|
|
||||||
if isinstance(loc, six.string_types):
|
if isinstance(loc, six.string_types):
|
||||||
name = ast.literal_eval(loc)
|
name = ast.literal_eval(loc)
|
||||||
|
try:
|
||||||
sourcedevice_id = name['source_id']
|
sourcedevice_id = name['source_id']
|
||||||
snap_name = name['snap_name']
|
snap_name = name['snap_name']
|
||||||
|
except KeyError:
|
||||||
|
LOG.info("Error retrieving snapshot details. Assuming "
|
||||||
|
"legacy structure of snapshot...")
|
||||||
|
return None, None
|
||||||
# Ensure snapvx is on the array.
|
# Ensure snapvx is on the array.
|
||||||
try:
|
try:
|
||||||
snap_details = self.rest.get_volume_snap(
|
snap_details = self.rest.get_volume_snap(
|
||||||
@ -1358,8 +1378,8 @@ class VMAXCommon(object):
|
|||||||
|
|
||||||
The pool_name extra spec must be set, otherwise a default slo/workload
|
The pool_name extra spec must be set, otherwise a default slo/workload
|
||||||
will be chosen. The portgroup can either be passed as an extra spec
|
will be chosen. The portgroup can either be passed as an extra spec
|
||||||
on the volume type (e.g. 'port_group_name = os-pg1-pg'), or can
|
on the volume type (e.g. 'storagetype:portgroupname = os-pg1-pg'), or
|
||||||
be chosen from a list which must be provided in the xml file, e.g.:
|
can be chosen from a list provided in the xml file, e.g.:
|
||||||
<PortGroups>
|
<PortGroups>
|
||||||
<PortGroup>OS-PORTGROUP1-PG</PortGroup>
|
<PortGroup>OS-PORTGROUP1-PG</PortGroup>
|
||||||
<PortGroup>OS-PORTGROUP2-PG</PortGroup>
|
<PortGroup>OS-PORTGROUP2-PG</PortGroup>
|
||||||
@ -1376,8 +1396,9 @@ class VMAXCommon(object):
|
|||||||
extra_specs[utils.PORTGROUPNAME] = pool_record['PortGroup']
|
extra_specs[utils.PORTGROUPNAME] = pool_record['PortGroup']
|
||||||
if not extra_specs[utils.PORTGROUPNAME]:
|
if not extra_specs[utils.PORTGROUPNAME]:
|
||||||
error_message = (_("Port group name has not been provided - "
|
error_message = (_("Port group name has not been provided - "
|
||||||
"please configure the 'port_group_name' extra "
|
"please configure the "
|
||||||
"spec on the volume type, or enter a list of "
|
"'storagetype:portgroupname' extra spec on "
|
||||||
|
"the volume type, or enter a list of "
|
||||||
"portgroups to the xml file associated with "
|
"portgroups to the xml file associated with "
|
||||||
"this backend e.g."
|
"this backend e.g."
|
||||||
"<PortGroups>"
|
"<PortGroups>"
|
||||||
@ -1397,25 +1418,36 @@ class VMAXCommon(object):
|
|||||||
# Set pool_name slo and workload
|
# Set pool_name slo and workload
|
||||||
if 'pool_name' in extra_specs:
|
if 'pool_name' in extra_specs:
|
||||||
pool_name = extra_specs['pool_name']
|
pool_name = extra_specs['pool_name']
|
||||||
else:
|
|
||||||
slo_list = self.rest.get_slo_list(pool_record['SerialNumber'])
|
|
||||||
if 'Optimized' in slo_list:
|
|
||||||
slo = 'Optimized'
|
|
||||||
elif 'Diamond' in slo_list:
|
|
||||||
slo = 'Diamond'
|
|
||||||
else:
|
|
||||||
slo = 'None'
|
|
||||||
pool_name = ("%(slo)s+%(workload)s+%(srpName)s+%(array)s"
|
|
||||||
% {'slo': slo,
|
|
||||||
'workload': 'None',
|
|
||||||
'srpName': pool_record['srpName'],
|
|
||||||
'array': pool_record['SerialNumber']})
|
|
||||||
LOG.warning("Pool_name is not present in the extra_specs "
|
|
||||||
"- using default pool %(pool_name)s.",
|
|
||||||
{'pool_name': pool_name})
|
|
||||||
pool_details = pool_name.split('+')
|
pool_details = pool_name.split('+')
|
||||||
slo_from_extra_spec = pool_details[0]
|
slo_from_extra_spec = pool_details[0]
|
||||||
workload_from_extra_spec = pool_details[1]
|
workload_from_extra_spec = pool_details[1]
|
||||||
|
# Check if legacy pool chosen
|
||||||
|
if workload_from_extra_spec == pool_record['srpName']:
|
||||||
|
workload_from_extra_spec = 'NONE'
|
||||||
|
|
||||||
|
elif pool_record.get('ServiceLevel'):
|
||||||
|
slo_from_extra_spec = pool_record['ServiceLevel']
|
||||||
|
workload_from_extra_spec = pool_record.get('Workload', 'None')
|
||||||
|
LOG.info("Pool_name is not present in the extra_specs "
|
||||||
|
"- using slo/ workload from xml file: %(slo)s/%(wl)s.",
|
||||||
|
{'slo': slo_from_extra_spec,
|
||||||
|
'wl': workload_from_extra_spec})
|
||||||
|
|
||||||
|
else:
|
||||||
|
slo_list = self.rest.get_slo_list(pool_record['SerialNumber'])
|
||||||
|
if 'Optimized' in slo_list:
|
||||||
|
slo_from_extra_spec = 'Optimized'
|
||||||
|
elif 'Diamond' in slo_list:
|
||||||
|
slo_from_extra_spec = 'Diamond'
|
||||||
|
else:
|
||||||
|
slo_from_extra_spec = 'None'
|
||||||
|
workload_from_extra_spec = 'NONE'
|
||||||
|
LOG.warning("Pool_name is not present in the extra_specs"
|
||||||
|
"and no slo/ workload information is present "
|
||||||
|
"in the xml file - using default slo/ workload "
|
||||||
|
"combination: %(slo)s/%(wl)s.",
|
||||||
|
{'slo': slo_from_extra_spec,
|
||||||
|
'wl': workload_from_extra_spec})
|
||||||
# Standardize slo and workload 'NONE' naming conventions
|
# Standardize slo and workload 'NONE' naming conventions
|
||||||
if workload_from_extra_spec.lower() == 'none':
|
if workload_from_extra_spec.lower() == 'none':
|
||||||
workload_from_extra_spec = 'NONE'
|
workload_from_extra_spec = 'NONE'
|
||||||
@ -1432,10 +1464,8 @@ class VMAXCommon(object):
|
|||||||
else:
|
else:
|
||||||
extra_specs.pop(utils.DISABLECOMPRESSION, None)
|
extra_specs.pop(utils.DISABLECOMPRESSION, None)
|
||||||
|
|
||||||
LOG.debug("SRP is: %(srp)s "
|
LOG.debug("SRP is: %(srp)s, Array is: %(array)s "
|
||||||
"Array is: %(array)s "
|
"SLO is: %(slo)s, Workload is: %(workload)s.",
|
||||||
"SLO is: %(slo)s "
|
|
||||||
"Workload is: %(workload)s.",
|
|
||||||
{'srp': extra_specs[utils.SRP],
|
{'srp': extra_specs[utils.SRP],
|
||||||
'array': extra_specs[utils.ARRAY],
|
'array': extra_specs[utils.ARRAY],
|
||||||
'slo': extra_specs[utils.SLO],
|
'slo': extra_specs[utils.SLO],
|
||||||
@ -2127,7 +2157,11 @@ class VMAXCommon(object):
|
|||||||
if (isinstance(loc, six.string_types)
|
if (isinstance(loc, six.string_types)
|
||||||
and isinstance(rep_data, six.string_types)):
|
and isinstance(rep_data, six.string_types)):
|
||||||
name = ast.literal_eval(loc)
|
name = ast.literal_eval(loc)
|
||||||
|
try:
|
||||||
array = name['array']
|
array = name['array']
|
||||||
|
except KeyError:
|
||||||
|
array = (name['keybindings']
|
||||||
|
['SystemName'].split('+')[1].strip('-'))
|
||||||
rep_extra_specs = self._get_replication_extra_specs(
|
rep_extra_specs = self._get_replication_extra_specs(
|
||||||
extra_specs, self.rep_config)
|
extra_specs, self.rep_config)
|
||||||
(target_device, remote_array, rdf_group_no,
|
(target_device, remote_array, rdf_group_no,
|
||||||
@ -2320,7 +2354,11 @@ class VMAXCommon(object):
|
|||||||
try:
|
try:
|
||||||
name = ast.literal_eval(loc)
|
name = ast.literal_eval(loc)
|
||||||
replication_keybindings = ast.literal_eval(rep_data)
|
replication_keybindings = ast.literal_eval(rep_data)
|
||||||
|
try:
|
||||||
array = name['array']
|
array = name['array']
|
||||||
|
except KeyError:
|
||||||
|
array = (name['keybindings']
|
||||||
|
['SystemName'].split('+')[1].strip('-'))
|
||||||
device_id = self._find_device_on_array(vol, {utils.ARRAY: array})
|
device_id = self._find_device_on_array(vol, {utils.ARRAY: array})
|
||||||
|
|
||||||
(target_device, remote_array, rdf_group,
|
(target_device, remote_array, rdf_group,
|
||||||
|
@ -289,8 +289,12 @@ class VMAXFCDriver(driver.FibreChannelDriver):
|
|||||||
loc = volume.provider_location
|
loc = volume.provider_location
|
||||||
name = ast.literal_eval(loc)
|
name = ast.literal_eval(loc)
|
||||||
host = connector['host']
|
host = connector['host']
|
||||||
|
try:
|
||||||
array = name['array']
|
array = name['array']
|
||||||
device_id = name['device_id']
|
device_id = name['device_id']
|
||||||
|
except KeyError:
|
||||||
|
array = name['keybindings']['SystemName'].split('+')[1].strip('-')
|
||||||
|
device_id = name['keybindings']['DeviceID']
|
||||||
LOG.debug("Start FC detach process for volume: %(volume)s.",
|
LOG.debug("Start FC detach process for volume: %(volume)s.",
|
||||||
{'volume': volume.name})
|
{'volume': volume.name})
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import random
|
import random
|
||||||
@ -45,7 +46,7 @@ ARRAY = 'array'
|
|||||||
SLO = 'slo'
|
SLO = 'slo'
|
||||||
WORKLOAD = 'workload'
|
WORKLOAD = 'workload'
|
||||||
SRP = 'srp'
|
SRP = 'srp'
|
||||||
PORTGROUPNAME = 'port_group_name'
|
PORTGROUPNAME = 'storagetype:portgroupname'
|
||||||
DEVICE_ID = 'device_id'
|
DEVICE_ID = 'device_id'
|
||||||
INITIATOR_CHECK = 'initiator_check'
|
INITIATOR_CHECK = 'initiator_check'
|
||||||
SG_NAME = 'storagegroup_name'
|
SG_NAME = 'storagegroup_name'
|
||||||
@ -340,6 +341,8 @@ class VMAXUtils(object):
|
|||||||
if srp_name is None:
|
if srp_name is None:
|
||||||
LOG.error("SRP Name must be in the file %(file)s.",
|
LOG.error("SRP Name must be in the file %(file)s.",
|
||||||
{'file': file_name})
|
{'file': file_name})
|
||||||
|
slo = self._process_tag(dom, 'ServiceLevel')
|
||||||
|
workload = self._process_tag(dom, 'Workload')
|
||||||
kwargs = (
|
kwargs = (
|
||||||
{'RestServerIp': connargs['RestServerIp'],
|
{'RestServerIp': connargs['RestServerIp'],
|
||||||
'RestServerPort': connargs['RestServerPort'],
|
'RestServerPort': connargs['RestServerPort'],
|
||||||
@ -350,6 +353,8 @@ class VMAXUtils(object):
|
|||||||
'SerialNumber': serialnumber,
|
'SerialNumber': serialnumber,
|
||||||
'srpName': srp_name,
|
'srpName': srp_name,
|
||||||
'PortGroup': portgroup})
|
'PortGroup': portgroup})
|
||||||
|
if slo is not None:
|
||||||
|
kwargs.update({'ServiceLevel': slo, 'Workload': workload})
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
@ -658,3 +663,25 @@ class VMAXUtils(object):
|
|||||||
LOG.debug("Retries are set at: %(retries)s.",
|
LOG.debug("Retries are set at: %(retries)s.",
|
||||||
{'retries': retries})
|
{'retries': retries})
|
||||||
return extra_specs
|
return extra_specs
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_legacy_pools(pools):
|
||||||
|
"""Add legacy pools to allow extending a volume after upgrade.
|
||||||
|
|
||||||
|
:param pools: the pool list
|
||||||
|
:return: pools - the updated pool list
|
||||||
|
"""
|
||||||
|
extra_pools = []
|
||||||
|
for pool in pools:
|
||||||
|
if 'none' in pool['pool_name'].lower():
|
||||||
|
extra_pools.append(pool)
|
||||||
|
for pool in extra_pools:
|
||||||
|
slo = pool['pool_name'].split('+')[0]
|
||||||
|
srp = pool['pool_name'].split('+')[2]
|
||||||
|
array = pool['pool_name'].split('+')[3]
|
||||||
|
new_pool_name = ('%(slo)s+%(srp)s+%(array)s'
|
||||||
|
% {'slo': slo, 'srp': srp, 'array': array})
|
||||||
|
new_pool = deepcopy(pool)
|
||||||
|
new_pool['pool_name'] = new_pool_name
|
||||||
|
pools.append(new_pool)
|
||||||
|
return pools
|
||||||
|
Loading…
x
Reference in New Issue
Block a user