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 2016/04/08 05:14:50 UTC
[1/3] mesos git commit: Added benchmark for allocator metrics.
Repository: mesos
Updated Branches:
refs/heads/master 1fa6340f8 -> 69e2664c6
Added benchmark for allocator metrics.
Review: https://reviews.apache.org/r/44853/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/c409d5d2
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/c409d5d2
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/c409d5d2
Branch: refs/heads/master
Commit: c409d5d203f601f3487fa37e671bf2f9f6fbd730
Parents: 1fa6340
Author: Benjamin Bannier <be...@mesosphere.io>
Authored: Thu Apr 7 16:53:10 2016 -0700
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Thu Apr 7 17:22:59 2016 -0700
----------------------------------------------------------------------
src/tests/hierarchical_allocator_tests.cpp | 45 +++++++++++++++++++++++++
1 file changed, 45 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/c409d5d2/src/tests/hierarchical_allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp
index f4bda3a..964570c 100644
--- a/src/tests/hierarchical_allocator_tests.cpp
+++ b/src/tests/hierarchical_allocator_tests.cpp
@@ -3325,6 +3325,51 @@ TEST_F(HierarchicalAllocator_BENCHMARK_Test, ResourceLabels)
Clock::resume();
}
+
+// Measures the processing time required for the allocator metrics.
+//
+// TODO(bmahler): Add allocations to this benchmark.
+TEST_P(HierarchicalAllocator_BENCHMARK_Test, Metrics)
+{
+ size_t slaveCount = std::tr1::get<0>(GetParam());
+ size_t frameworkCount = std::tr1::get<1>(GetParam());
+
+ // Pause the clock because we want to manually drive the allocations.
+ Clock::pause();
+
+ initialize();
+
+ for (size_t i = 0; i < frameworkCount; i++) {
+ string role = stringify(i);
+ allocator->setQuota(role, createQuota(role, "cpus:1;mem:512;disk:256"));
+ }
+
+ for (size_t i = 0; i < frameworkCount; i++) {
+ FrameworkInfo framework = createFrameworkInfo(stringify(i));
+ allocator->addFramework(framework.id(), framework, {});
+ }
+
+ for (size_t i = 0; i < slaveCount; i++) {
+ SlaveInfo slave = createSlaveInfo("cpus:16;mem:2048;disk:1024");
+ allocator->addSlave(slave.id(), slave, None(), slave.resources(), {});
+ }
+
+ // Wait for all the `addSlave` operations to complete.
+ Clock::settle();
+
+ Stopwatch watch;
+
+ // TODO(bmahler): Avoid timing the JSON parsing here.
+ // Ideally we also avoid timing the HTTP layer.
+ watch.start();
+ JSON::Object metrics = Metrics();
+ watch.stop();
+
+ cout << "/metrics/snapshot took " << watch.elapsed()
+ << " for " << slaveCount << " slaves"
+ << " and " << frameworkCount << " frameworks" << endl;
+}
+
} // namespace tests {
} // namespace internal {
} // namespace mesos {
[2/3] mesos git commit: Added the quota sorter type to the allocator
template.
Posted by bm...@apache.org.
Added the quota sorter type to the allocator template.
Review: https://reviews.apache.org/r/45533/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/b1e2ef09
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/b1e2ef09
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/b1e2ef09
Branch: refs/heads/master
Commit: b1e2ef09ed3daaf84741a989e9e726b76020aff8
Parents: c409d5d
Author: Benjamin Bannier <be...@mesosphere.io>
Authored: Thu Apr 7 17:25:55 2016 -0700
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Thu Apr 7 17:26:57 2016 -0700
----------------------------------------------------------------------
src/master/allocator/mesos/hierarchical.cpp | 7 ++-----
src/master/allocator/mesos/hierarchical.hpp | 24 ++++++++++++++++--------
2 files changed, 18 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/b1e2ef09/src/master/allocator/mesos/hierarchical.cpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/mesos/hierarchical.cpp b/src/master/allocator/mesos/hierarchical.cpp
index a8d80b4..0de03c7 100644
--- a/src/master/allocator/mesos/hierarchical.cpp
+++ b/src/master/allocator/mesos/hierarchical.cpp
@@ -135,12 +135,9 @@ void HierarchicalAllocatorProcess::initialize(
// Resources for quota'ed roles are allocated separately and prior to
// non-quota'ed roles, hence a dedicated sorter for quota'ed roles is
- // necessary. We create an instance of the same sorter type we use for
- // all roles.
- //
- // TODO(alexr): Consider introducing a sorter type for quota'ed roles.
+ // necessary.
roleSorter.reset(roleSorterFactory());
- quotaRoleSorter.reset(roleSorterFactory());
+ quotaRoleSorter.reset(quotaRoleSorterFactory());
VLOG(1) << "Initialized hierarchical allocator process";
http://git-wip-us.apache.org/repos/asf/mesos/blob/b1e2ef09/src/master/allocator/mesos/hierarchical.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/mesos/hierarchical.hpp b/src/master/allocator/mesos/hierarchical.hpp
index be4ccff..29d0759 100644
--- a/src/master/allocator/mesos/hierarchical.hpp
+++ b/src/master/allocator/mesos/hierarchical.hpp
@@ -45,10 +45,13 @@ namespace allocator {
// We forward declare the hierarchical allocator process so that we
// can typedef an instantiation of it with DRF sorters.
-template <typename RoleSorter, typename FrameworkSorter>
+template <
+ typename RoleSorter,
+ typename FrameworkSorter,
+ typename QuotaRoleSorter>
class HierarchicalAllocatorProcess;
-typedef HierarchicalAllocatorProcess<DRFSorter, DRFSorter>
+typedef HierarchicalAllocatorProcess<DRFSorter, DRFSorter, DRFSorter>
HierarchicalDRFAllocatorProcess;
typedef MesosAllocator<HierarchicalDRFAllocatorProcess>
@@ -69,7 +72,8 @@ class HierarchicalAllocatorProcess : public MesosAllocatorProcess
public:
HierarchicalAllocatorProcess(
const std::function<Sorter*()>& _roleSorterFactory,
- const std::function<Sorter*()>& _frameworkSorterFactory)
+ const std::function<Sorter*()>& _frameworkSorterFactory,
+ const std::function<Sorter*()>& _quotaRoleSorterFactory)
: ProcessBase(process::ID::generate("hierarchical-allocator")),
initialized(false),
paused(true),
@@ -77,7 +81,8 @@ public:
roleSorter(NULL),
quotaRoleSorter(NULL),
roleSorterFactory(_roleSorterFactory),
- frameworkSorterFactory(_frameworkSorterFactory) {}
+ frameworkSorterFactory(_frameworkSorterFactory),
+ quotaRoleSorterFactory(_quotaRoleSorterFactory) {}
virtual ~HierarchicalAllocatorProcess() {}
@@ -448,10 +453,9 @@ protected:
hashmap<std::string, process::Owned<Sorter>> frameworkSorters;
// Factory functions for sorters.
- //
- // NOTE: `quotaRoleSorter` currently reuses `roleSorterFactory`.
const std::function<Sorter*()> roleSorterFactory;
const std::function<Sorter*()> frameworkSorterFactory;
+ const std::function<Sorter*()> quotaRoleSorterFactory;
};
@@ -461,7 +465,10 @@ protected:
// We map the templatized version of the `HierarchicalAllocatorProcess` to one
// that relies on sorter factories in the internal namespace. This allows us
// to keep the implemention of the allocator in the implementation file.
-template <typename RoleSorter, typename FrameworkSorter>
+template <
+ typename RoleSorter,
+ typename FrameworkSorter,
+ typename QuotaRoleSorter>
class HierarchicalAllocatorProcess
: public internal::HierarchicalAllocatorProcess
{
@@ -469,7 +476,8 @@ public:
HierarchicalAllocatorProcess()
: internal::HierarchicalAllocatorProcess(
[]() -> Sorter* { return new RoleSorter(); },
- []() -> Sorter* { return new FrameworkSorter(); }) {}
+ []() -> Sorter* { return new FrameworkSorter(); },
+ []() -> Sorter* { return new QuotaRoleSorter(); }) {}
};
} // namespace allocator {
[3/3] mesos git commit: Added dominant share metrics to the DRF
sorter.
Posted by bm...@apache.org.
Added dominant share metrics to the DRF sorter.
Review: https://reviews.apache.org/r/45534/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/69e2664c
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/69e2664c
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/69e2664c
Branch: refs/heads/master
Commit: 69e2664c6ef2e0eab85276d4a4eb8a0f8ade4ec3
Parents: b1e2ef0
Author: Benjamin Bannier <be...@mesosphere.io>
Authored: Thu Apr 7 18:02:53 2016 -0700
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Thu Apr 7 20:04:00 2016 -0700
----------------------------------------------------------------------
docs/monitoring.md | 7 ++
src/Makefile.am | 2 +
src/master/allocator/mesos/hierarchical.hpp | 4 +-
src/master/allocator/sorter/drf/metrics.cpp | 83 ++++++++++++++++++++
src/master/allocator/sorter/drf/metrics.hpp | 62 +++++++++++++++
src/master/allocator/sorter/drf/sorter.cpp | 14 ++++
src/master/allocator/sorter/drf/sorter.hpp | 12 +++
src/master/allocator/sorter/sorter.hpp | 14 +++-
src/tests/hierarchical_allocator_tests.cpp | 97 ++++++++++++++++++++++++
9 files changed, 293 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/docs/monitoring.md
----------------------------------------------------------------------
diff --git a/docs/monitoring.md b/docs/monitoring.md
index 76be328..38b4144 100644
--- a/docs/monitoring.md
+++ b/docs/monitoring.md
@@ -945,6 +945,13 @@ and resource allocations in the allocator.
</tr>
<tr>
<td>
+ <code>allocator/mesos/roles/<role>/shares/dominant</code>
+ </td>
+ <td>Dominant resource share for the role, exposed as a percentage (0.0-1.0)</td>
+ <td>Gauge</td>
+</tr>
+<tr>
+ <td>
<code>allocator/mesos/event_queue_dispatches</code>
</td>
<td>Number of dispatch events in the event queue</td>
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 71c4308..b7f3f36 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -643,6 +643,7 @@ libmesos_no_3rdparty_la_SOURCES += \
master/allocator/allocator.cpp \
master/allocator/mesos/hierarchical.cpp \
master/allocator/mesos/metrics.cpp \
+ master/allocator/sorter/drf/metrics.cpp \
master/allocator/sorter/drf/sorter.cpp \
master/contender/contender.cpp \
master/contender/standalone.cpp \
@@ -762,6 +763,7 @@ libmesos_no_3rdparty_la_SOURCES += \
master/allocator/mesos/hierarchical.hpp \
master/allocator/mesos/metrics.hpp \
master/allocator/sorter/sorter.hpp \
+ master/allocator/sorter/drf/metrics.hpp \
master/allocator/sorter/drf/sorter.hpp \
master/contender/standalone.hpp \
master/contender/zookeeper.hpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/master/allocator/mesos/hierarchical.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/mesos/hierarchical.hpp b/src/master/allocator/mesos/hierarchical.hpp
index 29d0759..3f5dff7 100644
--- a/src/master/allocator/mesos/hierarchical.hpp
+++ b/src/master/allocator/mesos/hierarchical.hpp
@@ -475,7 +475,9 @@ class HierarchicalAllocatorProcess
public:
HierarchicalAllocatorProcess()
: internal::HierarchicalAllocatorProcess(
- []() -> Sorter* { return new RoleSorter(); },
+ [this]() -> Sorter* {
+ return new RoleSorter(this->self(), "allocator/mesos/roles/");
+ },
[]() -> Sorter* { return new FrameworkSorter(); },
[]() -> Sorter* { return new QuotaRoleSorter(); }) {}
};
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/master/allocator/sorter/drf/metrics.cpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/sorter/drf/metrics.cpp b/src/master/allocator/sorter/drf/metrics.cpp
new file mode 100644
index 0000000..c793f32
--- /dev/null
+++ b/src/master/allocator/sorter/drf/metrics.cpp
@@ -0,0 +1,83 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "master/allocator/sorter/drf/metrics.hpp"
+
+#include <process/defer.hpp>
+
+#include <process/metrics/metrics.hpp>
+
+#include <stout/foreach.hpp>
+#include <stout/path.hpp>
+
+#include "master/allocator/sorter/drf/sorter.hpp"
+
+using std::string;
+
+using process::UPID;
+using process::defer;
+
+using process::metrics::Gauge;
+
+namespace mesos {
+namespace internal {
+namespace master {
+namespace allocator {
+
+Metrics::Metrics(
+ const UPID& _context,
+ DRFSorter& _sorter,
+ const std::string& _prefix)
+ : context(_context),
+ sorter(&_sorter),
+ prefix(_prefix) {}
+
+
+Metrics::~Metrics()
+{
+ foreachvalue (const Gauge& gauge, dominantShares) {
+ process::metrics::remove(gauge);
+ }
+}
+
+
+void Metrics::add(const string& client)
+{
+ CHECK(!dominantShares.contains(client));
+
+ Gauge gauge(
+ path::join(prefix, client, "/shares/", "/dominant"),
+ defer(context, [this, client]() {
+ return sorter->calculateShare(client);
+ }));
+
+ dominantShares.put(client, gauge);
+ process::metrics::add(gauge);
+}
+
+
+void Metrics::remove(const string& client)
+{
+ CHECK(dominantShares.contains(client));
+
+ process::metrics::remove(dominantShares.at(client));
+ dominantShares.erase(client);
+}
+
+} // namespace allocator {
+} // namespace master {
+} // namespace internal {
+} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/master/allocator/sorter/drf/metrics.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/sorter/drf/metrics.hpp b/src/master/allocator/sorter/drf/metrics.hpp
new file mode 100644
index 0000000..61568cb
--- /dev/null
+++ b/src/master/allocator/sorter/drf/metrics.hpp
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __MASTER_ALLOCATOR_SORTER_DRF_SORTER_METRICS_HPP__
+#define __MASTER_ALLOCATOR_SORTER_DRF_SORTER_METRICS_HPP__
+
+#include <string>
+
+#include <process/pid.hpp>
+
+#include <process/metrics/gauge.hpp>
+
+#include <stout/hashmap.hpp>
+
+namespace mesos {
+namespace internal {
+namespace master {
+namespace allocator {
+
+class DRFSorter;
+
+struct Metrics
+{
+ explicit Metrics(
+ const process::UPID& context,
+ DRFSorter& sorter,
+ const std::string& prefix);
+
+ ~Metrics();
+
+ void add(const std::string& client);
+ void remove(const std::string& client);
+
+ const process::UPID context;
+
+ DRFSorter* sorter;
+
+ const std::string prefix;
+
+ // Dominant share of each client.
+ hashmap<std::string, process::metrics::Gauge> dominantShares;
+};
+
+} // namespace allocator {
+} // namespace master {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __MASTER_ALLOCATOR_SORTER_DRF_SORTER_METRICS_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/master/allocator/sorter/drf/sorter.cpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/sorter/drf/sorter.cpp b/src/master/allocator/sorter/drf/sorter.cpp
index c14f9a4..d0efa4d 100644
--- a/src/master/allocator/sorter/drf/sorter.cpp
+++ b/src/master/allocator/sorter/drf/sorter.cpp
@@ -39,6 +39,12 @@ bool DRFComparator::operator()(const Client& client1, const Client& client2)
}
+DRFSorter::DRFSorter(
+ const process::UPID& allocator,
+ const std::string& metricsPrefix)
+ : metrics(Metrics(allocator, *this, metricsPrefix)) {}
+
+
void DRFSorter::add(const string& name, double weight)
{
Client client(name, 0, 0);
@@ -46,6 +52,10 @@ void DRFSorter::add(const string& name, double weight)
allocations[name] = Allocation();
weights[name] = weight;
+
+ if (metrics.isSome()) {
+ metrics->add(name);
+ }
}
@@ -66,6 +76,10 @@ void DRFSorter::remove(const string& name)
allocations.erase(name);
weights.erase(name);
+
+ if (metrics.isSome()) {
+ metrics->remove(name);
+ }
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/master/allocator/sorter/drf/sorter.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/sorter/drf/sorter.hpp b/src/master/allocator/sorter/drf/sorter.hpp
index f316bb5..05d5205 100644
--- a/src/master/allocator/sorter/drf/sorter.hpp
+++ b/src/master/allocator/sorter/drf/sorter.hpp
@@ -24,6 +24,8 @@
#include <stout/hashmap.hpp>
+#include "master/allocator/sorter/drf/metrics.hpp"
+
#include "master/allocator/sorter/sorter.hpp"
@@ -61,6 +63,12 @@ struct DRFComparator
class DRFSorter : public Sorter
{
public:
+ DRFSorter() = default;
+
+ explicit DRFSorter(
+ const process::UPID& allocator,
+ const std::string& metricsPrefix);
+
virtual ~DRFSorter() {}
virtual void add(const std::string& name, double weight = 1);
@@ -160,6 +168,10 @@ private:
// Maps client names to the resources they have been allocated.
hashmap<std::string, Allocation> allocations;
+
+ // Metrics are optionally exposed by the sorter.
+ friend Metrics;
+ Option<Metrics> metrics;
};
} // namespace allocator {
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/master/allocator/sorter/sorter.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/sorter/sorter.hpp b/src/master/allocator/sorter/sorter.hpp
index e2338d5..9e04adf 100644
--- a/src/master/allocator/sorter/sorter.hpp
+++ b/src/master/allocator/sorter/sorter.hpp
@@ -17,12 +17,15 @@
#ifndef __MASTER_ALLOCATOR_SORTER_SORTER_HPP__
#define __MASTER_ALLOCATOR_SORTER_SORTER_HPP__
+#include <functional>
#include <list>
#include <string>
#include <mesos/resources.hpp>
#include <mesos/type_utils.hpp>
+#include <process/pid.hpp>
+
namespace mesos {
namespace internal {
namespace master {
@@ -38,7 +41,16 @@ namespace allocator {
class Sorter
{
public:
- virtual ~Sorter() {}
+ Sorter() = default;
+
+ // Provides the allocator's execution context (via a UPID)
+ // and a name prefix in order to support metrics within the
+ // sorter implementation.
+ explicit Sorter(
+ const process::UPID& allocator,
+ const std::string& metricsPrefix) {}
+
+ virtual ~Sorter() = default;
// Adds a client to allocate resources to. A client
// may be a user or a framework.
http://git-wip-us.apache.org/repos/asf/mesos/blob/69e2664c/src/tests/hierarchical_allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp
index 964570c..a5dd57a 100644
--- a/src/tests/hierarchical_allocator_tests.cpp
+++ b/src/tests/hierarchical_allocator_tests.cpp
@@ -2745,6 +2745,103 @@ TEST_F(HierarchicalAllocatorTest, ActiveOfferFiltersMetrics)
}
+// Verifies that per-role dominant share metrics are correctly reported.
+TEST_F(HierarchicalAllocatorTest, DominantShareMetrics)
+{
+ // Pausing the clock is not necessary, but ensures that the test
+ // doesn't rely on the batch allocation in the allocator, which
+ // would slow down the test.
+ Clock::pause();
+
+ initialize();
+
+ // Register one agent and one framework. The framework will
+ // immediately receive receive an offer and make it have the
+ // maximum possible dominant share.
+ SlaveInfo agent1 = createSlaveInfo("cpus:1;mem:1024");
+ allocator->addSlave(agent1.id(), agent1, None(), agent1.resources(), {});
+
+ FrameworkInfo framework1 = createFrameworkInfo("roleA");
+ allocator->addFramework(framework1.id(), framework1, {});
+ Clock::settle();
+
+ JSON::Object expected;
+
+ expected.values = {
+ {"allocator/mesos/roles/roleA/shares/dominant", 1},
+ };
+
+ JSON::Value metrics = Metrics();
+ EXPECT_TRUE(metrics.contains(expected));
+
+ // Decline the offered resources and expect a zero share.
+ Future<Allocation> allocation = allocations.get();
+ AWAIT_READY(allocation);
+ allocator->recoverResources(
+ allocation->frameworkId,
+ agent1.id(),
+ allocation->resources.get(agent1.id()).get(),
+ None());
+ Clock::settle();
+
+ expected.values = {
+ {"allocator/mesos/roles/roleA/shares/dominant", 0},
+ };
+
+ metrics = Metrics();
+ EXPECT_TRUE(metrics.contains(expected));
+
+ // Register a second framework. This framework will receive
+ // offers as `framework1` has just declined an offer and the
+ // implicit filter has not yet timed out. The new framework
+ // will have the full share.
+ FrameworkInfo framework2 = createFrameworkInfo("roleB");
+ allocator->addFramework(framework2.id(), framework2, {});
+ Clock::settle();
+
+ expected.values = {
+ {"allocator/mesos/roles/roleA/shares/dominant", 0},
+ {"allocator/mesos/roles/roleB/shares/dominant", 1},
+ };
+
+ metrics = Metrics();
+ EXPECT_TRUE(metrics.contains(expected));
+
+ // Add a second, identical agent. Now `framework1` will
+ // receive an offer since it has the lowest dominant
+ // share. After the offer the dominant shares of
+ // `framework1` and `framework2` are equal.
+ SlaveInfo agent2 = createSlaveInfo("cpus:1;mem:1024");
+ allocator->addSlave(agent2.id(), agent2, None(), agent2.resources(), {});
+ Clock::settle();
+
+ expected.values = {
+ {"allocator/mesos/roles/roleA/shares/dominant", 0.5},
+ {"allocator/mesos/roles/roleB/shares/dominant", 0.5},
+ };
+
+ metrics = Metrics();
+ EXPECT_TRUE(metrics.contains(expected));
+
+ // Removing `framework2` frees up its allocated resources. The
+ // corresponding metric is removed when the last framework in
+ // the role is removed.
+ allocator->removeFramework(framework2.id());
+ Clock::settle();
+
+ expected.values = {
+ {"allocator/mesos/roles/roleA/shares/dominant", 0.5},
+ };
+
+ metrics = Metrics();
+ EXPECT_TRUE(metrics.contains(expected));
+
+ ASSERT_TRUE(metrics.is<JSON::Object>());
+ map<string, JSON::Value> values = metrics.as<JSON::Object>().values;
+ EXPECT_EQ(0u, values.count("allocator/mesos/roles/roleB/shares/dominant"));
+}
+
+
// This test ensures that resource allocation is done according to each role's
// weight. This is done by having six agents and three frameworks and making
// sure each framework gets the appropriate number of resources.