You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by vi...@apache.org on 2016/08/15 22:25:27 UTC

[1/4] mesos git commit: Added LAUNCH_GROUP event to executor API.

Repository: mesos
Updated Branches:
  refs/heads/master fc5f86ab0 -> 40115df30


Added LAUNCH_GROUP event to executor API.

This event is used to deliver a task group atomically to an executor.

Review: https://reviews.apache.org/r/51062


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/40115df3
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/40115df3
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/40115df3

Branch: refs/heads/master
Commit: 40115df3021cf0951cb3c9925cd979819d438e3a
Parents: a43b015
Author: Vinod Kone <vi...@gmail.com>
Authored: Fri Aug 12 15:41:01 2016 -0700
Committer: Vinod Kone <vi...@gmail.com>
Committed: Mon Aug 15 15:25:05 2016 -0700

----------------------------------------------------------------------
 include/mesos/executor/executor.proto    | 9 +++++++++
 include/mesos/v1/executor/executor.proto | 9 +++++++++
 src/examples/long_lived_executor.cpp     | 5 +++++
 src/examples/test_http_executor.cpp      | 6 ++++++
 src/launcher/executor.cpp                | 9 +++++++++
 src/tests/mesos.hpp                      | 3 +++
 6 files changed, 41 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/40115df3/include/mesos/executor/executor.proto
