You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2015/11/16 17:18:17 UTC
[4/5] mesos git commit: Quota: Introduced capacity heuristic for
quota set requests.
Quota: Introduced capacity heuristic for quota set requests.
Review: https://reviews.apache.org/r/38110
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/8057cdcd
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/8057cdcd
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/8057cdcd
Branch: refs/heads/master
Commit: 8057cdcda27a6749020302f8dc56c4c8a3921922
Parents: 20bfb61
Author: Alexander Rukletsov <ru...@gmail.com>
Authored: Mon Nov 16 11:40:21 2015 +0100
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Mon Nov 16 17:05:17 2015 +0100
----------------------------------------------------------------------
src/master/master.hpp | 24 ++++++++++++--
src/master/quota_handler.cpp | 67 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 88 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/8057cdcd/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 64edf14..dc5790a 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -847,8 +847,6 @@ private:
class QuotaHandler
{
public:
- // TODO(joerg84): For now this is just a stub. It will be filled as
- // part of MESOS-1791.
explicit QuotaHandler(Master* _master) : master(_master)
{
CHECK_NOTNULL(master);
@@ -874,6 +872,28 @@ private:
}
private:
+ // Heuristically tries to determine whether a quota request could
+ // reasonably be satisfied given the current cluster capacity. The
+ // goal is to determine whether a user may accidentally request an
+ // amount of resources that would prevent frameworks without quota
+ // from getting any offers. A force flag will allow users to bypass
+ // this check.
+ //
+ // The heuristic tests whether the total quota, including the new
+ // request, does not exceed the sum of non-static cluster resources,
+ // i.e. the following inequality holds:
+ // total - statically reserved >= total quota + quota request
+ //
+ // Please be advised that:
+ // * It is up to an allocator how to satisfy quota (for example,
+ // what resources to account towards quota, as well as which
+ // resources to consider allocatable for quota).
+ // * Even if there are enough resources at the moment of this check,
+ // agents may terminate at any time, rendering the cluster under
+ // quota.
+ Option<Error> capacityHeuristic(
+ const mesos::quota::QuotaInfo& request) const;
+
// To perform actions related to quota management, we require access to the
// master data structures. No synchronization primitives are needed here
// since `QuotaHandler`'s functions are invoked in the Master's actor.
http://git-wip-us.apache.org/repos/asf/mesos/blob/8057cdcd/src/master/quota_handler.cpp
----------------------------------------------------------------------
diff --git a/src/master/quota_handler.cpp b/src/master/quota_handler.cpp
index da8c0ff..3db3c55 100644
--- a/src/master/quota_handler.cpp
+++ b/src/master/quota_handler.cpp
@@ -88,6 +88,67 @@ static Try<QuotaInfo> createQuotaInfo(
}
+Option<Error> Master::QuotaHandler::capacityHeuristic(
+ const QuotaInfo& request) const
+{
+ VLOG(1) << "Performing capacity heuristic check for a set quota request";
+
+ // This should have been validated earlier.
+ CHECK(master->roles.contains(request.role()));
+ CHECK(!master->quotas.contains(request.role()));
+
+ // Calculate the total amount of resources requested by all quotas
+ // (including the request) in the cluster.
+ // NOTE: We have validated earlier that the quota for the role in the
+ // request does not exist, hence `master->quotas` is guaranteed not to
+ // contain the request role's quota yet.
+ // TODO(alexr): Relax this constraint once we allow updating quotas.
+ Resources totalQuota = request.guarantee();
+ foreachvalue (const Quota& quota, master->quotas) {
+ totalQuota += quota.info.guarantee();
+ }
+
+ // Remove roles via `flatten()` to facilitate resource math.
+ totalQuota = totalQuota.flatten();
+
+ // Determine whether the total quota, including the new request, does
+ // not exceed the sum of non-static cluster resources.
+ // NOTE: We do not necessarily calculate the full sum of non-static
+ // cluster resources. We apply the early termination logic as it can
+ // reduce the cost of the function significantly. This early exit does
+ // not influence the declared inequality check.
+ Resources nonStaticClusterResources;
+ foreachvalue (Slave* slave, master->slaves.registered) {
+ // We do not consider disconnected or inactive agents, because they
+ // do not participate in resource allocation.
+ if (!slave->connected || !slave->active) {
+ continue;
+ }
+
+ // NOTE: Dynamic reservations are not excluded here because they do
+ // not show up in `SlaveInfo` resources. In contrast to static
+ // reservations, dynamic reservations may be unreserved at any time,
+ // hence making resources available for quota'ed frameworks.
+ Resources nonStaticAgentResources =
+ Resources(slave->info.resources()).unreserved();
+
+ nonStaticClusterResources += nonStaticAgentResources;
+
+ // If we have found enough resources to satisfy the inequality, then
+ // we can return early.
+ if (nonStaticClusterResources.contains(totalQuota)) {
+ return None();
+ }
+ }
+
+ // If we reached this point, there are not enough available resources
+ // in the cluster, hence the request does not pass the heuristic.
+ return Error(
+ "Not enough available cluster capacity to reasonably satisfy quota "
+ "request; the force flag can be used to override this check");
+}
+
+
Future<http::Response> Master::QuotaHandler::set(
const http::Request& request) const
{
@@ -159,7 +220,11 @@ Future<http::Response> Master::QuotaHandler::set(
const QuotaInfo& quotaInfo = create.get();
// Validate whether a quota request can be satisfied.
- // TODO(alexr): Implement as per MESOS-3073.
+ Option<Error> error = capacityHeuristic(quotaInfo);
+ if (error.isSome()) {
+ return Conflict("Heuristic capacity check for set quota request failed: " +
+ error.get().message);
+ }
// Populate master's quota-related local state. We do this before updating
// the registry in order to make sure that we are not already trying to