diff --git a/buildstream/_platform/darwin.py b/buildstream/_platform/darwin.py index c018c261a74412d9bf33c4bce80cf81d6929c506..83643541960cd1c1b558ebd986b69ef897f74ce4 100644 --- a/buildstream/_platform/darwin.py +++ b/buildstream/_platform/darwin.py @@ -19,7 +19,7 @@ import os import resource from .._exceptions import PlatformError -from ..sandbox import SandboxChroot +from ..sandbox import SandboxChroot, DummySandbox from . import Platform @@ -38,7 +38,7 @@ class Darwin(Platform): return self._artifact_cache def create_sandbox(self, *args, **kwargs): - return SandboxChroot(*args, **kwargs) + return DummySandbox(*args, **kwargs) def get_cpu_count(self, cap=None): if cap < os.cpu_count(): diff --git a/buildstream/_platform/linux.py b/buildstream/_platform/linux.py index 8a7238e39898d10ab832aafd17c4202d0e0450e0..7fc4aee9b3350f04bfe3486a7008bed3f09c7e86 100644 --- a/buildstream/_platform/linux.py +++ b/buildstream/_platform/linux.py @@ -24,7 +24,7 @@ from .. import _site from .. import utils from .._artifactcache.cascache import CASCache from .._message import Message, MessageType -from ..sandbox import SandboxBwrap +from ..sandbox import SandboxBwrap, DummySandbox from . import Platform @@ -48,10 +48,13 @@ class Linux(Platform): return self._artifact_cache def create_sandbox(self, *args, **kwargs): - # Inform the bubblewrap sandbox as to whether it can use user namespaces or not - kwargs['user_ns_available'] = self._user_ns_available - kwargs['die_with_parent_available'] = self._die_with_parent_available - return SandboxBwrap(*args, **kwargs) + if not self._local_sandbox_available(): + return DummySandbox(*args, **kwargs) + else: + # Inform the bubblewrap sandbox as to whether it can use user namespaces or not + kwargs['user_ns_available'] = self._user_ns_available + kwargs['die_with_parent_available'] = self._die_with_parent_available + return SandboxBwrap(*args, **kwargs) ################################################ # Private Methods # diff --git a/buildstream/_platform/platform.py b/buildstream/_platform/platform.py index c178a8fcf8cc9df56248c086d268744700ef4bcc..5674bd6ad53036cdb8df847a7788ccf5b51be4f9 100644 --- a/buildstream/_platform/platform.py +++ b/buildstream/_platform/platform.py @@ -54,6 +54,8 @@ class Platform(): backend = 'linux' elif sys.platform.startswith('darwin'): backend = 'darwin' + elif not (os.path.exists(utils.get_host_tool('bwrap')) and os.path.exists('/dev/fuse')): + backend = 'no_local' else: backend = 'unix' diff --git a/buildstream/sandbox/__init__.py b/buildstream/sandbox/__init__.py index 2c76e9e8e42c9b38743782e8ec2b93936bf897fc..421b83586ac95325a2cc034d5d35643a3b3dbe41 100644 --- a/buildstream/sandbox/__init__.py +++ b/buildstream/sandbox/__init__.py @@ -21,3 +21,4 @@ from .sandbox import Sandbox, SandboxFlags from ._sandboxchroot import SandboxChroot from ._sandboxbwrap import SandboxBwrap from ._sandboxremote import SandboxRemote +from ._dummysandbox import DummySandbox diff --git a/buildstream/sandbox/_dummysandbox.py b/buildstream/sandbox/_dummysandbox.py new file mode 100644 index 0000000000000000000000000000000000000000..61723d5129f9071feddbfe9c21b74ce1e4ff71a6 --- /dev/null +++ b/buildstream/sandbox/_dummysandbox.py @@ -0,0 +1,58 @@ +# +# Copyright (C) 2017 Codethink Limited +# +# 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/>. +# +# Authors: + +from .._exceptions import SandboxError +from . import Sandbox + + +class DummySandbox(Sandbox): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + uid = self._get_config().build_uid + gid = self._get_config().build_gid + if uid != 0 or gid != 0: + raise SandboxError("Chroot sandboxes cannot specify a non-root uid/gid " + "({},{} were supplied via config)".format(uid, gid)) + + self.mount_map = None + + def run(self, command, flags, *, cwd=None, env=None): + + # Default settings + if cwd is None: + cwd = self._get_work_directory() + + if cwd is None: + cwd = '/' + + if env is None: + env = self._get_environment() + + # Naive getcwd implementations can break when bind-mounts to different + # paths on the same filesystem are present. Letting the command know + # what directory it is in makes it unnecessary to call the faulty + # getcwd. + env['PWD'] = cwd + + if not self._has_command(command[0], env): + raise SandboxError("Staged artifacts do not provide command " + "'{}'".format(command[0]), + reason='missing-command') + + raise SandboxError("This platform does not support local builds")