You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by al...@apache.org on 2016/08/28 15:04:07 UTC

[07/10] mesos git commit: Added support for HTTP/HTTPS health checks.

Added support for HTTP/HTTPS health checks.

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


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

Branch: refs/heads/master
Commit: 2b80207d1f05aa9dcb5747d161de84aada41643c
Parents: 7380d13
Author: haosdent huang <ha...@gmail.com>
Authored: Fri Aug 26 16:33:41 2016 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Sun Aug 28 16:42:57 2016 +0200

----------------------------------------------------------------------
 src/health-check/health_checker.cpp | 117 ++++++++++++++++++++++++++++++-
 src/health-check/health_checker.hpp |   7 ++
 2 files changed, 123 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/2b80207d/src/health-check/health_checker.cpp
----------------------------------------------------------------------
diff --git a/src/health-check/health_checker.cpp b/src/health-check/health_checker.cpp
index 097117a..4dd573b 100644
--- a/src/health-check/health_checker.cpp
+++ b/src/health-check/health_checker.cpp
@@ -31,6 +31,8 @@
 
 #include <process/collect.hpp>
 #include <process/delay.hpp>
+#include <process/http.hpp>
+#include <process/io.hpp>
 #include <process/subprocess.hpp>
 
 #include <stout/duration.hpp>
@@ -57,12 +59,20 @@ using process::UPID;
 
 using std::map;
 using std::string;
+using std::tuple;
 using std::vector;
 
 namespace mesos {
 namespace internal {
 namespace health {
 
+static const string DEFAULT_HTTP_SCHEME = "http";
+
+// Use '127.0.0.1' instead of 'localhost', because the host
+// file in some container images may not contain 'localhost'.
+static const string DEFAULT_DOMAIN = "127.0.0.1";
+
+
 Try<Owned<HealthChecker>> HealthChecker::create(
     const HealthCheck& check,
     const UPID& executor,
@@ -318,7 +328,112 @@ Future<Nothing> HealthCheckerProcess::_httpHealthCheck()
   CHECK_EQ(HealthCheck::HTTP, check.type());
   CHECK(check.has_http());
 
-  promise.fail("HTTP health check is not supported");
+  const HealthCheck::HTTPCheckInfo& http = check.http();
+
+  const string scheme = http.has_scheme() ? http.scheme() : DEFAULT_HTTP_SCHEME;
+  const string path = http.has_path() ? http.path() : "";
+  const string url = scheme + "://" + DEFAULT_DOMAIN + ":" +
+                     stringify(http.port()) + path;
+
+  VLOG(1) << "Launching HTTP health check '" << url << "'";
+
+  const vector<string> argv = {
+    "curl",
+    "-s",                 // Don't show progress meter or error messages.
+    "-S",                 // Makes curl show an error message if it fails.
+    "-L",                 // Follows HTTP 3xx redirects.
+    "-k",                 // Ignores SSL validation when scheme is https.
+    "-w", "%{http_code}", // Displays HTTP response code on stdout.
+    "-o", "/dev/null",    // Ignores output.
+    url
+  };
+
+  Try<Subprocess> s = subprocess(
+      "curl",
+      argv,
+      Subprocess::PATH("/dev/null"),
+      Subprocess::PIPE(),
+      Subprocess::PIPE());
+
+  if (s.isError()) {
+    return Failure("Failed to create the curl subprocess: " + s.error());
+  }
+
+  pid_t curlPid = s->pid();
+  Duration timeout = Seconds(check.timeout_seconds());
+
+  return await(
+      s->status(),
+      process::io::read(s->out().get()),
+      process::io::read(s->err().get()))
+    .after(timeout,
+      [timeout, curlPid](Future<tuple<Future<Option<int>>,
+                                      Future<string>,
+                                      Future<string>>> future) {
+      future.discard();
+
+      if (curlPid != -1) {
+        // Cleanup the curl process.
+        VLOG(1) << "Killing the HTTP health check process " << curlPid;
+
+        os::killtree(curlPid, SIGKILL);
+      }
+
+      return Failure(
+          "curl has not returned after " + stringify(timeout) + "; aborting");
+    })
+    .then(defer(self(), &Self::__httpHealthCheck, lambda::_1));
+}
+
+
+Future<Nothing> HealthCheckerProcess::__httpHealthCheck(
+    const tuple<
+        Future<Option<int>>,
+        Future<string>,
+        Future<string>>& t)
+{
+  Future<Option<int>> status = std::get<0>(t);
+  if (!status.isReady()) {
+    return Failure(
+        "Failed to get the exit status of the curl process: " +
+        (status.isFailed() ? status.failure() : "discarded"));
+  }
+
+  if (status->isNone()) {
+    return Failure("Failed to reap the curl process");
+  }
+
+  int statusCode = status->get();
+  if (statusCode != 0) {
+    Future<string> error = std::get<2>(t);
+    if (!error.isReady()) {
+      return Failure("curl returned " + WSTRINGIFY(statusCode) +
+                     "; reading stderr failed: " +
+                     (error.isFailed() ? error.failure() : "discarded"));
+    }
+
+    return Failure("curl returned " + WSTRINGIFY(statusCode) + ": " +
+                   error.get());
+  }
+
+  Future<string> output = std::get<1>(t);
+  if (!output.isReady()) {
+    return Failure("Failed to read stdout from curl: " +
+                   (output.isFailed() ? output.failure() : "discarded"));
+  }
+
+  // Parse the output and get the HTTP response code.
+  Try<int> code = numify<int>(output.get());
+  if (code.isError()) {
+    return Failure("Unexpected output from curl: " + output.get());
+  }
+
+  if (code.get() < process::http::Status::OK ||
+      code.get() >= process::http::Status::BAD_REQUEST) {
+    return Failure(
+        "Unexpected HTTP response code: " +
+        process::http::Status::string(code.get()));
+  }
 
   return Nothing();
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/2b80207d/src/health-check/health_checker.hpp
----------------------------------------------------------------------
diff --git a/src/health-check/health_checker.hpp b/src/health-check/health_checker.hpp
index 83cedfb..83a3384 100644
--- a/src/health-check/health_checker.hpp
+++ b/src/health-check/health_checker.hpp
@@ -18,6 +18,7 @@
 #define __HEALTH_CHECKER_HPP__
 
 #include <string>
+#include <tuple>
 
 #include <mesos/mesos.hpp>
 
@@ -82,6 +83,12 @@ private:
 
   process::Future<Nothing> _httpHealthCheck();
 
+  process::Future<Nothing> __httpHealthCheck(
+      const std::tuple<
+          process::Future<Option<int>>,
+          process::Future<std::string>,
+          process::Future<std::string>>& t);
+
   process::Future<Nothing> _tcpHealthCheck();
 
   void reschedule();