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 2012/03/27 08:03:47 UTC

svn commit: r1305740 - in /incubator/mesos/trunk: include/mesos/ src/common/ src/examples/ src/examples/java/ src/launcher/ src/slave/

Author: benh
Date: Tue Mar 27 06:03:46 2012
New Revision: 1305740

URL: http://svn.apache.org/viewvc?rev=1305740&view=rev
Log:
CommandInfo now accepts list of URIs (contributed by Vinod Kone).

Modified:
    incubator/mesos/trunk/include/mesos/mesos.proto
    incubator/mesos/trunk/src/common/type_utils.hpp
    incubator/mesos/trunk/src/examples/java/TestFramework.java
    incubator/mesos/trunk/src/examples/java/TestMultipleExecutorsFramework.java
    incubator/mesos/trunk/src/examples/long_lived_framework.cpp
    incubator/mesos/trunk/src/examples/test_framework.cpp
    incubator/mesos/trunk/src/launcher/launcher.cpp
    incubator/mesos/trunk/src/launcher/launcher.hpp
    incubator/mesos/trunk/src/launcher/main.cpp
    incubator/mesos/trunk/src/slave/http.cpp
    incubator/mesos/trunk/src/slave/lxc_isolation_module.cpp
    incubator/mesos/trunk/src/slave/process_based_isolation_module.cpp

Modified: incubator/mesos/trunk/include/mesos/mesos.proto
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/include/mesos/mesos.proto?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/include/mesos/mesos.proto (original)
+++ incubator/mesos/trunk/include/mesos/mesos.proto Tue Mar 27 06:03:46 2012
@@ -93,12 +93,20 @@ message FrameworkInfo {
 
 /**
  * Describes a command, executed via: '/bin/sh -c value'. Any uri's
- * specified are fetched before executing the command. In addition,
- * any environment variables are set before executing the command (so
- * they can be used to "parameterize" your command).
+ * specified are fetched before executing the command.
+ * If executable field for an uri is set, executable file permission 
+ * is set on the downloaded file. Also, if the downloaded file has ".tgz" 
+ * extension it is extracted into the executor's working directory.
+ * In addition, any environment variables are set before executing 
+ * the command (so they can be used to "parameterize" your command).
  */
 message CommandInfo {
-  optional string uri = 1; // TODO(benh): Make this repeated.
+  message URI {
+   required string value = 1;
+   optional bool executable = 2;
+  }
+
+  repeated URI uris = 1;
   optional Environment environment = 2;
   required string value = 3;
 }

Modified: incubator/mesos/trunk/src/common/type_utils.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/common/type_utils.hpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/common/type_utils.hpp (original)
+++ incubator/mesos/trunk/src/common/type_utils.hpp Tue Mar 27 06:03:46 2012
@@ -187,6 +187,7 @@ inline bool operator == (const Environme
       if (name == right.variables().Get(j).name() &&
           value == right.variables().Get(j).value()) {
         found = true;
+        break;
       }
     }
     if (!found) {
@@ -198,11 +199,35 @@ inline bool operator == (const Environme
 }
 
 
+inline bool operator == (const CommandInfo::URI& left,
+                         const CommandInfo::URI& right)
+{
+  return left.has_executable() == right.has_executable() &&
+    (!left.has_executable() || (left.executable() == right.executable())) &&
+    left.value() == right.value();
+}
+
+
 inline bool operator == (const CommandInfo& left, const CommandInfo& right)
 {
-  return left.has_uri() == right.has_uri() &&
-    (!left.has_uri() || (left.uri() == right.uri())) &&
-    left.has_environment() == right.has_environment() &&
+  if (left.uris().size() != right.uris().size()) {
+    return false;
+  }
+
+  for (int i=0; i<left.uris().size(); i++) {
+    bool found = false;
+    for (int j=0; j<right.uris().size(); j++) {
+      if (left.uris().Get(i) == right.uris().Get(j)) {
+        found = true;
+        break;
+      }
+    }
+    if (!found) {
+      return false;
+    }
+  }
+
+  return left.has_environment() == right.has_environment() &&
     (!left.has_environment() || (left.environment() == right.environment())) &&
     left.value() == right.value();
 }

Modified: incubator/mesos/trunk/src/examples/java/TestFramework.java
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/examples/java/TestFramework.java?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/examples/java/TestFramework.java (original)
+++ incubator/mesos/trunk/src/examples/java/TestFramework.java Tue Mar 27 06:03:46 2012
@@ -133,7 +133,7 @@ public class TestFramework {
 
     ExecutorInfo executor = ExecutorInfo.newBuilder()
       .setExecutorId(ExecutorID.newBuilder().setValue("default").build())
-      .setCommand(CommandInfo.newBuilder().setUri(uri).setValue(uri).build())
+      .setCommand(CommandInfo.newBuilder().setValue(uri).build())
       .build();
 
     MesosSchedulerDriver driver = args.length == 1

Modified: incubator/mesos/trunk/src/examples/java/TestMultipleExecutorsFramework.java
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/examples/java/TestMultipleExecutorsFramework.java?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/examples/java/TestMultipleExecutorsFramework.java (original)
+++ incubator/mesos/trunk/src/examples/java/TestMultipleExecutorsFramework.java Tue Mar 27 06:03:46 2012
@@ -75,7 +75,6 @@ public class TestMultipleExecutorsFramew
                                           .setValue("executor-foo")
                                           .build())
                            .setCommand(CommandInfo.newBuilder()
-                                       .setUri(file.getCanonicalPath())
                                        .setValue(file.getCanonicalPath())
                                        .build())
                            .build())
@@ -117,7 +116,6 @@ public class TestMultipleExecutorsFramew
                                           .setValue("executor-bar")
                                           .build())
                            .setCommand(CommandInfo.newBuilder()
-                                       .setUri(file.getCanonicalPath())
                                        .setValue(file.getCanonicalPath())
                                        .build())
                            .build())

