Repository: mesos Updated Branches: refs/heads/master c2c9bddd9 -> f0f6a276d
Add support for container image provisioners. Review: https://reviews.apache.org/r/34137/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/f0f6a276 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/f0f6a276 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/f0f6a276 Branch: refs/heads/master Commit: f0f6a276da0935e0041710dc2df61e32b6e8e270 Parents: c2c9bdd Author: Ian Downes <[email protected]> Authored: Thu Jul 16 16:54:02 2015 -0700 Committer: Timothy Chen <[email protected]> Committed: Thu Jul 16 17:32:14 2015 -0700 ---------------------------------------------------------------------- include/mesos/slave/isolator.hpp | 17 +- src/Makefile.am | 2 + src/slave/containerizer/mesos/containerizer.cpp | 175 ++++++++++++++++++- src/slave/containerizer/mesos/containerizer.hpp | 37 +++- src/slave/containerizer/provisioner.cpp | 43 +++++ src/slave/containerizer/provisioner.hpp | 77 ++++++++ src/slave/flags.cpp | 5 + src/slave/flags.hpp | 1 + src/slave/paths.cpp | 19 ++ src/slave/paths.hpp | 8 + src/slave/state.cpp | 24 +++ src/slave/state.hpp | 1 + src/tests/containerizer_tests.cpp | 32 +++- 13 files changed, 419 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/include/mesos/slave/isolator.hpp ---------------------------------------------------------------------- diff --git a/include/mesos/slave/isolator.hpp b/include/mesos/slave/isolator.hpp index ef2205d..85e38f5 100644 --- a/include/mesos/slave/isolator.hpp +++ b/include/mesos/slave/isolator.hpp @@ -67,12 +67,23 @@ struct Limitation // any dependency on RunState and in turn on internal protobufs. struct ExecutorRunState { - ExecutorRunState(ContainerID id_, pid_t pid_, std::string directory_) - : id(id_), pid(pid_), directory(directory_) {} - + ExecutorRunState( + const ExecutorInfo& executorInfo_, + const ContainerID& id_, + pid_t pid_, + const std::string& directory_, + const Option<std::string>& rootfs_) + : executorInfo(executorInfo_), + id(id_), + pid(pid_), + directory(directory_), + rootfs(rootfs_) {} + + ExecutorInfo executorInfo; ContainerID id; // Container id of the last executor run. pid_t pid; // Executor pid. std::string directory; // Executor work directory. + Option<std::string> rootfs; // Optional container rootfs. }; http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/Makefile.am ---------------------------------------------------------------------- diff --git a/src/Makefile.am b/src/Makefile.am index e2cbd15..d8fdfab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -520,6 +520,7 @@ if OS_LINUX libmesos_no_3rdparty_la_SOURCES += slave/containerizer/isolators/namespaces/pid.cpp libmesos_no_3rdparty_la_SOURCES += slave/containerizer/isolators/filesystem/shared.cpp libmesos_no_3rdparty_la_SOURCES += slave/containerizer/linux_launcher.cpp + libmesos_no_3rdparty_la_SOURCES += slave/containerizer/provisioner.cpp else EXTRA_DIST += linux/cgroups.cpp EXTRA_DIST += linux/fs.cpp @@ -640,6 +641,7 @@ libmesos_no_3rdparty_la_SOURCES += \ slave/containerizer/isolators/cgroups/perf_event.hpp \ slave/containerizer/isolators/namespaces/pid.hpp \ slave/containerizer/isolators/filesystem/shared.hpp \ + slave/containerizer/provisioner.hpp \ slave/resource_estimators/noop.hpp \ tests/cluster.hpp \ tests/containerizer.hpp \ http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/containerizer/mesos/containerizer.cpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp index 47d1461..54787ac 100644 --- a/src/slave/containerizer/mesos/containerizer.cpp +++ b/src/slave/containerizer/mesos/containerizer.cpp @@ -178,8 +178,20 @@ Try<MesosContainerizer*> MesosContainerizer::create( return Error("Failed to create launcher: " + launcher.error()); } + Try<hashmap<ContainerInfo::Image::Type, Owned<Provisioner>>> provisioners = + Provisioner::create(flags, fetcher); + + if (provisioners.isError()) { + return Error("Failed to create provisioner(s): " + provisioners.error()); + } + return new MesosContainerizer( - flags_, local, fetcher, Owned<Launcher>(launcher.get()), isolators); + flags_, + local, + fetcher, + Owned<Launcher>(launcher.get()), + isolators, + provisioners.get()); } @@ -188,13 +200,16 @@ MesosContainerizer::MesosContainerizer( bool local, Fetcher* fetcher, const Owned<Launcher>& launcher, - const vector<Owned<Isolator>>& isolators) + const vector<Owned<Isolator>>& isolators, + const hashmap<ContainerInfo::Image::Type, + Owned<Provisioner>>& provisioners) : process(new MesosContainerizerProcess( flags, local, fetcher, launcher, - isolators)) + isolators, + provisioners)) { spawn(process.get()); } @@ -385,9 +400,11 @@ Future<Nothing> MesosContainerizerProcess::recover( CHECK(os::exists(directory)); ExecutorRunState executorRunState( + executorInfo, run.get().id.get(), run.get().forkedPid.get(), - directory); + directory, + run.get().rootfs); recoverable.push_back(executorRunState); } @@ -404,13 +421,19 @@ Future<Nothing> MesosContainerizerProcess::_recover( const list<ExecutorRunState>& recoverable, const hashset<ContainerID>& orphans) { - // Then recover the isolators. list<Future<Nothing>> futures; + + // Then recover the provisioners. + foreachvalue (const Owned<Provisioner>& provisioner, provisioners) { + futures.push_back(provisioner->recover(recoverable, orphans)); + } + + // Then recover the isolators. foreach (const Owned<Isolator>& isolator, isolators) { futures.push_back(isolator->recover(recoverable, orphans)); } - // If all isolators recover then continue. + // If all provisioners and isolators recover then continue. return collect(futures) .then(defer(self(), &Self::__recover, recoverable, orphans)); } @@ -431,11 +454,15 @@ Future<Nothing> MesosContainerizerProcess::__recover( container->directory = run.directory; + container->rootfs = run.rootfs; + // We only checkpoint the containerizer pid after the container // successfully launched, therefore we can assume checkpointed // containers should be running after recover. container->state = RUNNING; + container->executorInfo = run.executorInfo; + containers_[containerId] = Owned<Container>(container); foreach (const Owned<Isolator>& isolator, isolators) { @@ -538,6 +565,7 @@ Future<bool> MesosContainerizerProcess::launch( Container* container = new Container(); container->directory = directory; container->state = PREPARING; + container->executorInfo = executorInfo; containers_[containerId] = Owned<Container>(container); // Prepare volumes for the container. @@ -556,7 +584,13 @@ Future<bool> MesosContainerizerProcess::launch( // container resources. container->resources = executorInfo.resources(); - return prepare(containerId, executorInfo, directory, user) + return provision(containerId, executorInfo, slaveId, directory, checkpoint) + .then(defer(self(), + &Self::prepare, + containerId, + executorInfo, + directory, + user)) .then(defer(self(), &Self::_launch, containerId, @@ -570,6 +604,70 @@ Future<bool> MesosContainerizerProcess::launch( } +Future<Nothing> MesosContainerizerProcess::provision( + const ContainerID& containerId, + const ExecutorInfo& executorInfo, + const SlaveID& slaveId, + const string& directory, + bool checkpoint) +{ + if (!executorInfo.has_container()) { + // TODO(idownes): Consider refusing to run a container if the + // containerizer is configured with an image provisioner but the + // executor doesn't specify an image. + return Nothing(); + } + + if (executorInfo.container().type() != ContainerInfo::MESOS) { + return Failure("Mesos containerizer can only provision Mesos containers"); + } + + if (!executorInfo.container().mesos().has_image()) { + // No image to provision. + return Nothing(); + } + + ContainerInfo::Image image = executorInfo.container().mesos().image(); + + if (!provisioners.contains(image.type())) { + return Failure("ExecutorInfo specifies container image type '" + + stringify(image.type()) + + "' but no suitable provisioner available"); + } + + return provisioners[image.type()]->provision(containerId, image) + .then(defer(self(), [=](const string& rootfs) -> Future<Nothing> { + if (!containers_.contains(containerId)) { + return Failure("Container is already destroyed"); + } + + containers_[containerId]->rootfs = rootfs; + + if (checkpoint) { + const string path = slave::paths::getContainerRootfsPath( + slave::paths::getMetaRootDir(flags.work_dir), + slaveId, + executorInfo.framework_id(), + executorInfo.executor_id(), + containerId); + + LOG(INFO) << "Checkpointing container's rootfs path '" << rootfs + << "' to '" << path << "'"; + + Try<Nothing> checkpointed = slave::state::checkpoint(path, rootfs); + if (checkpointed.isError()) { + LOG(ERROR) << "Failed to checkpoint container's rootfs path to '" + << path << "': " << checkpointed.error(); + + return Failure("Could not checkpoint container's rootfs"); + } + } + + return Nothing(); + })); +} + + Future<bool> MesosContainerizerProcess::launch( const ContainerID& containerId, const TaskInfo& taskInfo, @@ -694,7 +792,9 @@ Future<bool> MesosContainerizerProcess::_launch( // Prepare environment variables for the executor. map<string, string> environment = executorEnvironment( executorInfo, - directory, + containers_[containerId]->rootfs.isSome() + ? flags.sandbox_directory + : directory, slaveId, slavePid, checkpoint, @@ -717,7 +817,12 @@ Future<bool> MesosContainerizerProcess::_launch( MesosContainerizerLaunch::Flags launchFlags; launchFlags.command = JSON::Protobuf(executorInfo.command()); - launchFlags.directory = directory; + + launchFlags.directory = containers_[containerId]->rootfs.isSome() + ? flags.sandbox_directory + : directory; + + launchFlags.rootfs = containers_[containerId]->rootfs; launchFlags.user = user; launchFlags.pipe_read = pipes[0]; launchFlags.pipe_write = pipes[1]; @@ -1143,6 +1248,58 @@ void MesosContainerizerProcess::____destroy( } } + if (container->rootfs.isNone()) { + // No rootfs to clean up so continue. + return _____destroy(containerId, status, message, killed, Nothing()); + } + + ContainerInfo::Image::Type type = + container->executorInfo.container().mesos().image().type(); + + if (!provisioners.contains(type)) { + // We should have a provisioner to handle cleaning up the rootfs + // but continue clean up even if we don't. + LOG(WARNING) << "No provisioner to clean up rootfs for container " + << containerId << " (type '" << type << "'), continuing"; + return _____destroy(containerId, status, message, killed, Nothing()); + } + + provisioners[type]->destroy(containerId) + .onAny(defer(self(), + &Self::_____destroy, + containerId, + status, + message, + killed, + lambda::_1)); + + return; +} + + +void MesosContainerizerProcess::_____destroy( + const ContainerID& containerId, + const Future<Option<int>>& status, + Option<string> message, + bool killed, + const Future<Nothing>& cleanup) +{ + CHECK(containers_.contains(containerId)); + + Container* container = containers_[containerId].get(); + + if (!cleanup.isReady()) { + container->promise.fail( + "Failed to clean up the root filesystem when destroying container: " + + (cleanup.isFailed() ? cleanup.failure() : "discarded future")); + + containers_.erase(containerId); + + ++metrics.container_destroy_errors; + + return; + } + // If any isolator limited the container then we mark it to killed. // Note: We may not see a limitation in time for it to be // registered. This could occur if the limitation (e.g., an OOM) http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/containerizer/mesos/containerizer.hpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/mesos/containerizer.hpp b/src/slave/containerizer/mesos/containerizer.hpp index 3ac2387..f8eb0a9 100644 --- a/src/slave/containerizer/mesos/containerizer.hpp +++ b/src/slave/containerizer/mesos/containerizer.hpp @@ -33,6 +33,7 @@ #include "slave/containerizer/containerizer.hpp" #include "slave/containerizer/launcher.hpp" +#include "slave/containerizer/provisioner.hpp" namespace mesos { namespace internal { @@ -56,7 +57,10 @@ public: bool local, Fetcher* fetcher, const process::Owned<Launcher>& launcher, - const std::vector<process::Owned<mesos::slave::Isolator>>& isolators); + const std::vector<process::Owned<mesos::slave::Isolator>>& isolators, + const hashmap<ContainerInfo::Image::Type, + process::Owned<Provisioner>>& provisioners); + // Used for testing. MesosContainerizer(const process::Owned<MesosContainerizerProcess>& _process); @@ -113,12 +117,15 @@ public: bool _local, Fetcher* _fetcher, const process::Owned<Launcher>& _launcher, - const std::vector<process::Owned<mesos::slave::Isolator>>& _isolators) + const std::vector<process::Owned<mesos::slave::Isolator>>& _isolators, + const hashmap<ContainerInfo::Image::Type, + process::Owned<Provisioner>>& _provisioners) : flags(_flags), local(_local), fetcher(_fetcher), launcher(_launcher), - isolators(_isolators) {} + isolators(_isolators), + provisioners(_provisioners) {} virtual ~MesosContainerizerProcess() {} @@ -176,6 +183,13 @@ private: const std::list<mesos::slave::ExecutorRunState>& recovered, const hashset<ContainerID>& orphans); + process::Future<Nothing> provision( + const ContainerID& containerId, + const ExecutorInfo& executorInfo, + const SlaveID& slaveId, + const std::string& directory, + bool checkpoint); + process::Future<std::list<Option<CommandInfo>>> prepare( const ContainerID& containerId, const ExecutorInfo& executorInfo, @@ -219,7 +233,7 @@ private: const Option<std::string>& message, bool killed); - // Continues (and completes) '__destroy()' once all isolators have completed + // Continues '__destroy()' once all isolators have completed // cleanup. void ____destroy( const ContainerID& containerId, @@ -228,6 +242,15 @@ private: Option<std::string> message, bool killed); + // Continues (and completes) '__destroy()' once any root filessystem + // has been cleaned up. + void _____destroy( + const ContainerID& containerId, + const process::Future<Option<int>>& status, + Option<std::string> message, + bool killed, + const process::Future<Nothing>& cleanup); + // Call back for when an isolator limits a container and impacts the // processes. This will trigger container destruction. void limited( @@ -254,6 +277,9 @@ private: Fetcher* fetcher; const process::Owned<Launcher> launcher; const std::vector<process::Owned<mesos::slave::Isolator>> isolators; + hashmap<ContainerInfo::Image::Type, + process::Owned<Provisioner>> provisioners; + enum State { @@ -292,6 +318,9 @@ private: // ResourceStatistics limits in usage(). Resources resources; + // We keep track of the ExecutorInfo so we have the optional ContainerInfo. + ExecutorInfo executorInfo; + // The executor's working directory on the host. std::string directory; http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/containerizer/provisioner.cpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/provisioner.cpp b/src/slave/containerizer/provisioner.cpp new file mode 100644 index 0000000..1d304a6 --- /dev/null +++ b/src/slave/containerizer/provisioner.cpp @@ -0,0 +1,43 @@ +/** + * 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/hashmap.hpp> +#include <stout/strings.hpp> + +#include "slave/containerizer/provisioner.hpp" + +#include "slave/containerizer/provisioners/appc.hpp" + +using namespace process; + +using std::string; + +namespace mesos { +namespace internal { +namespace slave { + +Try<hashmap<ContainerInfo::Image::Type, Owned<Provisioner>>> + Provisioner::create(const Flags& flags, Fetcher* fetcher) +{ + // TODO(tnachen): Load provisioners when one of them is available. + return hashmap<ContainerInfo::Image::Type, Owned<Provisioner>>(); +} + +} // namespace slave { +} // namespace internal { +} // namespace mesos { http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/containerizer/provisioner.hpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/provisioner.hpp b/src/slave/containerizer/provisioner.hpp new file mode 100644 index 0000000..eef935f --- /dev/null +++ b/src/slave/containerizer/provisioner.hpp @@ -0,0 +1,77 @@ +/** + * 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 __MESOS_PROVISIONER_HPP__ +#define __MESOS_PROVISIONER_HPP__ + +#include <list> + +#include <mesos/resources.hpp> + +#include <stout/hashmap.hpp> +#include <stout/nothing.hpp> +#include <stout/try.hpp> + +#include <process/future.hpp> +#include <process/owned.hpp> + +#include "slave/flags.hpp" + +#include "slave/containerizer/fetcher.hpp" + +// For ExecutorRunState. +#include "mesos/slave/isolator.hpp" + +namespace mesos { +namespace internal { +namespace slave { + +class Provisioner +{ +public: + virtual ~Provisioner() {} + + static Try<hashmap<ContainerInfo::Image::Type, process::Owned<Provisioner>>> + create(const Flags& flags, Fetcher* fetcher); + + // Recover containers from the run states and the orphan containers + // (known to the launcher but not known to the slave) detected by + // the launcher. + // Recover also is responsible for cleaning up any intermediate + // artifacts (e.g. directories) to not leak anything. + virtual process::Future<Nothing> recover( + const std::list<mesos::slave::ExecutorRunState>& states, + const hashset<ContainerID>& orphans) = 0; + + // Provision a root filesystem for the container using the specified + // image and return the absolute path to the root filesystem. + virtual process::Future<std::string> provision( + const ContainerID& containerId, + const ContainerInfo::Image& image) = 0; + + // Destroy a previously provisioned root filesystem. Assumes that + // all references (e.g., mounts, open files) to the provisioned + // filesystem have been removed. + virtual process::Future<Nothing> destroy(const ContainerID& containerId) = 0; +}; + +} // namespace slave { +} // namespace internal { +} // namespace mesos { + +#endif // __MESOS_PROVISIONER_HPP__ http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/flags.cpp ---------------------------------------------------------------------- diff --git a/src/slave/flags.cpp b/src/slave/flags.cpp index f569363..82b6cf4 100644 --- a/src/slave/flags.cpp +++ b/src/slave/flags.cpp @@ -59,6 +59,11 @@ mesos::internal::slave::Flags::Flags() "for the Mesos Containerizer.", "posix/cpu,posix/mem"); + add(&Flags::provisioners, + "provisioners", + "Comma separated list of image rootfs provisioners,\n" + "e.g., appc,docker"); + add(&Flags::default_role, "default_role", "Any resources in the --resources flag that\n" http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/flags.hpp ---------------------------------------------------------------------- diff --git a/src/slave/flags.hpp b/src/slave/flags.hpp index bbc1b9e..881d494 100644 --- a/src/slave/flags.hpp +++ b/src/slave/flags.hpp @@ -46,6 +46,7 @@ public: Option<std::string> hostname; Option<std::string> resources; std::string isolation; + Option<std::string> provisioners; std::string default_role; Option<std::string> attributes; Bytes fetcher_cache_size; http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/paths.cpp ---------------------------------------------------------------------- diff --git a/src/slave/paths.cpp b/src/slave/paths.cpp index 0741616..5fe567d 100644 --- a/src/slave/paths.cpp +++ b/src/slave/paths.cpp @@ -51,6 +51,7 @@ const char LIBPROCESS_PID_FILE[] = "libprocess.pid"; const char EXECUTOR_INFO_FILE[] = "executor.info"; const char EXECUTOR_SENTINEL_FILE[] = "executor.sentinel"; const char FORKED_PID_FILE[] = "forked.pid"; +const char CONTAINER_ROOTFS_FILE[] = "rootfs"; const char TASK_INFO_FILE[] = "task.info"; const char TASK_UPDATES_FILE[] = "task.updates"; const char RESOURCES_INFO_FILE[] = "resources.info"; @@ -230,6 +231,24 @@ string getExecutorLatestRunPath( } +string getContainerRootfsPath( + const string& rootDir, + const SlaveID& slaveId, + const FrameworkID& frameworkId, + const ExecutorID& executorId, + const ContainerID& containerId) +{ + return path::join( + getExecutorRunPath( + rootDir, + slaveId, + frameworkId, + executorId, + containerId), + CONTAINER_ROOTFS_FILE); +} + + string getLibprocessPidPath( const string& rootDir, const SlaveID& slaveId, http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/paths.hpp ---------------------------------------------------------------------- diff --git a/src/slave/paths.hpp b/src/slave/paths.hpp index 00476f1..7e1e315 100644 --- a/src/slave/paths.hpp +++ b/src/slave/paths.hpp @@ -188,6 +188,14 @@ std::string getExecutorLatestRunPath( const ExecutorID& executorId); +std::string getContainerRootfsPath( + const std::string& rootDir, + const SlaveID& slaveId, + const FrameworkID& frameworkId, + const ExecutorID& executorId, + const ContainerID& containerId); + + std::string getLibprocessPidPath( const std::string& rootDir, const SlaveID& slaveId, http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/state.cpp ---------------------------------------------------------------------- diff --git a/src/slave/state.cpp b/src/slave/state.cpp index f8a9514..a2b8c5a 100644 --- a/src/slave/state.cpp +++ b/src/slave/state.cpp @@ -458,6 +458,30 @@ Try<RunState> RunState::recover( state.errors += task.get().errors; } + // Read the location of the container's root filesystem, if used. + path = paths::getContainerRootfsPath( + rootDir, slaveId, frameworkId, executorId, containerId); + + // Because a container root filesystem is optional we'll recover the + // path if present but continue to recover normally if it's not. + if (os::exists(path)) { + Try<string> rootfs = os::read(path); + if (rootfs.isError()) { + message = "Failed to recover container rootfs from '" + path + + "': " + rootfs.error(); + + if (strict) { + return Error(message); + } else { + LOG(WARNING) << message; + state.errors++; + return state; + } + } + + state.rootfs = rootfs.get(); + } + // Read the forked pid. path = paths::getForkedPidPath( rootDir, slaveId, frameworkId, executorId, containerId); http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/slave/state.hpp ---------------------------------------------------------------------- diff --git a/src/slave/state.hpp b/src/slave/state.hpp index bb0eee7..c549b18 100644 --- a/src/slave/state.hpp +++ b/src/slave/state.hpp @@ -206,6 +206,7 @@ struct RunState Option<ContainerID> id; hashmap<TaskID, TaskState> tasks; + Option<std::string> rootfs; Option<pid_t> forkedPid; Option<process::UPID> libprocessPid; http://git-wip-us.apache.org/repos/asf/mesos/blob/f0f6a276/src/tests/containerizer_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/containerizer_tests.cpp b/src/tests/containerizer_tests.cpp index 0cdb2d2..cae717e 100644 --- a/src/tests/containerizer_tests.cpp +++ b/src/tests/containerizer_tests.cpp @@ -94,12 +94,15 @@ public: return Error(launcher.error()); } + hashmap<ContainerInfo::Image::Type, Owned<Provisioner>> provisioners; + return new MesosContainerizer( flags, false, fetcher, Owned<Launcher>(launcher.get()), - isolators); + isolators, + provisioners); } @@ -335,8 +338,16 @@ public: bool local, Fetcher* fetcher, const process::Owned<Launcher>& launcher, - const vector<process::Owned<Isolator>>& isolators) - : MesosContainerizerProcess(flags, local, fetcher, launcher, isolators) + const vector<process::Owned<Isolator>>& isolators, + const hashmap<ContainerInfo::Image::Type, + Owned<Provisioner>>& provisioners) + : MesosContainerizerProcess( + flags, + local, + fetcher, + launcher, + isolators, + provisioners) { // NOTE: See TestContainerizer::setup for why we use // 'EXPECT_CALL' and 'WillRepeatedly' here instead of @@ -440,12 +451,15 @@ TEST_F(MesosContainerizerDestroyTest, DestroyWhileFetching) Fetcher fetcher; + hashmap<ContainerInfo::Image::Type, Owned<Provisioner>> provisioners; + MockMesosContainerizerProcess* process = new MockMesosContainerizerProcess( flags, true, &fetcher, Owned<Launcher>(launcher.get()), - isolators); + isolators, + provisioners); Future<Nothing> exec; Promise<bool> promise; @@ -509,12 +523,15 @@ TEST_F(MesosContainerizerDestroyTest, DestroyWhilePreparing) Fetcher fetcher; + hashmap<ContainerInfo::Image::Type, Owned<Provisioner>> provisioners; + MockMesosContainerizerProcess* process = new MockMesosContainerizerProcess( flags, true, &fetcher, Owned<Launcher>(launcher.get()), - isolators); + isolators, + provisioners); MesosContainerizer containerizer((Owned<MesosContainerizerProcess>(process))); @@ -584,12 +601,15 @@ TEST_F(MesosContainerizerDestroyTest, LauncherDestroyFailure) vector<process::Owned<Isolator>> isolators; Fetcher fetcher; + hashmap<ContainerInfo::Image::Type, Owned<Provisioner>> provisioners; + MesosContainerizerProcess* process = new MesosContainerizerProcess( flags, true, &fetcher, Owned<Launcher>(launcher), - isolators); + isolators, + provisioners); MesosContainerizer containerizer((Owned<MesosContainerizerProcess>(process)));
