Add driver mode attr definition for all drivers

Driver mode functionality was implemented to be able to specify how
driver should work and filter backends scheduling share creation based on this.
Add to all drivers update of attr 'mode' based on its current behavior.

Set 'share_driver_mode' extra spec to volume/share type with one of available
values. Scheduler will use it for host filtering.

Implements blueprint driver-modes-for-scheduler

Change-Id: Ida644f630ee07c51c02aea5d6280980b5d704c2f
This commit is contained in:
Ponomaryov Valeriy 2014-12-28 21:17:33 +02:00 committed by Valeriy Ponomaryov
parent 0dd28ab401
commit a9c25274ab
18 changed files with 109 additions and 2 deletions

View File

@ -318,6 +318,7 @@ class ShareDriver(object):
# each driver may define these values in its own config options # each driver may define these values in its own config options
# or fetch from driver specific configuration file. # or fetch from driver specific configuration file.
data["share_backend_name"] = backend_name or 'Generic_NFS' data["share_backend_name"] = backend_name or 'Generic_NFS'
data["share_driver_mode"] = self.mode
data["vendor_name"] = 'Open Source' data["vendor_name"] = 'Open Source'
data["driver_version"] = '1.0' data["driver_version"] = '1.0'
data["storage_protocol"] = None data["storage_protocol"] = None

View File

@ -125,6 +125,7 @@ class EMCShareDriver(driver.ShareDriver):
backend_name = self.configuration.safe_get('emc_share_backend') backend_name = self.configuration.safe_get('emc_share_backend')
self.plugin = self.plugin_manager.load_plugin(backend_name, LOG) self.plugin = self.plugin_manager.load_plugin(backend_name, LOG)
self.mode = self.get_driver_mode(self.plugin.supported_driver_modes)
self.plugin.connect(self, context) self.plugin.connect(self, context)
@ -136,6 +137,7 @@ class EMCShareDriver(driver.ShareDriver):
backend_name = self.configuration.safe_get( backend_name = self.configuration.safe_get(
'share_backend_name') or "EMC_NAS_Storage" 'share_backend_name') or "EMC_NAS_Storage"
data["share_backend_name"] = backend_name data["share_backend_name"] = backend_name
data["share_driver_mode"] = self.mode
data["vendor_name"] = 'EMC' data["vendor_name"] = 'EMC'
data["driver_version"] = '1.0' data["driver_version"] = '1.0'
data["storage_protocol"] = 'NFS_CIFS' data["storage_protocol"] = 'NFS_CIFS'

View File

@ -25,6 +25,8 @@ class StorageConnection(object):
def __init__(self, logger): def __init__(self, logger):
self.logger = logger self.logger = logger
# NOTE(vponomaryov): redefine 'supported_driver_modes' within plugin.
self.supported_driver_modes = None
@abc.abstractmethod @abc.abstractmethod
def create_share(self, emc_share_driver, context, share, share_server): def create_share(self, emc_share_driver, context, share, share_server):

View File

@ -17,6 +17,7 @@ from oslo.utils import excutils
from oslo.utils import units from oslo.utils import units
import six import six
from manila.common import constants as const
from manila import db as manila_db from manila import db as manila_db
from manila import exception from manila import exception
from manila.i18n import _ from manila.i18n import _
@ -47,6 +48,7 @@ class VNXStorageConnection(driver.StorageConnection):
self._pool_name = None self._pool_name = None
self._pool = None self._pool = None
self._filesystems = {} self._filesystems = {}
self.supported_driver_modes = const.MULTI_SVM_MODE
def create_share(self, emc_share_driver, context, share, def create_share(self, emc_share_driver, context, share,
share_server=None): share_server=None):

View File

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

View File