Modified: incubator/mesos/trunk/src/examples/long_lived_framework.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/examples/long_lived_framework.cpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/examples/long_lived_framework.cpp (original)
+++ incubator/mesos/trunk/src/examples/long_lived_framework.cpp Tue Mar 27 06:03:46 2012
@@ -156,7 +156,6 @@ int main(int argc, char** argv)
 
   ExecutorInfo executor;
   executor.mutable_executor_id()->set_value("default");
-  executor.mutable_command()->set_uri(uri);
   executor.mutable_command()->set_value(uri);
 
   LongLivedScheduler scheduler(executor);

Modified: incubator/mesos/trunk/src/examples/test_framework.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/examples/test_framework.cpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/examples/test_framework.cpp (original)
+++ incubator/mesos/trunk/src/examples/test_framework.cpp Tue Mar 27 06:03:46 2012
@@ -168,7 +168,6 @@ int main(int argc, char** argv)
 
   ExecutorInfo executor;
   executor.mutable_executor_id()->set_value("default");
-  executor.mutable_command()->set_uri(uri);
   executor.mutable_command()->set_value(uri);
 
   TestScheduler scheduler(executor);

Modified: incubator/mesos/trunk/src/launcher/launcher.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/launcher/launcher.cpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/launcher/launcher.cpp (original)
+++ incubator/mesos/trunk/src/launcher/launcher.cpp Tue Mar 27 06:03:46 2012
@@ -47,8 +47,7 @@ namespace launcher {
 ExecutorLauncher::ExecutorLauncher(
     const FrameworkID& _frameworkId,
     const ExecutorID& _executorId,
-    const string& _executorUri,
-    const string& _command,
+    const CommandInfo& _commandInfo,
     const string& _user,
     const string& _workDirectory,
     const string& _slavePid,
@@ -56,12 +55,10 @@ ExecutorLauncher::ExecutorLauncher(
     const string& _hadoopHome,
     bool _redirectIO,
     bool _shouldSwitchUser,
-    const string& _container,
-    const Environment& _environment)
+    const string& _container)
   : frameworkId(_frameworkId),
     executorId(_executorId),
-    executorUri(_executorUri),
-    command(_command),
+    commandInfo(_commandInfo),
     user(_user),
     workDirectory(_workDirectory),
     slavePid(_slavePid),
@@ -69,8 +66,7 @@ ExecutorLauncher::ExecutorLauncher(
     hadoopHome(_hadoopHome),
     redirectIO(_redirectIO),
     shouldSwitchUser(_shouldSwitchUser),
-    container(_container),
-    environment(_environment) {}
+    container(_container) {}
 
 
 ExecutorLauncher::~ExecutorLauncher() {}
@@ -95,7 +91,7 @@ int ExecutorLauncher::run()
     }
   }
 
