diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2014-11-11 17:28:13 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2014-11-11 17:35:45 +0000 |
commit | 2a019b5fee65a738bdd38717b0b84eea638a776d (patch) | |
tree | 5c53ffd0f89bb4ce8a50b1c8f5355ab758c8dbbf | |
parent | 384dc8d2eb9222746085f0274c625eb163eda88a (diff) | |
download | morph-2a019b5fee65a738bdd38717b0b84eea638a776d.tar.gz |
Revert "Make system-integration commands use containerised_cmdline"
This reverts commit 203f34b2b19b1d3dc51a956ae9329d064ea294dd.
The path inversion logic is still buggy for the case of wanting to keep
the top-level directory writable.
This escaped detection in the test suite because it resulted in
directories two levels down being made read-only, and I was only testing
one level down.
-rw-r--r-- | morphlib/builder2.py | 60 |
1 files changed, 55 insertions, 5 deletions
diff --git a/morphlib/builder2.py b/morphlib/builder2.py index f71f21db..8615ed59 100644 --- a/morphlib/builder2.py +++ b/morphlib/builder2.py @@ -28,6 +28,7 @@ import time import traceback import subprocess import tempfile +import textwrap import gzip import cliapp @@ -646,6 +647,53 @@ class SystemBuilder(BuilderBase): # pragma: no cover os.chmod(os_release_file, 0644) + def _chroot_runcmd(self, rootdir, to_mount, env, *args): + # We need to do mounts in a different namespace. Unfortunately + # this means we have to in-line the mount commands in the + # command-line. + command = textwrap.dedent(r''' + mount --make-rprivate / + rootdir="$1" + shift + ''') + cmdargs = [rootdir] + + # We need to mount all the specified mounts in the namespace, + # we don't need to unmount them before exiting, as they'll be + # unmounted when the namespace is no longer used. + command += textwrap.dedent(r''' + while true; do + case "$1" in + --) + shift + break + ;; + *) + mount_point="$1" + mount_type="$2" + mount_source="$3" + shift 3 + path="$rootdir/$mount_point" + mount -t "$mount_type" "$mount_source" "$path" + ;; + esac + done + ''') + for mount_opts in to_mount: + cmdargs.extend(mount_opts) + cmdargs.append('--') + + command += textwrap.dedent(r''' + exec chroot "$rootdir" "$@" + ''') + cmdargs.extend(args) + + # The single - is just a shell convention to fill $0 when using -c, + # since ordinarily $0 contains the program name. + cmdline = ['unshare', '--mount', '--', 'sh', '-ec', command, '-'] + cmdline.extend(cmdargs) + self.app.runcmd(cmdline, env=env) + def run_system_integration_commands(self, rootdir): # pragma: no cover ''' Run the system integration commands ''' @@ -660,16 +708,18 @@ class SystemBuilder(BuilderBase): # pragma: no cover self.app.status(msg='Running the system integration commands') to_mount = ( + ('proc', 'proc', 'none'), ('dev/shm', 'tmpfs', 'none'), ('tmp', 'tmpfs', 'none'), ) try: + for mount_point, mount_type, source in to_mount: + path = os.path.join(rootdir, mount_point) + if not os.path.exists(path): + os.makedirs(path) for bin in sorted(os.listdir(sys_integration_dir)): - self.app.runcmd( - morphlib.util.containerised_cmdline( - [os.path.join(SYSTEM_INTEGRATION_PATH, bin)], - root=rootdir, mounts=to_mount, mount_proc=True), - env=env) + self._chroot_runcmd(rootdir, to_mount, env, + os.path.join(SYSTEM_INTEGRATION_PATH, bin)) except BaseException, e: self.app.status( msg='Error while running system integration commands', |