@ -32,6 +32,7 @@ import xml.etree.cElementTree as etree
from oslo.config import cfg from oslo.config import cfg
import six import six
from manila.common import constants as const
from manila import exception from manila import exception
from manila.i18n import _ from manila.i18n import _
from manila.i18n import _LE from manila.i18n import _LE
@ -99,6 +100,7 @@ class GlusterfsShareDriver(driver.ExecuteMixin, driver.ShareDriver):
self.configuration.append_config_values(GlusterfsManilaShare_opts) self.configuration.append_config_values(GlusterfsManilaShare_opts)
self.backend_name = self.configuration.safe_get( self.backend_name = self.configuration.safe_get(
'share_backend_name') or 'GlusterFS' 'share_backend_name') or 'GlusterFS'
self.mode = self.get_driver_mode(const.SINGLE_SVM_MODE)
def do_setup(self, context): def do_setup(self, context):
"""Native mount the GlusterFS volume and tune it.""" """Native mount the GlusterFS volume and tune it."""
@ -267,6 +269,7 @@ class GlusterfsShareDriver(driver.ExecuteMixin, driver.ShareDriver):
data = {} data = {}
data["share_backend_name"] = self.backend_name data["share_backend_name"] = self.backend_name
data["share_driver_mode"] = self.mode
data["vendor_name"] = 'Red Hat' data["vendor_name"] = 'Red Hat'
data["driver_version"] = '1.0' data["driver_version"] = '1.0'
data["storage_protocol"] = 'NFS' data["storage_protocol"] = 'NFS'

View File

@ -33,6 +33,7 @@ import tempfile
from oslo.config import cfg from oslo.config import cfg
import six import six
from manila.common import constants as const
from manila import exception from manila import exception
from manila.i18n import _ from manila.i18n import _
from manila.i18n import _LI from manila.i18n import _LI
@ -84,6 +85,7 @@ class GlusterfsNativeShareDriver(driver.ExecuteMixin, driver.ShareDriver):
glusterfs_native_manila_share_opts) glusterfs_native_manila_share_opts)
self.backend_name = self.configuration.safe_get( self.backend_name = self.configuration.safe_get(
'share_backend_name') or 'GlusterFS-Native' 'share_backend_name') or 'GlusterFS-Native'
self.mode = self.get_driver_mode(const.SINGLE_SVM_MODE)
def do_setup(self, context): def do_setup(self, context):
"""Setup the GlusterFS volumes.""" """Setup the GlusterFS volumes."""
@ -505,6 +507,7 @@ class GlusterfsNativeShareDriver(driver.ExecuteMixin, driver.ShareDriver):
data = {} data = {}
data["share_backend_name"] = self.backend_name data["share_backend_name"] = self.backend_name
data["share_driver_mode"] = self.mode
data["vendor_name"] = 'Red Hat' data["vendor_name"] = 'Red Hat'
data["driver_version"] = '1.1' data["driver_version"] = '1.1'
data["storage_protocol"] = 'glusterfs' data["storage_protocol"] = 'glusterfs'

View File

