From 9f5b2d64071ab8416487b5fc265908a511a9bf68 Mon Sep 17 00:00:00 2001 From: Adam Coldrick Date: Thu, 5 Feb 2015 13:51:23 +0000 Subject: Add support for unionfs Overlayfs is new in version 3.18 of the kernel, so add support for a different implementation of a union/overlay filesystem in order to allow morph to work on older kernels. --- morphlib/app.py | 7 +++++++ morphlib/builder.py | 13 ++++++------- morphlib/fsutils.py | 17 +++++++++++++++++ morphlib/plugins/deploy_plugin.py | 18 +++++++++--------- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/morphlib/app.py b/morphlib/app.py index 0c87f814..5b645012 100644 --- a/morphlib/app.py +++ b/morphlib/app.py @@ -121,6 +121,13 @@ class Morph(cliapp.Application): metavar='URL', default=None, group=group_advanced) + self.settings.string(['union-filesystem'], + 'filesystem used to provide "union filesystem" ' + 'functionality when building and deploying. ' + 'Only "overlayfs" and "unionfs" are supported ' + 'at this time.', + default='overlayfs', + group=group_advanced) group_build = 'Build Options' self.settings.integer(['max-jobs'], diff --git a/morphlib/builder.py b/morphlib/builder.py index 40df10c3..cfba83c7 100644 --- a/morphlib/builder.py +++ b/morphlib/builder.py @@ -558,19 +558,18 @@ class SystemBuilder(BuilderBase): # pragma: no cover try: fs_root = self.staging_area.destdir(self.source) self.unpack_strata(fs_root) - overlay_root = self.staging_area.overlay_upperdir( + upperdir = self.staging_area.overlay_upperdir( self.source) editable_root = self.staging_area.overlaydir(self.source) workdir = os.path.join(self.staging_area.dirname, 'overlayfs-workdir') if not os.path.exists(workdir): os.makedirs(workdir) - options = '-olowerdir=%s,upperdir=%s,workdir=%s' % \ - (fs_root, overlay_root, workdir) - morphlib.fsutils.mount(self.app.runcmd, - 'overlay-%s' % a_name, - editable_root, - 'overlay', options) + morphlib.fsutils.overlay_mount(self.app.runcmd, + 'overlay-%s' % a_name, + editable_root, fs_root, + upperdir, workdir, + self.app.settings) self.write_metadata(editable_root, a_name) self.run_system_integration_commands(editable_root) unslashy_root = editable_root[1:] diff --git a/morphlib/fsutils.py b/morphlib/fsutils.py index 97a7a8f2..3a9ee4db 100644 --- a/morphlib/fsutils.py +++ b/morphlib/fsutils.py @@ -60,6 +60,23 @@ def mount(runcmd, partition, mount_point, runcmd(['mount', partition, mount_point] + fstype + options) +def overlay_mount(runcmd, partition, mount_point, + lowerdir, upperdir, workdir, settings): # pragma: no cover + method = settings['union-filesystem'] + if method == 'overlayfs': + options = '-olowerdir=%s,upperdir=%s,workdir=%s' % \ + (lowerdir, upperdir, workdir) + mount(runcmd, partition, mount_point, 'overlay', options) + elif method == 'unionfs': + if not os.path.exists(mount_point): + os.mkdir(mount_point) + dir_string = '%s=RW:%s=RO' % (upperdir, lowerdir) + runcmd(['unionfs', '-o', 'cow', dir_string, mount_point]) + else: + raise cliapp.AppException('Union filesystem %s not supported' % + method) + + def unmount(runcmd, mount_point): # pragma: no cover runcmd(['umount', mount_point]) diff --git a/morphlib/plugins/deploy_plugin.py b/morphlib/plugins/deploy_plugin.py index 4f78d126..a4895106 100644 --- a/morphlib/plugins/deploy_plugin.py +++ b/morphlib/plugins/deploy_plugin.py @@ -580,12 +580,12 @@ class DeployPlugin(cliapp.Plugin): msg='System unpacked at %(system_tree)s', system_tree=system_tree) - options = '-olowerdir=%s,upperdir=%s,workdir=%s' % \ - (system_tree, overlay_dir, work_dir) - morphlib.fsutils.mount(self.app.runcmd, - 'overlay-deploy-%s' % artifact.name, - deploy_tree, fstype='overlay', - options=options) + morphlib.fsutils.overlay_mount(self.app.runcmd, + 'overlay-deploy-%s' % + artifact.name, + deploy_tree, system_tree, + overlay_dir, work_dir, + self.app.settings) self.app.status( msg='Writing deployment metadata file') @@ -598,12 +598,12 @@ class DeployPlugin(cliapp.Plugin): sort_keys=True, encoding='unicode-escape') return deploy_tree except Exception: - shutil.rmtree(system_tree) - shutil.rmtree(overlay_dir) - shutil.rmtree(work_dir) if deploy_tree and os.path.exists(deploy_tree): morphlib.fsutils.unmount(self.app.runcmd, deploy_tree) shutil.rmtree(deploy_tree) + shutil.rmtree(system_tree) + shutil.rmtree(overlay_dir) + shutil.rmtree(work_dir) raise def run_deploy_commands(self, deploy_tempdir, env, artifact, root_repo_dir, -- cgit v1.2.1