Merge "VMAX driver - Cannot extend volumes in a replication relationship"
This commit is contained in:
commit
4d58665b69
@ -3372,9 +3372,10 @@ class VMAXCommonTest(test.TestCase):
|
||||
self.common._unmap_lun.assert_called_once_with(
|
||||
volume, connector)
|
||||
|
||||
@mock.patch.object(rest.VMAXRest, 'is_next_gen_array', return_value=True)
|
||||
@mock.patch.object(common.VMAXCommon, '_sync_check')
|
||||
@mock.patch.object(provision.VMAXProvision, 'extend_volume')
|
||||
def test_extend_volume_success(self, mock_extend, mock_sync):
|
||||
def test_extend_volume_success(self, mock_extend, mock_sync, mock_newgen):
|
||||
volume = self.data.test_volume
|
||||
array = self.data.array
|
||||
device_id = self.data.device_id
|
||||
@ -3382,7 +3383,13 @@ class VMAXCommonTest(test.TestCase):
|
||||
ref_extra_specs = deepcopy(self.data.extra_specs_intervals_set)
|
||||
ref_extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||
with mock.patch.object(self.rest, 'is_vol_in_rep_session',
|
||||
return_value=(False, False, None)):
|
||||
side_effect=[(False, False, None),
|
||||
(False, True, None)]):
|
||||
self.common.extend_volume(volume, new_size)
|
||||
mock_extend.assert_called_once_with(
|
||||
array, device_id, new_size, ref_extra_specs)
|
||||
# Success, with snapshot, on new VMAX array
|
||||
mock_extend.reset_mock()
|
||||
self.common.extend_volume(volume, new_size)
|
||||
mock_extend.assert_called_once_with(
|
||||
array, device_id, new_size, ref_extra_specs)
|
||||
@ -6194,15 +6201,15 @@ class VMAXCommonReplicationTest(test.TestCase):
|
||||
self.data.test_volume, self.data.connector)
|
||||
mock_es.assert_called_once_with(extra_specs, rep_config)
|
||||
|
||||
@mock.patch.object(rest.VMAXRest, 'is_vol_in_rep_session',
|
||||
return_value=(False, False, None))
|
||||
@mock.patch.object(common.VMAXCommon, 'extend_volume_is_replicated')
|
||||
@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, mock_ex_re,
|
||||
mock_is_re):
|
||||
extra_specs = deepcopy(self.extra_specs)
|
||||
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||
volume_name = self.data.test_volume.name
|
||||
with mock.patch.object(self.rest, 'is_vol_in_rep_session',
|
||||
return_value=(False, False, None)):
|
||||
with mock.patch.object(
|
||||
self.common, 'extend_volume_is_replicated') as mock_ex_re:
|
||||
self.common.extend_volume(self.data.test_volume, '5')
|
||||
mock_ex_re.assert_called_once_with(
|
||||
self.data.array, self.data.test_volume,
|
||||
@ -6475,6 +6482,15 @@ class VMAXCommonReplicationTest(test.TestCase):
|
||||
'vol1', '5', self.data.extra_specs_rep_enabled)
|
||||
self.assertEqual(2, mock_remove.call_count)
|
||||
self.assertEqual(2, mock_extend.call_count)
|
||||
mock_remove.reset_mock()
|
||||
mock_extend.reset_mock()
|
||||
with mock.patch.object(self.rest, 'is_next_gen_array',
|
||||
return_value=True):
|
||||
self.common.extend_volume_is_replicated(
|
||||
self.data.array, self.data.test_volume, self.data.device_id,
|
||||
'vol1', '5', self.data.extra_specs_rep_enabled)
|
||||
mock_remove.assert_not_called()
|
||||
self.assertEqual(2, mock_extend.call_count)
|
||||
|
||||
def test_extend_volume_is_replicated_exception(self):
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
|
@ -683,12 +683,15 @@ class VMAXCommon(object):
|
||||
raise exception.VolumeBackendAPIException(data=exception_message)
|
||||
__, snapvx_src, __ = self.rest.is_vol_in_rep_session(array, device_id)
|
||||
if snapvx_src:
|
||||
if not self.rest.is_next_gen_array(array):
|
||||
exception_message = (
|
||||
_("The volume: %(volume)s is a snapshot source. Extending a "
|
||||
"volume with snapVx snapshots is not supported. Exiting...")
|
||||
% {'volume': volume_name})
|
||||
_("The volume: %(volume)s is a snapshot source. "
|
||||
"Extending a volume with snapVx snapshots is only "
|
||||
"supported on VMAX from HyperMaxOS version 5978 "
|
||||
"onwards. Exiting...") % {'volume': volume_name})
|
||||
LOG.error(exception_message)
|
||||
raise exception.VolumeBackendAPIException(data=exception_message)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exception_message)
|
||||
|
||||
if int(original_vol_size) > int(new_size):
|
||||
exception_message = (_(
|
||||
@ -2605,22 +2608,31 @@ class VMAXCommon(object):
|
||||
:param new_size: the new size the volume should be
|
||||
:param extra_specs: extra specifications
|
||||
"""
|
||||
if self.extend_replicated_vol is True:
|
||||
ode_replication = False
|
||||
if self.utils.is_replication_enabled(extra_specs):
|
||||
if self.rest.is_next_gen_array(array):
|
||||
# Check if remote array is next gen
|
||||
__, remote_array = self.get_rdf_details(array)
|
||||
if self.rest.is_next_gen_array(remote_array):
|
||||
ode_replication = True
|
||||
if self.extend_replicated_vol is True or ode_replication is True:
|
||||
try:
|
||||
(target_device, remote_array, rdf_group,
|
||||
local_vol_state, pair_state) = (
|
||||
self.get_remote_target_device(array, volume, device_id))
|
||||
|
||||
self.get_remote_target_device(
|
||||
array, volume, device_id))
|
||||
rep_extra_specs = self._get_replication_extra_specs(
|
||||
extra_specs, self.rep_config)
|
||||
if not ode_replication:
|
||||
# Volume must be removed from replication (storage) group
|
||||
# before the replication relationship can be ended (cannot
|
||||
# have a mix of replicated and non-replicated volumes as
|
||||
# the SRDF groups become unmanageable).
|
||||
self.masking.remove_and_reset_members(
|
||||
array, volume, device_id, volume_name, extra_specs, False)
|
||||
array, volume, device_id, volume_name,
|
||||
extra_specs, False)
|
||||
|
||||
# Repeat on target side
|
||||
rep_extra_specs = self._get_replication_extra_specs(
|
||||
extra_specs, self.rep_config)
|
||||
self.masking.remove_and_reset_members(
|
||||
remote_array, volume, target_device, volume_name,
|
||||
rep_extra_specs, False)
|
||||
@ -2630,16 +2642,21 @@ class VMAXCommon(object):
|
||||
array, device_id, target_device,
|
||||
rdf_group, rep_extra_specs, pair_state)
|
||||
|
||||
# Extend the target volume
|
||||
LOG.info("Extending target volume...")
|
||||
# Check to make sure the R2 device requires extending first...
|
||||
r2_size = self.rest.get_size_of_device_on_array(
|
||||
remote_array, target_device)
|
||||
if int(r2_size) < int(new_size):
|
||||
self.provision.extend_volume(remote_array, target_device,
|
||||
new_size, rep_extra_specs)
|
||||
|
||||
# Extend the source volume
|
||||
LOG.info("Extending source volume...")
|
||||
self.provision.extend_volume(
|
||||
array, device_id, new_size, extra_specs)
|
||||
|
||||
# Extend the target volume
|
||||
LOG.info("Extending target volume...")
|
||||
self.provision.extend_volume(
|
||||
remote_array, target_device, new_size, rep_extra_specs)
|
||||
|
||||
if not ode_replication:
|
||||
# Re-create replication relationship
|
||||
LOG.info("Recreating replication relationship...")
|
||||
self.setup_volume_replication(
|
||||
|
Loading…
x
Reference in New Issue
Block a user