You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2015/09/14 19:58:48 UTC

[04/16] mesos git commit: Maintenance Primitives: Set offer `unavailability` for maintenance.

Maintenance Primitives: Set offer `unavailability` for maintenance.

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


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

Branch: refs/heads/master
Commit: ee1eb2ba6b17cba66ad99f4e6344416c2d2709d2
Parents: 9e7ee6b
Author: Joris Van Remoortere <jo...@gmail.com>
Authored: Tue Aug 25 18:39:35 2015 -0400
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Mon Sep 14 13:58:37 2015 -0400

----------------------------------------------------------------------
 include/mesos/type_utils.hpp           | 24 ++++++++
 include/mesos/v1/mesos.hpp             | 24 ++++++++
 src/master/master.cpp                  |  8 +++
 src/tests/master_maintenance_tests.cpp | 96 +++++++++++++++++++++++++++++
 4 files changed, 152 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/ee1eb2ba/include/mesos/type_utils.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/type_utils.hpp b/include/mesos/type_utils.hpp
index 4fb0037..64c2a86 100644
--- a/include/mesos/type_utils.hpp
+++ b/include/mesos/type_utils.hpp
@@ -108,6 +108,18 @@ inline bool operator==(const TaskID& left, const TaskID& right)
 }
 
 
+inline bool operator==(const TimeInfo& left, const TimeInfo& right)
+{
+  return left.nanoseconds() == right.nanoseconds();
+}
+
+
+inline bool operator==(const DurationInfo& left, const DurationInfo& right)
+{
+  return left.nanoseconds() == right.nanoseconds();
+}
+
+
 inline bool operator==(const ContainerID& left, const std::string& right)
 {
   return left.value() == right;
@@ -183,6 +195,18 @@ inline bool operator!=(const SlaveID& left, const SlaveID& right)
 }
 
 
+inline bool operator!=(const TimeInfo& left, const TimeInfo& right)
+{
+  return !(left == right);
+}
+
+
+inline bool operator!=(const DurationInfo& left, const DurationInfo& right)
+{
+  return !(left == right);
+}
+
+
 inline bool operator<(const ContainerID& left, const ContainerID& right)
 {
   return left.value() < right.value();

http://git-wip-us.apache.org/repos/asf/mesos/blob/ee1eb2ba/include/mesos/v1/mesos.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/v1/mesos.hpp b/include/mesos/v1/mesos.hpp
index 0d695f3..f8f9617 100644
--- a/include/mesos/v1/mesos.hpp
+++ b/include/mesos/v1/mesos.hpp
@@ -89,6 +89,18 @@ inline bool operator==(const TaskID& left, const TaskID& right)
 }
 
 
+inline bool operator==(const TimeInfo& left, const TimeInfo& right)
+{
+  return left.nanoseconds() == right.nanoseconds();
+}
+
+
+inline bool operator==(const DurationInfo& left, const DurationInfo& right)
+{
+  return left.nanoseconds() == right.nanoseconds();
+}
+
+
 inline bool operator==(const ContainerID& left, const std::string& right)
 {
   return left.value() == right;
@@ -125,6 +137,18 @@ inline bool operator==(const TaskID& left, const std::string& right)
 }
 
 
+inline bool operator!=(const TimeInfo& left, const TimeInfo& right)
+{
+  return !(left == right);
+}
+
+
+inline bool operator!=(const DurationInfo& left, const DurationInfo& right)
+{
+  return !(left == right);
+}
+
+
 inline bool operator!=(const ContainerID& left, const ContainerID& right)
 {
   return left.value() != right.value();

http://git-wip-us.apache.org/repos/asf/mesos/blob/ee1eb2ba/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 31fc83d..5c2f032 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -4654,6 +4654,14 @@ void Master::offer(const FrameworkID& frameworkId,
       }
     }
 
+    // If the slave in this offer is planned to be unavailable due to
+    // maintenance in the future, then set the Unavailability.
+    CHECK(machines.contains(slave->machineId));
+    if (machines[slave->machineId].info.has_unavailability()) {
+      offer->mutable_unavailability()->CopyFrom(
+          machines[slave->machineId].info.unavailability());
+    }
+
     offers[offer->id()] = offer;
 
     framework->addOffer(offer);

