Browse Source

PowerMax driver - rebranding VMAX to PowerMax

PowerMax is to replace VMAX in release notes, online documentation,
directory structure and driver name.

Implements: blueprint vmax-powermax-rebrand

Change-Id: I74f690b60aac6d0d4bf49d25b04a067c7993bfc7
changes/59/620659/20
Helen Walsh 3 years ago
parent
commit
76fd03819c
  1. 6
      cinder/opts.py
  2. 0
      cinder/tests/unit/volume/drivers/dell_emc/powermax/__init__.py
  3. 1045
      cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax.py
  4. 0
      cinder/volume/drivers/dell_emc/powermax/__init__.py
  5. 219
      cinder/volume/drivers/dell_emc/powermax/common.py
  6. 39
      cinder/volume/drivers/dell_emc/powermax/fc.py
  7. 39
      cinder/volume/drivers/dell_emc/powermax/iscsi.py
  8. 28
      cinder/volume/drivers/dell_emc/powermax/masking.py
  9. 22
      cinder/volume/drivers/dell_emc/powermax/metadata.py
  10. 14
      cinder/volume/drivers/dell_emc/powermax/provision.py
  11. 31
      cinder/volume/drivers/dell_emc/powermax/rest.py
  12. 28
      cinder/volume/drivers/dell_emc/powermax/utils.py
  13. 4
      cinder/volume/manager.py
  14. 358
      doc/source/configuration/block-storage/drivers/dell-emc-powermax-driver.rst
  15. 2
      doc/source/configuration/block-storage/volume-drivers.rst
  16. 5
      releasenotes/notes/vmax-powermax-rebrand-70569fc8cdf40a8c.yaml

6
cinder/opts.py

@ -77,6 +77,8 @@ from cinder.volume.drivers.datacore import iscsi as \
cinder_volume_drivers_datacore_iscsi
from cinder.volume.drivers.datera import datera_iscsi as \
cinder_volume_drivers_datera_dateraiscsi
from cinder.volume.drivers.dell_emc.powermax import common as \
cinder_volume_drivers_dell_emc_powermax_common
from cinder.volume.drivers.dell_emc import ps as \
cinder_volume_drivers_dell_emc_ps
from cinder.volume.drivers.dell_emc.sc import storagecenter_common as \
@ -85,8 +87,6 @@ from cinder.volume.drivers.dell_emc.scaleio import driver as \
cinder_volume_drivers_dell_emc_scaleio_driver
from cinder.volume.drivers.dell_emc.unity import driver as \
cinder_volume_drivers_dell_emc_unity_driver
from cinder.volume.drivers.dell_emc.vmax import common as \
cinder_volume_drivers_dell_emc_vmax_common
from cinder.volume.drivers.dell_emc.vnx import common as \
cinder_volume_drivers_dell_emc_vnx_common
from cinder.volume.drivers.dell_emc import xtremio as \
@ -284,12 +284,12 @@ def list_opts():
cinder_volume_driver.iser_opts,
cinder_volume_driver.nvmet_opts,
cinder_volume_drivers_datera_dateraiscsi.d_opts,
cinder_volume_drivers_dell_emc_powermax_common.powermax_opts,
cinder_volume_drivers_dell_emc_ps.eqlx_opts,
cinder_volume_drivers_dell_emc_sc_storagecentercommon.
common_opts,
cinder_volume_drivers_dell_emc_scaleio_driver.scaleio_opts,
cinder_volume_drivers_dell_emc_unity_driver.UNITY_OPTS,
cinder_volume_drivers_dell_emc_vmax_common.vmax_opts,
cinder_volume_drivers_dell_emc_vnx_common.VNX_OPTS,
cinder_volume_drivers_dell_emc_xtremio.XTREMIO_OPTS,
cinder_volume_drivers_drbdmanagedrv.drbd_opts,

0
cinder/tests/unit/volume/drivers/dell_emc/vmax/__init__.py → cinder/tests/unit/volume/drivers/dell_emc/powermax/__init__.py

1045
cinder/tests/unit/volume/drivers/dell_emc/powermax/test_powermax.py
File diff suppressed because it is too large
View File

0
cinder/volume/drivers/dell_emc/vmax/__init__.py → cinder/volume/drivers/dell_emc/powermax/__init__.py

219
cinder/volume/drivers/dell_emc/vmax/common.py → cinder/volume/drivers/dell_emc/powermax/common.py

