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/02/04 23:56:20 UTC
[1/3] mesos git commit: Renamed 'directory' flag to 'sandbox' in
mesos containerizer launch.
Repository: mesos
Updated Branches:
refs/heads/master 020d9ec43 -> d467eeeb8
Renamed 'directory' flag to 'sandbox' in mesos containerizer launch.
Review: https://reviews.apache.org/r/43166/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/d467eeeb
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/d467eeeb
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/d467eeeb
Branch: refs/heads/master
Commit: d467eeeb89a94c2ddacfc9248e0b2aecbbff56c0
Parents: 9228d91
Author: Gilbert Song <so...@gmail.com>
Authored: Thu Feb 4 14:09:36 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Thu Feb 4 14:56:14 2016 -0800
----------------------------------------------------------------------
src/slave/containerizer/mesos/containerizer.cpp | 2 +-
src/slave/containerizer/mesos/launch.cpp | 21 ++++++++++----------
src/slave/containerizer/mesos/launch.hpp | 2 +-
src/tests/containerizer/launch_tests.cpp | 2 +-
src/tests/containerizer/port_mapping_tests.cpp | 2 +-
5 files changed, 14 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/d467eeeb/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index 8039a10..dc0868e 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -1026,7 +1026,7 @@ Future<bool> MesosContainerizerProcess::__launch(
? JSON::protobuf(executorLaunchCommand.get())
: JSON::protobuf(executorInfo.command());
- launchFlags.directory = rootfs.isSome()
+ launchFlags.sandbox = rootfs.isSome()
? flags.sandbox_directory
: directory;
launchFlags.rootfs = rootfs;
http://git-wip-us.apache.org/repos/asf/mesos/blob/d467eeeb/src/slave/containerizer/mesos/launch.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.cpp b/src/slave/containerizer/mesos/launch.cpp
index 0cfdc0c..23970a2 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -51,16 +51,15 @@ MesosContainerizerLaunch::Flags::Flags()
"command",
"The command to execute.");
- // TODO(jieyu): Consider renaming it to 'sandbox'.
- add(&directory,
- "directory",
- "The directory to chdir to. If rootfs is specified this must\n"
+ add(&sandbox,
+ "sandbox",
+ "The sandbox to chdir to. If rootfs is specified this must\n"
"be relative to the new root.");
add(&rootfs,
"rootfs",
"Absolute path to the container root filesystem.\n"
- "The command and directory flags are interpreted relative\n"
+ "The command and sandbox flags are interpreted relative\n"
"to rootfs\n"
"Different platforms may implement 'chroot' differently.");
@@ -91,8 +90,8 @@ int MesosContainerizerLaunch::execute()
return 1;
}
- if (flags.directory.isNone()) {
- cerr << "Flag --directory is not specified" << endl;
+ if (flags.sandbox.isNone()) {
+ cerr << "Flag --sandbox is not specified" << endl;
return 1;
}
@@ -250,11 +249,11 @@ int MesosContainerizerLaunch::execute()
}
}
- // Enter working directory, relative to the new root.
- Try<Nothing> chdir = os::chdir(flags.directory.get());
+ // Enter sandbox directory, relative to the new root.
+ Try<Nothing> chdir = os::chdir(flags.sandbox.get());
if (chdir.isError()) {
- cerr << "Failed to chdir into work directory '"
- << flags.directory.get() << "': " << chdir.error() << endl;
+ cerr << "Failed to chdir into sandbox directory '"
+ << flags.sandbox.get() << "': " << chdir.error() << endl;
return 1;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/d467eeeb/src/slave/containerizer/mesos/launch.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.hpp b/src/slave/containerizer/mesos/launch.hpp
index 7220319..78d6b9d 100644
--- a/src/slave/containerizer/mesos/launch.hpp
+++ b/src/slave/containerizer/mesos/launch.hpp
@@ -35,7 +35,7 @@ public:
Flags();
Option<JSON::Object> command;
- Option<std::string> directory;
+ Option<std::string> sandbox;
Option<std::string> rootfs;
Option<std::string> user;
Option<int> pipe_read;
http://git-wip-us.apache.org/repos/asf/mesos/blob/d467eeeb/src/tests/containerizer/launch_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/launch_tests.cpp b/src/tests/containerizer/launch_tests.cpp
index c7ebe26..fd84c13 100644
--- a/src/tests/containerizer/launch_tests.cpp
+++ b/src/tests/containerizer/launch_tests.cpp
@@ -62,7 +62,7 @@ public:
command.set_value(_command);
launchFlags.command = JSON::protobuf(command);
- launchFlags.directory = "/tmp";
+ launchFlags.sandbox = "/tmp";
launchFlags.pipe_read = open("/dev/zero", O_RDONLY);
launchFlags.pipe_write = open("/dev/null", O_WRONLY);
launchFlags.rootfs = rootfs;
http://git-wip-us.apache.org/repos/asf/mesos/blob/d467eeeb/src/tests/containerizer/port_mapping_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/port_mapping_tests.cpp b/src/tests/containerizer/port_mapping_tests.cpp
index fd6f063..26261b0 100644
--- a/src/tests/containerizer/port_mapping_tests.cpp
+++ b/src/tests/containerizer/port_mapping_tests.cpp
@@ -309,7 +309,7 @@ protected:
MesosContainerizerLaunch::Flags launchFlags;
launchFlags.command = JSON::protobuf(commandInfo);
- launchFlags.directory = os::getcwd();
+ launchFlags.sandbox = os::getcwd();
CHECK_SOME(os::user());
launchFlags.user = os::user().get();
[3/3] mesos git commit: Supported entrypoint and cmd in docker
runtime isolator.
Posted by ji...@apache.org.
Supported entrypoint and cmd in docker runtime isolator.
Review: https://reviews.apache.org/r/43081/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/21224a75
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/21224a75
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/21224a75
Branch: refs/heads/master
Commit: 21224a75349871624db3753adb45de7e8ea2e863
Parents: 020d9ec
Author: Gilbert Song <so...@gmail.com>
Authored: Thu Feb 4 13:27:24 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Thu Feb 4 14:56:14 2016 -0800
----------------------------------------------------------------------
src/slave/containerizer/mesos/containerizer.cpp | 18 +-
.../mesos/isolators/docker/runtime.cpp | 176 +++++++++++++++++++
.../mesos/isolators/docker/runtime.hpp | 4 +
3 files changed, 197 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/21224a75/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index ed8a545..8039a10 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -924,6 +924,12 @@ Future<bool> MesosContainerizerProcess::__launch(
// Determine the root filesystem for the container. Only one
// isolator should return the container root filesystem.
Option<string> rootfs;
+
+ // Determine the executor launch command for the container.
+ // At most one command can be returned from docker runtime
+ // isolator if a docker image is specifed.
+ Option<CommandInfo> executorLaunchCommand;
+
foreach (const Option<ContainerLaunchInfo>& launchInfo, launchInfos) {
if (launchInfo.isSome() && launchInfo->has_rootfs()) {
if (rootfs.isSome()) {
@@ -950,6 +956,14 @@ Future<bool> MesosContainerizerProcess::__launch(
environment[name] = value;
}
}
+
+ if (launchInfo.isSome() && launchInfo->has_command()) {
+ if (executorLaunchCommand.isSome()) {
+ return Failure("At most one command can be returned from isolators");
+ } else {
+ executorLaunchCommand = launchInfo->command();
+ }
+ }
}
// TODO(jieyu): Consider moving this to 'executorEnvironment' and
@@ -1008,7 +1022,9 @@ Future<bool> MesosContainerizerProcess::__launch(
// Prepare the flags to pass to the launch process.
MesosContainerizerLaunch::Flags launchFlags;
- launchFlags.command = JSON::protobuf(executorInfo.command());
+ launchFlags.command = executorLaunchCommand.isSome()
+ ? JSON::protobuf(executorLaunchCommand.get())
+ : JSON::protobuf(executorInfo.command());
launchFlags.directory = rootfs.isSome()
? flags.sandbox_directory
http://git-wip-us.apache.org/repos/asf/mesos/blob/21224a75/src/slave/containerizer/mesos/isolators/docker/runtime.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/docker/runtime.cpp b/src/slave/containerizer/mesos/isolators/docker/runtime.cpp
index e60defd..c8a9372 100644
--- a/src/slave/containerizer/mesos/isolators/docker/runtime.cpp
+++ b/src/slave/containerizer/mesos/isolators/docker/runtime.cpp
@@ -19,8 +19,12 @@
#include <glog/logging.h>
+#include <mesos/docker/v1.hpp>
+
+#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/stringify.hpp>
+#include <stout/strings.hpp>
#include "slave/flags.hpp"
@@ -100,6 +104,17 @@ Future<Option<ContainerLaunchInfo>> DockerRuntimeIsolatorProcess::prepare(
launchInfo.mutable_environment()->CopyFrom(environment.get());
}
+ Try<CommandInfo> command = getExecutorLaunchCommand(
+ containerId,
+ containerConfig);
+
+ if (command.isError()) {
+ return Failure("Failed to determine the executor launch command: " +
+ command.error());
+ }
+
+ launchInfo.mutable_command()->CopyFrom(command.get());
+
return launchInfo;
}
@@ -144,6 +159,167 @@ Option<Environment> DockerRuntimeIsolatorProcess::getLaunchEnvironment(
}
+// This method reads the CommandInfo form ExecutorInfo and optional
+// TaskInfo, and merge them with docker image default Entrypoint and
+// Cmd. It returns a merged CommandInfo which will be used to launch
+// the executor.
+Try<CommandInfo> DockerRuntimeIsolatorProcess::getExecutorLaunchCommand(
+ const ContainerID& containerId,
+ const ContainerConfig& containerConfig)
+{
+ CHECK(containerConfig.docker().manifest().has_config());
+
+ // We may or may not mutate the CommandInfo for executor depending
+ // on the logic table below. For custom executor case, we make
+ // changes to the command directly. For command task case, if no
+ // need to change the launch command for the user task, we do not do
+ // anything and return the CommandInfo from ExecutorInfo. We only
+ // add a flag `--task_command` to carry command as a JSON object if
+ // it is neccessary to mutate.
+ CommandInfo command;
+
+ if (!containerConfig.has_task_info()) {
+ // Custom executor case.
+ CHECK(containerConfig.executor_info().has_command());
+ command = containerConfig.executor_info().command();
+ } else {
+ // Command task case.
+ CHECK(containerConfig.task_info().has_command());
+ command = containerConfig.task_info().command();
+ }
+
+ // We merge the CommandInfo following the logic:
+ // 1. If 'shell' is true, we will ignore Entrypoint and Cmd from
+ // the docker image (row 5-8).
+ // 2. If 'shell' is false and 'value' is set, we will ignore the
+ // Entrypoint and Cmd from the docker image as well (row 3-4).
+ // 3. If 'shell' is false and 'value' is not set, use the docker
+ // image specified runtime configuration.
+ // i. If 'Entrypoint' is set, it is treated as executable,
+ // then 'Cmd' get appended as arguments.
+ // ii.If 'Entrypoint' is not set, use the first 'Cmd' as
+ // executable and the others as arguments.
+ // +---------+--------------+--------------+--------------+--------------+
+ // | | Entrypoint=0 | Entrypoint=0 | Entrypoint=1 | Entrypoint=1 |
+ // | | Cmd=0 | Cmd=1 | Cmd=0 | Cmd=1 |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=0 | Error | ./Cmd[0] | ./Entrypt[0] | ./Entrypt[0] |
+ // | value=0 | | Cmd[1].. | Entrypt[1].. | Entrypt[1].. |
+ // | argv=0 | | | | Cmd.. |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=0 | Error | ./Cmd[0] | ./Entrypt[0] | ./Entrypt[0] |
+ // | value=0 | | argv | Entrypt[1].. | Entrypt[1].. |
+ // | argv=1 | | | argv | argv |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=0 | ./value | ./value | ./value | ./value |
+ // | value=1 | | | | |
+ // | argv=0 | | | | |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=0 | ./value | ./value | ./value | ./value |
+ // | value=1 | argv | argv | argv | argv |
+ // | argv=1 | | | | |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=1 | Error | Error | Error | Error |
+ // | value=0 | | | | |
+ // | argv=0 | | | | |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=1 | Error | Error | Error | Error |
+ // | value=0 | | | | |
+ // | argv=1 | | | | |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=1 | /bin/sh -c | /bin/sh -c | /bin/sh -c | /bin/sh -c |
+ // | value=1 | value | value | value | value |
+ // | argv=0 | | | | |
+ // +---------+--------------+--------------+--------------+--------------+
+ // | sh=1 | /bin/sh -c | /bin/sh -c | /bin/sh -c | /bin/sh -c |
+ // | value=1 | value | value | value | value |
+ // | argv=1 | | | | |
+ // +---------+--------------+--------------+--------------+--------------+
+ if (command.shell()) {
+ if (!command.has_value()) {
+ return Error("Shell specified but no command value provided");
+ }
+ } else {
+ if (!command.has_value()) {
+ // TODO(gilbert): Deprecate 'override' flag option in command
+ // task. We do not exclude override case here.
+
+ // We keep the arguments of commandInfo while it does not have a
+ // value, so that arguments can be specified by user, which is
+ // running with default image Entrypoint.
+ const docker::spec::v1::ImageManifest::Config& config =
+ containerConfig.docker().manifest().config();
+
+ // Filter out executable for commandInfo value.
+ if (config.entrypoint_size() > 0) {
+ command.set_value(config.entrypoint(0));
+
+ // Put user defined argv after default entrypoint argv
+ // in sequence.
+ command.clear_arguments();
+
+ for (int i = 1; i < config.entrypoint_size(); i++) {
+ command.add_arguments(config.entrypoint(i));
+ }
+
+ // Append all possible user argv after entrypoint arguments.
+ if (!containerConfig.has_task_info()) {
+ // Custom executor case.
+ command.mutable_arguments()->MergeFrom(
+ containerConfig.executor_info().command().arguments());
+ } else {
+ // Command task case.
+ command.mutable_arguments()->MergeFrom(
+ containerConfig.task_info().command().arguments());
+ }
+
+ // Overwrite default cmd arguments if CommandInfo arguments
+ // are set by user. The logic below is the case that no
+ // argument is set by user.
+ if (command.arguments_size() == config.entrypoint_size() - 1) {
+ foreach (const string& cmd, config.cmd()) {
+ command.add_arguments(cmd);
+ }
+ }
+ } else if (config.cmd_size() > 0) {
+ command.set_value(config.cmd(0));
+
+ // Overwrite default cmd arguments if CommandInfo arguments
+ // are set by user.
+ if (command.arguments_size() == 0) {
+ for (int i = 1; i < config.cmd_size(); i++) {
+ command.add_arguments(config.cmd(i));
+ }
+ }
+ } else {
+ return Error("No executable is found for container: '" +
+ containerId.value() + "'");
+ }
+ }
+ }
+
+ if (containerConfig.has_task_info()) {
+ // For command executor, with command value as 'mesos-executor'.
+ CommandInfo executorCommand = containerConfig.executor_info().command();
+
+ // Only pass the mutated command to command executor as a flag if
+ // image default config is included (see table above: row 1-2).
+ if (!containerConfig.task_info().command().shell() &&
+ !containerConfig.task_info().command().has_value()) {
+ JSON::Object object = JSON::protobuf(command);
+
+ // Pass task command as a flag, which will be loaded by
+ // command executor.
+ executorCommand.add_arguments("--task_command=" + stringify(object));
+ }
+
+ return executorCommand;
+ }
+
+ return command;
+}
+
+
Future<Nothing> DockerRuntimeIsolatorProcess::isolate(
const ContainerID& containerId,
pid_t pid)
http://git-wip-us.apache.org/repos/asf/mesos/blob/21224a75/src/slave/containerizer/mesos/isolators/docker/runtime.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/docker/runtime.hpp b/src/slave/containerizer/mesos/isolators/docker/runtime.hpp
index e419b6b..6e6ec86 100644
--- a/src/slave/containerizer/mesos/isolators/docker/runtime.hpp
+++ b/src/slave/containerizer/mesos/isolators/docker/runtime.hpp
@@ -65,6 +65,10 @@ private:
const ContainerID& containerId,
const mesos::slave::ContainerConfig& containerConfig);
+ Try<CommandInfo> getExecutorLaunchCommand(
+ const ContainerID& containerId,
+ const mesos::slave::ContainerConfig& containerConfig);
+
const Flags flags;
};
[2/3] mesos git commit: Added a new flag to command executor for
overriding the task command.
Posted by ji...@apache.org.
Added a new flag to command executor for overriding the task command.
Review: https://reviews.apache.org/r/43082/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/9228d91d
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/9228d91d
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/9228d91d
Branch: refs/heads/master
Commit: 9228d91d2da0d928f373bec205e0e31deeadfd37
Parents: 21224a7
Author: Gilbert Song <so...@gmail.com>
Authored: Thu Feb 4 13:48:37 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Thu Feb 4 14:56:14 2016 -0800
----------------------------------------------------------------------
src/launcher/executor.cpp | 115 ++++++++++++++++++++++++++++-------------
1 file changed, 78 insertions(+), 37 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/9228d91d/src/launcher/executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/executor.cpp b/src/launcher/executor.cpp
index 356d311..b214a3f 100644
--- a/src/launcher/executor.cpp
+++ b/src/launcher/executor.cpp
@@ -39,6 +39,7 @@
#include <stout/duration.hpp>
#include <stout/flags.hpp>
+#include <stout/json.hpp>
#include <stout/lambda.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
@@ -81,7 +82,8 @@ public:
const Option<char**>& override,
const string& _healthCheckDir,
const Option<string>& _sandboxDirectory,
- const Option<string>& _user)
+ const Option<string>& _user,
+ const Option<string>& _taskCommand)
: state(REGISTERING),
launched(false),
killed(false),
@@ -93,7 +95,8 @@ public:
healthCheckDir(_healthCheckDir),
override(override),
sandboxDirectory(_sandboxDirectory),
- user(_user) {}
+ user(_user),
+ taskCommand(_taskCommand) {}
virtual ~CommandExecutorProcess() {}
@@ -137,26 +140,46 @@ public:
return;
}
- // Skip sanity checks for TaskInfo if override is provided since
- // the executor will be running the override command.
- if (override.isNone()) {
- // Sanity checks.
- CHECK(task.has_command()) << "Expecting task " << task.task_id()
- << " to have a command!";
+ // Determine the command to launch the task.
+ CommandInfo command;
+
+ if (taskCommand.isSome()) {
+ // Get CommandInfo from a JSON string.
+ Try<JSON::Object> object = JSON::parse<JSON::Object>(taskCommand.get());
+ if (object.isError()) {
+ cerr << "Failed to parse JSON: " << object.error() << endl;
+ abort();
+ }
+
+ Try<CommandInfo> parse = protobuf::parse<CommandInfo>(object.get());
+ if (parse.isError()) {
+ cerr << "Failed to parse protobuf: " << parse.error() << endl;
+ abort();
+ }
+
+ command = parse.get();
+ } else if (task.has_command()) {
+ command = task.command();
+ } else {
+ CHECK_SOME(override)
+ << "Expecting task '" << task.task_id()
+ << "' to have a command!";
+ }
+ if (override.isNone()) {
// TODO(jieyu): For now, we just fail the executor if the task's
// CommandInfo is not valid. The framework will receive
// TASK_FAILED for the task, and will most likely find out the
// cause with some debugging. This is a temporary solution. A more
// correct solution is to perform this validation at master side.
- if (task.command().shell()) {
- CHECK(task.command().has_value())
- << "Shell command of task " << task.task_id()
- << " is not specified!";
+ if (command.shell()) {
+ CHECK(command.has_value())
+ << "Shell command of task '" << task.task_id()
+ << "' is not specified!";
} else {
- CHECK(task.command().has_value())
- << "Executable of task " << task.task_id()
- << " is not specified!";
+ CHECK(command.has_value())
+ << "Executable of task '" << task.task_id()
+ << "' is not specified!";
}
}
@@ -241,31 +264,31 @@ public:
}
// Prepare the argv before fork as it's not async signal safe.
- char **argv = new char*[task.command().arguments().size() + 1];
- for (int i = 0; i < task.command().arguments().size(); i++) {
- argv[i] = (char*) task.command().arguments(i).c_str();
+ char **argv = new char*[command.arguments().size() + 1];
+ for (int i = 0; i < command.arguments().size(); i++) {
+ argv[i] = (char*) command.arguments(i).c_str();
}
- argv[task.command().arguments().size()] = NULL;
+ argv[command.arguments().size()] = NULL;
// Prepare the command log message.
- string command;
+ string commandString;
if (override.isSome()) {
char** argv = override.get();
// argv is guaranteed to be NULL terminated and we rely on
// that fact to print command to be executed.
for (int i = 0; argv[i] != NULL; i++) {
- command += string(argv[i]) + " ";
+ commandString += string(argv[i]) + " ";
}
- } else if (task.command().shell()) {
- command = "sh -c '" + task.command().value() + "'";
+ } else if (command.shell()) {
+ commandString = "sh -c '" + command.value() + "'";
} else {
- command =
- "[" + task.command().value() + ", " +
- strings::join(", ", task.command().arguments()) + "]";
+ commandString =
+ "[" + command.value() + ", " +
+ strings::join(", ", command.arguments()) + "]";
}
if ((pid = fork()) == -1) {
- cerr << "Failed to fork to run " << command << ": "
+ cerr << "Failed to fork to run " << commandString << ": "
<< os::strerror(errno) << endl;
abort();
}
@@ -344,19 +367,19 @@ public:
}
- cout << command << endl;
+ cout << commandString << endl;
// The child has successfully setsid, now run the command.
if (override.isNone()) {
- if (task.command().shell()) {
+ if (command.shell()) {
execlp(
"sh",
"sh",
"-c",
- task.command().value().c_str(),
+ command.value().c_str(),
(char*) NULL);
} else {
- execvp(task.command().value().c_str(), argv);
+ execvp(command.value().c_str(), argv);
}
} else {
char** argv = override.get();
@@ -624,6 +647,7 @@ private:
Option<char**> override;
Option<string> sandboxDirectory;
Option<string> user;
+ Option<string> taskCommand;
};
@@ -634,10 +658,11 @@ public:
const Option<char**>& override,
const string& healthCheckDir,
const Option<string>& sandboxDirectory,
- const Option<string>& user)
+ const Option<string>& user,
+ const Option<string>& taskCommand)
{
process = new CommandExecutorProcess(
- override, healthCheckDir, sandboxDirectory, user);
+ override, healthCheckDir, sandboxDirectory, user, taskCommand);
spawn(process);
}
@@ -715,6 +740,8 @@ class Flags : public flags::FlagsBase
public:
Flags()
{
+ // TODO(gilbert): Deprecate the 'override' flag since no one is
+ // using it, and it may cause confusing with 'task_command' flag.
add(&override,
"override",
"Whether to override the command the executor should run when the\n"
@@ -734,6 +761,11 @@ public:
"user",
"The user that the task should be running as.");
+ add(&task_command,
+ "task_command",
+ "If specified, this is the overrided command for launching the\n"
+ "task (instead of the command from TaskInfo).");
+
// TODO(nnielsen): Add 'prefix' option to enable replacing
// 'sh -c' with user specified wrapper.
}
@@ -741,6 +773,7 @@ public:
bool override;
Option<string> sandbox_directory;
Option<string> user;
+ Option<string> task_command;
};
@@ -774,11 +807,19 @@ int main(int argc, char** argv)
}
const Option<string> envPath = os::getenv("MESOS_LAUNCHER_DIR");
- string path =
- envPath.isSome() ? envPath.get()
- : os::realpath(Path(argv[0]).dirname()).get();
+
+ string path = envPath.isSome()
+ ? envPath.get()
+ : os::realpath(Path(argv[0]).dirname()).get();
+
mesos::internal::CommandExecutor executor(
- override, path, flags.sandbox_directory, flags.user);
+ override,
+ path,
+ flags.sandbox_directory,
+ flags.user,
+ flags.task_command);
+
mesos::MesosExecutorDriver driver(&executor);
+
return driver.run() == mesos::DRIVER_STOPPED ? EXIT_SUCCESS : EXIT_FAILURE;
}