@ -43,6 +43,7 @@ from oslo.utils import units
from oslo_concurrency import processutils from oslo_concurrency import processutils
import six import six
from manila.common import constants as const
from manila import exception from manila import exception
from manila.i18n import _, _LE, _LI from manila.i18n import _, _LE, _LI
from manila.openstack.common import log as logging from manila.openstack.common import log as logging
@ -129,6 +130,7 @@ class GPFSShareDriver(driver.ExecuteMixin, driver.GaneshaMixin,
self.configuration.append_config_values(gpfs_share_opts) self.configuration.append_config_values(gpfs_share_opts)
self.backend_name = self.configuration.safe_get( self.backend_name = self.configuration.safe_get(
'share_backend_name') or "IBM Storage System" 'share_backend_name') or "IBM Storage System"
self.mode = self.get_driver_mode(const.SINGLE_SVM_MODE)
self.sshpool = None self.sshpool = None
self.ssh_connections = {} self.ssh_connections = {}
self._gpfs_execute = None self._gpfs_execute = None
@ -501,6 +503,7 @@ class GPFSShareDriver(driver.ExecuteMixin, driver.GaneshaMixin,
data = {} data = {}
data["share_backend_name"] = self.backend_name data["share_backend_name"] = self.backend_name
data["share_driver_mode"] = self.mode
data["vendor_name"] = 'IBM' data["vendor_name"] = 'IBM'
data["driver_version"] = '1.0' data["driver_version"] = '1.0'
data["storage_protocol"] = 'NFS' data["storage_protocol"] = 'NFS'

View File

@ -28,6 +28,7 @@ from oslo.utils import excutils
from oslo.utils import units from oslo.utils import units
import six import six
from manila.common import constants as const
from manila import context from manila import context
from manila import exception from manila import exception
from manila.i18n import _ from manila.i18n import _
@ -144,6 +145,7 @@ class NetAppClusteredShareDriver(driver.ShareDriver):
self.api_version = (1, 15) self.api_version = (1, 15)
self.backend_name = self.configuration.safe_get( self.backend_name = self.configuration.safe_get(
'share_backend_name') or "NetApp_Cluster_Mode" 'share_backend_name') or "NetApp_Cluster_Mode"
self.mode = self.get_driver_mode(const.MULTI_SVM_MODE)
def do_setup(self, context): def do_setup(self, context):
"""Prepare once the driver. """Prepare once the driver.
@ -194,6 +196,7 @@ class NetAppClusteredShareDriver(driver.ShareDriver):
LOG.debug("Updating share stats") LOG.debug("Updating share stats")
data = {} data = {}
data["share_backend_name"] = self.backend_name data["share_backend_name"] = self.backend_name
data["share_driver_mode"] = self.mode
data["vendor_name"] = 'NetApp' data["vendor_name"] = 'NetApp'
data["driver_version"] = '1.0' data["driver_version"] = '1.0'
data["storage_protocol"] = 'NFS_CIFS' data["storage_protocol"] = 'NFS_CIFS'

View File

@ -20,6 +20,7 @@ import base64
from oslo.config import cfg from oslo.config import cfg
from oslo.utils import units from oslo.utils import units
from manila.common import constants as const
from manila import exception from manila import exception
from manila.i18n import _ from manila.i18n import _
from manila.i18n import _LE from manila.i18n import _LE
@ -121,6 +122,7 @@ class ZFSSAShareDriver(driver.ShareDriver):
'quota_snap': self.configuration.zfssa_nas_quota_snap, 'quota_snap': self.configuration.zfssa_nas_quota_snap,
'reservation_snap': self.configuration.zfssa_nas_quota_snap, 'reservation_snap': self.configuration.zfssa_nas_quota_snap,
} }
self.mode = self.get_driver_mode(const.SINGLE_SVM_MODE)
def do_setup(self, context): def do_setup(self, context):
"""Login, create project, no sharing option enabled.""" """Login, create project, no sharing option enabled."""
@ -305,6 +307,7 @@ class ZFSSAShareDriver(driver.ShareDriver):
data = {} data = {}
backend_name = self.configuration.safe_get('share_backend_name') backend_name = self.configuration.safe_get('share_backend_name')
data["share_backend_name"] = backend_name or self.__class__.__name__ data["share_backend_name"] = backend_name or self.__class__.__name__
data["share_driver_mode"] = self.mode
data["vendor_name"] = 'Oracle' data["vendor_name"] = 'Oracle'
data["driver_version"] = self.VERSION data["driver_version"] = self.VERSION
data["storage_protocol"] = self.PROTOCOL data["storage_protocol"] = self.PROTOCOL

View File

@ -16,6 +16,7 @@
import mock import mock
from stevedore import extension from stevedore import extension
from manila.common import constants as const
from manila.openstack.common import log as logging from manila.openstack.common import log as logging
from manila.share import configuration as conf from manila.share import configuration as conf
from manila.share.drivers.emc import driver as emcdriver from manila.share.drivers.emc import driver as emcdriver
@ -28,6 +29,7 @@ LOG = logging.getLogger(__name__)
class FakeConnection(base.StorageConnection): class FakeConnection(base.StorageConnection):
def __init__(self, logger): def __init__(self, logger):
self.logger = logger self.logger = logger
self.supported_driver_modes = const.MULTI_SVM_MODE
def create_share(self, emc_share_driver, context, share, share_server): def create_share(self, emc_share_driver, context, share, share_server):
"""Is called to create share.""" """Is called to create share."""
@ -123,6 +125,7 @@ class EMCShareFrameworkTestCase(test.TestCase):
self.driver.plugin = mock.Mock() self.driver.plugin = mock.Mock()
self.driver._update_share_stats() self.driver._update_share_stats()
data["share_backend_name"] = FAKE_BACKEND data["share_backend_name"] = FAKE_BACKEND
data["share_driver_mode"] = self.driver.mode
data["vendor_name"] = 'EMC' data["vendor_name"] = 'EMC'
data["driver_version"] = '1.0' data["driver_version"] = '1.0'
data["storage_protocol"] = 'NFS_CIFS' data["storage_protocol"] = 'NFS_CIFS'

