Repository: mesos
Updated Branches:
  refs/heads/master 41b495ecf -> 1b592c167


Added support for removing capabilities on framework re-registration.

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


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

Branch: refs/heads/master
Commit: 1b592c16721576eddc4e7ce1167784ef5c43c111
Parents: 41b495e
Author: Aditi Dixit <[email protected]>
Authored: Mon Aug 24 15:53:07 2015 -0700
Committer: Vinod Kone <[email protected]>
Committed: Mon Aug 24 15:53:08 2015 -0700

----------------------------------------------------------------------
 src/master/allocator/mesos/hierarchical.hpp |  2 +
 src/master/master.hpp                       |  5 +-
 src/tests/oversubscription_tests.cpp        | 99 ++++++++++++++++++++++++
 3 files changed, 103 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/1b592c16/src/master/allocator/mesos/hierarchical.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/mesos/hierarchical.hpp 
b/src/master/allocator/mesos/hierarchical.hpp
index e278139..38f8fd2 100644
--- a/src/master/allocator/mesos/hierarchical.hpp
+++ b/src/master/allocator/mesos/hierarchical.hpp
@@ -492,6 +492,8 @@ HierarchicalAllocatorProcess<RoleSorter, 
FrameworkSorter>::updateFramework(
   CHECK_EQ(frameworks[frameworkId].role, frameworkInfo.role());
   CHECK_EQ(frameworks[frameworkId].checkpoint, frameworkInfo.checkpoint());
 
+  frameworks[frameworkId].revocable = false;
+
   foreach (const FrameworkInfo::Capability& capability,
            frameworkInfo.capabilities()) {
     if (capability.type() == FrameworkInfo::Capability::REVOCABLE_RESOURCES) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/1b592c16/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 0432842..36c6759 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -1563,11 +1563,10 @@ struct Framework
       info.clear_webui_url();
     }
 
-    // TODO(aditidixit): Add the case where the capabilities are
-    // previously set but now being unset. (MESOS-2880)
-
     if (source.capabilities_size() > 0) {
       info.mutable_capabilities()->CopyFrom(source.capabilities());
+    } else {
+      info.clear_capabilities();
     }
 
     if (source.has_labels()) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/1b592c16/src/tests/oversubscription_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/oversubscription_tests.cpp 
b/src/tests/oversubscription_tests.cpp
index d41f030..0c5edaf 100644
--- a/src/tests/oversubscription_tests.cpp
+++ b/src/tests/oversubscription_tests.cpp
@@ -997,6 +997,105 @@ TEST_F(OversubscriptionTest, 
UpdateAllocatorOnSchedulerFailover)
   Shutdown();
 }
 
+TEST_F(OversubscriptionTest, RemoveCapabilitiesOnSchedulerFailover)
+{
+  // Start the master.
+  Try<PID<Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  // Start the slave with mock executor and test resource estimator.
+  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);
+
+  // Start the framework which accepts revocable resources.
+  FrameworkInfo framework1 = DEFAULT_FRAMEWORK_INFO;
+  framework1.add_capabilities()->set_type(
+      FrameworkInfo::Capability::REVOCABLE_RESOURCES);
+
+  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();
+
+  // Initially the framework will get all regular resources.
+  AWAIT_READY(offers1);
+  EXPECT_NE(0u, offers1.get().size());
+  EXPECT_TRUE(Resources(offers1.get()[0].resources()).revocable().empty());
+
+  Future<vector<Offer>> offers2;
+  EXPECT_CALL(sched1, resourceOffers(&driver1, _))
+    .WillOnce(FutureArg<1>(&offers2))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  // Inject an estimation of oversubscribable cpu resources.
+  Resources taskResources = createRevocableResources("cpus", "1");
+  Resources executorResources = createRevocableResources("cpus", "1");
+  estimations.put(taskResources + executorResources);
+
+  // Now the framework will get revocable resources.
+  AWAIT_READY(offers2);
+  EXPECT_NE(0u, offers2.get().size());
+  EXPECT_EQ(
+      taskResources + executorResources,
+      Resources(offers2.get()[0].resources()));
+
+  // Reregister the framework with removal of revocable resources capability.
+  FrameworkInfo framework2 = DEFAULT_FRAMEWORK_INFO;
+  framework2.mutable_id()->MergeFrom(frameworkId.get());
+
+  MockScheduler sched2;
+  MesosSchedulerDriver driver2(
+      &sched2, framework2, master.get(), DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched2, registered(&driver2, _, _));
+
+  // 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));
+
+  Future<vector<Offer>> offers3;
+  EXPECT_CALL(sched2, resourceOffers(&driver2, _))
+    .WillOnce(FutureArg<1>(&offers3))
+    .WillRepeatedly(Return());
+
+  driver2.start();
+
+  AWAIT_READY(offers3);
+  EXPECT_NE(0u, offers3.get().size());
+  EXPECT_TRUE(Resources(offers3.get()[0].resources()).revocable().empty());
+
+  driver1.stop();
+  driver1.join();
+
+  Shutdown();
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

Reply via email to