summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2020-02-03 19:42:22 +0000
committerJürg Billeter <j@bitron.ch>2020-02-03 19:42:22 +0000
commit5c9da3a51e1906fd149ac5de4798ecb33795f7e1 (patch)
tree3a6c686b1a86898e8f24b7012ad4499cfd8193e3
parent5e169159ebf45cabaf168bdf8b0e3c9d1e019bb5 (diff)
parentdba3d8b0f7afe6ce7d43b6cbbb1477546a821c3f (diff)
downloadbuildstream-5c9da3a51e1906fd149ac5de4798ecb33795f7e1.tar.gz
Merge branch 'juerg/buildbox-run-bind-mount' into 'master'
_sandboxbuildboxrun.py: Support host-files See merge request BuildStream/buildstream!1807
-rw-r--r--src/buildstream/sandbox/_sandboxbuildboxrun.py34
-rw-r--r--src/buildstream/sandbox/_sandboxreapi.py3
-rw-r--r--tests/integration/shell.py15
3 files changed, 48 insertions, 4 deletions
diff --git a/src/buildstream/sandbox/_sandboxbuildboxrun.py b/src/buildstream/sandbox/_sandboxbuildboxrun.py
index d542d39f8..93ee330b1 100644
--- a/src/buildstream/sandbox/_sandboxbuildboxrun.py
+++ b/src/buildstream/sandbox/_sandboxbuildboxrun.py
@@ -24,6 +24,7 @@ import psutil
from .. import utils, _signals
from . import SandboxFlags
from .._exceptions import SandboxError
+from .._message import Message, MessageType
from .._protos.build.bazel.remote.execution.v2 import remote_execution_pb2
from ._sandboxreapi import SandboxREAPI
@@ -40,11 +41,19 @@ class SandboxBuildBoxRun(SandboxREAPI):
@classmethod
def check_available(cls):
try:
- utils.get_host_tool("buildbox-run")
+ path = utils.get_host_tool("buildbox-run")
except utils.ProgramNotFoundError as Error:
cls._dummy_reasons += ["buildbox-run not found"]
raise SandboxError(" and ".join(cls._dummy_reasons), reason="unavailable-local-sandbox") from Error
+ exit_code, output = utils._call([path, "--capabilities"], stdout=subprocess.PIPE)
+ if exit_code == 0:
+ # buildbox-run --capabilities prints one capability per line
+ cls._capabilities = set(output.split("\n"))
+ else:
+ # buildbox-run is too old to support extra capabilities
+ cls._capabilities = set()
+
@classmethod
def check_sandbox_config(cls, platform, config):
# Report error for elements requiring non-0 UID/GID
@@ -78,11 +87,31 @@ class SandboxBuildBoxRun(SandboxREAPI):
"--action-result={}".format(result_file.name),
]
+ marked_directories = self._get_marked_directories()
+ mount_sources = self._get_mount_sources()
+ for mark in marked_directories:
+ mount_point = mark["directory"]
+ mount_source = mount_sources.get(mount_point)
+ if not mount_source:
+ # Handled by the input tree in the action
+ continue
+
+ if "bind-mount" not in self._capabilities:
+ self._warn("buildbox-run does not support host-files")
+ break
+
+ buildbox_command.append("--bind-mount={}:{}".format(mount_source, mount_point))
+
# If we're interactive, we want to inherit our stdin,
# otherwise redirect to /dev/null, ensuring process
# disconnected from terminal.
if flags & SandboxFlags.INTERACTIVE:
stdin = sys.stdin
+
+ if "bind-mount" in self._capabilities:
+ # In interactive mode, we want a complete devpts inside
+ # the container, so there is a /dev/console and such.
+ buildbox_command.append("--bind-mount=/dev:/dev")
else:
stdin = subprocess.DEVNULL
@@ -146,3 +175,6 @@ class SandboxBuildBoxRun(SandboxREAPI):
if returncode != 0:
raise SandboxError("buildbox-run failed with returncode {}".format(returncode))
+
+ def _warn(self, msg):
+ self._get_context().messenger.message(Message(MessageType.WARN, msg))
diff --git a/src/buildstream/sandbox/_sandboxreapi.py b/src/buildstream/sandbox/_sandboxreapi.py
index 2430fd372..f1cd477d6 100644
--- a/src/buildstream/sandbox/_sandboxreapi.py
+++ b/src/buildstream/sandbox/_sandboxreapi.py
@@ -59,8 +59,11 @@ class SandboxREAPI(Sandbox):
# Create directories for all marked directories. This emulates
# some of the behaviour of other sandboxes, which create these
# to use as mount points.
+ mount_sources = self._get_mount_sources()
for mark in self._get_marked_directories():
directory = mark["directory"]
+ if directory in mount_sources:
+ continue
# Create each marked directory
vdir.descend(*directory.split(os.path.sep), create=True)
diff --git a/tests/integration/shell.py b/tests/integration/shell.py
index 5e35d550c..c4725ec07 100644
--- a/tests/integration/shell.py
+++ b/tests/integration/shell.py
@@ -162,7 +162,10 @@ def test_no_shell(cli, datafiles):
@pytest.mark.parametrize("path", [("/etc/pony.conf"), ("/usr/share/pony/pony.txt")])
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox")
-@pytest.mark.xfail(HAVE_SANDBOX == "buildbox-run", reason="Not working with BuildBox")
+@pytest.mark.xfail(
+ HAVE_SANDBOX == "buildbox-run" and BUILDBOX_RUN != "buildbox-run-bubblewrap",
+ reason="Only available with bubblewrap",
+)
def test_host_files(cli, datafiles, path):
project = str(datafiles)
ponyfile = os.path.join(project, "files", "shell-mount", "pony.txt")
@@ -177,7 +180,10 @@ def test_host_files(cli, datafiles, path):
@pytest.mark.parametrize("path", [("/etc"), ("/usr/share/pony")])
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox")
-@pytest.mark.xfail(HAVE_SANDBOX == "buildbox-run", reason="Not working with BuildBox")
+@pytest.mark.xfail(
+ HAVE_SANDBOX == "buildbox-run" and BUILDBOX_RUN != "buildbox-run-bubblewrap",
+ reason="Only available with bubblewrap",
+)
def test_host_files_expand_environ(cli, datafiles, path):
project = str(datafiles)
hostpath = os.path.join(project, "files", "shell-mount")
@@ -250,7 +256,10 @@ def test_host_files_missing(cli, datafiles, optional):
@pytest.mark.parametrize("path", [("/etc/pony.conf"), ("/usr/share/pony/pony.txt")])
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox")
-@pytest.mark.xfail(HAVE_SANDBOX == "buildbox-run", reason="Not working with BuildBox")
+@pytest.mark.xfail(
+ HAVE_SANDBOX == "buildbox-run" and BUILDBOX_RUN != "buildbox-run-bubblewrap",
+ reason="Only available with bubblewrap",
+)
def test_cli_mount(cli, datafiles, path):
project = str(datafiles)
ponyfile = os.path.join(project, "files", "shell-mount", "pony.txt")