summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2017-11-06 18:49:58 +0900
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2017-11-06 20:31:08 +0900
commit69cc9ef00b957a202a80c7690f7ee3e5ad8b8eda (patch)
tree795b7a254425c1aa7950240408380ba6fa78d75e
parente2959c27382464f1b5ba37f6ea6db14f21d71b72 (diff)
downloadbuildstream-69cc9ef00b957a202a80c7690f7ee3e5ad8b8eda.tar.gz
sandbox: Refactoring, moving accidentally public MountMap into it's own file
-rw-r--r--buildstream/sandbox/__init__.py2
-rw-r--r--buildstream/sandbox/_mount.py127
-rw-r--r--buildstream/sandbox/_sandboxbwrap.py3
-rw-r--r--buildstream/sandbox/_sandboxchroot.py9
-rw-r--r--buildstream/sandbox/sandbox.py106
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()