From 17c9ac3cbc56944ec71370b7f9cdb7439fda33f6 Mon Sep 17 00:00:00 2001 From: Ivan Pchelintsev Date: Tue, 19 May 2020 14:01:27 +0300 Subject: [PATCH] Remove VxFlex OS credentials from connection_properties VxFlex OS password is not stored in block_device_mapping table. Instead of this passwords are stored in separate file and are retrieved during each attach/detach operation. Closes-Bug: #1823200 Change-Id: I46f4b16c4cb383cbc61b5e212e3c64962a3fc282 --- os_brick/initiator/connectors/scaleio.py | 20 ++++++++++-- os_brick/privileged/scaleio.py | 31 +++++++++++++++++++ .../initiator/connectors/test_scaleio.py | 8 +++-- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/os_brick/initiator/connectors/scaleio.py b/os_brick/initiator/connectors/scaleio.py index 0f65b96..1ae65ab 100644 --- a/os_brick/initiator/connectors/scaleio.py +++ b/os_brick/initiator/connectors/scaleio.py @@ -30,6 +30,7 @@ from os_brick import utils LOG = logging.getLogger(__name__) DEVICE_SCAN_ATTEMPTS_DEFAULT = 3 +CONNECTOR_CONF_PATH = '/opt/emc/scaleio/openstack/connector.conf' synchronized = lockutils.synchronized_with_prefix('os-brick-') @@ -86,6 +87,19 @@ class ScaleIOConnector(base.BaseLinuxConnector): LOG.error(msg) raise exception.BrickException(message=msg) + @staticmethod + def _get_connector_password(config_group, failed_over): + LOG.info("Get ScaleIO connector password from configuration file") + try: + return priv_scaleio.get_connector_password(CONNECTOR_CONF_PATH, + config_group, + failed_over) + except Exception as e: + msg = _("Error getting ScaleIO connector password from " + "configuration file: %s") % e + LOG.error(msg) + raise exception.BrickException(message=msg) + def _rescan_vols(self): LOG.info("ScaleIO rescan volumes") @@ -306,8 +320,10 @@ class ScaleIOConnector(base.BaseLinuxConnector): self.server_ip = connection_properties['serverIP'] self.server_port = connection_properties['serverPort'] self.server_username = connection_properties['serverUsername'] - self.server_password = connection_properties['serverPassword'] - self.server_token = connection_properties['serverToken'] + self.server_password = self._get_connector_password( + connection_properties['config_group'], + connection_properties['failed_over'], + ) self.iops_limit = connection_properties['iopsLimit'] self.bandwidth_limit = connection_properties['bandwidthLimit'] device_info = {'type': 'block', diff --git a/os_brick/privileged/scaleio.py b/os_brick/privileged/scaleio.py index 322289e..4b619b4 100644 --- a/os_brick/privileged/scaleio.py +++ b/os_brick/privileged/scaleio.py @@ -11,12 +11,14 @@ # under the License. from binascii import hexlify +import configparser from contextlib import contextmanager from fcntl import ioctl import os import struct import uuid +from os_brick import exception from os_brick import privileged SCINI_DEVICE_PATH = '/dev/scini' @@ -70,3 +72,32 @@ def rescan_vols(op_code): with open_scini_device() as fd: ioctl(fd, op_code, struct.pack('Q', 0)) + + +@privileged.default.entrypoint +def get_connector_password(filename, config_group, failed_over): + """Read ScaleIO connector configuration file and get appropriate password. + + :param filename: path to connector configuration file + :type filename: str + :param config_group: name of section in configuration file + :type config_group: str + :param failed_over: flag representing if storage is in failed over state + :type failed_over: bool + :return: connector password + :rtype: str + """ + + if not os.path.isfile(filename): + msg = ( + "ScaleIO connector configuration file " + "is not found in path %s." % filename + ) + raise exception.BrickException(message=msg) + + conf = configparser.ConfigParser() + conf.read(filename) + password_key = ( + "replicating_san_password" if failed_over else "san_password" + ) + return conf[config_group][password_key] diff --git a/os_brick/tests/initiator/connectors/test_scaleio.py b/os_brick/tests/initiator/connectors/test_scaleio.py index 14e45b2..c9671c0 100644 --- a/os_brick/tests/initiator/connectors/test_scaleio.py +++ b/os_brick/tests/initiator/connectors/test_scaleio.py @@ -45,8 +45,8 @@ class ScaleIOConnectorTestCase(test_connector.ConnectorTestCase): 'scaleIO_volume_id': self.vol['provider_id'], 'serverPort': 443, 'serverUsername': 'test', - 'serverPassword': 'fake', - 'serverToken': 'fake_token', + 'config_group': 'test', + 'failed_over': False, 'iopsLimit': None, 'bandwidthLimit': None } @@ -83,6 +83,9 @@ class ScaleIOConnectorTestCase(test_connector.ConnectorTestCase): return_value=["emc-vol-{}".format(self.vol['id'])]) # Patch scaleio privileged calls + self.get_password_mock = self.mock_object(scaleio.priv_scaleio, + 'get_connector_password', + return_value='fake_password') self.get_guid_mock = self.mock_object(scaleio.priv_scaleio, 'get_guid', return_value=self.fake_guid) self.rescan_vols_mock = self.mock_object(scaleio.priv_scaleio, @@ -168,6 +171,7 @@ class ScaleIOConnectorTestCase(test_connector.ConnectorTestCase): self.connector.connect_volume(self.fake_connection_properties) self.get_guid_mock.assert_called_once_with( self.connector.GET_GUID_OP_CODE) + self.get_password_mock.assert_called_once() def test_connect_volume_without_volume_id(self): """Successful connect to volume without a Volume Id""" -- 2.17.1