You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2014/10/26 02:44:14 UTC
[1/3] git commit: Mark running tasks killed during framework shutdown.
Repository: mesos
Updated Branches:
refs/heads/master 169e969c9 -> 12e067419
Mark running tasks killed during framework shutdown.
When a framework is shut down e.g. by calling driver.stop() from the
scheduler, running tasks are marked KILLED before migrating them to
completed.
Review: https://reviews.apache.org/r/25250
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/12e06741
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/12e06741
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/12e06741
Branch: refs/heads/master
Commit: 12e06741911300d70ae6498119563634730d33af
Parents: 06bec4f
Author: Alexander Rukletsov <al...@mesosphere.io>
Authored: Sun Oct 12 15:05:02 2014 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Sat Oct 25 16:57:40 2014 -0700
----------------------------------------------------------------------
src/master/master.cpp | 20 ++++++++++++++
src/tests/master_tests.cpp | 61 +++++++++++++++++++++++++++++++++++------
2 files changed, 72 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/12e06741/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 9ebdc35..9491b22 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -4226,6 +4226,26 @@ void Master::removeFramework(Framework* framework)
<< "Unknown slave " << task->slave_id()
<< " for task " << task->task_id();
+ // The task is implicitly killed, and TASK_KILLED is the closest
+ // state we have by now. We mark the task and remove it, without
+ // sending the update. However, a task may finish during the
+ // executor graceful shutdown period. By marking such task as
+ // killed and moving it to completed, we lose the opportunity to
+ // collect the possible finished status. We tolerate this,
+ // because we expect that if the framework has been asked to shut
+ // down, its user is not interested in results anymore.
+ // TODO(alex): consider a more descrptive state, e.g. TASK_ABANDONED.
+ const StatusUpdate& update = protobuf::createStatusUpdate(
+ task->framework_id(),
+ task->slave_id(),
+ task->task_id(),
+ TASK_KILLED,
+ "Framework " + framework->id.value() + " removed",
+ (task->has_executor_id()
+ ? Option<ExecutorID>(task->executor_id())
+ : None()));
+
+ updateTask(task, update);
removeTask(task);
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/12e06741/src/tests/master_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_tests.cpp b/src/tests/master_tests.cpp
index f60e376..2e52574 100644
--- a/src/tests/master_tests.cpp
+++ b/src/tests/master_tests.cpp
@@ -164,9 +164,12 @@ TEST_F(MasterTest, TaskRunning)
}
+// This test ensures that stopping a scheduler driver triggers
+// executor's shutdown callback and all still running tasks are
+// marked as killed.
TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
{
- Try<PID<Master> > master = StartMaster();
+ Try<PID<Master>> master = StartMaster();
ASSERT_SOME(master);
MockExecutor exec(DEFAULT_EXECUTOR_ID);
@@ -176,7 +179,7 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
slave::Flags flags = CreateSlaveFlags();
flags.executor_shutdown_grace_period = Seconds(0);
- Try<PID<Slave> > slave = StartSlave(&containerizer, flags);
+ Try<PID<Slave>> slave = StartSlave(&containerizer, flags);
ASSERT_SOME(slave);
MockScheduler sched;
@@ -186,7 +189,7 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
EXPECT_CALL(sched, registered(&driver, _, _))
.Times(1);
- Future<vector<Offer> > offers;
+ Future<vector<Offer>> offers;
EXPECT_CALL(sched, resourceOffers(&driver, _))
.WillOnce(FutureArg<1>(&offers))
.WillRepeatedly(Return()); // Ignore subsequent offers.
@@ -195,12 +198,13 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
AWAIT_READY(offers);
EXPECT_NE(0u, offers.get().size());
+ Offer offer = offers.get()[0];
TaskInfo task;
task.set_name("");
task.mutable_task_id()->set_value("1");
- task.mutable_slave_id()->MergeFrom(offers.get()[0].slave_id());
- task.mutable_resources()->MergeFrom(offers.get()[0].resources());
+ task.mutable_slave_id()->MergeFrom(offer.slave_id());
+ task.mutable_resources()->MergeFrom(offer.resources());
task.mutable_executor()->MergeFrom(DEFAULT_EXECUTOR_INFO);
vector<TaskInfo> tasks;
@@ -214,7 +218,7 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
Future<Nothing> update;
EXPECT_CALL(containerizer,
- update(_, Resources(offers.get()[0].resources())))
+ update(_, Resources(offer.resources())))
.WillOnce(DoAll(FutureSatisfy(&update),
Return(Future<Nothing>())));
@@ -222,20 +226,59 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
EXPECT_CALL(sched, statusUpdate(&driver, _))
.WillOnce(FutureArg<1>(&status));
- driver.launchTasks(offers.get()[0].id(), tasks);
+ driver.launchTasks(offer.id(), tasks);
AWAIT_READY(status);
EXPECT_EQ(TASK_RUNNING, status.get().state());
AWAIT_READY(update);
+ // Set expectation that Master receives UnregisterFrameworkMessage,
+ // which triggers marking running tasks as killed.
+ UnregisterFrameworkMessage message;
+ message.mutable_framework_id()->MergeFrom(offer.framework_id());
+
+ Future<UnregisterFrameworkMessage> unregisterFrameworkMessage =
+ FUTURE_PROTOBUF(message, _, master.get());
+
+ // Set expectation that Executor's shutdown callback is invoked.
+ Future<Nothing> shutdown;
EXPECT_CALL(exec, shutdown(_))
- .Times(AtMost(1));
+ .WillOnce(FutureSatisfy(&shutdown));
+ // Stop the driver while the task is running.
driver.stop();
driver.join();
- Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
+ // Wait for UnregisterFrameworkMessage message to be dispatched and
+ // executor's shutdown callback to be called.
+ AWAIT_READY(unregisterFrameworkMessage);
+ AWAIT_READY(shutdown);
+
+ // We have to be sure the UnregisterFrameworkMessage is processed
+ // completely and running tasks enter a terminal state before we
+ // request the master state.
+ Clock::pause();
+ Clock::settle();
+ Clock::resume();
+
+ // Request master state.
+ Future<process::http::Response> response =
+ process::http::get(master.get(), "state.json");
+ AWAIT_READY(response);
+
+ // These checks are not essential for the test, but may help
+ // understand what went wrong.
+ Try<JSON::Object> parse = JSON::parse<JSON::Object>(response.get().body);
+ ASSERT_SOME(parse);
+
+ // Make sure the task landed in completed and marked as killed.
+ Result<JSON::String> state = parse.get().find<JSON::String>(
+ "completed_frameworks[0].completed_tasks[0].state");
+
+ ASSERT_SOME_EQ(JSON::String("TASK_KILLED"), state);
+
+ Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
}
[3/3] git commit: Implemented array subscript lookup in
JSON::Object::find.
Posted by be...@apache.org.
Implemented array subscript lookup in JSON::Object::find.
Review: https://reviews.apache.org/r/26634
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/dfe33807
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/dfe33807
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/dfe33807
Branch: refs/heads/master
Commit: dfe338078659a73846f2972a4bebccafcc369a07
Parents: 169e969
Author: Benjamin Hindman <be...@gmail.com>
Authored: Sun Oct 12 21:33:58 2014 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Sat Oct 25 16:57:40 2014 -0700
----------------------------------------------------------------------
.../3rdparty/stout/include/stout/json.hpp | 54 +++++++++++++++++---
.../3rdparty/stout/tests/json_tests.cpp | 20 +++++---
2 files changed, 59 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/dfe33807/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
index 2e1f78e..11bb7ed 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
@@ -19,7 +19,6 @@
#include <iomanip>
#include <iostream>
#include <limits>
-#include <list>
#include <map>
#include <string>
#include <vector>
@@ -30,6 +29,7 @@
#include <stout/check.hpp>
#include <stout/foreach.hpp>
+#include <stout/numify.hpp>
#include <stout/result.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>
@@ -85,7 +85,7 @@ struct Object
// Returns the JSON value (specified by the type) given a "path"
// into the structure, for example:
//
- // Result<JSON::Array> array = object.find<JSON::Array>("nested.array");
+ // Result<JSON::Array> array = object.find<JSON::Array>("nested.array[0]");
//
// Will return 'None' if no field could be found called 'array'
// within a field called 'nested' of 'object' (where 'nested' must
@@ -94,8 +94,6 @@ struct Object
// Returns an error if a JSON value of the wrong type is found, or
// an intermediate JSON value is not an object that we can do a
// recursive find on.
- //
- // TODO(benh): Support paths that index, e.g., 'nested.array[4].field'.
template <typename T>
Result<T> find(const std::string& path) const;
@@ -105,7 +103,7 @@ struct Object
struct Array
{
- std::list<Value> values;
+ std::vector<Value> values;
};
@@ -225,13 +223,53 @@ Result<T> Object::find(const std::string& path) const
return None();
}
- std::map<std::string, Value>::const_iterator entry = values.find(names[0]);
+ std::string name = names[0];
+
+ // Determine if we have an array subscript. If so, save it but
+ // remove it from the name for doing the lookup.
+ Option<size_t> subscript = None();
+ size_t index = name.find('[');
+ if (index != std::string::npos) {
+ // Check for the closing bracket.
+ if (name.at(name.length() - 1) != ']') {
+ return Error("Malformed array subscript, expecting ']'");
+ }
+
+ // Now remove the closing bracket (last character) and everything
+ // before and including the opening bracket.
+ std::string s = name.substr(0, name.length() - 1);
+ s = s.substr(index + 1);
+
+ // Now numify the subscript.
+ Try<int> i = numify<int>(s);
+
+ if (i.isError()) {
+ return Error("Failed to numify array subscript '" + s + "'");
+ } else if (i.get() < 0) {
+ return Error("Array subscript '" + s + "' must be >= 0");
+ }
+
+ subscript = i.get();
+
+ // And finally remove the array subscript from the name.
+ name = name.substr(0, index);
+ }
+
+ std::map<std::string, Value>::const_iterator entry = values.find(name);
if (entry == values.end()) {
return None();
}
- const Value& value = entry->second;
+ Value value = entry->second;
+
+ if (value.is<Array>() && subscript.isSome()) {
+ Array array = value.as<Array>();
+ if (subscript.get() >= array.values.size()) {
+ return None();
+ }
+ value = array.values[subscript.get()];
+ }
if (names.size() == 1) {
if (!value.is<T>()) {
@@ -375,7 +413,7 @@ inline std::ostream& operator << (std::ostream& out, const Object& object)
inline std::ostream& operator << (std::ostream& out, const Array& array)
{
out << "[";
- std::list<Value>::const_iterator iterator;
+ std::vector<Value>::const_iterator iterator;
iterator = array.values.begin();
while (iterator != array.values.end()) {
out << *iterator;
http://git-wip-us.apache.org/repos/asf/mesos/blob/dfe33807/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
index 3bfc8e6..2be4c65 100644
--- a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
+++ b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
@@ -220,13 +220,19 @@ TEST(JsonTest, Find)
JSON::Null(),
object.find<JSON::Null>("nested1.nested2.null"));
- Result<JSON::Array> result =
- object.find<JSON::Array>("nested1.nested2.array");
-
- ASSERT_SOME(result);
- ASSERT_FALSE(result.get().values.empty());
- ASSERT_TRUE(result.get().values.front().is<JSON::String>());
- ASSERT_EQ("hello", result.get().values.front().as<JSON::String>());
+ ASSERT_SOME_EQ(
+ JSON::String("hello"),
+ object.find<JSON::String>("nested1.nested2.array[0]"));
+
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[1"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[[1]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[1]]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array.[1]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[.1]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[1.]"));
+
+ // Out of bounds is none.
+ ASSERT_NONE(object.find<JSON::String>("nested1.nested2.array[1]"));
// Also test getting JSON::Value when you don't know the type.
ASSERT_SOME(object.find<JSON::Value>("nested1.nested2.null"));
[2/3] git commit: Fixes necessary due to JSON::Array::values change
to std::vector.
Posted by be...@apache.org.
Fixes necessary due to JSON::Array::values change to std::vector.
Review: https://reviews.apache.org/r/26635
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/06bec4fa
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/06bec4fa
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/06bec4fa
Branch: refs/heads/master
Commit: 06bec4fa91f5f1c30eb1eac30f2a123100872d8e
Parents: dfe3380
Author: Benjamin Hindman <be...@gmail.com>
Authored: Sun Oct 12 21:34:43 2014 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Sat Oct 25 16:57:40 2014 -0700
----------------------------------------------------------------------
3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp | 3 +--
3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp | 7 +++++++
src/docker/docker.cpp | 2 +-
3 files changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/06bec4fa/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
index 11bb7ed..334c898 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
@@ -237,8 +237,7 @@ Result<T> Object::find(const std::string& path) const
// Now remove the closing bracket (last character) and everything
// before and including the opening bracket.
- std::string s = name.substr(0, name.length() - 1);
- s = s.substr(index + 1);
+ std::string s = name.substr(index + 1, name.length() - index - 2);
// Now numify the subscript.
Try<int> i = numify<int>(s);
http://git-wip-us.apache.org/repos/asf/mesos/blob/06bec4fa/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
index 2be4c65..f60d1bb 100644
--- a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
+++ b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
@@ -230,6 +230,13 @@ TEST(JsonTest, Find)
ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array.[1]"));
ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[.1]"));
ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[1.]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[[]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[]]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[[]]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[[1]]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[[1]"));
+ ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array[1]]"));
// Out of bounds is none.
ASSERT_NONE(object.find<JSON::String>("nested1.nested2.array[1]"));
http://git-wip-us.apache.org/repos/asf/mesos/blob/06bec4fa/src/docker/docker.cpp
----------------------------------------------------------------------
diff --git a/src/docker/docker.cpp b/src/docker/docker.cpp
index e09b51c..9973782 100644
--- a/src/docker/docker.cpp
+++ b/src/docker/docker.cpp
@@ -253,7 +253,7 @@ Try<Docker::Image> Docker::Image::create(const JSON::Object& json)
return Error("Unexpected type found for 'ContainerConfig.Entrypoint'");
}
- const list<JSON::Value>& values = entrypoint.get().as<JSON::Array>().values;
+ const vector<JSON::Value>& values = entrypoint.get().as<JSON::Array>().values;
if (values.size() == 0) {
return Docker::Image(None());
}