View File

@ -128,6 +128,28 @@ class GPFSShareDriverTestCase(test.TestCase):
['127.0.0.1', self.local_ip]) ['127.0.0.1', self.local_ip])
)) ))
def test_get_share_stats_refresh_false(self):
self._driver._stats = {'fake_key': 'fake_value'}
result = self._driver.get_share_stats(False)
self.assertEqual(self._driver._stats, result)
def test_get_share_stats_refresh_true(self):
self.stubs.Set(
self._driver, '_get_available_capacity',
mock.Mock(return_value=(11111.0, 12345.0)))
result = self._driver.get_share_stats(True)
expected_keys = [
'QoS_support', 'driver_version', 'share_backend_name',
'free_capacity_gb', 'share_driver_mode', 'total_capacity_gb',
'reserved_percentage', 'vendor_name', 'storage_protocol',
]
for key in expected_keys:
self.assertIn(key, result)
self.assertEqual(self._driver.mode, result['share_driver_mode'])
self.assertEqual('IBM', result['vendor_name'])
self._driver._get_available_capacity.assert_called_once_with(
self._driver.configuration.gpfs_mount_point_base)
def test_do_setup(self): def test_do_setup(self):
self.stubs.Set(self._driver, '_setup_helpers', mock.Mock()) self.stubs.Set(self._driver, '_setup_helpers', mock.Mock())
self._driver.do_setup(self._context) self._driver.do_setup(self._context)

View File

@ -140,6 +140,7 @@ class NetAppClusteredDrvTestCase(test.TestCase):
expected = {} expected = {}
expected["share_backend_name"] = self.driver.backend_name expected["share_backend_name"] = self.driver.backend_name
expected["share_driver_mode"] = self.driver.mode
expected["vendor_name"] = 'NetApp' expected["vendor_name"] = 'NetApp'
expected["driver_version"] = '1.0' expected["driver_version"] = '1.0'
expected["storage_protocol"] = 'NFS_CIFS' expected["storage_protocol"] = 'NFS_CIFS'
@ -147,7 +148,7 @@ class NetAppClusteredDrvTestCase(test.TestCase):
expected['free_capacity_gb'] = 3 expected['free_capacity_gb'] = 3
expected['reserved_percentage'] = 0 expected['reserved_percentage'] = 0
expected['QoS_support'] = False expected['QoS_support'] = False
self.assertDictMatch(res, expected) self.assertDictMatch(expected, res)
def test_setup_server(self): def test_setup_server(self):
self.driver._vserver_create_if_not_exists = mock.Mock( self.driver._vserver_create_if_not_exists = mock.Mock(

View File

@ -932,6 +932,30 @@ class GenericShareDriverTestCase(test.TestCase):
) )
self.assertEqual(ssh_output, result) self.assertEqual(ssh_output, result)
def test_get_share_stats_refresh_false(self):
self._driver._stats = {'fake_key': 'fake_value'}
result = self._driver.get_share_stats(False)
self.assertEqual(self._driver._stats, result)
def test_get_share_stats_refresh_true(self):
fake_stats = {'fake_key': 'fake_value'}
self._driver._stats = fake_stats
expected_keys = [
'QoS_support', 'driver_version', 'share_backend_name',
'free_capacity_gb', 'share_driver_mode', 'total_capacity_gb',
'reserved_percentage', 'vendor_name', 'storage_protocol',
]
result = self._driver.get_share_stats(True)
self.assertNotEqual(fake_stats, result)
for key in expected_keys:
self.assertIn(key, result)
self.assertEqual(self._driver.mode, result['share_driver_mode'])
self.assertEqual('Open Source', result['vendor_name'])
@mock.patch.object( @mock.patch.object(
generic.service_instance, 'ServiceInstanceManager', mock.Mock()) generic.service_instance, 'ServiceInstanceManager', mock.Mock())
def test_driver_mode_valid_value(self): def test_driver_mode_valid_value(self):

View File

