You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2017/12/02 05:34:27 UTC

[1/6] mesos git commit: Changed the semantics of `JSON::protobuf` for deprecated fields [14/20].

Repository: mesos
Updated Branches:
  refs/heads/1.3.x 022e52405 -> 721eeb222


Changed the semantics of `JSON::protobuf` for deprecated fields [14/20].

Updated `JSON::protobuf` to not emit a __deprecated__ optional field
with a default value if it's not explicitly set. The specific issue
we're solving here is that the round-trip of Protobuf to JSON and
back does not work with the current behavior. For example,
the `Resource` object in the "post-reservation-refinement" format does
not have the `Resource.role` field. During the Protobuf -> JSON
conversion, the `"role"` field is set to `"*"` since it is an optional
field with a default value. When such a JSON object is parsed back in
as a Protobuf message, the `Resource` object is in an invalid state.

In order to facilitate this at least in the short term, this patch
changes the generic Protobuf -> JSON logic to not output unset fields
if they are marked deprecated.

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


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

Branch: refs/heads/1.3.x
Commit: 3d39124e554de5099881e4faba1727c90288efda
Parents: 022e524
Author: Michael Park <mp...@apache.org>
Authored: Tue Jun 20 01:06:31 2017 -0700
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Fri Dec 1 20:03:57 2017 -0800

----------------------------------------------------------------------
 3rdparty/stout/include/stout/protobuf.hpp | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/3d39124e/3rdparty/stout/include/stout/protobuf.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/protobuf.hpp b/3rdparty/stout/include/stout/protobuf.hpp
index 2735354..15690b6 100644
--- a/3rdparty/stout/include/stout/protobuf.hpp
+++ b/3rdparty/stout/include/stout/protobuf.hpp
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/repeated_field.h>
 
@@ -698,8 +699,8 @@ struct Protobuf : Representation<google::protobuf::Message>
 
 
 // `json` function for protobuf messages. Refer to `jsonify.hpp` for details.
-// TODO(mpark): This currently uses the default value for optional fields with
-// a default that are not set, but we may want to revisit this decision.
+// TODO(mpark): This currently uses the default value for optional fields
+// that are not deprecated, but we may want to revisit this decision.
 inline void json(ObjectWriter* writer, const Protobuf& protobuf)
 {
   using google::protobuf::FieldDescriptor;
@@ -723,8 +724,9 @@ inline void json(ObjectWriter* writer, const Protobuf& protobuf)
         // Has repeated field with members, output as JSON.
         fields.push_back(field);
       }
-    } else if (reflection->HasField(message, field) ||
-               field->has_default_value()) {
+    } else if (
+        reflection->HasField(message, field) ||
+        (field->has_default_value() && !field->options().deprecated())) {
       // Field is set or has default, output as JSON.
       fields.push_back(field);
     }
@@ -832,8 +834,8 @@ inline void json(ObjectWriter* writer, const Protobuf& protobuf)
 }
 
 
-// TODO(bmahler): This currently uses the default value for optional
-// fields but we may want to revisit this decision.
+// TODO(bmahler): This currently uses the default value for optional fields
+// that are not deprecated, but we may want to revisit this decision.
 inline Object protobuf(const google::protobuf::Message& message)
 {
   Object object;
@@ -854,8 +856,9 @@ inline Object protobuf(const google::protobuf::Message& message)
         // Has repeated field with members, output as JSON.
         fields.push_back(field);
       }
-    } else if (reflection->HasField(message, field) ||
-               field->has_default_value()) {
+    } else if (
+        reflection->HasField(message, field) ||
+        (field->has_default_value() && !field->options().deprecated())) {
       // Field is set or has default, output as JSON.
       fields.push_back(field);
     }
@@ -978,7 +981,7 @@ inline Object protobuf(const google::protobuf::Message& message)
           break;
         case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
           object.values[field->name()] =
-              protobuf(reflection->GetMessage(message, field));
+            protobuf(reflection->GetMessage(message, field));
           break;
         case google::protobuf::FieldDescriptor::TYPE_ENUM:
           object.values[field->name()] =


[6/6] mesos git commit: Added MESOS-8237 to the 1.3.2 CHANGELOG.

Posted by bm...@apache.org.
Added MESOS-8237 to the 1.3.2 CHANGELOG.


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

Branch: refs/heads/1.3.x
Commit: 721eeb222edfd8456959b54c98895bfa7d60b7d2
Parents: 5a87d51
Author: Benjamin Mahler <bm...@apache.org>
Authored: Fri Dec 1 20:17:47 2017 -0800
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Fri Dec 1 20:18:16 2017 -0800

----------------------------------------------------------------------
 CHANGELOG | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/721eeb22/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index 5dc8acd..af64a23 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -20,6 +20,7 @@ All Issues:
   * [MESOS-8051] - Killing TASK_GROUP fail to kill some tasks.
   * [MESOS-8080] - The default executor does not propagate missing task exit status correctly.
   * [MESOS-8135] - Masters can lose track of tasks' executor IDs.
+  * [MESOS-8237] - Strip (Offer|Resource).allocation_info for non-MULTI_ROLE schedulers.
 
 
 


[2/6] mesos git commit: Stripped AllocationInfo from offers to non-MULTI_ROLE schedulers.

Posted by bm...@apache.org.
Stripped AllocationInfo from offers to non-MULTI_ROLE schedulers.

Per MESOS-8237, it is problematic to show `Resource.allocation_info`
for "old" schedulers. The example that was presented was the
"mesos-go" 3rd party library that provides resource comparison logic.
The library has both MULTI-ROLE and non-MULTI_ROLE schedulers as
clients, these clients use the comparison logic supplied by the
library to see if the offer contains the resources they need.
The library author does not want to have to do any stripping of the
allocation info to preserve the equality.

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


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

Branch: refs/heads/1.3.x
Commit: 8855f0e42a0cf54e5f535092f1ebda10d323ae05
Parents: 55b498c
Author: Benjamin Mahler <bm...@apache.org>
Authored: Wed Nov 29 17:37:36 2017 -0800
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Fri Dec 1 20:18:15 2017 -0800

----------------------------------------------------------------------
 src/master/master.cpp | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/8855f0e4/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 141d512..3975f8b 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -7294,6 +7294,23 @@ void Master::offer(
         }
       }
 
+      // Per MESOS-8237, it is problematic to show the
+      // `Resource.allocation_info` for pre-MULTI_ROLE schedulers.
+      // Pre-MULTI_ROLE schedulers are not `AllocationInfo` aware,
+      // and since they may be performing operations that
+      // implicitly uses all of Resource's state (e.g. equality
+      // comparison), we strip the `AllocationInfo` from `Resource`,
+      // as well as Offer. The idea here is that since the
+      // information doesn't provide any value to a pre-MULTI_ROLE
+      // scheduler, we preserve the old `Offer` format for them.
+      if (!framework->capabilities.multiRole) {
+        offer_.clear_allocation_info();
+
+        foreach (Resource& resource, *offer_.mutable_resources()) {
+          resource.clear_allocation_info();
+        }
+      }
+
       // Add the offer *AND* the corresponding slave's PID.
       message.add_offers()->MergeFrom(offer_);
       message.add_pids(slave->pid);


[4/6] mesos git commit: Updated the tests to use MULTI_ROLE frameworks by default.

Posted by bm...@apache.org.
http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/reservation_endpoints_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/reservation_endpoints_tests.cpp b/src/tests/reservation_endpoints_tests.cpp
index cc8499a..99dbd42 100644
--- a/src/tests/reservation_endpoints_tests.cpp
+++ b/src/tests/reservation_endpoints_tests.cpp
@@ -80,7 +80,7 @@ public:
   {
     master::Flags flags = MesosTest::CreateMasterFlags();
     flags.allocation_interval = Milliseconds(50);
-    flags.roles = createFrameworkInfo().role();
+    flags.roles = createFrameworkInfo().roles(0);
     return flags;
   }
 
@@ -88,7 +88,7 @@ public:
   FrameworkInfo createFrameworkInfo()
   {
     FrameworkInfo info = DEFAULT_FRAMEWORK_INFO;
-    info.set_role("role");
+    info.set_roles(0, "role");
     return info;
   }
 
@@ -126,7 +126,7 @@ TEST_F(ReservationEndpointsTest, AvailableResources)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -156,7 +156,7 @@ TEST_F(ReservationEndpointsTest, AvailableResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   Future<Nothing> recoverResources;
   EXPECT_CALL(allocator, recoverResources(_, _, _, _))
@@ -189,7 +189,7 @@ TEST_F(ReservationEndpointsTest, AvailableResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // Ignore subsequent `recoverResources` calls triggered from recovering the
   // resources that this framework is currently holding onto.
@@ -225,7 +225,7 @@ TEST_F(ReservationEndpointsTest, ReserveOfferedResources)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   MockScheduler sched;
@@ -247,7 +247,7 @@ TEST_F(ReservationEndpointsTest, ReserveOfferedResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, resourceOffers(&driver, _))
     .WillOnce(FutureArg<1>(&offers));
@@ -269,7 +269,7 @@ TEST_F(ReservationEndpointsTest, ReserveOfferedResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -299,8 +299,9 @@ TEST_F(ReservationEndpointsTest, UnreserveOfferedResources)
   FrameworkInfo frameworkInfo = createFrameworkInfo();
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
+
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -330,7 +331,7 @@ TEST_F(ReservationEndpointsTest, UnreserveOfferedResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, resourceOffers(&driver, _))
     .WillOnce(FutureArg<1>(&offers));
@@ -352,7 +353,7 @@ TEST_F(ReservationEndpointsTest, UnreserveOfferedResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -390,7 +391,7 @@ TEST_F(ReservationEndpointsTest, ReserveAvailableAndOfferedResources)
 
   Resources total = available + offered;
   Resources dynamicallyReserved = total.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   MockScheduler sched;
@@ -420,7 +421,7 @@ TEST_F(ReservationEndpointsTest, ReserveAvailableAndOfferedResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(available + offered, frameworkInfo.role())));
+      allocatedResources(available + offered, frameworkInfo.roles(0))));
 
   // Launch a task on the 'available' resources portion of the offer, which
   // recovers 'offered' resources portion.
@@ -455,7 +456,7 @@ TEST_F(ReservationEndpointsTest, ReserveAvailableAndOfferedResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(offered, frameworkInfo.role())));
+      allocatedResources(offered, frameworkInfo.roles(0))));
 
   // Kill the task running on 'available' resources to make it available.
   EXPECT_CALL(sched, statusUpdate(_, _));
@@ -471,7 +472,7 @@ TEST_F(ReservationEndpointsTest, ReserveAvailableAndOfferedResources)
 
   AWAIT_READY(availableResources);
   EXPECT_TRUE(availableResources->contains(
-      allocatedResources(available, frameworkInfo.role())));
+      allocatedResources(available, frameworkInfo.roles(0))));
 
   // At this point, we have 'available' resources in the allocator, and
   // 'offered' resources offered to the framework.
@@ -501,7 +502,7 @@ TEST_F(ReservationEndpointsTest, ReserveAvailableAndOfferedResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // Ignore subsequent `recoverResources` calls triggered from recovering the
   // resources that this framework is currently holding onto.
@@ -541,12 +542,12 @@ TEST_F(ReservationEndpointsTest, UnreserveAvailableAndOfferedResources)
 
   Resources available = Resources::parse("cpus:1;mem:128").get();
   available = available.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Resources offered = Resources::parse("mem:384").get();
   offered = offered.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Resources total = available + offered;
@@ -587,7 +588,7 @@ TEST_F(ReservationEndpointsTest, UnreserveAvailableAndOfferedResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(available + offered, frameworkInfo.role())));
+      allocatedResources(available + offered, frameworkInfo.roles(0))));
 
   // Launch a task on the 'available' resources portion of the offer, which
   // recovers 'offered' resources portion.
@@ -622,7 +623,7 @@ TEST_F(ReservationEndpointsTest, UnreserveAvailableAndOfferedResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(offered, frameworkInfo.role())));
+      allocatedResources(offered, frameworkInfo.roles(0))));
 
   // Kill the task running on 'available' resources to make it available.
   EXPECT_CALL(sched, statusUpdate(_, _));
@@ -638,7 +639,7 @@ TEST_F(ReservationEndpointsTest, UnreserveAvailableAndOfferedResources)
 
   AWAIT_READY(availableResources);
   EXPECT_TRUE(availableResources->contains(
-      allocatedResources(available, frameworkInfo.role())));
+      allocatedResources(available, frameworkInfo.roles(0))));
 
   // At this point, we have 'available' resources in the allocator, and
   // 'offered' resources offered to the framework.
@@ -668,7 +669,7 @@ TEST_F(ReservationEndpointsTest, UnreserveAvailableAndOfferedResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // Ignore subsequent `recoverResources` calls triggered from recovering the
   // resources that this framework is currently holding onto.
@@ -715,10 +716,10 @@ TEST_F(ReservationEndpointsTest, LabeledResources)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources labeledResources1 = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal(), labels1)).get();
   Resources labeledResources2 = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal(), labels2)).get();
 
   // Make two resource reservations with different labels.
@@ -758,9 +759,9 @@ TEST_F(ReservationEndpointsTest, LabeledResources)
 
   Resources offeredResources = Resources(offer.resources());
   EXPECT_TRUE(offeredResources.contains(
-      allocatedResources(labeledResources1, frameworkInfo.role())));
+      allocatedResources(labeledResources1, frameworkInfo.roles(0))));
   EXPECT_TRUE(offeredResources.contains(
-      allocatedResources(labeledResources2, frameworkInfo.role())));
+      allocatedResources(labeledResources2, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, resourceOffers(&driver, _))
     .WillOnce(FutureArg<1>(&offers));
@@ -784,13 +785,13 @@ TEST_F(ReservationEndpointsTest, LabeledResources)
 
   offeredResources = Resources(offer.resources());
   EXPECT_FALSE(offeredResources.contains(
-      allocatedResources(totalSlaveResources, frameworkInfo.role())));
+      allocatedResources(totalSlaveResources, frameworkInfo.roles(0))));
   EXPECT_TRUE(offeredResources.contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
   EXPECT_FALSE(offeredResources.contains(
-      allocatedResources(labeledResources1, frameworkInfo.role())));
+      allocatedResources(labeledResources1, frameworkInfo.roles(0))));
   EXPECT_TRUE(offeredResources.contains(
-      allocatedResources(labeledResources2, frameworkInfo.role())));
+      allocatedResources(labeledResources2, frameworkInfo.roles(0))));
 
   // Now that the first labeled reservation has been unreserved,
   // attempting to unreserve it again should fail.
