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/08/05 00:09:25 UTC
[04/43] git commit: Bug fixes and cleanups in Docker abstraction.
Bug fixes and cleanups in Docker abstraction.
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/fa400fef
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/fa400fef
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/fa400fef
Branch: refs/heads/master
Commit: fa400fef337900a97ccc77906dbf80b7d0fbd967
Parents: 86a9769
Author: Benjamin Hindman <be...@gmail.com>
Authored: Mon Jun 23 09:32:57 2014 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Mon Aug 4 15:08:15 2014 -0700
----------------------------------------------------------------------
src/docker/docker.cpp | 107 +++++++++++++++++++++++++++++++++++++++------
src/docker/docker.hpp | 17 +++++--
2 files changed, 107 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/fa400fef/src/docker/docker.cpp
----------------------------------------------------------------------
diff --git a/src/docker/docker.cpp b/src/docker/docker.cpp
index db31ba3..976a660 100644
--- a/src/docker/docker.cpp
+++ b/src/docker/docker.cpp
@@ -4,9 +4,12 @@
#include <stout/lambda.hpp>
#include <stout/strings.hpp>
+#include <stout/result.hpp>
+
+#include <stout/os/read.hpp>
+
#include <process/check.hpp>
#include <process/collect.hpp>
-#include <process/io.hpp>
#include "docker/docker.hpp"
@@ -18,6 +21,16 @@ using std::string;
using std::vector;
+string Docker::Container::id() const
+{
+ map<string, JSON::Value>::const_iterator entry =
+ json.values.find("Id");
+ CHECK(entry != json.values.end());
+ JSON::Value value = entry->second;
+ CHECK(value.is<JSON::String>());
+ return value.as<JSON::String>().value;
+}
+
string Docker::Container::name() const
{
map<string, JSON::Value>::const_iterator entry =
@@ -29,10 +42,16 @@ string Docker::Container::name() const
}
-Future<Option<int> > Docker::run(const string& image) const
+Future<Option<int> > Docker::run(
+ const string& image,
+ const string& command,
+ const string& name) const
{
+ VLOG(1) << "Running " << path << " run --name=" << name << " "
+ << image << " " << command;
+
Try<Subprocess> s = subprocess(
- path + " run " + image,
+ path + " run --name=" + name + " " + image + " " + command,
Subprocess::PIPE(),
Subprocess::PIPE(),
Subprocess::PIPE());
@@ -47,6 +66,8 @@ Future<Option<int> > Docker::run(const string& image) const
Future<Option<int> > Docker::kill(const string& container) const
{
+ VLOG(1) << "Running " << path << " kill " << container;
+
Try<Subprocess> s = subprocess(
path + " kill " + container,
Subprocess::PIPE(),
@@ -63,6 +84,8 @@ Future<Option<int> > Docker::kill(const string& container) const
Future<Docker::Container> Docker::inspect(const string& container) const
{
+ VLOG(1) << "Running " << path << " inspect " << container;
+
Try<Subprocess> s = subprocess(
path + " inspect " + container,
Subprocess::PIPE(),
@@ -70,7 +93,6 @@ Future<Docker::Container> Docker::inspect(const string& container) const
Subprocess::PIPE());
if (s.isError()) {
- // TODO(benh): Include stdout and stderr in error message.
return Failure(s.error());
}
@@ -79,24 +101,73 @@ Future<Docker::Container> Docker::inspect(const string& container) const
}
+namespace os {
+
+inline Result<std::string> read(
+ int fd,
+ Option<size_t> size = None(),
+ size_t chunk = 16 * 4096)
+{
+ std::string result;
+
+ while (size.isNone() || result.size() < size.get()) {
+ char buffer[chunk];
+ ssize_t length = ::read(fd, buffer, chunk);
+
+ if (length < 0) {
+ // TODO(bmahler): Handle a non-blocking fd? (EAGAIN, EWOULDBLOCK)
+ if (errno == EINTR) {
+ continue;
+ }
+ return ErrnoError();
+ } else if (length == 0) {
+ // Reached EOF before expected! Only return as much data as
+ // available or None if we haven't read anything yet.
+ if (result.size() > 0) {
+ return result;
+ }
+ return None();
+ }
+
+ result.append(buffer, length);
+ }
+
+ return result;
+}
+
+} // namespace os {
+
+
Future<Docker::Container> Docker::_inspect(const Subprocess& s)
{
- // Check the exit status of 'docker ps'.
+ // Check the exit status of 'docker inspect'.
CHECK_READY(s.status());
Option<int> status = s.status().get();
if (status.isSome() && status.get() != 0) {
- // TODO(benh): Include stdout and stderr in error message.
- return Failure("Failed to do 'docker ps'");
+ // TODO(benh): Include stderr in error message.
+ Result<string> read = os::read(s.err().get());
+ return Failure("Failed to do 'docker inspect': " +
+ (read.isSome()
+ ? read.get()
+ : " exited with status " + stringify(status.get())));
}
// Read to EOF.
// TODO(benh): Read output asynchronously.
CHECK_SOME(s.out());
- string output = io::read(s.out().get()).get();
+ Result<string> output = os::read(s.out().get());
+
+ if (output.isError()) {
+ // TODO(benh): Include stderr in error message.
+ return Failure("Failed to read output: " + output.error());
+ } else if (output.isNone()) {
+ // TODO(benh): Include stderr in error message.
+ return Failure("No output available");
+ }
- Try<JSON::Array> parse = JSON::parse<JSON::Array>(output);
+ Try<JSON::Array> parse = JSON::parse<JSON::Array>(output.get());
if (parse.isError()) {
return Failure("Failed to parse JSON: " + parse.error());
@@ -119,6 +190,8 @@ Future<Docker::Container> Docker::_inspect(const Subprocess& s)
Future<list<Docker::Container> > Docker::ps() const
{
+ VLOG(1) << "Running " << path << " ps";
+
Try<Subprocess> s = subprocess(
path + " ps",
Subprocess::PIPE(),
@@ -144,16 +217,24 @@ Future<list<Docker::Container> > Docker::_ps(
Option<int> status = s.status().get();
if (status.isSome() && status.get() != 0) {
- // TODO(benh): Include stdout and stderr in error message.
+ // TODO(benh): Include stderr in error message.
return Failure("Failed to do 'docker ps'");
}
// Read to EOF.
// TODO(benh): Read output asynchronously.
CHECK_SOME(s.out());
- string output = io::read(s.out().get()).get();
+ Result<string> output = os::read(s.out().get());
+
+ if (output.isError()) {
+ // TODO(benh): Include stderr in error message.
+ return Failure("Failed to read output: " + output.error());
+ } else if (output.isNone()) {
+ // TODO(benh): Include stderr in error message.
+ return Failure("No output available");
+ }
- vector<string> lines = strings::split(output, "\n");
+ vector<string> lines = strings::tokenize(output.get(), "\n");
// Skip the header.
CHECK_NE(0, lines.size());
@@ -163,7 +244,7 @@ Future<list<Docker::Container> > Docker::_ps(
foreach (const string& line, lines) {
// Inspect the container.
- futures.push_back(docker.inspect(strings::split(line, "\n")[0]));
+ futures.push_back(docker.inspect(strings::split(line, " ")[0]));
}
return collect(futures);
http://git-wip-us.apache.org/repos/asf/mesos/blob/fa400fef/src/docker/docker.hpp
----------------------------------------------------------------------
diff --git a/src/docker/docker.hpp b/src/docker/docker.hpp
index 26d6ec3..3bed71d 100644
--- a/src/docker/docker.hpp
+++ b/src/docker/docker.hpp
@@ -37,6 +37,9 @@ public:
public:
Container(const JSON::Object& json) : json(json) {}
+ // Returns the ID of the container.
+ std::string id() const;
+
// Returns the name of the container.
std::string name() const;
@@ -48,20 +51,26 @@ public:
Docker(const std::string& path) : path(path) {}
// Performs 'docker run IMAGE'.
- process::Future<Option<int> > run(const std::string& image) const;
+ process::Future<Option<int> > run(
+ const std::string& image,
+ const std::string& command,
+ const std::string& name) const;
// Performs 'docker kill CONTAINER'.
- process::Future<Option<int> > kill(const std::string& container) const;
+ process::Future<Option<int> > kill(
+ const std::string& container) const;
// Performs 'docker inspect CONTAINER'.
- process::Future<Container> inspect(const std::string& container) const;
+ process::Future<Container> inspect(
+ const std::string& container) const;
// Performs 'docker ps'.
process::Future<std::list<Container> > ps() const;
private:
// Continuations.
- static process::Future<Container> _inspect(const process::Subprocess& s);
+ static process::Future<Container> _inspect(
+ const process::Subprocess& s);
static process::Future<std::list<Container> > _ps(
const Docker& docker,
const process::Subprocess& s);