-  fetchExecutor(); // TODO(benh): fetchExecutors();
+  fetchExecutors();
 
   setupEnvironment();
 
@@ -103,6 +99,8 @@ int ExecutorLauncher::run()
     switchUser();
   }
 
+  const string& command = commandInfo.value();
+
   // TODO(benh): Clean up this gross special cased LXC garbage!!!!
   if (container != "") {
     // If we are running with a container than we need to fork an
@@ -142,11 +140,13 @@ void ExecutorLauncher::initializeWorking
 }
 
 
-// Download the executor's binary if required and return its path.
-void ExecutorLauncher::fetchExecutor()
-{
-  if (executorUri != "") {
-    string executor = executorUri;
+// Download the executor's files and optionally set executable permissions
+// if requested.
+void ExecutorLauncher::fetchExecutors()
+{
+  foreach(const CommandInfo::URI& uri, commandInfo.uris()) {
+    string executor = uri.value();
+    bool executable = uri.has_executable() && uri.executable();
 
     // Some checks to make using the executor in shell commands safe;
     // these should be pushed into the master and reported to the user
@@ -182,7 +182,7 @@ void ExecutorLauncher::fetchExecutor()
       if (ret != 0)
         fatal("HDFS copyToLocal failed: return code %d", ret);
       executor = localFile;
-      if (chmod(executor.c_str(), S_IRWXU | S_IRGRP | S_IXGRP |
+      if (executable && chmod(executor.c_str(), S_IRWXU | S_IRGRP | S_IXGRP |
                 S_IROTH | S_IXOTH) != 0)
         fatalerror("chmod failed");
     } else if (executor.find("http://") == 0
@@ -202,7 +202,7 @@ void ExecutorLauncher::fetchExecutor()
               code.get());
       }
       executor = path;
-      if (chmod(executor.c_str(), S_IRWXU | S_IRGRP | S_IXGRP |
+      if (executable && chmod(executor.c_str(), S_IRWXU | S_IRGRP | S_IXGRP |
                 S_IROTH | S_IXOTH) != 0)
         fatalerror("chmod failed");
     } else if (executor.find_first_of("/") != 0) {
@@ -219,43 +219,13 @@ void ExecutorLauncher::fetchExecutor()
       }
     }
 
-    // If the executor was a .tgz, untar it in the work directory. The .tgz
-    // expected to contain a single directory. This directory should contain
-    // a program or script called "executor" to run the executor. We chdir
-    // into this directory and run the script from in there.
+    // If the executor was a .tgz, untar it in the work directory.
     if (executor.rfind(".tgz") == executor.size() - strlen(".tgz")) {
       string command = "tar xzf '" + executor + "'";
       cout << "Untarring executor: " + command << endl;
       int ret = system(command.c_str());
       if (ret != 0)
         fatal("Untar failed: return code %d", ret);
-      // The .tgz should have contained a single directory; find it
-      if (DIR *dir = opendir(".")) {
-        bool found = false;
-        string dirname = "";
-        while (struct dirent *ent = readdir(dir)) {
-          if (string(".") != ent->d_name && string("..") != ent->d_name) {
-            struct stat info;
-            if (stat(ent->d_name, &info) == 0) {
-              if (S_ISDIR(info.st_mode)) {
-                if (found) // Already found a directory earlier
-                  fatal("Executor .tgz must contain a single directory");
-                dirname = ent->d_name;
-                found = true;
-              }
-            } else {
-              fatalerror("Stat failed on %s", ent->d_name);
-            }
-          }
-        }
-        if (!found) // No directory found
-          fatal("Executor .tgz must contain a single directory");
-        if (chdir(dirname.c_str()) < 0)
-          fatalerror("Chdir failed");
-        executor = "./executor";
-      } else {
-        fatalerror("Failed to list work directory");
-      }
     }
   }
 }
@@ -265,8 +235,11 @@ void ExecutorLauncher::fetchExecutor()
 void ExecutorLauncher::setupEnvironment()
 {
   // Set up the environment as specified in the ExecutorInfo.
-  foreach (const Environment::Variable& variable, environment.variables()) {
-    utils::os::setenv(variable.name(), variable.value());
+  if (commandInfo.has_environment()) {
+    foreach (const Environment::Variable& variable,
+             commandInfo.environment().variables()) {
+      utils::os::setenv(variable.name(), variable.value());
+    }
   }
 
   // Set Mesos environment variables for slave ID, framework ID, etc.
@@ -295,9 +268,21 @@ void ExecutorLauncher::setupEnvironmentF
 
   // Set up Mesos environment variables that launcher/main.cpp will
   // pass as arguments to an ExecutorLauncher there.
+  string uris = "";
+  foreach (const CommandInfo::URI& uri, commandInfo.uris()) {
+   uris += uri.value() + "+" +
+           (uri.has_executable() && uri.executable() ? "1" : "0");
+   uris += " ";
+  }
+
+  // Remove extra space at the end.
+  if (uris.size() > 0) {
+    uris = strings::trim(uris);
+  }
+
   utils::os::setenv("MESOS_FRAMEWORK_ID", frameworkId.value());
-  utils::os::setenv("MESOS_EXECUTOR_URI", executorUri);
-  utils::os::setenv("MESOS_COMMAND", command);
+  utils::os::setenv("MESOS_COMMAND", commandInfo.value());
+  utils::os::setenv("MESOS_EXECUTOR_URIS", uris);
   utils::os::setenv("MESOS_USER", user);
   utils::os::setenv("MESOS_WORK_DIRECTORY", workDirectory);
   utils::os::setenv("MESOS_SLAVE_PID", slavePid);

Modified: incubator/mesos/trunk/src/launcher/launcher.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/launcher/launcher.hpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/launcher/launcher.hpp (original)
+++ incubator/mesos/trunk/src/launcher/launcher.hpp Tue Mar 27 06:03:46 2012
@@ -44,8 +44,7 @@ public:
   ExecutorLauncher(
       const FrameworkID& frameworkId,
       const ExecutorID& executorId,
-      const std::string& executorUri,
-      const std::string& command,
+      const CommandInfo& commandInfo,
       const std::string& user,
       const std::string& workDirectory,
       const std::string& slavePid,
@@ -53,8 +52,7 @@ public:
       const std::string& hadoopHome,
       bool redirectIO,
       bool shouldSwitchUser,
-      const std::string& container,
-      const Environment& environment);
+      const std::string& container);
 
   virtual ~ExecutorLauncher();
 
@@ -73,10 +71,11 @@ protected:
   // Initialize executor's working director.
   virtual void initializeWorkingDirectory();
 
-  // Download the executor's binary if required and return its path.
+  // Download the required files for the executor from the given set of URIs.
+  // Optionally, it will set the executable file permissions for the files.
   // This method is expected to place files in the current directory
   // (which will be the workDirectory).
-  virtual void fetchExecutor();
+  virtual void fetchExecutors();
 
   // Set up environment variables for launching a framework's executor.
   virtual void setupEnvironment();
@@ -87,8 +86,7 @@ protected:
 protected:
   FrameworkID frameworkId;
   ExecutorID executorId;
-  std::string executorUri;
-  std::string command;
+  CommandInfo commandInfo;
   std::string user;
   std::string workDirectory; // Directory in which the framework should run.
   std::string slavePid;
@@ -97,7 +95,6 @@ protected:
   bool redirectIO;   // Whether to redirect stdout and stderr to files.
   bool shouldSwitchUser; // Whether to setuid to framework's user.
   std::string container;
-  Environment environment;
 };
 
 } // namespace launcher {

Modified: incubator/mesos/trunk/src/launcher/main.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/launcher/main.cpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/launcher/main.cpp (original)
+++ incubator/mesos/trunk/src/launcher/main.cpp Tue Mar 27 06:03:46 2012
@@ -18,6 +18,7 @@
 
 #include <mesos/mesos.hpp>
 
+#include "common/strings.hpp"
 #include "common/utils.hpp"
 
 #include "launcher/launcher.hpp"
@@ -36,11 +37,27 @@ int main(int argc, char** argv)
   ExecutorID executorId;
   executorId.set_value(utils::os::getenv("MESOS_EXECUTOR_ID"));
 
+  CommandInfo commandInfo;
+  commandInfo.set_value(utils::os::getenv("MESOS_COMMAND"));
+
+  // Construct URIs from the encoded environment string.
+  const std::string& uris = utils::os::getenv("MESOS_EXECUTOR_URIS");
+  foreach (const std::string& token, strings::split(uris, " ")) {
+    size_t pos = token.rfind("+"); // Delim between uri and exec permission.
+    CHECK(pos != std::string::npos) << "Invalid executor uri token in env "
+                                    << token;
+
+    CommandInfo::URI uri;
+    uri.set_value(token.substr(0, pos));
+    uri.set_executable(token.substr(pos + 1) == "1");
+
+    commandInfo.add_uris()->MergeFrom(uri);
+  }
+
   return mesos::internal::launcher::ExecutorLauncher(
       frameworkId,
       executorId,
-      utils::os::getenv("MESOS_EXECUTOR_URI"),
-      utils::os::getenv("MESOS_COMMAND"),
+      commandInfo,
       utils::os::getenv("MESOS_USER"),
       utils::os::getenv("MESOS_WORK_DIRECTORY"),
       utils::os::getenv("MESOS_SLAVE_PID"),
@@ -48,6 +65,6 @@ int main(int argc, char** argv)
       utils::os::getenv("MESOS_HADOOP_HOME"),
       utils::os::getenv("MESOS_REDIRECT_IO") == "1",
       utils::os::getenv("MESOS_SWITCH_USER") == "1",
-      utils::os::getenv("MESOS_CONTAINER", false),
-      Environment()).run();
+      utils::os::getenv("MESOS_CONTAINER", false))
+    .run();
 }