@@ -825,11 +826,11 @@ TEST_F(ReservationEndpointsTest, LabeledResources)
   offeredResources = Resources(offer.resources());
 
   EXPECT_TRUE(offeredResources.contains(
-      allocatedResources(totalSlaveResources, frameworkInfo.role())));
+      allocatedResources(totalSlaveResources, frameworkInfo.roles(0))));
   EXPECT_FALSE(offeredResources.contains(
-      allocatedResources(labeledResources1, frameworkInfo.role())));
+      allocatedResources(labeledResources1, frameworkInfo.roles(0))));
   EXPECT_FALSE(offeredResources.contains(
-      allocatedResources(labeledResources2, frameworkInfo.role())));
+      allocatedResources(labeledResources2, frameworkInfo.roles(0))));
 
   // Ignore subsequent `recoverResources` calls triggered from recovering the
   // resources that this framework is currently holding onto.
@@ -924,7 +925,7 @@ TEST_F(ReservationEndpointsTest, InsufficientResources)
 
   Resources unreserved = Resources::parse("cpus:4;mem:4096").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   process::http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
@@ -965,7 +966,7 @@ TEST_F(ReservationEndpointsTest, NoHeader)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -1057,13 +1058,13 @@ TEST_F(ReservationEndpointsTest, GoodReserveAndUnreserveACL)
       DEFAULT_CREDENTIAL.principal());
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
   masterFlags.allocation_interval = Milliseconds(50);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   EXPECT_CALL(allocator, initialize(_, _, _, _));
 
@@ -1087,7 +1088,7 @@ TEST_F(ReservationEndpointsTest, GoodReserveAndUnreserveACL)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   // Reserve the resources.
@@ -1180,13 +1181,13 @@ TEST_F(ReservationEndpointsTest, BadReserveACL)
   reserve->mutable_roles()->set_type(mesos::ACL::Entity::NONE);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
   masterFlags.allocation_interval = Milliseconds(50);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   EXPECT_CALL(allocator, initialize(_, _, _, _));
 
@@ -1210,7 +1211,7 @@ TEST_F(ReservationEndpointsTest, BadReserveACL)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   // Attempt to reserve the resources.
@@ -1239,13 +1240,13 @@ TEST_F(ReservationEndpointsTest, BadUnreserveACL)
   unreserve->mutable_reserver_principals()->set_type(mesos::ACL::Entity::NONE);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
   masterFlags.allocation_interval = Milliseconds(50);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   EXPECT_CALL(allocator, initialize(_, _, _, _));
 
@@ -1269,7 +1270,7 @@ TEST_F(ReservationEndpointsTest, BadUnreserveACL)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   // Reserve the resources.
@@ -1470,7 +1471,7 @@ TEST_F(ReservationEndpointsTest, ReserveAndUnreserveNoAuthentication)
   TestAllocator<> allocator;
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
@@ -1503,7 +1504,7 @@ TEST_F(ReservationEndpointsTest, ReserveAndUnreserveNoAuthentication)
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
 
   Resources dynamicallyReservedWithNoPrincipal = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo()).get();
 
   // Try a reservation with no principal in `ReservationInfo` and no
@@ -1527,7 +1528,7 @@ TEST_F(ReservationEndpointsTest, ReserveAndUnreserveNoAuthentication)
   AWAIT_EXPECT_RESPONSE_STATUS_EQ(Accepted().status, response);
 
   Resources dynamicallyReservedWithPrincipal = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   // Try a reservation with a principal in `ReservationInfo` and no
@@ -1579,12 +1580,13 @@ TEST_F(ReservationEndpointsTest, DifferentPrincipalsSameRole)
   FrameworkInfo frameworkInfo = createFrameworkInfo();
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
+
   Resources dynamicallyReserved1 = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Resources dynamicallyReserved2 = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL_2.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -1623,9 +1625,9 @@ TEST_F(ReservationEndpointsTest, DifferentPrincipalsSameRole)
   Resources resources = Resources(offer.resources());
 
   EXPECT_TRUE(resources.contains(
-      allocatedResources(dynamicallyReserved1, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved1, frameworkInfo.roles(0))));
   EXPECT_TRUE(resources.contains(
-      allocatedResources(dynamicallyReserved2, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved2, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/reservation_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/reservation_tests.cpp b/src/tests/reservation_tests.cpp
index 4504831..77e5dac 100644
--- a/src/tests/reservation_tests.cpp
+++ b/src/tests/reservation_tests.cpp
@@ -89,11 +89,11 @@ class ReservationTest : public MesosTest {};
 TEST_F(ReservationTest, ReserveThenUnreserve)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -116,7 +116,7 @@ TEST_F(ReservationTest, ReserveThenUnreserve)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -137,7 +137,7 @@ TEST_F(ReservationTest, ReserveThenUnreserve)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -153,7 +153,7 @@ TEST_F(ReservationTest, ReserveThenUnreserve)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -169,7 +169,7 @@ TEST_F(ReservationTest, ReserveThenUnreserve)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -186,7 +186,7 @@ TEST_F(ReservationTest, ReserveThenUnreserve)
 TEST_F(ReservationTest, ReserveTwiceWithDoubleValue)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
@@ -213,7 +213,7 @@ TEST_F(ReservationTest, ReserveTwiceWithDoubleValue)
   Resources unreserved = Resources::parse("cpus:0.1;mem:512").get();
   Resources dynamicallyReserved =
     unreserved.flatten(
-        frameworkInfo.role(),
+        frameworkInfo.roles(0),
         createReservationInfo(frameworkInfo.principal())).get();
 
   Future<vector<Offer>> offers;
@@ -231,7 +231,7 @@ TEST_F(ReservationTest, ReserveTwiceWithDoubleValue)
 
   // In the first offer, expect an offer with unreserved resources.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -247,7 +247,7 @@ TEST_F(ReservationTest, ReserveTwiceWithDoubleValue)
 
   // In the second offer, expect an offer with reserved resources.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -268,11 +268,11 @@ TEST_F(ReservationTest, ReserveTwiceWithDoubleValue)
   Resources reserved = Resources::parse("cpus:0.2;mem:512").get();
   Resources finalReservation =
     reserved.flatten(
-        frameworkInfo.role(),
+        frameworkInfo.roles(0),
         createReservationInfo(frameworkInfo.principal())).get();
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(finalReservation, frameworkInfo.role())));
+      allocatedResources(finalReservation, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -290,11 +290,11 @@ TEST_F(ReservationTest, ReserveTwiceWithDoubleValue)
 TEST_F(ReservationTest, ReserveAndLaunchThenUnreserve)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -317,7 +317,7 @@ TEST_F(ReservationTest, ReserveAndLaunchThenUnreserve)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -338,7 +338,7 @@ TEST_F(ReservationTest, ReserveAndLaunchThenUnreserve)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // Create a task.
   TaskInfo taskInfo =
@@ -369,7 +369,7 @@ TEST_F(ReservationTest, ReserveAndLaunchThenUnreserve)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -390,7 +390,7 @@ TEST_F(ReservationTest, ReserveAndLaunchThenUnreserve)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   EXPECT_CALL(exec, shutdown(_))
     .Times(AtMost(1));
@@ -412,11 +412,11 @@ TEST_F(ReservationTest, ReserveShareWithinRole)
 
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo1.set_name("framework1");
-  frameworkInfo1.set_role(role);
+  frameworkInfo1.set_roles(0, role);
 
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo1.set_name("framework2");
-  frameworkInfo2.set_role(role);
+  frameworkInfo2.set_roles(0, role);
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
@@ -462,7 +462,7 @@ TEST_F(ReservationTest, ReserveShareWithinRole)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo1.role())));
+      allocatedResources(unreserved, frameworkInfo1.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched1, resourceOffers(&driver1, _))
@@ -483,7 +483,7 @@ TEST_F(ReservationTest, ReserveShareWithinRole)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo1.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo1.roles(0))));
 
   // The filter to decline the offer "forever".
   Filters filtersForever;
@@ -509,7 +509,7 @@ TEST_F(ReservationTest, ReserveShareWithinRole)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo1.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo1.roles(0))));
 
   driver1.stop();
   driver1.join();
@@ -527,11 +527,11 @@ TEST_F(ReservationTest, DropReserveTooLarge)
   TestAllocator<> allocator;
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   EXPECT_CALL(allocator, initialize(_, _, _, _));
 
@@ -554,7 +554,7 @@ TEST_F(ReservationTest, DropReserveTooLarge)
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources unreservedTooLarge = Resources::parse("cpus:1;mem:1024").get();
   Resources dynamicallyReservedTooLarge = unreservedTooLarge.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture the offers from 'resourceOffers'.
@@ -577,7 +577,7 @@ TEST_F(ReservationTest, DropReserveTooLarge)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -606,7 +606,7 @@ TEST_F(ReservationTest, DropReserveTooLarge)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -620,11 +620,11 @@ TEST_F(ReservationTest, DropReserveStaticReservation)
   TestAllocator<> allocator;
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   EXPECT_CALL(allocator, initialize(_, _, _, _));
 
@@ -647,7 +647,7 @@ TEST_F(ReservationTest, DropReserveStaticReservation)
   Resources staticallyReserved =
     Resources::parse("cpus(role):1;mem(role):512").get();
   Resources dynamicallyReserved = staticallyReserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -671,7 +671,7 @@ TEST_F(ReservationTest, DropReserveStaticReservation)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(staticallyReserved, frameworkInfo.role())));
+      allocatedResources(staticallyReserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -697,7 +697,7 @@ TEST_F(ReservationTest, DropReserveStaticReservation)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(staticallyReserved, frameworkInfo.role())));
+      allocatedResources(staticallyReserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -711,11 +711,11 @@ TEST_F(ReservationTest, DropReserveStaticReservation)
 TEST_F(ReservationTest, SendingCheckpointResourcesMessage)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -733,12 +733,12 @@ TEST_F(ReservationTest, SendingCheckpointResourcesMessage)
 
   Resources unreserved1 = Resources::parse("cpus:8").get();
   Resources reserved1 = unreserved1.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   Resources unreserved2 = Resources::parse("mem:2048").get();
   Resources reserved2 = unreserved2.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -761,7 +761,7 @@ TEST_F(ReservationTest, SendingCheckpointResourcesMessage)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved1 + unreserved2, frameworkInfo.role())));
+      allocatedResources(unreserved1 + unreserved2, frameworkInfo.roles(0))));
 
   Future<CheckpointResourcesMessage> message3 =
     FUTURE_PROTOBUF(CheckpointResourcesMessage(), _, _);
@@ -813,11 +813,11 @@ TEST_F(ReservationTest, SendingCheckpointResourcesMessage)
 TEST_F(ReservationTest, ResourcesCheckpointing)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -836,7 +836,7 @@ TEST_F(ReservationTest, ResourcesCheckpointing)
 
   Resources unreserved = Resources::parse("cpus:8;mem:2048").get();
   Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -858,7 +858,7 @@ TEST_F(ReservationTest, ResourcesCheckpointing)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   Future<CheckpointResourcesMessage> checkpointResources =
     FUTURE_PROTOBUF(CheckpointResourcesMessage(), _, slave.get()->pid);
@@ -905,11 +905,11 @@ TEST_F(ReservationTest, ResourcesCheckpointing)
 TEST_F(ReservationTest, MasterFailover)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master1 = StartMaster(masterFlags);
   ASSERT_SOME(master1);
@@ -927,7 +927,7 @@ TEST_F(ReservationTest, MasterFailover)
 
   Resources unreserved = Resources::parse("cpus:8;mem:2048").get();
   Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -1005,7 +1005,7 @@ TEST_F(ReservationTest, MasterFailover)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(reserved, frameworkInfo.role())));
+      allocatedResources(reserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1027,11 +1027,11 @@ TEST_F(ReservationTest, MasterFailover)
 TEST_F(ReservationTest, CompatibleCheckpointedResources)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1053,7 +1053,7 @@ TEST_F(ReservationTest, CompatibleCheckpointedResources)
 
   Resources unreserved = Resources::parse("cpus:8;mem:2048").get();
   Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -1075,7 +1075,7 @@ TEST_F(ReservationTest, CompatibleCheckpointedResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   Future<CheckpointResourcesMessage> checkpointResources =
     FUTURE_PROTOBUF(CheckpointResourcesMessage(), _, _);
@@ -1135,11 +1135,11 @@ TEST_F(ReservationTest, CompatibleCheckpointedResources)
 TEST_F(ReservationTest, CompatibleCheckpointedResourcesWithPersistentVolumes)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1161,12 +1161,12 @@ TEST_F(ReservationTest, CompatibleCheckpointedResourcesWithPersistentVolumes)
 
   Resources unreserved = Resources::parse("cpus:8;mem:2048").get();
   Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   Resource unreservedDisk = Resources::parse("disk", "1024", "*").get();
   Resource reservedDisk = unreservedDisk;
-  reservedDisk.set_role(frameworkInfo.role());
+  reservedDisk.set_role(frameworkInfo.roles(0));
   reservedDisk.mutable_reservation()->CopyFrom(
       createReservationInfo(frameworkInfo.principal()));
 
@@ -1195,7 +1195,7 @@ TEST_F(ReservationTest, CompatibleCheckpointedResourcesWithPersistentVolumes)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved + unreservedDisk, frameworkInfo.role())));
+      allocatedResources(unreserved + unreservedDisk, frameworkInfo.roles(0))));
 
   Future<CheckpointResourcesMessage> message2 =
     FUTURE_PROTOBUF(CheckpointResourcesMessage(), _, _);
@@ -1233,7 +1233,7 @@ TEST_F(ReservationTest, CompatibleCheckpointedResourcesWithPersistentVolumes)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(reserved + volume, frameworkInfo.role())));
+      allocatedResources(reserved + volume, frameworkInfo.roles(0))));
 
   Future<OfferID> rescindedOfferId;
 
