glusterfs_native: fix delete share
With GlusterFS 3.7.x versions, the delete share operation fails when deleting the contents of a GlusterFS volume, a share. This is because two directories are auto-created within a GlusterFS volume when it's started and GlusterFS refuses to unlink their paths. Fix this issue, by not trying to remove the two directory paths, but remove their contents and the rest of the contents of the volume. Change-Id: I1675bbf593bf578301d6899ee3f9860320080956 Closes-Bug: #1473324
This commit is contained in:
parent
8d0c93d3d7
commit
29456c2299
@ -112,6 +112,8 @@ Known Restrictions
|
||||
- Certificate setup (aka trust setup) between instance and storage backend is
|
||||
out of band of Manila.
|
||||
- Support for 'create_share_from_snapshot' is planned for Liberty release.
|
||||
- For Manila to use GlusterFS volumes, the name of the trashcan directory in
|
||||
GlusterFS volumes must not be changed from the default.
|
||||
|
||||
The :mod:`manila.share.drivers.glusterfs_native.GlusterfsNativeShareDriver` Module
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -28,8 +28,9 @@ ip: CommandFilter, ip, root
|
||||
# manila/network/linux/interface.py: 'ovs-vsctl', 'add-port', '%s', '%s'
|
||||
ovs-vsctl: CommandFilter, ovs-vsctl, root
|
||||
|
||||
# manila/share/drivers/glusterfs_native.py: 'find', '%s', '-mindepth', '1', '!', '-path', '%s', '!', '-path', '%s', '-delete'
|
||||
# manila/share/drivers/glusterfs_native.py: 'find', '%s', '-mindepth', '1', '-delete'
|
||||
find_del: RegExpFilter, find, root, find, .*, -mindepth, 1, -delete
|
||||
find: CommandFilter, find, root
|
||||
|
||||
# manila/share/drivers/glusterfs_native.py: 'umount', '%s'
|
||||
umount: CommandFilter, umount, root
|
||||
|
@ -26,7 +26,7 @@ Supports working with multiple glusterfs volumes.
|
||||
"""
|
||||
|
||||
import errno
|
||||
import pipes
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
@ -508,8 +508,28 @@ class GlusterfsNativeShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||
raise
|
||||
|
||||
# Delete only the contents, not the directory.
|
||||
cmd = ['find', pipes.quote(tmpdir), '-mindepth', '1', '-delete']
|
||||
# extracting Gluster server address, i.e.,'[remote_user]@host' from the
|
||||
# GlusterManager object.
|
||||
srvaddr = re.sub(':/' + gluster_mgr.volume + '$', '',
|
||||
gluster_mgr.qualified)
|
||||
|
||||
# Delete the contents of a GlusterFS volume that is temporarily
|
||||
# mounted.
|
||||
# From GlusterFS version 3.7, two directories, '.trashcan' at the root
|
||||
# of the GlusterFS volume and 'internal_op' within the '.trashcan'
|
||||
# directory, are internally created when a GlusterFS volume is started.
|
||||
# GlusterFS does not allow unlink(2) of the two directories. So do not
|
||||
# delete the paths of the two directories, but delete their contents
|
||||
# along with the rest of the contents of the volume.
|
||||
if glusterfs.GlusterManager.numreduct(self.glusterfs_versions[srvaddr]
|
||||
) < (3, 7):
|
||||
cmd = ['find', tmpdir, '-mindepth', '1', '-delete']
|
||||
else:
|
||||
ignored_dirs = map(lambda x: os.path.join(tmpdir, *x),
|
||||
[('.trashcan', ), ('.trashcan', 'internal_op')])
|
||||
cmd = ['find', tmpdir, '-mindepth', '1', '!', '-path',
|
||||
ignored_dirs[0], '!', '-path', ignored_dirs[1], '-delete']
|
||||
|
||||
try:
|
||||
self._execute(*cmd, run_as_root=True)
|
||||
except exception.ProcessExecutionError as exc:
|
||||
|
@ -118,7 +118,8 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
||||
self._driver = glusterfs_native.GlusterfsNativeShareDriver(
|
||||
execute=self._execute,
|
||||
configuration=self.fake_conf)
|
||||
|
||||
self._driver.glusterfs_versions = {self.glusterfs_server1: ('3', '6'),
|
||||
self.glusterfs_server2: ('3', '7')}
|
||||
self.addCleanup(fake_utils.fake_execute_set_repliers, [])
|
||||
self.addCleanup(fake_utils.fake_execute_clear_log)
|
||||
|
||||
@ -470,7 +471,14 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
||||
self.assertRaises(exception.GlusterfsException,
|
||||
self._driver._do_umount, tmpdir)
|
||||
|
||||
def test_wipe_gluster_vol(self):
|
||||
@ddt.data({'vers_minor': '6',
|
||||
'cmd': 'find /tmp/tmpKGHKJ -mindepth 1 -delete'},
|
||||
{'vers_minor': '7',
|
||||
'cmd': 'find /tmp/tmpKGHKJ -mindepth 1 ! -path '
|
||||
'/tmp/tmpKGHKJ/.trashcan ! -path '
|
||||
'/tmp/tmpKGHKJ/.trashcan/internal_op -delete'})
|
||||
@ddt.unpack
|
||||
def test_wipe_gluster_vol(self, vers_minor, cmd):
|
||||
self._driver._restart_gluster_vol = mock.Mock()
|
||||
self._driver._do_mount = mock.Mock()
|
||||
self._driver._do_umount = mock.Mock()
|
||||
@ -483,8 +491,9 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
||||
|
||||
gmgr = glusterfs.GlusterManager
|
||||
gmgr1 = gmgr(self.glusterfs_target1, self._execute, None, None)
|
||||
|
||||
expected_exec = ['find /tmp/tmpKGHKJ -mindepth 1 -delete']
|
||||
self._driver.glusterfs_versions = {
|
||||
self.glusterfs_server1: ('3', vers_minor)}
|
||||
expected_exec = [cmd]
|
||||
|
||||
self._driver._wipe_gluster_vol(gmgr1)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user