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 2016/09/27 22:38:46 UTC
[2/2] mesos git commit: Added 'volume/sandbox_path' isolator.
Added 'volume/sandbox_path' isolator.
Review: https://reviews.apache.org/r/52285
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/dc47b380
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/dc47b380
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/dc47b380
Branch: refs/heads/master
Commit: dc47b3805629fe1778e444ce3fb518b0cd1517e8
Parents: 288134f
Author: Jie Yu <yu...@gmail.com>
Authored: Mon Sep 26 16:06:02 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Tue Sep 27 15:38:29 2016 -0700
----------------------------------------------------------------------
src/CMakeLists.txt | 1 +
src/Makefile.am | 2 +
src/slave/containerizer/mesos/containerizer.cpp | 4 +
.../mesos/isolators/volume/sandbox_path.cpp | 260 +++++++++++++++++++
.../mesos/isolators/volume/sandbox_path.hpp | 62 +++++
5 files changed, 329 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/dc47b380/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 981b36e..35eb63f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -357,6 +357,7 @@ if (NOT WIN32)
slave/containerizer/mesos/isolators/docker/volume/paths.cpp
slave/containerizer/mesos/isolators/network/cni/paths.cpp
slave/containerizer/mesos/isolators/network/cni/spec.cpp
+ slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
)
endif (NOT WIN32)
http://git-wip-us.apache.org/repos/asf/mesos/blob/dc47b380/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 410b5f2..0fa85b6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -834,6 +834,7 @@ libmesos_no_3rdparty_la_SOURCES += \
slave/containerizer/mesos/isolators/network/cni/paths.cpp \
slave/containerizer/mesos/isolators/network/cni/spec.cpp \
slave/containerizer/mesos/isolators/posix/disk.cpp \
+ slave/containerizer/mesos/isolators/volume/sandbox_path.cpp \
slave/containerizer/mesos/provisioner/backend.cpp \
slave/containerizer/mesos/provisioner/paths.cpp \
slave/containerizer/mesos/provisioner/provisioner.cpp \
@@ -964,6 +965,7 @@ libmesos_no_3rdparty_la_SOURCES += \
slave/containerizer/mesos/isolators/network/cni/paths.hpp \
slave/containerizer/mesos/isolators/network/cni/spec.hpp \
slave/containerizer/mesos/isolators/network/cni/spec.hpp \
+ slave/containerizer/mesos/isolators/volume/sandbox_path.hpp \
slave/containerizer/mesos/isolators/windows.hpp \
slave/containerizer/mesos/provisioner/backend.hpp \
slave/containerizer/mesos/provisioner/paths.hpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/dc47b380/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index ac2823f..014f3bd 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -113,6 +113,8 @@
#include "slave/containerizer/mesos/isolators/volume/image.hpp"
#endif
+#include "slave/containerizer/mesos/isolators/volume/sandbox_path.hpp"
+
#include "slave/containerizer/mesos/constants.hpp"
#include "slave/containerizer/mesos/containerizer.hpp"
#include "slave/containerizer/mesos/launch.hpp"
@@ -309,6 +311,7 @@ Try<MesosContainerizer*> MesosContainerizer::create(
// "posix/disk" is deprecated in favor of the name "disk/du".
{"posix/disk", &PosixDiskIsolatorProcess::create},
{"disk/du", &PosixDiskIsolatorProcess::create},
+ {"volume/sandbox_path", &VolumeSandboxPathIsolatorProcess::create},
#if ENABLE_XFS_DISK_ISOLATOR
{"disk/xfs", &XfsDiskIsolatorProcess::create},
@@ -316,6 +319,7 @@ Try<MesosContainerizer*> MesosContainerizer::create(
#else
{"windows/cpu", &WindowsCpuIsolatorProcess::create},
#endif // __WINDOWS__
+
#ifdef __linux__
{"cgroups/cpu", &CgroupsIsolatorProcess::create},
{"cgroups/devices", &CgroupsIsolatorProcess::create},
http://git-wip-us.apache.org/repos/asf/mesos/blob/dc47b380/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
new file mode 100644
index 0000000..7b5edf0
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
@@ -0,0 +1,260 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stout/foreach.hpp>
+#include <stout/fs.hpp>
+#include <stout/stringify.hpp>
+#include <stout/strings.hpp>
+
+#include <stout/os/mkdir.hpp>
+
+#ifdef __linux__
+#include "linux/ns.hpp"
+#endif // __linux__
+
+#include "slave/containerizer/mesos/isolators/volume/sandbox_path.hpp"
+
+using std::list;
+using std::string;
+
+using process::Failure;
+using process::Future;
+using process::Owned;
+
+using mesos::slave::ContainerConfig;
+using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::ContainerState;
+using mesos::slave::Isolator;
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+Try<Isolator*> VolumeSandboxPathIsolatorProcess::create(
+ const Flags& flags)
+{
+ bool bindMountSupported = false;
+
+ if (flags.launcher == "linux" &&
+ strings::contains(flags.isolation, "filesystem/linux")) {
+ bindMountSupported = true;
+ }
+
+ Owned<MesosIsolatorProcess> process(
+ new VolumeSandboxPathIsolatorProcess(flags, bindMountSupported));
+
+ return new MesosIsolator(process);
+}
+
+
+VolumeSandboxPathIsolatorProcess::VolumeSandboxPathIsolatorProcess(
+ const Flags& _flags,
+ bool _bindMountSupported)
+ : ProcessBase(process::ID::generate("volume-sandbox-path-isolator")),
+ flags(_flags),
+ bindMountSupported(_bindMountSupported) {}
+
+
+VolumeSandboxPathIsolatorProcess::~VolumeSandboxPathIsolatorProcess() {}
+
+
+Future<Nothing> VolumeSandboxPathIsolatorProcess::recover(
+ const list<ContainerState>& states,
+ const hashset<ContainerID>& orphans)
+{
+ foreach (const ContainerState& state, states) {
+ sandboxes[state.container_id()] = state.directory();
+ }
+
+ return Nothing();
+}
+
+
+Future<Option<ContainerLaunchInfo>> VolumeSandboxPathIsolatorProcess::prepare(
+ const ContainerID& containerId,
+ const ContainerConfig& containerConfig)
+{
+ // Remember the sandbox location for each container (including
+ // nested). This information is important for looking up sandbox
+ // locations for parent containers.
+ sandboxes[containerId] = containerConfig.directory();
+
+ if (!containerConfig.has_container_info()) {
+ return None();
+ }
+
+ const ContainerInfo& containerInfo = containerConfig.container_info();
+
+ if (containerInfo.type() != ContainerInfo::MESOS) {
+ return Failure(
+ "Can only prepare the sandbox volume isolator "
+ "for a MESOS container");
+ }
+
+ if (!bindMountSupported && containerConfig.has_rootfs()) {
+ return Failure(
+ "The 'linux' launcher and 'filesystem/linux' isolator must be "
+ "enabled to change the rootfs and bind mount");
+ }
+
+ ContainerLaunchInfo launchInfo;
+
+#ifdef __linux__
+ if (bindMountSupported) {
+ launchInfo.set_namespaces(CLONE_NEWNS);
+ }
+#endif // __linux__
+
+ foreach (const Volume& volume, containerInfo.volumes()) {
+ if (!volume.has_source() ||
+ !volume.source().has_type() ||
+ volume.source().type() != Volume::Source::SANDBOX_PATH) {
+ continue;
+ }
+
+ if (!volume.source().has_sandbox_path()) {
+ return Failure("volume.source.sandbox_path is not specified");
+ }
+
+ const Volume::Source::SandboxPath& sandboxPath =
+ volume.source().sandbox_path();
+
+ // TODO(jieyu): Support other type of SANDBOX_PATH (e.g., SELF).
+ if (!sandboxPath.has_type() ||
+ sandboxPath.type() != Volume::Source::SandboxPath::PARENT) {
+ return Failure("Only PARENT sandbox path is supported");
+ }
+
+ if (!containerId.has_parent()) {
+ return Failure("PARENT sandbox path only works for nested container");
+ }
+
+ // TODO(jieyu): Validate sandboxPath.path for other invalid chars.
+ if (strings::contains(sandboxPath.path(), ".") ||
+ strings::contains(sandboxPath.path(), " ")) {
+ return Failure("Invalid char found in volume.source.sandbox_path.path");
+ }
+
+ if (!sandboxes.contains(containerId.parent())) {
+ return Failure("Failed to locate the sandbox for the parent container");
+ }
+
+ // Prepare the source.
+ const string source = path::join(
+ sandboxes[containerId.parent()],
+ sandboxPath.path());
+
+ Try<Nothing> mkdir = os::mkdir(source);
+ if (mkdir.isError()) {
+ return Failure(
+ "Failed to create the directory in the parent sandbox: " +
+ mkdir.error());
+ }
+
+ // Prepare the target.
+ string target;
+
+ if (path::absolute(volume.container_path())) {
+ if (!bindMountSupported) {
+ return Failure(
+ "The 'linux' launcher and 'filesystem/linux' isolator must be "
+ "enabled to support absolute container path");
+ }
+
+ if (containerConfig.has_rootfs()) {
+ target = path::join(
+ containerConfig.rootfs(),
+ volume.container_path());
+
+ Try<Nothing> mkdir = os::mkdir(target);
+ if (mkdir.isError()) {
+ return Failure(
+ "Failed to create the target of the mount at '" +
+ target + "': " + mkdir.error());
+ }
+ } else {
+ target = volume.container_path();
+
+ if (!os::exists(target)) {
+ return Failure(
+ "Absolute container path '" + target + "' "
+ "does not exist");
+ }
+ }
+ } else {
+ if (containerConfig.has_rootfs()) {
+ target = path::join(
+ containerConfig.rootfs(),
+ flags.sandbox_directory,
+ volume.container_path());
+ } else {
+ target = path::join(
+ containerConfig.directory(),
+ volume.container_path());
+ }
+
+ // Create the mount point if bind mount is used.
+ // NOTE: We cannot create the mount point at 'target' if
+ // container has rootfs defined. The bind mount of the sandbox
+ // will hide what's inside 'target'. So we should always create
+ // the mount point in the sandbox.
+ if (bindMountSupported) {
+ const string mountPoint = path::join(
+ containerConfig.directory(),
+ volume.container_path());
+
+ Try<Nothing> mkdir = os::mkdir(mountPoint);
+ if (mkdir.isError()) {
+ return Failure(
+ "Failed to create the target of the mount at '" +
+ mountPoint + "': " + mkdir.error());
+ }
+ }
+ }
+
+ if (bindMountSupported) {
+ 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);
+ } else {
+ LOG(INFO) << "Linking SANDBOX_PATH volume from "
+ << "'" << source << "' to '" << target << "' "
+ << "for container " << containerId;
+
+ Try<Nothing> symlink = fs::symlink(source, target);
+ if (symlink.isError()) {
+ return Failure(
+ "Failed to symlink '" + source + "' -> '" + target + "'"
+ ": " + symlink.error());
+ }
+ }
+ }
+
+ return launchInfo;
+}
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/dc47b380/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp
new file mode 100644
index 0000000..bc933c9
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __VOLUME_SANDBOX_PATH_ISOLATOR_HPP__
+#define __VOLUME_SANDBOX_PATH_ISOLATOR_HPP__
+
+#include <string>
+
+#include <stout/hashmap.hpp>
+
+#include "slave/flags.hpp"
+
+#include "slave/containerizer/mesos/isolator.hpp"
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+class VolumeSandboxPathIsolatorProcess : public MesosIsolatorProcess
+{
+public:
+ static Try<mesos::slave::Isolator*> create(const Flags& flags);
+
+ virtual ~VolumeSandboxPathIsolatorProcess();
+
+ virtual process::Future<Nothing> recover(
+ const std::list<mesos::slave::ContainerState>& states,
+ const hashset<ContainerID>& orphans);
+
+ virtual process::Future<Option<mesos::slave::ContainerLaunchInfo>> prepare(
+ const ContainerID& containerId,
+ const mesos::slave::ContainerConfig& containerConfig);
+
+private:
+ VolumeSandboxPathIsolatorProcess(
+ const Flags& flags,
+ bool bindMountSupported);
+
+ const Flags flags;
+ const bool bindMountSupported;
+
+ hashmap<ContainerID, std::string> sandboxes;
+};
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __VOLUME_SANDBOX_PATH_ISOLATOR_HPP__