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/12/07 00:07:46 UTC
[4/6] mesos git commit: Added implementation of `watch()` to the
'IOSwitchboard' isolator.
Added implementation of `watch()` to the 'IOSwitchboard' isolator.
We use watch() to trigger the destruction of a container if the
io switchboard server process ever exits unexpectedly.
Review: https://reviews.apache.org/r/54356/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/052abf15
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/052abf15
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/052abf15
Branch: refs/heads/master
Commit: 052abf154510a9047019197e37857e8e26daab72
Parents: 4069e1c
Author: Kevin Klues <kl...@gmail.com>
Authored: Tue Dec 6 15:21:50 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Tue Dec 6 15:21:50 2016 -0800
----------------------------------------------------------------------
include/mesos/mesos.proto | 1 +
include/mesos/v1/mesos.proto | 1 +
.../containerizer/mesos/io/switchboard.cpp | 54 +++++++++++++++
.../containerizer/mesos/io/switchboard.hpp | 4 ++
.../containerizer/io_switchboard_tests.cpp | 72 ++++++++++++++++++++
5 files changed, 132 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/052abf15/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index 8279225..8b311fb 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -1649,6 +1649,7 @@ message TaskStatus {
REASON_GC_ERROR = 4;
REASON_INVALID_FRAMEWORKID = 5;
REASON_INVALID_OFFERS = 6;
+ REASON_IO_SWITCHBOARD_EXITED = 27;
REASON_MASTER_DISCONNECTED = 7;
REASON_RECONCILIATION = 9;
REASON_RESOURCES_UNKNOWN = 18;
http://git-wip-us.apache.org/repos/asf/mesos/blob/052abf15/include/mesos/v1/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/mesos.proto b/include/mesos/v1/mesos.proto
index 4628cc6..70fab66 100644
--- a/include/mesos/v1/mesos.proto
+++ b/include/mesos/v1/mesos.proto
@@ -1648,6 +1648,7 @@ message TaskStatus {
REASON_GC_ERROR = 4;
REASON_INVALID_FRAMEWORKID = 5;
REASON_INVALID_OFFERS = 6;
+ REASON_IO_SWITCHBOARD_EXITED = 27;
REASON_MASTER_DISCONNECTED = 7;
REASON_RECONCILIATION = 9;
REASON_RESOURCES_UNKNOWN = 18;
http://git-wip-us.apache.org/repos/asf/mesos/blob/052abf15/src/slave/containerizer/mesos/io/switchboard.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/io/switchboard.cpp b/src/slave/containerizer/mesos/io/switchboard.cpp
index 8d4f1e9..e1ca695 100644
--- a/src/slave/containerizer/mesos/io/switchboard.cpp
+++ b/src/slave/containerizer/mesos/io/switchboard.cpp
@@ -89,6 +89,7 @@ using mesos::slave::ContainerConfig;
using mesos::slave::ContainerClass;
using mesos::slave::ContainerIO;
using mesos::slave::ContainerLaunchInfo;
+using mesos::slave::ContainerLimitation;
using mesos::slave::ContainerLogger;
using mesos::slave::ContainerState;
using mesos::slave::Isolator;
@@ -645,6 +646,59 @@ Future<http::Connection> IOSwitchboard::connect(
}
+Future<ContainerLimitation> IOSwitchboard::watch(
+ const ContainerID& containerId)
+{
+#ifdef __WINDOWS__
+ return Future<ContainerLimitation>();
+#else
+ if (local) {
+ return Future<ContainerLimitation>();
+ }
+
+ // We ignore unknown containers here because legacy containers
+ // without an io switchboard directory will not have an info struct
+ // created for during recovery. Likewise, containers launched
+ // by a previous agent with io switchboard server mode disabled will
+ // not have info structs created for them either. In both cases
+ // there is nothing to watch, so we return an unsatisfiable future.
+ if (!infos.contains(containerId)) {
+ return Future<ContainerLimitation>();
+ }
+
+ Future<Option<int>> status = infos[containerId]->status;
+
+ return status
+ .then([](const Option<int>& status) {
+ if (status.isNone()) {
+ return Future<ContainerLimitation>();
+ }
+
+ if (status.isSome() &&
+ WIFEXITED(status.get()) &&
+ WEXITSTATUS(status.get()) == 0) {
+ return Future<ContainerLimitation>();
+ }
+
+ ContainerLimitation limitation;
+ limitation.set_reason(TaskStatus::REASON_IO_SWITCHBOARD_EXITED);
+
+ if (WIFEXITED(status.get())) {
+ limitation.set_message(
+ "'IOSwitchboard' exited with status:"
+ " " + stringify(WEXITSTATUS(status.get())));
+ } else if (WIFSIGNALED(status.get())) {
+ limitation.set_message(
+ "'IOSwitchboard' exited with signal:"
+ " " + stringify(strsignal(WTERMSIG(status.get()))));
+ }
+
+ return Future<ContainerLimitation>(limitation);
+ });
+#endif // __WINDOWS__
+}
+
+
Future<Nothing> IOSwitchboard::cleanup(
const ContainerID& containerId)
{
http://git-wip-us.apache.org/repos/asf/mesos/blob/052abf15/src/slave/containerizer/mesos/io/switchboard.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/io/switchboard.hpp b/src/slave/containerizer/mesos/io/switchboard.hpp
index ca0eee6..a3f19fc 100644
--- a/src/slave/containerizer/mesos/io/switchboard.hpp
+++ b/src/slave/containerizer/mesos/io/switchboard.hpp
@@ -26,6 +26,7 @@
#include <stout/try.hpp>
+#include <mesos/slave/containerizer.hpp>
#include <mesos/slave/container_logger.hpp>
#include "slave/flags.hpp"
@@ -68,6 +69,9 @@ public:
const ContainerID& containerId,
const mesos::slave::ContainerConfig& containerConfig);
+ virtual process::Future<mesos::slave::ContainerLimitation> watch(
+ const ContainerID& containerId);
+
virtual process::Future<Nothing> cleanup(
const ContainerID& containerId);
http://git-wip-us.apache.org/repos/asf/mesos/blob/052abf15/src/tests/containerizer/io_switchboard_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/io_switchboard_tests.cpp b/src/tests/containerizer/io_switchboard_tests.cpp
index c8fe876..d98e4f4 100644
--- a/src/tests/containerizer/io_switchboard_tests.cpp
+++ b/src/tests/containerizer/io_switchboard_tests.cpp
@@ -35,6 +35,8 @@
#include "common/http.hpp"
#include "common/recordio.hpp"
+#include "slave/containerizer/mesos/paths.hpp"
+
#include "slave/containerizer/mesos/io/switchboard.hpp"
#include "tests/environment.hpp"
@@ -46,6 +48,8 @@ namespace http = process::http;
namespace unix = process::network::unix;
#endif // __WINDOWS__
+namespace paths = mesos::internal::slave::containerizer::paths;
+
using mesos::agent::Call;
using mesos::agent::ProcessIO;
@@ -508,6 +512,74 @@ TEST_F(IOSwitchboardTest, OutputRedirectionWithTTY)
EXPECT_SOME_EQ("HelloWorld", os::read(path::join(directory.get(), "stdout")));
}
+
+// This test verifies that a container will be
+// destroyed if its io switchboard exits unexpectedly.
+TEST_F(IOSwitchboardTest, KillSwitchboardContainerDestroyed)
+{
+ slave::Flags flags = CreateSlaveFlags();
+ flags.launcher = "posix";
+ flags.isolation = "posix/cpu";
+ flags.io_switchboard_enable_server = true;
+
+ Fetcher fetcher;
+
+ Try<MesosContainerizer*> create = MesosContainerizer::create(
+ flags,
+ false,
+ &fetcher);
+
+ ASSERT_SOME(create);
+
+ Owned<MesosContainerizer> containerizer(create.get());
+
+ SlaveState state;
+ state.id = SlaveID();
+
+ AWAIT_READY(containerizer->recover(state));
+
+ ContainerID containerId;
+ containerId.set_value(UUID::random().toString());
+
+ Try<string> directory = environment->mkdtemp();
+ ASSERT_SOME(directory);
+
+ ExecutorInfo executorInfo = createExecutorInfo(
+ "executor",
+ "sleep 1000",
+ "cpus:1");
+
+ Future<bool> launch = containerizer->launch(
+ containerId,
+ None(),
+ executorInfo,
+ directory.get(),
+ None(),
+ SlaveID(),
+ map<string, string>(),
+ true); // TODO(benh): Ever want to test not checkpointing?
+
+ AWAIT_ASSERT_TRUE(launch);
+
+ Result<pid_t> pid = paths::getContainerIOSwitchboardPid(
+ flags.runtime_dir, containerId);
+
+ ASSERT_SOME(pid);
+
+ ASSERT_EQ(0, os::kill(pid.get(), SIGKILL));
+
+ Future<Option<ContainerTermination>> wait = containerizer->wait(containerId);
+
+ AWAIT_READY(wait);
+ ASSERT_SOME(wait.get());
+
+ ASSERT_TRUE(wait.get()->has_status());
+ EXPECT_WTERMSIG_EQ(SIGKILL, wait.get()->status());
+
+ ASSERT_TRUE(wait.get()->reasons().size() == 1);
+ ASSERT_EQ(TaskStatus::REASON_IO_SWITCHBOARD_EXITED,
+ wait.get()->reasons().Get(0));
+}
#endif // __WINDOWS__
} // namespace tests {