Modified: incubator/mesos/trunk/src/slave/http.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/slave/http.cpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/slave/http.cpp (original)
+++ incubator/mesos/trunk/src/slave/http.cpp Tue Mar 27 06:03:46 2012
@@ -65,7 +65,6 @@ JSON::Object model(const Executor& execu
 {
   JSON::Object object;
   object.values["id"] = executor.id.value();
-  object.values["uri"] = executor.info.command().uri();
   object.values["directory"] = executor.directory;
   object.values["resources"] = model(executor.resources);
 

Modified: incubator/mesos/trunk/src/slave/lxc_isolation_module.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/slave/lxc_isolation_module.cpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/slave/lxc_isolation_module.cpp (original)
+++ incubator/mesos/trunk/src/slave/lxc_isolation_module.cpp Tue Mar 27 06:03:46 2012
@@ -174,17 +174,15 @@ void LxcIsolationModule::launchExecutor(
     ExecutorLauncher* launcher =
       new ExecutorLauncher(frameworkId,
 			   executorId,
-			   executorInfo.command().uri(),
-			   executorInfo.command().value(),
+			   executorInfo.command(),
 			   frameworkInfo.user(),
-                           directory,
+         directory,
 			   slave,
 			   conf.get("frameworks_home", ""),
 			   conf.get("hadoop_home", ""),
 			   !local,
 			   conf.get("switch_user", true),
-			   container,
-			   executorInfo.command().environment());
+			   container);
 
     launcher->setupEnvironmentForLauncherMain();
 

Modified: incubator/mesos/trunk/src/slave/process_based_isolation_module.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/slave/process_based_isolation_module.cpp?rev=1305740&r1=1305739&r2=1305740&view=diff
==============================================================================
--- incubator/mesos/trunk/src/slave/process_based_isolation_module.cpp (original)
+++ incubator/mesos/trunk/src/slave/process_based_isolation_module.cpp Tue Mar 27 06:03:46 2012
@@ -89,7 +89,7 @@ void ProcessBasedIsolationModule::launch
   const ExecutorID& executorId = executorInfo.executor_id();
 
   LOG(INFO) << "Launching " << executorId
-            << " (" << executorInfo.command().uri() << ")"
+            << " (" << executorInfo.command().value() << ")"
             << " in " << directory
             << " with resources " << resources
             << "' for framework " << frameworkId;
@@ -186,8 +186,7 @@ ExecutorLauncher* ProcessBasedIsolationM
 {
   return new ExecutorLauncher(frameworkId,
                               executorInfo.executor_id(),
-                              executorInfo.command().uri(),
-                              executorInfo.command().value(),
+                              executorInfo.command(),
                               frameworkInfo.user(),
                               directory,
                               slave,
@@ -195,8 +194,7 @@ ExecutorLauncher* ProcessBasedIsolationM
                               conf.get("hadoop_home", ""),
                               !local,
                               conf.get("switch_user", true),
-                              "",
-                              executorInfo.command().environment());
+                              "");
 }