diff options
-rw-r--r-- | exec/chroot.py | 58 | ||||
-rw-r--r-- | sandbox.py | 69 |
2 files changed, 127 insertions, 0 deletions
diff --git a/exec/chroot.py b/exec/chroot.py new file mode 100644 index 0000000..d393d50 --- /dev/null +++ b/exec/chroot.py @@ -0,0 +1,58 @@ +# Run a sandbox in a chroot. + + +import contextlib +import json +import os +import shutil +import subprocess +import tarfile +import tempfile + + +@contextlib.contextmanager +def unpack_app_container_image(image_file): + tempdir = tempfile.mkdtemp() + try: + # FIXME: you gotta be root, sorry. + with tarfile.open(image_file, 'r') as tf: + tf.extractall(path=tempdir) + + manifest_path = os.path.join(tempdir, 'manifest') + rootfs_path = os.path.join(tempdir, 'rootfs') + + with open(manifest_path, 'r') as f: + manifest_data = json.load(f) + + yield rootfs_path, manifest_data + finally: + shutil.rmtree(tempdir) + + +def _run_sandbox_real(rootfs_path, manifest, command=None): + # FIXME: you gotta be root. + print manifest + if command is None: + # Use the command from the image + command = manifest['app']['exec'] + if type(command) == str: + command = [command] + subprocess.call(['chroot', rootfs_path] + command) + + +def run_sandbox(app_container_image=None, + rootfs_path=None, + manifest=None, + command=None): + if app_container_image is not None: + assert rootfs_path is None and manifest is None, \ + "You cannot specify a rootfs_path or manifest when running an " \ + "App Container image." + with unpack_app_container_image(app_container_image) as (rootfs_path, manifest): + return _run_sandbox_real(rootfs_path, manifest, command=command) + else: + _run_sandbox_real(rootfs_path, manifest, command=command) + + +run_sandbox(app_container_image='/home/shared/baserock/baserock-minimal.aci', + command=['/bin/sh', '-c', 'echo foo && exit 1']) diff --git a/sandbox.py b/sandbox.py new file mode 100644 index 0000000..85107ae --- /dev/null +++ b/sandbox.py @@ -0,0 +1,69 @@ +# Make a sandbox for running a command. + +# Sandbox could be: a baserock chroot, for the time being. + +# Image layout: /rootfs, /manifest + + +import json +import os +import shutil +import subprocess +import sys +import tarfile +import tempfile + + +def appc_manifest_for_command(command): + '''Fake an appc manifest.''' + manifest = { + 'acKind': 'ImageManifest', + 'acVersion': '0.5.2', + 'name': 'temp/temp1', + 'labels': [], + 'app': { + 'exec': command, + 'user': 'root', + 'group': 'root', + 'workingDirectory': '/temp.build', + } + } + return json.dumps(manifest) + +def make_sandbox_for_command(command, source_tar, target, + actool='/home/shared/baserock/appc-spec/actool/actool'): + '''Fake an appc image. + + This is a dumb idea, because you have to unpack a tar, create a tar, then + unpack it again to run it. + + Better to have the executor take manifest and rootfs separately. + + ''' + tempdir = tempfile.mkdtemp() + + try: + manifest_path = os.path.join(tempdir, 'manifest') + rootfs_path = os.path.join(tempdir, 'rootfs') + + with open(manifest_path, 'w') as f: + f.write(appc_manifest_for_command(command)) + + os.mkdir(rootfs_path) + # FIXME: You've probably got to run this as root. + with tarfile.TarFile(source_tar, 'r') as tf: + tf.extractall(path=rootfs_path) + + subprocess.check_call( + [actool, 'build', tempdir, target], + stdout=sys.stdout, + stderr=sys.stderr) + print 'Created %s' % target + finally: + shutil.rmtree(tempdir) + + +make_sandbox_for_command( + command=['/bin/sh', '-c', '"echo foo && exit 1"'], + source_tar='/home/shared/baserock-chroot-src/definitions/baserock-minimal.tar', + target='/home/shared/baserock/baserock-minimal.aci') |