Merge "Dell EMC: PowerMax - Configurable SRDF snapshots"
This commit is contained in:
commit
08835cab08
@ -450,6 +450,7 @@ class PowerMaxData(object):
|
||||
rep_extra_specs['sync_retries'] = 200
|
||||
rep_extra_specs['rdf_group_label'] = rdf_group_name_1
|
||||
rep_extra_specs['rdf_group_no'] = rdf_group_no_1
|
||||
rep_extra_specs[utils.DISABLE_PROTECTED_SNAP] = False
|
||||
rep_extra_specs2 = deepcopy(rep_extra_specs)
|
||||
rep_extra_specs2[utils.PORTGROUPNAME] = port_group_name_f
|
||||
rep_extra_specs3 = deepcopy(rep_extra_specs)
|
||||
|
@ -105,6 +105,7 @@ class PowerMaxReplicationTest(test.TestCase):
|
||||
extra_specs[utils.PORTGROUPNAME] = self.data.port_group_name_f
|
||||
extra_specs[utils.IS_RE] = True
|
||||
extra_specs[utils.FORCE_VOL_EDIT] = True
|
||||
extra_specs[utils.DISABLE_PROTECTED_SNAP] = False
|
||||
rep_config = self.data.rep_config_sync
|
||||
rep_config = deepcopy(self.data.rep_config_sync)
|
||||
rep_config[utils.RDF_CONS_EXEMPT] = False
|
||||
|
@ -1574,7 +1574,8 @@ class PowerMaxCommon(object):
|
||||
if rep_config.get(utils.METROBIAS):
|
||||
extra_specs[utils.METROBIAS] = (
|
||||
rep_config[utils.METROBIAS])
|
||||
|
||||
extra_specs[utils.DISABLE_PROTECTED_SNAP] =\
|
||||
self.utils.is_protected_snap_disabled(extra_specs)
|
||||
return extra_specs, qos_specs
|
||||
|
||||
def _get_replicated_volume_backend_id(self, volume):
|
||||
@ -2074,14 +2075,23 @@ class PowerMaxCommon(object):
|
||||
return volume_name
|
||||
|
||||
array = extra_specs[utils.ARRAY]
|
||||
if self.utils.is_replication_enabled(extra_specs):
|
||||
self._validate_rdfg_status(array, extra_specs)
|
||||
dps = self.utils.is_protected_snap_disabled(extra_specs)
|
||||
# If a volume is not replicated and has the
|
||||
# powermax:disable_protected_snap set to True,
|
||||
# then clean up the volume without replication cleanup.
|
||||
if dps and volume.replication_status is None:
|
||||
self.masking.remove_and_reset_members(
|
||||
array, volume, device_id, volume_name, extra_specs, False)
|
||||
self._cleanup_device_retry(array, device_id, extra_specs)
|
||||
else:
|
||||
if self.utils.is_replication_enabled(extra_specs):
|
||||
self._validate_rdfg_status(array, extra_specs)
|
||||
|
||||
self._cleanup_device_retry(array, device_id, extra_specs)
|
||||
self._cleanup_device_retry(array, device_id, extra_specs)
|
||||
|
||||
# Remove from any storage groups and cleanup replication
|
||||
self._remove_vol_and_cleanup_replication(
|
||||
array, device_id, volume_name, extra_specs, volume)
|
||||
# Remove from any storage groups and cleanup replication
|
||||
self._remove_vol_and_cleanup_replication(
|
||||
array, device_id, volume_name, extra_specs, volume)
|
||||
self._delete_from_srp(
|
||||
array, device_id, volume_name, extra_specs)
|
||||
return volume_name
|
||||
@ -2898,6 +2908,10 @@ class PowerMaxCommon(object):
|
||||
create_snap, copy_mode, rep_extra_specs = False, False, dict()
|
||||
volume_dict = self.rest.get_volume(array, source_device_id)
|
||||
replication_enabled = self.utils.is_replication_enabled(extra_specs)
|
||||
if self.utils.is_protected_snap_disabled(extra_specs):
|
||||
extra_specs.pop(utils.IS_RE, None)
|
||||
replication_enabled = False
|
||||
|
||||
if replication_enabled:
|
||||
copy_mode = True
|
||||
__, rep_extra_specs, __, __ = (
|
||||
@ -5778,6 +5792,9 @@ class PowerMaxCommon(object):
|
||||
bias = True if rep_config.get(utils.METROBIAS) else False
|
||||
rep_extra_specs[utils.METROBIAS] = bias
|
||||
|
||||
rep_extra_specs[utils.DISABLE_PROTECTED_SNAP] =\
|
||||
self.utils.is_protected_snap_disabled(extra_specs)
|
||||
|
||||
# If disable compression is set, check if target array is all flash
|
||||
do_disable_compression = self.utils.is_compression_disabled(
|
||||
extra_specs)
|
||||
@ -7800,3 +7817,20 @@ class PowerMaxCommon(object):
|
||||
'dev_ident': dev_id_from_identifier})
|
||||
self.rest.rename_volume(
|
||||
array, dev_id_from_identifier, None)
|
||||
|
||||
@staticmethod
|
||||
def get_vendor_properties(self):
|
||||
"""Retrieves the vendor properties for the powermax driver.
|
||||
|
||||
:param self: The object instance.
|
||||
:return: A tuple containing the properties dictionary and the
|
||||
driver name.
|
||||
"""
|
||||
properties = {}
|
||||
self._set_property(
|
||||
properties,
|
||||
utils.DISABLE_PROTECTED_SNAP,
|
||||
"Disable protected snap",
|
||||
_("Prevent protected snap being created on SRDF device."),
|
||||
"boolean")
|
||||
return properties, "powermax"
|
||||
|
@ -134,9 +134,10 @@ class PowerMaxFCDriver(san.SanDriver, driver.FibreChannelDriver):
|
||||
4.4.1 - Report trim/discard support
|
||||
4.5.0 - Add PowerMax v4 support
|
||||
4.5.1 - Add active/active compliance
|
||||
4.5.2 - Add 'disable_protected_snap' option
|
||||
"""
|
||||
|
||||
VERSION = "4.5.1"
|
||||
VERSION = "4.5.2"
|
||||
SUPPORTS_ACTIVE_ACTIVE = True
|
||||
|
||||
# ThirdPartySystems wiki
|
||||
@ -166,6 +167,9 @@ class PowerMaxFCDriver(san.SanDriver, driver.FibreChannelDriver):
|
||||
def check_for_setup_error(self):
|
||||
pass
|
||||
|
||||
def _init_vendor_properties(self):
|
||||
return self.common.get_vendor_properties(self)
|
||||
|
||||
def create_volume(self, volume):
|
||||
"""Creates a PowerMax/VMAX volume.
|
||||
|
||||
|
@ -139,9 +139,10 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
|
||||
4.4.1 - Report trim/discard support
|
||||
4.5.0 - Add PowerMax v4 support
|
||||
4.5.1 - Add active/active compliance
|
||||
4.5.2 - Add 'disable_protected_snap' option
|
||||
"""
|
||||
|
||||
VERSION = "4.5.1"
|
||||
VERSION = "4.5.2"
|
||||
SUPPORTS_ACTIVE_ACTIVE = True
|
||||
|
||||
# ThirdPartySystems wiki
|
||||
@ -171,6 +172,9 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
|
||||
def check_for_setup_error(self):
|
||||
pass
|
||||
|
||||
def _init_vendor_properties(self):
|
||||
return self.common.get_vendor_properties(self)
|
||||
|
||||
def create_volume(self, volume):
|
||||
"""Creates a PowerMax/VMAX volume.
|
||||
|
||||
@ -255,7 +259,6 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
|
||||
:param context: the context
|
||||
:param volume_id: the volume id
|
||||
"""
|
||||
pass
|
||||
|
||||
def initialize_connection(self, volume, connector):
|
||||
"""Initializes the connection and returns connection info.
|
||||
@ -461,15 +464,15 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
|
||||
data['driver_version'] = self.VERSION
|
||||
self._stats = data
|
||||
|
||||
def manage_existing(self, volume, external_ref):
|
||||
def manage_existing(self, volume, existing_ref):
|
||||
"""Manages an existing PowerMax/VMAX Volume (import to Cinder).
|
||||
|
||||
Renames the Volume to match the expected name for the volume.
|
||||
Also need to consider things like QoS, Emulation, account/tenant.
|
||||
"""
|
||||
return self.common.manage_existing(volume, external_ref)
|
||||
return self.common.manage_existing(volume, existing_ref)
|
||||
|
||||
def manage_existing_get_size(self, volume, external_ref):
|
||||
def manage_existing_get_size(self, volume, existing_ref):
|
||||
"""Return size of an existing PowerMax/VMAX volume to manage_existing.
|
||||
|
||||
:param self: reference to class
|
||||
@ -477,7 +480,7 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
|
||||
:param external_ref: reference to the existing volume
|
||||
:returns: size of the volume in GB
|
||||
"""
|
||||
return self.common.manage_existing_get_size(volume, external_ref)
|
||||
return self.common.manage_existing_get_size(volume, existing_ref)
|
||||
|
||||
def unmanage(self, volume):
|
||||
"""Export PowerMax/VMAX volume from Cinder.
|
||||
@ -550,10 +553,10 @@ class PowerMaxISCSIDriver(san.SanISCSIDriver):
|
||||
return self.common.get_manageable_snapshots(marker, limit, offset,
|
||||
sort_keys, sort_dirs)
|
||||
|
||||
def retype(self, ctxt, volume, new_type, diff, host):
|
||||
def retype(self, context, volume, new_type, diff, host):
|
||||
"""Migrate volume to another host using retype.
|
||||
|
||||
:param ctxt: context
|
||||
:param context: context
|
||||
:param volume: the volume object including the volume_type_id
|
||||
:param new_type: the new volume type.
|
||||
:param diff: difference between old and new volume types.
|
||||
|
@ -140,6 +140,7 @@ REST_API_CONNECT_TIMEOUT = 'rest_api_connect_timeout'
|
||||
REST_API_READ_TIMEOUT = 'rest_api_read_timeout'
|
||||
REST_API_CONNECT_TIMEOUT_KEY = 'RestAPIConnectTimeout'
|
||||
REST_API_READ_TIMEOUT_KEY = 'RestAPIReadTimeout'
|
||||
DISABLE_PROTECTED_SNAP = 'powermax:disable_protected_snap'
|
||||
|
||||
# Array Models, Service Levels & Workloads
|
||||
VMAX_HYBRID_MODELS = ['VMAX100K', 'VMAX200K', 'VMAX400K']
|
||||
@ -530,6 +531,15 @@ class PowerMaxUtils(object):
|
||||
host_list = host.split('+')
|
||||
return host_list[-1]
|
||||
|
||||
def is_protected_snap_disabled(self, extra_specs):
|
||||
"""Check is the disable_protected_snap flag set.
|
||||
|
||||
:param extra_specs: extra specifications :returns: boolean
|
||||
"""
|
||||
if extra_specs.get(DISABLE_PROTECTED_SNAP, False) in IS_TRUE:
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_compression_disabled(self, extra_specs):
|
||||
"""Check is compression is to be disabled.
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Dell EMC PowerMax driver: Added SRDF ``powermax:disable_protected_snap``
|
||||
volume-type extra-spec property for the purpose of avoiding
|
||||
overconsumption on both source and target storage arrays.
|
||||
|
||||
An operator may enable this functionality by creating a specific volume
|
||||
type with the property::
|
||||
|
||||
"powermax:disable_protected_snap": "<is> True"
|
||||
|
||||
When disabled (which is the default and current behavior), a
|
||||
replicated source volume will be protected with a snapshot of the
|
||||
same volume type.
|
||||
|
||||
When enabled, snapshots of replicated source volumes will be treated
|
||||
as regular, non-replicated devices.
|
||||
|
Loading…
Reference in New Issue
Block a user