diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-05-22 12:13:30 +0100 |
---|---|---|
committer | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-05-22 12:13:30 +0100 |
commit | efe56eb94d868870ac67e2a4fe4521f82df86bda (patch) | |
tree | 7e17ef7e424ee1d9716ba7019682f2f72a084137 /sandboxlib | |
parent | 6035cf559bea99ea26186ab49c8efaa1e579304c (diff) | |
download | sandboxlib-efe56eb94d868870ac67e2a4fe4521f82df86bda.tar.gz |
Add linux-user-chroot backend, run-sandbox script, 'appc' loader
This library is now enough to run a very simple App Container image,
using either 'chroot' or 'linux-user-chroot'.
Diffstat (limited to 'sandboxlib')
-rw-r--r-- | sandboxlib/__init__.py | 44 | ||||
-rw-r--r-- | sandboxlib/chroot.py | 8 | ||||
-rw-r--r-- | sandboxlib/linux_user_chroot.py | 30 | ||||
-rw-r--r-- | sandboxlib/load/__init__.py | 19 | ||||
-rw-r--r-- | sandboxlib/load/appc.py | 48 |
5 files changed, 148 insertions, 1 deletions
diff --git a/sandboxlib/__init__.py b/sandboxlib/__init__.py new file mode 100644 index 0000000..04ae353 --- /dev/null +++ b/sandboxlib/__init__.py @@ -0,0 +1,44 @@ +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + + +'''sandboxlib module.''' + + +BASE_ENVIRONMENT = { + # Mandated by https://github.com/appc/spec/blob/master/SPEC.md#execution-environment + 'PATH': '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', +} + + +def environment_vars(extra_env=None): + '''Return the complete set of environment variables for a sandbox. + + The base environment is defined above, and callers can add extra variables + to this or override the defaults by passing a dict to 'extra_env'. + + ''' + env = BASE_ENVIRONMENT.copy() + + if extra_env is not None: + env.update(extra_env) + + return env + + +# Executors +import sandboxlib.chroot +import sandboxlib.linux_user_chroot + +import sandboxlib.load diff --git a/sandboxlib/chroot.py b/sandboxlib/chroot.py index a20b6c8..3fe1857 100644 --- a/sandboxlib/chroot.py +++ b/sandboxlib/chroot.py @@ -18,10 +18,16 @@ import subprocess +import sandboxlib -def run_sandbox(rootfs_path, command): + +def run_sandbox(rootfs_path, command, extra_env=None): if type(command) == str: command = [command] + env = sandboxlib.BASE_ENVIRONMENT.copy() + if extra_env is not None: + env.update(extra_env) + # FIXME: you gotta be root for this one. subprocess.call(['chroot', rootfs_path] + command) diff --git a/sandboxlib/linux_user_chroot.py b/sandboxlib/linux_user_chroot.py new file mode 100644 index 0000000..8957191 --- /dev/null +++ b/sandboxlib/linux_user_chroot.py @@ -0,0 +1,30 @@ +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + + +'''Execute command in a sandbox, using 'linux-user-chroot'.''' + + +import subprocess + +import sandboxlib + + +def run_sandbox(rootfs_path, command, extra_env=None): + if type(command) == str: + command = [command] + + env = sandboxlib.environment_vars(extra_env) + + subprocess.call(['linux-user-chroot', rootfs_path] + command, env=env) diff --git a/sandboxlib/load/__init__.py b/sandboxlib/load/__init__.py new file mode 100644 index 0000000..59b8cf6 --- /dev/null +++ b/sandboxlib/load/__init__.py @@ -0,0 +1,19 @@ +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + + +'''sandboxlib loaders module.''' + + +import sandboxlib.load.appc diff --git a/sandboxlib/load/appc.py b/sandboxlib/load/appc.py new file mode 100644 index 0000000..486391e --- /dev/null +++ b/sandboxlib/load/appc.py @@ -0,0 +1,48 @@ +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + + +'''Sandbox loader module for App Container images.''' + + +import contextlib +import json +import logging +import os +import shutil +import tarfile +import tempfile + + +def is_app_container_image(path): + return path.endswith('.aci') + + +@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) |