@@ -1286,11 +1286,11 @@ TEST_F(ReservationTest, CompatibleCheckpointedResourcesWithPersistentVolumes)
 TEST_F(ReservationTest, IncompatibleCheckpointedResources)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1312,7 +1312,7 @@ TEST_F(ReservationTest, IncompatibleCheckpointedResources)
 
   Resources unreserved = Resources::parse("cpus:8;mem:2048").get();
   Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -1333,7 +1333,7 @@ TEST_F(ReservationTest, IncompatibleCheckpointedResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   Future<CheckpointResourcesMessage> checkpointResources =
     FUTURE_PROTOBUF(CheckpointResourcesMessage(), _, _);
@@ -1405,13 +1405,13 @@ TEST_F(ReservationTest, GoodACLReserveThenUnreserve)
       DEFAULT_CREDENTIAL.principal());
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1436,7 +1436,7 @@ TEST_F(ReservationTest, GoodACLReserveThenUnreserve)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -1457,7 +1457,7 @@ TEST_F(ReservationTest, GoodACLReserveThenUnreserve)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1473,7 +1473,7 @@ TEST_F(ReservationTest, GoodACLReserveThenUnreserve)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1489,7 +1489,7 @@ TEST_F(ReservationTest, GoodACLReserveThenUnreserve)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1508,13 +1508,13 @@ TEST_F(ReservationTest, BadACLDropReserve)
   reserve->mutable_roles()->set_type(mesos::ACL::Entity::ANY);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1539,7 +1539,7 @@ TEST_F(ReservationTest, BadACLDropReserve)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -1560,7 +1560,7 @@ TEST_F(ReservationTest, BadACLDropReserve)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1577,7 +1577,7 @@ TEST_F(ReservationTest, BadACLDropReserve)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1601,13 +1601,13 @@ TEST_F(ReservationTest, BadACLDropUnreserve)
   unreserve->mutable_reserver_principals()->set_type(mesos::ACL::Entity::NONE);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1633,12 +1633,12 @@ TEST_F(ReservationTest, BadACLDropUnreserve)
   // Define the resources to be reserved.
   Resources unreserved1 = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved1 = unreserved1.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   Resources unreserved2 = Resources::parse("cpus:0.5;mem:256").get();
   Resources dynamicallyReserved2 = unreserved2.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -1660,7 +1660,7 @@ TEST_F(ReservationTest, BadACLDropUnreserve)
 
   // The slave's total resources are twice those defined by `unreserved1`.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved1 + unreserved1, frameworkInfo.role())));
+      allocatedResources(unreserved1 + unreserved1, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1680,7 +1680,7 @@ TEST_F(ReservationTest, BadACLDropUnreserve)
   EXPECT_TRUE(Resources(offer.resources()).contains(
       allocatedResources(
           dynamicallyReserved1 + unreserved1,
-          frameworkInfo.role())));
+          frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1702,7 +1702,7 @@ TEST_F(ReservationTest, BadACLDropUnreserve)
   EXPECT_TRUE(Resources(offer.resources()).contains(
       allocatedResources(
           dynamicallyReserved1 + dynamicallyReserved2 + unreserved2,
-          frameworkInfo.role())));
+          frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1730,13 +1730,13 @@ TEST_F(ReservationTest, ACLMultipleOperations)
   unreserve->mutable_reserver_principals()->set_type(mesos::ACL::Entity::NONE);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
   masterFlags.allocation_interval = Milliseconds(5);
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1767,12 +1767,12 @@ TEST_F(ReservationTest, ACLMultipleOperations)
   // Define the resources to be reserved.
   Resources unreserved1 = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved1 = unreserved1.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   Resources unreserved2 = Resources::parse("cpus:0.5;mem:256").get();
   Resources dynamicallyReserved2 = unreserved2.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from 'resourceOffers'.
@@ -1800,7 +1800,7 @@ TEST_F(ReservationTest, ACLMultipleOperations)
 
   // The slave's total resources are twice those defined by `unreserved1`.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved1 + unreserved1, frameworkInfo.role())));
+      allocatedResources(unreserved1 + unreserved1, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1823,7 +1823,7 @@ TEST_F(ReservationTest, ACLMultipleOperations)
   EXPECT_TRUE(Resources(offer.resources()).contains(
       allocatedResources(
           dynamicallyReserved1 + unreserved1,
-          frameworkInfo.role())));
+          frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1868,7 +1868,7 @@ TEST_F(ReservationTest, ACLMultipleOperations)
   EXPECT_TRUE(Resources(offer.resources()).contains(
       allocatedResources(
           dynamicallyReserved1 + dynamicallyReserved2 + unreserved2,
-          frameworkInfo.role())));
+          frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1905,7 +1905,7 @@ TEST_F(ReservationTest, ACLMultipleOperations)
   EXPECT_TRUE(Resources(offer.resources()).contains(
       allocatedResources(
           dynamicallyReserved1 + dynamicallyReserved2 + unreserved2,
-          frameworkInfo.role())));
+          frameworkInfo.roles(0))));
 
   // Check that the task launched as expected.
   EXPECT_EQ(TASK_FINISHED, failedTaskStatus->state());
@@ -1928,7 +1928,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithoutPrincipal)
 
   // Create a framework without a principal.
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
   frameworkInfo.clear_principal();
 
   // Create a master with no framework authentication.
@@ -1958,7 +1958,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithoutPrincipal)
   // Create dynamically reserved resources whose `ReservationInfo` does not
   // contain a principal.
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(), createReservationInfo()).get();
+      frameworkInfo.roles(0), createReservationInfo()).get();
 
   // We use this to capture offers from `resourceOffers`.
   Future<vector<Offer>> offers;
@@ -1980,7 +1980,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithoutPrincipal)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the offer with reserved resources.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -1999,7 +1999,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithoutPrincipal)
 
   // Make sure that the reservation succeeded.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // An expectation for an offer with unreserved resources.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -2019,7 +2019,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithoutPrincipal)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -2036,7 +2036,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithPrincipal)
 
   // Create a framework with a principal.
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   // Create a master with no framework authentication.
   master::Flags masterFlags = CreateMasterFlags();
@@ -2065,7 +2065,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithPrincipal)
   // Create dynamically reserved resources whose `ReservationInfo` contains a
   // principal.
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from `resourceOffers`.
@@ -2088,7 +2088,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithPrincipal)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the offer with reserved resources.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -2107,7 +2107,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithPrincipal)
 
   // Make sure that the reservation succeeded.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // An expectation for an offer with unreserved resources.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -2127,7 +2127,7 @@ TEST_F(ReservationTest, WithoutAuthenticationWithPrincipal)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -2142,7 +2142,7 @@ TEST_F(ReservationTest, DropReserveWithInvalidRole)
   const string invalidRole = "invalid-role";
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(frameworkRole);
+  frameworkInfo.set_roles(0, frameworkRole);
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
@@ -2187,7 +2187,7 @@ TEST_F(ReservationTest, DropReserveWithInvalidRole)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -2221,7 +2221,7 @@ TEST_F(ReservationTest, DropReserveWithInvalidRole)
   offer = offers->front();
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -2235,12 +2235,12 @@ TEST_F(ReservationTest, PreventUnreservingAlienResources)
   const string frameworkRole1 = "role1";
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo1.set_name("framework1");
-  frameworkInfo1.set_role(frameworkRole1);
+  frameworkInfo1.set_roles(0, frameworkRole1);
 
   const string frameworkRole2 = "role2";
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo1.set_name("framework2");
-  frameworkInfo2.set_role(frameworkRole2);
+  frameworkInfo2.set_name("framework2");
+  frameworkInfo2.set_roles(0, frameworkRole2);
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.allocation_interval = Milliseconds(5);
@@ -2286,7 +2286,7 @@ TEST_F(ReservationTest, PreventUnreservingAlienResources)
   const Resources unreserved = Resources::parse("cpus:1;mem:512").get();
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo1.role())));
+      allocatedResources(unreserved, frameworkInfo1.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched1, resourceOffers(&driver1, _))
@@ -2314,9 +2314,9 @@ TEST_F(ReservationTest, PreventUnreservingAlienResources)
   offer = offers->front();
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo1.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo1.roles(0))));
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(halfMemory, frameworkInfo1.role())));
+      allocatedResources(halfMemory, frameworkInfo1.roles(0))));
 
   // The filter to decline the offer "forever".
   Filters filtersForever;
@@ -2341,9 +2341,9 @@ TEST_F(ReservationTest, PreventUnreservingAlienResources)
   offer = offers->front();
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(halfMemory, frameworkInfo2.role())));
+      allocatedResources(halfMemory, frameworkInfo2.roles(0))));
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo2.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo2.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched2, resourceOffers(&driver2, _))
@@ -2361,9 +2361,9 @@ TEST_F(ReservationTest, PreventUnreservingAlienResources)
   AWAIT_READY(offers);
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(halfMemory, frameworkInfo2.role())));
+      allocatedResources(halfMemory, frameworkInfo2.roles(0))));
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo2.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo2.roles(0))));
 
   // Decline the offer "forever" in order to force `framework1` to
   // receive the remaining resources.
@@ -2387,9 +2387,9 @@ TEST_F(ReservationTest, PreventUnreservingAlienResources)
 
   // Make sure that the reservation is still in place.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(halfMemory, frameworkInfo1.role())));
+      allocatedResources(halfMemory, frameworkInfo1.roles(0))));
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo1.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo1.roles(0))));
 
   driver1.stop();
   driver1.join();

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/role_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/role_tests.cpp b/src/tests/role_tests.cpp
index 4285e64..6b879df 100644
--- a/src/tests/role_tests.cpp
+++ b/src/tests/role_tests.cpp
@@ -70,7 +70,7 @@ class RoleTest : public MesosTest {};
 TEST_F(RoleTest, BadRegister)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("invalid");
+  frameworkInfo.set_roles(0, "invalid");
 
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.roles = "foo,bar";
@@ -115,7 +115,7 @@ TEST_F(RoleTest, ImplicitRoleRegister)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("new-role-name");
+  frameworkInfo.set_roles(0, "new-role-name");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -128,7 +128,7 @@ TEST_F(RoleTest, ImplicitRoleRegister)
 
   Resources unreserved = Resources::parse("disk:1024").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(frameworkInfo.principal())).get();
 
   // We use this to capture offers from `resourceOffers`.
@@ -149,9 +149,9 @@ TEST_F(RoleTest, ImplicitRoleRegister)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // The expectation for the next offer.
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -167,13 +167,13 @@ TEST_F(RoleTest, ImplicitRoleRegister)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   Resources volume = createPersistentVolume(
       Megabytes(64),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "path1",
       frameworkInfo.principal(),
@@ -193,11 +193,11 @@ TEST_F(RoleTest, ImplicitRoleRegister)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -227,7 +227,7 @@ TEST_F(RoleTest, ImplicitRoleStaticReservation)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -258,7 +258,7 @@ TEST_F(RoleTest, ImplicitRoleStaticReservation)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(staticallyReserved, frameworkInfo.role())));
+      allocatedResources(staticallyReserved, frameworkInfo.roles(0))));
 
   // Create a task to launch with the resources of `staticallyReserved`.
   TaskInfo taskInfo =