http://git-wip-us.apache.org/repos/asf/mesos/blob/ee1eb2ba/src/tests/master_maintenance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_maintenance_tests.cpp b/src/tests/master_maintenance_tests.cpp
index fb8dca3..5811446 100644
--- a/src/tests/master_maintenance_tests.cpp
+++ b/src/tests/master_maintenance_tests.cpp
@@ -63,6 +63,7 @@ using mesos::internal::protobuf::maintenance::createUnavailability;
 using mesos::internal::protobuf::maintenance::createWindow;
 
 using std::string;
+using std::vector;
 
 using testing::DoAll;
 
@@ -90,10 +91,18 @@ public:
     unavailability = createUnavailability(Clock::now());
   }
 
+  virtual slave::Flags CreateSlaveFlags()
+  {
+    slave::Flags slaveFlags = MesosTest::CreateSlaveFlags();
+    slaveFlags.hostname = maintenanceHostname;
+    return slaveFlags;
+  }
 
   // Default headers for all POST's to maintenance endpoints.
   hashmap<string, string> headers;
 
+  const string maintenanceHostname = "maintenance-host";
+
   // Some generic `MachineID`s that can be used in this test.
   MachineID machine1;
   MachineID machine2;
@@ -291,6 +300,93 @@ TEST_F(MasterMaintenanceTest, FailToUnscheduleDeactivatedMachines)
 }
 
 
+// Test ensures that an offer will have an `unavailability` set if the
+// slave is scheduled to go down for maintenance.
+TEST_F(MasterMaintenanceTest, PendingUnavailabilityTest)
+{
+  Try<PID<Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  Try<PID<Slave>> slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  // Intercept offers sent to the scheduler.
+  Future<vector<Offer>> normalOffers;
+  Future<vector<Offer>> unavailabilityOffers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&normalOffers))
+    .WillOnce(FutureArg<1>(&unavailabilityOffers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  // Start the test.
+  driver.start();
+
+  // Wait for some normal offers.
+  AWAIT_READY(normalOffers);
+  EXPECT_NE(0u, normalOffers.get().size());
+
+  // Check that unavailability is not set.
+  foreach (const Offer& offer, normalOffers.get()) {
+    EXPECT_FALSE(offer.has_unavailability());
+
+    // We have a few seconds between allocations (by default).  That should
+    // be enough time to post a schedule before the next allocation.
+    driver.declineOffer(offer.id());
+  }
+
+  // Schedule this slave for maintenance.
+  MachineID machine;
+  machine.set_hostname("maintenance-host");
+  machine.set_ip(stringify(slave.get().address.ip));
+
+  // TODO(jmlvanre): Replace Time(0.0) with `Clock::now()` once JSON double
+  // conversion is fixed. For now using a rounded time avoids the issue.
+  const Time start = Time::create(0.0).get() + Seconds(60);
+  const Duration duration = Seconds(120);
+  const Unavailability unavailability = createUnavailability(start, duration);
+
+  // Post a valid schedule with one machine.
+  maintenance::Schedule schedule = createSchedule({
+      createWindow({machine}, unavailability)});
+
+  Future<Response> response = process::http::post(
+      master.get(),
+      "maintenance/schedule",
+      headers,
+      stringify(JSON::Protobuf(schedule)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Speed up the test by not waiting until the next allocation.
+  driver.reviveOffers();
+
+  // Wait for some offers.
+  AWAIT_READY(unavailabilityOffers);
+  EXPECT_NE(0u, unavailabilityOffers.get().size());
+
+  // Check that each offer has an unavailability.
+  foreach (const Offer& offer, unavailabilityOffers.get()) {
+    EXPECT_TRUE(offer.has_unavailability());
+    EXPECT_EQ(unavailability.start(), offer.unavailability().start());
+    EXPECT_EQ(unavailability.duration(), offer.unavailability().duration());
+  }
+
+  driver.stop();
+  driver.join();
+
+  Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
+}
+
+
 // Posts valid and invalid machines to the maintenance start endpoint.
 TEST_F(MasterMaintenanceTest, BringDownMachines)
 {