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/07/22 22:31:56 UTC
mesos git commit: Added implementation to Appc Runtime Isolator.
Repository: mesos
Updated Branches:
refs/heads/master 0eec82f3b -> b9c01fc36
Added implementation to Appc Runtime Isolator.
Review: https://reviews.apache.org/r/49348/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/b9c01fc3
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/b9c01fc3
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/b9c01fc3
Branch: refs/heads/master
Commit: b9c01fc36452ea9e4375e622ab9ac94000eef4b0
Parents: 0eec82f
Author: Srinivas Brahmaroutu <sr...@us.ibm.com>
Authored: Fri Jul 22 15:31:45 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Jul 22 15:31:45 2016 -0700
----------------------------------------------------------------------
.../mesos/isolators/appc/runtime.cpp | 218 ++++++++++++++++++-
1 file changed, 214 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/b9c01fc3/src/slave/containerizer/mesos/isolators/appc/runtime.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/appc/runtime.cpp b/src/slave/containerizer/mesos/isolators/appc/runtime.cpp
index 19c68e8..e8fe131 100644
--- a/src/slave/containerizer/mesos/isolators/appc/runtime.cpp
+++ b/src/slave/containerizer/mesos/isolators/appc/runtime.cpp
@@ -66,7 +66,77 @@ Future<Option<ContainerLaunchInfo>> AppcRuntimeIsolatorProcess::prepare(
const ContainerID& containerId,
const mesos::slave::ContainerConfig& containerConfig)
{
- return None();
+ const ExecutorInfo& executorInfo = containerConfig.executor_info();
+
+ if (!executorInfo.has_container()) {
+ return None();
+ }
+
+ if (executorInfo.container().type() != ContainerInfo::MESOS) {
+ return Failure("Can only prepare Appc runtime for a MESOS container");
+ }
+
+ if (!containerConfig.has_appc()) {
+ // No Appc image default config available.
+ return None();
+ }
+
+ Option<Environment> environment =
+ getLaunchEnvironment(containerId, containerConfig);
+
+ Option<string> workingDirectory = getWorkingDirectory(containerConfig);
+
+ Result<CommandInfo> command = getLaunchCommand(containerId, containerConfig);
+
+ if (command.isError()) {
+ return Failure("Failed to determine the launch command: " +
+ command.error());
+ }
+
+ // Set 'launchInfo'.
+ ContainerLaunchInfo launchInfo;
+
+ if (environment.isSome()) {
+ launchInfo.mutable_environment()->CopyFrom(environment.get());
+ }
+
+ // If working directory or command exists, operation has to be
+ // distinguished for either custom executor or command task. For
+ // custom executor case, info will be included in 'launchInfo', and
+ // will be passed back to containerizer. For command task case, info
+ // will be passed to command executor as flags.
+ if (!containerConfig.has_task_info()) {
+ // Custom executor case.
+ if (workingDirectory.isSome()) {
+ launchInfo.set_working_directory(workingDirectory.get());
+ }
+
+ if (command.isSome()) {
+ launchInfo.mutable_command()->CopyFrom(command.get());
+ }
+ } else {
+ // Command task case. The 'executorCommand' below is the
+ // command with value as 'mesos-executor'.
+ CommandInfo executorCommand = containerConfig.executor_info().command();
+
+ // Pass working directory to command executor as a flag.
+ if (workingDirectory.isSome()) {
+ executorCommand.add_arguments(
+ "--working_directory=" + workingDirectory.get());
+ }
+
+ // Pass task command as a flag, which will be loaded by
+ // command executor.
+ if (command.isSome()) {
+ executorCommand.add_arguments(
+ "--task_command=" +
+ stringify(JSON::protobuf(command.get())));
+ }
+
+ launchInfo.mutable_command()->CopyFrom(executorCommand);
+ }
+
+ return launchInfo;
}
@@ -74,7 +144,27 @@ Option<Environment> AppcRuntimeIsolatorProcess::getLaunchEnvironment(
const ContainerID& containerId,
const mesos::slave::ContainerConfig& containerConfig)
{
- return None();
+ if (!containerConfig.appc().manifest().has_app()) {
+ return None();
+ }
+
+ if (containerConfig.appc().manifest().app().environment_size() == 0) {
+ return None();
+ }
+
+ Environment environment;
+
+ foreach (const appc::spec::ImageManifest::Environment& env,
+ containerConfig.appc().manifest().app().environment()) {
+ // Keep all environment from runtime isolator. If there exists
+ // environment variable duplicate cases, it will be overwritten
+ // in mesos containerizer.
+ Environment::Variable* variable = environment.add_variables();
+ variable->set_name(env.name());
+ variable->set_value(env.value());
+ }
+
+ return environment;
}
@@ -84,14 +174,134 @@ Result<CommandInfo> AppcRuntimeIsolatorProcess::getLaunchCommand(
const ContainerID& containerId,
const mesos::slave::ContainerConfig& containerConfig)
{
- return None();
+ if (!containerConfig.appc().manifest().has_app()) {
+ return None();
+ }
+
+ // 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 false, and 'value' is not set, use 'Exec' from the image.
+ // Rows 1 and 2 in the table below. On row 2 notice that arguments in the
+ // image are overwritten when arguments are provided by the user.
+ // 2. If 'shell' is false and 'value' is set, ignore 'Exec' from the image.
+ // Rows 3 and 4 in the table below.
+ // 3. If 'shell' is true and 'value' is not set, Error.
+ // Rows 5 and 6 in the table below.
+ // 4. If 'shell' is true and 'value' is set, ignore 'Exec' from the image.
+ // Rows 7 and 8 in the table below.
+ // +---------+---------------+---------------+
+ // | | Exec=0 | Exec=1 |
+ // +---------+---------------+---------------+
+ // | sh=0 | Error | ./Exec[0] |
+ // | value=0 | | Exec[1].. |
+ // | argv=0 | | |
+ // +---------+---------------+---------------+
+ // | sh=0 | Error | ./Exec[0] |
+ // | value=0 | | argv |
+ // | argv=1 | | |
+ // +---------+---------------+---------------+
+ // | sh=0 | ./value | ./value |
+ // | value=1 | | |
+ // | argv=0 | | |
+ // +---------+---------------+---------------+
+ // | sh=0 | ./value | ./value |
+ // | value=1 | argv | argv |
+ // | argv=1 | | |
+ // +---------+---------------+---------------+
+ // | sh=1 | Error | Error |
+ // | value=0 | | |
+ // | argv=0 | | |
+ // +---------+---------------+---------------+
+ // | sh=1 | Error | Error |
+ // | value=0 | | |
+ // | argv=1 | | |
+ // +---------+---------------+---------------+
+ // | sh=1 | /bin/sh -c | /bin/sh -c |
+ // | value=1 | value | value |
+ // | argv=0 | | |
+ // +---------+---------------+---------------+
+ // | sh=1 | /bin/sh -c | /bin/sh -c |
+ // | value=1 | value | value |
+ // | argv=1 | | |
+ // +---------+---------------+---------------+
+ if (command.shell()) {
+ // Error that value is not set (row 5-6)
+ if (!command.has_value()) {
+ return Error("Shell specified but no command value provided");
+ }
+
+ // No need to mutate command (row 7-8).
+ return None();
+ }
+
+ if (command.has_value()) {
+ // No need to mutate command (row 3-4).
+ return None();
+ }
+
+ const appc::spec::ImageManifest::App& app =
+ containerConfig.appc().manifest().app();
+
+ if (app.exec_size() > 0) {
+ command.set_value(app.exec(0));
+
+ command.clear_arguments();
+ command.add_arguments(app.exec(0));
+
+ if (!containerConfig.has_task_info()) {
+ command.mutable_arguments()->MergeFrom(
+ containerConfig.executor_info().command().arguments());
+ } else {
+ command.mutable_arguments()->MergeFrom(
+ containerConfig.task_info().command().arguments());
+ }
+
+ if (command.arguments_size() == 1) {
+ for (int i = 1; i < app.exec_size(); i++) {
+ command.add_arguments(app.exec(i));
+ }
+ }
+ } else {
+ return Error("No executable is found");
+ }
+
+ return command;
}
Option<string> AppcRuntimeIsolatorProcess::getWorkingDirectory(
const mesos::slave::ContainerConfig& containerConfig)
{
- return None();
+ if (!containerConfig.appc().manifest().has_app()) {
+ return None();
+ }
+
+ // NOTE: In Appc manifest, if an image working directory is none,
+ // it will be set as `"workingDirectory": ""`.
+ if (!containerConfig.appc().manifest().app().has_workingdirectory() ||
+ containerConfig.appc().manifest().app().workingdirectory().empty()) {
+ return None();
+ }
+
+ return containerConfig.appc().manifest().app().workingdirectory();
}
} // namespace slave {