Skip to content

Commit

Permalink
Add driver mode interface
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vponomaryov committed Dec 18, 2014
1 parent 7b588c8 commit 28f311c
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 5 deletions.
8 changes: 8 additions & 0 deletions manila/common/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@

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,
)
62 changes: 58 additions & 4 deletions manila/share/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
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
Expand Down Expand Up @@ -51,6 +53,13 @@
"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 = [
Expand All @@ -76,11 +85,8 @@
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))

Expand Down Expand Up @@ -115,10 +121,58 @@ def __init__(self, *args, **kwargs):
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()
Expand Down
1 change: 1 addition & 0 deletions manila/share/drivers/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ def __init__(self, db, *args, **kwargs):
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"
Expand Down
2 changes: 2 additions & 0 deletions manila/tests/fake_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import mock

from manila.common import constants
from manila.openstack.common import log as logging
from manila.share import driver

Expand All @@ -28,6 +29,7 @@ def __init__(self, *args, **kwargs):
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
Expand Down
28 changes: 28 additions & 0 deletions manila/tests/share/drivers/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,34 @@ def test_ssh_exec_connection_recreation(self):
)
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."""
Expand Down
85 changes: 84 additions & 1 deletion manila/tests/share/test_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import mock

from manila.common import constants
from manila import exception
from manila import network
from manila.share import configuration
Expand All @@ -35,6 +36,10 @@ def fake_sleep(duration):
pass


class ShareDriverWithExecuteMixin(driver.ShareDriver, driver.ExecuteMixin):
pass


class ShareDriverTestCase(test.TestCase):

def setUp(self):
Expand All @@ -45,7 +50,7 @@ def setUp(self):
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)
Expand All @@ -67,6 +72,8 @@ def _instantiate_share_driver(self, network_config_group):
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)
Expand All @@ -81,3 +88,79 @@ def test_instantiate_share_driver_no_configuration(self):

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, ])

0 comments on commit 28f311c

Please sign in to comment.