[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mesos-commits
Subject:    [8/8] mesos git commit: Maintenance Primitives: Added maintenance status endpoint.
From:       joris () apache ! org
Date:       2015-08-31 17:19:31
Message-ID: 6817290223814daf81c12b1d88a1fe29 () git ! apache ! org
[Download RAW message or body]

Maintenance Primitives: Added maintenance status endpoint.

Endpoint: /maintenance/status
  Retrieves the maintenance status of machines.

Also adds a protobuf for the purpose of serialization.

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


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

Branch: refs/heads/master
Commit: 09e4ba2faf8eb8f4b82b640b641ec4199a11001d
Parents: bf4ca54
Author: Joseph Wu <joseph@mesosphere.io>
Authored: Sun Aug 30 13:56:45 2015 -0400
Committer: Joris Van Remoortere <joris.van.remoortere@gmail.com>
Committed: Mon Aug 31 13:15:18 2015 -0400

----------------------------------------------------------------------
 include/mesos/maintenance/maintenance.proto |  10 ++
 src/master/http.cpp                         |  41 +++++++
 src/master/master.cpp                       |   6 +
 src/master/master.hpp                       |   5 +
 src/tests/master_maintenance_tests.cpp      | 139 +++++++++++++++++++++++
 5 files changed, 201 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/09e4ba2f/include/mesos/maintenance/maintenance.proto
----------------------------------------------------------------------
diff --git a/include/mesos/maintenance/maintenance.proto b/include/mesos/maintenance/maintenance.proto
index ba28d0f..ee01c5d 100644
--- a/include/mesos/maintenance/maintenance.proto
+++ b/include/mesos/maintenance/maintenance.proto
@@ -65,3 +65,13 @@ message Window {
 message Schedule {
   repeated Window windows = 1;
 }
+
+
+/**
+ * Represents the maintenance status of each machine in the cluster.
+ * Corresponds to the `MachineInfo.Mode` enumeration.
+ */
+message ClusterStatus {
+  repeated MachineID draining_machines = 1;
+  repeated MachineID down_machines = 2;
+}

http://git-wip-us.apache.org/repos/asf/mesos/blob/09e4ba2f/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index 6fad959..94e97a2 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -1651,6 +1651,47 @@ Future<Response> Master::Http::machineUp(const Request& request) const
 }
 
 
+// /master/maintenance/status endpoint help.
+const string Master::Http::MAINTENANCE_STATUS_HELP = HELP(
+    TLDR(
+        "Retrieves the maintenance status of the cluster."),
+    USAGE(
+        "/master/maintenance/status"),
+    DESCRIPTION(
+        "Returns an object with one list of machines per machine mode."));
+
+
+// /master/maintenance/status endpoint handler.
+Future<Response> Master::Http::maintenanceStatus(const Request& request) const
+{
+  if (request.method != "GET") {
+    return BadRequest("Expecting GET, got '" + request.method + "'");
+  }
+
+  // Unwrap the master's machine information into two arrays of machines.
+  mesos::maintenance::ClusterStatus status;
+  foreachkey (const MachineID& id, master->machineInfos) {
+    switch (master->machineInfos[id].mode()) {
+      case MachineInfo::DRAINING: {
+        status.add_draining_machines()->CopyFrom(id);
+        break;
+      }
+      case MachineInfo::DOWN: {
+        status.add_down_machines()->CopyFrom(id);
+        break;
+      }
+      // Currently, `UP` machines are not specifically tracked in the master.
+      case MachineInfo::UP: {}
+      default: {
+        break;
+      }
+    }
+  }
+
+  return OK(JSON::Protobuf(status), request.query.get("jsonp"));
+}
+
+
 Result<Credential> Master::Http::authenticate(const Request& request) const
 {
   // By default, assume everyone is authenticated if no credentials

http://git-wip-us.apache.org/repos/asf/mesos/blob/09e4ba2f/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index cd1b386..56bcbcc 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -821,6 +821,12 @@ void Master::initialize()
           Http::log(request);
           return http.maintenanceSchedule(request);
         });
+  route("/maintenance/status",
+        Http::MAINTENANCE_STATUS_HELP,
+        [http](const process::http::Request& request) {
+          Http::log(request);
+          return http.maintenanceStatus(request);
+        });
   route("/machine/down",
         Http::MACHINE_DOWN_HELP,
         [http](const process::http::Request& request) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/09e4ba2f/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 68be718..594dd25 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -836,6 +836,10 @@ private:
     process::Future<process::http::Response> maintenanceSchedule(
         const process::http::Request& request) const;
 
+    // /master/maintenance/status
+    process::Future<process::http::Response> maintenanceStatus(
+        const process::http::Request& request) const;
+
     // /master/machine/down
     process::Future<process::http::Response> machineDown(
         const process::http::Request& request) const;
@@ -855,6 +859,7 @@ private:
     const static std::string STATESUMMARY_HELP;
     const static std::string TASKS_HELP;
     const static std::string MAINTENANCE_SCHEDULE_HELP;
+    const static std::string MAINTENANCE_STATUS_HELP;
     const static std::string MACHINE_DOWN_HELP;
     const static std::string MACHINE_UP_HELP;
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/09e4ba2f/src/tests/master_maintenance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_maintenance_tests.cpp b/src/tests/master_maintenance_tests.cpp
index c3acd7a..fb8dca3 100644
--- a/src/tests/master_maintenance_tests.cpp
+++ b/src/tests/master_maintenance_tests.cpp
@@ -239,6 +239,58 @@ TEST_F(MasterMaintenanceTest, UpdateSchedule)
 }
 
 
