Add driver mode interface

Implement driver mode interface for share driver, that will allow operator
to switch share drivers to work in specific mode, like single or multi SVM.

Add usage of driver mode interface to Generic driver as an example.

To set driver mode use config option 'share_driver_mode'. Available values
are specified within its help message.

Partially Implements bp driver-modes
Change-Id: I2744cccfbe2c09c3d942822f902793493cd9befb
This commit is contained in:
Valeriy Ponomaryov 2014-12-18 14:30:48 +02:00
parent 7b588c86da
commit 28f311c9ad
6 changed files with 181 additions and 5 deletions

View File

@ -51,3 +51,11 @@ PING_PORTS = (
SERVICE_INSTANCE_SECGROUP_DATA = (
CIFS_PORTS + NFS_PORTS + SSH_PORTS + PING_PORTS)
SINGLE_SVM_MODE = 'single_svm'
MULTI_SVM_MODE = 'multi_svm'
VALID_SHARE_DRIVER_MODES = (
SINGLE_SVM_MODE,
MULTI_SVM_MODE,
)

View File

@ -20,7 +20,9 @@ Drivers for shares.
import time
from oslo.config import cfg
import six
from manila.common import constants
from manila import exception
from manila.i18n import _LE
from manila import network
@ -51,6 +53,13 @@ share_opts = [
"If not set, the share backend's config group will be used."
"If an option is not found within provided group, then"
"'DEFAULT' group will be used for search of option."),
cfg.ListOpt(
'share_driver_mode',
default=None,
help="One specific mode for driver to use. Available values: "
"%s. What modes are supported and can be used is "
"up to driver. If set None then default will be used." %
six.text_type(constants.VALID_SHARE_DRIVER_MODES)),
]
ssh_opts = [
@ -76,11 +85,8 @@ CONF.register_opts(ssh_opts)
class ExecuteMixin(object):
"""Provides an executable functionality to a driver class."""
def __init__(self, *args, **kwargs):
self.db = None
self.configuration = kwargs.get('configuration', None)
def init_execute_mixin(self, *args, **kwargs):
if self.configuration:
self.configuration.append_config_values(share_opts)
self.configuration.append_config_values(ssh_opts)
self.set_execute(kwargs.pop('execute', utils.execute))
@ -115,10 +121,58 @@ class ShareDriver(object):
self.configuration.append_config_values(share_opts)
network_config_group = (self.configuration.network_config_group or
self.configuration.config_group)
self.mode = self.configuration.safe_get('share_driver_mode')
else:
network_config_group = None
self.mode = CONF.share_driver_mode
if hasattr(self, 'init_execute_mixin'):
# Instance with 'ExecuteMixin'
self.init_execute_mixin(*args, **kwargs) # pylint: disable=E1101
self.network_api = network.API(config_group_name=network_config_group)
def _validate_driver_mode(self, mode):
valid = constants.VALID_SHARE_DRIVER_MODES
if mode not in valid:
data = {'mode': mode, 'valid': valid}
msg = ("Provided unsupported driver mode '%(mode)s'. List of "
"valid driver modes is %(valid)s." % data)
LOG.error(msg)
raise exception.InvalidParameterValue(msg)
return mode
def get_driver_mode(self, supported_driver_modes):
"""Verify and return driver mode.
Call this method within share driver to get value for 'mode' attr,
:param supported_driver_modes: list of supported modes by share driver,
see list of available values in
manila.common.constants.VALID_SHARE_DRIVER_MODES
:returns: text_type -- name of enabled driver mode.
:raises: exception.InvalidParameterValue
"""
msg = None
if not len(supported_driver_modes):
msg = "At least one mode should be supported by share driver."
elif self.mode:
if self.mode not in supported_driver_modes:
data = {'mode': self.mode, 'supported': supported_driver_modes}
msg = ("Unsupported driver mode '%(mode)s' is provided. "
"List of supported is %(supported)s." % data)
else:
return self._validate_driver_mode(self.mode)
elif len(supported_driver_modes) > 1:
msg = ("Driver mode was not specified explicitly and amount of "
"supported driver modes %s is bigger than one, please "
"specify it using config option 'share_driver_mode'." %
six.text_type(supported_driver_modes))
if msg:
LOG.error(msg)
raise exception.InvalidParameterValue(msg)
return self._validate_driver_mode(supported_driver_modes[0])
def create_share(self, context, share, share_server=None):
"""Is called to create share."""
raise NotImplementedError()

View File

@ -114,6 +114,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
self.db = db
self.configuration.append_config_values(share_opts)
self.configuration.append_config_values(service_instance.server_opts)
self.mode = self.get_driver_mode([const.MULTI_SVM_MODE, ])
self._helpers = {}
self.backend_name = self.configuration.safe_get(
'share_backend_name') or "Cinder_Volumes"

View File

@ -15,6 +15,7 @@
import mock
from manila.common import constants
from manila.openstack.common import log as logging
from manila.share import driver
@ -28,6 +29,7 @@ class FakeShareDriver(driver.ShareDriver):
super(FakeShareDriver, self).__init__(execute=self.fake_execute,
*args, **kwargs)
self.db = mock.Mock()
self.mode = constants.MULTI_SVM_MODE
def share_network_update(*args, **kwargs):
pass

View File

@ -878,6 +878,34 @@ class GenericShareDriverTestCase(test.TestCase):
)
self.assertEqual(ssh_output, result)
@mock.patch.object(
generic.service_instance, 'ServiceInstanceManager', mock.Mock())
def test_driver_mode_valid_value(self):
mode = const.MULTI_SVM_MODE
CONF.set_override('share_driver_mode', mode)
driver = generic.GenericShareDriver(
self._db, execute=self._execute, configuration=self.fake_conf)
self.assertEqual(mode, driver.mode)
generic.service_instance.ServiceInstanceManager.\
assert_called_once_with(self._db, driver_config=self.fake_conf)
def test_driver_mode_invalid_value(self):
mode = const.SINGLE_SVM_MODE
CONF.set_override('share_driver_mode', mode)
self.assertRaises(
exception.InvalidParameterValue,
generic.GenericShareDriver,
self._db,
execute=self._execute,
configuration=self.fake_conf)
def test_driver_mode_default_share_driver_modes(self):
mode = const.MULTI_SVM_MODE
self.assertEqual(mode, self._driver.mode)
class NFSHelperTestCase(test.TestCase):
"""Test case for NFS helper of generic driver."""