@@ -467,7 +467,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(RoleTest, EndpointImplicitRolesWeights)
   ASSERT_SOME(master);
 
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo1.set_role("roleX");
+  frameworkInfo1.set_roles(0, "roleX");
 
   MockScheduler sched1;
   MesosSchedulerDriver driver1(
@@ -480,7 +480,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(RoleTest, EndpointImplicitRolesWeights)
   driver1.start();
 
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo2.set_role("roleZ");
+  frameworkInfo2.set_roles(0, "roleZ");
 
   MockScheduler sched2;
   MesosSchedulerDriver driver2(
@@ -673,10 +673,8 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(
   ASSERT_SOME(master);
 
   FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
-  framework.add_roles("role1");
+  framework.set_roles(0, "role1");
   framework.add_roles("role2");
-  framework.add_capabilities()->set_type(
-      FrameworkInfo::Capability::MULTI_ROLE);
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -929,7 +927,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(
   auto runTask = [&master, &PATH, DISK_SIZE](
       const string& role, const string& id) {
     FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-    frameworkInfo.set_role(role);
+    frameworkInfo.set_roles(0, role);
 
     MockScheduler sched;
     MesosSchedulerDriver driver(

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/scheduler_http_api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/scheduler_http_api_tests.cpp b/src/tests/scheduler_http_api_tests.cpp
index cc03be0..4e17471 100644
--- a/src/tests/scheduler_http_api_tests.cpp
+++ b/src/tests/scheduler_http_api_tests.cpp
@@ -324,7 +324,7 @@ TEST_P(SchedulerHttpApiTest, RejectFrameworkWithInvalidRole)
   Call::Subscribe* subscribe = call.mutable_subscribe();
   v1::FrameworkInfo framework = v1::DEFAULT_FRAMEWORK_INFO;
   // Set invalid role.
-  framework.set_role("/test/test1");
+  framework.set_roles(0, "/test/test1");
   subscribe->mutable_framework_info()->CopyFrom(framework);
 
   // Retrieve the parameter passed as content type to this test.

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/slave_authorization_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_authorization_tests.cpp b/src/tests/slave_authorization_tests.cpp
index 4e55148..834ee05 100644
--- a/src/tests/slave_authorization_tests.cpp
+++ b/src/tests/slave_authorization_tests.cpp
@@ -166,7 +166,7 @@ TYPED_TEST(SlaveAuthorizerTest, FilterStateEndpoint)
 
   // Register framework with user "bar".
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
   frameworkInfo.set_user("bar");
 
   // Create an executor with user "bar".

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/slave_recovery_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_recovery_tests.cpp b/src/tests/slave_recovery_tests.cpp
index 4a0207e..4f5a6a2 100644
--- a/src/tests/slave_recovery_tests.cpp
+++ b/src/tests/slave_recovery_tests.cpp
@@ -1851,13 +1851,13 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
 
   Offer offer1 = offer;
   Resources resources1 = allocatedResources(
-      Resources::parse("cpus:1;mem:512").get(), frameworkInfo.role());
+      Resources::parse("cpus:1;mem:512").get(), frameworkInfo.roles(0));
   offer1.mutable_resources()->CopyFrom(resources1);
   tasks.push_back(createTask(offer1, "sleep 1000")); // Long-running task.
 
   Offer offer2 = offer;
   Resources resources2 = allocatedResources(
-      Resources::parse("cpus:1;mem:512").get(), frameworkInfo.role());
+      Resources::parse("cpus:1;mem:512").get(), frameworkInfo.roles(0));
   offer2.mutable_resources()->CopyFrom(resources2);
   tasks.push_back(createTask(offer2, "sleep 1000")); // Long-running task,
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/slave_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_tests.cpp b/src/tests/slave_tests.cpp
index 2a568a9..e3e50dd 100644
--- a/src/tests/slave_tests.cpp
+++ b/src/tests/slave_tests.cpp
@@ -785,12 +785,12 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(SlaveTest, GetExecutorInfo)
   FrameworkID frameworkId;
   frameworkId.set_value("20141010-221431-251662764-60288-32120-0000");
 
-  FrameworkInfo frameworkInfo;
+  FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo.mutable_id()->CopyFrom(frameworkId);
 
   // Launch a task with the command executor.
   Resources taskResources = Resources::parse("cpus:0.1;mem:32").get();
-  taskResources.allocate(frameworkInfo.role());
+  taskResources.allocate(frameworkInfo.roles(0));
 
   TaskInfo task;
   task.set_name("task");
@@ -843,14 +843,14 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(SlaveTest, GetExecutorInfoForTaskWithContainer)
 
   MockSlave slave(CreateSlaveFlags(), &detector, &containerizer);
 
-  FrameworkInfo frameworkInfo;
+  FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo.mutable_id()->set_value(
       "20141010-221431-251662764-60288-12345-0000");
 
   // Launch a task with the command executor and ContainerInfo with
   // NetworkInfo.
   Resources taskResources = Resources::parse("cpus:0.1;mem:32").get();
-  taskResources.allocate(frameworkInfo.role());
+  taskResources.allocate(frameworkInfo.roles(0));
 
   TaskInfo task;
   task.set_name("task");
@@ -920,12 +920,12 @@ TEST_F(SlaveTest, ROOT_LaunchTaskInfoWithContainerInfo)
   StandaloneMasterDetector detector;
   MockSlave slave(flags, &detector, containerizer.get());
 
-  FrameworkInfo frameworkInfo;
+  FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo.mutable_id()->set_value(
       "20141010-221431-251662764-60288-12345-0000");
 
   Resources taskResources = Resources::parse("cpus:0.1;mem:32").get();
-  taskResources.allocate(frameworkInfo.role());
+  taskResources.allocate(frameworkInfo.roles(0));
 
   // Launch a task with the command executor and ContainerInfo with
   // NetworkInfo.
@@ -1642,9 +1642,14 @@ TEST_F(SlaveTest, StateEndpoint)
   EXPECT_EQ(1u, frameworks.values.size());
 
   ASSERT_TRUE(frameworks.values[0].is<JSON::Object>());
-  JSON::Object framework = frameworks.values[0].as<JSON::Object>();
 
-  EXPECT_EQ("*", framework.values["role"]);
+  JSON::Object roles = {
+    { "roles", JSON::Array { DEFAULT_FRAMEWORK_INFO.roles(0) } }
+  };
+
+  EXPECT_TRUE(frameworks.values[0].contains(roles));
+
+  JSON::Object framework = frameworks.values[0].as<JSON::Object>();
   EXPECT_EQ("default", framework.values["name"]);
   EXPECT_EQ(model(resources.get()), state.values["resources"]);
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/upgrade_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/upgrade_tests.cpp b/src/tests/upgrade_tests.cpp
index 03ca360..2a66490 100644
--- a/src/tests/upgrade_tests.cpp
+++ b/src/tests/upgrade_tests.cpp
@@ -119,6 +119,8 @@ TEST_F(UpgradeTest, ReregisterOldAgentWithMultiRoleMaster)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo.clear_capabilities();
+  frameworkInfo.clear_roles();
   frameworkInfo.set_role("foo");
 
   MockScheduler sched;
@@ -335,10 +337,7 @@ TEST_F(UpgradeTest, UpgradeSlaveIntoMultiRole)
   AWAIT_READY(slaveRegisteredMessage);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.clear_role();
-  frameworkInfo.add_roles("foo");
-  frameworkInfo.add_capabilities()->set_type(
-      FrameworkInfo::Capability::MULTI_ROLE);
+  frameworkInfo.set_roles(0, "foo");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -408,6 +407,8 @@ TEST_F(UpgradeTest, MultiRoleSchedulerUpgrade)
   ASSERT_SOME(agent);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo.clear_capabilities();
+  frameworkInfo.clear_roles();
   frameworkInfo.set_role("foo");
 
   MockScheduler sched1;


[3/6] mesos git commit: Added MESOS-7674 to the 1.3.2 CHANGELOG.

Posted by bm...@apache.org.
Added MESOS-7674 to the 1.3.2 CHANGELOG.


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

Branch: refs/heads/1.3.x
Commit: 55b498ceeb21d11851de1de6f98e45aafb07c991
Parents: 3d39124
Author: Benjamin Mahler <bm...@apache.org>
Authored: Fri Dec 1 20:16:25 2017 -0800
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Fri Dec 1 20:18:15 2017 -0800

----------------------------------------------------------------------
 CHANGELOG | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/55b498ce/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index a2c913d..5dc8acd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,7 @@ All Issues:
   * [MESOS-6743] - Docker executor hangs forever if `docker stop` fails.
   * [MESOS-6950] - Launching two tasks with the same Docker image simultaneously may cause a staging dir never cleaned up.
   * [MESOS-7652] - Docker image with universal containerizer does not work if WORKDIR is missing in the rootfs.
+  * [MESOS-7674] - Update the generic Protobuf to JSON facility to not output deprecated fields.
   * [MESOS-7858] - Launching a nested container with namespace/pid isolation, with glibc < 2.25, may deadlock the LinuxLauncher and MesosContainerizer.
   * [MESOS-7863] - Agent may drop pending kill task status updates.
   * [MESOS-7865] - Agent may process a kill task and still launch the task.
@@ -21,6 +22,7 @@ All Issues:
   * [MESOS-8135] - Masters can lose track of tasks' executor IDs.
 
 
+
 Release Notes - Mesos - Version 1.3.1
 -------------------------------------
 * This is a bug fix release.


[5/6] mesos git commit: Updated the tests to use MULTI_ROLE frameworks by default.

Posted by bm...@apache.org.
Updated the tests to use MULTI_ROLE frameworks by default.

Now that we strip the `Resource.allocation_info` for non-MULTI_ROLE
schedulers, it's simpler to default the tests to use the MULTI_ROLE
capability, since we've already updated the majority of the tests
to be aware of `Resource.allocation_info`.

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


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

Branch: refs/heads/1.3.x
Commit: 5a87d51ece14a5b884341a39dff456bb8ec48461
Parents: 8855f0e
Author: Benjamin Mahler <bm...@apache.org>
Authored: Wed Nov 29 17:41:11 2017 -0800
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Fri Dec 1 20:18:15 2017 -0800

----------------------------------------------------------------------
 src/examples/balloon_framework.cpp              |  10 +-
 src/examples/disk_full_framework.cpp            |   7 +-
 src/examples/dynamic_reservation_framework.cpp  |   4 +-
 src/examples/long_lived_framework.cpp           |  11 +-
 src/examples/no_executor_framework.cpp          |   5 +-
 src/examples/persistent_volume_framework.cpp    |  32 +--
 src/examples/test_framework.cpp                 |   4 +-
 src/examples/test_http_framework.cpp            |  13 +-
 src/tests/api_tests.cpp                         |  26 +--
 .../containerizer/cgroups_isolator_tests.cpp    |   5 +-
 .../docker_containerizer_tests.cpp              |   6 +-
 .../linux_filesystem_isolator_tests.cpp         |   8 +-
 src/tests/default_executor_tests.cpp            |  16 +-
 src/tests/disk_quota_tests.cpp                  |   4 +-
 src/tests/fault_tolerance_tests.cpp             |   6 +-
 src/tests/hook_tests.cpp                        |   2 +-
 src/tests/master_allocator_tests.cpp            |  16 +-
 src/tests/master_authorization_tests.cpp        |  12 +-
 src/tests/master_quota_tests.cpp                |   4 +-
 src/tests/master_tests.cpp                      |  35 ++-
 src/tests/master_validation_tests.cpp           |  26 ++-
 src/tests/mesos.hpp                             |   9 +-
 src/tests/oversubscription_tests.cpp            |  28 ++-
 src/tests/partition_tests.cpp                   |   2 +-
 src/tests/persistent_volume_endpoints_tests.cpp |  71 +++---
 src/tests/persistent_volume_tests.cpp           | 110 ++++-----
 src/tests/reservation_endpoints_tests.cpp       | 104 ++++-----
 src/tests/reservation_tests.cpp                 | 222 +++++++++----------
 src/tests/role_tests.cpp                        |  36 ++-
 src/tests/scheduler_http_api_tests.cpp          |   2 +-
 src/tests/slave_authorization_tests.cpp         |   2 +-
 src/tests/slave_recovery_tests.cpp              |   4 +-
 src/tests/slave_tests.cpp                       |  21 +-
 src/tests/upgrade_tests.cpp                     |   9 +-
 34 files changed, 464 insertions(+), 408 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/balloon_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/balloon_framework.cpp b/src/examples/balloon_framework.cpp
index bfaae37..1ef43d6 100644
--- a/src/examples/balloon_framework.cpp
+++ b/src/examples/balloon_framework.cpp
@@ -140,6 +140,7 @@ public:
       const ExecutorInfo& _executor,
       const Flags& _flags)
     : frameworkInfo(_frameworkInfo),
+      role(_frameworkInfo.roles(0)),
       executor(_executor),
       flags(_flags),
       taskActive(false),
@@ -167,10 +168,10 @@ public:
     Resources taskResources = Resources::parse(
         "cpus:" + stringify(CPUS_PER_TASK) +
         ";mem:" + stringify(flags.task_memory.megabytes())).get();
-    taskResources.allocate(frameworkInfo.role());
+    taskResources.allocate(role);
 
     Resources executorResources = Resources(executor.resources());
-    executorResources.allocate(frameworkInfo.role());
+    executorResources.allocate(role);
 
     foreach (const Offer& offer, offers) {
       Resources resources(offer.resources());
@@ -265,6 +266,7 @@ public:
 
 private:
   const FrameworkInfo frameworkInfo;
+  const string role;
   const ExecutorInfo executor;
   const Flags flags;
   bool taskActive;
@@ -497,7 +499,9 @@ int main(int argc, char** argv)
   framework.set_user(os::user().get());
   framework.set_name("Balloon Framework (C++)");
   framework.set_checkpoint(flags.checkpoint);
-  framework.set_role("*");
+  framework.add_roles("*");
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
 
   BalloonScheduler scheduler(framework, executor, flags);
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/disk_full_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/disk_full_framework.cpp b/src/examples/disk_full_framework.cpp
index a73e6cf..de1de5f 100644
--- a/src/examples/disk_full_framework.cpp
+++ b/src/examples/disk_full_framework.cpp
@@ -116,6 +116,7 @@ public:
       const FrameworkInfo& _frameworkInfo)
     : flags(_flags),
       frameworkInfo(_frameworkInfo),
+      role(_frameworkInfo.roles(0)),
       tasksLaunched(0),
       taskActive(false),
       isRegistered(false),
@@ -142,7 +143,7 @@ public:
         "cpus:" + stringify(CPUS_PER_TASK) +
         ";mem:" + stringify(MEMORY_PER_TASK) +
         ";disk:" + stringify(DISK_PER_TASK.megabytes())).get();
-    taskResources.allocate(frameworkInfo.role());
+    taskResources.allocate(role);
 
     foreach (const Offer& offer, offers) {
       LOG(INFO) << "Received offer " << offer.id() << " from agent "
@@ -257,6 +258,7 @@ public:
 private:
   const Flags flags;
   const FrameworkInfo frameworkInfo;
+  const string role;
 
   int tasksLaunched;
   bool taskActive;
@@ -436,6 +438,9 @@ int main(int argc, char** argv)
   framework.set_user(""); // Have Mesos fill the current user.
   framework.set_name("Disk Full Framework (C++)");
   framework.set_checkpoint(true);
+  framework.add_roles("*");
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
 
   DiskFullScheduler scheduler(flags, framework);
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/dynamic_reservation_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/dynamic_reservation_framework.cpp b/src/examples/dynamic_reservation_framework.cpp
index 4122814..fa90eff 100644
--- a/src/examples/dynamic_reservation_framework.cpp
+++ b/src/examples/dynamic_reservation_framework.cpp
@@ -379,7 +379,9 @@ int main(int argc, char** argv)
   FrameworkInfo framework;
   framework.set_user(""); // Mesos'll fill in the current user.
   framework.set_name("Dynamic Reservation Framework (C++)");
-  framework.set_role(flags.role.get());
+  framework.add_roles(flags.role.get());
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
   framework.set_principal(flags.principal);
 
   DynamicReservationScheduler scheduler(

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/long_lived_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/long_lived_framework.cpp b/src/examples/long_lived_framework.cpp
index 7ee4f27..4233135 100644
--- a/src/examples/long_lived_framework.cpp
+++ b/src/examples/long_lived_framework.cpp
@@ -105,12 +105,13 @@ public:
     : state(DISCONNECTED),
       master(_master),
       framework(_framework),
+      role(_framework.roles(0)),
       executor(_executor),
-      taskResources([&_framework]() {
+      taskResources([this]() {
         Resources resources = Resources::parse(
             "cpus:" + stringify(CPUS_PER_TASK) +
             ";mem:" + stringify(MEM_PER_TASK)).get();
-        resources.allocate(_framework.role());
+        resources.allocate(this->role);
         return resources;
       }()),
       tasksLaunched(0),
@@ -243,7 +244,7 @@ protected:
 
     const Resources executorResources = [this]() {
       Resources resources(executor.resources());
-      resources.allocate(framework.role());
+      resources.allocate(role);
       return resources;
     }();
 
@@ -402,6 +403,7 @@ private:
 
   const string master;
   FrameworkInfo framework;
+  const string role;
   const ExecutorInfo executor;
   const Resources taskResources;
   string uri;
@@ -583,6 +585,9 @@ int main(int argc, char** argv)
   framework.set_user(os::user().get());
   framework.set_name("Long Lived Framework (C++)");
   framework.set_checkpoint(flags.checkpoint);
+  framework.add_roles("*");
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
 
   Option<Credential> credential = None();
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/no_executor_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/no_executor_framework.cpp b/src/examples/no_executor_framework.cpp
index 77b7408..f206378 100644
--- a/src/examples/no_executor_framework.cpp
+++ b/src/examples/no_executor_framework.cpp
@@ -329,6 +329,9 @@ int main(int argc, char** argv)
   framework.set_user(""); // Have Mesos fill in the current user.
   framework.set_name("No Executor Framework");
   framework.set_checkpoint(flags.checkpoint);
+  framework.add_roles("*");
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
 
   if (flags.task_revocable_resources.isSome()) {
     framework.add_capabilities()->set_type(
@@ -366,7 +369,7 @@ int main(int argc, char** argv)
     }
   }
 
-  taskResources.allocate(framework.role());
+  taskResources.allocate(framework.roles(0));
 
   logging::initialize(argv[0], flags, true); // Catch signals.
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/persistent_volume_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/persistent_volume_framework.cpp b/src/examples/persistent_volume_framework.cpp
index ab4597d..df03ad2 100644
--- a/src/examples/persistent_volume_framework.cpp
+++ b/src/examples/persistent_volume_framework.cpp
@@ -140,24 +140,27 @@ public:
       size_t numShards,
       size_t numSharedShards,
       size_t tasksPerShard)
-    : frameworkInfo(_frameworkInfo)
+    : frameworkInfo(_frameworkInfo),
+      role(_frameworkInfo.roles(0))
   {
     // Initialize the shards using regular persistent volume.
     for (size_t i = 0; i < numShards; i++) {
-      shards.push_back(Shard(
-          "shard-" + stringify(i),
-          frameworkInfo.role(),
-          tasksPerShard,
-          false));
+      shards.push_back(
+          Shard(
+              "shard-" + stringify(i),
+              role,
+              tasksPerShard,
+              false));
     }
 
     // Initialize the shards using shared persistent volume.
     for (size_t i = 0; i < numSharedShards; i++) {
-      shards.push_back(Shard(
-          "shared-shard-" + stringify(i),
-          frameworkInfo.role(),
-          tasksPerShard,
-          true));
+      shards.push_back(
+          Shard(
+              "shared-shard-" + stringify(i),
+              role,
+              tasksPerShard,
+              true));
     }
   }
 
@@ -206,7 +209,7 @@ public:
 
             if (offered.contains(shard.resources)) {
               Resource volume = SHARD_PERSISTENT_VOLUME(
-                  frameworkInfo.role(),
+                  role,
                   UUID::random().toString(),
                   "volume",
                   frameworkInfo.principal(),
@@ -491,6 +494,7 @@ private:
   };
 
   FrameworkInfo frameworkInfo;
+  const string role;
   vector<Shard> shards;
 };
 
@@ -574,7 +578,9 @@ int main(int argc, char** argv)
   FrameworkInfo framework;
   framework.set_user(""); // Have Mesos fill in the current user.
   framework.set_name("Persistent Volume Framework (C++)");
-  framework.set_role(flags.role);
+  framework.add_roles(flags.role);
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
   framework.set_checkpoint(true);
   framework.set_principal(flags.principal);
   framework.add_capabilities()->set_type(

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/test_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/test_framework.cpp b/src/examples/test_framework.cpp
index 05ddc89..9c4e08a 100644
--- a/src/examples/test_framework.cpp
+++ b/src/examples/test_framework.cpp
@@ -249,7 +249,9 @@ int main(int argc, char** argv)
   FrameworkInfo framework;
   framework.set_user(""); // Have Mesos fill in the current user.
   framework.set_name("Test Framework (C++)");
-  framework.set_role(flags.role);
+  framework.add_roles(flags.role);
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
 
   value = os::getenv("MESOS_CHECKPOINT");
   if (value.isSome()) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/examples/test_http_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/test_http_framework.cpp b/src/examples/test_http_framework.cpp
index 471835c..8b31230 100644
--- a/src/examples/test_http_framework.cpp
+++ b/src/examples/test_http_framework.cpp
@@ -72,6 +72,7 @@ public:
                 const ExecutorInfo& _executor,
                 const string& _master)
     : framework(_framework),
+      role(_framework.roles(0)),
       executor(_executor),
       master(_master),
       state(INITIALIZING),
@@ -84,6 +85,7 @@ public:
                 const string& _master,
                 const Credential& credential)
     : framework(_framework),
+      role(_framework.roles(0)),
       executor(_executor),
       master(_master),
       state(INITIALIZING),
@@ -225,7 +227,7 @@ private:
       Resources taskResources = Resources::parse(
           "cpus:" + stringify(CPUS_PER_TASK) +
           ";mem:" + stringify(MEM_PER_TASK)).get();
-      taskResources.allocate(framework.role());
+      taskResources.allocate(role);
 
       Resources remaining = offer.resources();
 
@@ -245,10 +247,10 @@ private:
         task.mutable_agent_id()->MergeFrom(offer.agent_id());
         task.mutable_executor()->MergeFrom(executor);
 
-        Try<Resources> flattened = taskResources.flatten(framework.role());
+        Try<Resources> flattened = taskResources.flatten(role);
         CHECK_SOME(flattened);
-        Option<Resources> resources = remaining.find(flattened.get());
 
+        Option<Resources> resources = remaining.find(flattened.get());
         CHECK_SOME(resources);
 
         task.mutable_resources()->CopyFrom(resources.get());
@@ -352,6 +354,7 @@ private:
   }
 
   FrameworkInfo framework;
+  const string role;
   const ExecutorInfo executor;
   const string master;
   process::Owned<scheduler::Mesos> mesos;
@@ -429,7 +432,9 @@ int main(int argc, char** argv)
 
   FrameworkInfo framework;
   framework.set_name("Event Call Scheduler using libprocess (C++)");
-  framework.set_role(flags.role);
+  framework.add_roles(flags.role);
+  framework.add_capabilities()->set_type(
+      FrameworkInfo::Capability::MULTI_ROLE);
 
   const Result<string> user = os::user();
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/api_tests.cpp b/src/tests/api_tests.cpp
index faf3242..6ec0436 100644
--- a/src/tests/api_tests.cpp
+++ b/src/tests/api_tests.cpp
@@ -241,7 +241,7 @@ TEST_P(MasterAPITest, GetFrameworks)
 
   ASSERT_EQ(1, frameworks.frameworks_size());
   ASSERT_EQ("default", frameworks.frameworks(0).framework_info().name());
-  ASSERT_EQ("*", frameworks.frameworks(0).framework_info().role());
+  ASSERT_EQ("*", frameworks.frameworks(0).framework_info().roles(0));
   ASSERT_FALSE(frameworks.frameworks(0).framework_info().checkpoint());
   ASSERT_TRUE(frameworks.frameworks(0).active());
   ASSERT_TRUE(frameworks.frameworks(0).connected());
@@ -864,7 +864,7 @@ TEST_P(MasterAPITest, GetRoles)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -952,11 +952,11 @@ TEST_P(MasterAPITest, ReserveResources)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   MockScheduler sched;
@@ -978,7 +978,7 @@ TEST_P(MasterAPITest, ReserveResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, resourceOffers(&driver, _))
     .WillOnce(FutureArg<1>(&offers));
@@ -1012,7 +1012,7 @@ TEST_P(MasterAPITest, ReserveResources)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1044,11 +1044,11 @@ TEST_P(MasterAPITest, UnreserveResources)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
 
   Resources unreserved = Resources::parse("cpus:1;mem:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   v1::master::Call v1Call;
@@ -1090,7 +1090,7 @@ TEST_P(MasterAPITest, UnreserveResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, resourceOffers(&driver, _))
     .WillOnce(FutureArg<1>(&offers));
@@ -1124,7 +1124,7 @@ TEST_P(MasterAPITest, UnreserveResources)
 
   // Verifies if the resources are unreserved.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -2010,7 +2010,7 @@ TEST_P(MasterAPITest, CreateAndDestroyVolumes)
   AWAIT_READY(v1CreateVolumesResponse);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   // Start a framework and launch a task on the persistent volume.
   MockScheduler sched;
@@ -2031,11 +2031,11 @@ TEST_P(MasterAPITest, CreateAndDestroyVolumes)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   Resources taskResources = Resources::parse(
       "disk:256",
-      frameworkInfo.role()).get();
+      frameworkInfo.roles(0)).get();
 
   TaskInfo taskInfo = createTask(
       offer.slave_id(),

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/containerizer/cgroups_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/cgroups_isolator_tests.cpp b/src/tests/containerizer/cgroups_isolator_tests.cpp
index 4e1d027..fb5dc5e 100644
--- a/src/tests/containerizer/cgroups_isolator_tests.cpp
+++ b/src/tests/containerizer/cgroups_isolator_tests.cpp
@@ -309,8 +309,9 @@ TEST_F(CgroupsIsolatorTest, ROOT_CGROUPS_RevocableCpu)
 
   // Now the framework will get revocable resources.
   AWAIT_READY(offers2);
-  EXPECT_NE(0u, offers2->size());
-  EXPECT_EQ(allocatedResources(cpus, frameworkInfo.role()),
+
+  ASSERT_FALSE(offers2->empty());
+  EXPECT_EQ(allocatedResources(cpus, frameworkInfo.roles(0)),
             Resources(offers2.get()[0].resources()));
 
   TaskInfo task = createTask(

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/containerizer/docker_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/docker_containerizer_tests.cpp b/src/tests/containerizer/docker_containerizer_tests.cpp
index 4eef399..5635b07 100644
--- a/src/tests/containerizer/docker_containerizer_tests.cpp
+++ b/src/tests/containerizer/docker_containerizer_tests.cpp
@@ -1590,7 +1590,7 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_LaunchWithPersistentVolumes)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -1745,7 +1745,7 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_RecoverPersistentVolumes)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
   frameworkInfo.set_checkpoint(true);
 
   MockScheduler sched;
@@ -1908,7 +1908,7 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_RecoverOrphanedPersistentVolumes)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
   frameworkInfo.set_checkpoint(true);
 
   MockScheduler sched;

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/containerizer/linux_filesystem_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/linux_filesystem_isolator_tests.cpp b/src/tests/containerizer/linux_filesystem_isolator_tests.cpp
index 70a0dce..9c7f34f 100644
--- a/src/tests/containerizer/linux_filesystem_isolator_tests.cpp
+++ b/src/tests/containerizer/linux_filesystem_isolator_tests.cpp
@@ -1075,7 +1075,7 @@ TEST_F(LinuxFilesystemIsolatorMesosTest,
 
   MockScheduler sched;
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   MesosSchedulerDriver driver(
       &sched,
@@ -1211,7 +1211,7 @@ TEST_F(LinuxFilesystemIsolatorMesosTest,
 
   MockScheduler sched;
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
   frameworkInfo.set_checkpoint(true);
 
   MesosSchedulerDriver driver(
@@ -1431,7 +1431,7 @@ TEST_F(LinuxFilesystemIsolatorMesosTest,
 
   MockScheduler sched;
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   MesosSchedulerDriver driver(
       &sched,
@@ -1523,7 +1523,7 @@ TEST_F(LinuxFilesystemIsolatorMesosTest,
 
   MockScheduler sched;
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/default_executor_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/default_executor_tests.cpp b/src/tests/default_executor_tests.cpp
index 22af7e9..a8c7a97 100644
--- a/src/tests/default_executor_tests.cpp
+++ b/src/tests/default_executor_tests.cpp
@@ -1293,7 +1293,7 @@ TEST_P(DefaultExecutorTest, ReservedResources)
   AWAIT_READY(connected);
 
   v1::FrameworkInfo frameworkInfo = v1::DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   Future<v1::scheduler::Event::Subscribed> subscribed;
   EXPECT_CALL(*scheduler, subscribed(_, _))
@@ -1323,7 +1323,7 @@ TEST_P(DefaultExecutorTest, ReservedResources)
 
   // Launch the executor using reserved resources.
   v1::Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       v1::createReservationInfo(frameworkInfo.principal())).get();
 
   v1::ExecutorInfo executorInfo;
@@ -1443,7 +1443,7 @@ TEST_P(PersistentVolumeDefaultExecutor, ROOT_PersistentResources)
   auto scheduler = std::make_shared<v1::MockHTTPScheduler>();
 
   v1::FrameworkInfo frameworkInfo = v1::DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   Future<Nothing> connected;
   EXPECT_CALL(*scheduler, connected(_))
@@ -1476,12 +1476,12 @@ TEST_P(PersistentVolumeDefaultExecutor, ROOT_PersistentResources)
     v1::Resources::parse("cpus:0.1;mem:32;disk:32").get();
 
   v1::Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       v1::createReservationInfo(frameworkInfo.principal())).get();
 
   v1::Resource volume = v1::createPersistentVolume(
       Megabytes(1),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "executor_volume_path",
       frameworkInfo.principal(),
@@ -1585,7 +1585,7 @@ TEST_P(PersistentVolumeDefaultExecutor, ROOT_TaskSandboxPersistentVolume)
   auto scheduler = std::make_shared<v1::MockHTTPScheduler>();
 
   v1::FrameworkInfo frameworkInfo = v1::DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   Future<Nothing> connected;
   EXPECT_CALL(*scheduler, connected(_))
@@ -1633,7 +1633,7 @@ TEST_P(PersistentVolumeDefaultExecutor, ROOT_TaskSandboxPersistentVolume)
 
   v1::Resource volume = v1::createPersistentVolume(
       Megabytes(1),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "task_volume_path",
       frameworkInfo.principal(),
@@ -1641,7 +1641,7 @@ TEST_P(PersistentVolumeDefaultExecutor, ROOT_TaskSandboxPersistentVolume)
       frameworkInfo.principal());
 
   v1::Resources reserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       v1::createReservationInfo(frameworkInfo.principal())).get();
 
   // Launch a task that expects the persistent volume to be

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/disk_quota_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/disk_quota_tests.cpp b/src/tests/disk_quota_tests.cpp
index 9fe2c86..c361883 100644
--- a/src/tests/disk_quota_tests.cpp
+++ b/src/tests/disk_quota_tests.cpp
@@ -245,7 +245,7 @@ TEST_F(DiskQuotaTest, DiskUsageExceedsQuota)
 TEST_F(DiskQuotaTest, VolumeUsageExceedsQuota)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   master::Flags masterFlags = CreateMasterFlags();
 
@@ -472,7 +472,7 @@ TEST_F(DiskQuotaTest, ResourceStatistics)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   MockScheduler sched;
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/fault_tolerance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/fault_tolerance_tests.cpp b/src/tests/fault_tolerance_tests.cpp
index ee2130c..e551ba4 100644
--- a/src/tests/fault_tolerance_tests.cpp
+++ b/src/tests/fault_tolerance_tests.cpp
@@ -2039,6 +2039,8 @@ TEST_F(FaultToleranceTest, UpdateFrameworkInfoOnSchedulerFailover)
   // scheduler with updated information.
 
   FrameworkInfo finfo1 = DEFAULT_FRAMEWORK_INFO;
+  finfo1.clear_capabilities();
+  finfo1.clear_roles();
   finfo1.set_name("Framework 1");
   finfo1.set_failover_timeout(1000);
   finfo1.mutable_labels()->add_labels()->CopyFrom(createLabel("foo", "bar"));
@@ -2063,7 +2065,8 @@ TEST_F(FaultToleranceTest, UpdateFrameworkInfoOnSchedulerFailover)
   // updated FrameworkInfo and wait until it gets a registered
   // callback.
 
-  FrameworkInfo finfo2 = DEFAULT_FRAMEWORK_INFO;
+  FrameworkInfo finfo2 = finfo1;
+
   finfo2.mutable_id()->MergeFrom(frameworkId.get());
   auto capabilityType = FrameworkInfo::Capability::REVOCABLE_RESOURCES;
   finfo2.add_capabilities()->set_type(capabilityType);
@@ -2071,6 +2074,7 @@ TEST_F(FaultToleranceTest, UpdateFrameworkInfoOnSchedulerFailover)
   finfo2.set_webui_url("http://localhost:8080/");
   finfo2.set_failover_timeout(100);
   finfo2.set_hostname("myHostname");
+  finfo2.clear_labels();
   finfo2.mutable_labels()->add_labels()->CopyFrom(createLabel("baz", "qux"));
 
   MockScheduler sched2;

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/hook_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hook_tests.cpp b/src/tests/hook_tests.cpp
index 02d8f80..5c8f601 100644
--- a/src/tests/hook_tests.cpp
+++ b/src/tests/hook_tests.cpp
@@ -1119,7 +1119,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(
 
   EXPECT_EQ(TEST_HOOK_CPUS, resources.cpus().get());
 
-  const string allocationRole = DEFAULT_FRAMEWORK_INFO.role();
+  const string allocationRole = DEFAULT_FRAMEWORK_INFO.roles(0);
   EXPECT_TRUE(resources.contains(
       allocatedResources(TEST_HOOK_ADDITIONAL_RESOURCES, allocationRole)));
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/master_allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_allocator_tests.cpp b/src/tests/master_allocator_tests.cpp
index d05ee44..c0593de 100644
--- a/src/tests/master_allocator_tests.cpp
+++ b/src/tests/master_allocator_tests.cpp
@@ -820,7 +820,7 @@ TYPED_TEST(MasterAllocatorTest, SlaveLost)
   EXPECT_EQ(Resources(resourceOffers.get()[0].resources()),
             allocatedResources(
                 Resources::parse(flags2.resources.get()).get(),
-                DEFAULT_FRAMEWORK_INFO.role()));
+                DEFAULT_FRAMEWORK_INFO.roles(0)));
 
   // Shut everything down.
   EXPECT_CALL(allocator, recoverResources(_, _, _, _))
@@ -1268,7 +1268,7 @@ TYPED_TEST(MasterAllocatorTest, RoleTest)
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo1.set_name("framework1");
   frameworkInfo1.set_user("user1");
-  frameworkInfo1.set_role("role1");
+  frameworkInfo1.set_roles(0, "role1");
 
   MockScheduler sched1;
   MesosSchedulerDriver driver1(
@@ -1287,7 +1287,7 @@ TYPED_TEST(MasterAllocatorTest, RoleTest)
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo2.set_name("framework2");
   frameworkInfo2.set_user("user2");
-  frameworkInfo2.set_role("role2");
+  frameworkInfo2.set_roles(0, "role2");
 
   MockScheduler sched2;
   MesosSchedulerDriver driver2(
@@ -1637,7 +1637,7 @@ TYPED_TEST(MasterAllocatorTest, RebalancedForUpdatedWeights)
   // and all resources will be offered to this framework since it is the only
   // framework running so far.
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo1.set_role("role1");
+  frameworkInfo1.set_roles(0, "role1");
   MockScheduler sched1;
   MesosSchedulerDriver driver1(
       &sched1, frameworkInfo1, master.get()->pid, DEFAULT_CREDENTIAL);
@@ -1667,7 +1667,7 @@ TYPED_TEST(MasterAllocatorTest, RebalancedForUpdatedWeights)
   // It will not get any offers due to all resources having outstanding offers
   // to framework1 when it registered.
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo2.set_role("role2");
+  frameworkInfo2.set_roles(0, "role2");
   MockScheduler sched2;
   MesosSchedulerDriver driver2(
       &sched2, frameworkInfo2, master.get()->pid, DEFAULT_CREDENTIAL);
@@ -1818,7 +1818,7 @@ TYPED_TEST(MasterAllocatorTest, DISABLED_NestedRoles)
   // Register a framework in the "a/b" role and launch a single task,
   // consuming all the resources on `slave1`.
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo1.set_role("a/b");
+  frameworkInfo1.set_roles(0, "a/b");
 
   MockScheduler sched1;
   MesosSchedulerDriver driver1(
@@ -1848,7 +1848,7 @@ TYPED_TEST(MasterAllocatorTest, DISABLED_NestedRoles)
   // Register a framework in the "a/c" role. It should not get any
   // offers, because there are no unused resources.
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo2.set_role("a/c");
+  frameworkInfo2.set_roles(0, "a/c");
 
   MockScheduler sched2;
   MesosSchedulerDriver driver2(
@@ -1867,7 +1867,7 @@ TYPED_TEST(MasterAllocatorTest, DISABLED_NestedRoles)
   // Register a framework in the "b/x" role. It should not get any
   // offers, because there are no unused resources.
   FrameworkInfo frameworkInfo3 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo3.set_role("b/x");
+  frameworkInfo3.set_roles(0, "b/x");
 
   MockScheduler sched3;
   MesosSchedulerDriver driver3(

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/master_authorization_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_authorization_tests.cpp b/src/tests/master_authorization_tests.cpp
index 5809bd9..d41e72e 100644
--- a/src/tests/master_authorization_tests.cpp
+++ b/src/tests/master_authorization_tests.cpp
@@ -993,7 +993,7 @@ TEST_F(MasterAuthorizationTest, AuthorizedRole)
   ASSERT_SOME(master);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("foo");
+  frameworkInfo.set_roles(0, "foo");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -1031,7 +1031,7 @@ TEST_F(MasterAuthorizationTest, UnauthorizedRole)
   ASSERT_SOME(master);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("foo");
+  frameworkInfo.set_roles(0, "foo");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -1369,7 +1369,7 @@ TYPED_TEST(MasterAuthorizerTest, FilterStateSummaryEndpoint)
 
   // Start framwork with user "bar".
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
   frameworkInfo.set_user(user);
 
   MockScheduler sched;
@@ -1501,7 +1501,7 @@ TYPED_TEST(MasterAuthorizerTest, FilterStateEndpoint)
 
   // Start framwork with user "bar".
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
   frameworkInfo.set_user(user);
 
   // Create an executor with user "bar".
@@ -1690,7 +1690,7 @@ TYPED_TEST(MasterAuthorizerTest, FilterFrameworksEndpoint)
 
   // Start framwork with user "bar".
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
   frameworkInfo.set_user("bar");
 
   // Create an executor with user "bar".
@@ -1881,7 +1881,7 @@ TYPED_TEST(MasterAuthorizerTest, FilterTasksEndpoint)
 
   // Start framwork with user "bar".
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role");
+  frameworkInfo.set_roles(0, "role");
   frameworkInfo.set_user(user);
 
   // Create an executor with user "bar".

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/master_quota_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_quota_tests.cpp b/src/tests/master_quota_tests.cpp
index 2c7ec5a..190de3e 100644
--- a/src/tests/master_quota_tests.cpp
+++ b/src/tests/master_quota_tests.cpp
@@ -112,11 +112,11 @@ protected:
   // Creates a FrameworkInfo with the specified role.
   FrameworkInfo createFrameworkInfo(const string& role)
   {
-    FrameworkInfo info;
+    FrameworkInfo info = DEFAULT_FRAMEWORK_INFO;
     info.set_user("user");
     info.set_name("framework" + process::ID::generate());
     info.mutable_id()->set_value(info.name());
-    info.set_role(role);
+    info.set_roles(0, role);
 
     return info;
   }

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/master_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_tests.cpp b/src/tests/master_tests.cpp
index b0678ad..c4320a4 100644
--- a/src/tests/master_tests.cpp
+++ b/src/tests/master_tests.cpp
@@ -833,7 +833,7 @@ TEST_F(MasterTest, RecoverResources)
 
   Resources executorResources = allocatedResources(
       Resources::parse("cpus:0.3;mem:200;ports:[5-8, 23-25]").get(),
-      DEFAULT_FRAMEWORK_INFO.role());
+      DEFAULT_FRAMEWORK_INFO.roles(0));
   executorInfo.mutable_resources()->MergeFrom(executorResources);
 
   TaskID taskId;
@@ -915,7 +915,7 @@ TEST_F(MasterTest, RecoverResources)
   EXPECT_NE(0u, offers->size());
 
   Resources slaveResources = Resources::parse(flags.resources.get()).get();
-  EXPECT_EQ(allocatedResources(slaveResources, DEFAULT_FRAMEWORK_INFO.role()),
+  EXPECT_EQ(allocatedResources(slaveResources, DEFAULT_FRAMEWORK_INFO.roles(0)),
             offers.get()[0].resources());
 
   driver.stop();
@@ -1925,11 +1925,8 @@ TEST_F(MasterTest, LaunchDifferentRoleLost)
   ASSERT_SOME(slave);
 
   FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
-  framework.clear_role();
-  framework.add_roles("role1");
+  framework.set_roles(0, "role1");
   framework.add_roles("role2");
-  framework.add_capabilities()->set_type(
-      FrameworkInfo::Capability::MULTI_ROLE);
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -3538,7 +3535,7 @@ TEST_F(MasterTest, IgnoreEphemeralPortsResource)
       Resources(offers.get()[0].resources()),
       allocatedResources(
           Resources::parse(resourcesWithoutEphemeralPorts).get(),
-          DEFAULT_FRAMEWORK_INFO.role()));
+          DEFAULT_FRAMEWORK_INFO.roles(0)));
 
   driver.stop();
   driver.join();
@@ -4050,13 +4047,16 @@ TEST_F(MasterTest, StateEndpointFrameworkInfo)
   AWAIT_READY(slaveRegisteredMessage);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo.clear_capabilities();
+
   frameworkInfo.set_webui_url("http://localhost:8080/");
 
   vector<FrameworkInfo::Capability::Type> capabilities = {
     FrameworkInfo::Capability::REVOCABLE_RESOURCES,
     FrameworkInfo::Capability::TASK_KILLING_STATE,
     FrameworkInfo::Capability::GPU_RESOURCES,
-    FrameworkInfo::Capability::PARTITION_AWARE
+    FrameworkInfo::Capability::PARTITION_AWARE,
+    FrameworkInfo::Capability::MULTI_ROLE,
   };
 
   foreach (FrameworkInfo::Capability::Type capability, capabilities) {
@@ -4132,7 +4132,7 @@ TEST_F(MasterTest, StateEndpointFrameworkInfo)
     .as<JSON::Array>().values[0].as<JSON::Object>();
 
   JSON::Object allocationInfo;
-  allocationInfo.values["role"] = frameworkInfo.role();
+  allocationInfo.values["role"] = frameworkInfo.roles(0);
 
   EXPECT_EQ(1u, offer.values.count("allocation_info"));
   EXPECT_EQ(allocationInfo, offer.values.at("allocation_info"));
@@ -4304,7 +4304,7 @@ TEST_F(MasterTest, StateEndpointAllocationRole)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("foo");
+  frameworkInfo.set_roles(0, "foo");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -4374,10 +4374,10 @@ TEST_F(MasterTest, StateEndpointAllocationRole)
       JSON::Array {
         JSON::Object {
           { "executors", JSON::Array {
-            JSON::Object { { "role", frameworkInfo.role() } } }
+            JSON::Object { { "role", frameworkInfo.roles(0) } } }
           },
           { "tasks", JSON::Array {
-            JSON::Object { { "role", frameworkInfo.role() } } }
+            JSON::Object { { "role", frameworkInfo.roles(0) } } }
           }
         }
       }
@@ -5451,7 +5451,7 @@ TEST_F(MasterTest, RejectFrameworkWithInvalidRole)
   FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
 
   // Add invalid role to the FrameworkInfo.
-  framework.set_role("/test/test1");
+  framework.set_roles(0, "/test/test1");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -6677,10 +6677,8 @@ TEST_F(MasterTest, MultiRoleFrameworkReceivesOffers)
   ASSERT_SOME(slave1);
 
   FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
-  framework.add_roles("role1");
+  framework.set_roles(0, "role1");
   framework.add_roles("role2");
-  framework.add_capabilities()->set_type(
-      FrameworkInfo::Capability::MULTI_ROLE);
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -6822,12 +6820,9 @@ TEST_F(MasterTest, MultiRoleSchedulerUnsubscribeFromRole)
   // capability, so we expect its tasks to continue running when the
   // partitioned agent reregisters.
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.clear_role();
-  frameworkInfo.add_roles("foo");
+  frameworkInfo.set_roles(0, "foo");
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::PARTITION_AWARE);
-  frameworkInfo.add_capabilities()->set_type(
-      FrameworkInfo::Capability::MULTI_ROLE);
 
   MockScheduler sched1;
   MesosSchedulerDriver driver1(

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/master_validation_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_validation_tests.cpp b/src/tests/master_validation_tests.cpp
index 3308803..5972c32 100644
--- a/src/tests/master_validation_tests.cpp
+++ b/src/tests/master_validation_tests.cpp
@@ -759,7 +759,7 @@ TEST_F(CreateOperationValidationTest, SharedVolumeBasedOnCapability)
   // When a FrameworkInfo with no SHARED_RESOURCES capability is
   // specified, the validation should fail.
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   error = operation::validate(create, Resources(), None(), frameworkInfo);
 
@@ -781,14 +781,14 @@ TEST_F(CreateOperationValidationTest, SharedVolumeBasedOnCapability)
 TEST_F(CreateOperationValidationTest, InsufficientDiskResource)
 {
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role("role1");
+  frameworkInfo.set_roles(0, "role1");
 
   master::Flags masterFlags = CreateMasterFlags();
 
   ACLs acls;
   mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
   acl->mutable_principals()->add_values(frameworkInfo.principal());
-  acl->mutable_roles()->add_values(frameworkInfo.role());
+  acl->mutable_roles()->add_values(frameworkInfo.roles(0));
 
   masterFlags.acls = acls;
   masterFlags.roles = "role1";
@@ -3333,7 +3333,8 @@ TEST_F(FrameworkInfoValidationTest, MissingMultiRoleCapability)
   ASSERT_SOME(master);
 
   FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
-  framework.add_roles("role");
+  framework.clear_capabilities();
+  framework.set_roles(0, "role");
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -3356,7 +3357,7 @@ TEST_F(FrameworkInfoValidationTest, AcceptMultiRoleFramework)
   ASSERT_SOME(master);
 
   FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
-  framework.add_roles("role1");
+  framework.set_roles(0, "role1");
   framework.add_roles("role2");
   framework.add_capabilities()->set_type(
       FrameworkInfo::Capability::MULTI_ROLE);
@@ -3386,7 +3387,7 @@ TEST_F(FrameworkInfoValidationTest, MultiRoleWhitelist)
   ASSERT_SOME(master);
 
   FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
-  framework.add_roles("role1");
+  framework.set_roles(0, "role1");
   framework.add_roles("role2");
   framework.add_capabilities()->set_type(
       FrameworkInfo::Capability::MULTI_ROLE);
@@ -3419,6 +3420,8 @@ TEST_F(FrameworkInfoValidationTest, UpgradeToMultiRole)
   ASSERT_SOME(master);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo.clear_capabilities();
+  frameworkInfo.clear_roles();
   frameworkInfo.set_role("role");
 
   // Set a long failover timeout so the framework isn't immediately removed.
@@ -3485,7 +3488,10 @@ TEST_F(FrameworkInfoValidationTest, DowngradeFromMultipleRoles)
   ASSERT_SOME(master);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.add_roles("role1");
+
+  frameworkInfo.clear_capabilities();
+
+  frameworkInfo.set_roles(0, "role1");
   frameworkInfo.add_roles("role2");
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::MULTI_ROLE);
@@ -3555,9 +3561,7 @@ TEST_F(FrameworkInfoValidationTest, RoleChangeWithMultiRole)
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
 
   ASSERT_FALSE(frameworkInfo.has_role());
-  frameworkInfo.add_roles("role1");
-  frameworkInfo.add_capabilities()->set_type(
-      FrameworkInfo::Capability::MULTI_ROLE);
+  frameworkInfo.set_roles(0, "role1");
 
   // Set a long failover timeout so the framework isn't immediately removed.
   frameworkInfo.set_failover_timeout(Weeks(1).secs());
@@ -3627,6 +3631,8 @@ TEST_F(FrameworkInfoValidationTest, RoleChangeWithMultiRoleMasterFailover)
   // immediately cleaned up.
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo.set_failover_timeout(Weeks(1).secs());
+  frameworkInfo.clear_capabilities();
+  frameworkInfo.clear_roles();
   frameworkInfo.set_role("role1");
 
   Future<FrameworkID> frameworkId;

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/mesos.hpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp
index 3c57f25..3b1d58e 100644
--- a/src/tests/mesos.hpp
+++ b/src/tests/mesos.hpp
@@ -439,6 +439,9 @@ struct DefaultFrameworkInfo
     framework.set_user(os::user().get());
     framework.set_principal(
         DefaultCredential<TCredential>::create().principal());
+    framework.add_roles("*");
+    framework.add_capabilities()->set_type(
+        TFrameworkInfo::Capability::MULTI_ROLE);
 
     return framework;
   }
@@ -1584,7 +1587,11 @@ ACTION_P5(LaunchTasks, executor, tasks, cpus, mem, role)
 
     Resources taskResources = Resources::parse(
         "cpus:" + stringify(cpus) + ";mem:" + stringify(mem)).get();
-    taskResources.allocate(role);
+
+    if (offer.resources_size() > 0 &&
+        offer.resources(0).has_allocation_info()) {
+      taskResources.allocate(role);
+    }
 
     int nextTaskId = 0;
     std::vector<TaskInfo> tasks;

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/oversubscription_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/oversubscription_tests.cpp b/src/tests/oversubscription_tests.cpp
index 25e2cdf..18bc49f 100644
--- a/src/tests/oversubscription_tests.cpp
+++ b/src/tests/oversubscription_tests.cpp
@@ -402,10 +402,10 @@ TEST_F(OversubscriptionTest, RevocableOffer)
   estimations.put(createRevocableResources("cpus", "2"));
 
   Resources taskResources = createRevocableResources("cpus", "1");
-  taskResources.allocate(framework.role());
+  taskResources.allocate(framework.roles(0));
 
   Resources executorResources = createRevocableResources("cpus", "1");
-  executorResources.allocate(framework.role());
+  executorResources.allocate(framework.roles(0));
 
   // Now the framework will get revocable resources.
   AWAIT_READY(offers2);
@@ -511,7 +511,7 @@ TEST_F(OversubscriptionTest, RescindRevocableOfferWithIncreasedRevocable)
   EXPECT_EQ(1u, offers.size());
   Future<Offer> offer = offers.get();
   AWAIT_READY(offer);
-  EXPECT_EQ(allocatedResources(resources1, framework.role()),
+  EXPECT_EQ(allocatedResources(resources1, framework.roles(0)),
             Resources(offer->resources()));
 
   Future<OfferID> offerId;
@@ -549,7 +549,7 @@ TEST_F(OversubscriptionTest, RescindRevocableOfferWithIncreasedRevocable)
   }
 
   // The offered resources should match the resource estimate.
-  EXPECT_EQ(allocatedResources(resources2, framework.role()), resources3);
+  EXPECT_EQ(allocatedResources(resources2, framework.roles(0)), resources3);
 
   driver.stop();
   driver.join();
@@ -624,8 +624,9 @@ TEST_F(OversubscriptionTest, RescindRevocableOfferWithDecreasedRevocable)
 
   // Now the framework will get revocable resources.
   AWAIT_READY(offers2);
-  EXPECT_NE(0u, offers2->size());
-  EXPECT_EQ(allocatedResources(resources1, framework.role()),
+
+  ASSERT_FALSE(offers2->empty());
+  EXPECT_EQ(allocatedResources(resources1, framework.roles(0)),
             Resources(offers2.get()[0].resources()));
 
   Future<OfferID> offerId;
@@ -655,8 +656,9 @@ TEST_F(OversubscriptionTest, RescindRevocableOfferWithDecreasedRevocable)
 
   // The new offer should include the latest oversubscribed resources.
   AWAIT_READY(offers3);
-  EXPECT_NE(0u, offers3->size());
-  EXPECT_EQ(allocatedResources(resources2, framework.role()),
+
+  ASSERT_FALSE(offers3->empty());
+  EXPECT_EQ(allocatedResources(resources2, framework.roles(0)),
             Resources(offers3.get()[0].resources()));
 
   driver.stop();
@@ -1286,8 +1288,9 @@ TEST_F(OversubscriptionTest, UpdateAllocatorOnSchedulerFailover)
   estimations.put(revocable);
 
   AWAIT_READY(offers2);
-  EXPECT_NE(0u, offers2->size());
-  EXPECT_EQ(allocatedResources(revocable, framework2.role()),
+
+  ASSERT_FALSE(offers2->empty());
+  EXPECT_EQ(allocatedResources(revocable, framework2.roles(0)),
             Resources(offers2.get()[0].resources()));
 
   EXPECT_EQ(DRIVER_STOPPED, driver2.stop());
@@ -1359,8 +1362,9 @@ TEST_F(OversubscriptionTest, RemoveCapabilitiesOnSchedulerFailover)
 
   // Now the framework will get revocable resources.
   AWAIT_READY(offers2);
-  EXPECT_NE(0u, offers2->size());
-  EXPECT_EQ(allocatedResources(revocable, framework1.role()),
+
+  ASSERT_FALSE(offers2->empty());
+  EXPECT_EQ(allocatedResources(revocable, framework1.roles(0)),
             Resources(offers2.get()[0].resources()));
 
   // Reregister the framework with removal of revocable resources capability.

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/partition_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/partition_tests.cpp b/src/tests/partition_tests.cpp
index 4ff4285..0b8f3b1 100644
--- a/src/tests/partition_tests.cpp
+++ b/src/tests/partition_tests.cpp
@@ -867,7 +867,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(
   Offer offer = offers.get()[0];
 
   Resources taskResources = Resources::parse("cpus:1;mem:512").get();
-  taskResources.allocate(DEFAULT_FRAMEWORK_INFO.role());
+  taskResources.allocate(DEFAULT_FRAMEWORK_INFO.roles(0));
 
   EXPECT_TRUE(Resources(offer.resources()).contains(taskResources));
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/persistent_volume_endpoints_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/persistent_volume_endpoints_tests.cpp b/src/tests/persistent_volume_endpoints_tests.cpp
index 1237d08..e9e579e 100644
--- a/src/tests/persistent_volume_endpoints_tests.cpp
+++ b/src/tests/persistent_volume_endpoints_tests.cpp
@@ -84,7 +84,7 @@ public:
   {
     master::Flags flags = MesosTest::CreateMasterFlags();
     flags.allocation_interval = Milliseconds(50);
-    flags.roles = createFrameworkInfo().role();
+    flags.roles = createFrameworkInfo().roles(0);
     return flags;
   }
 
@@ -92,7 +92,7 @@ public:
   FrameworkInfo createFrameworkInfo()
   {
     FrameworkInfo info = DEFAULT_FRAMEWORK_INFO;
-    info.set_role("role1");
+    info.set_roles(0, "role1");
     return info;
   }
 
@@ -171,7 +171,7 @@ TEST_F(PersistentVolumeEndpointsTest, StaticReservation)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   Future<OfferID> rescindedOfferId;
 
@@ -199,7 +199,7 @@ TEST_F(PersistentVolumeEndpointsTest, StaticReservation)
   offer = offers.get()[0];
 
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -233,7 +233,7 @@ TEST_F(PersistentVolumeEndpointsTest, DynamicReservation)
 
   Resources unreserved = Resources::parse("disk:1024").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -266,7 +266,7 @@ TEST_F(PersistentVolumeEndpointsTest, DynamicReservation)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   Future<OfferID> rescindedOfferId;
 
@@ -278,7 +278,7 @@ TEST_F(PersistentVolumeEndpointsTest, DynamicReservation)
 
   Resources volume = createPersistentVolume(
       Megabytes(64),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "path1",
       DEFAULT_CREDENTIAL.principal(),
@@ -303,7 +303,7 @@ TEST_F(PersistentVolumeEndpointsTest, DynamicReservation)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, offerRescinded(&driver, _))
     .WillOnce(FutureArg<1>(&rescindedOfferId));
@@ -355,7 +355,7 @@ TEST_F(PersistentVolumeEndpointsTest, DynamicReservationRoleMismatch)
 
   Resources unreserved = Resources::parse("disk:1024").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -385,9 +385,9 @@ TEST_F(PersistentVolumeEndpointsTest, DynamicReservationRoleMismatch)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
-  ASSERT_NE(frameworkInfo.role(), "role2");
+  ASSERT_NE(frameworkInfo.roles(0), "role2");
   Resources volume = createPersistentVolume(
       Megabytes(64),
       "role2",
@@ -437,7 +437,7 @@ TEST_F(PersistentVolumeEndpointsTest, UnreserveVolumeResources)
 
   Resources unreserved = Resources::parse("disk:1024").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -450,7 +450,7 @@ TEST_F(PersistentVolumeEndpointsTest, UnreserveVolumeResources)
 
   Resources volume = createPersistentVolume(
       Megabytes(64),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "path1",
       DEFAULT_CREDENTIAL.principal(),
@@ -728,7 +728,7 @@ TEST_F(PersistentVolumeEndpointsTest, NoHeader)
 
   Resources volume = createPersistentVolume(
       Megabytes(64),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "path1",
       None(),
@@ -903,7 +903,7 @@ TEST_F(PersistentVolumeEndpointsTest, GoodCreateAndDestroyACL)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   Future<OfferID> rescindedOfferId;
 
@@ -934,7 +934,7 @@ TEST_F(PersistentVolumeEndpointsTest, GoodCreateAndDestroyACL)
   offer = offers.get()[0];
 
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1133,7 +1133,7 @@ TEST_F(PersistentVolumeEndpointsTest, BadCreateAndDestroyACL)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   // The failed destruction attempt.
   Future<Response> destroyResponse = process::http::post(
@@ -1341,7 +1341,7 @@ TEST_F(PersistentVolumeEndpointsTest, GoodCreateAndDestroyACLBadCredential)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   // The failed destruction attempt.
   Future<Response> destroyResponse = process::http::post(
@@ -1575,11 +1575,10 @@ TEST_F(PersistentVolumeEndpointsTest, OfferCreateThenEndpointRemove)
   // Make a dynamic reservation for 512MB of disk.
   Resources unreserved = Resources::parse("disk:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   EXPECT_CALL(allocator, addFramework(_, _, _, _));
-
   EXPECT_CALL(sched, registered(_, _, _));
 
   Future<vector<Offer>> offers;
@@ -1614,12 +1613,12 @@ TEST_F(PersistentVolumeEndpointsTest, OfferCreateThenEndpointRemove)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   // Create a 1MB persistent volume.
   Resources volume = createPersistentVolume(
       Megabytes(1),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "volume_path",
       frameworkInfo.principal(),
@@ -1639,7 +1638,7 @@ TEST_F(PersistentVolumeEndpointsTest, OfferCreateThenEndpointRemove)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   Future<OfferID> rescindedOfferId;
 
@@ -1668,7 +1667,7 @@ TEST_F(PersistentVolumeEndpointsTest, OfferCreateThenEndpointRemove)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, offerRescinded(&driver, _))
     .WillOnce(FutureArg<1>(&rescindedOfferId));
@@ -1695,7 +1694,7 @@ TEST_F(PersistentVolumeEndpointsTest, OfferCreateThenEndpointRemove)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1731,7 +1730,7 @@ TEST_F(PersistentVolumeEndpointsTest, EndpointCreateThenOfferRemove)
   // Make a dynamic reservation for 512MB of disk.
   Resources unreserved = Resources::parse("disk:512").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -1745,7 +1744,7 @@ TEST_F(PersistentVolumeEndpointsTest, EndpointCreateThenOfferRemove)
   // Create a 1MB persistent volume.
   Resources volume = createPersistentVolume(
       Megabytes(1),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "volume_path",
       frameworkInfo.principal(),
@@ -1780,7 +1779,7 @@ TEST_F(PersistentVolumeEndpointsTest, EndpointCreateThenOfferRemove)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   // We use the filter explicitly here so that the resources will not
   // be filtered for 5 seconds (the default).
@@ -1802,7 +1801,7 @@ TEST_F(PersistentVolumeEndpointsTest, EndpointCreateThenOfferRemove)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(dynamicallyReserved, frameworkInfo.role())));
+      allocatedResources(dynamicallyReserved, frameworkInfo.roles(0))));
 
   EXPECT_CALL(sched, resourceOffers(&driver, _))
     .WillOnce(FutureArg<1>(&offers));
@@ -1817,7 +1816,7 @@ TEST_F(PersistentVolumeEndpointsTest, EndpointCreateThenOfferRemove)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(unreserved, frameworkInfo.role())));
+      allocatedResources(unreserved, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1868,7 +1867,7 @@ TEST_F(PersistentVolumeEndpointsTest, ReserveAndSlaveRemoval)
   // Reserve all CPUs on `slave1` via HTTP endpoint.
   Resources slave1Unreserved = Resources::parse("cpus:4").get();
   Resources slave1Reserved = slave1Unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -1907,7 +1906,7 @@ TEST_F(PersistentVolumeEndpointsTest, ReserveAndSlaveRemoval)
   // Use the offers API to reserve all CPUs on `slave2`.
   Resources slave2Unreserved = Resources::parse("cpus:3").get();
   Resources slave2Reserved = slave2Unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   for (size_t i = 0; i < offers->size(); i++) {
@@ -1987,7 +1986,7 @@ TEST_F(PersistentVolumeEndpointsTest, SlavesEndpointFullResources)
 
   Resources unreserved = Resources::parse("cpus:1;mem:512;disk:1024").get();
   Resources dynamicallyReserved = unreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   Future<Response> response = process::http::post(
@@ -2000,7 +1999,7 @@ TEST_F(PersistentVolumeEndpointsTest, SlavesEndpointFullResources)
 
   Resources volume = createPersistentVolume(
       Megabytes(64),
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       "id1",
       "path1",
       DEFAULT_CREDENTIAL.principal(),
@@ -2036,11 +2035,11 @@ TEST_F(PersistentVolumeEndpointsTest, SlavesEndpointFullResources)
   Offer offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   Resources taskUnreserved = Resources::parse("cpus:1;mem:256").get();
   Resources taskResources = taskUnreserved.flatten(
-      frameworkInfo.role(),
+      frameworkInfo.roles(0),
       createReservationInfo(DEFAULT_CREDENTIAL.principal())).get();
 
   TaskInfo taskInfo = createTask(offer.slave_id(), taskResources, "sleep 1000");

http://git-wip-us.apache.org/repos/asf/mesos/blob/5a87d51e/src/tests/persistent_volume_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/persistent_volume_tests.cpp b/src/tests/persistent_volume_tests.cpp
index 8f8bb26..3718841 100644
--- a/src/tests/persistent_volume_tests.cpp
+++ b/src/tests/persistent_volume_tests.cpp
@@ -15,6 +15,7 @@
 // limitations under the License.
 
 #include <list>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -68,6 +69,7 @@ using mesos::master::detector::MasterDetector;
 using mesos::master::detector::StandaloneMasterDetector;
 
 using std::list;
+using std::set;
 using std::string;
 using std::vector;
 
@@ -138,14 +140,16 @@ protected:
     master::Flags flags = CreateMasterFlags();
 
     ACLs acls;
-    hashset<string> roles;
+    set<string> roles;
 
     foreach (const FrameworkInfo& framework, frameworks) {
       mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
       acl->mutable_principals()->add_values(framework.principal());
-      acl->mutable_roles()->add_values(framework.role());
 
-      roles.insert(framework.role());
+      foreach (const string& role, protobuf::framework::getRoles(framework)) {
+        acl->mutable_roles()->add_values(role);
+        roles.insert(role);
+      }
     }
 
     flags.acls = acls;
@@ -255,11 +259,11 @@ TEST_P(PersistentVolumeTest, CreateAndDestroyPersistentVolumes)
   Clock::pause();
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -375,9 +379,9 @@ TEST_P(PersistentVolumeTest, CreateAndDestroyPersistentVolumes)
 
   // Expect that the offer contains the persistent volumes we created.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume1, frameworkInfo.role())));
+      allocatedResources(volume1, frameworkInfo.roles(0))));
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume2, frameworkInfo.role())));
+      allocatedResources(volume2, frameworkInfo.roles(0))));
 
   // Destroy `volume1`.
   driver.acceptOffers(
@@ -432,7 +436,7 @@ TEST_P(PersistentVolumeTest, ResourcesCheckpointing)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -498,7 +502,7 @@ TEST_P(PersistentVolumeTest, PreparePersistentVolume)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -567,7 +571,7 @@ TEST_P(PersistentVolumeTest, MasterFailover)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   MockScheduler sched;
   TestingMesosSchedulerDriver driver(&sched, &detector, frameworkInfo);
@@ -643,7 +647,7 @@ TEST_P(PersistentVolumeTest, MasterFailover)
   Offer offer2 = offers2.get()[0];
 
   EXPECT_TRUE(Resources(offer2.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -669,7 +673,7 @@ TEST_P(PersistentVolumeTest, IncompatibleCheckpointedResources)
   spawn(slave1);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   MockScheduler sched;
   MesosSchedulerDriver driver(
@@ -756,7 +760,7 @@ TEST_P(PersistentVolumeTest, AccessPersistentVolume)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 
@@ -869,7 +873,7 @@ TEST_P(PersistentVolumeTest, AccessPersistentVolume)
   offer = offers.get()[0];
 
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   Future<CheckpointResourcesMessage> checkpointMessage =
     FUTURE_PROTOBUF(CheckpointResourcesMessage(), _, _);
@@ -923,7 +927,7 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeMultipleTasks)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 
@@ -1037,7 +1041,7 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeRescindOnDestroy)
 
   // 1. Create framework1 so that all resources are offered to this framework.
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo1.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo1.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo1.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 
@@ -1115,7 +1119,7 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeRescindOnDestroy)
   // 3. Create framework2 of the same role. It would be offered resources
   //    recovered from the framework1 call.
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo2.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo2.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo2.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 
@@ -1137,9 +1141,9 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeRescindOnDestroy)
   Offer offer2 = offers2.get()[0];
 
   EXPECT_TRUE(Resources(offer2.resources()).contains(
-      allocatedResources(volume1, frameworkInfo2.role())));
+      allocatedResources(volume1, frameworkInfo2.roles(0))));
   EXPECT_TRUE(Resources(offer2.resources()).contains(
-      allocatedResources(volume2, frameworkInfo2.role())));
+      allocatedResources(volume2, frameworkInfo2.roles(0))));
 
   // 4. framework1 kills the task which results in an offer to framework1
   //    with the shared volumes. At this point, both frameworks will have
@@ -1162,9 +1166,9 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeRescindOnDestroy)
   offer1 = offers1.get()[0];
 
   EXPECT_TRUE(Resources(offer1.resources()).contains(
-      allocatedResources(volume1, frameworkInfo1.role())));
+      allocatedResources(volume1, frameworkInfo1.roles(0))));
   EXPECT_TRUE(Resources(offer1.resources()).contains(
-      allocatedResources(volume2, frameworkInfo1.role())));
+      allocatedResources(volume2, frameworkInfo1.roles(0))));
 
   // 5. DESTROY both the shared volumes via framework2 which would result
   //    in framework1 being rescinded the offer.
@@ -1205,7 +1209,7 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeMasterFailover)
 
   // Create the framework with SHARED_RESOURCES capability.
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 
@@ -1307,9 +1311,9 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeMasterFailover)
   EXPECT_TRUE(Resources(offer2.resources()).contains(
       allocatedResources(
           Resources::parse("cpus:1;mem:1024").get(),
-          frameworkInfo.role())));
+          frameworkInfo.roles(0))));
   EXPECT_TRUE(Resources(offer2.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1331,7 +1335,7 @@ TEST_P(PersistentVolumeTest, DestroyPersistentVolumeMultipleTasks)
   filters.set_refuse_seconds(0);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 
@@ -1556,7 +1560,7 @@ TEST_P(PersistentVolumeTest, SharedPersistentVolumeMultipleIterations)
 
   // 1. Create framework so that all resources are offered to this framework.
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo.add_capabilities()->set_type(
       FrameworkInfo::Capability::SHARED_RESOURCES);
 
@@ -1694,7 +1698,7 @@ TEST_P(PersistentVolumeTest, SlaveRecovery)
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo.set_checkpoint(true);
 
   MockScheduler sched;
@@ -1828,12 +1832,12 @@ TEST_P(PersistentVolumeTest, GoodACLCreateThenDestroy)
   filters.set_refuse_seconds(0);
 
   FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
   ASSERT_SOME(master);
@@ -1906,7 +1910,7 @@ TEST_P(PersistentVolumeTest, GoodACLCreateThenDestroy)
 
   // Check that the persistent volume was created successfully.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
   EXPECT_TRUE(os::exists(slave::paths::getPersistentVolumePath(
       slaveFlags.work_dir,
       volume)));
@@ -1938,7 +1942,7 @@ TEST_P(PersistentVolumeTest, GoodACLCreateThenDestroy)
 
   // Check that the persistent volume is not in the offer.
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
 
   driver.stop();
   driver.join();
@@ -1973,16 +1977,15 @@ TEST_P(PersistentVolumeTest, GoodACLNoPrincipal)
   filters.set_refuse_seconds(0);
 
   // Create a `FrameworkInfo` with no principal.
-  FrameworkInfo frameworkInfo;
-  frameworkInfo.set_name("no-principal");
-  frameworkInfo.set_user(os::user().get());
-  frameworkInfo.set_role(DEFAULT_TEST_ROLE);
+  FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo.clear_principal();
+  frameworkInfo.set_roles(0, DEFAULT_TEST_ROLE);
 
   // Create a master. Since the framework has no
   // principal, we don't authenticate frameworks.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
-  masterFlags.roles = frameworkInfo.role();
+  masterFlags.roles = frameworkInfo.roles(0);
   masterFlags.authenticate_frameworks = false;
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
@@ -2056,7 +2059,7 @@ TEST_P(PersistentVolumeTest, GoodACLNoPrincipal)
 
   // Check that the persistent volume was successfully created.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
   EXPECT_TRUE(os::exists(slave::paths::getPersistentVolumePath(
       slaveFlags.work_dir,
       volume)));
@@ -2086,7 +2089,7 @@ TEST_P(PersistentVolumeTest, GoodACLNoPrincipal)
 
   // Check that the persistent volume was not created
   EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo.role())));
