glusterfs vol layout: start volume cloned from snapshot
When handling create_share_from_snapshot with glusterfs
volume layout, we do a snapshot clone gluster operation
that gives us a new volume (which will be used to back
the new share). 'snapshot clone' does not start the
resultant volume, we have explicitly start it from Manila.
So far the volume layout code did not bother about it,
rather the 'vol start' was called from glusterfs-native
driver. That however broke all other volume layout based
configs (ie. glusterfs driver with vol layout).
Fix this now by doing the 'vol start' call in the vol
layout code.
Change-Id: I63c13ce468a3227f09e381814f55e8c914fbef95
Closes-Bug: #1499347
(cherry picked from commit 4e4c8759a2
)
This commit is contained in:
parent
552a80a5bf
commit
be76d9e404
|
@ -485,6 +485,17 @@ class GlusterfsVolumeMappedLayout(layout.GlusterfsShareLayoutBase):
|
|||
export = self.driver._setup_via_manager(
|
||||
{'share': share, 'manager': gmgr},
|
||||
{'share': snapshot['share_instance'], 'manager': old_gmgr})
|
||||
|
||||
try:
|
||||
gmgr.gluster_call(
|
||||
'volume', 'start', gmgr.volume)
|
||||
except exception.ProcessExecutionError as exc:
|
||||
msg = (_("Error starting gluster volume. "
|
||||
"Volume: %(volname)s, Error: %(error)s") %
|
||||
{'volname': gmgr.volume, 'error': exc.stderr})
|
||||
LOG.error(msg)
|
||||
raise exception.GlusterfsException(msg)
|
||||
|
||||
self.gluster_used_vols.add(gmgr.qualified)
|
||||
self.private_storage.update(share['id'], {'volume': gmgr.qualified})
|
||||
return export
|
||||
|
|
|
@ -126,12 +126,6 @@ class GlusterfsNativeShareDriver(driver.ExecuteMixin,
|
|||
):
|
||||
gluster_actions.append(('set', option, value))
|
||||
|
||||
if not gluster_mgr_parent:
|
||||
# TODO(deepakcs) Remove this once ssl options can be
|
||||
# set dynamically.
|
||||
gluster_actions.append(('stop', '--mode=script'))
|
||||
gluster_actions.append(('start',))
|
||||
|
||||
for action in gluster_actions:
|
||||
try:
|
||||
gluster_mgr.gluster_call(
|
||||
|
@ -145,6 +139,11 @@ class GlusterfsNativeShareDriver(driver.ExecuteMixin,
|
|||
LOG.error(msg)
|
||||
raise exception.GlusterfsException(msg)
|
||||
|
||||
if not gluster_mgr_parent:
|
||||
# TODO(deepakcs) Remove this once ssl options can be
|
||||
# set dynamically.
|
||||
common._restart_gluster_vol(gluster_mgr)
|
||||
|
||||
return gluster_mgr.export
|
||||
|
||||
@utils.synchronized("glusterfs_native_access", external=False)
|
||||
|
|
|
@ -715,7 +715,7 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self.mock_object(old_gmgr, 'gluster_call',
|
||||
mock.Mock(side_effect=[('', ''), ('', '')]))
|
||||
self.mock_object(new_gmgr, 'gluster_call',
|
||||
mock.Mock(side_effect=[('', ''), ('', '')]))
|
||||
mock.Mock(side_effect=[('', '')]))
|
||||
self.mock_object(new_gmgr, 'get_gluster_vol_option',
|
||||
mock.Mock())
|
||||
new_gmgr.get_gluster_vol_option.return_value = (
|
||||
|
@ -738,6 +738,8 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
'force', '--mode=script'),
|
||||
('snapshot', 'clone', volume, 'fake_snap_id_xyz'))
|
||||
old_gmgr.gluster_call.assert_has_calls([mock.call(*a) for a in args])
|
||||
args = (('volume', 'start', volume),)
|
||||
new_gmgr.gluster_call.assert_has_calls([mock.call(*a) for a in args])
|
||||
self._layout._share_manager.assert_called_once_with(
|
||||
snapshot['share_instance'])
|
||||
self._layout._glustermanager.assert_called_once_with(
|
||||
|
@ -752,7 +754,69 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self._layout.gluster_used_vols)
|
||||
self.assertEqual('host1:/gv1', ret)
|
||||
|
||||
def test_create_share_from_snapshot_error_old_gmr_gluster_calls(self):
|
||||
@ddt.data({'trouble': exception.ProcessExecutionError,
|
||||
'_exception': exception.GlusterfsException},
|
||||
{'trouble': RuntimeError, '_exception': RuntimeError})
|
||||
@ddt.unpack
|
||||
def test_create_share_from_snapshot_error_new_gmr_gluster_calls(
|
||||
self, trouble, _exception):
|
||||
glusterfs_target = 'root@host1:/gv1'
|
||||
glusterfs_server = 'root@host1'
|
||||
share = new_share()
|
||||
volume = ''.join(['manila-', share['id']])
|
||||
new_vol_addr = ':/'.join([glusterfs_server, volume])
|
||||
gmgr = common.GlusterManager
|
||||
old_gmgr = gmgr(glusterfs_target, 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',
|
||||
mock.Mock(side_effect=[('', ''), ('', '')]))
|
||||
self.mock_object(new_gmgr, 'gluster_call',
|
||||
mock.Mock(side_effect=trouble))
|
||||
self.mock_object(new_gmgr, 'get_gluster_vol_option',
|
||||
mock.Mock())
|
||||
new_gmgr.get_gluster_vol_option.return_value = (
|
||||
'glusterfs-server-1,client')
|
||||
self.mock_object(self._layout, '_find_actual_backend_snapshot_name',
|
||||
mock.Mock(return_value='fake_snap_id_xyz'))
|
||||
self.mock_object(self._layout, '_share_manager',
|
||||
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'))
|
||||
|
||||
snapshot = {
|
||||
'id': 'fake_snap_id',
|
||||
'share_instance': new_share(export_location=glusterfs_target)
|
||||
}
|
||||
self.assertRaises(_exception,
|
||||
self._layout.create_share_from_snapshot,
|
||||
self._context, share, snapshot)
|
||||
|
||||
(self._layout._find_actual_backend_snapshot_name.
|
||||
assert_called_once_with(old_gmgr, snapshot))
|
||||
args = (('snapshot', 'activate', 'fake_snap_id_xyz',
|
||||
'force', '--mode=script'),
|
||||
('snapshot', 'clone', volume, 'fake_snap_id_xyz'))
|
||||
old_gmgr.gluster_call.assert_has_calls([mock.call(*a) for a in args])
|
||||
args = (('volume', 'start', volume),)
|
||||
new_gmgr.gluster_call.assert_has_calls([mock.call(*a) for a in args])
|
||||
self._layout._share_manager.assert_called_once_with(
|
||||
snapshot['share_instance'])
|
||||
self._layout._glustermanager.assert_called_once_with(
|
||||
gmgr.parse(new_vol_addr))
|
||||
self._layout.driver._setup_via_manager.assert_called_once_with(
|
||||
{'manager': new_gmgr, 'share': share},
|
||||
{'manager': old_gmgr, 'share': snapshot['share_instance']})
|
||||
|
||||
@ddt.data({'trouble': exception.ProcessExecutionError,
|
||||
'_exception': exception.GlusterfsException},
|
||||
{'trouble': RuntimeError, '_exception': RuntimeError})
|
||||
@ddt.unpack
|
||||
def test_create_share_from_snapshot_error_old_gmr_gluster_calls(
|
||||
self, trouble, _exception):
|
||||
glusterfs_target = 'root@host1:/gv1'
|
||||
glusterfs_server = 'root@host1'
|
||||
share = new_share()
|
||||
|
@ -765,9 +829,7 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self._layout.glusterfs_versions = {glusterfs_server: ('3', '7')}
|
||||
self.mock_object(
|
||||
old_gmgr, 'gluster_call',
|
||||
mock.Mock(side_effect=[('', ''), exception.ProcessExecutionError]))
|
||||
self.mock_object(new_gmgr, 'gluster_call',
|
||||
mock.Mock(side_effect=[('', ''), ('', '')]))
|
||||
mock.Mock(side_effect=[('', ''), trouble]))
|
||||
self.mock_object(new_gmgr, 'get_gluster_vol_option',
|
||||
mock.Mock())
|
||||
new_gmgr.get_gluster_vol_option.return_value = (
|
||||
|
@ -783,7 +845,7 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
'id': 'fake_snap_id',
|
||||
'share_instance': new_share(export_location=glusterfs_target)
|
||||
}
|
||||
self.assertRaises(exception.GlusterfsException,
|
||||
self.assertRaises(_exception,
|
||||
self._layout.create_share_from_snapshot,
|
||||
self._context, share, snapshot)
|
||||
|
||||
|
@ -815,9 +877,6 @@ class GlusterfsVolumeMappedLayoutTestCase(test.TestCase):
|
|||
self.mock_object(
|
||||
old_gmgr, 'gluster_call',
|
||||
mock.Mock(side_effect=[('', ''), ('', '')]))
|
||||
self.mock_object(
|
||||
new_gmgr, 'gluster_call',
|
||||
mock.Mock(side_effect=[('', ''), exception.ProcessExecutionError]))
|
||||
self.mock_object(new_gmgr, 'get_gluster_vol_option',
|
||||
mock.Mock())
|
||||
new_gmgr.get_gluster_vol_option.return_value = (
|
||||
|
|
|
@ -143,8 +143,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
'glusterfs-server-name,manila-host.com'),
|
||||
('volume', 'set', 'fakevol', 'nfs.export-volumes', 'off'),
|
||||
('volume', 'set', 'fakevol', 'client.ssl', 'on'),
|
||||
('volume', 'set', 'fakevol', 'server.ssl', 'on'),
|
||||
('volume', 'start', 'fakevol'))
|
||||
('volume', 'set', 'fakevol', 'server.ssl', 'on'))
|
||||
gmgr.gluster_call.assert_has_calls([mock.call(*a) for a in args])
|
||||
self.assertEqual(ret, gmgr.export)
|
||||
|
||||
|
@ -187,7 +186,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
self.assertTrue(self._driver.snapshots_are_supported)
|
||||
|
||||
def test_allow_access_via_manager(self):
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
access = {'access_type': 'cert', 'access_to': 'client.example.com'}
|
||||
gmgr1 = common.GlusterManager(self.glusterfs_target1, self._execute,
|
||||
None, None)
|
||||
|
@ -205,7 +204,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
common._restart_gluster_vol.assert_called_once_with(gmgr1)
|
||||
|
||||
def test_allow_access_via_manager_with_share_having_access(self):
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
access = {'access_type': 'cert', 'access_to': 'client.example.com'}
|
||||
gmgr1 = common.GlusterManager(self.glusterfs_target1, self._execute,
|
||||
None, None)
|
||||
|
@ -222,7 +221,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
self.assertFalse(common._restart_gluster_vol.called)
|
||||
|
||||
def test_allow_access_via_manager_invalid_access_type(self):
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
access = {'access_type': 'invalid', 'access_to': 'client.example.com'}
|
||||
expected_exec = []
|
||||
|
||||
|
@ -242,7 +241,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
if (args == test_args):
|
||||
raise exception.ProcessExecutionError()
|
||||
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
gmgr1 = common.GlusterManager(self.glusterfs_target1, self._execute,
|
||||
None, None)
|
||||
self.mock_object(gmgr1, 'get_gluster_vol_option',
|
||||
|
@ -260,7 +259,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
self.assertFalse(common._restart_gluster_vol.called)
|
||||
|
||||
def test_deny_access_via_manager(self):
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
access = {'access_type': 'cert', 'access_to': 'client.example.com'}
|
||||
gmgr1 = common.GlusterManager(self.glusterfs_target1, self._execute,
|
||||
None, None)
|
||||
|
@ -279,7 +278,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
common._restart_gluster_vol.assert_called_once_with(gmgr1)
|
||||
|
||||
def test_deny_access_via_manager_with_share_having_no_access(self):
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
access = {'access_type': 'cert', 'access_to': 'client.example.com'}
|
||||
gmgr1 = common.GlusterManager(self.glusterfs_target1, self._execute,
|
||||
None, None)
|
||||
|
@ -295,7 +294,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
self.assertFalse(common._restart_gluster_vol.called)
|
||||
|
||||
def test_deny_access_via_manager_invalid_access_type(self):
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
|
||||
access = {'access_type': 'invalid', 'access_to': 'NotApplicable'}
|
||||
self.assertRaises(exception.InvalidShareAccess,
|
||||
|
@ -313,7 +312,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||
if (args == test_args):
|
||||
raise exception.ProcessExecutionError()
|
||||
|
||||
common._restart_gluster_vol = mock.Mock()
|
||||
self.mock_object(common, '_restart_gluster_vol', mock.Mock())
|
||||
gmgr1 = common.GlusterManager(self.glusterfs_target1, self._execute,
|
||||
None, None)
|
||||
self.mock_object(
|
||||
|
|
Loading…
Reference in New Issue