Merge "VMAX driver - Errors extending replicated volumes"

This commit is contained in:
Zuul 2018-01-17 16:56:46 +00:00 committed by Gerrit Code Review
commit 2f23983353
3 changed files with 55 additions and 37 deletions

View File

@ -3072,10 +3072,17 @@ class VMAXProvisionTest(test.TestCase):
device_id = self.data.device_id device_id = self.data.device_id
new_size = '3' new_size = '3'
extra_specs = self.data.extra_specs extra_specs = self.data.extra_specs
with mock.patch.object(self.provision.rest, 'extend_volume'): with mock.patch.object(self.provision.rest, 'extend_volume'
) as mock_ex:
self.provision.extend_volume(array, device_id, new_size, self.provision.extend_volume(array, device_id, new_size,
extra_specs) extra_specs)
self.provision.rest.extend_volume.assert_called_once_with( mock_ex.assert_called_once_with(
array, device_id, new_size, extra_specs)
mock_ex.reset_mock()
# Pass in rdf group
self.provision.extend_volume(array, device_id, new_size,
extra_specs, self.data.rdf_group_no)
mock_ex.assert_called_once_with(
array, device_id, new_size, extra_specs) array, device_id, new_size, extra_specs)
def test_get_srp_pool_stats(self): def test_get_srp_pool_stats(self):
@ -3167,6 +3174,15 @@ class VMAXProvisionTest(test.TestCase):
target_device = self.data.device_id2 target_device = self.data.device_id2
rdf_group_name = self.data.rdf_group_name rdf_group_name = self.data.rdf_group_name
rep_extra_specs = self.data.rep_extra_specs rep_extra_specs = self.data.rep_extra_specs
# State is suspended
self.provision.break_rdf_relationship(
array, device_id, target_device,
rdf_group_name, rep_extra_specs, "Suspended")
mock_mod.assert_not_called()
mock_del.assert_called_once_with(
array, device_id, rdf_group_name)
mock_del.reset_mock()
# State is synchronized
self.provision.break_rdf_relationship( self.provision.break_rdf_relationship(
array, device_id, target_device, array, device_id, target_device,
rdf_group_name, rep_extra_specs, "Synchronized") rdf_group_name, rep_extra_specs, "Synchronized")

View File

@ -2931,9 +2931,9 @@ class VMAXCommon(object):
"""Extend a replication-enabled volume. """Extend a replication-enabled volume.
Cannot extend volumes in a synchronization pair where the source Cannot extend volumes in a synchronization pair where the source
and/or target arrays are running HyperMax versions < 5978, or for and/or target arrays are running HyperMax versions < 5978. Must first
Metro-enabled volumes. Must first break the relationship, extend break the relationship, extend them separately, then recreate the
them separately, then recreate the pair. pair. Extending Metro protected volumes is not supported.
:param array: the array serial number :param array: the array serial number
:param volume: the volume objcet :param volume: the volume objcet
:param device_id: the volume device id :param device_id: the volume device id
@ -2949,8 +2949,7 @@ class VMAXCommon(object):
__, remote_array = self.get_rdf_details(array) __, remote_array = self.get_rdf_details(array)
if self.rest.is_next_gen_array(remote_array): if self.rest.is_next_gen_array(remote_array):
ode_replication = True ode_replication = True
if (self.utils.is_metro_device(self.rep_config, extra_specs) if self.utils.is_metro_device(self.rep_config, extra_specs):
and not self.allow_delete_metro):
allow_extend = False allow_extend = False
if allow_extend is True or ode_replication is True: if allow_extend is True or ode_replication is True:
try: try:
@ -2960,18 +2959,16 @@ class VMAXCommon(object):
array, volume, device_id)) array, volume, device_id))
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)
lock_rdf_group = rdf_group
if not ode_replication: if not ode_replication:
# Volume must be removed from replication (storage) group # Volume must be removed from replication (storage) group
# before the replication relationship can be ended (cannot # before the replication relationship can be ended (cannot
# have a mix of replicated and non-replicated volumes as # have a mix of replicated and non-replicated volumes as
# the SRDF groups become unmanageable), but # the SRDF groups become unmanageable)
# leave the vol in metro management group for now lock_rdf_group = None
metro_grp = self.utils.get_async_rdf_managed_grp_name(
self.rep_config) if self.utils.is_metro_device(
self.rep_config, rep_extra_specs) else None
self.masking.remove_and_reset_members( self.masking.remove_and_reset_members(
array, volume, device_id, volume_name, array, volume, device_id, volume_name,
extra_specs, False, async_grp=metro_grp) extra_specs, False)
# Repeat on target side # Repeat on target side
self.masking.remove_and_reset_members( self.masking.remove_and_reset_members(
@ -2979,17 +2976,9 @@ class VMAXCommon(object):
rep_extra_specs, False) rep_extra_specs, False)
LOG.info("Breaking replication relationship...") LOG.info("Breaking replication relationship...")
if self.utils.is_metro_device( self.provision.break_rdf_relationship(
self.rep_config, rep_extra_specs): array, device_id, target_device, rdf_group,
rep_extra_specs['allow_del_metro'] = ( rep_extra_specs, pair_state)
self.allow_delete_metro)
self._cleanup_metro_target(
array, device_id, target_device,
rdf_group, rep_extra_specs)
else:
self.provision.break_rdf_relationship(
array, device_id, target_device, rdf_group,
rep_extra_specs, pair_state)
# Extend the target volume # Extend the target volume
LOG.info("Extending target volume...") LOG.info("Extending target volume...")
@ -2997,13 +2986,14 @@ class VMAXCommon(object):
r2_size = self.rest.get_size_of_device_on_array( r2_size = self.rest.get_size_of_device_on_array(
remote_array, target_device) remote_array, target_device)
if int(r2_size) < int(new_size): if int(r2_size) < int(new_size):
self.provision.extend_volume(remote_array, target_device, self.provision.extend_volume(
new_size, rep_extra_specs) remote_array, target_device, new_size,
rep_extra_specs, lock_rdf_group)
# Extend the source volume # Extend the source volume
LOG.info("Extending source volume...") LOG.info("Extending source volume...")
self.provision.extend_volume( self.provision.extend_volume(
array, device_id, new_size, extra_specs) array, device_id, new_size, extra_specs, lock_rdf_group)
if not ode_replication: if not ode_replication:
# Re-create replication relationship # Re-create replication relationship
@ -3026,9 +3016,9 @@ class VMAXCommon(object):
else: else:
exception_message = (_( exception_message = (_(
"Extending a replicated volume is not " "Extending a replicated volume is not permitted on this "
"permitted on this backend. Please contact " "backend. Please contact your administrator. Note that "
"your administrator.")) "you cannot extend SRDF/Metro protected volumes."))
LOG.error(exception_message) LOG.error(exception_message)
raise exception.VolumeBackendAPIException(data=exception_message) raise exception.VolumeBackendAPIException(data=exception_message)

