Repository: mesos Updated Branches: refs/heads/master dcc87a160 -> 0ba6b89b7
Added usage() for the docker containerizer. Added one unit test for this. Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/1f994fd1 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/1f994fd1 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/1f994fd1 Branch: refs/heads/master Commit: 1f994fd1c4e28987d022c815200a42e854a4aa69 Parents: 1bb4bd7 Author: Yifan Gu <[email protected]> Authored: Thu Jun 26 23:56:58 2014 -0700 Committer: Benjamin Hindman <[email protected]> Committed: Mon Aug 4 15:08:15 2014 -0700 ---------------------------------------------------------------------- src/slave/containerizer/docker.cpp | 39 ++++++++++- src/slave/containerizer/isolators/posix.hpp | 14 +++- src/tests/docker_containerizer_tests.cpp | 86 ++++++++++++++++++++++++ src/usage/usage.cpp | 4 +- src/usage/usage.hpp | 2 +- 5 files changed, 137 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/1f994fd1/src/slave/containerizer/docker.cpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/docker.cpp b/src/slave/containerizer/docker.cpp index 3c7f810..5968916 100644 --- a/src/slave/containerizer/docker.cpp +++ b/src/slave/containerizer/docker.cpp @@ -36,6 +36,9 @@ #include "slave/containerizer/containerizer.hpp" #include "slave/containerizer/docker.hpp" +#include "usage/usage.hpp" + + using std::list; using std::map; using std::string; @@ -130,6 +133,10 @@ private: const bool& killed, const Future<Option<int > >& status); + Future<ResourceStatistics> _usage( + const ContainerID& containerId, + const Future<Docker::Container> container); + // Call back for when the executor exits. This will trigger // container destroy. void reaped(const ContainerID& containerId); @@ -623,9 +630,35 @@ Future<Nothing> DockerContainerizerProcess::update( Future<ResourceStatistics> DockerContainerizerProcess::usage( const ContainerID& containerId) { - // TODO(benh): Implement! Look up Docker container ID then read - // cgroups files ala ./isolators/cgroups/cpushare.cpp. - return ResourceStatistics(); +#ifndef __linux__ + return Failure("Does not support usage() on non-linux platform"); +#endif // __linux__ + + if (!promises.contains(containerId)) { + return Failure("Unknown container: " + stringify(containerId)); + } + + // Construct the Docker container name. + string name = DOCKER_NAME_PREFIX + stringify(containerId); + return docker.inspect(name) + .then(defer(self(), &Self::_usage, containerId, lambda::_1)); +} + + +Future<ResourceStatistics> DockerContainerizerProcess::_usage( + const ContainerID& containerId, + const Future<Docker::Container> container) +{ + pid_t pid = container.get().pid(); + if (pid == 0) { + return Failure("Container is not running"); + } + Try<ResourceStatistics> usage = + mesos::internal::usage(pid, true, true); + if (usage.isError()) { + return Failure(usage.error()); + } + return usage.get(); } http://git-wip-us.apache.org/repos/asf/mesos/blob/1f994fd1/src/slave/containerizer/isolators/posix.hpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/isolators/posix.hpp b/src/slave/containerizer/isolators/posix.hpp index 17bbd10..f120aaf 100644 --- a/src/slave/containerizer/isolators/posix.hpp +++ b/src/slave/containerizer/isolators/posix.hpp @@ -160,7 +160,12 @@ public: } // Use 'mesos-usage' but only request 'cpus_' values. - return mesos::internal::usage(pids.get(containerId).get(), false, true); + Try<ResourceStatistics> usage = + mesos::internal::usage(pids.get(containerId).get(), false, true); + if (usage.isError()) { + return Failure(usage.error()); + } + return usage.get(); } private: @@ -188,7 +193,12 @@ public: } // Use 'mesos-usage' but only request 'mem_' values. - return mesos::internal::usage(pids.get(containerId).get(), true, false); + Try<ResourceStatistics> usage = + mesos::internal::usage(pids.get(containerId).get(), true, false); + if (usage.isError()) { + return Failure(usage.error()); + } + return usage.get(); } private: http://git-wip-us.apache.org/repos/asf/mesos/blob/1f994fd1/src/tests/docker_containerizer_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/docker_containerizer_tests.cpp b/src/tests/docker_containerizer_tests.cpp index a6ba9da..3941d5a 100644 --- a/src/tests/docker_containerizer_tests.cpp +++ b/src/tests/docker_containerizer_tests.cpp @@ -172,3 +172,89 @@ TEST_F(DockerContainerizerTest, DOCKER_Launch) Shutdown(); } + +// This test tests DockerContainerizer::usage() +TEST_F(DockerContainerizerTest, DOCKER_Usage) +{ + Try<PID<Master> > master = StartMaster(); + ASSERT_SOME(master); + + slave::Flags flags = CreateSlaveFlags(); + + Docker docker("docker"); + + MockDockerContainerizer dockerContainer(flags, true, docker); + + Try<PID<Slave> > slave = StartSlave((slave::Containerizer*) &dockerContainer); + ASSERT_SOME(slave); + + MockScheduler sched; + MesosSchedulerDriver driver( + &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); + + Future<FrameworkID> frameworkId; + EXPECT_CALL(sched, registered(&driver, _, _)) + .WillOnce(FutureArg<1>(&frameworkId)); + + Future<vector<Offer> > offers; + EXPECT_CALL(sched, resourceOffers(&driver, _)) + .WillOnce(FutureArg<1>(&offers)) + .WillRepeatedly(Return()); // Ignore subsequent offers. + + driver.start(); + + AWAIT_READY(frameworkId); + + AWAIT_READY(offers); + EXPECT_NE(0u, offers.get().size()); + + const Offer& offer = offers.get()[0]; + + TaskInfo task; + task.set_name(""); + task.mutable_task_id()->set_value("1"); + task.mutable_slave_id()->CopyFrom(offer.slave_id()); + task.mutable_resources()->CopyFrom(offer.resources()); + + CommandInfo command; + CommandInfo::ContainerInfo* containerInfo = command.mutable_container(); + containerInfo->set_image("docker://busybox"); + command.set_value("sleep 120"); + + task.mutable_command()->CopyFrom(command); + + Future<TaskStatus> statusRunning; + + vector<TaskInfo> tasks; + tasks.push_back(task); + + EXPECT_CALL(sched, statusUpdate(&driver, _)) + .WillOnce(FutureArg<1>(&statusRunning)) + .WillRepeatedly(DoDefault()); + + // Usage() should fail since the container is not launched. + Future<ResourceStatistics> usage = + dockerContainer.usage(dockerContainer.lastContainerId); + + AWAIT_FAILED(usage); + + driver.launchTasks(offers.get()[0].id(), tasks); + + AWAIT_READY_FOR(statusRunning, Seconds(60)); + EXPECT_EQ(TASK_RUNNING, statusRunning.get().state()); + + usage = dockerContainer.usage(dockerContainer.lastContainerId); + AWAIT_READY(usage); + // TODO(yifan): Verify the usage. + + dockerContainer.destroy(dockerContainer.lastContainerId); + + // Usage() should fail again since the container is destroyed + usage = dockerContainer.usage(dockerContainer.lastContainerId); + AWAIT_FAILED(usage); + + driver.stop(); + driver.join(); + + Shutdown(); +} http://git-wip-us.apache.org/repos/asf/mesos/blob/1f994fd1/src/usage/usage.cpp ---------------------------------------------------------------------- diff --git a/src/usage/usage.cpp b/src/usage/usage.cpp index 29014d1..bb6c0ea 100644 --- a/src/usage/usage.cpp +++ b/src/usage/usage.cpp @@ -30,12 +30,12 @@ namespace mesos { namespace internal { -ResourceStatistics usage(pid_t pid, bool mem, bool cpus) +Try<ResourceStatistics> usage(pid_t pid, bool mem, bool cpus) { Try<os::ProcessTree> pstree = os::pstree(pid); if (pstree.isError()) { - return ResourceStatistics(); + return Error("Failed to get usage: " + pstree.error()); } ResourceStatistics statistics; http://git-wip-us.apache.org/repos/asf/mesos/blob/1f994fd1/src/usage/usage.hpp ---------------------------------------------------------------------- diff --git a/src/usage/usage.hpp b/src/usage/usage.hpp index 5a76746..e0ad2e2 100644 --- a/src/usage/usage.hpp +++ b/src/usage/usage.hpp @@ -29,7 +29,7 @@ namespace internal { // Collects resource usage of a process tree rooted at 'pid'. Only // collects the 'mem_*' values if 'mem' is true and the 'cpus_*' // values if 'cpus' is true. -ResourceStatistics usage(pid_t pid, bool mem = true, bool cpus = true); +Try<ResourceStatistics> usage(pid_t pid, bool mem = true, bool cpus = true); } // namespace internal { } // namespace mesos {
