VMAX driver - Deprecate backend xml configuration

The use of xml files for vmax backend configuration is deprecated.
Configuration parameters should be set in cinder.conf for security and
uniformity. The xml file can still be used but will not be supported after
the queens release.

Change-Id: Ic7fc1827608190ec47db30b1265bebde616b616b
Implements: blueprint backend-xml-deprecation
This commit is contained in:
Unana Okpoyo 2017-10-02 11:33:55 +01:00 committed by Ciara Stacke
parent 6480e33b98
commit ec7f04ee97
6 changed files with 150 additions and 30 deletions

View File

@ -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

View File

@ -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') == '<is> 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

View File

@ -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"

View File

@ -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"

View File

@ -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()

View File

@ -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.