summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2018-09-18 13:50:15 +0000
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2018-09-18 13:50:15 +0000
commitd8450166db2dc72e43018a48e2cbc6f546af05f8 (patch)
tree26df4d2164f0150097a01356975e3459e895c8d4
parent97071b6ee598aad5ed159bb038bb333a468f065e (diff)
parent8430fdc7da59a20d6a3ec9b526d681b8f68920ec (diff)
downloadbuildstream-d8450166db2dc72e43018a48e2cbc6f546af05f8.tar.gz
Merge branch 'richardmaw/fix-chroot-sandbox-devices' into 'master'
fix chroot sandbox devices See merge request BuildStream/buildstream!781
-rw-r--r--buildstream/_fuse/hardlinks.py5
-rw-r--r--buildstream/_fuse/mount.py6
-rw-r--r--buildstream/sandbox/_mount.py11
-rw-r--r--buildstream/sandbox/_sandboxchroot.py6
-rw-r--r--tests/integration/project/elements/integration.bst9
-rw-r--r--tests/integration/shell.py10
6 files changed, 38 insertions, 9 deletions
diff --git a/buildstream/_fuse/hardlinks.py b/buildstream/_fuse/hardlinks.py
index 1386f14cf..0797cb4bc 100644
--- a/buildstream/_fuse/hardlinks.py
+++ b/buildstream/_fuse/hardlinks.py
@@ -42,9 +42,10 @@ from .mount import Mount
#
class SafeHardlinks(Mount):
- def __init__(self, directory, tempdir):
+ def __init__(self, directory, tempdir, fuse_mount_options={}):
self.directory = directory
self.tempdir = tempdir
+ super().__init__(fuse_mount_options=fuse_mount_options)
def create_operations(self):
return SafeHardlinkOps(self.directory, self.tempdir)
@@ -121,7 +122,7 @@ class SafeHardlinkOps(Operations):
st = os.lstat(full_path)
return dict((key, getattr(st, key)) for key in (
'st_atime', 'st_ctime', 'st_gid', 'st_mode',
- 'st_mtime', 'st_nlink', 'st_size', 'st_uid'))
+ 'st_mtime', 'st_nlink', 'st_size', 'st_uid', 'st_rdev'))
def readdir(self, path, fh):
full_path = self._full_path(path)
diff --git a/buildstream/_fuse/mount.py b/buildstream/_fuse/mount.py
index 0ab1ce715..30cc85b77 100644
--- a/buildstream/_fuse/mount.py
+++ b/buildstream/_fuse/mount.py
@@ -87,6 +87,9 @@ class Mount():
# User Facing API #
################################################
+ def __init__(self, fuse_mount_options={}):
+ self._fuse_mount_options = fuse_mount_options
+
# mount():
#
# User facing API for mounting a fuse subclass implementation
@@ -184,7 +187,8 @@ class Mount():
# Run fuse in foreground in this child process, internally libfuse
# will handle SIGTERM and gracefully exit it's own little main loop.
#
- FUSE(self.__operations, self.__mountpoint, nothreads=True, foreground=True, nonempty=True)
+ FUSE(self.__operations, self.__mountpoint, nothreads=True, foreground=True, nonempty=True,
+ **self._fuse_mount_options)
# Explicit 0 exit code, if the operations crashed for some reason, the exit
# code will not be 0, and we want to know about it.
diff --git a/buildstream/sandbox/_mount.py b/buildstream/sandbox/_mount.py
index 49068fe92..4fca3d1b0 100644
--- a/buildstream/sandbox/_mount.py
+++ b/buildstream/sandbox/_mount.py
@@ -30,7 +30,7 @@ from .._fuse import SafeHardlinks
# Helper data object representing a single mount point in the mount map
#
class Mount():
- def __init__(self, sandbox, mount_point, safe_hardlinks):
+ def __init__(self, sandbox, mount_point, safe_hardlinks, fuse_mount_options={}):
scratch_directory = sandbox._get_scratch_directory()
# Getting _get_underlying_directory() here is acceptable as
# we're part of the sandbox code. This will fail if our
@@ -39,6 +39,7 @@ class Mount():
self.mount_point = mount_point
self.safe_hardlinks = safe_hardlinks
+ self._fuse_mount_options = fuse_mount_options
# FIXME: When the criteria for mounting something and it's parent
# mount is identical, then there is no need to mount an additional
@@ -82,7 +83,7 @@ class Mount():
@contextmanager
def mounted(self, sandbox):
if self.safe_hardlinks:
- mount = SafeHardlinks(self.mount_origin, self.mount_tempdir)
+ mount = SafeHardlinks(self.mount_origin, self.mount_tempdir, self._fuse_mount_options)
with mount.mounted(self.mount_source):
yield
else:
@@ -100,12 +101,12 @@ class Mount():
#
class MountMap():
- def __init__(self, sandbox, root_readonly):
+ def __init__(self, sandbox, root_readonly, fuse_mount_options={}):
# We will be doing the mounts in the order in which they were declared.
self.mounts = OrderedDict()
# We want safe hardlinks on rootfs whenever root is not readonly
- self.mounts['/'] = Mount(sandbox, '/', not root_readonly)
+ self.mounts['/'] = Mount(sandbox, '/', not root_readonly, fuse_mount_options)
for mark in sandbox._get_marked_directories():
directory = mark['directory']
@@ -113,7 +114,7 @@ class MountMap():
# We want safe hardlinks for any non-root directory where
# artifacts will be staged to
- self.mounts[directory] = Mount(sandbox, directory, artifact)
+ self.mounts[directory] = Mount(sandbox, directory, artifact, fuse_mount_options)
# get_mount_source()
#
diff --git a/buildstream/sandbox/_sandboxchroot.py b/buildstream/sandbox/_sandboxchroot.py
index 64fb3c1bc..b3a2a6d9d 100644
--- a/buildstream/sandbox/_sandboxchroot.py
+++ b/buildstream/sandbox/_sandboxchroot.py
@@ -35,6 +35,9 @@ from . import Sandbox, SandboxFlags
class SandboxChroot(Sandbox):
+
+ _FUSE_MOUNT_OPTIONS = {'dev': True}
+
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -67,7 +70,8 @@ class SandboxChroot(Sandbox):
# Create the mount map, this will tell us where
# each mount point needs to be mounted from and to
- self.mount_map = MountMap(self, flags & SandboxFlags.ROOT_READ_ONLY)
+ self.mount_map = MountMap(self, flags & SandboxFlags.ROOT_READ_ONLY,
+ self._FUSE_MOUNT_OPTIONS)
root_mount_source = self.mount_map.get_mount_source('/')
# Create a sysroot and run the command inside it
diff --git a/tests/integration/project/elements/integration.bst b/tests/integration/project/elements/integration.bst
new file mode 100644
index 000000000..be21ae31b
--- /dev/null
+++ b/tests/integration/project/elements/integration.bst
@@ -0,0 +1,9 @@
+kind: manual
+depends:
+- base.bst
+
+public:
+ bst:
+ integration-commands:
+ - |
+ echo noise >/dev/null
diff --git a/tests/integration/shell.py b/tests/integration/shell.py
index 18953aa2d..947650ff1 100644
--- a/tests/integration/shell.py
+++ b/tests/integration/shell.py
@@ -342,3 +342,13 @@ def test_sysroot_workspace_visible(cli, tmpdir, datafiles):
])
assert result.exit_code == 0
assert result.output == workspace_hello
+
+
+# Test system integration commands can access devices in /dev
+@pytest.mark.datafiles(DATA_DIR)
+def test_integration_devices(cli, tmpdir, datafiles):
+ project = os.path.join(datafiles.dirname, datafiles.basename)
+ element_name = 'integration.bst'
+
+ result = execute_shell(cli, project, ["true"], element=element_name)
+ assert result.exit_code == 0