+// Tries to remove deactivated machines from the schedule.
+TEST_F(MasterMaintenanceTest, FailToUnscheduleDeactivatedMachines)
+{
+  // Set up a master.
+  Try<PID<Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  // Schedule two machines.
+  maintenance::Schedule schedule = createSchedule(
+      {createWindow({machine1, machine2}, unavailability)});
+
+  Future<Response> response = process::http::post(
+      master.get(),
+      "maintenance/schedule",
+      headers,
+      stringify(JSON::Protobuf(schedule)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Deactivate machine1.
+  MachineIDs machines = createMachineList({machine1});
+  response = process::http::post(
+      master.get(),
+      "machine/down",
+      headers,
+      stringify(JSON::Protobuf(machines)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Try to unschedule machine1, by posting a schedule without it.
+  schedule = createSchedule({createWindow({machine2}, unavailability)});
+
+  response = process::http::post(
+      master.get(),
+      "maintenance/schedule",
+      headers,
+      stringify(JSON::Protobuf(schedule)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response);
+
+  // Reactivate machine1.
+  machines = createMachineList({machine1});
+  response = process::http::post(
+      master.get(),
+      "machine/up",
+      headers,
+      stringify(JSON::Protobuf(machines)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+}
+
+
 // Posts valid and invalid machines to the maintenance start endpoint.
 TEST_F(MasterMaintenanceTest, BringDownMachines)
 {
@@ -448,6 +500,93 @@ TEST_F(MasterMaintenanceTest, BringUpMachines)
   ASSERT_EQ(0, masterSchedule.get().windows().size());
 }
 
+
+// Queries for machine statuses in between maintenance mode transitions.
+TEST_F(MasterMaintenanceTest, MachineStatus)
+{
+  // Set up a master.
+  Try<PID<Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  // Try to stop maintenance on an unscheduled machine.
+  maintenance::Schedule schedule = createSchedule(
+      {createWindow({machine1, machine2}, unavailability)});
+
+  Future<Response> response = process::http::post(
+      master.get(),
+      "maintenance/schedule",
+      headers,
+      stringify(JSON::Protobuf(schedule)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Get the maintenance statuses.
+  response = process::http::get(master.get(), "maintenance/status");
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Check that both machines are draining.
+  Try<JSON::Object> statuses_ =
+    JSON::parse<JSON::Object>(response.get().body);
+
+  ASSERT_SOME(statuses_);
+  Try<maintenance::ClusterStatus> statuses =
+    ::protobuf::parse<maintenance::ClusterStatus>(statuses_.get());
+
+  ASSERT_SOME(statuses);
+  ASSERT_EQ(2, statuses.get().draining_machines().size());
+  ASSERT_EQ(0, statuses.get().down_machines().size());
+
+  // Deactivate machine1.
+  MachineIDs machines = createMachineList({machine1});
+  response = process::http::post(
+      master.get(),
+      "machine/down",
+      headers,
+      stringify(JSON::Protobuf(machines)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Get the maintenance statuses.
+  response = process::http::get(master.get(), "maintenance/status");
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Check one machine is deactivated.
+  statuses_ = JSON::parse<JSON::Object>(response.get().body);
+
+  ASSERT_SOME(statuses_);
+  statuses = ::protobuf::parse<maintenance::ClusterStatus>(statuses_.get());
+
+  ASSERT_SOME(statuses);
+  ASSERT_EQ(1, statuses.get().draining_machines().size());
+  ASSERT_EQ(1, statuses.get().down_machines().size());
+  ASSERT_EQ("Machine1", statuses.get().down_machines(0).hostname());
+
+  // Reactivate machine1.
+  machines = createMachineList({machine1});
+  response = process::http::post(
+      master.get(),
+      "machine/up",
+      headers,
+      stringify(JSON::Protobuf(machines)));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Get the maintenance statuses.
+  response = process::http::get(master.get(), "maintenance/status");
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  // Check that only one machine remains.
+  statuses_ = JSON::parse<JSON::Object>(response.get().body);
+
+  ASSERT_SOME(statuses_);
+  statuses = ::protobuf::parse<maintenance::ClusterStatus>(statuses_.get());
+
+  ASSERT_SOME(statuses);
+  ASSERT_EQ(1, statuses.get().draining_machines().size());
+  ASSERT_EQ(0, statuses.get().down_machines().size());
+  ASSERT_EQ("0.0.0.2", statuses.get().draining_machines(0).ip());
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic