Modify the configuration mode of FusionStorage Cinder Driver
Modify the configuration mode by using existing standard config options. Change-Id: I033a739c08c01867660c00ea44642e78ddf3e3ea
This commit is contained in:
parent
a8d995c2f2
commit
c9aa071b32
@ -15,6 +15,7 @@
|
||||
import ddt
|
||||
|
||||
import mock
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
@ -43,52 +44,108 @@ class FusionStorageConfTestCase(test.TestCase):
|
||||
self.tmp_dir + '/cinder.conf')
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.add_section('storage')
|
||||
config.set('storage', 'RestURL', 'https://fake_rest_site')
|
||||
config.set('storage', 'UserName', 'fake_user')
|
||||
config.set('storage', 'Password', 'fake_passwd')
|
||||
config.set('storage', 'StoragePool', 'fake_pool')
|
||||
config.add_section('backend_name')
|
||||
config.set('backend_name', 'dsware_rest_url', 'https://fake_rest_site')
|
||||
config.set('backend_name', 'san_login', 'fake_user')
|
||||
config.set('backend_name', 'san_password', 'fake_passwd')
|
||||
config.set('backend_name', 'dsware_storage_pools', 'fake_pool')
|
||||
|
||||
config.add_section('manager_ip')
|
||||
config.set('manager_ip', 'fake_host', 'fake_ip')
|
||||
config.write(open(self.conf.cinder_fusionstorage_conf_file, 'w'))
|
||||
|
||||
def test_update_config_value(self):
|
||||
@mock.patch.object(fs_conf.FusionStorageConf, '_encode_authentication')
|
||||
@mock.patch.object(fs_conf.FusionStorageConf, '_pools_name')
|
||||
@mock.patch.object(fs_conf.FusionStorageConf, '_san_address')
|
||||
@mock.patch.object(fs_conf.FusionStorageConf, '_san_user')
|
||||
@mock.patch.object(fs_conf.FusionStorageConf, '_san_password')
|
||||
def test_update_config_value(self, mock_san_password, mock_san_user,
|
||||
mock_san_address, mock_pools_name,
|
||||
mock_encode_authentication):
|
||||
self.fusionstorage_conf.update_config_value()
|
||||
mock_encode_authentication.assert_called_once_with()
|
||||
mock_pools_name.assert_called_once_with()
|
||||
mock_san_address.assert_called_once_with()
|
||||
mock_san_user.assert_called_once_with()
|
||||
mock_san_password.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(os.path, 'exists')
|
||||
def test__encode_authentication(self, mock_exists):
|
||||
config = configparser.ConfigParser()
|
||||
config.read(self.conf.cinder_fusionstorage_conf_file)
|
||||
storage_info = {'RestURL': config.get('storage', 'RestURL'),
|
||||
'UserName': config.get('storage', 'UserName'),
|
||||
'Password': config.get('storage', 'Password'),
|
||||
'StoragePool': config.get('storage', 'StoragePool')}
|
||||
mock_exists.return_value = False
|
||||
|
||||
user_name = 'fake_user'
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=storage_info)
|
||||
return_value=user_name)
|
||||
self.fusionstorage_conf._encode_authentication()
|
||||
|
||||
self.fusionstorage_conf.update_config_value()
|
||||
password = 'fake_passwd'
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=password)
|
||||
self.fusionstorage_conf._encode_authentication()
|
||||
|
||||
@mock.patch.object(os.path, 'exists')
|
||||
@mock.patch.object(configparser.ConfigParser, 'set')
|
||||
def test__rewrite_conf(self, mock_set, mock_exists):
|
||||
mock_exists.return_value = False
|
||||
mock_set.return_value = "success"
|
||||
self.fusionstorage_conf._rewrite_conf('fake_name', 'fake_pwd')
|
||||
|
||||
def test__san_address(self):
|
||||
address = 'https://fake_rest_site'
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=address)
|
||||
self.fusionstorage_conf._san_address()
|
||||
self.assertEqual('https://fake_rest_site',
|
||||
self.fusionstorage_conf.configuration.san_address)
|
||||
|
||||
def test__san_user(self):
|
||||
user = '!&&&ZmFrZV91c2Vy'
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=user)
|
||||
self.fusionstorage_conf._san_user()
|
||||
self.assertEqual(
|
||||
'fake_user', self.fusionstorage_conf.configuration.san_user)
|
||||
|
||||
user = 'fake_user_2'
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=user)
|
||||
self.fusionstorage_conf._san_user()
|
||||
self.assertEqual(
|
||||
'fake_user_2', self.fusionstorage_conf.configuration.san_user)
|
||||
|
||||
def test__san_password(self):
|
||||
password = '!&&&ZmFrZV9wYXNzd2Q='
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=password)
|
||||
self.fusionstorage_conf._san_password()
|
||||
self.assertEqual(
|
||||
'fake_passwd', self.fusionstorage_conf.configuration.san_password)
|
||||
|
||||
password = 'fake_passwd_2'
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=password)
|
||||
self.fusionstorage_conf._san_password()
|
||||
self.assertEqual('fake_passwd_2',
|
||||
self.fusionstorage_conf.configuration.san_password)
|
||||
|
||||
def test__pools_name(self):
|
||||
pools_name = 'fake_pool'
|
||||
self.mock_object(
|
||||
self.fusionstorage_conf.configuration, 'safe_get',
|
||||
return_value=pools_name)
|
||||
self.fusionstorage_conf._pools_name()
|
||||
self.assertListEqual(
|
||||
['fake_pool'], self.fusionstorage_conf.configuration.pools_name)
|
||||
|
||||
def test__encode_authentication(self):
|
||||
config = configparser.ConfigParser()
|
||||
config.read(self.conf.cinder_fusionstorage_conf_file)
|
||||
|
||||
storage_info = {'RestURL': config.get('storage', 'RestURL'),
|
||||
'UserName': config.get('storage', 'UserName'),
|
||||
'Password': config.get('storage', 'Password'),
|
||||
'StoragePool': config.get('storage', 'StoragePool')}
|
||||
self.fusionstorage_conf._encode_authentication(storage_info)
|
||||
name_node = storage_info.get('UserName')
|
||||
pwd_node = storage_info.get('Password')
|
||||
self.assertEqual('!&&&ZmFrZV91c2Vy', name_node)
|
||||
self.assertEqual('!&&&ZmFrZV9wYXNzd2Q=', pwd_node)
|
||||
|
||||
def test__manager_ip(self):
|
||||
manager_ips = {'fake_host': 'fake_ip'}
|
||||
self.mock_object(
|
||||
|
@ -23,9 +23,8 @@ VOLUME_NOT_EXIST = 31000000
|
||||
BASIC_URI = '/dsware/service/'
|
||||
CONF_PATH = "/etc/cinder/cinder.conf"
|
||||
|
||||
CONF_ADDRESS = "RestURL"
|
||||
CONF_ADDRESS = "dsware_rest_url"
|
||||
CONF_MANAGER_IP = "manager_ips"
|
||||
CONF_POOLS = "StoragePool"
|
||||
CONF_PWD = "Password"
|
||||
CONF_STORAGE = "storage"
|
||||
CONF_USER = "UserName"
|
||||
CONF_POOLS = "dsware_storage_pools"
|
||||
CONF_PWD = "san_password"
|
||||
CONF_USER = "san_login"
|
||||
|
@ -25,6 +25,7 @@ from cinder import interface
|
||||
from cinder.volume import driver
|
||||
from cinder.volume.drivers.fusionstorage import fs_client
|
||||
from cinder.volume.drivers.fusionstorage import fs_conf
|
||||
from cinder.volume.drivers.san import san
|
||||
from cinder.volume import utils as volume_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -89,13 +90,15 @@ volume_opts = [
|
||||
help='This option is to support the FSA to mount across the '
|
||||
'different nodes. The parameters takes the standard dict '
|
||||
'config form, manager_ips = host1:ip1, host2:ip2...'),
|
||||
cfg.DictOpt('storage',
|
||||
default={},
|
||||
secret=True,
|
||||
help='This field is configured with the information of array '
|
||||
'and user info. The parameters takes the standard dict '
|
||||
'config form, Storage = UserName:xxx, Password:xxx, '
|
||||
'RestURL:xxx')
|
||||
cfg.StrOpt('dsware_rest_url',
|
||||
default='',
|
||||
help='The address of FusionStorage array. For example, '
|
||||
'"dsware_rest_url=xxx"'),
|
||||
cfg.StrOpt('dsware_storage_pools',
|
||||
default="",
|
||||
help='The list of pools on the FusionStorage array, the '
|
||||
'semicolon(;) was used to split the storage pools, '
|
||||
'"dsware_storage_pools = xxx1; xxx2; xxx3"')
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -116,6 +119,7 @@ class DSWAREDriver(driver.VolumeDriver):
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
self.configuration.append_config_values(volume_opts)
|
||||
self.configuration.append_config_values(san.san_opts)
|
||||
self.conf = fs_conf.FusionStorageConf(self.configuration, self.host)
|
||||
self.client = None
|
||||
|
||||
|
@ -44,16 +44,15 @@ class FusionStorageConf(object):
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
def update_config_value(self):
|
||||
storage_info = self.configuration.safe_get(constants.CONF_STORAGE)
|
||||
self._pools_name(storage_info)
|
||||
self._san_address(storage_info)
|
||||
self._encode_authentication(storage_info)
|
||||
self._san_user(storage_info)
|
||||
self._san_password(storage_info)
|
||||
self._encode_authentication()
|
||||
self._pools_name()
|
||||
self._san_address()
|
||||
self._san_user()
|
||||
self._san_password()
|
||||
|
||||
def _encode_authentication(self, storage_info):
|
||||
name_node = storage_info.get(constants.CONF_USER)
|
||||
pwd_node = storage_info.get(constants.CONF_PWD)
|
||||
def _encode_authentication(self):
|
||||
name_node = self.configuration.safe_get(constants.CONF_USER)
|
||||
pwd_node = self.configuration.safe_get(constants.CONF_PWD)
|
||||
|
||||
need_encode = False
|
||||
if name_node is not None and not name_node.startswith('!&&&'):
|
||||
@ -67,29 +66,18 @@ class FusionStorageConf(object):
|
||||
need_encode = True
|
||||
|
||||
if need_encode:
|
||||
self._rewrite_conf(storage_info, name_node, pwd_node)
|
||||
self._rewrite_conf(name_node, pwd_node)
|
||||
|
||||
def _rewrite_conf(self, storage_info, name_node, pwd_node):
|
||||
storage_info.update({constants.CONF_USER: name_node,
|
||||
constants.CONF_PWD: pwd_node})
|
||||
storage_info = ("\n %(conf_name)s: %(name)s,"
|
||||
"\n %(conf_pwd)s: %(pwd)s,"
|
||||
"\n %(conf_url)s: %(url)s,"
|
||||
"\n %(conf_pool)s: %(pool)s"
|
||||
% {"conf_name": constants.CONF_USER,
|
||||
"conf_pwd": constants.CONF_PWD,
|
||||
"conf_url": constants.CONF_ADDRESS,
|
||||
"conf_pool": constants.CONF_POOLS,
|
||||
"name": name_node,
|
||||
"pwd": pwd_node,
|
||||
"url": storage_info.get(constants.CONF_ADDRESS),
|
||||
"pool": storage_info.get(constants.CONF_POOLS)})
|
||||
def _rewrite_conf(self, name_node, pwd_node):
|
||||
if os.path.exists(constants.CONF_PATH):
|
||||
utils.execute("chmod", "666", constants.CONF_PATH,
|
||||
run_as_root=True)
|
||||
conf = configparser.ConfigParser()
|
||||
conf.read(constants.CONF_PATH)
|
||||
conf.set(self.host, constants.CONF_STORAGE, storage_info)
|
||||
if name_node:
|
||||
conf.set(self.host, constants.CONF_USER, name_node)
|
||||
if pwd_node:
|
||||
conf.set(self.host, constants.CONF_PWD, pwd_node)
|
||||
fh = open(constants.CONF_PATH, 'w')
|
||||
conf.write(fh)
|
||||
fh.close()
|
||||
@ -102,25 +90,29 @@ class FusionStorageConf(object):
|
||||
LOG.error(msg)
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
def _san_address(self, storage_info):
|
||||
address = storage_info.get(constants.CONF_ADDRESS)
|
||||
def _san_address(self):
|
||||
address = self.configuration.safe_get(constants.CONF_ADDRESS)
|
||||
self._assert_text_result(address, mess=constants.CONF_ADDRESS)
|
||||
setattr(self.configuration, 'san_address', address)
|
||||
|
||||
def _san_user(self, storage_info):
|
||||
user_text = storage_info.get(constants.CONF_USER)
|
||||
def _decode_text(self, text):
|
||||
return (base64.b64decode(six.b(text[4:])).decode() if
|
||||
text.startswith('!&&&') else text)
|
||||
|
||||
def _san_user(self):
|
||||
user_text = self.configuration.safe_get(constants.CONF_USER)
|
||||
self._assert_text_result(user_text, mess=constants.CONF_USER)
|
||||
user = base64.b64decode(six.b(user_text[4:])).decode()
|
||||
user = self._decode_text(user_text)
|
||||
setattr(self.configuration, 'san_user', user)
|
||||
|
||||
def _san_password(self, storage_info):
|
||||
pwd_text = storage_info.get(constants.CONF_PWD)
|
||||
def _san_password(self):
|
||||
pwd_text = self.configuration.safe_get(constants.CONF_PWD)
|
||||
self._assert_text_result(pwd_text, mess=constants.CONF_PWD)
|
||||
pwd = base64.b64decode(six.b(pwd_text[4:])).decode()
|
||||
pwd = self._decode_text(pwd_text)
|
||||
setattr(self.configuration, 'san_password', pwd)
|
||||
|
||||
def _pools_name(self, storage_info):
|
||||
pools_name = storage_info.get(constants.CONF_POOLS)
|
||||
def _pools_name(self):
|
||||
pools_name = self.configuration.safe_get(constants.CONF_POOLS)
|
||||
self._assert_text_result(pools_name, mess=constants.CONF_POOLS)
|
||||
pools = set(x.strip() for x in pools_name.split(';') if x.strip())
|
||||
if not pools:
|
||||
|
@ -0,0 +1,24 @@
|
||||
---
|
||||
upgrades:
|
||||
- The FusionStorage driver has added the configuration options "manager_ips",
|
||||
"dsware_rest_url", "san_login", "san_password" and "dsware_storage_pools".
|
||||
"[<backend_id>]/manager_ips", the ips of FusionStorage Agent(FSA). This
|
||||
option is to support FSA to mount accross the different FSA nodes. The
|
||||
parameters takes the standard dict config form, manager_ips = host1:ip1,
|
||||
host2:ip2...
|
||||
"[<backend_id>]/dsware_rest_url", the address and port of FusionStorage
|
||||
Manager(FSM) in the format of a string. Currently, only one "dsware_rest_url"
|
||||
is supported.
|
||||
"[<backend_id>]/san_login", the user name of the FusionStorage Manager(FSM)
|
||||
in the format of a string. Currently, only one "san_login" is supported.
|
||||
"[<backend_id>]/san_password", the user password of FusionStorage Manager(FSM)
|
||||
in the format of a string. Currently, only one "san_password" is supported.
|
||||
"[<backend_id>]/dsware_storage_pools", the name of the storage pools that
|
||||
exists on the FusionStorage Manager. Multiple storage pools can be configed,
|
||||
separated by a semicolon.
|
||||
deprecations:
|
||||
- The FusionStorage driver has deprecated the configuration options
|
||||
"dsware_isthin", "dsware_manager", "fusionstorageagent",
|
||||
"clone_volume_timeout", "pool_type", and "pool_id_filter". These configuration
|
||||
options will be removed in the Train release(14.0.0).
|
||||
|
Loading…
Reference in New Issue
Block a user