@ -1,4 +1,4 @@
# Copyright (c) 2017 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -31,11 +31,11 @@ from cinder import exception
from cinder.i18n import _
from cinder.objects import fields
from cinder.volume import configuration
from cinder.volume.drivers.dell_emc.vmax import masking
from cinder.volume.drivers.dell_emc.vmax import metadata as volume_metadata
from cinder.volume.drivers.dell_emc.vmax import provision
from cinder.volume.drivers.dell_emc.vmax import rest
from cinder.volume.drivers.dell_emc.vmax import utils
from cinder.volume.drivers.dell_emc.powermax import masking
from cinder.volume.drivers.dell_emc.powermax import metadata as volume_metadata
from cinder.volume.drivers.dell_emc.powermax import provision
from cinder.volume.drivers.dell_emc.powermax import rest
from cinder.volume.drivers.dell_emc.powermax import utils
from cinder.volume import utils as volume_utils
from cinder.volume import volume_types
LOG = logging.getLogger(__name__)
@ -53,7 +53,7 @@ FAILOVER_ERROR = fields.ReplicationStatus.FAILOVER_ERROR
REPLICATION_ERROR = fields.ReplicationStatus.ERROR
vmax_opts = [
powermax_opts = [
cfg.IntOpt('interval',
default=3,
help='Use this value to specify '
@ -64,10 +64,9 @@ vmax_opts = [
'number of retries.'),
cfg.IntOpt(utils.VMAX_SNAPVX_UNLINK_LIMIT,
default=3,
help='Use this value to specify '
'the maximum number of unlinks '
'for the temporary snapshots '
'before a clone operation.'),
help='DEPRECATED: vmax_snapvc_unlink_limit.',
deprecated_for_removal=True,
deprecated_reason='Replaced by powermax_snapvx_unlink_limit.'),
cfg.BoolOpt('initiator_check',
default=False,
help='Use this value to enable '
@ -81,21 +80,25 @@ vmax_opts = [
default=8443,
help='REST server port number.'),
cfg.StrOpt(utils.VMAX_ARRAY,
help='Serial number of the array to connect to.'),
help='DEPRECATED: vmax_array.',
deprecated_for_removal=True,
deprecated_reason='Replaced by powermax_array.'),
cfg.StrOpt(utils.VMAX_SRP,
help='Storage resource pool on array to use for '
'provisioning.'),
help='DEPRECATED: vmax_srp.',
deprecated_for_removal=True,
deprecated_reason='Replaced by powermax_srp.'),
cfg.StrOpt(utils.VMAX_SERVICE_LEVEL,
help='Service level to use for provisioning storage. '
'Setting this as an extra spec in pool_name '
'is preferable.'),
help='DEPRECATED: vmax_service_level.',
deprecated_for_removal=True,
deprecated_reason='Replaced by powermax_service_level.'),
cfg.StrOpt(utils.VMAX_WORKLOAD,
help='Workload, setting this as an extra spec in '
'pool_name is preferable.'),
cfg.ListOpt(utils.VMAX_PORT_GROUPS,
bounds=True,
help='List of port groups containing frontend ports '
'configured prior for server connection.'),
help='DEPRECATED: vmax_port_groups.',
deprecated_for_removal=True,
deprecated_reason='Replaced by powermax_port_groups.'),
cfg.IntOpt(utils.U4P_FAILOVER_TIMEOUT,
default=20.0,
help='How long to wait for the server to send data before '
@ -120,17 +123,37 @@ vmax_opts = [
'connection is re-established.'),
cfg.MultiOpt(utils.U4P_FAILOVER_TARGETS,
item_type=types.Dict(),
help='Dictionary of Unisphere failover target info.')]
help='Dictionary of Unisphere failover target info.'),
cfg.IntOpt(utils.POWERMAX_SNAPVX_UNLINK_LIMIT,
default=3,
help='Use this value to specify '
'the maximum number of unlinks '
'for the temporary snapshots '
'before a clone operation.'),
cfg.StrOpt(utils.POWERMAX_ARRAY,
help='Serial number of the array to connect to.'),
cfg.StrOpt(utils.POWERMAX_SRP,
help='Storage resource pool on array to use for '
'provisioning.'),
cfg.StrOpt(utils.POWERMAX_SERVICE_LEVEL,
help='Service level to use for provisioning storage. '
'Setting this as an extra spec in pool_name '
'is preferable.'),
cfg.ListOpt(utils.POWERMAX_PORT_GROUPS,
bounds=True,
help='List of port groups containing frontend ports '
'configured prior for server connection.')]
CONF.register_opts(vmax_opts, group=configuration.SHARED_CONF_GROUP)
CONF.register_opts(powermax_opts, group=configuration.SHARED_CONF_GROUP)
class VMAXCommon(object):
"""Common class for Rest based VMAX volume drivers.
class PowerMaxCommon(object):
"""Common class for Rest based PowerMax volume drivers.
This common class is for Dell EMC VMAX volume drivers
This common class is for Dell EMC PowerMax volume drivers
based on UniSphere Rest API.
It supports VMAX 3 and VMAX All Flash arrays.
It supports VMAX 3 and VMAX All Flash and PowerMax arrays.
"""
pool_info = {'backend_name': None,
@ -145,13 +168,13 @@ class VMAXCommon(object):
self.protocol = prtcl
self.configuration = configuration
self.configuration.append_config_values(vmax_opts)
self.rest = rest.VMAXRest()
self.utils = utils.VMAXUtils()
self.masking = masking.VMAXMasking(prtcl, self.rest)
self.provision = provision.VMAXProvision(self.rest)
self.configuration.append_config_values(powermax_opts)
self.rest = rest.PowerMaxRest()
self.utils = utils.PowerMaxUtils()
self.masking = masking.PowerMaxMasking(prtcl, self.rest)
self.provision = provision.PowerMaxProvision(self.rest)
self.version = version
self.volume_metadata = volume_metadata.VMAXVolumeMetadata(
self.volume_metadata = volume_metadata.PowerMaxVolumeMetadata(
self.rest, version, LOG.isEnabledFor(logging.DEBUG))
# replication
self.replication_enabled = False
@ -186,8 +209,9 @@ class VMAXCommon(object):
"""Get relevent details from configuration file."""
self.interval = self.configuration.safe_get('interval')
self.retries = self.configuration.safe_get('retries')
self.snapvx_unlink_limit = self.configuration.safe_get(
utils.VMAX_SNAPVX_UNLINK_LIMIT)
self.snapvx_unlink_limit = self._get_unlink_configuration_value(
utils.VMAX_SNAPVX_UNLINK_LIMIT,
utils.POWERMAX_SNAPVX_UNLINK_LIMIT)
self.pool_info['backend_name'] = (
self.configuration.safe_get('volume_backend_name'))
mosr = volume_utils.get_max_over_subscription_ratio(
@ -247,13 +271,13 @@ class VMAXCommon(object):
LOG.warning("There has been no failover instances of Unisphere "
"configured for this instance of Cinder. If your "
"primary instance of Unisphere goes down then your "
"VMAX will be inaccessible until the Unisphere REST "
"API is responsive again.")
"PowerMax/VMAX will be inaccessible until the "
"Unisphere REST API is responsive again.")
def retest_primary_u4p(self):
"""Retest connection to the primary instance of Unisphere."""
primary_array_info = self.get_attributes_from_cinder_config()
temp_conn = rest.VMAXRest()
temp_conn = rest.PowerMaxRest()
temp_conn.set_rest_credentials(primary_array_info)
LOG.debug(
"Running connection check to primary instance of Unisphere "
@ -310,8 +334,8 @@ class VMAXCommon(object):
{'rep_config': self.rep_config})
elif self.rep_devices and len(self.rep_devices) > 1:
LOG.error("More than one replication target is configured. "
"Dell EMC VMAX only suppports a single replication "
"target. Replication will not be enabled.")
"Dell EMC PowerMax/VMAX only suppports a single "
"replication target. Replication will not be enabled.")
def _get_slo_workload_combinations(self, array_info):
"""Method to query the array for SLO and Workloads.
@ -383,7 +407,7 @@ class VMAXCommon(object):
return finalarrayinfolist
def create_volume(self, volume):
"""Creates a EMC(VMAX) volume from a storage group.
"""Creates a EMC(PowerMax/VMAX) volume from a storage group.
:param volume: volume object
:returns: model_update - dict
@ -548,7 +572,7 @@ class VMAXCommon(object):
replication_driver_data)}, rep_info_dict)
def delete_volume(self, volume):
"""Deletes a EMC(VMAX) volume.
"""Deletes a EMC(PowerMax/VMAX) volume.
:param volume: volume object
"""
@ -617,7 +641,7 @@ class VMAXCommon(object):
Removes volume from the storage group that belongs to a masking view.
:param array: the array serial number
:param volume: volume object
:param device_id: the VMAX volume device id
:param device_id: the PowerMax/VMAX volume device id
:param extra_specs: extra specifications
:param connector: the connector object
:param is_multiattach: flag to indicate if this is a multiattach case
@ -839,9 +863,9 @@ class VMAXCommon(object):
extra_specs, rep_extra_specs):
"""Helper method to attach a metro volume.
Metro protected volumes point to two VMAX devices on different arrays,
which are presented as a single device to the host. This method
masks the remote device to the host.
Metro protected volumes point to two PowerMax/VMAX devices on
different arrays, which are presented as a single device to the host.
This method masks the remote device to the host.
:param volume: the volume object
:param connector: the connector dict
:param is_multiattach: flag to indicate if this a multiattach case
@ -941,8 +965,8 @@ class VMAXCommon(object):
exception_message = (
_("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})
"supported on PowerMax/VMAX from HyperMaxOS version "
"5978 onwards. Exiting...") % {'volume': volume_name})
LOG.error(exception_message)
raise exception.VolumeBackendAPIException(
message=exception_message)
@ -1020,7 +1044,7 @@ class VMAXCommon(object):
'array': array_info['SerialNumber']})
if already_queried:
# The dictionary will only have one key per VMAX
# The dictionary will only have one key per PowerMax/VMAX
# Construct the location info
try:
temp_location_info = (
@ -1181,7 +1205,7 @@ class VMAXCommon(object):
return extra_specs, qos_specs
def _find_device_on_array(self, volume, extra_specs):
"""Given the volume get the VMAX device Id.
"""Given the volume get the PowerMax/VMAX device Id.
:param volume: volume object
:param extra_specs: the extra Specs
@ -1663,7 +1687,7 @@ class VMAXCommon(object):
return volume_dict
def _set_vmax_extra_specs(self, extra_specs, pool_record):
"""Set the VMAX extra specs.
"""Set the PowerMax/PowerMax/VMAX extra specs.
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
@ -1944,7 +1968,7 @@ class VMAXCommon(object):
clone_id = clone_volume.id
clone_name = self.utils.get_volume_element_name(clone_id)
create_snap = False
# VMAX supports using a target volume that is bigger than
# PowerMax/VMAX supports using a target volume that is bigger than
# the source volume, so we create the target volume the desired
# size at this point to avoid having to extend later
try:
@ -2105,7 +2129,7 @@ class VMAXCommon(object):
do_delete_temp_volume_snap(source)
def manage_existing(self, volume, external_ref):
"""Manages an existing VMAX Volume (import to Cinder).
"""Manages an existing PowerMax/VMAX Volume (import to Cinder).
Renames the existing volume to match the expected name for the volume.
Also need to consider things like QoS, Emulation, account/tenant.
@ -2176,7 +2200,7 @@ class VMAXCommon(object):
:param device_id: the device id
:param volume_id: the cinder volume id
:param external_ref: the external reference
:returns volume_identifier - name of the volume on VMAX
:returns volume_identifier - name of the volume on PowerMax/VMAX
:returns sg - the storage group which the LUN belongs to
:raises: ManageExistingInvalidReference, ManageExistingAlreadyManaged:
"""
@ -2229,7 +2253,7 @@ class VMAXCommon(object):
return volume_identifier, sg
def manage_existing_get_size(self, volume, external_ref):
"""Return size of an existing VMAX volume to manage_existing.
"""Return size of an existing PowerMax/VMAX volume to manage_existing.
:param self: reference to class
:param volume: the volume object including the volume_type_id
@ -2251,7 +2275,7 @@ class VMAXCommon(object):
size = float(self.rest.get_size_of_device_on_array(array, device_id))
if not size.is_integer():
exception_message = (
_("Cannot manage existing VMAX volume %(device_id)s "
_("Cannot manage existing PowerMax/VMAX volume %(device_id)s "
"- it has a size of %(vol_size)s but only whole GB "
"sizes are supported. Please extend the "
"volume to the nearest GB value before importing.")
@ -2265,7 +2289,7 @@ class VMAXCommon(object):
return int(size)
def unmanage(self, volume):
"""Export VMAX volume from Cinder.
"""Export PowerMax/VMAX volume from Cinder.
Leave the volume intact on the backend array.
@ -2313,7 +2337,7 @@ class VMAXCommon(object):
volume_id, extra_specs)
def manage_existing_snapshot(self, snapshot, existing_ref):
"""Manage an existing VMAX Snapshot (import to Cinder).
"""Manage an existing PowerMax/VMAX Snapshot (import to Cinder).
Renames the Snapshot to prefix it with OS- to indicate
it is managed by Cinder
@ -2409,7 +2433,7 @@ class VMAXCommon(object):
extra_specs[utils.ARRAY], device_id)
def unmanage_snapshot(self, snapshot):
"""Export VMAX Snapshot from Cinder.
"""Export PowerMax/VMAX Snapshot from Cinder.
Leaves the snapshot intact on the backend VMAX
@ -2425,7 +2449,7 @@ class VMAXCommon(object):
exception_message = (
_("It is not possible to unmanage a snapshot where the "
"source volume is failed-over, revert back to source "
"VMAX to unmanage snapshot %(snap_name)s")
"PowerMax/VMAX to unmanage snapshot %(snap_name)s")
% {'snap_name': snap_name})
LOG.exception(exception_message)
@ -2452,7 +2476,7 @@ class VMAXCommon(object):
self._sync_check(array, device_id, volume.name, extra_specs)
LOG.info("Snapshot %(snap_name)s is no longer managed in "
"OpenStack but still remains on VMAX source "
"OpenStack but still remains on PowerMax/VMAX source "
"%(array_id)s", {'snap_name': snap_name, 'array_id': array})
def get_manageable_volumes(self, marker, limit, offset, sort_keys,
@ -2477,11 +2501,11 @@ class VMAXCommon(object):
'array_id': array})
volumes = self.rest.get_private_volume_list(array)
# No volumes returned from VMAX
# No volumes returned from PowerMax/VMAX
if not volumes:
LOG.info("There were no volumes found on the backend VMAX. "
"You need to create some volumes before they can be "
"managed into Cinder.")
LOG.info("There were no volumes found on the backend "
"PowerMax/VMAX. You need to create some volumes before "
"they can be managed into Cinder.")
return manageable_vols
for device in volumes:
@ -2561,11 +2585,11 @@ class VMAXCommon(object):
'array_id': array})
volumes = self.rest.get_private_volume_list(array)
# No volumes returned from VMAX
# No volumes returned from PowerMax/VMAX
if not volumes:
LOG.info("There were no volumes found on the backend VMAX. "
"You need to create some volumes before snapshots can "
"be created and managed into Cinder.")
LOG.info("There were no volumes found on the backend "
"PowerMax/VMAX. You need to create some volumes "
"before snashot can be created and managed into Cinder.")
return manageable_snaps
for device in volumes:
@ -2638,7 +2662,8 @@ class VMAXCommon(object):
manageable_snaps = manageable_snaps[snap_index:]
else:
msg = (_("Snapshot marker %(marker)s not found, marker "
"provided must be a valid VMAX snapshot ID") %
"provided must be a valid PowerMax/VMAX "
"snapshot ID") %
{'marker': marker})
raise exception.VolumeBackendAPIException(msg)
@ -3625,7 +3650,7 @@ class VMAXCommon(object):
self, array, device_id, volume_name, extra_specs):
"""Add a volume to the default replication group.
Replication groups are VMAX storage groups that contain only
Replication groups are PowerMax/VMAX storage groups that contain only
RDF-paired volumes. We can use our normal storage group operations.
:param array: array serial number
:param device_id: the device id
@ -4264,8 +4289,8 @@ class VMAXCommon(object):
LOG.error(error_msg)
raise exception.VolumeBackendAPIException(message=error_msg)
LOG.debug("Enter VMAX create_volume group_from_src. Group to be "
"created: %(grpId)s, Source : %(SourceGrpId)s.",
LOG.debug("Enter PowerMax/VMAX create_volume group_from_src. Group "
"to be created: %(grpId)s, Source : %(SourceGrpId)s.",
{'grpId': group.id, 'SourceGrpId': source_id})
try:
@ -4632,19 +4657,22 @@ class VMAXCommon(object):
username = self.configuration.safe_get(utils.VMAX_USER_NAME)
password = self.configuration.safe_get(utils.VMAX_PASSWORD)
if username and password:
serial_number = self.configuration.safe_get(utils.VMAX_ARRAY)
serial_number = self._get_configuration_value(
utils.VMAX_ARRAY, utils.POWERMAX_ARRAY)
if serial_number is None:
LOG.error("Array Serial Number must be set in cinder.conf")
srp_name = self.configuration.safe_get(utils.VMAX_SRP)
srp_name = self._get_configuration_value(
utils.VMAX_SRP, utils.POWERMAX_SRP)
if srp_name is None:
LOG.error("SRP Name must be set in cinder.conf")
slo = self.configuration.safe_get(utils.VMAX_SERVICE_LEVEL)
slo = self._get_configuration_value(
utils.VMAX_SERVICE_LEVEL, utils.POWERMAX_SERVICE_LEVEL)
workload = self.configuration.safe_get(utils.VMAX_WORKLOAD)
port_groups = self.configuration.safe_get(utils.VMAX_PORT_GROUPS)
port_groups = self._get_configuration_value(
utils.VMAX_PORT_GROUPS, utils.POWERMAX_PORT_GROUPS)
random_portgroup = None
if port_groups:
random_portgroup = random.choice(self.configuration.safe_get(
utils.VMAX_PORT_GROUPS))
random_portgroup = random.choice(port_groups)
kwargs = (
{'RestServerIp': self.configuration.safe_get(
@ -4670,6 +4698,41 @@ class VMAXCommon(object):
return kwargs
def _get_configuration_value(self, first_key, second_key):
"""Get the configuration value of the first or second key
:param first_key: the first key
:param second_key: the second key
:returns: value
"""
return_value = None
if (self.configuration.safe_get(first_key)
and self.configuration.safe_get(second_key)):
LOG.error("Cannot specifiy both %(first_key)s. "
"and %(second_key)s.",
{'first_key': first_key, 'second_key': second_key})
else:
return_value = self.configuration.safe_get(first_key)
if return_value is None:
return_value = self.configuration.safe_get(second_key)
return return_value
def _get_unlink_configuration_value(self, first_key, second_key):
"""Get the configuration value of snapvx_unlink_limit
This will give back the value of the default snapvx_unlink_limit
unless either powermax_snapvx_unlink_limit or vmax_snapvx_unlink_limit
is set to something else
:param first_key: the first key
:param second_key: the second key
:returns: value
"""
return_value = self.configuration.safe_get(second_key)
if return_value == 3:
return_value = self.configuration.safe_get(first_key)
return return_value
def _get_unisphere_port(self):
"""Get unisphere port from the configuration file
@ -4680,7 +4743,7 @@ class VMAXCommon(object):
elif self.configuration.safe_get(utils.VMAX_SERVER_PORT_NEW):
return self.configuration.safe_get(utils.VMAX_SERVER_PORT_NEW)
else:
LOG.debug("VMAX port is not set, using default port: %s",
LOG.debug("PowerMax/VMAX port is not set, using default port: %s",
utils.DEFAULT_PORT)
return utils.DEFAULT_PORT

39
cinder/volume/drivers/dell_emc/vmax/fc.py → cinder/volume/drivers/dell_emc/powermax/fc.py

@ -1,4 +1,4 @@
# Copyright (c) 2017 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -19,7 +19,7 @@ from oslo_log import log as logging
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.dell_emc.vmax import common
from cinder.volume.drivers.dell_emc.powermax import common
from cinder.volume.drivers.san import san
from cinder.zonemanager import utils as fczm_utils
@ -27,8 +27,8 @@ LOG = logging.getLogger(__name__)
@interface.volumedriver
class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver):
"""FC Drivers for VMAX using REST.
class PowerMaxFCDriver(san.SanDriver, driver.FibreChannelDriver):
"""FC Drivers for PowerMax using REST.
Version history:
@ -98,23 +98,24 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver):
- Fix for SSL verification/cert application (bug #1772924)
- Log VMAX metadata of a volume (bp vmax-metadata)
- Fix for get-pools command (bug #1784856)
3.3.0 - Fix for initiator retrieval and short hostname unmapping
4.0.0 - Fix for initiator retrieval and short hostname unmapping
(bugs #1783855 #1783867)
- Fix for HyperMax OS Upgrade Bug (bug #1790141)
- Support for failover to secondary Unisphere
(bp/vmax-unisphere-failover)
- Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand)
"""
VERSION = "3.3.0"
VERSION = "4.0.0"
# ThirdPartySystems wiki
CI_WIKI_NAME = "EMC_VMAX_CI"
def __init__(self, *args, **kwargs):
super(VMAXFCDriver, self).__init__(*args, **kwargs)
super(PowerMaxFCDriver, self).__init__(*args, **kwargs)
self.active_backend_id = kwargs.get('active_backend_id', None)
self.common = common.VMAXCommon(
self.common = common.PowerMaxCommon(
'FC',
self.VERSION,
configuration=self.configuration,
@ -125,7 +126,7 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver):
pass
def create_volume(self, volume):
"""Creates a VMAX volume.
"""Creates a PowerMax/VMAX volume.
:param volume: the cinder volume object
:returns: provider location dict
@ -152,7 +153,7 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver):
return self.common.create_cloned_volume(volume, src_vref)
def delete_volume(self, volume):
"""Deletes a VMAX volume.
"""Deletes a PowerMax/VMAX volume.
:param volume: the cinder volume object
"""
@ -474,18 +475,18 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver):
self._stats = data
def manage_existing(self, volume, external_ref):
"""Manages an existing VMAX Volume (import to Cinder).
"""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.
:param volume: the volume object
:param external_ref: the reference for the VMAX volume
:param external_ref: the reference for the PowerMax/VMAX volume
:returns: model_update
"""
return self.common.manage_existing(volume, external_ref)
def manage_existing_get_size(self, volume, external_ref):
"""Return size of an existing VMAX volume to manage_existing.
"""Return size of an existing PowerMax/VMAX volume to manage_existing.
:param self: reference to class
:param volume: the volume object including the volume_type_id
@ -495,20 +496,20 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver):
return self.common.manage_existing_get_size(volume, external_ref)
def unmanage(self, volume):
"""Export VMAX volume from Cinder.
"""Export PowerMax/VMAX volume from Cinder.
Leave the volume intact on the backend array.
"""
return self.common.unmanage(volume)
def manage_existing_snapshot(self, snapshot, existing_ref):
"""Manage an existing VMAX Snapshot (import to Cinder).
"""Manage an existing PowerMax/VMAX Snapshot (import to Cinder).
Renames the Snapshot to prefix it with OS- to indicate
it is managed by Cinder.
:param snapshot: the snapshot object
:param existing_ref: the snapshot name on the backend VMAX
:param existing_ref: the snapshot name on the backend PowerMax/VMAX
:returns: model_update
"""
return self.common.manage_existing_snapshot(snapshot, existing_ref)
@ -517,15 +518,15 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver):
"""Return the size of the source volume for manage-existing-snapshot.
:param snapshot: the snapshot object
:param existing_ref: the snapshot name on the backend VMAX
:param existing_ref: the snapshot name on the backend PowerMax/VMAX
:returns: size of the source volume in GB
"""
return self.common.manage_existing_snapshot_get_size(snapshot)
def unmanage_snapshot(self, snapshot):
"""Export VMAX Snapshot from Cinder.
"""Export PowerMax/VMAX Snapshot from Cinder.
Leaves the snapshot intact on the backend VMAX.
Leaves the snapshot intact on the backend PowerMax/VMAX.
:param snapshot: the snapshot object
"""

39
cinder/volume/drivers/dell_emc/vmax/iscsi.py → cinder/volume/drivers/dell_emc/powermax/iscsi.py

@ -1,4 +1,4 @@
# Copyright (c) 2017 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
"""
ISCSI Drivers for Dell EMC VMAX arrays based on REST.
ISCSI Drivers for Dell EMC PowerMax/PowerMax/VMAX arrays based on REST.
"""
from oslo_log import log as logging
@ -23,15 +23,15 @@ import six
from cinder import exception
from cinder.i18n import _
from cinder import interface
from cinder.volume.drivers.dell_emc.vmax import common
from cinder.volume.drivers.dell_emc.powermax import common
from cinder.volume.drivers.san import san
LOG = logging.getLogger(__name__)
@interface.volumedriver
class VMAXISCSIDriver(san.SanISCSIDriver):
"""ISCSI Drivers for VMAX using Rest.
class PowerMaxISCSIDriver(san.SanISCSIDriver):
"""ISCSI Drivers for PowerMax using Rest.
Version history:
@ -103,24 +103,25 @@ class VMAXISCSIDriver(san.SanISCSIDriver):
- Fix for SSL verification/cert application (bug #1772924)
- Log VMAX metadata of a volume (bp vmax-metadata)
- Fix for get-pools command (bug #1784856)
3.3.0 - Fix for initiator retrieval and short hostname unmapping
4.0.0 - Fix for initiator retrieval and short hostname unmapping
(bugs #1783855 #1783867)
- Fix for HyperMax OS Upgrade Bug (bug #1790141)
- Support for failover to secondary Unisphere
(bp/vmax-unisphere-failover)
- Rebrand from VMAX to PowerMax(bp/vmax-powermax-rebrand)
"""
VERSION = "3.3.0"
VERSION = "4.0.0"
# ThirdPartySystems wiki
CI_WIKI_NAME = "EMC_VMAX_CI"
def __init__(self, *args, **kwargs):
super(VMAXISCSIDriver, self).__init__(*args, **kwargs)
super(PowerMaxISCSIDriver, self).__init__(*args, **kwargs)
self.active_backend_id = kwargs.get('active_backend_id', None)
self.common = (
common.VMAXCommon(
common.PowerMaxCommon(
'iSCSI',
self.VERSION,
configuration=self.configuration,
@ -130,7 +131,7 @@ class VMAXISCSIDriver(san.SanISCSIDriver):
pass
def create_volume(self, volume):
"""Creates a VMAX volume.
"""Creates a PowerMax/VMAX volume.
:param volume: the cinder volume object
:returns: provider location dict
@ -157,7 +158,7 @@ class VMAXISCSIDriver(san.SanISCSIDriver):
return self.common.create_cloned_volume(volume, src_vref)
def delete_volume(self, volume):
"""Deletes a VMAX volume.
"""Deletes a PowerMax/VMAX volume.
:param volume: the cinder volume object
"""
@ -397,7 +398,7 @@ class VMAXISCSIDriver(san.SanISCSIDriver):
self._stats = data
def manage_existing(self, volume, external_ref):
"""Manages an existing VMAX Volume (import to Cinder).
"""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.
@ -405,7 +406,7 @@ class VMAXISCSIDriver(san.SanISCSIDriver):
return self.common.manage_existing(volume, external_ref)
def manage_existing_get_size(self, volume, external_ref):
"""Return size of an existing VMAX volume to manage_existing.
"""Return size of an existing PowerMax/VMAX volume to manage_existing.
:param self: reference to class
:param volume: the volume object including the volume_type_id
@ -415,20 +416,20 @@ class VMAXISCSIDriver(san.SanISCSIDriver):
return self.common.manage_existing_get_size(volume, external_ref)
def unmanage(self, volume):
"""Export VMAX volume from Cinder.
"""Export PowerMax/VMAX volume from Cinder.
Leave the volume intact on the backend array.
"""
return self.common.unmanage(volume)
def manage_existing_snapshot(self, snapshot, existing_ref):
"""Manage an existing VMAX Snapshot (import to Cinder).
"""Manage an existing PowerMax/VMAX Snapshot (import to Cinder).
Renames the Snapshot to prefix it with OS- to indicate
it is managed by Cinder.
:param snapshot: the snapshot object
:param existing_ref: the snapshot name on the backend VMAX
:param existing_ref: the snapshot name on the backend PowerMax/VMAX
:returns: model_update
"""
return self.common.manage_existing_snapshot(snapshot, existing_ref)
@ -437,15 +438,15 @@ class VMAXISCSIDriver(san.SanISCSIDriver):
"""Return the size of the source volume for manage-existing-snapshot.
:param snapshot: the snapshot object
:param existing_ref: the snapshot name on the backend VMAX
:param existing_ref: the snapshot name on the backend PowerMax/VMAX
:returns: size of the source volume in GB
"""
return self.common.manage_existing_snapshot_get_size(snapshot)
def unmanage_snapshot(self, snapshot):
"""Export VMAX Snapshot from Cinder.
"""Export PowerMax/VMAX Snapshot from Cinder.
Leaves the snapshot intact on the backend VMAX.
Leaves the snapshot intact on the backend PowerMax/VMAX.
:param snapshot: the snapshot object
"""

28
cinder/volume/drivers/dell_emc/vmax/masking.py → cinder/volume/drivers/dell_emc/powermax/masking.py

@ -1,4 +1,4 @@
# Copyright (c) 2017 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -24,24 +24,24 @@ import six
from cinder import coordination
from cinder import exception
from cinder.i18n import _
from cinder.volume.drivers.dell_emc.vmax import provision
from cinder.volume.drivers.dell_emc.vmax import utils
from cinder.volume.drivers.dell_emc.powermax import provision
from cinder.volume.drivers.dell_emc.powermax import utils
from cinder.volume import utils as volume_utils
LOG = logging.getLogger(__name__)
class VMAXMasking(object):
"""Masking class for Dell EMC VMAX.
class PowerMaxMasking(object):
"""Masking class for Dell EMC PowerMax.
Masking code to dynamically create a masking view.
It supports VMAX arrays.
It supports VMAX 3, All Flash and PowerMax arrays.
"""
def __init__(self, prtcl, rest):
self.protocol = prtcl
self.utils = utils.VMAXUtils()
self.utils = utils.PowerMaxUtils()
self.rest = rest
self.provision = provision.VMAXProvision(self.rest)
self.provision = provision.PowerMaxProvision(self.rest)
def setup_masking_view(
self, serial_number, volume, masking_view_dict, extra_specs):
@ -877,8 +877,8 @@ class VMAXMasking(object):
contains the correct initiators. If it does not contain the correct
initiators then we delete the initiator group from the masking view,
re-create it with the correct initiators and add it to the masking view
NOTE: VMAX does not support ModifyMaskingView so we must first
delete the masking view and recreate it.
NOTE: PowerMax/VMAX does not support ModifyMaskingView so we must
first delete the masking view and recreate it.
:param serial_number: the array serial number
:param maskingview_name: name of the masking view
:param maskingview_dict: the masking view dict
@ -1551,8 +1551,8 @@ class VMAXMasking(object):
self, serial_number, initiatorgroup_name, host):
"""Delete the initiator group.
Delete the Initiator group if it has been created by the VMAX driver,
and if there are no masking views associated with it.
Delete the Initiator group if it has been created by the PowerMax
driver, and if there are no masking views associated with it.
:param serial_number: the array serial number
:param initiatorgroup_name: initiator group name
:param host: the short name of the host
@ -1591,8 +1591,8 @@ class VMAXMasking(object):
'nmv': len(maskingview_names)})
else:
LOG.warning("Initiator group %(ig_name)s was "
"not created by the VMAX driver so will "
"not be deleted by the VMAX driver.",
"not created by the PowerMax driver so will "
"not be deleted by the PowerMax driver.",
{'ig_name': initiatorgroup_name})
else:
LOG.warning("Cannot get host name from connector object - "

22
cinder/volume/drivers/dell_emc/vmax/metadata.py → cinder/volume/drivers/dell_emc/powermax/metadata.py

@ -1,4 +1,4 @@
# Copyright (c) 2018 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -24,7 +24,7 @@ from oslo_log import log as logging
from cinder.objects import volume
from cinder import version
from cinder.volume.drivers.dell_emc.vmax import utils
from cinder.volume.drivers.dell_emc.powermax import utils
LOG = logging.getLogger(__name__)
CLEANUP_LIST = ['masking_view', 'child_storage_group', 'parent_storage_group',
'initiator_group', 'port_group', 'storage_group']
@ -46,8 +46,8 @@ def debug_required(func):
return func_wrapper
class VMAXVolumeMetadata(object):
"""Gathers VMAX specific volume information.
class PowerMaxVolumeMetadata(object):
"""Gathers PowerMax/VMAX specific volume information.
Also gathers Unisphere, Microcode OS/distribution and python versions.
"""
@ -55,7 +55,7 @@ class VMAXVolumeMetadata(object):
def __init__(self, rest, version, is_debug):
self.version_dict = {}
self.rest = rest
self.utils = utils.VMAXUtils()
self.utils = utils.PowerMaxUtils()
self.volume_trace_list = []
self.is_debug = is_debug
self.vmax_driver_version = version
@ -137,7 +137,7 @@ class VMAXVolumeMetadata(object):
self._update_info_from_version_info()
def _update_vmax_info(self, serial_number):
"""Update VMAX info.
"""Update PowerMax/VMAX info.
:param serial_number: the serial number of the array
"""
@ -583,7 +583,7 @@ class VMAXVolumeMetadata(object):
:param volume: volume object
:param rep_info_dict: information gathered from replication
:param device_id: the VMAX device id
:param device_id: the PowerMax/VMAX device id
:param extra_specs: the extra specs
"""
operation = "manage_existing_volume"
@ -632,11 +632,11 @@ class VMAXVolumeMetadata(object):
:param volume_id: volume identifier
:param volume_size: volume size
:param device_id: the VMAX device id
:param array: the VMAX serialnumber
:param srp: VMAX SRP
:param device_id: the PowerMax/VMAX device id
:param array: the PowerMax/VMAX serialnumber
:param srp: PowerMax/VMAX SRP
:param target_slo: volume name
:param target_workload: the VMAX device id
:param target_workload: the PowerMax/VMAX device id
:param is_rep_enabled: replication enabled flag
:param rep_mode: replication mode
:param is_compression_disabled: compression disabled flag

14
cinder/volume/drivers/dell_emc/vmax/provision.py → cinder/volume/drivers/dell_emc/powermax/provision.py

@ -1,4 +1,4 @@
# Copyright (c) 2017 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -21,7 +21,7 @@ from oslo_service import loopingcall
from cinder import coordination
from cinder import exception
from cinder.i18n import _
from cinder.volume.drivers.dell_emc.vmax import utils
from cinder.volume.drivers.dell_emc.powermax import utils
LOG = logging.getLogger(__name__)
@ -30,13 +30,13 @@ UNLINK_INTERVAL = 15
UNLINK_RETRIES = 30
class VMAXProvision(object):
"""Provisioning Class for Dell EMC VMAX volume drivers.
class PowerMaxProvision(object):
"""Provisioning Class for Dell EMC PowerMax volume drivers.
It supports VMAX arrays.
It supports VMAX 3, All Flash and PowerMax arrays.
"""
def __init__(self, rest):
self.utils = utils.VMAXUtils()
self.utils = utils.PowerMaxUtils()
self.rest = rest
def create_storage_group(
@ -392,7 +392,7 @@ class VMAXProvision(object):
_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.",
LOG.debug("Extend PowerMax/VMAX volume took: %(delta)s H:MM:SS.",
{'delta': self.utils.get_time_delta(start_time,
time.time())})

31
cinder/volume/drivers/dell_emc/vmax/rest.py → cinder/volume/drivers/dell_emc/powermax/rest.py

@ -1,4 +1,4 @@
# Copyright (c) 2018 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -31,7 +31,7 @@ from cinder import coordination
from cinder import exception
from cinder.i18n import _
from cinder.utils import retry
from cinder.volume.drivers.dell_emc.vmax import utils
from cinder.volume.drivers.dell_emc.powermax import utils
requests.packages.urllib3.disable_warnings(urllib_exp.InsecureRequestWarning)
@ -60,11 +60,11 @@ SUCCEEDED = 'succeeded'
CREATE_VOL_STRING = "Creating new Volumes"
class VMAXRest(object):
"""Rest class based on Unisphere for VMAX Rest API."""
class PowerMaxRest(object):
"""Rest class based on Unisphere for PowerMax Rest API."""
def __init__(self):
self.utils = utils.VMAXUtils()
self.utils = utils.PowerMaxUtils()
self.session = None
self.base_uri = None
self.user = None
@ -169,14 +169,15 @@ class VMAXRest(object):
self.set_rest_credentials(self.u4p_failover_targets[0])
self.u4p_failover_targets.pop(0)
if self.u4p_in_failover:
LOG.warning("VMAX driver still in u4p failover mode. A "
LOG.warning("PowerMax driver still in u4p failover mode. A "
"periodic check will be made to see if primary "
"Unisphere comes back online for seamless "
"restoration.")
else:
LOG.warning("VMAX driver set to u4p failover mode. A periodic "
"check will be made to see if primary Unisphere "
"comes back online for seamless restoration.")
LOG.warning("PowerMax driver set to u4p failover mode. A "
"periodic check will be made to see if primary "
"Unisphere comes back online for seamless "
"restoration.")
self.u4p_in_failover = True
else:
msg = _("A connection could not be established with the "
@ -639,10 +640,10 @@ class VMAXRest(object):
return workload_setting
def get_vmax_model(self, array):
"""Get the VMAX model.
"""Get the PowerMax/VMAX model.
:param array: the array serial number
:return: the VMAX model
:return: the PowerMax/VMAX model
"""
vmax_version = ''
system_uri = ("/%(version)s/system/symmetrix/%(array)s" % {
@ -1120,7 +1121,7 @@ class VMAXRest(object):
job, extra_specs)
def get_volume(self, array, device_id):
"""Get a VMAX volume from array.
"""Get a PowerMax/VMAX volume from array.
:param array: the array serial number
:param device_id: the volume device id
@ -1161,7 +1162,7 @@ class VMAXRest(object):
return volume_dict
def get_volume_list(self, array, params):
"""Get a filtered list of VMAX volumes from array.
"""Get a filtered list of PowerMax/VMAX volumes from array.
Filter parameters are required as the unfiltered volume list could be
very large and could affect performance if called often.
@ -1205,7 +1206,7 @@ class VMAXRest(object):
payload, resource_name=device_id)
def extend_volume(self, array, device_id, new_size, extra_specs):
"""Extend a VMAX volume.
"""Extend a PowerMax/VMAX volume.
:param array: the array serial number
:param device_id: volume device id
@ -1344,7 +1345,7 @@ class VMAXRest(object):
return device_id
def find_volume_identifier(self, array, device_id):
"""Get the volume identifier of a VMAX volume.
"""Get the volume identifier of a PowerMax/VMAX volume.
:param array: array serial number
:param device_id: the device id

28
cinder/volume/drivers/dell_emc/vmax/utils.py → cinder/volume/drivers/dell_emc/powermax/utils.py

@ -1,4 +1,4 @@
# Copyright (c) 2017 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -101,16 +101,22 @@ U4P_FAILOVER_RETRIES = 'u4p_failover_retries'
U4P_FAILOVER_BACKOFF_FACTOR = 'u4p_failover_backoff_factor'
U4P_FAILOVER_AUTOFAILBACK = 'u4p_failover_autofailback'
U4P_FAILOVER_TARGETS = 'u4p_failover_target'
POWERMAX_ARRAY = 'powermax_array'
POWERMAX_SRP = 'powermax_srp'
POWERMAX_SERVICE_LEVEL = 'powermax_service_level'
POWERMAX_PORT_GROUPS = 'powermax_port_groups'
POWERMAX_SNAPVX_UNLINK_LIMIT = 'powermax_snapvx_unlink_limit'
class VMAXUtils(object):
"""Utility class for Rest based VMAX volume drivers.
class PowerMaxUtils(object):
"""Utility class for Rest based PowerMax volume drivers.
This Utility class is for VMAX volume drivers based on Unisphere Rest API.
This Utility class is for PowerMax volume drivers based on Unisphere
Rest API.
"""
def __init__(self):
"""Utility class for Rest based VMAX volume drivers."""
"""Utility class for Rest based PowerMax volume drivers."""
def get_host_short_name(self, host_name):
"""Returns the short name for a given qualified host name.
@ -245,7 +251,7 @@ class VMAXUtils(object):
@staticmethod
def modify_snapshot_prefix(snapshot_name, manage=False, unmanage=False):
"""Modify a Snapshot prefix on VMAX backend.
"""Modify a Snapshot prefix on PowerMax/VMAX backend.
Prepare a snapshot name for manage/unmanage snapshot process either
by adding or removing 'OS-' prefix.
@ -253,7 +259,7 @@ class VMAXUtils(object):
:param snapshot_name: the old snapshot backend display name
:param manage: (bool) if the operation is managing a snapshot
:param unmanage: (bool) if the operation is unmanaging a snapshot
:return: snapshot name ready for backend VMAX assignment
:return: snapshot name ready for backend PowerMax/VMAX assignment
"""
new_snap_name = None
if manage:
@ -813,8 +819,8 @@ class VMAXUtils(object):
"""
vol_head = source_vol['volumeHeader']
# VMAX disk geometry uses cylinders, so volume sizes are matched to
# the nearest full cylinder size: 1GB = 547cyl = 1026MB
# PowerMax/VMAX disk geometry uses cylinders, so volume sizes are
# matched to the nearest full cylinder size: 1GB = 547cyl = 1026MB
if vol_head['capMB'] < 1026 or not vol_head['capGB'].is_integer():
return False
@ -857,8 +863,8 @@ class VMAXUtils(object):
if not source_vol['timeFinderInfo']['snapVXSrc']:
return False
# VMAX disk geometry uses cylinders, so volume sizes are matched to
# the nearest full cylinder size: 1GB = 547cyl = 1026MB
# PowerMax/VMAX disk geometry uses cylinders, so volume sizes are
# matched to the nearest full cylinder size: 1GB = 547cyl = 1026MB
if (vol_head['capMB'] < 1026 or
not vol_head['capGB'].is_integer()):
return False

4
cinder/volume/manager.py

@ -165,6 +165,10 @@ CONF.register_opts(volume_backend_opts, group=config.SHARED_CONF_GROUP)
# new name (the dict value) for at least a cycle to allow time for deployments
# to transition.
MAPPING = {
'cinder.volume.drivers.dell_emc.vmax.iscsi.VMAXISCSIDriver':
'cinder.volume.drivers.dell_emc.powermax.iscsi.PowerMaxISCSIDriver',
'cinder.volume.drivers.dell_emc.vmax.fc.VMAXFCDriver':
'cinder.volume.drivers.dell_emc.powermax.fc.PowerMaxFCDriver',
}

358
doc/source/configuration/block-storage/drivers/dell-emc-vmax-driver.rst → doc/source/configuration/block-storage/drivers/dell-emc-powermax-driver.rst

@ -1,16 +1,24 @@
==================================
Dell EMC VMAX iSCSI and FC drivers
==================================
======================================
Dell EMC POWERMAX iSCSI and FC drivers
======================================
The Dell EMC VMAX drivers, ``VMAXISCSIDriver`` and ``VMAXFCDriver``, support
the use of Dell EMC VMAX storage arrays with the Cinder Block Storage project.
They both provide equivalent functions and differ only in support for their
respective host attachment methods.
The Dell EMC PowerMax drivers, ``PowerMaxISCSIDriver`` and ``PowerMaxFCDriver``,
support the use of Dell EMC PowerMax and VMAX storage arrays with the Cinder
Block Storage project. They both provide equivalent functions and differ only
in support for their respective host attachment methods.
The drivers perform volume operations by communicating with the back-end VMAX
storage management software. They use the Requests HTTP library to communicate
with a Unisphere for VMAX instance, using a RESTAPI interface in the backend
to perform VMAX storage operations.
The drivers perform volume operations by communicating with the back-end
PowerMax storage management software. They use the Requests HTTP library to
communicate with a Unisphere for PowerMax instance, using a RESTAPI interface
in the backend to perform PowerMax and VMAX storage operations.
.. note::
While ``PowerMax`` will be used throughout this document, it will be used
to collectively categorize the following supported arrays, PowerMax 2000,
8000, VMAX All Flash 250F, 450F, 850F and 950F and VMAX Hybrid. Please note
That we will no longer be supporting the VMAX Hybrid in the ``T`` release
of OpenStack.
.. note::
@ -20,17 +28,18 @@ to perform VMAX storage operations.
leveraged workload i.e. DSS, DSS_REP, OLTP and OLTP_REP, attaching and
detaching will no longer work and the volume type will be unusable.
Refrain from upgrading to PowerMax OS 5978 or greater on an All Flash
until a fix is merged. Please contact your Dell EMC VMAX customer support
representative if in any doubt.
until a fix is merged. Please contact your Dell EMC PowerMax customer
support representative if in any doubt.
System requirements and licensing
=================================
The Dell EMC VMAX Cinder driver supports the VMAX-3 hybrid series, VMAX
All-Flash series and the PowerMax arrays.
The Dell EMC PowerMax Cinder driver supports the VMAX-3 hybrid series, VMAX
All-Flash series and the PowerMax arrays. Please note we will be no longer
supporting the VMAX hybrid series in the ``T`` release of OpenStack.
The array operating system software, Solutions Enabler 9.0.x series, and
Unisphere for PowerMax 9.0.x series are required to run Dell EMC VMAX
Unisphere for PowerMax 9.0.x series are required to run Dell EMC PowerMax
Cinder driver.
Download Solutions Enabler and Unisphere from the Dell EMC's support web site
@ -38,8 +47,8 @@ Download Solutions Enabler and Unisphere from the Dell EMC's support web site
and Configuration Guide`` and ``Dell EMC Unisphere for PowerMax Installation
Guide`` at ``support.emc.com``.
Required VMAX software suites for OpenStack
-------------------------------------------
Required PowerMax software suites for OpenStack
-----------------------------------------------
There are five Dell EMC Software Suites sold with the VMAX Hybrid arrays:
@ -49,17 +58,17 @@ There are five Dell EMC Software Suites sold with the VMAX Hybrid arrays:
- Remote Replication Suite
- Total Productivity Pack
The Dell EMC VMAX Cinder driver requires the Advanced Suite and the Local
The Dell EMC PowerMax Cinder driver requires the Advanced Suite and the Local
Replication Suite or the Total Productivity Pack (it includes the Advanced
Suite and the Local Replication Suite) for the VMAX Hybrid.
Using VMAX Remote Replication functionality will also require the Remote
Using PowerMax Remote Replication functionality will also require the Remote
Replication Suite.
For full functionality including SRDF for the VMAX All Flash, the FX package,
or the F package plus the SRDF ``a la carte`` add on is required.
The storage system also requires a Unisphere for VMAX (SMC) eLicence.
The storage system also requires a Unisphere for PowerMax (SMC) eLicence.
Each are licensed separately. For further details on how to get the
relevant license(s), reference eLicensing Support below.
@ -68,7 +77,7 @@ relevant license(s), reference eLicensing Support below.
eLicensing support
------------------
To activate your entitlements and obtain your VMAX license files, visit the
To activate your entitlements and obtain your PowerMax license files, visit the
Service Center on `<https://support.emc.com>`_, as directed on your License
Authorization Code (LAC) letter emailed to you.
@ -92,7 +101,7 @@ Authorization Code (LAC) letter emailed to you.
Supported operations
====================
VMAX drivers support these operations:
PowerMax drivers support these operations:
- Create, list, delete, attach, and detach volumes
- Create, list, and delete volume snapshots
@ -112,7 +121,7 @@ VMAX drivers support these operations:
- Manage and unmanage volumes and snapshots
- List Manageable Volumes/Snapshots
VMAX drivers also support the following features:
PowerMax drivers also support the following features:
- Dynamic masking view creation
- Dynamic determination of the target iSCSI IP address
@ -137,15 +146,15 @@ VMAX drivers also support the following features:
compressed.
VMAX naming conventions
=======================
PowerMax naming conventions
===========================
Masking view names
------------------
Masking views are dynamically created by the VMAX FC and iSCSI drivers using
the following naming conventions. ``[protocol]`` is either ``I`` for volumes
attached over iSCSI or ``F`` for volumes attached over Fiber Channel.
Masking views are dynamically created by the PowerMax FC and iSCSI drivers
using the following naming conventions. ``[protocol]`` is either ``I`` for
volumes attached over iSCSI or ``F`` for volumes attached over Fiber Channel.
.. code-block:: text