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/04/30 05:50:38 UTC
[1/5] git commit: Updated uses of http::post.
Repository: mesos
Updated Branches:
refs/heads/master 406ba14e1 -> 714ed3c7f
Updated uses of http::post.
Review: https://reviews.apache.org/r/20278
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/714ed3c7
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/714ed3c7
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/714ed3c7
Branch: refs/heads/master
Commit: 714ed3c7f98f6d3179ea3d9076cdba7e11ea3925
Parents: 4a9ea8d
Author: Benjamin Hindman <be...@gmail.com>
Authored: Fri Apr 11 22:58:28 2014 -0600
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Tue Apr 29 20:44:58 2014 -0700
----------------------------------------------------------------------
src/tests/repair_tests.cpp | 57 +++++++++++++++++++++++++++++++----------
1 file changed, 43 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/714ed3c7/src/tests/repair_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/repair_tests.cpp b/src/tests/repair_tests.cpp
index 0c638c7..5235058 100644
--- a/src/tests/repair_tests.cpp
+++ b/src/tests/repair_tests.cpp
@@ -110,19 +110,35 @@ TEST_F(HealthTest, ObserveEndpoint)
VALIDATE_BAD_RESPONSE(response, "Missing value for 'monitor'.");
// Malformed value causes error.
- response = process::http::post(master.get(), "observe", "monitor=foo%");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=foo%");
VALIDATE_BAD_RESPONSE(response, "Malformed % escape in 'foo%': '%'");
// Empty value causes error.
- response = process::http::post(master.get(), "observe", "monitor=");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=");
VALIDATE_BAD_RESPONSE(response, "Empty string for 'monitor'.");
// Missing hosts.
- response = process::http::post(master.get(), "observe", "monitor=a");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=a");
VALIDATE_BAD_RESPONSE(response, "Missing value for 'hosts'.");
// Missing level.
- response = process::http::post(master.get(), "observe", "monitor=a&hosts=b");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=a&hosts=b");
VALIDATE_BAD_RESPONSE(response, "Missing value for 'level'.");
// Good request is successful.
@@ -131,21 +147,33 @@ TEST_F(HealthTest, ObserveEndpoint)
expected.hosts.push_back("b");
expected.isHealthy = true;
- response =
- process::http::post(master.get(), "observe", "monitor=a&hosts=b&level=ok");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=a&hosts=b&level=ok");
VALIDATE_GOOD_RESPONSE(response, stringify(expected) );
// ok is case-insensitive.
- response =
- process::http::post(master.get(), "observe", "monitor=a&hosts=b&level=Ok");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=a&hosts=b&level=Ok");
VALIDATE_GOOD_RESPONSE(response, stringify(expected) );
- response =
- process::http::post(master.get(), "observe", "monitor=a&hosts=b&level=oK");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=a&hosts=b&level=oK");
VALIDATE_GOOD_RESPONSE(response, stringify(expected) );
- response =
- process::http::post(master.get(), "observe", "monitor=a&hosts=b&level=OK");
+ response = process::http::post(
+ master.get(),
+ "observe",
+ None(),
+ "monitor=a&hosts=b&level=OK");
VALIDATE_GOOD_RESPONSE(response, stringify(expected) );
// level != OK is unhealthy.
@@ -154,15 +182,16 @@ TEST_F(HealthTest, ObserveEndpoint)
process::http::post(
master.get(),
"observe",
+ None(),
"monitor=a&hosts=b&level=true");
VALIDATE_GOOD_RESPONSE(response, stringify(expected) );
// Comma seperated hosts are parsed into an array.
expected.hosts.push_back("e");
- response =
- process::http::post(
+ response = process::http::post(
master.get(),
"observe",
+ None(),
"monitor=a&hosts=b,e&level=true");
VALIDATE_GOOD_RESPONSE(response, stringify(expected) );
[5/5] git commit: Added 'mesos-usage' for use by external
containerizers.
Posted by be...@apache.org.
Added 'mesos-usage' for use by external containerizers.
Review: https://reviews.apache.org/r/20070
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/1c0f56f6
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/1c0f56f6
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/1c0f56f6
Branch: refs/heads/master
Commit: 1c0f56f6a626645115e4ff73373e9117310e4e6a
Parents: 054e194
Author: Benjamin Hindman <be...@gmail.com>
Authored: Sun Apr 6 16:58:50 2014 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Tue Apr 29 20:44:58 2014 -0700
----------------------------------------------------------------------
include/mesos/mesos.proto | 2 +-
src/Makefile.am | 9 +-
src/slave/containerizer/isolators/posix.hpp | 63 ++----------
src/usage/main.cpp | 121 +++++++++++++++++++++++
src/usage/usage.hpp | 92 +++++++++++++++++
5 files changed, 229 insertions(+), 58 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/1c0f56f6/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index 52257ec..e48e50a 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -310,7 +310,7 @@ message ResourceStatistics {
optional double cpus_system_time_secs = 3;
// Number of CPUs allocated.
- required double cpus_limit = 4;
+ optional double cpus_limit = 4;
// cpu.stat on process throttling (for contention issues).
optional uint32 cpus_nr_periods = 7;
http://git-wip-us.apache.org/repos/asf/mesos/blob/1c0f56f6/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 7f9ece1..f461a15 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -302,7 +302,9 @@ libmesos_no_3rdparty_la_SOURCES += common/attributes.hpp \
tests/containerizer.hpp \
tests/isolator.hpp \
tests/mesos.hpp \
- tests/zookeeper_test_server.hpp zookeeper/authentication.hpp \
+ tests/zookeeper_test_server.hpp \
+ usage/usage.hpp \
+ zookeeper/authentication.hpp \
zookeeper/contender.hpp \
zookeeper/detector.hpp \
zookeeper/group.hpp zookeeper/watcher.hpp \
@@ -477,6 +479,11 @@ mesos_executor_SOURCES = launcher/executor.cpp
mesos_executor_CPPFLAGS = $(MESOS_CPPFLAGS)
mesos_executor_LDADD = libmesos.la
+pkglibexec_PROGRAMS += mesos-usage
+mesos_usage_SOURCES = usage/main.cpp
+mesos_usage_CPPFLAGS = $(MESOS_CPPFLAGS)
+mesos_usage_LDADD = libmesos.la
+
bin_PROGRAMS += mesos-log
mesos_log_SOURCES = log/main.cpp
mesos_log_CPPFLAGS = $(MESOS_CPPFLAGS)
http://git-wip-us.apache.org/repos/asf/mesos/blob/1c0f56f6/src/slave/containerizer/isolators/posix.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/isolators/posix.hpp b/src/slave/containerizer/isolators/posix.hpp
index 318a1bf..17bbd10 100644
--- a/src/slave/containerizer/isolators/posix.hpp
+++ b/src/slave/containerizer/isolators/posix.hpp
@@ -20,12 +20,15 @@
#define __POSIX_ISOLATOR_HPP__
#include <stout/hashmap.hpp>
+
#include <stout/os/pstree.hpp>
#include <process/future.hpp>
#include "slave/containerizer/isolator.hpp"
+#include "usage/usage.hpp"
+
namespace mesos {
namespace internal {
namespace slave {
@@ -156,36 +159,8 @@ public:
return ResourceStatistics();
}
- Try<os::ProcessTree> tree = os::pstree(pids.get(containerId).get());
-
- if (!tree.isSome()) {
- return ResourceStatistics();
- }
-
- ResourceStatistics result;
-
- std::deque<os::ProcessTree> trees;
- trees.push_back(tree.get());
-
- while (!trees.empty()) {
- os::ProcessTree root = trees.front();
-
- // We only show utime and stime when both are available, otherwise
- // we're exposing a partial view of the CPU times.
- if (root.process.utime.isSome() && root.process.stime.isSome()) {
- result.set_cpus_user_time_secs(
- result.cpus_user_time_secs() + root.process.utime.get().secs());
- result.set_cpus_system_time_secs(
- result.cpus_system_time_secs() + root.process.stime.get().secs());
- }
-
- trees.pop_front();
- foreach (const os::ProcessTree& child, root.children) {
- trees.push_back(child);
- }
- }
-
- return result;
+ // Use 'mesos-usage' but only request 'cpus_' values.
+ return mesos::internal::usage(pids.get(containerId).get(), false, true);
}
private:
@@ -212,32 +187,8 @@ public:
return ResourceStatistics();
}
- Try<os::ProcessTree> tree = os::pstree(pids.get(containerId).get());
-
- if (!tree.isSome()) {
- return ResourceStatistics();
- }
-
- ResourceStatistics result;
-
- std::deque<os::ProcessTree> trees;
- trees.push_back(tree.get());
-
- while (!trees.empty()) {
- os::ProcessTree root = trees.front();
-
- if (root.process.rss.isSome()) {
- result.set_mem_rss_bytes(
- result.mem_rss_bytes() + root.process.rss.get().bytes());
- }
-
- trees.pop_front();
- foreach (const os::ProcessTree& child, root.children) {
- trees.push_back(child);
- }
- }
-
- return result;
+ // Use 'mesos-usage' but only request 'mem_' values.
+ return mesos::internal::usage(pids.get(containerId).get(), true, false);
}
private:
http://git-wip-us.apache.org/repos/asf/mesos/blob/1c0f56f6/src/usage/main.cpp
----------------------------------------------------------------------
diff --git a/src/usage/main.cpp b/src/usage/main.cpp
new file mode 100644
index 0000000..97f55e9
--- /dev/null
+++ b/src/usage/main.cpp
@@ -0,0 +1,121 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h> // For pid_t and STDOUT_FILENO.
+
+#include <iostream>
+
+#include <stout/duration.hpp>
+#include <stout/flags.hpp>
+#include <stout/json.hpp>
+#include <stout/option.hpp>
+#include <stout/protobuf.hpp>
+#include <stout/try.hpp>
+
+#include "usage/usage.hpp"
+
+using namespace mesos;
+
+using std::cerr;
+using std::cout;
+using std::endl;
+
+
+class Flags : public virtual flags::FlagsBase
+{
+public:
+ Flags()
+ {
+ add(&Flags::pid,
+ "pid",
+ "Root pid for aggregating usage/statistics");
+
+ add(&Flags::recordio,
+ "recordio",
+ "Whether or not to output ResourceStatistics protobuf\n"
+ "using the \"recordio\" format, i.e., the size as a \n"
+ "4 byte unsigned integer followed by the serialized\n"
+ "protobuf itself. By default the ResourceStatistics\n"
+ "will be output as JSON",
+ false);
+ }
+
+ Option<pid_t> pid;
+ bool recordio;
+};
+
+
+void usage(const char* argv0, const flags::FlagsBase& flags)
+{
+ cerr << "Usage: " << os::basename(argv0).get() << " [...]" << endl
+ << endl
+ << "Supported options:" << endl
+ << flags.usage();
+}
+
+
+int main(int argc, char** argv)
+{
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ Flags flags;
+
+ bool help;
+ flags.add(&help,
+ "help",
+ "Prints this help message",
+ false);
+
+ Try<Nothing> load = flags.load(None(), argc, argv);
+
+ if (load.isError()) {
+ cerr << load.error() << endl;
+ usage(argv[0], flags);
+ return -1;
+ }
+
+ if (help) {
+ usage(argv[0], flags);
+ return 0;
+ }
+
+ if (flags.pid.isNone()) {
+ cerr << "Missing pid" << endl;
+ usage(argv[0], flags);
+ return -1;
+ }
+
+ Try<ResourceStatistics> statistics = mesos::internal::usage(flags.pid.get());
+
+ if (statistics.isError()) {
+ cerr << "Failed to get usage: " << statistics.error() << endl;
+ return -1;
+ }
+
+ if (flags.recordio) {
+ Try<Nothing> write = protobuf::write(STDOUT_FILENO, statistics.get());
+ if (write.isError()) {
+ cerr << "Failed to write record: " << write.error() << endl;
+ return -1;
+ }
+ } else {
+ cout << stringify(JSON::Protobuf(statistics.get())) << endl;
+ }
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/mesos/blob/1c0f56f6/src/usage/usage.hpp
----------------------------------------------------------------------
diff --git a/src/usage/usage.hpp b/src/usage/usage.hpp
new file mode 100644
index 0000000..af04a6a
--- /dev/null
+++ b/src/usage/usage.hpp
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __USAGE_HPP__
+#define __USAGE_HPP__
+
+#include <unistd.h> // For pid_t.
+
+#include <deque>
+
+#include <mesos/mesos.hpp>
+
+#include <process/clock.hpp>
+
+#include <stout/foreach.hpp>
+#include <stout/os.hpp>
+
+namespace mesos {
+namespace internal {
+
+// Collects resource usage of a process tree rooted at 'pid'. Only
+// collects the 'mem_*' values if 'mem' is true and the 'cpus_*'
+// values if 'cpus' is true.
+ResourceStatistics usage(pid_t pid, bool mem = true, bool cpus = true)
+{
+ Try<os::ProcessTree> pstree = os::pstree(pid);
+
+ if (pstree.isError()) {
+ return ResourceStatistics();
+ }
+
+ ResourceStatistics statistics;
+
+ // The timestamp is the only required field.
+ statistics.set_timestamp(process::Clock::now().secs());
+
+ std::deque<os::ProcessTree> trees;
+ trees.push_back(pstree.get());
+
+ while (!trees.empty()) {
+ const os::ProcessTree& tree = trees.front();
+
+ if (mem) {
+ if (tree.process.rss.isSome()) {
+ statistics.set_mem_rss_bytes(
+ statistics.mem_rss_bytes() + tree.process.rss.get().bytes());
+ }
+ }
+
+ // We only show utime and stime when both are available, otherwise
+ // we're exposing a partial view of the CPU times.
+ if (cpus) {
+ if (tree.process.utime.isSome() && tree.process.stime.isSome()) {
+ statistics.set_cpus_user_time_secs(
+ statistics.cpus_user_time_secs() +
+ tree.process.utime.get().secs());
+
+ statistics.set_cpus_system_time_secs(
+ statistics.cpus_system_time_secs() +
+ tree.process.stime.get().secs());
+ }
+ }
+
+ foreach (const os::ProcessTree& child, tree.children) {
+ trees.push_back(child);
+ }
+
+ trees.pop_front();
+ }
+
+ return statistics;
+}
+
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __USAGE_HPP__
[2/5] git commit: Added test for slave stopping before containerizer
launches.
Posted by be...@apache.org.
Added test for slave stopping before containerizer launches.
Review: https://reviews.apache.org/r/20179
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/46afda85
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/46afda85
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/46afda85
Branch: refs/heads/master
Commit: 46afda855b9a1f516c0353c637d495fb3b0fcb65
Parents: 1c0f56f
Author: Benjamin Hindman <be...@gmail.com>
Authored: Wed Apr 9 14:52:45 2014 -0600
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Tue Apr 29 20:44:58 2014 -0700
----------------------------------------------------------------------
src/tests/containerizer.cpp | 40 ++++++++++++-----
src/tests/containerizer.hpp | 28 ++++++++----
src/tests/slave_recovery_tests.cpp | 79 +++++++++++++++++++++++++++++++++
3 files changed, 128 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/46afda85/src/tests/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer.cpp b/src/tests/containerizer.cpp
index 50803a0..7dacab5 100644
--- a/src/tests/containerizer.cpp
+++ b/src/tests/containerizer.cpp
@@ -22,6 +22,10 @@
using std::map;
using std::string;
+using testing::_;
+using testing::Invoke;
+using testing::Return;
+
using namespace process;
namespace mesos {
@@ -69,7 +73,7 @@ TestContainerizer::~TestContainerizer()
}
-Future<Nothing> TestContainerizer::launch(
+Future<Nothing> TestContainerizer::_launch(
const ContainerID& containerId,
const ExecutorInfo& executorInfo,
const string& directory,
@@ -161,8 +165,11 @@ Future<Nothing> TestContainerizer::launch(
Future<containerizer::Termination> TestContainerizer::wait(
const ContainerID& containerId)
{
- CHECK(promises.contains(containerId))
- << "Container " << containerId << " not started";
+ // An unknown container is possible for tests where we "drop" the
+ // 'launch' in order to verify recovery still works correctly.
+ if (!promises.contains(containerId)) {
+ return Failure("Unknown container: " + stringify(containerId));
+ }
return promises[containerId]->future();
}
@@ -210,14 +217,25 @@ Future<hashset<ContainerID> > TestContainerizer::containers()
void TestContainerizer::setup()
{
- EXPECT_CALL(*this, recover(testing::_))
- .WillRepeatedly(testing::Return(Nothing()));
-
- EXPECT_CALL(*this, usage(testing::_))
- .WillRepeatedly(testing::Return(ResourceStatistics()));
-
- EXPECT_CALL(*this, update(testing::_, testing::_))
- .WillRepeatedly(testing::Return(Nothing()));
+ // NOTE: We use 'EXPECT_CALL' and 'WillRepeatedly' here instead of
+ // 'ON_CALL' and 'WillByDefault' because the latter gives the gmock
+ // warning "Uninteresting mock function call" unless each tests puts
+ // the expectations in place which would make the tests much more
+ // verbose.
+ // See groups.google.com/forum/#!topic/googlemock/EX4kLxddlko for a
+ // suggestion for how we might be able to use 'NiceMock' here
+ // instead.
+ EXPECT_CALL(*this, recover(_))
+ .WillRepeatedly(Return(Nothing()));
+
+ EXPECT_CALL(*this, usage(_))
+ .WillRepeatedly(Return(ResourceStatistics()));
+
+ EXPECT_CALL(*this, update(_, _))
+ .WillRepeatedly(Return(Nothing()));
+
+ EXPECT_CALL(*this, launch(_, _, _, _, _, _, _))
+ .WillRepeatedly(Invoke(this, &TestContainerizer::_launch));
}
} // namespace tests {
http://git-wip-us.apache.org/repos/asf/mesos/blob/46afda85/src/tests/containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer.hpp b/src/tests/containerizer.hpp
index 2b7ee0d..8e21bd1 100644
--- a/src/tests/containerizer.hpp
+++ b/src/tests/containerizer.hpp
@@ -64,14 +64,16 @@ public:
virtual ~TestContainerizer();
- virtual process::Future<Nothing> launch(
- const ContainerID& containerId,
- const ExecutorInfo& executorInfo,
- const std::string& directory,
- const Option<std::string>& user,
- const SlaveID& slaveId,
- const process::PID<slave::Slave>& slavePid,
- bool checkpoint);
+ MOCK_METHOD7(
+ launch,
+ process::Future<Nothing>(
+ const ContainerID&,
+ const ExecutorInfo&,
+ const std::string&,
+ const Option<std::string>&,
+ const SlaveID&,
+ const process::PID<slave::Slave>&,
+ bool checkpoint));
virtual process::Future<Nothing> launch(
const ContainerID& containerId,
@@ -109,6 +111,16 @@ public:
private:
void setup();
+ // Default 'launch' implementation.
+ process::Future<Nothing> _launch(
+ const ContainerID& containerId,
+ const ExecutorInfo& executorInfo,
+ const std::string& directory,
+ const Option<std::string>& user,
+ const SlaveID& slaveId,
+ const process::PID<slave::Slave>& slavePid,
+ bool checkpoint);
+
hashmap<ExecutorID, Executor*> executors;
hashmap<std::pair<FrameworkID, ExecutorID>, ContainerID> containers_;
http://git-wip-us.apache.org/repos/asf/mesos/blob/46afda85/src/tests/slave_recovery_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_recovery_tests.cpp b/src/tests/slave_recovery_tests.cpp
index cd28c8b..21b1345 100644
--- a/src/tests/slave_recovery_tests.cpp
+++ b/src/tests/slave_recovery_tests.cpp
@@ -52,6 +52,7 @@
#include "messages/messages.hpp"
+#include "tests/containerizer.hpp"
#include "tests/mesos.hpp"
#include "tests/utils.hpp"
@@ -73,6 +74,7 @@ using std::vector;
using testing::_;
using testing::AtMost;
+using testing::DoAll;
using testing::Eq;
using testing::Return;
using testing::SaveArg;
@@ -3087,3 +3089,80 @@ TYPED_TEST(SlaveRecoveryTest, ResourceStatistics)
delete containerizer2.get();
}
+
+
+// The slave is stopped after it dispatched Containerizer::launch but
+// before the containerizer has processed the launch. When the slave
+// comes back up it should send a TASK_LOST for the task.
+// NOTE: This is a 'TYPED_TEST' but we don't use 'TypeParam'.
+TYPED_TEST(SlaveRecoveryTest, RestartBeforeContainerizerLaunch)
+{
+ Try<PID<Master> > master = this->StartMaster();
+ ASSERT_SOME(master);
+
+ slave::Flags flags = this->CreateSlaveFlags();
+
+ TestContainerizer* containerizer1 = new TestContainerizer();
+
+ Try<PID<Slave> > slave = this->StartSlave(containerizer1, flags);
+ ASSERT_SOME(slave);
+
+ MockScheduler sched;
+
+ // Enable checkpointing for the framework.
+ FrameworkInfo frameworkInfo;
+ frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
+ frameworkInfo.set_checkpoint(true);
+
+ MesosSchedulerDriver driver(
+ &sched, frameworkInfo, master.get(), DEFAULT_CREDENTIAL);
+
+ EXPECT_CALL(sched, registered(_, _, _));
+
+ Future<vector<Offer> > offers;
+ EXPECT_CALL(sched, resourceOffers(_, _))
+ .WillOnce(FutureArg<1>(&offers))
+ .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+ driver.start();
+
+ AWAIT_READY(offers);
+ EXPECT_NE(0u, offers.get().size());
+
+ TaskInfo task = createTask(offers.get()[0], "sleep 1000");
+ vector<TaskInfo> tasks;
+ tasks.push_back(task); // Long-running task.
+
+ // Expect the launch but don't do anything.
+ Future<Nothing> launch;
+ EXPECT_CALL(*containerizer1, launch(_, _, _, _, _, _, _))
+ .WillOnce(DoAll(FutureSatisfy(&launch),
+ Return(Future<Nothing>())));
+
+ driver.launchTasks(offers.get()[0].id(), tasks);
+
+ // Once we get the launch restart the slave.
+ AWAIT_READY(launch);
+
+ this->Stop(slave.get());
+ delete containerizer1;
+
+ Future<TaskStatus> status;
+ EXPECT_CALL(sched, statusUpdate(_, _))
+ .WillOnce(FutureArg<1>(&status));
+
+ TestContainerizer* containerizer2 = new TestContainerizer();
+
+ slave = this->StartSlave(containerizer2, flags);
+ ASSERT_SOME(slave);
+
+ // Scheduler should receive an update for the lost task.
+ AWAIT_READY(status);
+ ASSERT_EQ(TASK_LOST, status.get().state());
+
+ driver.stop();
+ driver.join();
+
+ this->Shutdown();
+ delete containerizer2;
+}
[4/5] git commit: Allowed passing headers to http::get/post.
Posted by be...@apache.org.
Allowed passing headers to http::get/post.
Review: https://reviews.apache.org/r/20275
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/4a9ea8dc
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/4a9ea8dc
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/4a9ea8dc
Branch: refs/heads/master
Commit: 4a9ea8dce4e6345bf529a882e6449adf00ef064d
Parents: 46afda8
Author: Benjamin Hindman <be...@gmail.com>
Authored: Fri Apr 11 13:36:15 2014 -0600
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Tue Apr 29 20:44:58 2014 -0700
----------------------------------------------------------------------
3rdparty/libprocess/include/process/http.hpp | 4 +-
3rdparty/libprocess/src/http.cpp | 61 ++++++++++++++++-------
3rdparty/libprocess/src/tests/http_tests.cpp | 17 ++++++-
3 files changed, 61 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/4a9ea8dc/3rdparty/libprocess/include/process/http.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/http.hpp b/3rdparty/libprocess/include/process/http.hpp
index f85c065..b3b9111 100644
--- a/3rdparty/libprocess/include/process/http.hpp
+++ b/3rdparty/libprocess/include/process/http.hpp
@@ -488,7 +488,8 @@ inline Try<std::string> decode(const std::string& s)
Future<Response> get(
const UPID& upid,
const Option<std::string>& path = None(),
- const Option<std::string>& query = None());
+ const Option<std::string>& query = None(),
+ const Option<hashmap<std::string, std::string> >& headers = None());
// Sends a blocking HTTP POST request to the process with the given upid.
@@ -496,6 +497,7 @@ Future<Response> get(
Future<Response> post(
const UPID& upid,
const Option<std::string>& path = None(),
+ const Option<hashmap<std::string, std::string> >& headers = None(),
const Option<std::string>& body = None(),
const Option<std::string>& contentType = None());
http://git-wip-us.apache.org/repos/asf/mesos/blob/4a9ea8dc/3rdparty/libprocess/src/http.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/http.cpp b/3rdparty/libprocess/src/http.cpp
index f8b93dc..eb20380 100644
--- a/3rdparty/libprocess/src/http.cpp
+++ b/3rdparty/libprocess/src/http.cpp
@@ -61,6 +61,7 @@ Future<Response> request(
const string& method,
const Option<string>& path,
const Option<string>& query,
+ const Option<hashmap<string, string> >& _headers,
const Option<string>& body,
const Option<string>& contentType)
{
@@ -103,28 +104,44 @@ Future<Response> request(
out << " HTTP/1.1\r\n";
- // Call inet_ntop since inet_ntoa is not thread-safe!
- char ip[INET_ADDRSTRLEN];
- PCHECK(inet_ntop(AF_INET, (in_addr *) &upid.ip, ip, INET_ADDRSTRLEN) != NULL);
+ // Set up the headers as necessary.
+ hashmap<string, string> headers;
- out << "Host: " << ip << ":" << upid.port << "\r\n"
- << "Connection: close\r\n";
+ if (_headers.isSome()) {
+ headers = _headers.get();
+ }
- if (body.isNone() && contentType.isSome()) {
- os::close(s);
- return Failure("Attempted to do a POST with a Content-Type but no body");
+ // Need to specify the 'Host' header. We use inet_ntop since
+ // inet_ntoa is not thread-safe!
+ char ip[INET_ADDRSTRLEN];
+ if (inet_ntop(AF_INET, (in_addr*) &upid.ip, ip, INET_ADDRSTRLEN) == NULL) {
+ return Failure(ErrnoError("Failed to create 'Host' header"));
}
+ headers["Host"] = string(ip) + ":" + stringify(upid.port);
+
+ // Tell the server to close the connection when it's done.
+ headers["Connection"] = "close";
+
+ // Overwrite Content-Type if necessary.
if (contentType.isSome()) {
- out << "Content-Type: " << contentType.get() << "\r\n";
+ headers["Content-Type"] = contentType.get();
+ }
+
+ // Make sure the Content-Length is set correctly if necessary.
+ if (body.isSome()) {
+ headers["Content-Length"] = stringify(body.get().length());
}
- if (body.isNone()) {
- out << "\r\n";
- } else {
- out << "Content-Length: " << body.get().length() << "\r\n"
- << "\r\n"
- << body.get();
+ // Emit the headers.
+ foreachpair (const string& key, const string& value, headers) {
+ out << key << ": " << value << "\r\n";
+ }
+
+ out << "\r\n";
+
+ if (body.isSome()) {
+ out << body.get();
}
Try<Nothing> nonblock = os::nonblock(s);
@@ -149,19 +166,27 @@ Future<Response> request(
Future<Response> get(
const UPID& upid,
const Option<string>& path,
- const Option<string>& query)
+ const Option<string>& query,
+ const Option<hashmap<string, string> >& headers)
{
- return internal::request(upid, "GET", path, query, None(), None());
+ return internal::request(
+ upid, "GET", path, query, headers, None(), None());
}
Future<Response> post(
const UPID& upid,
const Option<string>& path,
+ const Option<hashmap<string, string> >& headers,
const Option<string>& body,
const Option<string>& contentType)
{
- return internal::request(upid, "POST", path, None(), body, contentType);
+ if (body.isNone() && contentType.isSome()) {
+ return Failure("Attempted to do a POST with a Content-Type but no body");
+ }
+
+ return internal::request(
+ upid, "POST", path, None(), headers, body, contentType);
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/4a9ea8dc/3rdparty/libprocess/src/tests/http_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/http_tests.cpp b/3rdparty/libprocess/src/tests/http_tests.cpp
index 983e2a0..fd7c252 100644
--- a/3rdparty/libprocess/src/tests/http_tests.cpp
+++ b/3rdparty/libprocess/src/tests/http_tests.cpp
@@ -265,7 +265,7 @@ TEST(HTTP, Post)
// Test the case where there is a content type but no body.
Future<http::Response> future =
- http::post(process.self(), "post", None(), "text/plain");
+ http::post(process.self(), "post", None(), None(), "text/plain");
AWAIT_EXPECT_FAILED(future);
@@ -273,7 +273,20 @@ TEST(HTTP, Post)
.WillOnce(Invoke(validatePost));
future =
- http::post(process.self(), "post", "This is the payload.", "text/plain");
+ http::post(process.self(), "post", None(), "This is the payload.", "text/plain");
+
+ AWAIT_READY(future);
+ ASSERT_EQ(http::statuses[200], future.get().status);
+
+ // Now test passing headers instead.
+ hashmap<string, string> headers;
+ headers["Content-Type"] = "text/plain";
+
+ EXPECT_CALL(process, post(_))
+ .WillOnce(Invoke(validatePost));
+
+ future =
+ http::post(process.self(), "post", headers, "This is the payload.");
AWAIT_READY(future);
ASSERT_EQ(http::statuses[200], future.get().status);
[3/5] git commit: Better error message for protobuf::write.
Posted by be...@apache.org.
Better error message for protobuf::write.
Review: https://reviews.apache.org/r/20072
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/054e1944
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/054e1944
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/054e1944
Branch: refs/heads/master
Commit: 054e1944e7f6f244efb4ecbf568e448059080c09
Parents: 406ba14
Author: Benjamin Hindman <be...@gmail.com>
Authored: Sun Apr 6 18:56:08 2014 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Tue Apr 29 20:44:58 2014 -0700
----------------------------------------------------------------------
3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/054e1944/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
index ea5665a..ddc13e9 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
@@ -47,7 +47,8 @@ namespace protobuf {
inline Try<Nothing> write(int fd, const google::protobuf::Message& message)
{
if (!message.IsInitialized()) {
- return Error("Uninitialized protocol buffer");
+ return Error(message.InitializationErrorString() +
+ " is required but not initialized");
}
// First write the size of the protobuf.