summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2014-11-11 17:28:13 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2014-11-11 17:35:45 +0000
commit2a019b5fee65a738bdd38717b0b84eea638a776d (patch)
tree5c53ffd0f89bb4ce8a50b1c8f5355ab758c8dbbf
parent384dc8d2eb9222746085f0274c625eb163eda88a (diff)
downloadmorph-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.py60
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',