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/10/08 21:21:42 UTC

[2/3] mesos git commit: Added test case `CgroupsIsolatorTest.ROOT_CGROUPS_MemoryBackward`.

Added test case `CgroupsIsolatorTest.ROOT_CGROUPS_MemoryBackward`.

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


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

Branch: refs/heads/master
Commit: 9118eded36b3e61a0727fa328540e7da1b9402f0
Parents: 96c866d
Author: haosdent huang <ha...@gmail.com>
Authored: Sat Oct 8 10:45:18 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Sat Oct 8 10:45:18 2016 -0700

----------------------------------------------------------------------
 .../containerizer/cgroups_isolator_tests.cpp    | 197 +++++++++++++++++++
 1 file changed, 197 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9118eded/src/tests/containerizer/cgroups_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/cgroups_isolator_tests.cpp b/src/tests/containerizer/cgroups_isolator_tests.cpp
index 1bb4ad2..af0dcd4 100644
--- a/src/tests/containerizer/cgroups_isolator_tests.cpp
+++ b/src/tests/containerizer/cgroups_isolator_tests.cpp
@@ -1290,6 +1290,203 @@ TEST_F(CgroupsIsolatorTest, ROOT_CGROUPS_MemoryForward)
   driver.join();
 }
 
+
+// Test that the memory subsystem can be disabled after the agent
+// restart. Previously created containers will perform memory isolation
+// but newly created containers will.
+TEST_F(CgroupsIsolatorTest, ROOT_CGROUPS_MemoryBackward)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  // Start an agent using a containerizer with the memory isolation.
+  slave::Flags flags = CreateSlaveFlags();
+  flags.isolation = "cgroups/cpu,cgroups/mem";
+
+  Fetcher fetcher;
+
+  Try<MesosContainerizer*> create =
+    MesosContainerizer::create(flags, true, &fetcher);
+
+  ASSERT_SOME(create);
+
+  Owned<slave::Containerizer> containerizer(create.get());
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+
+  Try<Owned<cluster::Slave>> slave = StartSlave(
+      detector.get(),
+      containerizer.get(),
+      flags);
+
+  ASSERT_SOME(slave);
+
+  // Enable checkpointing for the framework.
+  FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo.set_checkpoint(true);
+
+  MockScheduler sched;
+
+  MesosSchedulerDriver driver(
+      &sched,
+      frameworkInfo,
+      master.get()->pid,
+      DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _));
+
+  Future<vector<Offer>> offers1;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers1))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers1);
+  EXPECT_NE(0u, offers1->size());
+
+  Future<TaskStatus> statusRunning1;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&statusRunning1))
+    .WillRepeatedly(Return());
+
+  TaskInfo task1 = createTask(
+      offers1.get()[0].slave_id(),
+      Resources::parse("cpus:0.5;mem:128").get(),
+      "sleep 1000");
+
+  // We want to be notified immediately with new offer.
+  Filters filters;
+  filters.set_refuse_seconds(0);
+
+  driver.launchTasks(offers1.get()[0].id(), {task1}, filters);
+
+  AWAIT_READY(statusRunning1);
+  EXPECT_EQ(TASK_RUNNING, statusRunning1->state());
+
+  Future<hashset<ContainerID>> containers = containerizer->containers();
+
+  AWAIT_READY(containers);
+  EXPECT_EQ(1u, containers->size());
+
+  ContainerID containerId1 = *(containers->begin());
+
+  Future<ResourceStatistics> usage = containerizer->usage(containerId1);
+  AWAIT_READY(usage);
+
+  EXPECT_TRUE(usage.get().has_mem_total_bytes());
+
+  slave.get()->terminate();
+
+  Future<vector<Offer>> offers2;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers2))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  // Set up this to speed up the recovery of the agent.
+  Future<ReregisterExecutorMessage> reregisterExecutorMessage =
+    FUTURE_PROTOBUF(ReregisterExecutorMessage(), _, _);
+
+  Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover);
+
+  // Start an agent using a containerizer without the memory isolation.
+  flags.isolation = "cgroups/cpu";
+
+  containerizer.reset();
+
+  create = MesosContainerizer::create(flags, true, &fetcher);
+  ASSERT_SOME(create);
+
+  containerizer.reset(create.get());
+
+  slave = StartSlave(detector.get(), containerizer.get(), flags);
+  ASSERT_SOME(slave);
+
+  Clock::pause();
+
+  // Wait for the executor to re-register.
+  AWAIT_READY(reregisterExecutorMessage);
+
+  // Ensure the agent considers itself recovered.
+  Clock::advance(EXECUTOR_REREGISTER_TIMEOUT);
+  Clock::resume();
+
+  // Wait until agent recovery is complete.
+  AWAIT_READY(__recover);
+
+  AWAIT_READY(offers2);
+  EXPECT_NE(0u, offers2->size());
+
+  // The first container should not report memory statistics.
+  usage = containerizer->usage(containerId1);
+  AWAIT_READY(usage);
+
+  // After restart the agent without the memory isolation,
+  // the container should not report memory statistics.
+  EXPECT_FALSE(usage->has_mem_total_bytes());
+
+  TaskInfo task2 = createTask(offers2.get()[0], "sleep 1000");
+
+  Future<TaskStatus> statusRunning2;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&statusRunning2))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.launchTasks(offers2.get()[0].id(), {task2});
+
+  AWAIT_READY(statusRunning2);
+  EXPECT_EQ(TASK_RUNNING, statusRunning2.get().state());
+
+  containers = containerizer->containers();
+
+  AWAIT_READY(containers);
+  EXPECT_EQ(2u, containers.get().size());
+  EXPECT_TRUE(containers.get().contains(containerId1));
+
+  ContainerID containerId2;
+  foreach (const ContainerID containerId, containers.get()) {
+    if (containerId != containerId1) {
+      containerId2 = containerId;
+    }
+  }
+
+  usage = containerizer->usage(containerId2);
+  AWAIT_READY(usage);
+
+  // After restart the agent without the memory isolation,
+  // the container should not report memory statistics.
+  EXPECT_FALSE(usage->has_mem_total_bytes());
+
+  driver.stop();
+  driver.join();
+
+  slave.get()->terminate();
+
+  __recover = FUTURE_DISPATCH(_, &Slave::__recover);
+
+  // Restart an agent using a containerizer with the memory isolation to
+  // clean up the orphan cgroups.
+  flags.isolation = "cgroups/mem";
+
+  containerizer.reset();
+
+  create = MesosContainerizer::create(flags, true, &fetcher);
+  ASSERT_SOME(create);
+
+  containerizer.reset(create.get());
+
+  slave = StartSlave(detector.get(), containerizer.get(), flags);
+  ASSERT_SOME(slave);
+
+  Clock::pause();
+  Clock::settle();
+  // Ensure the agent considers itself recovered.
+  Clock::advance(EXECUTOR_REREGISTER_TIMEOUT);
+  Clock::resume();
+
+  AWAIT_READY(__recover);
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {