Merge "Dell PowerMax: RDF consistency exempt"
This commit is contained in:
@@ -2085,12 +2085,14 @@ class PowerMaxRestTest(test.TestCase):
|
|||||||
rdf_group_no = self.data.rdf_group_no_1
|
rdf_group_no = self.data.rdf_group_no_1
|
||||||
sg_name = self.data.default_sg_re_enabled
|
sg_name = self.data.default_sg_re_enabled
|
||||||
rep_extra_specs = self.data.rep_extra_specs
|
rep_extra_specs = self.data.rep_extra_specs
|
||||||
|
|
||||||
self.rest.srdf_suspend_replication(
|
self.rest.srdf_suspend_replication(
|
||||||
array_id, sg_name, rdf_group_no, rep_extra_specs)
|
array_id, sg_name, rdf_group_no, rep_extra_specs)
|
||||||
|
# Replication mode in this test is synchronous, so the expecation
|
||||||
|
# is that the consistency exempt flag is false.
|
||||||
mck_modify.assert_called_once_with(
|
mck_modify.assert_called_once_with(
|
||||||
array_id, rdf_group_no, sg_name,
|
array_id, rdf_group_no, sg_name,
|
||||||
{'suspend': {'force': 'true'}, 'action': 'Suspend'},
|
{'suspend': {'force': 'true', 'consExempt': 'false'},
|
||||||
|
'action': 'Suspend'},
|
||||||
rep_extra_specs, 'Suspend SRDF Group Replication')
|
rep_extra_specs, 'Suspend SRDF Group Replication')
|
||||||
|
|
||||||
@mock.patch.object(rest.PowerMaxRest, 'srdf_modify_group')
|
@mock.patch.object(rest.PowerMaxRest, 'srdf_modify_group')
|
||||||
@@ -2102,12 +2104,14 @@ class PowerMaxRestTest(test.TestCase):
|
|||||||
rdf_group_no = self.data.rdf_group_no_1
|
rdf_group_no = self.data.rdf_group_no_1
|
||||||
sg_name = self.data.default_sg_re_enabled
|
sg_name = self.data.default_sg_re_enabled
|
||||||
rep_extra_specs = self.data.rep_extra_specs
|
rep_extra_specs = self.data.rep_extra_specs
|
||||||
|
|
||||||
self.rest.srdf_suspend_replication(
|
self.rest.srdf_suspend_replication(
|
||||||
array_id, sg_name, rdf_group_no, rep_extra_specs)
|
array_id, sg_name, rdf_group_no, rep_extra_specs)
|
||||||
|
# Replication mode in this test is synchronous, so the expecation
|
||||||
|
# is that the consistency exempt flag is false.
|
||||||
mck_modify.assert_called_once_with(
|
mck_modify.assert_called_once_with(
|
||||||
array_id, rdf_group_no, sg_name,
|
array_id, rdf_group_no, sg_name,
|
||||||
{'suspend': {'force': 'true'}, 'action': 'Suspend'},
|
{'suspend': {'force': 'true', 'consExempt': 'false'},
|
||||||
|
'action': 'Suspend'},
|
||||||
rep_extra_specs, 'Suspend SRDF Group Replication')
|
rep_extra_specs, 'Suspend SRDF Group Replication')
|
||||||
|
|
||||||
@mock.patch.object(rest.PowerMaxRest, 'srdf_modify_group')
|
@mock.patch.object(rest.PowerMaxRest, 'srdf_modify_group')
|
||||||
|
@@ -2906,21 +2906,6 @@ class PowerMaxRest(object):
|
|||||||
number = None
|
number = None
|
||||||
return number
|
return number
|
||||||
|
|
||||||
def _get_async_payload_info(self, array, rdf_group_no):
|
|
||||||
"""Get the payload details for an async create pair.
|
|
||||||
|
|
||||||
:param array: the array serial number
|
|
||||||
:param rdf_group_no: the rdf group number
|
|
||||||
:returns: payload_update
|
|
||||||
"""
|
|
||||||
num_vols, payload_update = 0, {}
|
|
||||||
rdfg_details = self.get_rdf_group(array, rdf_group_no)
|
|
||||||
if rdfg_details is not None and rdfg_details.get('numDevices'):
|
|
||||||
num_vols = int(rdfg_details['numDevices'])
|
|
||||||
if num_vols > 0:
|
|
||||||
payload_update = {'exempt': 'true'}
|
|
||||||
return payload_update
|
|
||||||
|
|
||||||
def get_metro_payload_info(self, array, payload,
|
def get_metro_payload_info(self, array, payload,
|
||||||
rdf_group_no, extra_specs, next_gen):
|
rdf_group_no, extra_specs, next_gen):
|
||||||
"""Get the payload details for a metro active create pair.
|
"""Get the payload details for a metro active create pair.
|
||||||
@@ -3026,15 +3011,48 @@ class PowerMaxRest(object):
|
|||||||
|
|
||||||
if group_state:
|
if group_state:
|
||||||
group_state = [x.lower() for x in group_state]
|
group_state = [x.lower() for x in group_state]
|
||||||
|
|
||||||
if len(group_state) == 1 and utils.RDF_SUSPENDED_STATE in group_state:
|
if len(group_state) == 1 and utils.RDF_SUSPENDED_STATE in group_state:
|
||||||
LOG.info('SRDF Group %(grp_num)s is already in a suspended state',
|
LOG.info('SRDF Group %(grp_num)s is already in a suspended state',
|
||||||
{'grp_num': rdf_group_no})
|
{'grp_num': rdf_group_no})
|
||||||
else:
|
else:
|
||||||
|
cons_exempt = self._get_cons_exempt(
|
||||||
|
array_id, storage_group, rdf_group_no,
|
||||||
|
rep_extra_specs['rep_mode'])
|
||||||
|
payload = {"suspend": {"force": "true"}, "action": "Suspend"}
|
||||||
|
payload["suspend"]["consExempt"] = (
|
||||||
|
"true" if cons_exempt else "false")
|
||||||
self.srdf_modify_group(
|
self.srdf_modify_group(
|
||||||
array_id, rdf_group_no, storage_group,
|
array_id, rdf_group_no, storage_group,
|
||||||
{"suspend": {"force": "true"}, "action": "Suspend"},
|
payload, rep_extra_specs,
|
||||||
rep_extra_specs, 'Suspend SRDF Group Replication')
|
'Suspend SRDF Group Replication')
|
||||||
|
|
||||||
|
def _get_cons_exempt(self, array_id, storage_group, rdf_group_no,
|
||||||
|
rep_mode=None):
|
||||||
|
"""Get the consistency exempt flag for a storage group.
|
||||||
|
|
||||||
|
:param array_id: array serial number
|
||||||
|
:param storage_group: storage group name
|
||||||
|
:param rdf_group_no: RDF group number
|
||||||
|
:param rep_mode: Replication mode of the SRDF session
|
||||||
|
:returns: A boolean indicating if consistency is exempt
|
||||||
|
"""
|
||||||
|
if not rep_mode:
|
||||||
|
return False
|
||||||
|
|
||||||
|
resource = ('storagegroup/%(sg)s/rdf_group/%(rdfg)s' % {
|
||||||
|
'sg': storage_group, 'rdfg': rdf_group_no})
|
||||||
|
rdf_group = self.get_resource(array_id, REPLICATION, resource)
|
||||||
|
modes = list(rep_mode)
|
||||||
|
|
||||||
|
if rdf_group and rdf_group.get('modes'):
|
||||||
|
modes.append(rdf_group.get('modes'))
|
||||||
|
# Ensure we don't see the error message:
|
||||||
|
# "A problem occurred modifying the Storage Group
|
||||||
|
# SRDF Group resource: The device is not in
|
||||||
|
# asynchronous mode"
|
||||||
|
cons_exempt = utils.REP_ASYNC in modes
|
||||||
|
LOG.debug("Consistency exempt: %s", cons_exempt)
|
||||||
|
return cons_exempt
|
||||||
|
|
||||||
def srdf_resume_replication(self, array_id, storage_group, rdf_group_no,
|
def srdf_resume_replication(self, array_id, storage_group, rdf_group_no,
|
||||||
rep_extra_specs, async_call=True):
|
rep_extra_specs, async_call=True):
|
||||||
|
17
releasenotes/notes/bp-dell-powermax-consistency-exempt.yaml
Normal file
17
releasenotes/notes/bp-dell-powermax-consistency-exempt.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Dell PowerMax Driver: use consistency exempt flag consistently
|
||||||
|
PowerMax allows volumes to be added, removed, or suspended without
|
||||||
|
affecting the state of the SRDF/A or SRDF/Metro session or requiring
|
||||||
|
that other volumes in the session be suspended. Known as --exempt for
|
||||||
|
symcli and editStorageGroupActionParam in the PowerMax REST API,
|
||||||
|
this capability is available for an SRDF group supporting an active
|
||||||
|
SRDF/A session or an active SRDF/Metro session.
|
||||||
|
|
||||||
|
The PowerMax Cinder driver currently uses the exempt flag when
|
||||||
|
volumes are added to SRDF groups, but not when volumes are
|
||||||
|
removed. This incurs an unnecessary performance penalty that is
|
||||||
|
resolved by this change.
|
||||||
|
|
||||||
|
Blueprint: dell-powermax-srdf-exempt
|
Reference in New Issue
Block a user