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 {