----------------------------------------------------------------------
diff --git a/include/mesos/executor/executor.proto b/include/mesos/executor/executor.proto
index 9aa046e..0d31406 100644
--- a/include/mesos/executor/executor.proto
+++ b/include/mesos/executor/executor.proto
@@ -40,6 +40,7 @@ message Event {
 
     SUBSCRIBED = 1;   // See 'Subscribed' below.
     LAUNCH = 2;       // See 'Launch' below.
+    LAUNCH_GROUP = 8; // See 'LaunchGroup' below.
     KILL = 3;         // See 'Kill' below.
     ACKNOWLEDGED = 4; // See 'Acknowledged' below.
     MESSAGE = 5;      // See 'Message' below.
@@ -80,6 +81,13 @@ message Event {
     required TaskInfo task = 1;
   }
 
+  // Received when the framework attempts to launch a group of tasks atomically.
+  // Similar to `Launch` above the executor must send TASK_RUNNING updates for
+  // tasks that are successfully launched.
+  message LaunchGroup {
+    required TaskGroupInfo task_group = 1;
+  }
+
   // Received when the scheduler wants to kill a specific task. Once
   // the task is terminated, the executor should send a TASK_KILLED
   // (or TASK_FAILED) update. The terminal update is necessary so
@@ -129,6 +137,7 @@ message Event {
   optional Subscribed subscribed = 2;
   optional Acknowledged acknowledged = 3;
   optional Launch launch = 4;
+  optional LaunchGroup launch_group = 8;
   optional Kill kill = 5;
   optional Message message = 6;
   optional Error error = 7;

http://git-wip-us.apache.org/repos/asf/mesos/blob/40115df3/include/mesos/v1/executor/executor.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/executor/executor.proto b/include/mesos/v1/executor/executor.proto
index 5e76e4e..0783596 100644
--- a/include/mesos/v1/executor/executor.proto
+++ b/include/mesos/v1/executor/executor.proto
@@ -40,6 +40,7 @@ message Event {
 
     SUBSCRIBED = 1;   // See 'Subscribed' below.
     LAUNCH = 2;       // See 'Launch' below.
+    LAUNCH_GROUP = 8; // See 'LaunchGroup' below.
     KILL = 3;         // See 'Kill' below.
     ACKNOWLEDGED = 4; // See 'Acknowledged' below.
     MESSAGE = 5;      // See 'Message' below.
@@ -80,6 +81,13 @@ message Event {
     required TaskInfo task = 1;
   }
 
+  // Received when the framework attempts to launch a group of tasks atomically.
+  // Similar to `Launch` above the executor must send TASK_RUNNING updates for
+  // tasks that are successfully launched.
+  message LaunchGroup {
+    required TaskGroupInfo task_group = 1;
+  }
+
   // Received when the scheduler wants to kill a specific task. Once
   // the task is terminated, the executor should send a TASK_KILLED
   // (or TASK_FAILED) update. The terminal update is necessary so
@@ -130,6 +138,7 @@ message Event {
   optional Subscribed subscribed = 2;
   optional Acknowledged acknowledged = 3;
   optional Launch launch = 4;
+  optional LaunchGroup launch_group = 8;
   optional Kill kill = 5;
   optional Message message = 6;
   optional Error error = 7;

http://git-wip-us.apache.org/repos/asf/mesos/blob/40115df3/src/examples/long_lived_executor.cpp
----------------------------------------------------------------------
diff --git a/src/examples/long_lived_executor.cpp b/src/examples/long_lived_executor.cpp
index 5c1fde1..65fc9af 100644
--- a/src/examples/long_lived_executor.cpp
+++ b/src/examples/long_lived_executor.cpp
@@ -111,6 +111,11 @@ protected:
           break;
         }
 
+        case Event::LAUNCH_GROUP: {
+          // TODO(vinod): Implement this.
+          break;
+        }
+
         case Event::ACKNOWLEDGED: {
           // Remove the corresponding update.
           updates.erase(UUID::fromBytes(event.acknowledged().uuid()).get());

http://git-wip-us.apache.org/repos/asf/mesos/blob/40115df3/src/examples/test_http_executor.cpp
----------------------------------------------------------------------
diff --git a/src/examples/test_http_executor.cpp b/src/examples/test_http_executor.cpp
index 19d0f68..b9b6bfd 100644
--- a/src/examples/test_http_executor.cpp
+++ b/src/examples/test_http_executor.cpp
@@ -158,6 +158,12 @@ public:
           break;
         }
 
+        case Event::LAUNCH_GROUP: {
+          cout << "Received a LAUNCH_GROUP event";
+          // TODO(vinod): Implement this.
+          break;
+        }
+
         case Event::KILL: {
           cout << "Received a KILL event" << endl;
           break;

http://git-wip-us.apache.org/repos/asf/mesos/blob/40115df3/src/launcher/executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/executor.cpp b/src/launcher/executor.cpp
index 2d04edb..71ede1e 100644
--- a/src/launcher/executor.cpp
+++ b/src/launcher/executor.cpp
@@ -195,6 +195,15 @@ public:
         break;
       }
 
+      case Event::LAUNCH_GROUP: {
+        cerr << "LAUNCH_GROUP event is not supported" << endl;
+        // Shut down because this is unexpected; `LAUNCH_GROUP` event
+        // should only ever go to a group-capable default executor and
+        // not the command executor.
+        shutdown();
+        break;
+      }
+
       case Event::KILL: {
         Option<KillPolicy> override = event.kill().has_kill_policy()
           ? Option<KillPolicy>(event.kill().kill_policy())

http://git-wip-us.apache.org/repos/asf/mesos/blob/40115df3/src/tests/mesos.hpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp
index 3a1860d..4cae54b 100644
--- a/src/tests/mesos.hpp
+++ b/src/tests/mesos.hpp
@@ -1158,6 +1158,9 @@ public:
       case Event::LAUNCH:
         launch(mesos, event.launch());
         break;
+      case Event::LAUNCH_GROUP:
+        // TODO(vinod): Implement this.
+        break;
       case Event::KILL:
         kill(mesos, event.kill());
         break;


[4/4] mesos git commit: Made `ExecutorInfo.command` optional.

Posted by vi...@apache.org.
Made `ExecutorInfo.command` optional.

This is done to allow schedulers to use `ExecutorInfo` with just
`executor_id` set. This is a requirement for the upcoming support
for `TaskGroup` semantics.

Note that in this patch, TASK_ERROR is returned when
`ExecutorInfo.command` is unset to keep the existing semantics for
`LAUNCH` offer operation. This might change when we add `LAUNCH_GROUP`
operation.

Review: https://reviews.apache.org/r/51059


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/c7f5d870
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/c7f5d870
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/c7f5d870

Branch: refs/heads/master
Commit: c7f5d870fb61f63c5ec1eb5cf0cd95022c49dee3
Parents: fc5f86a
Author: Vinod Kone <vi...@gmail.com>
Authored: Fri Aug 12 12:59:17 2016 -0700
Committer: Vinod Kone <vi...@gmail.com>
Committed: Mon Aug 15 15:25:05 2016 -0700

----------------------------------------------------------------------
 include/mesos/mesos.proto             | 37 ++++++++++++++++++++++++---
 include/mesos/v1/mesos.proto          | 37 ++++++++++++++++++++++++---
 src/master/validation.cpp             | 21 +++++++++++++---
 src/tests/master_validation_tests.cpp | 40 ++++++++++++++++++++++++++++++
 4 files changed, 125 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c7f5d870/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index cd75038..90518a2 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -501,13 +501,43 @@ message CommandInfo {
 
 
 /**
- * Describes information about an executor. The 'data' field can be
- * used to pass arbitrary bytes to an executor.
+ * Describes information about an executor.
  */
 message ExecutorInfo {
+  enum Type {
+    UNKNOWN = 0;
+
+    // Mesos provides a simple built-in default executor that frameworks can
+    // leverage to run shell commands and containers.
+    //
+    // NOTES:
+    //
+    // 1) `command` must not be set when using a default executor.
+    //
+    // 2) If "cpu" or "mem" resources are not set, default values of 0.1 cpu
+    //    and 32 MB memory will be used; schedulers should account for these
+    //    resources when accepting offers.
+    //
+    // 3) Default executor only accepts a *single* launch operation.
+    DEFAULT = 1;
+
+    // For frameworks that need custom functionality to run tasks, a `CUSTOM`
+    // executor can be used. Note that `command` must be set when using a
+    // `CUSTOM` executor.
+    CUSTOM = 2;
+  }
+
+  // For backwards compatibility, if this field is not set when using `LAUNCH`
+  // offer operation, Mesos will infer the type by checking if `command` is
+  // set (`CUSTOM`) or unset (`DEFAULT`).
+  //
+  // TODO(vinod): Add support for explicitly setting `type` to `DEFAULT `
+  // in `LAUNCH` offer operation.
+  optional Type type = 15;
+
   required ExecutorID executor_id = 1;
   optional FrameworkID framework_id = 8; // TODO(benh): Make this required.
-  required CommandInfo command = 7;
+  optional CommandInfo command = 7;
 
   // Executor provided with a container will launch the container
   // with the executor's CommandInfo and we expect the container to
@@ -529,6 +559,7 @@ message ExecutorInfo {
   // free-form metadata instead.
   optional string source = 10 [deprecated = true]; // Since 1.0.
 
+  // This field can be used to pass arbitrary bytes to an executor.
   optional bytes data = 4;
 
   // Service discovery information for the executor. It is not

http://git-wip-us.apache.org/repos/asf/mesos/blob/c7f5d870/include/mesos/v1/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/mesos.proto b/include/mesos/v1/mesos.proto
index a30f877..93a4bce 100644
--- a/include/mesos/v1/mesos.proto
+++ b/include/mesos/v1/mesos.proto
@@ -501,13 +501,43 @@ message CommandInfo {
 
 
 /**
- * Describes information about an executor. The 'data' field can be
- * used to pass arbitrary bytes to an executor.
+ * Describes information about an executor.
  */
 message ExecutorInfo {
+  enum Type {
+    UNKNOWN = 0;
+
+    // Mesos provides a simple built-in default executor that frameworks can
+    // leverage to run shell commands and containers.
+    //
+    // NOTES:
+    //
+    // 1) `command` must not be set when using a default executor.
+    //
+    // 2) If "cpu" or "mem" resources are not set, default values of 0.1 cpu
+    //    and 32 MB memory will be used; schedulers should account for these
+    //    resources when accepting offers.
+    //
+    // 3) Default executor only accepts a *single* launch operation.
+    DEFAULT = 1;
+
+    // For frameworks that need custom functionality to run tasks, a `CUSTOM`
+    // executor can be used. Note that `command` must be set when using a
+    // `CUSTOM` executor.
+    CUSTOM = 2;
+  }
+
+  // For backwards compatibility, if this field is not set when using `LAUNCH`
+  // offer operation, Mesos will infer the type by checking if `command` is
+  // set (`CUSTOM`) or unset (`DEFAULT`).
+  //
+  // TODO(vinod): Add support for explicitly setting `type` to `DEFAULT `
+  // in `LAUNCH` offer operation.
+  optional Type type = 15;
+
   required ExecutorID executor_id = 1;
   optional FrameworkID framework_id = 8; // TODO(benh): Make this required.
-  required CommandInfo command = 7;
+  optional CommandInfo command = 7;
 
   // Executor provided with a container will launch the container
   // with the executor's CommandInfo and we expect the container to
@@ -529,6 +559,7 @@ message ExecutorInfo {
   // free-form metadata instead.
   optional string source = 10 [deprecated = true]; // Since 1.0.
 
+  // This field can be used to pass arbitrary bytes to an executor.
   optional bytes data = 4;
 
   // Service discovery information for the executor. It is not

http://git-wip-us.apache.org/repos/asf/mesos/blob/c7f5d870/src/master/validation.cpp
----------------------------------------------------------------------
diff --git a/src/master/validation.cpp b/src/master/validation.cpp
index 52d9137..ddc7ac3 100644
--- a/src/master/validation.cpp
+++ b/src/master/validation.cpp
@@ -572,10 +572,8 @@ Option<Error> validateExecutorInfo(
   }
 
   if (task.has_executor()) {
-    // The master currently expects ExecutorInfo.framework_id to be
-    // set even though it is an optional field. Currently, the
-    // scheduler driver ensures that the field is set. For schedulers
-    // not using the driver, we need to do the validation here.
+    // Master ensures `ExecutorInfo.framework_id` is set before calling
+    // this method.
     CHECK(task.executor().has_framework_id());
 
     if (task.executor().framework_id() != framework->id()) {
@@ -585,6 +583,21 @@ Option<Error> validateExecutorInfo(
           " vs Expected: " + stringify(framework->id()) + ")");
     }
 
+
+    // TODO(vinod): Revisit these when `TaskGroup` validation is added
+    // (MESOS-6042).
+
+    if (task.executor().has_type() &&
+        task.executor().type() != ExecutorInfo::CUSTOM) {
+      return Error("'ExecutorInfo.type' must be 'CUSTOM'");
+    }
+
+    // While `ExecutorInfo.command` is optional in the protobuf,
+    // semantically it is still required for backwards compatibility.
+    if (!task.executor().has_command()) {
+      return Error("'ExecutorInfo.command' must be set");
+    }
+
     const ExecutorID& executorId = task.executor().executor_id();
     Option<ExecutorInfo> executorInfo = None();
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/c7f5d870/src/tests/master_validation_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_validation_tests.cpp b/src/tests/master_validation_tests.cpp
index 9eb82a5..ad89812 100644
--- a/src/tests/master_validation_tests.cpp
+++ b/src/tests/master_validation_tests.cpp
@@ -702,6 +702,46 @@ TEST_F(TaskValidationTest, TaskUsesCommandInfoAndExecutorInfo)
 }
 
 
+// TODO(vinod): Revisit this test after `TaskGroup` validation is implemented.
+TEST_F(TaskValidationTest, TaskUsesExecutorInfoWithoutCommandInfo)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get());
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _));
+
+  // Create an executor without command info.
+  ExecutorInfo executor;
+  executor.mutable_executor_id()->set_value("default");
+
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(LaunchTasks(executor, 1, 1, 16, "*"))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
+
+  driver.start();
+
+  AWAIT_READY(status);
+  EXPECT_EQ(TASK_ERROR, status->state());
+  EXPECT_TRUE(strings::startsWith(
+      status->message(), "'ExecutorInfo.command' must be set"));
+
+  driver.stop();
+  driver.join();
+}
+
+
 TEST_F(TaskValidationTest, TaskUsesNoResources)
 {
   Try<Owned<cluster::Master>> master = StartMaster();


[2/4] mesos git commit: Made `Offer::Operation::Type` optional with default `UNKNOWN`.

Posted by vi...@apache.org.
Made `Offer::Operation::Type` optional with default `UNKNOWN`.

This is necessary to introduce new offer operations in a backwards
compatible manner. See MESOS-4997 for context.

Review: https://reviews.apache.org/r/51060


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/d3adee2d
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/d3adee2d
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/d3adee2d

Branch: refs/heads/master
Commit: d3adee2d9500a0e1ed5124df7c79f8043ec2bfda
Parents: c7f5d87
Author: Vinod Kone <vi...@gmail.com>
Authored: Fri Aug 12 14:02:19 2016 -0700
Committer: Vinod Kone <vi...@gmail.com>
Committed: Mon Aug 15 15:25:05 2016 -0700

----------------------------------------------------------------------
 include/mesos/mesos.proto    |  3 ++-
 include/mesos/v1/mesos.proto |  3 ++-
 src/common/resources.cpp     |  4 ++--
 src/master/master.cpp        | 11 +++++++++--
 src/v1/resources.cpp         |  4 ++--
 5 files changed, 17 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/d3adee2d/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index 90518a2..0326a5c 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -1252,6 +1252,7 @@ message Offer {
   // Defines an operation that can be performed against offers.
   message Operation {
     enum Type {
+      UNKNOWN = 0;
       LAUNCH = 1;
       RESERVE = 2;
       UNRESERVE = 3;
@@ -1279,7 +1280,7 @@ message Offer {
       repeated Resource volumes = 1;
     }
 
-    required Type type = 1;
+    optional Type type = 1;
     optional Launch launch = 2;
     optional Reserve reserve = 3;
     optional Unreserve unreserve = 4;

http://git-wip-us.apache.org/repos/asf/mesos/blob/d3adee2d/include/mesos/v1/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/mesos.proto b/include/mesos/v1/mesos.proto
index 93a4bce..fa29335 100644
--- a/include/mesos/v1/mesos.proto
+++ b/include/mesos/v1/mesos.proto
@@ -1251,6 +1251,7 @@ message Offer {
   // Defines an operation that can be performed against offers.
   message Operation {
     enum Type {
+      UNKNOWN = 0;
       LAUNCH = 1;
       RESERVE = 2;
       UNRESERVE = 3;
@@ -1278,7 +1279,7 @@ message Offer {
       repeated Resource volumes = 1;
     }
 
-    required Type type = 1;
+    optional Type type = 1;
     optional Launch launch = 2;
     optional Reserve reserve = 3;
     optional Unreserve unreserve = 4;

http://git-wip-us.apache.org/repos/asf/mesos/blob/d3adee2d/src/common/resources.cpp
----------------------------------------------------------------------
diff --git a/src/common/resources.cpp b/src/common/resources.cpp
index 6b7af91..f180a0f 100644
--- a/src/common/resources.cpp
+++ b/src/common/resources.cpp
@@ -1234,8 +1234,8 @@ Try<Resources> Resources::apply(const Offer::Operation& operation) const
       break;
     }
 
-    default:
-      return Error("Unknown offer operation " + stringify(operation.type()));
+    case Offer::Operation::UNKNOWN:
+      return Error("Unknown offer operation");
   }
 
   // The following are sanity checks to ensure the amount of each type of

http://git-wip-us.apache.org/repos/asf/mesos/blob/d3adee2d/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 0bd1a34..33c2ba1 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -3426,6 +3426,12 @@ void Master::accept(
 
         break;
       }
+
+      case Offer::Operation::UNKNOWN: {
+        // TODO(vinod): Send an error event to the scheduler?
+        LOG(ERROR) << "Ignoring unknown offer operation";
+        break;
+      }
     }
   }
 
@@ -3861,9 +3867,10 @@ void Master::_accept(
         break;
       }
 
-      default:
-        LOG(ERROR) << "Unsupported offer operation " << operation.type();
+      case Offer::Operation::UNKNOWN: {
+        LOG(ERROR) << "Ignoring unknown offer operation";
         break;
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/d3adee2d/src/v1/resources.cpp
----------------------------------------------------------------------
diff --git a/src/v1/resources.cpp b/src/v1/resources.cpp
index 03ee0cb..4948b21 100644
--- a/src/v1/resources.cpp
+++ b/src/v1/resources.cpp
@@ -1237,8 +1237,8 @@ Try<Resources> Resources::apply(const Offer::Operation& operation) const
       break;
     }
 
-    default:
-      return Error("Unknown offer operation " + stringify(operation.type()));
+    case Offer::Operation::UNKNOWN:
+      return Error("Unknown offer operation");
   }
 
   // The following are sanity checks to ensure the amount of each type of


[3/4] mesos git commit: Added LAUNCH_GROUP offer operation.

Posted by vi...@apache.org.
Added LAUNCH_GROUP offer operation.

A scheduler can use the LAUNCH_GROUP offer operation to send a
`TaskGroup` to an executor.

Review: https://reviews.apache.org/r/51061


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/a43b015d
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/a43b015d
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/a43b015d

Branch: refs/heads/master
Commit: a43b015dabfb4b91378a8fe14b6a6d8d59c13fe7
Parents: d3adee2
Author: Vinod Kone <vi...@gmail.com>
Authored: Fri Aug 12 11:41:52 2016 -0700
Committer: Vinod Kone <vi...@gmail.com>
Committed: Mon Aug 15 15:25:05 2016 -0700

----------------------------------------------------------------------
 include/mesos/mesos.proto    | 36 ++++++++++++++++++++++++++++++++++--
 include/mesos/v1/mesos.proto | 36 ++++++++++++++++++++++++++++++++++--
 src/common/resources.cpp     |  4 ++++
 src/master/master.cpp        | 12 ++++++++++++
 src/v1/resources.cpp         |  4 ++++
 5 files changed, 88 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/a43b015d/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index 0326a5c..53b6547 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -518,7 +518,8 @@ message ExecutorInfo {
     //    and 32 MB memory will be used; schedulers should account for these
     //    resources when accepting offers.
     //
-    // 3) Default executor only accepts a *single* launch operation.
+    // 3) Default executor only accepts a *single* `LAUNCH` or `LAUNCH_GROUP`
+    //    offer operation.
     DEFAULT = 1;
 
     // For frameworks that need custom functionality to run tasks, a `CUSTOM`
@@ -529,7 +530,8 @@ message ExecutorInfo {
 
   // For backwards compatibility, if this field is not set when using `LAUNCH`
   // offer operation, Mesos will infer the type by checking if `command` is
-  // set (`CUSTOM`) or unset (`DEFAULT`).
+  // set (`CUSTOM`) or unset (`DEFAULT`). `type` must be set when using
+  // `LAUNCH_GROUP` offer operation.
   //
   // TODO(vinod): Add support for explicitly setting `type` to `DEFAULT `
   // in `LAUNCH` offer operation.
@@ -1254,16 +1256,31 @@ message Offer {
     enum Type {
       UNKNOWN = 0;
       LAUNCH = 1;
+      LAUNCH_GROUP = 6;
       RESERVE = 2;
       UNRESERVE = 3;
       CREATE = 4;
       DESTROY = 5;
     }
 
+    // TODO(vinod): Deprecate this in favor of `LaunchGroup` below.
     message Launch {
       repeated TaskInfo task_infos = 1;
     }
 
+    // Unlike `Launch` above, all the tasks in a `task_group` are
+    // atomically delivered to an executor.
+    //
+    // `NetworkInfo` set on executor will be shared by all tasks in
+    // the task group.
+    //
+    // TODO(vinod): Any volumes set on executor could be used by a
+    // task by explicitly setting `Volume.source` in its resources.
+    message LaunchGroup {
+      required ExecutorInfo executor = 1;
+      required TaskGroupInfo task_group = 2;
+    }
+
     message Reserve {
       repeated Resource resources = 1;
     }
@@ -1282,6 +1299,7 @@ message Offer {
 
     optional Type type = 1;
     optional Launch launch = 2;
+    optional LaunchGroup launch_group = 7;
     optional Reserve reserve = 3;
     optional Unreserve unreserve = 4;
     optional Create create = 5;
@@ -1389,6 +1407,20 @@ message TaskInfo {
 }
 
 
+/**
+ * Describes a group of tasks that belong to an executor. The
+ * executor will receive the task group in a single message to
+ * allow the group to be launched "atomically".
+ *
+ * NOTES:
+ * 1) `TaskInfo.executor` must not be set.
+ * 2) `NetworkInfo` must not be set inside task's `ContainerInfo`.
+ */
+message TaskGroupInfo {
+  repeated TaskInfo tasks = 1;
+}
+
+
 // TODO(bmahler): Add executor_uuid here, and send it to the master. This will
 // allow us to expose executor work directories for tasks in the webui when
 // looking from the master level. Currently only the slave knows which run the

http://git-wip-us.apache.org/repos/asf/mesos/blob/a43b015d/include/mesos/v1/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/mesos.proto b/include/mesos/v1/mesos.proto
index fa29335..f6b59e1 100644
--- a/include/mesos/v1/mesos.proto
+++ b/include/mesos/v1/mesos.proto
@@ -518,7 +518,8 @@ message ExecutorInfo {
     //    and 32 MB memory will be used; schedulers should account for these
     //    resources when accepting offers.
     //
-    // 3) Default executor only accepts a *single* launch operation.
+    // 3) Default executor only accepts a *single* `LAUNCH` or `LAUNCH_GROUP`
+    //    offer operation.
     DEFAULT = 1;
 
     // For frameworks that need custom functionality to run tasks, a `CUSTOM`
@@ -529,7 +530,8 @@ message ExecutorInfo {
 
   // For backwards compatibility, if this field is not set when using `LAUNCH`
   // offer operation, Mesos will infer the type by checking if `command` is
-  // set (`CUSTOM`) or unset (`DEFAULT`).
+  // set (`CUSTOM`) or unset (`DEFAULT`). `type` must be set when using
+  // `LAUNCH_GROUP` offer operation.
   //
   // TODO(vinod): Add support for explicitly setting `type` to `DEFAULT `
   // in `LAUNCH` offer operation.
@@ -1253,16 +1255,31 @@ message Offer {
     enum Type {
       UNKNOWN = 0;
       LAUNCH = 1;
+      LAUNCH_GROUP = 6;
       RESERVE = 2;
       UNRESERVE = 3;
       CREATE = 4;
       DESTROY = 5;
     }
 
+    // TODO(vinod): Deprecate this in favor of `LaunchGroup` below.
     message Launch {
       repeated TaskInfo task_infos = 1;
     }
 
+    // Unlike `Launch` above, all the tasks in a `task_group` are
+    // atomically delivered to an executor.
+    //
+    // `NetworkInfo` set on executor will be shared by all tasks in
+    // the task group.
+    //
+    // TODO(vinod): Any volumes set on executor could be used by a
+    // task by explicitly setting `Volume.source` in its resources.
+    message LaunchGroup {
+      required ExecutorInfo executor = 1;
+      required TaskGroupInfo task_group = 2;
+    }
+
     message Reserve {
       repeated Resource resources = 1;
     }
@@ -1281,6 +1298,7 @@ message Offer {
 
     optional Type type = 1;
     optional Launch launch = 2;
+    optional LaunchGroup launch_group = 7;
     optional Reserve reserve = 3;
     optional Unreserve unreserve = 4;
     optional Create create = 5;
@@ -1388,6 +1406,20 @@ message TaskInfo {
 }
 
 
+/**
+ * Describes a group of tasks that belong to an executor. The
+ * executor will receive the task group in a single message to
+ * allow the group to be launched "atomically".
+ *
+ * NOTES:
+ * 1) `TaskInfo.executor` must not be set.
+ * 2) `NetworkInfo` must not be set inside task's `ContainerInfo`.
+ */
+message TaskGroupInfo {
+  repeated TaskInfo tasks = 1;
+}
+
+
 // TODO(bmahler): Add executor_uuid here, and send it to the master. This will
 // allow us to expose executor work directories for tasks in the webui when
 // looking from the master level. Currently only the agent knows which run the

http://git-wip-us.apache.org/repos/asf/mesos/blob/a43b015d/src/common/resources.cpp
----------------------------------------------------------------------
diff --git a/src/common/resources.cpp b/src/common/resources.cpp
index f180a0f..96b4c39 100644
--- a/src/common/resources.cpp
+++ b/src/common/resources.cpp
@@ -1109,6 +1109,10 @@ Try<Resources> Resources::apply(const Offer::Operation& operation) const
       // Launch operation does not alter the offered resources.
       break;
 
+    case Offer::Operation::LAUNCH_GROUP:
+      // LaunchGroup operation does not alter the offered resources.
+      break;
+
     case Offer::Operation::RESERVE: {
       Option<Error> error = validate(operation.reserve().resources());
       if (error.isSome()) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/a43b015d/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 33c2ba1..d94a851 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -3369,6 +3369,12 @@ void Master::accept(
         break;
       }
 
+      case Offer::Operation::LAUNCH_GROUP : {
+        // TODO(vinod): Implement this.
+        LOG(WARNING) << "Ignoring unimplemented LAUNCH_GROUP operation";
+        break;
+      }
+
       // NOTE: When handling RESERVE and UNRESERVE operations, authorization
       // will proceed even if no principal is specified, although currently
       // resources cannot be reserved or unreserved unless a principal is
@@ -3867,6 +3873,12 @@ void Master::_accept(
         break;
       }
 
+      case Offer::Operation::LAUNCH_GROUP : {
+        // TODO(vinod): Implement this.
+        LOG(WARNING) << "Ignoring unimplemented LAUNCH_GROUP operation";
+        break;
+      }
+
       case Offer::Operation::UNKNOWN: {
         LOG(ERROR) << "Ignoring unknown offer operation";
         break;

http://git-wip-us.apache.org/repos/asf/mesos/blob/a43b015d/src/v1/resources.cpp
----------------------------------------------------------------------
diff --git a/src/v1/resources.cpp b/src/v1/resources.cpp
index 4948b21..3cc7580 100644
--- a/src/v1/resources.cpp
+++ b/src/v1/resources.cpp
@@ -1112,6 +1112,10 @@ Try<Resources> Resources::apply(const Offer::Operation& operation) const
       // Launch operation does not alter the offered resources.
       break;
 
+    case Offer::Operation::LAUNCH_GROUP:
+      // LaunchGroup operation does not alter the offered resources.
+      break;
+
     case Offer::Operation::RESERVE: {
       Option<Error> error = validate(operation.reserve().resources());
       if (error.isSome()) {