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__