Repository: mesos
Updated Branches:
  refs/heads/master 9dd1e74d6 -> 33058278e


Added support for preparing images specified in volumes.

Review: https://reviews.apache.org/r/37726


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/347d51ce
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/347d51ce
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/347d51ce

Branch: refs/heads/master
Commit: 347d51ceca849cc26b9ada8f1014e4c578eeb47b
Parents: 9dd1e74
Author: Jie Yu <[email protected]>
Authored: Mon Aug 24 12:44:12 2015 -0700
Committer: Jie Yu <[email protected]>
Committed: Wed Aug 26 14:26:28 2015 -0700

----------------------------------------------------------------------
 .../isolators/filesystem/linux.cpp              | 89 +++++++++++++++-----
 .../isolators/filesystem/linux.hpp              |  7 ++
 .../containerizer/filesystem_isolator_tests.cpp | 59 +++++++++++++
 3 files changed, 134 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/347d51ce/src/slave/containerizer/isolators/filesystem/linux.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/isolators/filesystem/linux.cpp 
b/src/slave/containerizer/isolators/filesystem/linux.cpp
index f36424e..f7d990d 100644
--- a/src/slave/containerizer/isolators/filesystem/linux.cpp
+++ b/src/slave/containerizer/isolators/filesystem/linux.cpp
@@ -154,33 +154,33 @@ Future<Option<ContainerPrepareInfo>> 
LinuxFilesystemIsolatorProcess::prepare(
 
   infos.put(containerId, Owned<Info>(new Info(directory)));
 
+  if (!executorInfo.has_container()) {
+    return __prepare(containerId, executorInfo, directory, user, None());
+  }
+
   // Provision the root filesystem if needed.
-  if (executorInfo.has_container()) {
-    CHECK_EQ(executorInfo.container().type(), ContainerInfo::MESOS);
+  CHECK_EQ(executorInfo.container().type(), ContainerInfo::MESOS);
 
-    if (executorInfo.container().mesos().has_image()) {
-      const Image& image = executorInfo.container().mesos().image();
+  if (!executorInfo.container().mesos().has_image()) {
+    return _prepare(containerId, executorInfo, directory, user, None());
+  }
 
-      if (!provisioners.contains(image.type())) {
-        return Failure(
-            "No suitable provisioner found for container image type '" +
-            stringify(image.type()) + "'");
-      }
+  const Image& image = executorInfo.container().mesos().image();
 
-      return provisioners[image.type()]->provision(containerId, image)
-        .then(defer(PID<LinuxFilesystemIsolatorProcess>(this),
-                    &LinuxFilesystemIsolatorProcess::_prepare,
-                    containerId,
-                    executorInfo,
-                    directory,
-                    user,
-                    lambda::_1));
-    }
+  if (!provisioners.contains(image.type())) {
+    return Failure(
+        "No suitable provisioner found for container image type '" +
+        stringify(image.type()) + "'");
   }
 
-  // TODO(jieyu): Provision images in volumes as well.
-
-  return _prepare(containerId, executorInfo, directory, user, None());
+  return provisioners[image.type()]->provision(containerId, image)
+    .then(defer(PID<LinuxFilesystemIsolatorProcess>(this),
+                &LinuxFilesystemIsolatorProcess::_prepare,
+                containerId,
+                executorInfo,
+                directory,
+                user,
+                lambda::_1));
 }
 
 
@@ -191,6 +191,53 @@ Future<Option<ContainerPrepareInfo>> 
LinuxFilesystemIsolatorProcess::_prepare(
     const Option<string>& user,
     const Option<string>& rootfs)
 {
+  CHECK(executorInfo.has_container());
+  CHECK_EQ(executorInfo.container().type(), ContainerInfo::MESOS);
+
+  // We will provision the images specified in ContainerInfo::volumes
+  // as well. We will mutate ContainerInfo::volumes to include the
+  // paths to the provisioned root filesystems (by setting the
+  // 'host_path') if the volume specifies an image as the source.
+  Owned<ExecutorInfo> _executorInfo(new ExecutorInfo(executorInfo));
+  list<Future<Nothing>> futures;
+
+  for (int i = 0; i < _executorInfo->container().volumes_size(); i++) {
+    Volume* volume = _executorInfo->mutable_container()->mutable_volumes(i);
+
+    if (!volume->has_image()) {
+      continue;
+    }
+
+    const Image& image = volume->image();
+
+    if (!provisioners.contains(image.type())) {
+      return Failure(
+          "No suitable provisioner found for image type '" +
+          stringify(image.type()) + "' in a volume");
+    }
+
+    futures.push_back(
+        provisioners[image.type()]->provision(containerId, image)
+          .then([volume](const string& path) -> Future<Nothing> {
+            volume->set_host_path(path);
+            return Nothing();
+          }));
+  }
+
+  return collect(futures)
+    .then([=]() -> Future<Option<ContainerPrepareInfo>> {
+      return __prepare(containerId, *_executorInfo, directory, user, rootfs);
+    });
+}
+
+
+Future<Option<ContainerPrepareInfo>> LinuxFilesystemIsolatorProcess::__prepare(
+    const ContainerID& containerId,
+    const ExecutorInfo& executorInfo,
+    const string& directory,
+    const Option<string>& user,
+    const Option<string>& rootfs)
+{
   CHECK(infos.contains(containerId));
 
   const Owned<Info>& info = infos[containerId];

http://git-wip-us.apache.org/repos/asf/mesos/blob/347d51ce/src/slave/containerizer/isolators/filesystem/linux.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/isolators/filesystem/linux.hpp 
b/src/slave/containerizer/isolators/filesystem/linux.hpp
index ee5b33d..ab60f0c 100644
--- a/src/slave/containerizer/isolators/filesystem/linux.hpp
+++ b/src/slave/containerizer/isolators/filesystem/linux.hpp
@@ -93,6 +93,13 @@ private:
     const Option<std::string>& user,
     const Option<std::string>& rootfs);
 
+  process::Future<Option<mesos::slave::ContainerPrepareInfo>> __prepare(
+    const ContainerID& containerId,
+    const ExecutorInfo& executorInfo,
+    const std::string& directory,
+    const Option<std::string>& user,
+    const Option<std::string>& rootfs);
+
   Try<std::string> script(
     const ExecutorInfo& executorInfo,
     const std::string& directory,

http://git-wip-us.apache.org/repos/asf/mesos/blob/347d51ce/src/tests/containerizer/filesystem_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/filesystem_isolator_tests.cpp 
b/src/tests/containerizer/filesystem_isolator_tests.cpp
index 7003b03..dd1e49b 100644
--- a/src/tests/containerizer/filesystem_isolator_tests.cpp
+++ b/src/tests/containerizer/filesystem_isolator_tests.cpp
@@ -137,6 +137,19 @@ public:
     return info;
   }
 
+  Volume createVolume(
+      const string& containerPath,
+      const Image::Type& imageType,
+      const Volume::Mode& mode)
+  {
+    Volume volume;
+    volume.set_container_path(containerPath);
+    volume.mutable_image()->set_type(imageType);
+    volume.set_mode(mode);
+
+    return volume;
+  }
+
 private:
   Fetcher fetcher;
 };