@ -447,6 +447,7 @@ class GlusterfsShareDriverTestCase(test.TestCase):
def test_update_share_stats(self): def test_update_share_stats(self):
test_data = { test_data = {
'share_backend_name': 'GlusterFS', 'share_backend_name': 'GlusterFS',
'share_driver_mode': self._driver.mode,
'vendor_name': 'Red Hat', 'vendor_name': 'Red Hat',
'driver_version': '1.0', 'driver_version': '1.0',
'storage_protocol': 'NFS', 'storage_protocol': 'NFS',

View File

@ -792,6 +792,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
def test_update_share_stats(self): def test_update_share_stats(self):
test_data = { test_data = {
'share_backend_name': 'GlusterFS-Native', 'share_backend_name': 'GlusterFS-Native',
'share_driver_mode': self._driver.mode,
'vendor_name': 'Red Hat', 'vendor_name': 'Red Hat',
'driver_version': '1.1', 'driver_version': '1.1',
'storage_protocol': 'glusterfs', 'storage_protocol': 'glusterfs',

View File

@ -17,6 +17,7 @@ Unit tests for Oracle's ZFSSA Manila driver.
import mock import mock
from oslo.config import cfg from oslo.config import cfg
from manila.common import constants as const
from manila import context from manila import context
from manila import exception from manila import exception
from manila.share import configuration as conf from manila.share import configuration as conf
@ -70,7 +71,11 @@ class ZFSSAShareDriverTestCase(test.TestCase):
self._driver.do_setup(self._context) self._driver.do_setup(self._context)
def _create_fake_config(self): def _create_fake_config(self):
def _safe_get(opt):
return getattr(self.configuration, opt)
self.configuration = mock.Mock(spec=conf.Configuration) self.configuration = mock.Mock(spec=conf.Configuration)
self.configuration.safe_get = mock.Mock(side_effect=_safe_get)
self.configuration.zfssa_host = '1.1.1.1' self.configuration.zfssa_host = '1.1.1.1'
self.configuration.zfssa_data_ip = '1.1.1.1' self.configuration.zfssa_data_ip = '1.1.1.1'
self.configuration.zfssa_auth_user = 'user' self.configuration.zfssa_auth_user = 'user'
@ -86,6 +91,7 @@ class ZFSSAShareDriverTestCase(test.TestCase):
self.configuration.zfssa_nas_quota_snap = 'true' self.configuration.zfssa_nas_quota_snap = 'true'
self.configuration.zfssa_rest_timeout = 60 self.configuration.zfssa_rest_timeout = 60
self.configuration.network_config_group = 'fake_network_config_group' self.configuration.network_config_group = 'fake_network_config_group'
self.configuration.share_driver_mode = const.SINGLE_SVM_MODE
def test_create_share(self): def test_create_share(self):
self.stubs.Set(self._driver.zfssa, 'create_share', mock.Mock()) self.stubs.Set(self._driver.zfssa, 'create_share', mock.Mock())

View File

@ -111,6 +111,32 @@ class ShareDriverTestCase(test.TestCase):
self.assertEqual(None, share_driver.configuration) self.assertEqual(None, share_driver.configuration)
network.API.assert_called_once_with(config_group_name=None) network.API.assert_called_once_with(config_group_name=None)
def test_get_share_stats_refresh_false(self):
share_driver = driver.ShareDriver(configuration=None)
share_driver._stats = {'fake_key': 'fake_value'}
result = share_driver.get_share_stats(False)
self.assertEqual(share_driver._stats, result)
def test_get_share_stats_refresh_true(self):
conf = configuration.Configuration(None)
expected_keys = [
'QoS_support', 'driver_version', 'share_backend_name',
'free_capacity_gb', 'share_driver_mode', 'total_capacity_gb',
'reserved_percentage', 'vendor_name', 'storage_protocol',
]
share_driver = driver.ShareDriver(configuration=conf)
fake_stats = {'fake_key': 'fake_value'}
share_driver._stats = fake_stats
result = share_driver.get_share_stats(True)
self.assertNotEqual(fake_stats, result)
for key in expected_keys:
self.assertIn(key, result)
self.assertEqual('Open Source', result['vendor_name'])
@ddt.data( @ddt.data(
'', 'v1', 'v2', 'fake1', None, '', 'v1', 'v2', 'fake1', None,
[], ['v1'], ['v2'], ['v1', 'v2'], ['fake1'], ['fake1', 'fake2'], [], ['v1'], ['v2'], ['v1', 'v2'], ['fake1'], ['fake1', 'fake2'],