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 {