View File

@ -19,6 +19,7 @@ import time
import mock
from manila.common import constants
from manila import exception
from manila import network
from manila.share import configuration
@ -35,6 +36,10 @@ def fake_sleep(duration):
pass
class ShareDriverWithExecuteMixin(driver.ShareDriver, driver.ExecuteMixin):
pass
class ShareDriverTestCase(test.TestCase):
def setUp(self):
@ -45,7 +50,7 @@ class ShareDriverTestCase(test.TestCase):
self.stubs.Set(self.time, 'sleep', fake_sleep)
def test__try_execute(self):
execute_mixin = driver.ExecuteMixin(
execute_mixin = ShareDriverWithExecuteMixin(
configuration=configuration.Configuration(None))
self.assertRaises(exception.ProcessExecutionError,
execute_mixin._try_execute)
@ -67,6 +72,8 @@ class ShareDriverTestCase(test.TestCase):
else:
network.API.assert_called_once_with(
config_group_name=config.config_group)
self.assertTrue(hasattr(share_driver, 'mode'))
return share_driver
def test_instantiate_share_driver(self):
self._instantiate_share_driver(None)
@ -81,3 +88,79 @@ class ShareDriverTestCase(test.TestCase):
self.assertEqual(None, share_driver.configuration)
network.API.assert_called_once_with(config_group_name=None)
def test_get_driver_mode_empty_list(self):
share_driver = self._instantiate_share_driver(None)
self.assertRaises(
exception.InvalidParameterValue,
share_driver.get_driver_mode, [])
def test_get_driver_mode_one_value_in_list_mode_is_not_set(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = None
mode = share_driver.get_driver_mode([constants.SINGLE_SVM_MODE, ])
self.assertEqual(constants.SINGLE_SVM_MODE, mode)
def test_get_driver_mode_one_value_in_list_mode_is_set_and_equal(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = constants.SINGLE_SVM_MODE
mode = share_driver.get_driver_mode([constants.SINGLE_SVM_MODE, ])
self.assertEqual(constants.SINGLE_SVM_MODE, mode)
def test_get_driver_mode_one_value_in_list_mode_is_set_and_not_equal(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = constants.SINGLE_SVM_MODE
self.assertRaises(
exception.InvalidParameterValue,
share_driver.get_driver_mode,
[constants.MULTI_SVM_MODE, ])
def test_get_driver_mode_two_values_in_list_mode_is_not_set(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = None
self.assertRaises(
exception.InvalidParameterValue,
share_driver.get_driver_mode,
[constants.SINGLE_SVM_MODE, constants.MULTI_SVM_MODE])
def test_get_driver_mode_two_values_in_list_mode_is_set(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = constants.MULTI_SVM_MODE
mode = share_driver.get_driver_mode(
[constants.SINGLE_SVM_MODE, constants.MULTI_SVM_MODE, ])
self.assertEqual(constants.MULTI_SVM_MODE, mode)
def test_get_driver_mode_one_invalid_value_in_list_mode_is_not_set(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = None
self.assertRaises(
exception.InvalidParameterValue,
share_driver.get_driver_mode,
['fake', ])
def test_get_driver_mode_one_valid_value_in_list_mode_is_invalid(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = 'fake'
self.assertRaises(
exception.InvalidParameterValue,
share_driver.get_driver_mode,
[constants.MULTI_SVM_MODE, ])
def test_get_driver_mode_two_values_in_list_invalid_mode_set(self):
share_driver = self._instantiate_share_driver(None)
share_driver.mode = 'fake'
self.assertRaises(
exception.InvalidParameterValue,
share_driver.get_driver_mode,
[constants.SINGLE_SVM_MODE, constants.MULTI_SVM_MODE, ])