This is an automated email from the ASF dual-hosted git repository.

bmahler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit 697de69e9ebf3e5ffdad4a44118cdbdf24a8f39d
Author: Benjamin Mahler <[email protected]>
AuthorDate: Fri Jun 28 17:07:42 2019 -0400

    Added Role::consumedQuota to the master.
    
    Quota consumption is computed as follows:
    
      Allocation + Unallocated Reservation ==
      Reservations + Unreserved Allocation
    
    That is, reservations count towards quota regardless of whether
    they're allocated. Allocation counts towards quota. Offered resources
    *do not* count towards quota, this is to (1) provide stability of the
    quota consumption metrics in the face of offers flowing in and out,
    and (2) to ensure that we treat offers as rescindable and therefore
    not yet "counting" towards quota. Also, if in the future schedulers
    are offered more than their quota to improve their choices, counting
    offered resources as consumed quota will be problematic.
    
    Review: https://reviews.apache.org/r/71029
---
 src/master/framework.cpp |  2 +-
 src/master/master.hpp    | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/src/master/framework.cpp b/src/master/framework.cpp
index c35de25..e69a7c2 100644
--- a/src/master/framework.cpp
+++ b/src/master/framework.cpp
@@ -646,7 +646,7 @@ void Framework::trackUnderRole(const std::string& role)
   CHECK(!isTrackedUnderRole(role));
 
   if (!master->roles.contains(role)) {
-    master->roles[role] = new Role(role);
+    master->roles[role] = new Role(master, role);
   }
   master->roles.at(role)->addFramework(this);
 }
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 6da02b8..b57483c 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -27,6 +27,7 @@
 
 #include <mesos/mesos.hpp>
 #include <mesos/resources.hpp>
+#include <mesos/roles.hpp>
 #include <mesos/type_utils.hpp>
 
 #include <mesos/maintenance/maintenance.hpp>
@@ -1954,6 +1955,7 @@ private:
   friend struct Framework;
   friend struct FrameworkMetrics;
   friend struct Metrics;
+  friend struct Role;
   friend struct Slave;
   friend struct SlavesWriter;
   friend struct Subscriber;
@@ -2687,7 +2689,9 @@ struct Role
 {
   Role() = delete;
 
-  Role(const std::string& _role) : role(_role) {}
+  Role(const Master* _master,
+       const std::string& _role)
+    : master(_master), role(_role) {}
 
   void addFramework(Framework* framework)
   {
@@ -2699,6 +2703,63 @@ struct Role
     frameworks.erase(framework->id());
   }
 
+  // TODO(bmahler): Include non-scalar quantities.
+  //
+  // TODO(bmahler): This function is somewhat expensive,
+  // it should ideally migrate into a field updated in an
+  // event-driven manner within a role tree structure. Or,
+  // at least compute the overall tree when looping over
+  // all agents rather than looping over all agents for
+  // each role.
+  ResourceQuantities consumedQuota() const
+  {
+    const std::string& role = this->role; // For cleaner captures.
+
+    // Consumed quota = allocation + unallocated reservation.
+
+    ResourceQuantities allocation;
+
+    auto allocatedToRoleSubtree = [&role](const Resource& r) {
+      CHECK(r.has_allocation_info());
+      return r.allocation_info().role() == role ||
+        roles::isStrictSubroleOf(r.allocation_info().role(), role);
+    };
+
+    // Loop over all frameworks since `frameworks` only tracks
+    // those that are directly subscribed to this role, and we
+    // need to sum all descendant role allocations.
+    foreachvalue (Framework* framework, master->frameworks.registered) {
+      allocation += ResourceQuantities::fromScalarResources(
+        framework->totalUsedResources.scalars()
+          .filter(allocatedToRoleSubtree));
+    }
+
+    ResourceQuantities unallocatedReservation;
+
+    auto reservedToRoleSubtree = [&role](const Resource& r) {
+      return Resources::isReserved(r) &&
+        (Resources::reservationRole(r) == role ||
+         roles::isStrictSubroleOf(Resources::reservationRole(r), role));
+    };
+
+    foreachvalue (Slave* slave, master->slaves.registered) {
+      ResourceQuantities totalReservation =
+        ResourceQuantities::fromScalarResources(
+           slave->totalResources.scalars()
+             .filter(reservedToRoleSubtree));
+
+       ResourceQuantities usedReservation;
+       foreachvalue (const Resources& r, slave->usedResources) {
+         usedReservation += ResourceQuantities::fromScalarResources(
+             r.scalars().filter(reservedToRoleSubtree));
+       }
+
+       unallocatedReservation += totalReservation - usedReservation;
+     }
+
+    return allocation + unallocatedReservation;
+  }
+
   Resources allocatedAndOfferedResources() const
   {
     Resources resources;
@@ -2718,6 +2779,7 @@ struct Role
     return resources;
   }
 
+  const Master* master;
   const std::string role;
 
   // NOTE: The dynamic role/quota relation is stored in and administrated

Reply via email to