Refactor DirectorySandbox to take the Mesos sandbox path
Rather than taking "/path/to/mesos_task_dir/sandbox" as a constructor
argument, the sandbox objects are now passed just "/path/to/mesos_task_dir"
as this simplifies a few operations that need the folder created by
Mesos.
The "sandbox" subfolder is still created with the same name, but this is
now only handled internally. There is no user-visible behaviour change.
diff --git a/src/main/python/apache/aurora/executor/common/sandbox.py b/src/main/python/apache/aurora/executor/common/sandbox.py
index fe1562e..64b7d00 100644
--- a/src/main/python/apache/aurora/executor/common/sandbox.py
+++ b/src/main/python/apache/aurora/executor/common/sandbox.py
@@ -71,34 +71,35 @@
class DefaultSandboxProvider(SandboxProvider):
- SANDBOX_NAME = 'sandbox'
MESOS_DIRECTORY_ENV_VARIABLE = 'MESOS_DIRECTORY'
def from_assigned_task(self, assigned_task, **kwargs):
- sandbox_root = os.path.join(os.environ[self.MESOS_DIRECTORY_ENV_VARIABLE], self.SANDBOX_NAME)
+ mesos_dir = os.environ[self.MESOS_DIRECTORY_ENV_VARIABLE]
container = assigned_task.task.container
if container.docker:
- return DockerDirectorySandbox(sandbox_root, **kwargs)
+ return DockerDirectorySandbox(mesos_dir, **kwargs)
elif container.mesos and container.mesos.image:
return FileSystemImageSandbox(
- sandbox_root,
+ mesos_dir,
user=self._get_sandbox_user(assigned_task),
**kwargs)
else:
- return DirectorySandbox(sandbox_root, user=self._get_sandbox_user(assigned_task), **kwargs)
+ return DirectorySandbox(mesos_dir, user=self._get_sandbox_user(assigned_task), **kwargs)
class DirectorySandbox(SandboxInterface):
""" Basic sandbox implementation using a directory on the filesystem """
- def __init__(self, root, user=getpass.getuser(), **kwargs):
- self._root = root
+ SANDBOX_NAME = 'sandbox'
+
+ def __init__(self, mesos_dir, user=getpass.getuser(), **kwargs):
+ self._mesos_dir = mesos_dir
self._user = user
@property
def root(self):
- return self._root
+ return os.path.join(self._mesos_dir, self.SANDBOX_NAME)
@property
def container_root(self):
@@ -154,26 +155,24 @@
class DockerDirectorySandbox(DirectorySandbox):
""" A sandbox implementation that configures the sandbox correctly for docker containers. """
- def __init__(self, root, **kwargs):
- self._mesos_host_sandbox = os.environ[DefaultSandboxProvider.MESOS_DIRECTORY_ENV_VARIABLE]
-
+ def __init__(self, mesos_dir, **kwargs):
# remove the user value from kwargs if it was set.
kwargs.pop('user', None)
- super(DockerDirectorySandbox, self).__init__(root, user=None, **kwargs)
+ super(DockerDirectorySandbox, self).__init__(mesos_dir, user=None, **kwargs)
def _create_symlinks(self):
# This sets up the container to have a similar directory structure to the host.
- # It takes self._mesos_host_sandbox (e.g. "[exec-root]/runs/RUN1/") and:
+ # It takes self._mesos_dir (e.g. "[exec-root]/runs/RUN1/") and:
# - Sets mesos_host_sandbox_root = "[exec-root]/runs/" (one level up from mesos_host_sandbox)
# - Creates mesos_host_sandbox_root (recursively)
- # - Symlinks _mesos_host_sandbox -> $MESOS_SANDBOX (typically /mnt/mesos/sandbox)
+ # - Symlinks self._mesos_dir -> $MESOS_SANDBOX (typically /mnt/mesos/sandbox)
# $MESOS_SANDBOX is provided in the environment by the Mesos containerizer.
- mesos_host_sandbox_root = os.path.dirname(self._mesos_host_sandbox)
+ mesos_host_sandbox_root = os.path.dirname(self._mesos_dir)
try:
safe_mkdir(mesos_host_sandbox_root)
- os.symlink(os.environ['MESOS_SANDBOX'], self._mesos_host_sandbox)
+ os.symlink(os.environ['MESOS_SANDBOX'], self._mesos_dir)
except (IOError, OSError) as e:
raise self.CreationError('Failed to create the sandbox root: %s' % e)
@@ -195,10 +194,8 @@
# already exists.
_USER_OR_GROUP_NAME_EXISTS = 9
- def __init__(self, root, **kwargs):
- self._task_fs_root = os.path.join(
- os.environ[DefaultSandboxProvider.MESOS_DIRECTORY_ENV_VARIABLE],
- TASK_FILESYSTEM_MOUNT_POINT)
+ def __init__(self, mesos_dir, **kwargs):
+ self._task_fs_root = os.path.join(mesos_dir, TASK_FILESYSTEM_MOUNT_POINT)
self._no_create_user = kwargs.pop('no_create_user', False)
self._mounted_volume_paths = kwargs.pop('mounted_volume_paths', None)
@@ -208,7 +205,7 @@
raise self.Error(
'Failed to initialize FileSystemImageSandbox: no value specified for sandbox_mount_point')
- super(FileSystemImageSandbox, self).__init__(root, **kwargs)
+ super(FileSystemImageSandbox, self).__init__(mesos_dir, **kwargs)
def _verify_group_match_in_taskfs(self, group_id, group_name):
try:
diff --git a/src/test/python/apache/aurora/executor/common/test_sandbox.py b/src/test/python/apache/aurora/executor/common/test_sandbox.py
index 0b4958a..7309b67 100644
--- a/src/test/python/apache/aurora/executor/common/test_sandbox.py
+++ b/src/test/python/apache/aurora/executor/common/test_sandbox.py
@@ -31,6 +31,14 @@
from gen.apache.aurora.api.ttypes import AssignedTask, Container, DockerContainer, TaskConfig
+def test_sandbox_root_path():
+ with temporary_dir() as d:
+ mesos_dir = os.path.join(d, 'task1')
+ ds = DirectorySandbox(mesos_dir)
+
+ assert os.path.join(mesos_dir, DirectorySandbox.SANDBOX_NAME) == ds.root
+
+
def test_directory_sandbox():
with temporary_dir() as d:
ds1 = DirectorySandbox(os.path.join(d, 'task1'))
@@ -55,16 +63,16 @@
getpwnam.return_value.pw_gid = 123
getpwnam.return_value.pw_uid = 456
- with temporary_dir() as d:
- real_path = os.path.join(d, 'sandbox')
- ds = DirectorySandbox(real_path, 'cletus')
+ with temporary_dir() as mesos_dir:
+ ds = DirectorySandbox(mesos_dir, 'cletus')
ds.create()
- assert os.path.exists(real_path)
+ assert os.path.exists(ds.root)
getpwnam.assert_called_with('cletus')
getgrgid.assert_called_with(123)
- chown.assert_called_with(real_path, 456, 123)
- chmod.assert_called_with(real_path, 0700)
+
+ chown.assert_called_with(ds.root, 456, 123)
+ chmod.assert_called_with(ds.root, 0700)
@mock.patch('grp.getgrgid')
@@ -73,10 +81,9 @@
@mock.patch('os.chmod')
def test_create_no_user(*args):
with temporary_dir() as d:
- real_path = os.path.join(d, 'sandbox')
- ds = DirectorySandbox(real_path)
+ ds = DirectorySandbox(d)
ds.create()
- assert os.path.exists(real_path)
+ assert os.path.exists(ds.root)
for mocked in args:
mocked.assert_not_called()
@@ -95,8 +102,7 @@
getpwnam.side_effect = KeyError('johndoe')
with temporary_dir() as d:
- real_path = os.path.join(d, 'sandbox')
- ds = DirectorySandbox(real_path, 'cletus')
+ ds = DirectorySandbox(d, 'cletus')
with pytest.raises(DirectorySandbox.CreationError):
ds.create()
@@ -108,8 +114,7 @@
chown.side_effect = IOError('Disk is borked')
with temporary_dir() as d:
- real_path = os.path.join(d, 'sandbox')
- ds = DirectorySandbox(real_path)
+ ds = DirectorySandbox(d)
with pytest.raises(DirectorySandbox.CreationError):
ds.create()
@@ -123,16 +128,14 @@
'MESOS_SANDBOX': 'some-sandbox'
}):
with temporary_dir() as d:
- real_path = os.path.join(d, 'sandbox')
- ds = DockerDirectorySandbox(real_path)
+ ds = DockerDirectorySandbox(d)
with pytest.raises(DirectorySandbox.CreationError):
ds.create()
def test_destroy_ioerror():
with temporary_dir() as d:
- real_path = os.path.join(d, 'sandbox')
- ds = DirectorySandbox(real_path)
+ ds = DirectorySandbox(d)
ds.create()
with mock.patch('shutil.rmtree') as shutil_rmtree:
@@ -148,10 +151,7 @@
@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
def test_verify_group_match(mock_check_output):
with temporary_dir() as d:
- sandbox = FileSystemImageSandbox(
- os.path.join(d, 'sandbox'),
- user='someuser',
- sandbox_mount_point='/some/path')
+ sandbox = FileSystemImageSandbox(d, user='someuser', sandbox_mount_point='/some/path')
mock_check_output.return_value = 'test-group:x:2:'
@@ -184,9 +184,7 @@
os.makedirs(os.path.join(task_fs_path, 'etc'))
with mock.patch.dict(os.environ, {'MESOS_DIRECTORY': d}):
- sandbox = FileSystemImageSandbox(
- os.path.join(d, 'sandbox'),
- sandbox_mount_point='/some/sandbox/path')
+ sandbox = FileSystemImageSandbox(d, sandbox_mount_point='/some/sandbox/path')
sandbox._copy_files()
@@ -332,7 +330,7 @@
sandbox_directory = os.path.join(MOCK_MESOS_DIRECTORY, 'sandbox')
sandbox = FileSystemImageSandbox(
- sandbox_directory,
+ MOCK_MESOS_DIRECTORY,
user='someuser',
no_create_user=True,
mounted_volume_paths=['/some/container/path', '/some/other/container/path'],
@@ -375,10 +373,10 @@
@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
def test_filesystem_sandbox_no_volumes(mock_safe_mkdir, mock_check_call, mock_isfile):
sandbox_mount_point = '/some/mount/point'
- sandbox_directory = os.path.join(MOCK_MESOS_DIRECTORY, 'sandbox'),
+ sandbox_directory = os.path.join(MOCK_MESOS_DIRECTORY, 'sandbox')
sandbox = FileSystemImageSandbox(
- sandbox_directory,
+ MOCK_MESOS_DIRECTORY,
user='someuser',
no_create_user=True,
mounted_volume_paths=None,
@@ -418,7 +416,7 @@
sandbox_directory = os.path.join(MOCK_MESOS_DIRECTORY, 'sandbox')
sandbox = FileSystemImageSandbox(
- sandbox_directory,
+ MOCK_MESOS_DIRECTORY,
user='someuser',
no_create_user=True,
mounted_volume_paths=['/some/path/to/file', '/some/path/to/directory'],