View File

@ -344,20 +344,29 @@ class VMAXProvision(object):
list_volume_pairs=list_device_pairs) list_volume_pairs=list_device_pairs)
self.delete_volume_snap(array, snap_name, source_devices) self.delete_volume_snap(array, snap_name, source_devices)
def extend_volume(self, array, device_id, new_size, extra_specs): def extend_volume(self, array, device_id, new_size, extra_specs,
rdf_group=None):
"""Extend a volume. """Extend a volume.
:param array: the array serial number :param array: the array serial number
:param device_id: the volume device id :param device_id: the volume device id
:param new_size: the new size (GB) :param new_size: the new size (GB)
:param extra_specs: the extra specifications :param extra_specs: the extra specifications
:param rdf_group: the rdf group number, if required
:returns: status_code :returns: status_code
""" """
start_time = time.time() start_time = time.time()
self.rest.extend_volume(array, device_id, new_size, extra_specs) if rdf_group:
LOG.debug("Extend VMAX volume took: %(delta)s H:MM:SS.", @coordination.synchronized('emc-rg-{rdf_group}')
{'delta': self.utils.get_time_delta(start_time, def _extend_replicated_volume(rdf_group):
time.time())}) self.rest.extend_volume(array, device_id,
new_size, extra_specs)
_extend_replicated_volume(rdf_group)
else:
self.rest.extend_volume(array, device_id, new_size, extra_specs)
LOG.debug("Extend VMAX volume took: %(delta)s H:MM:SS.",
{'delta': self.utils.get_time_delta(start_time,
time.time())})
def get_srp_pool_stats(self, array, array_info): def get_srp_pool_stats(self, array, array_info):
"""Get the srp capacity stats. """Get the srp capacity stats.
@ -495,8 +504,11 @@ class VMAXProvision(object):
self.rest.wait_for_rdf_consistent_state( self.rest.wait_for_rdf_consistent_state(
array, device_id, target_device, array, device_id, target_device,
rep_extra_specs, state) rep_extra_specs, state)
self.rest.modify_rdf_device_pair( if state.lower() == utils.RDF_SUSPENDED_STATE:
array, device_id, rdf_group, rep_extra_specs, suspend=True) LOG.info("RDF pair is already suspended")
else:
self.rest.modify_rdf_device_pair(
array, device_id, rdf_group, rep_extra_specs, suspend=True)
self.delete_rdf_pair(array, device_id, rdf_group, self.delete_rdf_pair(array, device_id, rdf_group,
target_device, rep_extra_specs) target_device, rep_extra_specs)