@@ -450,6 +463,52 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_PersistentVolumeWithoutRootFilesystem)
 
   EXPECT_SOME_EQ("abc\n", os::read(path::join(volume, "file")));
 }
+
+
+// This test verifies that the image specified in the volume will be
+// properly provisioned and mounted into the container.
+TEST_F(LinuxFilesystemIsolatorTest, ROOT_ImageInVolume)
+{
+  slave::Flags flags = CreateSlaveFlags();
+
+  Try<Owned<MesosContainerizer>> containerizer = createContainerizer(flags);
+  ASSERT_SOME(containerizer);
+
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  ExecutorInfo executor = CREATE_EXECUTOR_INFO(
+      "test_executor",
+      "test -d rootfs/bin");
+
+  executor.mutable_container()->CopyFrom(createContainerInfo(
+      {createVolume("rootfs", Image::APPC, Volume::RW)}, false));
+
+  string directory = path::join(os::getcwd(), "sandbox");
+  ASSERT_SOME(os::mkdir(directory));
+
+  Future<bool> launch = containerizer.get()->launch(
+      containerId,
+      executor,
+      directory,
+      None(),
+      SlaveID(),
+      PID<Slave>(),
+      false);
+
+  // Wait for the launch to complete.
+  AWAIT_READY(launch);
+
+  // Wait on the container.
+  Future<containerizer::Termination> wait =
+    containerizer.get()->wait(containerId);
+
+  AWAIT_READY(wait);
+
+  // Check the executor exited correctly.
+  EXPECT_TRUE(wait.get().has_status());
+  EXPECT_EQ(0, wait.get().status());
+}
 #endif // __linux__
 
 } // namespace tests {

Reply via email to