+      allocatedResources(volume, frameworkInfo.roles(0))));
   EXPECT_FALSE(
       Resources(checkpointResources2->resources()).contains(volume));
 
@@ -2129,20 +2132,19 @@ TEST_P(PersistentVolumeTest, BadACLNoPrincipal)
   filters.set_refuse_seconds(0);
 
   // Create a `FrameworkInfo` with no principal.
-  FrameworkInfo frameworkInfo1;
-  frameworkInfo1.set_name("no-principal");
-  frameworkInfo1.set_user(os::user().get());
-  frameworkInfo1.set_role(DEFAULT_TEST_ROLE);
+  FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo1.clear_principal();
+  frameworkInfo1.set_roles(0, DEFAULT_TEST_ROLE);
 
   // Create a `FrameworkInfo` with a principal.
   FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo2.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo2.set_roles(0, DEFAULT_TEST_ROLE);
 
   // Create a master. Since one framework has no
   // principal, we don't authenticate frameworks.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
-  masterFlags.roles = frameworkInfo1.role();
+  masterFlags.roles = frameworkInfo1.roles(0);
   masterFlags.authenticate_frameworks = false;
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
@@ -2206,7 +2208,7 @@ TEST_P(PersistentVolumeTest, BadACLNoPrincipal)
 
     // Check that the persistent volume is not contained in this offer.
     EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo1.role())));
