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/08/22 20:46:38 UTC
[09/12] mesos git commit: Implemented the volume/image isolator.
Implemented the volume/image isolator.
This is a followup patch for r/51141, to move the image volumes
support from the mesos containerizer to the 'volume/image' isolator.
Review: https://reviews.apache.org/r/51172/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/192283f6
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/192283f6
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/192283f6
Branch: refs/heads/master
Commit: 192283f62a12b17108541be17197407470f44567
Parents: 836ad5e
Author: Gilbert Song <so...@gmail.com>
Authored: Mon Aug 22 13:00:37 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Mon Aug 22 13:00:37 2016 -0700
----------------------------------------------------------------------
src/CMakeLists.txt | 1 +
src/Makefile.am | 2 +
.../mesos/isolators/volume/image.cpp | 226 +++++++++++++++++++
.../mesos/isolators/volume/image.hpp | 69 ++++++
4 files changed, 298 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/192283f6/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9668fcf..ccd9892 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -180,6 +180,7 @@ set(LINUX_SRC
slave/containerizer/mesos/isolators/gpu/volume.cpp
slave/containerizer/mesos/isolators/namespaces/pid.cpp
slave/containerizer/mesos/isolators/network/cni/cni.cpp
+ slave/containerizer/mesos/isolators/volume/image.cpp
slave/containerizer/mesos/provisioner/backends/aufs.cpp
slave/containerizer/mesos/provisioner/backends/bind.cpp
slave/containerizer/mesos/provisioner/backends/overlay.cpp
http://git-wip-us.apache.org/repos/asf/mesos/blob/192283f6/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index dd24f53..8dc4175 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1042,6 +1042,7 @@ MESOS_LINUX_FILES = \
slave/containerizer/mesos/isolators/gpu/volume.cpp \
slave/containerizer/mesos/isolators/namespaces/pid.cpp \
slave/containerizer/mesos/isolators/network/cni/cni.cpp \
+ slave/containerizer/mesos/isolators/volume/image.cpp \
slave/containerizer/mesos/provisioner/backends/aufs.cpp \
slave/containerizer/mesos/provisioner/backends/bind.cpp \
slave/containerizer/mesos/provisioner/backends/overlay.cpp
@@ -1081,6 +1082,7 @@ MESOS_LINUX_FILES += \
slave/containerizer/mesos/isolators/gpu/volume.hpp \
slave/containerizer/mesos/isolators/namespaces/pid.hpp \
slave/containerizer/mesos/isolators/network/cni/cni.hpp \
+ slave/containerizer/mesos/isolators/volume/image.hpp \
slave/containerizer/mesos/provisioner/backends/aufs.hpp \
slave/containerizer/mesos/provisioner/backends/bind.hpp \
slave/containerizer/mesos/provisioner/backends/overlay.hpp
http://git-wip-us.apache.org/repos/asf/mesos/blob/192283f6/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
new file mode 100644
index 0000000..c25205b
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/volume/image.cpp
@@ -0,0 +1,226 @@
+// 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 <list>
+#include <string>
+#include <vector>
+
+#include <glog/logging.h>
+
+#include <process/collect.hpp>
+#include <process/defer.hpp>
+#include <process/id.hpp>
+
+#include <stout/error.hpp>
+#include <stout/foreach.hpp>
+#include <stout/strings.hpp>
+
+#include "slave/containerizer/mesos/isolators/volume/image.hpp"
+
+#include "slave/containerizer/mesos/provisioner/provisioner.hpp"
+
+using std::list;
+using std::string;
+using std::vector;
+
+using process::defer;
+using process::Failure;
+using process::Future;
+using process::Owned;
+using process::PID;
+using process::Shared;
+
+using mesos::slave::ContainerConfig;
+using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::Isolator;
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+VolumeImageIsolatorProcess::VolumeImageIsolatorProcess(
+ const Flags& _flags,
+ const Shared<Provisioner>& _provisioner)
+ : ProcessBase(process::ID::generate("volume-image-isolator")),
+ flags(_flags),
+ provisioner(_provisioner) {}
+
+
+VolumeImageIsolatorProcess::~VolumeImageIsolatorProcess() {}
+
+
+Try<Isolator*> VolumeImageIsolatorProcess::create(
+ const Flags& flags,
+ const Shared<Provisioner>& provisioner)
+{
+ process::Owned<MesosIsolatorProcess> process(
+ new VolumeImageIsolatorProcess(flags, provisioner));
+
+ return new MesosIsolator(process);
+}
+
+
+Future<Option<ContainerLaunchInfo>> VolumeImageIsolatorProcess::prepare(
+ const ContainerID& containerId,
+ const ContainerConfig& containerConfig)
+{
+ const ExecutorInfo& executorInfo = containerConfig.executor_info();
+
+ if (!executorInfo.has_container()) {
+ return None();
+ }
+
+ if (executorInfo.container().type() != ContainerInfo::MESOS) {
+ return Failure("Can only prepare image volumes for a MESOS container");
+ }
+
+ vector<string> targets;
+ list<Future<ProvisionInfo>> futures;
+
+ for (int i = 0; i < executorInfo.container().volumes_size(); i++) {
+ const Volume& volume = executorInfo.container().volumes(i);
+
+ if (!volume.has_image()) {
+ continue;
+ }
+
+ // Determine the target of the mount. The mount target
+ // is determined by 'container_path'.
+ string target;
+
+ // The logic to determine a volume mount target is identical to
+ // linux filesystem isolator, because volume image isolator has
+ // a dependency on that isolator, and it assumes that if the
+ // container specifies a rootfs the sandbox is already bind
+ // mounted into the container.
+ if (path::absolute(volume.container_path())) {
+ // To specify an image volume for a container, operators should
+ // be allowed to define the 'container_path' either as an absolute
+ // path or a relative path. Please see linux filesystem isolator
+ // for detail.
+ 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());
+ }
+
+ // 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 'directory'.
+ 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());
+ }
+ }
+
+ targets.push_back(target);
+ futures.push_back(provisioner->provision(containerId, volume.image()));
+ }
+
+ return await(futures)
+ .then(defer(
+ PID<VolumeImageIsolatorProcess>(this),
+ &VolumeImageIsolatorProcess::_prepare,
+ containerId,
+ targets,
+ lambda::_1));
+}
+
+
+Future<Option<ContainerLaunchInfo>> VolumeImageIsolatorProcess::_prepare(
+ const ContainerID& containerId,
+ const vector<string>& targets,
+ const list<Future<ProvisionInfo>>& futures)
+{
+ ContainerLaunchInfo launchInfo;
+ launchInfo.set_namespaces(CLONE_NEWNS);
+
+ vector<string> messages;
+ vector<string> sources;
+
+ foreach (const Future<ProvisionInfo>& future, futures) {
+ if (!future.isReady()) {
+ messages.push_back(future.isFailed() ? future.failure() : "discarded");
+ continue;
+ }
+
+ sources.push_back(future.get().rootfs);
+ }
+
+ if (!messages.empty()) {
+ return Failure(strings::join("\n", messages));
+ }
+
+ CHECK_EQ(sources.size(), targets.size());
+
+ for (size_t i = 0; i < sources.size(); i++) {
+ const string& source = sources[i];
+ const string& target = targets[i];
+
+ LOG(INFO) << "Mounting image volume rootfs '" << source
+ << "' to '" << target << "' for container " << containerId;
+
+ if (!os::exists(source)) {
+ return Failure(
+ "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);
+ }
+
+ return launchInfo;
+}
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/192283f6/src/slave/containerizer/mesos/isolators/volume/image.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/image.hpp b/src/slave/containerizer/mesos/isolators/volume/image.hpp
new file mode 100644
index 0000000..6333e9c
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/volume/image.hpp
@@ -0,0 +1,69 @@
+// 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_IMAGE_ISOLATOR_HPP__
+#define __VOLUME_IMAGE_ISOLATOR_HPP__
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include <process/shared.hpp>
+
+#include "slave/flags.hpp"
+
+#include "slave/containerizer/mesos/isolator.hpp"
+
+#include "slave/containerizer/mesos/provisioner/provisioner.hpp"
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+// The volume image isolator is responsible for preparing image
+// volumes for mesos container.
+class VolumeImageIsolatorProcess : public MesosIsolatorProcess
+{
+public:
+ static Try<mesos::slave::Isolator*> create(
+ const Flags& flags,
+ const process::Shared<Provisioner>& provisioner);
+
+ virtual ~VolumeImageIsolatorProcess();
+
+ virtual process::Future<Option<mesos::slave::ContainerLaunchInfo>> prepare(
+ const ContainerID& containerId,
+ const mesos::slave::ContainerConfig& containerConfig);
+
+private:
+ VolumeImageIsolatorProcess(
+ const Flags& flags,
+ const process::Shared<Provisioner>& provisioner);
+
+ process::Future<Option<mesos::slave::ContainerLaunchInfo>> _prepare(
+ const ContainerID& containerId,
+ const std::vector<std::string>& targets,
+ const std::list<process::Future<ProvisionInfo>>& futures);
+
+ const Flags flags;
+ const process::Shared<Provisioner> provisioner;
+};
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __VOLUME_IMAGE_ISOLATOR_HPP__