summaryrefslogtreecommitdiff
path: root/sandboxlib
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2015-05-22 12:13:30 +0100
committerSam Thursfield <sam.thursfield@codethink.co.uk>2015-05-22 12:13:30 +0100
commitefe56eb94d868870ac67e2a4fe4521f82df86bda (patch)
tree7e17ef7e424ee1d9716ba7019682f2f72a084137 /sandboxlib
parent6035cf559bea99ea26186ab49c8efaa1e579304c (diff)
downloadsandboxlib-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__.py44
-rw-r--r--sandboxlib/chroot.py8
-rw-r--r--sandboxlib/linux_user_chroot.py30
-rw-r--r--sandboxlib/load/__init__.py19
-rw-r--r--sandboxlib/load/appc.py48
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)