+      allocatedResources(volume, frameworkInfo1.roles(0))));
   }
 
   // Decline the offer and suppress so the second
@@ -2262,7 +2264,7 @@ TEST_P(PersistentVolumeTest, BadACLNoPrincipal)
 
   // Check that the persistent volume is contained in this offer.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo2.role())));
+      allocatedResources(volume, frameworkInfo2.roles(0))));
 
   // Decline and suppress offers to `driver2` so that
   // `driver1` can receive an offer.
@@ -2308,7 +2310,7 @@ TEST_P(PersistentVolumeTest, BadACLNoPrincipal)
   // the offer, we should also confirm that the Destroy operation failed for the
   // correct reason. See MESOS-5470.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo1.role())));
+      allocatedResources(volume, frameworkInfo1.roles(0))));
 
   driver1.stop();
   driver1.join();
@@ -2352,19 +2354,19 @@ TEST_P(PersistentVolumeTest, BadACLDropCreateAndDestroy)
 
   // Create a `FrameworkInfo` that cannot create or destroy volumes.
   FrameworkInfo frameworkInfo1 = DEFAULT_FRAMEWORK_INFO;
-  frameworkInfo1.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo1.set_roles(0, DEFAULT_TEST_ROLE);
 
   // Create a `FrameworkInfo` that can create volumes.
