diff --git a/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py b/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py index 9e2eede9051..bfc97ff5a60 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/vmax/test_vmax.py @@ -74,7 +74,7 @@ class VMAXCommonData(object): failed_resource = 'OS-failed-resource' fake_host = 'HostX@Backend#Diamond+DSS+SRP_1+000197800123' new_host = 'HostX@Backend#Silver+OLTP+SRP_1+000197800123' - version = '3.0.0' + version = '3.1.0' volume_wwn = '600000345' remote_array = '000197800124' device_id = '00001' @@ -846,14 +846,34 @@ class FakeRequestsSession(object): class FakeConfiguration(object): def __init__(self, emc_file=None, volume_backend_name=None, - interval=0, retries=0, replication_device=None): + interval=0, retries=0, replication_device=None, **kwargs): self.cinder_dell_emc_config_file = emc_file self.interval = interval self.retries = retries self.volume_backend_name = volume_backend_name self.config_group = volume_backend_name + self.san_is_local = False if replication_device: self.replication_device = [replication_device] + for key, value in kwargs.items(): + if key == 'san_login': + self.san_login = value + elif key == 'san_password': + self.san_password = value + elif key == 'san_ip': + self.san_ip = value + elif key == 'san_rest_port': + self.san_rest_port = value + elif key == 'vmax_srp': + self.vmax_srp = value + elif key == 'vmax_service_level': + self.vmax_service_level = value + elif key == 'vmax_workload': + self.vmax_workload = value + elif key == 'vmax_port_groups': + self.vmax_port_groups = value + elif key == 'vmax_array': + self.vmax_array = value def safe_get(self, key): try: @@ -4499,6 +4519,29 @@ class VMAXCommonTest(test.TestCase): source_group, source_vols)) self.assertEqual(ref_model_update, model_update) + def test_get_attributes_from_cinder_config(self): + kwargs_expected = ( + {'RestServerIp': '1.1.1.1', + 'RestServerPort': 8443, + 'RestUserName': 'smc', + 'RestPassword': 'smc', + 'SSLCert': None, + 'SSLVerify': False, + 'SerialNumber': self.data.array, + 'srpName': 'SRP_1', + 'PortGroup': self.data.port_group_name_i}) + backup_conf = self.common.configuration + configuration = FakeConfiguration( + None, 'CommonTests', 1, 1, san_ip='1.1.1.1', san_login='smc', + vmax_array=self.data.array, vmax_srp='SRP_1', san_password='smc', + san_rest_port=8443, vmax_port_groups=[self.data.port_group_name_i]) + self.common.configuration = configuration + kwargs_returned = self.common.get_attributes_from_cinder_config() + self.assertEqual(kwargs_expected, kwargs_returned) + self.common.configuration = backup_conf + kwargs = self.common.get_attributes_from_cinder_config() + self.assertIsNone(kwargs) + class VMAXFCTest(test.TestCase): def setUp(self): @@ -5020,9 +5063,9 @@ class VMAXMaskingTest(test.TestCase): self._gather_info = common.VMAXCommon._gather_info common.VMAXCommon._gather_info = mock.Mock() driver = common.VMAXCommon( - 'iSCSI', common.VMAXCommon.VERSION, configuration=configuration) + 'iSCSI', self.data.version, configuration=configuration) driver_fc = common.VMAXCommon( - 'FC', common.VMAXCommon.VERSION, configuration=configuration) + 'FC', self.data.version, configuration=configuration) self.driver = driver self.driver_fc = driver_fc self.mask = self.driver.masking diff --git a/cinder/volume/drivers/dell_emc/vmax/common.py b/cinder/volume/drivers/dell_emc/vmax/common.py index a5f9878772e..eb63fd93452 100644 --- a/cinder/volume/drivers/dell_emc/vmax/common.py +++ b/cinder/volume/drivers/dell_emc/vmax/common.py @@ -16,6 +16,7 @@ import ast from copy import deepcopy import os.path +import random import sys from oslo_config import cfg @@ -55,6 +56,7 @@ REPLICATION_ERROR = fields.ReplicationStatus.ERROR vmax_opts = [ cfg.StrOpt('cinder_dell_emc_config_file', default=CINDER_EMC_CONFIG_FILE, + deprecated_for_removal=True, help='Use this file for cinder emc plugin ' 'config data.'), cfg.IntOpt('interval', @@ -68,7 +70,22 @@ vmax_opts = [ cfg.BoolOpt('initiator_check', default=False, help='Use this value to enable ' - 'the initiator_check.')] + 'the initiator_check.'), + cfg.PortOpt(utils.VMAX_SERVER_PORT, + default=8443, + help='REST server port number.'), + cfg.StrOpt(utils.VMAX_ARRAY, + help='Serial number of the array to connect to.'), + cfg.StrOpt(utils.VMAX_SRP, + help='Storage resource pool on array to use for provisioning.'), + cfg.StrOpt(utils.VMAX_SERVICE_LEVEL, + help='Service level to use for provisioning storage.'), + cfg.StrOpt(utils.VMAX_WORKLOAD, + help='Workload'), + cfg.ListOpt(utils.VMAX_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) @@ -81,18 +98,6 @@ class VMAXCommon(object): It supports VMAX 3 and VMAX All Flash arrays. """ - VERSION = "3.0.0" - - stats = {'driver_version': '3.0', - 'free_capacity_gb': 0, - 'reserved_percentage': 0, - 'storage_protocol': None, - 'total_capacity_gb': 0, - 'vendor_name': 'Dell EMC', - 'volume_backend_name': None, - 'replication_enabled': False, - 'replication_targets': None} - pool_info = {'backend_name': None, 'config_file': None, 'arrays_info': {}, @@ -123,8 +128,10 @@ class VMAXCommon(object): def _gather_info(self): """Gather the relevant information for update_volume_stats.""" self._get_attributes_from_config() - array_info = self.utils.parse_file_to_get_array_map( - self.pool_info['config_file']) + array_info = self.get_attributes_from_cinder_config() + if array_info is None: + array_info = self.utils.parse_file_to_get_array_map( + self.pool_info['config_file']) self.rest.set_rest_credentials(array_info) finalarrayinfolist = self._get_slo_workload_combinations( array_info) @@ -855,7 +862,8 @@ class VMAXCommon(object): array_reserve_percent) def _set_config_file_and_get_extra_specs(self, volume, - volume_type_id=None): + volume_type_id=None, + register_config_file=True): """Given the volume object get the associated volumetype. Given the volume object get the associated volumetype and the @@ -876,13 +884,15 @@ class VMAXCommon(object): qos_specs = res['qos_specs'] config_group = None + config_file = None # If there are no extra specs then the default case is assumed. if extra_specs: config_group = self.configuration.config_group if extra_specs.get('replication_enabled') == ' True': extra_specs[utils.IS_RE] = True - config_file = self._register_config_file_from_config_group( - config_group) + if register_config_file: + config_file = self._register_config_file_from_config_group( + config_group) return extra_specs, config_file, qos_specs def _find_device_on_array(self, volume, extra_specs): @@ -1061,11 +1071,17 @@ class VMAXCommon(object): :raises: VolumeBackendAPIException: """ try: - extra_specs, config_file, qos_specs = ( - self._set_config_file_and_get_extra_specs( - volume, volume_type_id)) - array_info = self.utils.parse_file_to_get_array_map( - config_file) + array_info = self.get_attributes_from_cinder_config() + if array_info: + extra_specs, config_file, qos_specs = ( + self._set_config_file_and_get_extra_specs( + volume, volume_type_id, register_config_file=False)) + else: + extra_specs, config_file, qos_specs = ( + self._set_config_file_and_get_extra_specs( + volume, volume_type_id)) + array_info = self.utils.parse_file_to_get_array_map( + self.pool_info['config_file']) if not array_info: exception_message = (_( "Unable to get corresponding record for srp.")) @@ -3568,3 +3584,42 @@ class VMAXCommon(object): vol_model_updates.append(update) return model_update, vol_model_updates + + def get_attributes_from_cinder_config(self): + LOG.debug("Using cinder.conf file") + kwargs = None + 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) + 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) + if srp_name is None: + LOG.error("SRP Name must be set in cinder.conf") + slo = self.configuration.safe_get(utils.VMAX_SERVICE_LEVEL) + workload = self.configuration.safe_get(utils.WORKLOAD) + port_groups = self.configuration.safe_get(utils.VMAX_PORT_GROUPS) + random_portgroup = None + if port_groups: + random_portgroup = random.choice(self.configuration.safe_get( + utils.VMAX_PORT_GROUPS)) + kwargs = ( + {'RestServerIp': self.configuration.safe_get( + utils.VMAX_SERVER_IP), + 'RestServerPort': self.configuration.safe_get( + utils.VMAX_SERVER_PORT), + 'RestUserName': username, + 'RestPassword': password, + 'SSLCert': self.configuration.safe_get('driver_client_cert'), + 'SerialNumber': serial_number, + 'srpName': srp_name, + 'PortGroup': random_portgroup}) + if self.configuration.safe_get('driver_ssl_cert_verify'): + kwargs.update({'SSLVerify': self.configuration.safe_get( + 'driver_ssl_cert_path')}) + else: + kwargs.update({'SSLVerify': False}) + if slo is not None: + kwargs.update({'ServiceLevel': slo, 'Workload': workload}) + return kwargs diff --git a/cinder/volume/drivers/dell_emc/vmax/fc.py b/cinder/volume/drivers/dell_emc/vmax/fc.py index 585ae71689d..9be38fd73ab 100644 --- a/cinder/volume/drivers/dell_emc/vmax/fc.py +++ b/cinder/volume/drivers/dell_emc/vmax/fc.py @@ -20,13 +20,14 @@ 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.san import san from cinder.zonemanager import utils as fczm_utils LOG = logging.getLogger(__name__) @interface.volumedriver -class VMAXFCDriver(driver.FibreChannelDriver): +class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver): """FC Drivers for VMAX using REST. Version history: @@ -83,6 +84,7 @@ class VMAXFCDriver(driver.FibreChannelDriver): - Support for live migration - Support for Generic Volume Group 3.1.0 - Support for replication groups (Tiramisu) + - Deprecate backend xml configuration """ VERSION = "3.1.0" diff --git a/cinder/volume/drivers/dell_emc/vmax/iscsi.py b/cinder/volume/drivers/dell_emc/vmax/iscsi.py index bc5850d64a7..958b491e93f 100644 --- a/cinder/volume/drivers/dell_emc/vmax/iscsi.py +++ b/cinder/volume/drivers/dell_emc/vmax/iscsi.py @@ -22,14 +22,14 @@ import six from cinder import exception from cinder.i18n import _ from cinder import interface -from cinder.volume import driver from cinder.volume.drivers.dell_emc.vmax import common +from cinder.volume.drivers.san import san LOG = logging.getLogger(__name__) @interface.volumedriver -class VMAXISCSIDriver(driver.ISCSIDriver): +class VMAXISCSIDriver(san.SanISCSIDriver): """ISCSI Drivers for VMAX using Rest. Version history: @@ -88,6 +88,7 @@ class VMAXISCSIDriver(driver.ISCSIDriver): - Support for live migration - Support for Generic Volume Group 3.1.0 - Support for replication groups (Tiramisu) + - Deprecate backend xml configuration """ VERSION = "3.1.0" diff --git a/cinder/volume/drivers/dell_emc/vmax/utils.py b/cinder/volume/drivers/dell_emc/vmax/utils.py index 4b6c7b1aabb..953bab097f0 100644 --- a/cinder/volume/drivers/dell_emc/vmax/utils.py +++ b/cinder/volume/drivers/dell_emc/vmax/utils.py @@ -59,6 +59,17 @@ EXTRA_SPECS = 'extra_specs' IS_RE = 'replication_enabled' DISABLECOMPRESSION = 'storagetype:disablecompression' +# Cinder.conf vmax configuration +VMAX_SERVER_IP = 'san_ip' +VMAX_USER_NAME = 'san_login' +VMAX_PASSWORD = 'san_password' +VMAX_SERVER_PORT = 'san_rest_port' +VMAX_ARRAY = 'vmax_array' +VMAX_WORKLOAD = 'vmax_workload' +VMAX_SRP = 'vmax_srp' +VMAX_SERVICE_LEVEL = 'vmax_service_level' +VMAX_PORT_GROUPS = 'vmax_port_groups' + class VMAXUtils(object): """Utility class for Rest based VMAX volume drivers. @@ -325,6 +336,8 @@ class VMAXUtils(object): :param file_name: the configuration file :returns: list """ + LOG.warning("Use of xml file in backend configuration is deprecated " + "in Queens and will not be supported in future releases.") kwargs = {} my_file = open(file_name, 'r') data = my_file.read() diff --git a/releasenotes/notes/vmax-deprecate-backend-xml-708a41919bcc55a8.yaml b/releasenotes/notes/vmax-deprecate-backend-xml-708a41919bcc55a8.yaml new file mode 100644 index 00000000000..f2b73d78593 --- /dev/null +++ b/releasenotes/notes/vmax-deprecate-backend-xml-708a41919bcc55a8.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + The use of xml files for vmax backend configuration is now deprecated and + will be removed during the following release. Deployers are encouraged + to use the cinder.conf for configuring connections to the vmax.