glusterfs*: amend export location
The basic problem is that determining the export location of a share should happen in driver scope (as it depends on available export mechanims, which are implemented by the driver) while the code did it in layout scope in ad-hoc ways. Also in native driver the export location was abused to store the address of the backing GlusterFS resource. Fix these by - layout: - GlusterfsShareDriverBase._setup_via_manager (the layer -> driver reverse callback) will provide the export location as return value - the share object is also passed to GlusterfsShareDriverBase._setup_via_manager (besides the gluster manager), because some driver configs will need it to specify the export location - glusterfs-native: - free the code from using export location (apart from composing it in _setup_via_manager); store the address of backing resource in private storage instead of the export location field - glusterfs: - define the `get_export` method for the export helpers that provide the export location - _setup_via_manager determines export location by calling the helper's get_export Change-Id: Id02e4908a3e8e435c4c51ecacb6576785ac8afb6 Closes-Bug: #1476774 Closes-Bug: #1493080
This commit is contained in:
parent
24125c9884
commit
bd146a841d
|
@ -25,6 +25,7 @@ TODO(rraja): support SMB protocol.
|
|||
"""
|
||||
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
|
@ -91,7 +92,8 @@ class GlusterfsShareDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||
self._get_helper()
|
||||
super(GlusterfsShareDriver, self).do_setup(context)
|
||||
|
||||
def _setup_via_manager(self, gluster_manager, gluster_manager_parent=None):
|
||||
def _setup_via_manager(self, share_manager, share_manager_parent=None):
|
||||
gluster_manager = share_manager['manager']
|
||||
# exporting the whole volume must be prohibited
|
||||
# to not to defeat access control
|
||||
args = ('volume', 'set', gluster_manager.volume, NFS_EXPORT_VOL,
|
||||
|
@ -103,6 +105,9 @@ class GlusterfsShareDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||
"exporting the entire volume: %s"), exc.stderr)
|
||||
raise exception.GlusterfsException("gluster %s failed" %
|
||||
' '.join(args))
|
||||
return self.nfs_helper(self._execute, self.configuration,
|
||||
gluster_manager=gluster_manager).get_export(
|
||||
share_manager['share'])
|
||||
|
||||
def check_for_setup_error(self):
|
||||
pass
|
||||
|
@ -146,6 +151,9 @@ class GlusterNFSHelper(ganesha.NASHelperBase):
|
|||
super(GlusterNFSHelper, self).__init__(execute, config_object,
|
||||
**kwargs)
|
||||
|
||||
def get_export(self, share):
|
||||
return self.gluster_manager.export
|
||||
|
||||
def _get_export_dir_dict(self):
|
||||
"""Get the export entries of shares in the GlusterFS volume."""
|
||||
export_dir = self.gluster_manager.get_gluster_vol_option(
|
||||
|
@ -252,13 +260,16 @@ class GaneshaNFSHelper(ganesha.GaneshaNASHelper):
|
|||
privatekey=config_object.glusterfs_path_to_private_key)
|
||||
else:
|
||||
execute = ganesha_utils.RootExecutor(execute)
|
||||
ganesha_host = config_object.glusterfs_ganesha_server_ip
|
||||
if not ganesha_host:
|
||||
ganesha_host = 'localhost'
|
||||
kwargs['tag'] = '-'.join(('GLUSTER', 'Ganesha', ganesha_host))
|
||||
self.ganesha_host = config_object.glusterfs_ganesha_server_ip
|
||||
if not self.ganesha_host:
|
||||
self.ganesha_host = socket.gethostname()
|
||||
kwargs['tag'] = '-'.join(('GLUSTER', 'Ganesha', self.ganesha_host))
|
||||
super(GaneshaNFSHelper, self).__init__(execute, config_object,
|
||||
**kwargs)
|
||||
|
||||
def get_export(self, share):
|
||||
return ':/'.join((self.ganesha_host, share['name']))
|
||||
|
||||
def init_helper(self):
|
||||
@utils.synchronized(self.tag)
|
||||
def _init_helper():
|
||||
|
|
|
@ -65,7 +65,7 @@ class GlusterfsShareDriverBase(driver.ShareDriver):
|
|||
|
||||
self.layout = importutils.import_object(
|
||||
'.'.join((self.LAYOUT_PREFIX, layout_name)),
|
||||
self, configuration=self.configuration)
|
||||
self, **kwargs)
|
||||
# we determine snapshot support in our own scope, as
|
||||
# 1) the calculation based on parent method
|
||||
# redefinition does not work for us, as actual
|
||||
|
@ -78,17 +78,21 @@ class GlusterfsShareDriverBase(driver.ShareDriver):
|
|||
'_snapshots_are_supported',
|
||||
False)
|
||||
|
||||
def _setup_via_manager(self, gluster_mgr, gluster_mgr_parent=None):
|
||||
def _setup_via_manager(self, share_mgr, share_mgr_parent=None):
|
||||
"""Callback for layout's `create_share` and `create_share_from_snapshot`
|
||||
|
||||
:param gluster_mgr: GlusterManager instance
|
||||
representing the GlusterFS resource that backs
|
||||
the share created in `create_share` or
|
||||
`create_share_from_snapshot`.
|
||||
:param gluster_mgr_parent: GlusterManager instance
|
||||
:param share_mgr: a {'share': <share>, 'manager': <gmgr>}
|
||||
dict where <share> is the share created
|
||||
in `create_share` or `create_share_from_snapshot`
|
||||
and <gmgr> is a GlusterManager instance
|
||||
representing the GlusterFS resource
|
||||
that backs the share the snapshot of which
|
||||
was used in `create_share_from_snapshot`.
|
||||
allocated for it.
|
||||
:param gluster_mgr_parent: a {'share': <share>, 'manager': <gmgr>}
|
||||
dict where <share> is the original share of the snapshot
|
||||
used in `create_share_from_snapshot` and <gmgr> is a
|
||||
GlusterManager instance representing the GlusterFS
|
||||
resource allocated for it.
|
||||
:returns: export location for share_mgr['share'].
|
||||
"""
|
||||
|
||||
def allow_access(self, context, share, access, share_server=None):
|
||||
|
|
|
@ -161,8 +161,12 @@ class GlusterfsDirectoryMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
LOG.error(_LE('Unable to create share %s'), share['name'])
|
||||
raise exception.GlusterfsException(exc)
|
||||
|
||||
export_location = os.path.join(self.gluster_manager.qualified,
|
||||
share['name'])
|
||||
comp_share = self.gluster_manager.components.copy()
|
||||
comp_share['path'] = '/' + share['name']
|
||||
export_location = self.driver._setup_via_manager(
|
||||
{'share': share,
|
||||
'manager': self._glustermanager(comp_share)})
|
||||
|
||||
return export_location
|
||||
|
||||
def _cleanup_create_share(self, share_path, share_name):
|
||||
|
|
|
@ -106,6 +106,7 @@ class GlusterfsVolumeMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
# format check for srvaddr
|
||||
self._glustermanager(srvaddr, False)
|
||||
self.glusterfs_versions = {}
|
||||
self.private_storage = kwargs.get('private_storage')
|
||||
|
||||
def _compile_volume_pattern(self):
|
||||
"""Compile a RegexObject from the config specified regex template.
|
||||
|
@ -191,7 +192,8 @@ class GlusterfsVolumeMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
|
||||
def _share_manager(self, share):
|
||||
"""Return GlusterManager object representing share's backend."""
|
||||
return self._glustermanager(share['export_location'])
|
||||
return self._glustermanager(self.private_storage.get(
|
||||
share['id'], 'volume'))
|
||||
|
||||
def _fetch_gluster_volumes(self):
|
||||
"""Do a 'gluster volume list | grep <volume pattern>'.
|
||||
|
@ -325,7 +327,6 @@ class GlusterfsVolumeMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
# Within a host's volumes, choose alphabetically first,
|
||||
# to make it predictable.
|
||||
vol = sorted(chosen_hostmap[chosen_host])[0]
|
||||
self.driver._setup_via_manager(self._glustermanager(vol))
|
||||
self.gluster_used_vols.add(vol)
|
||||
return vol
|
||||
|
||||
|
@ -389,20 +390,24 @@ class GlusterfsVolumeMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
GlusterFS volume for use as a share.
|
||||
"""
|
||||
try:
|
||||
export_location = self._pop_gluster_vol(share['size'])
|
||||
vol = self._pop_gluster_vol(share['size'])
|
||||
except exception.GlusterfsException:
|
||||
msg = (_LE("Error creating share %(share_id)s"),
|
||||
{'share_id': share['id']})
|
||||
LOG.error(msg)
|
||||
raise
|
||||
|
||||
export = self.driver._setup_via_manager(
|
||||
{'share': share, 'manager': self._glustermanager(vol)})
|
||||
self.private_storage.update(share['id'], {'volume': vol})
|
||||
|
||||
# TODO(deepakcs): Enable quota and set it to the share size.
|
||||
|
||||
# For native protocol, the export_location should be of the form:
|
||||
# server:/volname
|
||||
LOG.info(_LI("export_location sent back from create_share: %s"),
|
||||
(export_location,))
|
||||
return export_location
|
||||
export)
|
||||
return export
|
||||
|
||||
def delete_share(self, context, share, share_server=None):
|
||||
"""Delete a share on the GlusterFS volume.
|
||||
|
@ -420,6 +425,7 @@ class GlusterfsVolumeMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
LOG.error(msg)
|
||||
raise
|
||||
|
||||
self.private_storage.delete(share['id'])
|
||||
# TODO(deepakcs): Disable quota.
|
||||
|
||||
@staticmethod
|
||||
|
@ -484,9 +490,12 @@ class GlusterfsVolumeMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
comp_vol = old_gmgr.components.copy()
|
||||
comp_vol.update({'volume': volume})
|
||||
gmgr = self._glustermanager(comp_vol)
|
||||
self.driver._setup_via_manager(gmgr, old_gmgr)
|
||||
export = self.driver._setup_via_manager(
|
||||
{'share': share, 'manager': gmgr},
|
||||
{'share': snapshot['share_instance'], 'manager': old_gmgr})
|
||||
self.gluster_used_vols.add(gmgr.qualified)
|
||||
return gmgr.qualified
|
||||
self.private_storage.update(share['id'], {'volume': gmgr.qualified})
|
||||
return export
|
||||
|
||||
def create_snapshot(self, context, snapshot, share_server=None):
|
||||
"""Creates a snapshot."""
|
||||
|
|
|
@ -72,9 +72,12 @@ class GlusterfsNativeShareDriver(driver.ExecuteMixin,
|
|||
self.backend_name = self.configuration.safe_get(
|
||||
'share_backend_name') or 'GlusterFS-Native'
|
||||
|
||||
def _setup_via_manager(self, gluster_mgr, gluster_mgr_parent=None):
|
||||
def _setup_via_manager(self, share_mgr, share_mgr_parent=None):
|
||||
# Enable gluster volumes for SSL access only.
|
||||
|
||||
gluster_mgr = share_mgr['manager']
|
||||
gluster_mgr_parent = (share_mgr_parent or {}).get('manager', None)
|
||||
|
||||
ssl_allow_opt = (gluster_mgr_parent if gluster_mgr_parent else
|
||||
gluster_mgr).get_gluster_vol_option(
|
||||
AUTH_SSL_ALLOW)
|
||||
|
@ -136,6 +139,8 @@ class GlusterfsNativeShareDriver(driver.ExecuteMixin,
|
|||
LOG.error(msg)
|
||||
raise exception.GlusterfsException(msg)
|
||||
|
||||
return gluster_mgr.export
|
||||
|
||||
@utils.synchronized("glusterfs_native_access", external=False)
|
||||
def _allow_access_via_manager(self, gluster_mgr, context, share, access,
|
||||
share_server=None):
|
||||
|
|
|
@ -232,20 +232,32 @@ class GlusterfsDirectoryMappedLayoutTestCase(test.TestCase):
|
|||
self.assertRaises(exception.GlusterfsException,
|
||||
self._layout._update_share_stats)
|
||||
|
||||
def test_create_share(self):
|
||||
@ddt.data((), (None,))
|
||||
def test_create_share(self, extra_args):
|
||||
exec_cmd1 = 'mkdir %s' % fake_local_share_path
|
||||
expected_exec = [exec_cmd1, ]
|
||||
expected_ret = 'testuser@127.0.0.1:/testvol/fakename'
|
||||
self.mock_object(
|
||||
self._layout, '_get_local_share_path',
|
||||
mock.Mock(return_value=fake_local_share_path))
|
||||
gmgr = mock.Mock()
|
||||
self.mock_object(
|
||||
self._layout, '_glustermanager', mock.Mock(return_value=gmgr))
|
||||
self.mock_object(
|
||||
self._layout.driver, '_setup_via_manager',
|
||||
mock.Mock(return_value=expected_ret))
|
||||
|
||||
ret = self._layout.create_share(self._context, self.share)
|
||||
ret = self._layout.create_share(self._context, self.share, *extra_args)
|
||||
|
||||
self._layout._get_local_share_path.called_once_with(self.share)
|
||||
self._layout.gluster_manager.gluster_call.assert_called_once_with(
|
||||
'volume', 'quota', 'testvol', 'limit-usage', '/fakename', '1GB')
|
||||
self.assertEqual(expected_exec, fake_utils.fake_execute_get_log())
|
||||
self._layout._glustermanager.assert_called_once_with(
|
||||
{'user': 'testuser', 'host': '127.0.0.1',
|
||||
'volume': 'testvol', 'path': '/fakename'})
|
||||
self._layout.driver._setup_via_manager.assert_called_once_with(
|
||||
{'share': self.share, 'manager': gmgr})
|
||||
self.assertEqual(expected_ret, ret)
|
||||
|
||||
def test_create_share_unable_to_create_share(self):
|
||||
|
@ -271,21 +283,6 @@ class GlusterfsDirectoryMappedLayoutTestCase(test.TestCase):
|
|||
layout_directory.LOG.error.assert_called_once_with(
|
||||
mock.ANY, mock.ANY)
|
||||
|
||||
def test_create_share_can_be_called_with_extra_arg_share_server(self):
|
||||
self._layout._get_local_share_path = mock.Mock()
|
||||
with mock.patch.object(os.path, 'join', return_value=None):
|
||||
|
||||
share_server = None
|
||||
ret = self._layout.create_share(self._context, self.share,
|
||||
share_server)
|
||||
|
||||
self.assertIsNone(ret)
|
||||
self._layout._get_local_share_path.called_once_with(self.share)
|
||||
self._layout._get_local_share_path.assert_called_once_with(
|
||||
self.share)
|
||||
os.path.join.assert_called_once_with(
|
||||
self._layout.gluster_manager.qualified, self.share['name'])
|
||||
|
||||
def test_cleanup_create_share_local_share_path_exists(self):
|
||||
expected_exec = ['rm -rf %s' % fake_local_share_path]
|
||||
self.mock_object(os.path, 'exists', mock.Mock(return_value=True))
|
||||
|
|
|
@ -114,11 +114,14 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
mock.Mock(return_value='/tmp/tmpKGHKJ'))
|
||||
self.mock_object(common.GlusterManager, 'make_gluster_call')
|
||||
|
||||
self.fake_private_storage = mock.Mock()
|
||||
|
||||
with mock.patch.object(layout_volume.GlusterfsVolumeMappedLayout,
|
||||
'_glustermanager',
|
||||
side_effect=[self.gmgr1, self.gmgr2]):
|
||||
self._layout = layout_volume.GlusterfsVolumeMappedLayout(
|
||||
self.fake_driver, configuration=self.fake_conf)
|
||||
self.fake_driver, configuration=self.fake_conf,
|
||||
private_storage=self.fake_private_storage)
|
||||
self._layout.glusterfs_versions = {self.glusterfs_server1: ('3', '6'),
|
||||
self.glusterfs_server2: ('3', '7')}
|
||||
self.addCleanup(fake_utils.fake_execute_set_repliers, [])
|
||||
|
@ -275,12 +278,15 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
def test_share_manager(self):
|
||||
self.mock_object(self._layout, '_glustermanager',
|
||||
mock.Mock(return_value=self.gmgr1))
|
||||
self.mock_object(self._layout.private_storage,
|
||||
'get', mock.Mock(return_value='host1:/gv1'))
|
||||
|
||||
ret = self._layout._share_manager(self.share1)
|
||||
|
||||
self._layout.private_storage.get.assert_called_once_with(
|
||||
self.share1['id'], 'volume')
|
||||
self._layout._glustermanager.assert_called_once_with('host1:/gv1')
|
||||
self.assertEqual(self.gmgr1, ret)
|
||||
self._layout._glustermanager.assert_called_once_with(
|
||||
self.share1['export_location'])
|
||||
|
||||
def test_ensure_share(self):
|
||||
share = self.share1
|
||||
|
@ -329,11 +335,7 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self.assertEqual(expected, result)
|
||||
self.assertIn(result, used_vols)
|
||||
self._layout._fetch_gluster_volumes.assert_called_once_with()
|
||||
self.assertEqual(
|
||||
[mock.call(result), mock.call(result)],
|
||||
self._layout._glustermanager.call_args_list
|
||||
)
|
||||
self.fake_driver._setup_via_manager.assert_called_once_with(gmgr1)
|
||||
self._layout._glustermanager.assert_called_once_with(result)
|
||||
|
||||
@ddt.data({"voldict": {"share2G": {"size": 2}},
|
||||
"used_vols": set(), "size": 3},
|
||||
|
@ -471,12 +473,20 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
def test_create_share(self):
|
||||
self._layout._pop_gluster_vol = mock.Mock(
|
||||
return_value=self.glusterfs_target1)
|
||||
self.mock_object(self._layout, '_glustermanager',
|
||||
mock.Mock(return_value=self.gmgr1))
|
||||
self.mock_object(self.fake_driver, '_setup_via_manager',
|
||||
mock.Mock(return_value='host1:/gv1'))
|
||||
|
||||
share = new_share()
|
||||
exp_locn = self._layout.create_share(self._context, share)
|
||||
|
||||
self.assertEqual(exp_locn, self.glusterfs_target1)
|
||||
self._layout._pop_gluster_vol.assert_called_once_with(share['size'])
|
||||
self.fake_driver._setup_via_manager.assert_called_once_with(
|
||||
{'manager': self.gmgr1, 'share': share})
|
||||
self._layout.private_storage.update.assert_called_once_with(
|
||||
share['id'], {'volume': self.glusterfs_target1})
|
||||
self.assertEqual('host1:/gv1', exp_locn)
|
||||
|
||||
def test_create_share_error(self):
|
||||
self._layout._pop_gluster_vol = mock.Mock(
|
||||
|
@ -503,6 +513,8 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self._layout._wipe_gluster_vol.assert_called_once_with(gmgr1)
|
||||
self._layout._push_gluster_vol.assert_called_once_with(
|
||||
self.glusterfs_target1)
|
||||
self._layout.private_storage.delete.assert_called_once_with(
|
||||
self.share1['id'])
|
||||
|
||||
def test_delete_share_error(self):
|
||||
self._layout._wipe_gluster_vol = mock.Mock()
|
||||
|
@ -612,10 +624,14 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
@ddt.unpack
|
||||
def test_create_snapshot_no_snap_cached(self, vers_minor, exctype):
|
||||
self._layout.gluster_nosnap_vols_dict = {
|
||||
self.share1['export_location']: 'fake error'}
|
||||
self.glusterfs_target1: 'fake error'}
|
||||
self._layout.glusterfs_versions = {
|
||||
self.glusterfs_server1: ('3', vers_minor)}
|
||||
self._layout.gluster_used_vols = set([self.glusterfs_target1])
|
||||
gmgr = common.GlusterManager
|
||||
gmgr1 = gmgr(self.glusterfs_target1, self._execute, None, None)
|
||||
self.mock_object(self._layout, '_share_manager',
|
||||
mock.Mock(return_value=gmgr1))
|
||||
|
||||
snapshot = {
|
||||
'id': 'fake_snap_id',
|
||||
|
@ -690,10 +706,10 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
'share_instance': new_share(export_location=glusterfs_target)
|
||||
}
|
||||
volume = ''.join(['manila-', share['id']])
|
||||
new_export_location = ':/'.join([glusterfs_server, volume])
|
||||
new_vol_addr = ':/'.join([glusterfs_server, volume])
|
||||
gmgr = common.GlusterManager
|
||||
old_gmgr = gmgr(glusterfs_target, self._execute, None, None)
|
||||
new_gmgr = gmgr(new_export_location, self._execute, None, None)
|
||||
new_gmgr = gmgr(new_vol_addr, self._execute, None, None)
|
||||
self._layout.gluster_used_vols = set([glusterfs_target])
|
||||
self._layout.glusterfs_versions = {glusterfs_server: ('3', '7')}
|
||||
self.mock_object(old_gmgr, 'gluster_call',
|
||||
|
@ -710,6 +726,8 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
mock.Mock(return_value=old_gmgr))
|
||||
self.mock_object(self._layout, '_glustermanager',
|
||||
mock.Mock(return_value=new_gmgr))
|
||||
self.mock_object(self.fake_driver, '_setup_via_manager',
|
||||
mock.Mock(return_value='host1:/gv1'))
|
||||
|
||||
ret = self._layout.create_share_from_snapshot(
|
||||
self._context, share, snapshot, None)
|
||||
|
@ -723,23 +741,26 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self._layout._share_manager.assert_called_once_with(
|
||||
snapshot['share_instance'])
|
||||
self._layout._glustermanager.assert_called_once_with(
|
||||
gmgr.parse(new_export_location))
|
||||
gmgr.parse(new_vol_addr))
|
||||
self._layout.driver._setup_via_manager.assert_called_once_with(
|
||||
new_gmgr, old_gmgr)
|
||||
{'manager': new_gmgr, 'share': share},
|
||||
{'manager': old_gmgr, 'share': snapshot['share_instance']})
|
||||
self._layout.private_storage.update.assert_called_once_with(
|
||||
share['id'], {'volume': new_vol_addr})
|
||||
self.assertIn(
|
||||
new_export_location,
|
||||
new_vol_addr,
|
||||
self._layout.gluster_used_vols)
|
||||
self.assertEqual(new_export_location, ret)
|
||||
self.assertEqual('host1:/gv1', ret)
|
||||
|
||||
def test_create_share_from_snapshot_error_old_gmr_gluster_calls(self):
|
||||
glusterfs_target = 'root@host1:/gv1'
|
||||
glusterfs_server = 'root@host1'
|
||||
share = new_share()
|
||||
volume = ''.join(['manila-', share['id']])
|
||||
new_export_location = ':/'.join([glusterfs_server, volume])
|
||||
new_vol_addr = ':/'.join([glusterfs_server, volume])
|
||||
gmgr = common.GlusterManager
|
||||
old_gmgr = gmgr(glusterfs_target, self._execute, None, None)
|
||||
new_gmgr = gmgr(new_export_location, self._execute, None, None)
|
||||
new_gmgr = gmgr(new_vol_addr, self._execute, None, None)
|
||||
self._layout.gluster_used_vols_dict = {glusterfs_target: old_gmgr}
|
||||
self._layout.glusterfs_versions = {glusterfs_server: ('3', '7')}
|
||||
self.mock_object(
|
||||
|
@ -776,7 +797,7 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
snapshot['share_instance'])
|
||||
self.assertFalse(new_gmgr.get_gluster_vol_option.called)
|
||||
self.assertFalse(new_gmgr.gluster_call.called)
|
||||
self.assertNotIn(new_export_location,
|
||||
self.assertNotIn(new_vol_addr,
|
||||
self._layout.glusterfs_versions.keys())
|
||||
|
||||
def test_create_share_from_snapshot_error_unsupported_gluster_version(
|
||||
|
@ -785,10 +806,10 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
glusterfs_server = 'root@host1'
|
||||
share = new_share()
|
||||
volume = ''.join(['manila-', share['id']])
|
||||
new_export_location = ':/'.join([glusterfs_server, volume])
|
||||
new_vol_addr = ':/'.join([glusterfs_server, volume])
|
||||
gmgr = common.GlusterManager
|
||||
old_gmgr = gmgr(glusterfs_target, self._execute, None, None)
|
||||
new_gmgr = gmgr(new_export_location, self._execute, None, None)
|
||||
new_gmgr = gmgr(new_vol_addr, self._execute, None, None)
|
||||
self._layout.gluster_used_vols_dict = {glusterfs_target: old_gmgr}
|
||||
self._layout.glusterfs_versions = {glusterfs_server: ('3', '6')}
|
||||
self.mock_object(
|
||||
|
@ -824,7 +845,7 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self.assertFalse(self._layout._glustermanager.called)
|
||||
self.assertFalse(new_gmgr.get_gluster_vol_option.called)
|
||||
self.assertFalse(new_gmgr.gluster_call.called)
|
||||
self.assertNotIn(new_export_location,
|
||||
self.assertNotIn(new_vol_addr,
|
||||
self._layout.glusterfs_versions.keys())
|
||||
|
||||
def test_delete_snapshot(self):
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
import copy
|
||||
import socket
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
|
@ -85,13 +86,21 @@ class GlusterfsShareDriverTestCase(test.TestCase):
|
|||
def test_setup_via_manager(self, has_parent):
|
||||
gmgr = mock.Mock()
|
||||
gmgr.gluster_call = mock.Mock()
|
||||
gmgr_parent = mock.Mock() if has_parent else None
|
||||
share_mgr_parent = mock.Mock() if has_parent else None
|
||||
nfs_helper = mock.Mock()
|
||||
nfs_helper.get_export = mock.Mock(return_value='host:/vol')
|
||||
self._driver.nfs_helper = mock.Mock(return_value=nfs_helper)
|
||||
|
||||
self._driver._setup_via_manager(
|
||||
gmgr, gluster_manager_parent=gmgr_parent)
|
||||
ret = self._driver._setup_via_manager(
|
||||
{'manager': gmgr, 'share': self.share},
|
||||
share_manager_parent=share_mgr_parent)
|
||||
|
||||
gmgr.gluster_call.assert_called_once_with(
|
||||
'volume', 'set', gmgr.volume, 'nfs.export-volumes', 'off')
|
||||
self._driver.nfs_helper.assert_called_once_with(
|
||||
self._execute, self.fake_conf, gluster_manager=gmgr)
|
||||
nfs_helper.get_export.assert_called_once_with(self.share)
|
||||
self.assertEqual('host:/vol', ret)
|
||||
|
||||
@ddt.data(exception.ProcessExecutionError, RuntimeError)
|
||||
def test_setup_via_manager_exception(self, _exception):
|
||||
|
@ -102,7 +111,8 @@ class GlusterfsShareDriverTestCase(test.TestCase):
|
|||
self.assertRaises(
|
||||
{exception.ProcessExecutionError:
|
||||
exception.GlusterfsException}.get(
|
||||
_exception, _exception), self._driver._setup_via_manager, gmgr)
|
||||
_exception, _exception), self._driver._setup_via_manager,
|
||||
{'manager': gmgr, 'share': self.share})
|
||||
|
||||
def test_check_for_setup_error(self):
|
||||
self._driver.check_for_setup_error()
|
||||
|
@ -160,6 +170,11 @@ class GlusterNFSHelperTestCase(test.TestCase):
|
|||
self._helper = glusterfs.GlusterNFSHelper(
|
||||
self._execute, self.fake_conf, gluster_manager=gluster_manager)
|
||||
|
||||
def test_get_export(self):
|
||||
ret = self._helper.get_export(mock.Mock())
|
||||
|
||||
self.assertEqual(fake_gluster_manager_attrs['export'], ret)
|
||||
|
||||
def test_get_export_dir_dict(self):
|
||||
output_str = '/foo(10.0.0.1|10.0.0.2),/bar(10.0.0.1)'
|
||||
self.mock_object(self._helper.gluster_manager,
|
||||
|
@ -359,6 +374,7 @@ class GaneshaNFSHelperTestCase(test.TestCase):
|
|||
mock.Mock(return_value=self._root_execute))
|
||||
self.mock_object(glusterfs.ganesha.GaneshaNASHelper, '__init__',
|
||||
mock.Mock())
|
||||
socket.gethostname = mock.Mock(return_value='example.com')
|
||||
self._helper = glusterfs.GaneshaNFSHelper(
|
||||
self._execute, self.fake_conf,
|
||||
gluster_manager=self.gluster_manager)
|
||||
|
@ -367,9 +383,15 @@ class GaneshaNFSHelperTestCase(test.TestCase):
|
|||
def test_init_local_ganesha_server(self):
|
||||
glusterfs.ganesha_utils.RootExecutor.assert_called_once_with(
|
||||
self._execute)
|
||||
socket.gethostname.assert_has_calls([mock.call()])
|
||||
glusterfs.ganesha.GaneshaNASHelper.__init__.assert_has_calls(
|
||||
[mock.call(self._root_execute, self.fake_conf,
|
||||
tag='GLUSTER-Ganesha-localhost')])
|
||||
tag='GLUSTER-Ganesha-example.com')])
|
||||
|
||||
def test_get_export(self):
|
||||
ret = self._helper.get_export(self.share)
|
||||
|
||||
self.assertEqual('example.com:/fakename', ret)
|
||||
|
||||
def test_init_remote_ganesha_server(self):
|
||||
ssh_execute = mock.Mock(return_value=('', ''))
|
||||
|
|
|
@ -102,10 +102,13 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
gmgr = mock.Mock()
|
||||
gmgr.gluster_call = mock.Mock()
|
||||
gmgr.volume = 'fakevol'
|
||||
gmgr.export = 'fakehost:/fakevol'
|
||||
gmgr.get_gluster_vol_option = mock.Mock(
|
||||
return_value='glusterfs-server-name,some-other-name')
|
||||
share = mock.Mock()
|
||||
|
||||
self._driver._setup_via_manager(gmgr)
|
||||
ret = self._driver._setup_via_manager({'manager': gmgr,
|
||||
'share': share})
|
||||
|
||||
gmgr.get_gluster_vol_option.assert_called_once_with('auth.ssl-allow')
|
||||
args = (
|
||||
|
@ -115,16 +118,22 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
('volume', 'stop', 'fakevol', '--mode=script'),
|
||||
('volume', 'start', 'fakevol'))
|
||||
gmgr.gluster_call.assert_has_calls([mock.call(*a) for a in args])
|
||||
self.assertEqual(ret, gmgr.export)
|
||||
|
||||
def test_setup_via_manager_with_parent(self):
|
||||
gmgr = mock.Mock()
|
||||
gmgr.gluster_call = mock.Mock()
|
||||
gmgr.volume = 'fakevol'
|
||||
gmgr.export = 'fakehost:/fakevol'
|
||||
gmgr_parent = mock.Mock()
|
||||
gmgr_parent.get_gluster_vol_option = mock.Mock(
|
||||
return_value='glusterfs-server-name,some-other-name')
|
||||
share = mock.Mock()
|
||||
share_parent = mock.Mock()
|
||||
|
||||
self._driver._setup_via_manager(gmgr, gmgr_parent)
|
||||
ret = self._driver._setup_via_manager(
|
||||
{'manager': gmgr, 'share': share},
|
||||
{'manager': gmgr_parent, 'share': share_parent})
|
||||
|
||||
gmgr_parent.get_gluster_vol_option.assert_called_once_with(
|
||||
'auth.ssl-allow')
|
||||
|
@ -136,27 +145,33 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
('volume', 'set', 'fakevol', 'server.ssl', 'on'),
|
||||
('volume', 'start', 'fakevol'))
|
||||
gmgr.gluster_call.assert_has_calls([mock.call(*a) for a in args])
|
||||
self.assertEqual(ret, gmgr.export)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_setup_via_manager_no_option_data(self, has_parent):
|
||||
share = mock.Mock()
|
||||
gmgr = mock.Mock()
|
||||
if has_parent:
|
||||
share_parent = mock.Mock()
|
||||
gmgr_parent = mock.Mock()
|
||||
share_mgr_parent = {'share': share_parent, 'manager': gmgr_parent}
|
||||
gmgr_queried = gmgr_parent
|
||||
else:
|
||||
gmgr_parent = None
|
||||
share_mgr_parent = None
|
||||
gmgr_queried = gmgr
|
||||
gmgr_queried.get_gluster_vol_option = mock.Mock(return_value='')
|
||||
|
||||
self.assertRaises(exception.GlusterfsException,
|
||||
self._driver._setup_via_manager,
|
||||
gmgr, gluster_mgr_parent=gmgr_parent)
|
||||
{'share': share, 'manager': gmgr},
|
||||
share_mgr_parent=share_mgr_parent)
|
||||
|
||||
gmgr_queried.get_gluster_vol_option.assert_called_once_with(
|
||||
'auth.ssl-allow')
|
||||
|
||||
@ddt.data(exception.ProcessExecutionError, RuntimeError)
|
||||
def test_setup_via_manager_exception(self, _exception):
|
||||
share = mock.Mock()
|
||||
gmgr = mock.Mock()
|
||||
gmgr.gluster_call = mock.Mock(side_effect=_exception)
|
||||
gmgr.get_gluster_vol_option = mock.Mock()
|
||||
|
@ -164,7 +179,8 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
self.assertRaises(
|
||||
{exception.ProcessExecutionError:
|
||||
exception.GlusterfsException}.get(
|
||||
_exception, _exception), self._driver._setup_via_manager, gmgr)
|
||||
_exception, _exception), self._driver._setup_via_manager,
|
||||
{'share': share, 'manager': gmgr})
|
||||
|
||||
def test_snapshots_are_supported(self):
|
||||
self.assertTrue(self._driver.snapshots_are_supported)
|
||||
|
|
Loading…
Reference in New Issue