You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2016/10/13 00:52:50 UTC
mesos git commit: Implemented `delegate` method.
Repository: mesos
Updated Branches:
refs/heads/master 8b4d83aec -> 99cbe69eb
Implemented `delegate` method.
Review: https://reviews.apache.org/r/51769/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/99cbe69e
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/99cbe69e
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/99cbe69e
Branch: refs/heads/master
Commit: 99cbe69eb4dd7e5bcac7a5df4134d1af9e4a00b8
Parents: 8b4d83a
Author: Avinash sridharan <av...@mesosphere.io>
Authored: Wed Oct 12 16:04:43 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Oct 12 17:52:46 2016 -0700
----------------------------------------------------------------------
.../cni/plugins/port_mapper/port_mapper.cpp | 154 ++++++++++++++++++-
1 file changed, 148 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/99cbe69e/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp b/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp
index 0473645..2ff8b0e 100644
--- a/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp
+++ b/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp
@@ -25,11 +25,19 @@
#include "slave/containerizer/mesos/isolators/network/cni/spec.hpp"
#include "slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.hpp"
+namespace io = process::io;
+
+using std::cerr;
+using std::endl;
+using std::map;
using std::string;
+using std::tuple;
using std::vector;
+using process::Failure;
using process::Future;
using process::Owned;
+using process::Subprocess;
using mesos::NetworkInfo;
@@ -180,19 +188,23 @@ Try<Owned<PortMapper>, PluginError> PortMapper::create(const string& _cniConfig)
// 'delegate' as it should be a valid CNI config JSON.
// Make sure the 'delegate' plugin exists.
- Result<JSON::String> delegatePlugin =
+ Result<JSON::String> _delegatePlugin =
_delegateConfig->find<JSON::String>("type");
- if (!delegatePlugin.isSome()) {
+ if (!_delegatePlugin.isSome()) {
return PluginError(
"Failed to get the delegate plugin 'type'" +
- (delegatePlugin.isError() ? delegatePlugin.error() : "Not found"),
+ (_delegatePlugin.isError() ? _delegatePlugin.error() : "Not found"),
ERROR_BAD_ARGS);
}
- if (os::which(delegatePlugin->value, cniPath.get()).isNone()) {
+ Option<string> delegatePlugin = os::which(
+ _delegatePlugin->value,
+ cniPath.get());
+
+ if (delegatePlugin.isNone()) {
return PluginError(
- "Could not find the delegate plugin '" + delegatePlugin->value +
+ "Could not find the delegate plugin '" + _delegatePlugin->value +
"' in '" + cniPath.get() + "'",
ERROR_BAD_ARGS);
}
@@ -211,7 +223,7 @@ Try<Owned<PortMapper>, PluginError> PortMapper::create(const string& _cniConfig)
cniArgs,
cniPath.get(),
networkInfo.get(),
- delegatePlugin->value,
+ delegatePlugin.get(),
delegateConfig,
chain->value,
excludeDevices));
@@ -226,6 +238,136 @@ Try<Option<string>, PluginError> PortMapper::execute()
Result<spec::NetworkInfo> PortMapper::delegate(const string& command)
{
+ map<std::string, std::string> environment;
+
+ environment["CNI_COMMAND"] = command;
+ environment["CNI_IFNAME"] = cniIfName;
+ environment["CNI_NETNS"] = cniNetNs;
+ environment["CNI_PATH"] = cniPath;
+
+ if (cniContainerId.isSome()) {
+ environment["CNI_CONTAINERID"] = cniContainerId.get();
+ }
+
+ if (cniArgs.isSome()) {
+ environment["CNI_ARGS"] = cniArgs.get();
+ }
+
+ // Some CNI plugins need to run "iptables" to set up IP Masquerade,
+ // so we need to set the "PATH" environment variable so that the
+ // plugin can locate the "iptables" executable file.
+ Option<string> value = os::getenv("PATH");
+ if (value.isSome()) {
+ environment["PATH"] = value.get();
+ } else {
+ environment["PATH"] =
+ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
+ }
+
+ Try<string> temp = os::mktemp();
+ if (temp.isError()) {
+ return Error("Failed to create the temp file: " + temp.error());
+ }
+
+ Try<Nothing> write = os::write(
+ temp.get(),
+ stringify(delegateConfig));
+
+ if (write.isError()) {
+ os::rm(temp.get());
+ return Error("Failed to write the temp file: " + write.error());
+ }
+
+ Try<Subprocess> s = process::subprocess(
+ delegatePlugin,
+ {delegatePlugin},
+ Subprocess::PATH(temp.get()),
+ Subprocess::PIPE(),
+ Subprocess::PIPE(),
+ nullptr,
+ environment);
+
+ if (s.isError()) {
+ return Error(
+ "Failed to exec the '" + delegatePlugin +
+ "' subprocess: " + s.error());
+ }
+
+ auto result = await(
+ s->status(),
+ io::read(s->out().get()),
+ io::read(s->err().get()));
+
+ result.await();
+
+ // At this point the subprocess has completed and hence we need to
+ // remove the `temp` file that we created.
+ os::rm(temp.get());
+
+ if (!result.isReady()) {
+ return Error(
+ "Failed to wait for exec of delegate CNI plugin '" +
+ delegatePlugin + "': " +
+ (result.isDiscarded() ? "discarded" : result.failure()));
+ }
+
+ Future<Option<int>> status = std::get<0>(result.get());
+ if (!status.isReady()) {
+ return Error(
+ "Failed to get the exit status of the delegate CNI plugin '" +
+ delegatePlugin + "' subprocess: " +
+ (status.isFailed() ? status.failure() : "discarded"));
+ }
+
+ if (status->isNone()) {
+ return Error(
+ "Failed to reap the delegate CNI plugin '" +
+ delegatePlugin + "' subprocess");
+ }
+
+ // CNI plugin will print result or error to stdout.
+ Future<string> output = std::get<1>(result.get());
+ if (!output.isReady()) {
+ return Error(
+ "Failed to read stdout from the delegate CNI plugin '" +
+ delegatePlugin + "' subprocess: " +
+ (output.isFailed() ? output.failure() : "discarded"));
+ }
+
+ // We are reading stderr of the plugin since any log messages from
+ // the CNI plugin would be thrown on stderr. This can be useful for
+ // debugging issues when the plugin throws a `spec::Error`.
+ Future<string> err = std::get<2>(result.get());
+ if (!err.isReady()) {
+ return Error(
+ "Failed to read STDERR from the delegate CNI plugin '" +
+ delegatePlugin + "' subprocess: " +
+ (err.isFailed() ? err.failure() : "discarded"));
+ }
+
+ if (status.get() != 0) {
+ cerr << "Delegate plugin reported error: " << err.get() << endl;
+
+ return Error(
+ "The delegate CNI plugin '" + delegatePlugin +
+ "' return status " + stringify(status->get()) +
+ ". Could not attach container: " + output.get());
+ }
+
+ if (command == spec::CNI_CMD_ADD) {
+ // Parse the output of CNI plugin.
+ Try<spec::NetworkInfo> parse = spec::parseNetworkInfo(output.get());
+ if (parse.isError()) {
+ return Error(
+ "Failed to parse the output of the delegate CNI plugin '" +
+ delegatePlugin + "': " + parse.error());
+ }
+
+ return parse.get();
+ }
+
+ // For `spec::CNI_CMD_DEL` CNI plugins don't return a result. They
+ // will report an error if any, which should be captured above.
return None();
}