summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buildstream/_platform/linux.py27
-rw-r--r--src/buildstream/sandbox/_sandboxbuildbox.py248
2 files changed, 0 insertions, 275 deletions
diff --git a/src/buildstream/_platform/linux.py b/src/buildstream/_platform/linux.py
index a6215c90f..05e55e0f5 100644
--- a/src/buildstream/_platform/linux.py
+++ b/src/buildstream/_platform/linux.py
@@ -24,14 +24,12 @@ from .. import utils
from ..sandbox import SandboxDummy
from .platform import Platform
-from .._exceptions import PlatformError
class Linux(Platform):
def _setup_sandbox(self, force_sandbox):
sandbox_setups = {
"bwrap": self._setup_bwrap_sandbox,
- "buildbox": self._setup_buildbox_sandbox,
"buildbox-run": self.setup_buildboxrun_sandbox,
"chroot": self._setup_chroot_sandbox,
"dummy": self._setup_dummy_sandbox,
@@ -129,28 +127,3 @@ class Linux(Platform):
self.check_sandbox_config = self._check_sandbox_config_chroot
self.create_sandbox = Linux._create_chroot_sandbox
return True
-
- # Buildbox sandbox methods
- def _check_sandbox_config_buildbox(self, config):
- from ..sandbox._sandboxbuildbox import SandboxBuildBox
-
- return SandboxBuildBox.check_sandbox_config(self, config)
-
- @staticmethod
- def _create_buildbox_sandbox(*args, **kwargs):
- from ..sandbox._sandboxbuildbox import SandboxBuildBox
-
- if kwargs.get("allow_real_directory"):
- raise PlatformError(
- "The BuildBox Sandbox does not support real directories.",
- reason="You are using BuildBox sandbox because BST_FORCE_SANBOX=buildbox",
- )
- return SandboxBuildBox(*args, **kwargs)
-
- def _setup_buildbox_sandbox(self):
- from ..sandbox._sandboxbuildbox import SandboxBuildBox
-
- self._check_sandbox(SandboxBuildBox)
- self.check_sandbox_config = self._check_sandbox_config_buildbox
- self.create_sandbox = self._create_buildbox_sandbox
- return True
diff --git a/src/buildstream/sandbox/_sandboxbuildbox.py b/src/buildstream/sandbox/_sandboxbuildbox.py
deleted file mode 100644
index c34d95223..000000000
--- a/src/buildstream/sandbox/_sandboxbuildbox.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#
-# Copyright (C) 2018 Bloomberg LP
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import sys
-import signal
-import subprocess
-from contextlib import ExitStack
-
-import psutil
-
-from .. import utils, _signals, ProgramNotFoundError
-from . import Sandbox, SandboxFlags, SandboxCommandError
-from .._protos.build.bazel.remote.execution.v2 import remote_execution_pb2
-from ..storage._casbaseddirectory import CasBasedDirectory
-from .._exceptions import SandboxError
-
-
-# SandboxBuidBox()
-#
-# BuildBox-based sandbox implementation.
-#
-class SandboxBuildBox(Sandbox):
- def __init__(self, context, project, directory, **kwargs):
- if kwargs.get("allow_real_directory"):
- raise SandboxError("BuildBox does not support real directories")
-
- kwargs["allow_real_directory"] = False
- super().__init__(context, project, directory, **kwargs)
-
- @classmethod
- def check_available(cls):
- try:
- utils.get_host_tool("buildbox")
- except utils.ProgramNotFoundError as Error:
- cls._dummy_reasons += ["buildbox not found"]
- raise SandboxError(" and ".join(cls._dummy_reasons), reason="unavailable-local-sandbox") from Error
-
- @classmethod
- def check_sandbox_config(cls, platform, config):
- # Report error for elements requiring non-0 UID/GID
- # TODO
- if config.build_uid != 0 or config.build_gid != 0:
- return False
-
- # Check host os and architecture match
- if config.build_os != platform.get_host_os():
- raise SandboxError("Configured and host OS don't match.")
- if config.build_arch != platform.get_host_arch():
- raise SandboxError("Configured and host architecture don't match.")
-
- return True
-
- def _run(self, command, flags, *, cwd, env):
- stdout, stderr = self._get_output()
-
- root_directory = self.get_virtual_directory()
- scratch_directory = self._get_scratch_directory()
-
- if not self._has_command(command[0], env):
- raise SandboxCommandError(
- "Staged artifacts do not provide command " "'{}'".format(command[0]), reason="missing-command"
- )
-
- # Grab the full path of the buildbox binary
- try:
- buildbox_command = [utils.get_host_tool("buildbox")]
- except ProgramNotFoundError as Err:
- raise SandboxError(
- ("BuildBox not on path, you are using the BuildBox sandbox because " "BST_FORCE_SANDBOX=buildbox")
- ) from Err
-
- for mark in self._get_marked_directories():
- path = mark["directory"]
- assert path.startswith("/") and len(path) > 1
- root_directory.descend(*path[1:].split(os.path.sep), create=True)
-
- digest = root_directory._get_digest()
- with open(os.path.join(scratch_directory, "in"), "wb") as input_digest_file:
- input_digest_file.write(digest.SerializeToString())
-
- buildbox_command += ["--local=" + root_directory.cas_cache.casdir]
- buildbox_command += ["--input-digest=in"]
- buildbox_command += ["--output-digest=out"]
-
- common_details = (
- "BuildBox is a experimental sandbox and does not support the requested feature.\n"
- "You are using this feature because BST_FORCE_SANDBOX=buildbox."
- )
-
- if not flags & SandboxFlags.NETWORK_ENABLED:
- # TODO
- self._issue_warning("BuildBox sandbox does not have Networking yet", detail=common_details)
-
- if cwd is not None:
- buildbox_command += ["--chdir=" + cwd]
-
- # In interactive mode, we want a complete devpts inside
- # the container, so there is a /dev/console and such. In
- # the regular non-interactive sandbox, we want to hand pick
- # a minimal set of devices to expose to the sandbox.
- #
- if flags & SandboxFlags.INTERACTIVE:
- # TODO
- self._issue_warning(
- "BuildBox sandbox does not fully support BuildStream shells yet", detail=common_details
- )
-
- if flags & SandboxFlags.ROOT_READ_ONLY:
- # TODO
- self._issue_warning(
- "BuildBox sandbox does not fully support BuildStream `Read only Root`", detail=common_details
- )
-
- # Set UID and GID
- if not flags & SandboxFlags.INHERIT_UID:
- # TODO
- self._issue_warning(
- "BuildBox sandbox does not fully support BuildStream Inherit UID", detail=common_details
- )
-
- os.makedirs(os.path.join(scratch_directory, "mnt"), exist_ok=True)
- buildbox_command += ["mnt"]
-
- # Add the command
- buildbox_command += command
-
- # Use the MountMap context manager to ensure that any redirected
- # mounts through fuse layers are in context and ready for buildbox
- # to mount them from.
- #
- with ExitStack() as stack:
- # Ensure the cwd exists
- if cwd is not None and len(cwd) > 1:
- assert cwd.startswith("/")
- root_directory.descend(*cwd[1:].split(os.path.sep), create=True)
-
- # 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
- else:
- stdin = stack.enter_context(open(os.devnull, "r"))
-
- # Run buildbox !
- exit_code = self.run_buildbox(
- buildbox_command,
- stdin,
- stdout,
- stderr,
- env,
- interactive=(flags & SandboxFlags.INTERACTIVE),
- cwd=scratch_directory,
- )
-
- if exit_code == 0:
- with open(os.path.join(scratch_directory, "out"), "rb") as output_digest_file:
- output_digest = remote_execution_pb2.Digest()
- output_digest.ParseFromString(output_digest_file.read())
- self._vdir = CasBasedDirectory(root_directory.cas_cache, digest=output_digest)
-
- return exit_code
-
- def run_buildbox(self, argv, stdin, stdout, stderr, env, *, interactive, cwd):
- def kill_proc():
- if process:
- # First attempt to gracefully terminate
- proc = psutil.Process(process.pid)
- proc.terminate()
-
- try:
- proc.wait(20)
- except psutil.TimeoutExpired:
- utils._kill_process_tree(process.pid)
-
- def suspend_proc():
- group_id = os.getpgid(process.pid)
- os.killpg(group_id, signal.SIGSTOP)
-
- def resume_proc():
- group_id = os.getpgid(process.pid)
- os.killpg(group_id, signal.SIGCONT)
-
- with _signals.suspendable(suspend_proc, resume_proc), _signals.terminator(kill_proc):
- process = subprocess.Popen(
- argv,
- close_fds=True,
- env=env,
- stdin=stdin,
- stdout=stdout,
- stderr=stderr,
- cwd=cwd,
- start_new_session=interactive,
- )
-
- # Wait for the child process to finish, ensuring that
- # a SIGINT has exactly the effect the user probably
- # expects (i.e. let the child process handle it).
- try:
- while True:
- try:
- _, status = os.waitpid(process.pid, 0)
- # If the process exits due to a signal, we
- # brutally murder it to avoid zombies
- if not os.WIFEXITED(status):
- utils._kill_process_tree(process.pid)
-
- # Unlike in the bwrap case, here only the main
- # process seems to receive the SIGINT. We pass
- # on the signal to the child and then continue
- # to wait.
- except KeyboardInterrupt:
- process.send_signal(signal.SIGINT)
- continue
-
- break
- # If we can't find the process, it has already died of
- # its own accord, and therefore we don't need to check
- # or kill anything.
- except psutil.NoSuchProcess:
- pass
-
- # Return the exit code - see the documentation for
- # os.WEXITSTATUS to see why this is required.
- if os.WIFEXITED(status):
- exit_code = os.WEXITSTATUS(status)
- else:
- exit_code = -1
-
- return exit_code
-
- def _use_cas_based_directory(self):
- # Always use CasBasedDirectory for BuildBox
- return True