Repository: mesos
Updated Branches:
  refs/heads/master a9c1c775b -> 0a610695e


Captured the `stderr` during execution of CNI plugin.

Till now we were capturing only the `stdout` of the CNI plugin.
However, during errors it makes sense to add the output from `stderr`
for the CNI plugin as well, since as per the CNI spec the CNI plugin
is supposed to output all unstructured output (debugs for example) to
`stderr`. This greatly helps in debugging the exact reason for CNI
plugin failures.

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


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

Branch: refs/heads/master
Commit: 0a610695e42e7b221d87c9c9ce0c29a3bd56ac26
Parents: a9c1c77
Author: Avinash sridharan <avin...@mesosphere.io>
Authored: Mon Oct 17 17:37:04 2016 -0700
Committer: Jie Yu <yujie....@gmail.com>
Committed: Mon Oct 17 17:57:19 2016 -0700

----------------------------------------------------------------------
 .../mesos/isolators/network/cni/cni.cpp         | 46 ++++++++++++++------
 .../mesos/isolators/network/cni/cni.hpp         |  2 +
 2 files changed, 35 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/0a610695/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp 
b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
index 7c35c30..ae78c65 100644
--- a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
+++ b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
@@ -1150,7 +1150,7 @@ Future<Nothing> NetworkCniIsolatorProcess::attach(
       {networkConfig.config.type()},
       Subprocess::PATH(networkConfigPath),
       Subprocess::PIPE(),
-      Subprocess::PATH("/dev/null"),
+      Subprocess::PIPE(),
       nullptr,
       environment);
 
@@ -1160,7 +1160,7 @@ Future<Nothing> NetworkCniIsolatorProcess::attach(
         plugin.get() + "': " + s.error());
   }
 
-  return await(s->status(), io::read(s->out().get()))
+  return await(s->status(), io::read(s->out().get()), io::read(s->err().get()))
     .then(defer(
         PID<NetworkCniIsolatorProcess>(this),
         &NetworkCniIsolatorProcess::_attach,
@@ -1175,7 +1175,7 @@ Future<Nothing> NetworkCniIsolatorProcess::_attach(
     const ContainerID& containerId,
     const string& networkName,
     const string& plugin,
-    const tuple<Future<Option<int>>, Future<string>>& t)
+    const tuple<Future<Option<int>>, Future<string>, Future<string>>& t)
 {
   CHECK(infos.contains(containerId));
   CHECK(infos[containerId]->containerNetworks.contains(networkName));
@@ -1204,10 +1204,18 @@ Future<Nothing> NetworkCniIsolatorProcess::_attach(
   }
 
   if (status.get() != 0) {
+    Future<string> error = std::get<2>(t);
+    if (!error.isReady()) {
+      return Failure(
+          "Failed to read stderr from the CNI plugin '" +
+          plugin + "' subprocess: " +
+          (error.isFailed() ? error.failure() : "discarded"));
+    }
+
     return Failure(
         "The CNI plugin '" + plugin + "' failed to attach container " +
-        containerId.value() + " to CNI network '" + networkName +
-        "': " + output.get());
+        stringify(containerId) + " to CNI network '" + networkName +
+        "': stdout='" + output.get() + "', stderr='" + error.get() + "'");
   }
 
   // Parse the output of CNI plugin.
@@ -1215,7 +1223,7 @@ Future<Nothing> NetworkCniIsolatorProcess::_attach(
   if (parse.isError()) {
     return Failure(
         "Failed to parse the output of the CNI plugin '" +
-        plugin + "': " + parse.error());
+        plugin + "' :" + parse.error());
   }
 
   if (parse.get().has_ip4()) {
@@ -1472,12 +1480,14 @@ Future<Nothing> NetworkCniIsolatorProcess::detach(
           << "' to detach container " << containerId << " from network '"
           << networkName << "'";
 
+  // NOTE: For 'DEL' the CNI plugin is not expected to return any
+  // result, hence setting the STDOUT to /dev/null.
   Try<Subprocess> s = subprocess(
       plugin.get(),
       {networkConfig.config.type()},
       Subprocess::PATH(networkConfigPath),
       Subprocess::PIPE(),
-      Subprocess::PATH("/dev/null"),
+      Subprocess::PIPE(),
       nullptr,
       environment);
 
@@ -1487,7 +1497,10 @@ Future<Nothing> NetworkCniIsolatorProcess::detach(
         "': " + s.error());
   }
 
-  return await(s->status(), io::read(s->out().get()))
+  return await(
+      s->status(),
+      io::read(s->out().get()),
+      io::read(s->err().get()))
     .then(defer(
         PID<NetworkCniIsolatorProcess>(this),
         &NetworkCniIsolatorProcess::_detach,
@@ -1502,7 +1515,7 @@ Future<Nothing> NetworkCniIsolatorProcess::_detach(
     const ContainerID& containerId,
     const string& networkName,
     const string& plugin,
-    const tuple<Future<Option<int>>, Future<string>>& t)
+    const tuple<Future<Option<int>>, Future<string>, Future<string>>& t)
 {
   CHECK(infos.contains(containerId));
   CHECK(infos[containerId]->containerNetworks.contains(networkName));
@@ -1537,8 +1550,6 @@ Future<Nothing> NetworkCniIsolatorProcess::_detach(
     return Nothing();
   }
 
-  // CNI plugin will print result (in case of success) or error (in
-  // case of failure) to stdout.
   Future<string> output = std::get<1>(t);
   if (!output.isReady()) {
     return Failure(
@@ -1547,9 +1558,18 @@ Future<Nothing> NetworkCniIsolatorProcess::_detach(
         (output.isFailed() ? output.failure() : "discarded"));
   }
 
+  Future<string> error = std::get<2>(t);
+  if (!error.isReady()) {
+    return Failure(
+        "Failed to read stderr from the CNI plugin '" +
+        plugin + "' subprocess: " +
+        (error.isFailed() ? error.failure() : "discarded"));
+  }
+
   return Failure(
-      "The CNI plugin '" + plugin + "' failed to detach container "
-      "from network '" + networkName + "': " + output.get());
+      "The CNI plugin '" + plugin + "' failed to detach container " +
+      stringify(containerId) + " from CNI network '" + networkName +
+      "': stdout='" + output.get() + "', stderr='" + error.get() + "'");
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/0a610695/src/slave/containerizer/mesos/isolators/network/cni/cni.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/cni/cni.hpp 
b/src/slave/containerizer/mesos/isolators/network/cni/cni.hpp
index a6861fc..b8fc755 100644
--- a/src/slave/containerizer/mesos/isolators/network/cni/cni.hpp
+++ b/src/slave/containerizer/mesos/isolators/network/cni/cni.hpp
@@ -151,6 +151,7 @@ private:
       const std::string& plugin,
       const std::tuple<
           process::Future<Option<int>>,
+          process::Future<std::string>,
           process::Future<std::string>>& t);
 
   process::Future<Nothing> detach(
@@ -163,6 +164,7 @@ private:
       const std::string& plugin,
       const std::tuple<
           process::Future<Option<int>>,
+          process::Future<std::string>,
           process::Future<std::string>>& t);
 
   process::Future<Nothing> _cleanup(

Reply via email to