diff --git a/charmhelpers/contrib/storage/linux/loopback.py b/charmhelpers/contrib/storage/linux/loopback.py index c296f09..3a3f514 100644 --- a/charmhelpers/contrib/storage/linux/loopback.py +++ b/charmhelpers/contrib/storage/linux/loopback.py @@ -76,3 +76,13 @@ def ensure_loopback_device(path, size): check_call(cmd) return create_loopback(path) + + +def is_mapped_loopback_device(device): + """ + Checks if a given device name is an existing/mapped loopback device. + :param device: str: Full path to the device (eg, /dev/loop1). + :returns: str: Path to the backing file if is a loopback device + empty string otherwise + """ + return loopback_devices().get(device, "") diff --git a/lib/swift_storage_utils.py b/lib/swift_storage_utils.py index be8e407..2daf3e2 100644 --- a/lib/swift_storage_utils.py +++ b/lib/swift_storage_utils.py @@ -27,6 +27,7 @@ from charmhelpers.fetch import ( from charmhelpers.core.host import ( mkdir, mount, + fstab_add, service_restart, lsb_release ) @@ -45,6 +46,10 @@ from charmhelpers.contrib.storage.linux.utils import ( is_device_mounted, ) +from charmhelpers.contrib.storage.linux.loopback import ( + is_mapped_loopback_device, +) + from charmhelpers.contrib.openstack.utils import ( configure_installation_source, get_os_codename_install_source, @@ -253,8 +258,20 @@ def setup_storage(): _dev = os.path.basename(dev) _mp = os.path.join('/srv', 'node', _dev) mkdir(_mp, owner='swift', group='swift') - mount(dev, '/srv/node/%s' % _dev, persist=True, - filesystem="xfs") + + options = None + loopback_device = is_mapped_loopback_device(dev) + + if loopback_device: + dev = loopback_device + options = "loop, defaults" + + mountpoint = '/srv/node/%s' % _dev + filesystem = "xfs" + + mount(dev, mountpoint, filesystem=filesystem) + fstab_add(dev, mountpoint, filesystem, options=options) + check_call(['chown', '-R', 'swift:swift', '/srv/node/']) check_call(['chmod', '-R', '0755', '/srv/node/']) diff --git a/unit_tests/test_swift_storage_utils.py b/unit_tests/test_swift_storage_utils.py index 6eaea1e..a00cd89 100644 --- a/unit_tests/test_swift_storage_utils.py +++ b/unit_tests/test_swift_storage_utils.py @@ -28,6 +28,9 @@ TO_PATCH = [ '_save_script_rc', 'lsb_release', 'is_paused', + 'fstab_add', + 'mount', + 'is_mapped_loopback_device', ] @@ -218,6 +221,7 @@ class SwiftStorageUtilsTests(CharmTestCase): @patch.object(swift_utils, 'mkfs_xfs') @patch.object(swift_utils, 'determine_block_devices') def test_setup_storage_overwrite(self, determine, mkfs, clean): + self.is_mapped_loopback_device.return_value = None determine.return_value = ['/dev/vdb'] self.test_config.set('overwrite', 'True') swift_utils.setup_storage() @@ -225,7 +229,10 @@ class SwiftStorageUtilsTests(CharmTestCase): self.mkdir.assert_called_with('/srv/node/vdb', owner='swift', group='swift') self.mount.assert_called_with('/dev/vdb', '/srv/node/vdb', - filesystem='xfs', persist=True) + filesystem='xfs') + self.fstab_add.assert_called_with('/dev/vdb', '/srv/node/vdb', + 'xfs', + options=None) calls = [call(['chown', '-R', 'swift:swift', '/srv/node/']), call(['chmod', '-R', '0755', '/srv/node/'])] self.check_call.assert_has_calls(calls) @@ -338,3 +345,21 @@ class SwiftStorageUtilsTests(CharmTestCase): swift_utils.OBJECT_SVCS) for service in services: self.assertIn(call(service), self.service_restart.call_args_list) + + @patch.object(swift_utils, "mkfs_xfs") + @patch.object(swift_utils, "determine_block_devices") + def test_setup_storage_img(self, determine, mkfs): + determine.return_value = ["/srv/test.img", ] + self.is_mapped_loopback_device.return_value = "/srv/test.img" + swift_utils.setup_storage() + self.mount.assert_called_with( + "/srv/test.img", + "/srv/node/test.img", + filesystem="xfs", + ) + self.fstab_add.assert_called_with( + '/srv/test.img', + '/srv/node/test.img', + 'xfs', + options='loop, defaults' + )