You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2017/11/29 03:35:12 UTC
[5/9] mesos git commit: Added ContainerMountInfo to avoid
pre_exec_commands for mounts.
Added ContainerMountInfo to avoid pre_exec_commands for mounts.
Added ContainerMountInfo protobuf in ContainerLaunchInfo. It is used
by isolators and MesosContainerizer to describe mounts. Previously,
the additional mounts for each container is specified using
'pre_exec_commands', which is not very flexible and slow (requires a
fork/exec for each mount).
Review: https://reviews.apache.org/r/63200
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/93ecd696
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/93ecd696
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/93ecd696
Branch: refs/heads/master
Commit: 93ecd69655f06ce2420a499d9f9050cc7592d1c3
Parents: c7304a1
Author: Jie Yu <yu...@gmail.com>
Authored: Mon Sep 4 08:30:07 2017 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Tue Nov 28 18:45:38 2017 -0800
----------------------------------------------------------------------
include/mesos/slave/containerizer.proto | 28 ++++++
.../mesos/isolators/docker/volume/isolator.cpp | 19 ++---
.../mesos/isolators/filesystem/linux.cpp | 90 +++++---------------
.../mesos/isolators/filesystem/linux.hpp | 4 -
.../mesos/isolators/filesystem/shared.cpp | 9 +-
.../mesos/isolators/gpu/isolator.cpp | 15 +++-
.../mesos/isolators/namespaces/pid.cpp | 14 +--
.../mesos/isolators/volume/host_path.cpp | 17 ++--
.../mesos/isolators/volume/image.cpp | 15 ++--
.../mesos/isolators/volume/sandbox_path.cpp | 23 +++--
src/slave/containerizer/mesos/launch.cpp | 20 +++++
11 files changed, 133 insertions(+), 121 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/include/mesos/slave/containerizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/slave/containerizer.proto b/include/mesos/slave/containerizer.proto
index 0f1e1da..5b4dcdd 100644
--- a/include/mesos/slave/containerizer.proto
+++ b/include/mesos/slave/containerizer.proto
@@ -167,6 +167,30 @@ message ContainerConfig {
/**
+ * Describes a single mount for the container.
+ */
+message ContainerMountInfo {
+ // The path to the mount point. It must be an absolute path in the
+ // agent's root filesystem.
+ required string target = 1;
+
+ // The source of the mount. This can be the path to a device, a file
+ // or a directory. The path must be an absolute path in the agent's
+ // root filesystem.
+ optional string source = 2;
+
+ // The type of the filesystem to be mounted.
+ optional string type = 3;
+
+ // Mount flags.
+ optional uint32 flags = 4;
+
+ // Mount options of the filesystem to be used.
+ optional string options = 5;
+}
+
+
+/**
* Protobuf returned by Isolator::prepare(). The command is executed
* by the Launcher in the containerized context.
* Note: Currently, any URIs or Environment in the CommandInfo will be
@@ -210,6 +234,10 @@ message ContainerLaunchInfo {
// from the task working directory when task defines an image.
optional string working_directory = 6;
+ // The additional mounts for the container. The mounts specified in
+ // this list will be mounted in order.
+ repeated ContainerMountInfo mounts = 17;
+
// (Linux only) The capabilities requested for the container.
// The capabilities are set while launching the container.
optional CapabilityInfo effective_capabilities = 7;
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp b/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
index ed65568..3e85afb 100644
--- a/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
+++ b/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
@@ -14,6 +14,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <sys/mount.h>
+
#include <process/collect.hpp>
#include <process/id.hpp>
@@ -40,6 +42,7 @@ using mesos::internal::slave::docker::volume::DriverClient;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerLimitation;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::ContainerState;
using mesos::slave::Isolator;
@@ -493,18 +496,10 @@ Future<Option<ContainerLaunchInfo>> DockerVolumeIsolatorProcess::_prepare(
LOG(INFO) << "Mounting docker volume mount point '" << source
<< "' to '" << target << "' for container " << containerId;
- // Launch mount command as a non-shell subprocess to avoid
- // injecting arbitrary shell commands (e.g., user defined
- // 'container_path' in volume can be postfixed with any
- // unsafe arbitrary commands).
- CommandInfo* command = launchInfo.add_pre_exec_commands();
- command->set_shell(false);
- command->set_value("mount");
- command->add_arguments("mount");
- command->add_arguments("-n");
- command->add_arguments("--rbind");
- command->add_arguments(source);
- command->add_arguments(target);
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_source(source);
+ mount->set_target(target);
+ mount->set_flags(MS_BIND | MS_REC);
}
return launchInfo;
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
index faf9490..d97f427 100644
--- a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
+++ b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
@@ -14,6 +14,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <sys/mount.h>
+
#include <list>
#include <sstream>
#include <string>
@@ -58,6 +60,7 @@ using mesos::slave::ContainerConfig;
using mesos::slave::ContainerState;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerLimitation;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::Isolator;
namespace mesos {
@@ -347,66 +350,15 @@ Future<Option<ContainerLaunchInfo>> LinuxFilesystemIsolatorProcess::prepare(
ContainerLaunchInfo launchInfo;
launchInfo.add_clone_namespaces(CLONE_NEWNS);
- // Prepare the commands that will be run in the container's mount
- // namespace right after forking the executor process. We use these
- // commands to mount those volumes specified in the container info
- // so that they don't pollute the host mount namespace.
- Try<vector<CommandInfo>> commands =
- getPreExecCommands(containerId, containerConfig);
-
- if (commands.isError()) {
- return Failure("Failed to get pre-exec commands: " + commands.error());
- }
-
- foreach (const CommandInfo& command, commands.get()) {
- launchInfo.add_pre_exec_commands()->CopyFrom(command);
- }
-
- // Currently, we only need to update resources for top level containers.
- if (containerId.has_parent()) {
- return launchInfo;
- }
-
- return update(containerId, containerConfig.executor_info().resources())
- .then([launchInfo]() -> Future<Option<ContainerLaunchInfo>> {
- return launchInfo;
- });
-}
-
-
-Try<vector<CommandInfo>> LinuxFilesystemIsolatorProcess::getPreExecCommands(
- const ContainerID& containerId,
- const ContainerConfig& containerConfig)
-{
- vector<CommandInfo> commands;
+ // Prepare the mounts that will be run in the container's mount
+ // namespace right after forking the executor process so that they
+ // don't pollute the host mount namespace.
// Make sure mounts in the container mount namespace do not
// propagate back to the host mount namespace.
- // NOTE: We cannot simply run `mount --make-rslave /`, for more info
- // please refer to comments in mount.hpp.
- CommandInfo command;
- command.set_shell(false);
- command.set_value(path::join(flags.launcher_dir, "mesos-containerizer"));
- command.add_arguments("mesos-containerizer");
- command.add_arguments(MesosContainerizerMount::NAME);
-
- MesosContainerizerMount::Flags mountFlags;
- mountFlags.operation = MesosContainerizerMount::MAKE_RSLAVE;
- mountFlags.path = "/";
-
- foreachvalue (const flags::Flag& flag, mountFlags) {
- const Option<string> value = flag.stringify(mountFlags);
- if (value.isSome()) {
- command.add_arguments(
- "--" + flag.effective_name().value + "=" + value.get());
- }
- }
-
- commands.push_back(command);
-
- if (!containerConfig.has_container_info()) {
- return commands;
- }
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_target("/");
+ mount->set_flags(MS_SLAVE | MS_REC);
// Bind mount the sandbox if the container specifies a rootfs.
if (containerConfig.has_rootfs()) {
@@ -419,24 +371,26 @@ Try<vector<CommandInfo>> LinuxFilesystemIsolatorProcess::getPreExecCommands(
// comments in 'provisioner/backend.hpp' for details.
Try<Nothing> mkdir = os::mkdir(sandbox);
if (mkdir.isError()) {
- return Error(
+ return Failure(
"Failed to create sandbox mount point at '" +
sandbox + "': " + mkdir.error());
}
- CommandInfo command;
- command.set_shell(false);
- command.set_value("mount");
- command.add_arguments("mount");
- command.add_arguments("-n");
- command.add_arguments("--rbind");
- command.add_arguments(containerConfig.directory());
- command.add_arguments(sandbox);
+ mount = launchInfo.add_mounts();
+ mount->set_source(containerConfig.directory());
+ mount->set_target(sandbox);
+ mount->set_flags(MS_BIND | MS_REC);
+ }
- commands.push_back(command);
+ // Currently, we only need to update resources for top level containers.
+ if (containerId.has_parent()) {
+ return launchInfo;
}
- return commands;
+ return update(containerId, containerConfig.executor_info().resources())
+ .then([launchInfo]() -> Future<Option<ContainerLaunchInfo>> {
+ return launchInfo;
+ });
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/filesystem/linux.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/filesystem/linux.hpp b/src/slave/containerizer/mesos/isolators/filesystem/linux.hpp
index c7fbda5..6584d1e 100644
--- a/src/slave/containerizer/mesos/isolators/filesystem/linux.hpp
+++ b/src/slave/containerizer/mesos/isolators/filesystem/linux.hpp
@@ -66,10 +66,6 @@ public:
private:
LinuxFilesystemIsolatorProcess(const Flags& flags);
- Try<std::vector<CommandInfo>> getPreExecCommands(
- const ContainerID& containerId,
- const mesos::slave::ContainerConfig& containerConfig);
-
const Flags flags;
struct Info
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp b/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
index ccd3da2..118f398 100644
--- a/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
+++ b/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
@@ -14,6 +14,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <sys/mount.h>
+
#include <set>
#include <process/id.hpp>
@@ -35,6 +37,7 @@ using std::string;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerLimitation;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::ContainerState;
using mesos::slave::Isolator;
@@ -209,8 +212,10 @@ Future<Option<ContainerLaunchInfo>> SharedFilesystemIsolatorProcess::prepare(
}
}
- launchInfo.add_pre_exec_commands()->set_value(
- "mount -n --bind " + hostPath + " " + volume.container_path());
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_source(hostPath);
+ mount->set_target(volume.container_path());
+ mount->set_flags(MS_BIND | MS_REC);
}
return launchInfo;
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
index 4d6f640..7b66426 100644
--- a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
+++ b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
@@ -16,6 +16,8 @@
#include <stdint.h>
+#include <sys/mount.h>
+
// This header include must be enclosed in an `extern "C"` block to
// workaround a bug in glibc <= 2.12 (see MESOS-7378).
//
@@ -65,6 +67,7 @@ using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerLimitation;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::ContainerState;
using mesos::slave::Isolator;
@@ -400,9 +403,15 @@ Future<Option<ContainerLaunchInfo>> NvidiaGpuIsolatorProcess::_prepare(
" '" + target + "': " + mkdir.error());
}
- launchInfo.add_pre_exec_commands()->set_value(
- "mount --no-mtab --rbind --read-only " +
- volume.HOST_PATH() + " " + target);
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_source(volume.HOST_PATH());
+ mount->set_target(target);
+ mount->set_flags(MS_RDONLY | MS_BIND | MS_REC);
+
+ // NOTE: MS_REMOUNT is needed to make a bind mount read only.
+ mount = launchInfo.add_mounts();
+ mount->set_target(target);
+ mount->set_flags(MS_RDONLY | MS_REMOUNT | MS_BIND | MS_REC);
}
return launchInfo;
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
index 42bc2e1..4f8253b 100644
--- a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
+++ b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
@@ -14,6 +14,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <sys/mount.h>
+
#include <process/id.hpp>
#include <stout/strings.hpp>
@@ -29,6 +31,7 @@ using process::Owned;
using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::Isolator;
namespace mesos {
@@ -121,17 +124,18 @@ Future<Option<ContainerLaunchInfo>> NamespacesPidIsolatorProcess::prepare(
// Mount /proc with standard options for the container's pid
// namespace to show the container's pids (and other /proc files),
// not the parent's. This technique was taken from unshare.c in
- // utils-linux for --mount-proc. We use the -n flag so the mount is
- // not added to the mtab where it will not be correctly removed when
- // the namespace terminates.
+ // utils-linux for --mount-proc.
//
// NOTE: 'filesystem/linux' isolator will make sure mounts in the
// child mount namespace will not be propagated back to the host
// mount namespace.
//
// TOOD(jieyu): Consider unmount the existing /proc.
- launchInfo.add_pre_exec_commands()->set_value(
- "mount -n -t proc proc /proc -o nosuid,noexec,nodev");
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_source("proc");
+ mount->set_target("/proc");
+ mount->set_type("proc");
+ mount->set_flags(MS_NOSUID | MS_NODEV | MS_NOEXEC);
return launchInfo;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/volume/host_path.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/host_path.cpp b/src/slave/containerizer/mesos/isolators/volume/host_path.cpp
index 949510a..241a7f6 100644
--- a/src/slave/containerizer/mesos/isolators/volume/host_path.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/host_path.cpp
@@ -14,6 +14,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <sys/mount.h>
+
#include <glog/logging.h>
#include <process/id.hpp>
@@ -41,6 +43,7 @@ using process::Owned;
using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::Isolator;
namespace mesos {
@@ -241,16 +244,10 @@ Future<Option<ContainerLaunchInfo>> VolumeHostPathIsolatorProcess::prepare(
}
// TODO(jieyu): Consider the mode in the volume.
- CommandInfo command;
- command.set_shell(false);
- command.set_value("mount");
- command.add_arguments("mount");
- command.add_arguments("-n");
- command.add_arguments("--rbind");
- command.add_arguments(hostPath.get());
- command.add_arguments(mountPoint);
-
- launchInfo.add_pre_exec_commands()->CopyFrom(command);
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_source(hostPath.get());
+ mount->set_target(mountPoint);
+ mount->set_flags(MS_BIND | MS_REC);
}
return launchInfo;
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/volume/image.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/image.cpp b/src/slave/containerizer/mesos/isolators/volume/image.cpp
index 35966aa..15e242d 100644
--- a/src/slave/containerizer/mesos/isolators/volume/image.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/image.cpp
@@ -14,6 +14,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <sys/mount.h>
+
#include <list>
#include <string>
#include <vector>
@@ -49,6 +51,7 @@ using process::Shared;
using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::Isolator;
namespace mesos {
@@ -229,14 +232,10 @@ Future<Option<ContainerLaunchInfo>> VolumeImageIsolatorProcess::_prepare(
"Provisioned rootfs '" + source + "' does not exist");
}
- CommandInfo* command = launchInfo.add_pre_exec_commands();
- command->set_shell(false);
- command->set_value("mount");
- command->add_arguments("mount");
- command->add_arguments("-n");
- command->add_arguments("--rbind");
- command->add_arguments(source);
- command->add_arguments(target);
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_source(source);
+ mount->set_target(target);
+ mount->set_flags(MS_BIND | MS_REC);
}
return launchInfo;
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
index ee5ea3d..d8e41c4 100644
--- a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
@@ -14,6 +14,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <sys/mount.h>
+
#include <glog/logging.h>
#include <process/future.hpp>
@@ -33,6 +35,10 @@
#include "common/validation.hpp"
+#ifdef __linux__
+#include "linux/fs.hpp"
+#endif // __linux__
+
#include "slave/containerizer/mesos/isolators/volume/sandbox_path.hpp"
using std::list;
@@ -46,6 +52,7 @@ using process::Owned;
using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::ContainerMountInfo;
using mesos::slave::ContainerState;
using mesos::slave::Isolator;
@@ -357,24 +364,22 @@ Future<Option<ContainerLaunchInfo>> VolumeSandboxPathIsolatorProcess::prepare(
}
if (bindMountSupported) {
+#ifdef __linux__
LOG(INFO) << "Mounting SANDBOX_PATH volume from "
<< "'" << source << "' to '" << target << "' "
<< "for container " << containerId;
- CommandInfo* command = launchInfo.add_pre_exec_commands();
- command->set_shell(false);
- command->set_value("mount");
- command->add_arguments("mount");
- command->add_arguments("-n");
- command->add_arguments("--rbind");
- command->add_arguments(source);
- command->add_arguments(target);
+ ContainerMountInfo* mount = launchInfo.add_mounts();
+ mount->set_source(source);
+ mount->set_target(target);
+ mount->set_flags(MS_BIND | MS_REC);
+#endif // __linux__
} else {
LOG(INFO) << "Linking SANDBOX_PATH volume from "
<< "'" << source << "' to '" << target << "' "
<< "for container " << containerId;
- Try<Nothing> symlink = fs::symlink(source, target);
+ Try<Nothing> symlink = ::fs::symlink(source, target);
if (symlink.isError()) {
return Failure(
"Failed to symlink '" + source + "' -> '" + target + "'"
http://git-wip-us.apache.org/repos/asf/mesos/blob/93ecd696/src/slave/containerizer/mesos/launch.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.cpp b/src/slave/containerizer/mesos/launch.cpp
index b1584ff..e61c185 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -73,6 +73,7 @@ using mesos::internal::capabilities::ProcessCapabilities;
#endif // __linux__
using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::ContainerMountInfo;
namespace mesos {
namespace internal {
@@ -421,6 +422,25 @@ int MesosContainerizerLaunch::execute()
}
#endif // __WINDOWS__
+#ifdef __linux__
+ foreach (const ContainerMountInfo& mount, launchInfo.mounts()) {
+ Try<Nothing> mnt = fs::mount(
+ (mount.has_source() ? Option<string>(mount.source()) : None()),
+ mount.target(),
+ (mount.has_type() ? Option<string>(mount.type()) : None()),
+ (mount.has_flags() ? mount.flags() : 0),
+ (mount.has_options() ? Option<string>(mount.options()) : None()));
+
+ if (mnt.isError()) {
+ cerr << "Failed to prepare mount '" << JSON::protobuf(mount)
+ << "': " << mnt.error() << endl;
+ exitWithStatus(EXIT_FAILURE);
+ }
+
+ cout << "Prepared mount '" << JSON::protobuf(mount) << "'" << endl;
+ }
+#endif // __linux__
+
// Run additional preparation commands. These are run as the same
// user and with the environment as the agent.
foreach (const CommandInfo& command, launchInfo.pre_exec_commands()) {