Repository: mesos
Updated Branches:
  refs/heads/master 8e0d6549d -> b6d14eb32


Added test for allocator update of framework info on scheduler
failover.

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


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

Branch: refs/heads/master
Commit: b6d14eb327613a5344e0528d4083bedf93a836f9
Parents: 8e0d654
Author: Aditi Dixit <[email protected]>
Authored: Thu Aug 6 10:16:23 2015 -0700
Committer: Vinod Kone <[email protected]>
Committed: Thu Aug 6 10:17:32 2015 -0700

----------------------------------------------------------------------
 src/tests/oversubscription_tests.cpp | 126 ++++++++++++++++++++++++++++++
 1 file changed, 126 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/b6d14eb3/src/tests/oversubscription_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/oversubscription_tests.cpp 
b/src/tests/oversubscription_tests.cpp
index 26ef5de..d41f030 100644
--- a/src/tests/oversubscription_tests.cpp
+++ b/src/tests/oversubscription_tests.cpp
@@ -871,6 +871,132 @@ TEST_F(OversubscriptionTest, QoSCorrectionKill)
 
   Shutdown();
 }
+
+
+// This test verifies that when a framework re-registers with updated
+// FrameworkInfo, it gets updated in the allocator. The steps involved
+// are:
+//   1. Launch a master, slave and scheduler.
+//   2. Record FrameworkID of launched scheduler.
+//   3. Check if revocable offers are being sent to the framework.
+//   4. Launch a second scheduler which has the same FrameworkID as
+//      the first scheduler and also has updated FrameworkInfo.
+//   5. Check if revocable offers are being sent to the framework.
+TEST_F(OversubscriptionTest, UpdateAllocatorOnSchedulerFailover)
+{
+  Try<PID<Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  MockResourceEstimator resourceEstimator;
+
+  EXPECT_CALL(resourceEstimator, initialize(_));
+
+  Queue<Resources> estimations;
+  EXPECT_CALL(resourceEstimator, oversubscribable())
+    .WillOnce(InvokeWithoutArgs(&estimations, &Queue<Resources>::get));
+
+  slave::Flags flags = CreateSlaveFlags();
+
+  Try<PID<Slave>> slave = StartSlave(&exec, &resourceEstimator, flags);
+  ASSERT_SOME(slave);
+
+  // Launch the first (i.e., failing) scheduler and wait until
+  // registered gets called to launch the second (i.e., failover)
+  // scheduler with updated information.
+
+  FrameworkInfo framework1 = DEFAULT_FRAMEWORK_INFO;
+
+  MockScheduler sched1;
+  MesosSchedulerDriver driver1(
+      &sched1, framework1, master.get(), DEFAULT_CREDENTIAL);
+
+  Future<FrameworkID> frameworkId;
+  EXPECT_CALL(sched1, registered(&driver1, _, _))
+    .WillOnce(FutureArg<1>(&frameworkId));
+
+  Future<vector<Offer>> offers1;
+  EXPECT_CALL(sched1, resourceOffers(&driver1, _))
+    .WillOnce(FutureArg<1>(&offers1));
+
+  driver1.start();
+
+  // Framework doesn't receive revocable resources because
+  // it doesn't have the capability set.
+
+  AWAIT_READY(offers1);
+  EXPECT_NE(0u, offers1.get().size());
+  EXPECT_TRUE(Resources(offers1.get()[0].resources()).revocable().empty());
+
+  // Now launch the second (i.e., failover) scheduler using the
+  // framework id recorded from the first scheduler, along with the
+  // updated FrameworkInfo and wait until it gets a registered
+  // callback.
+
+  MockScheduler sched2;
+
+  FrameworkInfo framework2 = DEFAULT_FRAMEWORK_INFO;
+  framework2.mutable_id()->MergeFrom(frameworkId.get());
+  auto capabilityType = FrameworkInfo::Capability::REVOCABLE_RESOURCES;
+  framework2.add_capabilities()->set_type(capabilityType);
+
+  MesosSchedulerDriver driver2(
+      &sched2, framework2, master.get(), DEFAULT_CREDENTIAL);
+
+  Future<Nothing> sched2Registered;
+  EXPECT_CALL(sched2, registered(&driver2, frameworkId.get(), _))
+    .WillOnce(FutureSatisfy(&sched2Registered));
+
+  // Scheduler1's expectations.
+
+  EXPECT_CALL(sched1, offerRescinded(&driver1, _))
+    .Times(AtMost(1));
+
+  Future<Nothing> sched1Error;
+  EXPECT_CALL(sched1, error(&driver1, "Framework failed over"))
+    .WillOnce(FutureSatisfy(&sched1Error));
+
+  EXPECT_CALL(sched2, resourceOffers(&driver2, _))
+    .WillOnce(FutureArg<1>(&offers1));
+
+  // Initially the framework will get all regular resources.
+
+  driver2.start();
+
+  AWAIT_READY(offers1);
+  EXPECT_NE(0u, offers1.get().size());
+  EXPECT_TRUE(Resources(offers1.get()[0].resources()).revocable().empty());
+
+  AWAIT_READY(sched2Registered);
+
+  AWAIT_READY(sched1Error);
+
+  // Check if framework receives revocable offers.
+
+  Resources taskResources = createRevocableResources("cpus", "1");
+  Resources executorResources = createRevocableResources("cpus", "1");
+  estimations.put(taskResources + executorResources);
+
+  Future<vector<Offer>> offers2;
+  EXPECT_CALL(sched2, resourceOffers(&driver2, _))
+    .WillOnce(FutureArg<1>(&offers2))
+    .WillRepeatedly(Return());
+
+  AWAIT_READY(offers2);
+  EXPECT_NE(0u, offers2.get().size());
+  EXPECT_EQ(taskResources + executorResources,
+            Resources(offers2.get()[0].resources()));
+
+  EXPECT_EQ(DRIVER_STOPPED, driver2.stop());
+  EXPECT_EQ(DRIVER_STOPPED, driver2.join());
+
+  EXPECT_EQ(DRIVER_ABORTED, driver1.stop());
+  EXPECT_EQ(DRIVER_STOPPED, driver1.join());
+
+  Shutdown();
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

Reply via email to