-  FrameworkInfo frameworkInfo2;
+  FrameworkInfo frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
   frameworkInfo2.set_name("creator-framework");
   frameworkInfo2.set_user(os::user().get());
-  frameworkInfo2.set_role(DEFAULT_TEST_ROLE);
+  frameworkInfo2.set_roles(0, DEFAULT_TEST_ROLE);
   frameworkInfo2.set_principal("creator-principal");
 
   // Create a master.
   master::Flags masterFlags = CreateMasterFlags();
   masterFlags.acls = acls;
-  masterFlags.roles = frameworkInfo1.role();
+  masterFlags.roles = frameworkInfo1.roles(0);
   masterFlags.authenticate_frameworks = false;
 
   Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
@@ -2428,7 +2430,7 @@ TEST_P(PersistentVolumeTest, BadACLDropCreateAndDestroy)
 
     // Check that the persistent volume is not contained in this offer.
     EXPECT_FALSE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo1.role())));
+      allocatedResources(volume, frameworkInfo1.roles(0))));
   }
 
   // Decline the offer and suppress so the second
@@ -2484,7 +2486,7 @@ TEST_P(PersistentVolumeTest, BadACLDropCreateAndDestroy)
 
   // Check that the persistent volume is contained in this offer.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo2.role())));
+      allocatedResources(volume, frameworkInfo2.roles(0))));
 
   // Decline and suppress offers to `driver2` so that
   // `driver1` can receive an offer.
@@ -2530,7 +2532,7 @@ TEST_P(PersistentVolumeTest, BadACLDropCreateAndDestroy)
   // the offer, we should also confirm that the Destroy operation failed for the
   // correct reason. See MESOS-5470.
   EXPECT_TRUE(Resources(offer.resources()).contains(
-      allocatedResources(volume, frameworkInfo1.role())));
+      allocatedResources(volume, frameworkInfo1.roles(0))));
 
   driver1.stop();
   driver1.join();