diff options
author | Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> | 2017-11-06 18:49:58 +0900 |
---|---|---|
committer | Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> | 2017-11-06 20:31:08 +0900 |
commit | 69cc9ef00b957a202a80c7690f7ee3e5ad8b8eda (patch) | |
tree | 795b7a254425c1aa7950240408380ba6fa78d75e /buildstream/sandbox | |
parent | e2959c27382464f1b5ba37f6ea6db14f21d71b72 (diff) | |
download | buildstream-69cc9ef00b957a202a80c7690f7ee3e5ad8b8eda.tar.gz |
sandbox: Refactoring, moving accidentally public MountMap into it's own file
Diffstat (limited to 'buildstream/sandbox')
-rw-r--r-- | buildstream/sandbox/__init__.py | 2 | ||||
-rw-r--r-- | buildstream/sandbox/_mount.py | 127 | ||||
-rw-r--r-- | buildstream/sandbox/_sandboxbwrap.py | 3 | ||||
-rw-r--r-- | buildstream/sandbox/_sandboxchroot.py | 9 | ||||
-rw-r--r-- | buildstream/sandbox/sandbox.py | 106 |
5 files changed, 135 insertions, 112 deletions
diff --git a/buildstream/sandbox/__init__.py b/buildstream/sandbox/__init__.py index c1f38eac4..7ee871cab 100644 --- a/buildstream/sandbox/__init__.py +++ b/buildstream/sandbox/__init__.py @@ -18,6 +18,6 @@ # Authors: # Tristan Maat <tristan.maat@codethink.co.uk> -from .sandbox import Sandbox, SandboxFlags, Mount, MountMap +from .sandbox import Sandbox, SandboxFlags from ._sandboxchroot import SandboxChroot from ._sandboxbwrap import SandboxBwrap diff --git a/buildstream/sandbox/_mount.py b/buildstream/sandbox/_mount.py new file mode 100644 index 000000000..a4f82575e --- /dev/null +++ b/buildstream/sandbox/_mount.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# +# 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: +# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> + +import os +from collections import OrderedDict +from contextlib import contextmanager, ExitStack + +from .. import utils +from .._fuse import SafeHardlinks + + +# Mount() +# +# Helper data object representing a single mount point in the mount map +# +class Mount(): + def __init__(self, sandbox, mount_point, safe_hardlinks): + scratch_directory = sandbox._get_scratch_directory() + root_directory = sandbox.get_directory() + + self.mount_point = mount_point + self.safe_hardlinks = safe_hardlinks + + # FIXME: When the criteria for mounting something and it's parent + # mount is identical, then there is no need to mount an additional + # fuse layer (i.e. if the root is read-write and there is a directory + # marked for staged artifacts directly within the rootfs, they can + # safely share the same fuse layer). + # + # In these cases it would be saner to redirect the sub-mount to + # a regular mount point within the parent's redirected mount. + # + if self.safe_hardlinks: + # Redirected mount + self.mount_origin = os.path.join(root_directory, mount_point.lstrip(os.sep)) + self.mount_base = os.path.join(scratch_directory, utils.url_directory_name(mount_point)) + self.mount_source = os.path.join(self.mount_base, 'mount') + self.mount_tempdir = os.path.join(self.mount_base, 'temp') + os.makedirs(self.mount_origin, exist_ok=True) + os.makedirs(self.mount_source, exist_ok=True) + os.makedirs(self.mount_tempdir, exist_ok=True) + else: + # No redirection needed + self.mount_source = os.path.join(root_directory, mount_point.lstrip(os.sep)) + os.makedirs(self.mount_source, exist_ok=True) + + @contextmanager + def mounted(self, sandbox): + if self.safe_hardlinks: + mount = SafeHardlinks(self.mount_origin, self.mount_tempdir) + with mount.mounted(self.mount_source): + yield + else: + # Nothing to mount here + yield + + +# MountMap() +# +# Helper object for mapping of the sandbox mountpoints +# +# Args: +# sandbox (Sandbox): The sandbox object +# root_readonly (bool): Whether the sandbox root is readonly +# +class MountMap(): + + def __init__(self, sandbox, root_readonly): + # 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) + + for mark in sandbox._get_marked_directories(): + directory = mark['directory'] + artifact = mark['artifact'] + + # We want safe hardlinks for any non-root directory where + # artifacts will be staged to + self.mounts[directory] = Mount(sandbox, directory, artifact) + + # get_mount_source() + # + # Gets the host directory where the mountpoint in the + # sandbox should be bind mounted from + # + # Args: + # mountpoint (str): The absolute mountpoint path inside the sandbox + # + # Returns: + # The host path to be mounted at the mount point + # + def get_mount_source(self, mountpoint): + return self.mounts[mountpoint].mount_source + + # mounted() + # + # A context manager which ensures all the mount sources + # were mounted with any fuse layers which may have been needed. + # + # Args: + # sandbox (Sandbox): The sandbox + # + @contextmanager + def mounted(self, sandbox): + with ExitStack() as stack: + for mountpoint, mount in self.mounts.items(): + stack.enter_context(mount.mounted(sandbox)) + yield diff --git a/buildstream/sandbox/_sandboxbwrap.py b/buildstream/sandbox/_sandboxbwrap.py index 04f3a4d74..a64dc8092 100644 --- a/buildstream/sandbox/_sandboxbwrap.py +++ b/buildstream/sandbox/_sandboxbwrap.py @@ -29,7 +29,8 @@ from contextlib import ExitStack import psutil from .. import utils, _signals -from . import Sandbox, SandboxFlags, MountMap +from ._mount import MountMap +from . import Sandbox, SandboxFlags # SandboxBwrap() diff --git a/buildstream/sandbox/_sandboxchroot.py b/buildstream/sandbox/_sandboxchroot.py index 26e04e50e..20ead6d84 100644 --- a/buildstream/sandbox/_sandboxchroot.py +++ b/buildstream/sandbox/_sandboxchroot.py @@ -31,7 +31,8 @@ from .._exceptions import SandboxError from .. import utils from .. import _signals from ._mounter import Mounter -from . import Sandbox, SandboxFlags, MountMap +from ._mount import MountMap +from . import Sandbox, SandboxFlags class SandboxChroot(Sandbox): @@ -250,7 +251,7 @@ class SandboxChroot(Sandbox): mount_source = self.mount_map.get_mount_source(point) mount_point = os.path.join(rootfs, point.lstrip(os.sep)) - with Mount.bind_mount(mount_point, src=mount_source, stdout=stdout, stderr=stderr, **kwargs): + with Mounter.bind_mount(mount_point, src=mount_source, stdout=stdout, stderr=stderr, **kwargs): yield @contextmanager @@ -258,7 +259,7 @@ class SandboxChroot(Sandbox): mount_point = os.path.join(rootfs, src.lstrip(os.sep)) os.makedirs(mount_point, exist_ok=True) - with Mount.bind_mount(mount_point, src=src, stdout=stdout, stderr=stderr, **kwargs): + with Mounter.bind_mount(mount_point, src=src, stdout=stdout, stderr=stderr, **kwargs): yield with ExitStack() as stack: @@ -277,7 +278,7 @@ class SandboxChroot(Sandbox): # Remount root RO if necessary if flags & flags & SandboxFlags.ROOT_READ_ONLY: - root_mount = Mount.mount(rootfs, stdout=stdout, stderr=stderr, remount=True, ro=True, bind=True) + root_mount = Mounter.mount(rootfs, stdout=stdout, stderr=stderr, remount=True, ro=True, bind=True) # Since the exit stack has already registered a mount # for this path, we do not need to register another # umount call. diff --git a/buildstream/sandbox/sandbox.py b/buildstream/sandbox/sandbox.py index 0dc9aa2a5..7c4887fe9 100644 --- a/buildstream/sandbox/sandbox.py +++ b/buildstream/sandbox/sandbox.py @@ -29,12 +29,7 @@ conform to this interface. """ import os -from collections import OrderedDict -from contextlib import contextmanager, ExitStack - -from .. import utils from .._exceptions import ImplError -from .._fuse import SafeHardlinks class SandboxFlags(): @@ -65,107 +60,6 @@ class SandboxFlags(): """ -# Mount() -# -# Helper data object representing a single mount point in the mount map -# -class Mount(): - def __init__(self, sandbox, mount_point, safe_hardlinks): - scratch_directory = sandbox._get_scratch_directory() - root_directory = sandbox.get_directory() - - self.mount_point = mount_point - self.safe_hardlinks = safe_hardlinks - - # FIXME: When the criteria for mounting something and it's parent - # mount is identical, then there is no need to mount an additional - # fuse layer (i.e. if the root is read-write and there is a directory - # marked for staged artifacts directly within the rootfs, they can - # safely share the same fuse layer). - # - # In these cases it would be saner to redirect the sub-mount to - # a regular mount point within the parent's redirected mount. - # - if self.safe_hardlinks: - # Redirected mount - self.mount_origin = os.path.join(root_directory, mount_point.lstrip(os.sep)) - self.mount_base = os.path.join(scratch_directory, utils.url_directory_name(mount_point)) - self.mount_source = os.path.join(self.mount_base, 'mount') - self.mount_tempdir = os.path.join(self.mount_base, 'temp') - os.makedirs(self.mount_origin, exist_ok=True) - os.makedirs(self.mount_source, exist_ok=True) - os.makedirs(self.mount_tempdir, exist_ok=True) - else: - # No redirection needed - self.mount_source = os.path.join(root_directory, mount_point.lstrip(os.sep)) - os.makedirs(self.mount_source, exist_ok=True) - - @contextmanager - def mounted(self, sandbox): - if self.safe_hardlinks: - mount = SafeHardlinks(self.mount_origin, self.mount_tempdir) - with mount.mounted(self.mount_source): - yield - else: - # Nothing to mount here - yield - - -# MountMap() -# -# Helper object for mapping of the sandbox mountpoints -# -# Args: -# sandbox (Sandbox): The sandbox object -# root_readonly (bool): Whether the sandbox root is readonly -# -class MountMap(): - - def __init__(self, sandbox, root_readonly): - # 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) - - for mark in sandbox._get_marked_directories(): - directory = mark['directory'] - artifact = mark['artifact'] - - # We want safe hardlinks for any non-root directory where - # artifacts will be staged to - self.mounts[directory] = Mount(sandbox, directory, artifact) - - # get_mount_source() - # - # Gets the host directory where the mountpoint in the - # sandbox should be bind mounted from - # - # Args: - # mountpoint (str): The absolute mountpoint path inside the sandbox - # - # Returns: - # The host path to be mounted at the mount point - # - def get_mount_source(self, mountpoint): - return self.mounts[mountpoint].mount_source - - # mounted() - # - # A context manager which ensures all the mount sources - # were mounted with any fuse layers which may have been needed. - # - # Args: - # sandbox (Sandbox): The sandbox - # - @contextmanager - def mounted(self, sandbox): - with ExitStack() as stack: - for mountpoint, mount in self.mounts.items(): - stack.enter_context(mount.mounted(sandbox)) - yield - - class Sandbox(): """Sandbox() |