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/02/03 00:12:57 UTC
[2/3] mesos git commit: Cleanups to the allocator tests.
Cleanups to the allocator tests.
This was necessary to greatly simplify the changes needed to the
allocator tests as we introduce support for multi-role frameworks.
The main improvement here is to establish and use equality on the
`Allocation` struct, which makes the tests more readable and avoids
the manual probing of the allocation structure across all the tests.
Review: https://reviews.apache.org/r/55868
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/33fd4608
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/33fd4608
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/33fd4608
Branch: refs/heads/master
Commit: 33fd4608b1430238ff8dbc00314a8c1e4b5a748d
Parents: ec12ed5
Author: Benjamin Mahler <bm...@apache.org>
Authored: Mon Jan 23 18:07:18 2017 -0800
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Thu Feb 2 15:49:27 2017 -0800
----------------------------------------------------------------------
src/tests/hierarchical_allocator_tests.cpp | 1071 ++++++++++++-----------
1 file changed, 561 insertions(+), 510 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/33fd4608/src/tests/hierarchical_allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp
index 3ecedb8..1e0b945 100644
--- a/src/tests/hierarchical_allocator_tests.cpp
+++ b/src/tests/hierarchical_allocator_tests.cpp
@@ -66,6 +66,7 @@ using std::atomic;
using std::cout;
using std::endl;
using std::map;
+using std::ostream;
using std::set;
using std::string;
using std::vector;
@@ -79,11 +80,34 @@ namespace tests {
struct Allocation
{
+ Allocation() = default;
+
+ Allocation(
+ const FrameworkID& frameworkId_,
+ const hashmap<SlaveID, Resources>& resources_)
+ : frameworkId(frameworkId_),
+ resources(resources_) {}
+
FrameworkID frameworkId;
hashmap<SlaveID, Resources> resources;
};
+bool operator==(const Allocation& left, const Allocation& right)
+{
+ return left.frameworkId == right.frameworkId &&
+ left.resources == right.resources;
+}
+
+
+ostream& operator<<(ostream& stream, const Allocation& allocation)
+{
+ return stream
+ << "FrameworkID: " << allocation.frameworkId
+ << " Resource Allocation: " << stringify(allocation.resources);
+}
+
+
struct Deallocation
{
FrameworkID frameworkId;
@@ -261,10 +285,11 @@ TEST_F(HierarchicalAllocatorTest, UnreservedDRF)
FrameworkInfo framework1 = createFrameworkInfo("role1");
allocator->addFramework(framework1.id(), framework1, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(slave1.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{slave1.id(), slave1.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 1 (cpus=2, mem=1024)
// framework1 share = 1
@@ -282,10 +307,11 @@ TEST_F(HierarchicalAllocatorTest, UnreservedDRF)
// framework2 will be offered all of slave2's resources since role2
// has the lowest user share, and framework2 is its only framework.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(slave2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{slave2.id(), slave2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 0.67 (cpus=2, mem=1024)
// framework1 share = 1
@@ -302,10 +328,11 @@ TEST_F(HierarchicalAllocatorTest, UnreservedDRF)
// framework2 will be offered all of slave3's resources since role2
// has the lowest share.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(slave3.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{slave3.id(), slave3.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 0.33 (cpus=2, mem=1024)
// framework1 share = 1
@@ -327,10 +354,11 @@ TEST_F(HierarchicalAllocatorTest, UnreservedDRF)
// framework3 will be offered all of slave4's resources since role1
// has the lowest user share, and framework3 has the lowest share of
// role1's frameworks.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework3.id(), allocation->frameworkId);
- EXPECT_EQ(slave4.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework3.id(),
+ {{slave4.id(), slave4.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 0.67 (cpus=6, mem=5120)
// framework1 share = 0.33 (cpus=2, mem=1024)
@@ -353,10 +381,11 @@ TEST_F(HierarchicalAllocatorTest, UnreservedDRF)
// Even though framework4 doesn't have any resources, role2 has a
// lower share than role1, so framework2 receives slave5's resources.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(slave5.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{slave5.id(), slave5.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -379,10 +408,11 @@ TEST_F(HierarchicalAllocatorTest, ReservedDRF)
FrameworkInfo framework1 = createFrameworkInfo("role1");
allocator->addFramework(framework1.id(), framework1, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(slave1.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{slave1.id(), slave1.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
FrameworkInfo framework2 = createFrameworkInfo("role2");
allocator->addFramework(framework2.id(), framework2, {}, true);
@@ -391,20 +421,22 @@ TEST_F(HierarchicalAllocatorTest, ReservedDRF)
SlaveInfo slave2 = createSlaveInfo("cpus:2;mem:512;disk:0");
allocator->addSlave(slave2.id(), slave2, None(), slave2.resources(), {});
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(slave2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{slave2.id(), slave2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Since `framework1` has more resources allocated to it than `framework2`,
// We expect `framework2` to receive this agent's resources.
SlaveInfo slave3 = createSlaveInfo("cpus:2;mem:512;disk:0");
allocator->addSlave(slave3.id(), slave3, None(), slave3.resources(), {});
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(slave3.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{slave3.id(), slave3.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Now add another framework in role1. Since the reserved resources
// should be allocated fairly between frameworks within a role, we
@@ -417,10 +449,11 @@ TEST_F(HierarchicalAllocatorTest, ReservedDRF)
"cpus(role1):2;mem(role1):1024;disk(role1):0");
allocator->addSlave(slave4.id(), slave4, None(), slave4.resources(), {});
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework3.id(), allocation->frameworkId);
- EXPECT_EQ(slave4.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework3.id(),
+ {{slave4.id(), slave4.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -455,10 +488,11 @@ TEST_F(HierarchicalAllocatorTest, DRFWithFairnessExclusion)
allocator->addFramework(framework1.id(), framework1, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent1.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{agent1.id(), agent1.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 1 (cpus=2, mem=1024, (ignored) gpus=1)
// framework1 share = 1
@@ -476,10 +510,11 @@ TEST_F(HierarchicalAllocatorTest, DRFWithFairnessExclusion)
// framework2 will be offered all of agent2's resources since role2
// has the lowest user share, and framework2 is its only framework.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 0.67 (cpus=2, mem=1024, (ignored) gpus=1)
// framework1 share = 1
@@ -496,10 +531,11 @@ TEST_F(HierarchicalAllocatorTest, DRFWithFairnessExclusion)
// framework2 will be offered all of agent3's resources since role2
// has the lowest share.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent3.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{agent3.id(), agent3.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 0.33 (cpus=2, mem=1024, (ignored)gpus=1)
// framework1 share = 1
@@ -521,10 +557,11 @@ TEST_F(HierarchicalAllocatorTest, DRFWithFairnessExclusion)
// framework3 will be offered all of agent4's resources since role1
// has the lowest user share, and framework3 has the lowest share of
// role1's frameworks.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework3.id(), allocation->frameworkId);
- EXPECT_EQ(agent4.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework3.id(),
+ {{agent4.id(), agent4.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// role1 share = 0.67 (cpus=6, mem=5120, (ignored) gpus=1)
// framework1 share = 0.33 (cpus=2, mem=1024, (ignored) gpus=1)
@@ -547,10 +584,11 @@ TEST_F(HierarchicalAllocatorTest, DRFWithFairnessExclusion)
// Even though framework4 doesn't have any resources, role2 has a
// lower share than role1, so framework2 receives agent5's resources.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent5.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{agent5.id(), agent5.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -577,10 +615,13 @@ TEST_F(HierarchicalAllocatorTest, OfferFilter)
// `framework` will be offered all of `agent` resources
// because it is the only framework in the cluster.
+ Allocation expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
+
// Now `framework` declines the offer and sets a filter
// with the duration greater than the allocation interval.
@@ -591,7 +632,7 @@ TEST_F(HierarchicalAllocatorTest, OfferFilter)
allocator->recoverResources(
framework.id(),
agent.id(),
- allocation->resources.get(agent.id()).get(),
+ allocation->resources.at(agent.id()),
offerFilter);
// Ensure the offer filter timeout is set before advancing the clock.
@@ -609,7 +650,7 @@ TEST_F(HierarchicalAllocatorTest, OfferFilter)
// There should be no allocation due to the offer filter.
allocation = allocations.get();
- ASSERT_TRUE(allocation.isPending());
+ EXPECT_TRUE(allocation.isPending());
// Ensure the offer filter times out (2x the allocation interval)
// and the next batch allocation occurs.
@@ -617,9 +658,11 @@ TEST_F(HierarchicalAllocatorTest, OfferFilter)
Clock::settle();
// The next batch allocation should offer resources to `framework1`.
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocation);
metrics = Metrics();
@@ -664,7 +707,7 @@ TEST_F(HierarchicalAllocatorTest, SmallOfferFilterTimeout)
agent1,
None(),
agent1.resources(),
- {std::make_pair(framework1.id(), agent1.resources())});
+ {{framework1.id(), agent1.resources()}});
// Process all triggered allocation events.
//
@@ -685,10 +728,13 @@ TEST_F(HierarchicalAllocatorTest, SmallOfferFilterTimeout)
// `framework2` will be offered all of `agent2` resources
// because its share (0) is smaller than `framework1`.
+ Allocation expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), agent2.resources()}});
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
+
// Total cluster resources (2 agents): cpus=2, mem=1024.
// ROLE1 share = 1 (cpus=2, mem=1024)
@@ -706,7 +752,7 @@ TEST_F(HierarchicalAllocatorTest, SmallOfferFilterTimeout)
allocator->recoverResources(
framework2.id(),
agent2.id(),
- allocation->resources.get(agent2.id()).get(),
+ allocation->resources.at(agent2.id()),
offerFilter);
// Total cluster resources (2 agents): cpus=2, mem=1024.
@@ -728,10 +774,12 @@ TEST_F(HierarchicalAllocatorTest, SmallOfferFilterTimeout)
// Since the filter is applied, resources are offered to `framework1`
// even though its share is greater than `framework2`.
+ expected = Allocation(
+ framework1.id(),
+ {{agent2.id(), agent2.resources()}});
+
allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Total cluster resources (2 agents): cpus=2, mem=1024.
// ROLE1 share = 1 (cpus=2, mem=1024)
@@ -745,7 +793,7 @@ TEST_F(HierarchicalAllocatorTest, SmallOfferFilterTimeout)
allocator->recoverResources(
framework1.id(),
agent2.id(),
- allocation->resources.get(agent2.id()).get(),
+ allocation->resources.at(agent2.id()),
None());
// Total cluster resources (2 agents): cpus=2, mem=1024.
@@ -757,10 +805,12 @@ TEST_F(HierarchicalAllocatorTest, SmallOfferFilterTimeout)
Clock::advance(flags.allocation_interval);
// Since the filter is removed, resources are offered to `framework2`.
+ expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), agent2.resources()}});
+
allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Total cluster resources (2 agents): cpus=2, mem=1024.
// ROLE1 share = 1 (cpus=2, mem=1024)
@@ -789,10 +839,11 @@ TEST_F(HierarchicalAllocatorTest, MaintenanceInverseOffers)
allocator->addFramework(framework.id(), framework, {}, true);
// Check that the resources go to the framework.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
const process::Time start = Clock::now() + Seconds(60);
@@ -845,11 +896,15 @@ TEST_F(HierarchicalAllocatorTest, CoarseGrained)
FrameworkInfo framework1 = createFrameworkInfo("role1");
allocator->addFramework(framework1.id(), framework1, {}, true);
+ Allocation expected = Allocation(
+ framework1.id(),
+ {
+ {slave1.id(), slave1.resources()},
+ {slave2.id(), slave2.resources()}
+ });
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(slave1.resources() + slave2.resources(),
- Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
allocator->recoverResources(
framework1.id(),
@@ -880,14 +935,14 @@ TEST_F(HierarchicalAllocatorTest, CoarseGrained)
// NOTE: `slave1` and `slave2` have the same resources, we don't care
// which framework received which slave, only that they each received one.
ASSERT_TRUE(frameworkAllocations.contains(framework1.id()));
- ASSERT_EQ(1u, frameworkAllocations[framework1.id()].resources.size());
- EXPECT_EQ(slave1.resources(),
- Resources::sum(frameworkAllocations[framework1.id()].resources));
+
+ allocation = frameworkAllocations.at(framework1.id());
+ EXPECT_EQ(slave1.resources(), Resources::sum(allocation->resources));
ASSERT_TRUE(frameworkAllocations.contains(framework2.id()));
- ASSERT_EQ(1u, frameworkAllocations[framework2.id()].resources.size());
- EXPECT_EQ(slave2.resources(),
- Resources::sum(frameworkAllocations[framework2.id()].resources));
+
+ allocation = frameworkAllocations.at(framework2.id());
+ EXPECT_EQ(slave2.resources(), Resources::sum(allocation->resources));
}
@@ -917,10 +972,14 @@ TEST_F(HierarchicalAllocatorTest, SameShareFairness)
for (int i = 0; i < 10; i++) {
Future<Allocation> allocation = allocations.get();
AWAIT_READY(allocation);
- counts[allocation->frameworkId]++;
- ASSERT_EQ(1u, allocation->resources.size());
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ allocation->frameworkId,
+ {{slave.id(), slave.resources()}});
+
+ EXPECT_EQ(expected, allocation.get());
+
+ counts[allocation->frameworkId]++;
allocator->recoverResources(
allocation->frameworkId,
@@ -963,26 +1022,24 @@ TEST_F(HierarchicalAllocatorTest, Reservations)
FrameworkInfo framework1 = createFrameworkInfo("role1");
allocator->addFramework(framework1.id(), framework1, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(2u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave1.id()));
- EXPECT_TRUE(allocation->resources.contains(slave2.id()));
- EXPECT_EQ(slave1.resources() + Resources(slave2.resources()).unreserved(),
- Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework1.id(),
+ {
+ {slave1.id(), slave1.resources()},
+ {slave2.id(), Resources(slave2.resources()).unreserved()}
+ });
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// framework2 should get all of its reserved resources on slave2.
FrameworkInfo framework2 = createFrameworkInfo("role2");
allocator->addFramework(framework2.id(), framework2, {}, true);
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave2.id()));
- EXPECT_EQ(Resources(slave2.resources()).reserved("role2"),
- Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{slave2.id(), Resources(slave2.resources()).reserved("role2")}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -1002,15 +1059,16 @@ TEST_F(HierarchicalAllocatorTest, RecoverResources)
FrameworkInfo framework = createFrameworkInfo("role1");
allocator->addFramework(framework.id(), framework, {}, true);
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Recover the reserved resources, expect them to be re-offered.
- Resources reserved = Resources(slave.resources()).reserved("role1");
+ Resources reserved = allocation->resources.at(slave.id()).reserved("role1");
+ Resources unreserved = allocation->resources.at(slave.id()).unreserved();
allocator->recoverResources(
allocation->frameworkId,
@@ -1020,16 +1078,14 @@ TEST_F(HierarchicalAllocatorTest, RecoverResources)
Clock::advance(flags.allocation_interval);
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), reserved}});
+
allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(reserved, Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Recover the unreserved resources, expect them to be re-offered.
- Resources unreserved = Resources(slave.resources()).unreserved();
-
allocator->recoverResources(
allocation->frameworkId,
slave.id(),
@@ -1038,12 +1094,12 @@ TEST_F(HierarchicalAllocatorTest, RecoverResources)
Clock::advance(flags.allocation_interval);
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), unreserved}});
+
allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(unreserved, Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -1073,12 +1129,11 @@ TEST_F(HierarchicalAllocatorTest, Allocatable)
"disk:128");
allocator->addSlave(slave2.id(), slave2, None(), slave2.resources(), {});
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave2.id()));
- EXPECT_EQ(slave2.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave2.id(), slave2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Enough memory to be considered allocatable.
SlaveInfo slave3 = createSlaveInfo(
@@ -1087,12 +1142,11 @@ TEST_F(HierarchicalAllocatorTest, Allocatable)
"disk:128");
allocator->addSlave(slave3.id(), slave3, None(), slave3.resources(), {});
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave3.id()));
- EXPECT_EQ(slave3.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave3.id(), slave3.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// slave4 has enough cpu and memory to be considered allocatable,
// but it lies across unreserved and reserved resources!
@@ -1104,12 +1158,11 @@ TEST_F(HierarchicalAllocatorTest, Allocatable)
"disk:128");
allocator->addSlave(slave4.id(), slave4, None(), slave4.resources(), {});
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave4.id()));
- EXPECT_EQ(slave4.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave4.id(), slave4.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -1128,12 +1181,12 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocation)
FrameworkInfo framework = createFrameworkInfo("role1");
allocator->addFramework(framework.id(), framework, {}, true);
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Construct an offer operation for the framework's allocation.
Resource volume = Resources::parse("disk", "5", "*").get();
@@ -1146,7 +1199,7 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocation)
// Ensure the offer operation can be applied.
Try<Resources> updated =
- Resources::sum(allocation->resources).apply(create);
+ allocation->resources.at(slave.id()).apply(create);
ASSERT_SOME(updated);
@@ -1154,7 +1207,7 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocation)
allocator->updateAllocation(
framework.id(),
slave.id(),
- Resources::sum(allocation->resources),
+ allocation->resources.at(slave.id()),
{create});
// Now recover the resources, and expect the next allocation to
@@ -1167,21 +1220,15 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocation)
Clock::advance(flags.allocation_interval);
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
// The allocation should be the slave's resources with the offer
// operation applied.
- updated = Resources(slave.resources()).apply(create);
- ASSERT_SOME(updated);
-
- EXPECT_NE(Resources(slave.resources()),
- Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), updated.get()}});
- EXPECT_EQ(updated.get(), Resources::sum(allocation->resources));
+ allocation = allocations.get();
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -1203,12 +1250,12 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocationSharedPersistentVolume)
allocator->addFramework(
framework.id(), framework, hashmap<SlaveID, Resources>(), true);
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Construct an offer operation for the framework's allocation.
// Create a shared volume.
@@ -1218,7 +1265,7 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocationSharedPersistentVolume)
// Ensure the offer operation can be applied.
Try<Resources> update =
- Resources::sum(allocation->resources).apply(create);
+ allocation->resources.at(slave.id()).apply(create);
ASSERT_SOME(update);
@@ -1226,7 +1273,7 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocationSharedPersistentVolume)
allocator->updateAllocation(
framework.id(),
slave.id(),
- Resources::sum(allocation->resources),
+ allocation->resources.at(slave.id()),
{create});
// Now recover the resources, and expect the next allocation to
@@ -1239,21 +1286,14 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocationSharedPersistentVolume)
Clock::advance(flags.allocation_interval);
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
-
// The allocation should be the slave's resources with the offer
// operation applied.
- update = Resources(slave.resources()).apply(create);
- ASSERT_SOME(update);
-
- EXPECT_NE(Resources(slave.resources()),
- Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), update.get()}});
- EXPECT_EQ(update.get(), Resources::sum(allocation->resources));
+ allocation = allocations.get();
+ AWAIT_EXPECT_EQ(expected, allocation);
// Construct an offer operation for the framework's allocation to
// destroy the shared volume.
@@ -1263,31 +1303,28 @@ TEST_F(HierarchicalAllocatorTest, UpdateAllocationSharedPersistentVolume)
allocator->updateAllocation(
framework.id(),
slave.id(),
- Resources::sum(allocation->resources),
+ allocation->resources.at(slave.id()),
{destroy});
// The resources to recover should be equal to the agent's original
// resources now that the shared volume is created and then destroyed.
- ASSERT_SOME_EQ(slave.resources(), update->apply(destroy));
+ update = update->apply(destroy);
+ ASSERT_SOME_EQ(slave.resources(), update);
- // Now recover the amount of `slave.resources()` and expect the
- // next allocation to equal `slave.resources()`.
allocator->recoverResources(
framework.id(),
slave.id(),
- slave.resources(),
+ update.get(),
None());
Clock::advance(flags.allocation_interval);
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), update.get()}});
- EXPECT_EQ(Resources(slave.resources()),
- Resources::sum(allocation->resources));
+ allocation = allocations.get();
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -1307,12 +1344,12 @@ TEST_F(HierarchicalAllocatorTest, SharedResourcesCapability)
allocator->addFramework(framework1.id(), framework1, {}, true);
// Initially, all the resources are allocated to `framework1`.
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{slave.id(), slave.resources()}});
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Create a shared volume.
Resource volume = createDiskResource(
@@ -1321,7 +1358,7 @@ TEST_F(HierarchicalAllocatorTest, SharedResourcesCapability)
// Ensure the offer operation can be applied.
Try<Resources> update =
- Resources::sum(allocation->resources).apply(create);
+ allocation->resources.at(slave.id()).apply(create);
ASSERT_SOME(update);
@@ -1329,7 +1366,7 @@ TEST_F(HierarchicalAllocatorTest, SharedResourcesCapability)
allocator->updateAllocation(
framework1.id(),
slave.id(),
- Resources::sum(allocation->resources),
+ allocation->resources.at(slave.id()),
{create});
// Now recover the resources, and expect the next allocation to
@@ -1344,12 +1381,12 @@ TEST_F(HierarchicalAllocatorTest, SharedResourcesCapability)
// opted in for SHARED_RESOURCES.
Clock::advance(flags.allocation_interval);
+ expected = Allocation(
+ framework1.id(),
+ {{slave.id(), update.get() - volume}});
+
allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_TRUE(allocation->resources.at(slave.id()).shared().empty());
+ AWAIT_EXPECT_EQ(expected, allocation);
// Recover the resources for the offer in the next allocation cycle.
allocator->recoverResources(
@@ -1368,12 +1405,12 @@ TEST_F(HierarchicalAllocatorTest, SharedResourcesCapability)
// has opted in for SHARED_RESOURCES.
Clock::advance(flags.allocation_interval);
+ expected = Allocation(
+ framework2.id(),
+ {{slave.id(), update.get()}});
+
allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(allocation->resources.at(slave.id()).shared(), Resources(volume));
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -1393,29 +1430,24 @@ TEST_F(HierarchicalAllocatorTest, UpdateAvailableSuccess)
Offer::Operation reserve = RESERVE(dynamicallyReserved);
+ Try<Resources> update = Resources(slave.resources()).apply(reserve);
+ ASSERT_SOME(update);
+ EXPECT_NE(Resources(slave.resources()), update.get());
+
// Update the allocation in the allocator.
- Future<Nothing> update = allocator->updateAvailable(slave.id(), {reserve});
- AWAIT_EXPECT_READY(update);
+ AWAIT_READY(allocator->updateAvailable(slave.id(), {reserve}));
// Expect to receive the updated available resources.
FrameworkInfo framework = createFrameworkInfo("role1");
allocator->addFramework(framework.id(), framework, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
-
// The allocation should be the slave's resources with the offer
// operation applied.
- Try<Resources> updated = Resources(slave.resources()).apply(reserve);
- ASSERT_SOME(updated);
-
- EXPECT_NE(Resources(slave.resources()),
- Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), update.get()}});
- EXPECT_EQ(updated.get(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -1432,12 +1464,11 @@ TEST_F(HierarchicalAllocatorTest, UpdateAvailableFail)
FrameworkInfo framework = createFrameworkInfo("role1");
allocator->addFramework(framework.id(), framework, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Construct an offer operation for the framework's allocation.
Resources unreserved = Resources::parse("cpus:25;mem:50").get();
@@ -1447,8 +1478,7 @@ TEST_F(HierarchicalAllocatorTest, UpdateAvailableFail)
Offer::Operation reserve = RESERVE(dynamicallyReserved);
// Update the allocation in the allocator.
- Future<Nothing> update = allocator->updateAvailable(slave.id(), {reserve});
- AWAIT_EXPECT_FAILED(update);
+ AWAIT_FAILED(allocator->updateAvailable(slave.id(), {reserve}));
}
@@ -1471,28 +1501,33 @@ TEST_F(HierarchicalAllocatorTest, UpdateSlave)
allocator->addFramework(framework.id(), framework, {}, true);
// Initially, all the resources are allocated.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Update the slave with 10 oversubscribed cpus.
Resources oversubscribed = createRevocableResources("cpus", "10");
allocator->updateSlave(slave.id(), oversubscribed);
// The next allocation should be for 10 oversubscribed resources.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(oversubscribed, Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), oversubscribed}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Update the slave again with 12 oversubscribed cpus.
Resources oversubscribed2 = createRevocableResources("cpus", "12");
allocator->updateSlave(slave.id(), oversubscribed2);
// The next allocation should be for 2 oversubscribed cpus.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(oversubscribed2 - oversubscribed,
- Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), oversubscribed2 - oversubscribed}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Update the slave again with 5 oversubscribed cpus.
Resources oversubscribed3 = createRevocableResources("cpus", "5");
@@ -1501,8 +1536,9 @@ TEST_F(HierarchicalAllocatorTest, UpdateSlave)
// Since there are no more available oversubscribed resources there
// shouldn't be an allocation.
Clock::settle();
- allocation = allocations.get();
- ASSERT_TRUE(allocation.isPending());
+
+ Future<Allocation> allocation = allocations.get();
+ EXPECT_TRUE(allocation.isPending());
}
@@ -1523,9 +1559,11 @@ TEST_F(HierarchicalAllocatorTest, OversubscribedNotAllocated)
allocator->addFramework(framework.id(), framework, {}, true);
// Initially, all the resources are allocated.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Update the slave with 10 oversubscribed cpus.
Resources oversubscribed = createRevocableResources("cpus", "10");
@@ -1534,8 +1572,9 @@ TEST_F(HierarchicalAllocatorTest, OversubscribedNotAllocated)
// No allocation should be made for oversubscribed resources because
// the framework has not opted in for them.
Clock::settle();
- allocation = allocations.get();
- ASSERT_TRUE(allocation.isPending());
+
+ Future<Allocation> allocation = allocations.get();
+ EXPECT_TRUE(allocation.isPending());
}
@@ -1558,18 +1597,22 @@ TEST_F(HierarchicalAllocatorTest, RecoverOversubscribedResources)
allocator->addFramework(framework.id(), framework, {}, true);
// Initially, all the resources are allocated.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Update the slave with 10 oversubscribed cpus.
Resources oversubscribed = createRevocableResources("cpus", "10");
allocator->updateSlave(slave.id(), oversubscribed);
// The next allocation should be for 10 oversubscribed cpus.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(oversubscribed, Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), oversubscribed}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Recover 6 oversubscribed cpus and 2 regular cpus.
Resources recovered = createRevocableResources("cpus", "6");
@@ -1581,9 +1624,11 @@ TEST_F(HierarchicalAllocatorTest, RecoverOversubscribedResources)
// The next allocation should be for 6 oversubscribed and 2 regular
// cpus.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(recovered, Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{slave.id(), recovered}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -1623,11 +1668,11 @@ TEST_F(HierarchicalAllocatorTest, Whitelist)
Clock::advance(flags.allocation_interval);
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{slave.id(), slave.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -1759,10 +1804,11 @@ TEST_F(HierarchicalAllocatorTest, QuotaProvidesGuarantee)
// `framework1` will be offered all of `agent1`'s resources because it is
// the only framework in the only role with unsatisfied quota.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent1.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{agent1.id(), agent1.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources: cpus=1, mem=512.
// QUOTA_ROLE share = 1 (cpus=1, mem=512) [quota: cpus=2, mem=1024]
@@ -1776,10 +1822,12 @@ TEST_F(HierarchicalAllocatorTest, QuotaProvidesGuarantee)
// `framework1` will again be offered all of `agent2`'s resources
// because it is the only framework in the only role with unsatisfied
// quota. `framework2` has to wait.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework1.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ Future<Allocation> allocation = allocations.get();
+ AWAIT_EXPECT_EQ(expected, allocation);
// Total cluster resources: cpus=2, mem=1024.
// QUOTA_ROLE share = 1 (cpus=2, mem=1024) [quota: cpus=2, mem=1024]
@@ -1798,7 +1846,7 @@ TEST_F(HierarchicalAllocatorTest, QuotaProvidesGuarantee)
allocator->recoverResources(
framework1.id(),
agent2.id(),
- allocation->resources.get(agent2.id()).get(),
+ allocation->resources.at(agent2.id()),
offerFilter);
// Total cluster resources: cpus=2, mem=1024.
@@ -1816,16 +1864,18 @@ TEST_F(HierarchicalAllocatorTest, QuotaProvidesGuarantee)
// There should be no allocation due to the offer filter.
allocation = allocations.get();
- ASSERT_TRUE(allocation.isPending());
+ EXPECT_TRUE(allocation.isPending());
// Ensure the offer filter times out (2x the allocation interval)
// and the next batch allocation occurs.
Clock::advance(flags.allocation_interval);
// Previously declined resources should be offered to the quota'ed role.
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework1.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocation);
// Total cluster resources: cpus=2, mem=1024.
// QUOTA_ROLE share = 1 (cpus=2, mem=1024) [quota: cpus=2, mem=1024]
@@ -1864,7 +1914,7 @@ TEST_F(HierarchicalAllocatorTest, RemoveQuota)
agent1,
None(),
agent1.resources(),
- {std::make_pair(framework1.id(), agent1.resources())});
+ {{framework1.id(), agent1.resources()}});
SlaveInfo agent2 = createSlaveInfo("cpus:1;mem:512;disk:0");
allocator->addSlave(
@@ -1872,7 +1922,7 @@ TEST_F(HierarchicalAllocatorTest, RemoveQuota)
agent2,
None(),
agent2.resources(),
- {std::make_pair(framework1.id(), agent2.resources())});
+ {{framework1.id(), agent2.resources()}});
// Total cluster resources (2 identical agents): cpus=2, mem=1024.
// QUOTA_ROLE share = 1 (cpus=2, mem=1024) [quota: cpus=2, mem=1024]
@@ -1901,10 +1951,11 @@ TEST_F(HierarchicalAllocatorTest, RemoveQuota)
// Trigger the next batch allocation.
Clock::advance(flags.allocation_interval);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent1.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework2.id(),
+ {{agent1.id(), agent1.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources: cpus=2, mem=1024.
// QUOTA_ROLE share = 0.5 (cpus=1, mem=512)
@@ -1967,10 +2018,11 @@ TEST_F(HierarchicalAllocatorTest, MultipleFrameworksInRoleWithQuota)
// `framework1a` will be offered all of `agent1`'s resources because
// it is the only framework in the only role with unsatisfied quota.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1a.id(), allocation->frameworkId);
- EXPECT_EQ(agent1.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework1a.id(),
+ {{agent1.id(), agent1.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources: cpus=1, mem=512.
// QUOTA_ROLE share = 1 (cpus=1, mem=512) [quota: cpus=2, mem=1024]
@@ -1988,10 +2040,11 @@ TEST_F(HierarchicalAllocatorTest, MultipleFrameworksInRoleWithQuota)
// `framework1b` will be offered all of `agent2`'s resources
// (coarse-grained allocation) because its share is 0 and it belongs
// to a role with unsatisfied quota.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1b.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework1b.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources: cpus=3, mem=1536.
// QUOTA_ROLE share = 1 (cpus=3, mem=1536) [quota: cpus=4, mem=2048]
@@ -2006,10 +2059,11 @@ TEST_F(HierarchicalAllocatorTest, MultipleFrameworksInRoleWithQuota)
// `framework1a` will be offered all of `agent3`'s resources because
// its share is less than `framework1b`'s and `QUOTA_ROLE` still
// has unsatisfied quota.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1a.id(), allocation->frameworkId);
- EXPECT_EQ(agent3.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework1a.id(),
+ {{agent3.id(), agent3.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources: cpus=4, mem=2048.
// QUOTA_ROLE share = 1 (cpus=4, mem=2048) [quota: cpus=4, mem=2048]
@@ -2031,10 +2085,12 @@ TEST_F(HierarchicalAllocatorTest, MultipleFrameworksInRoleWithQuota)
// Trigger the next batch allocation.
Clock::advance(flags.allocation_interval);
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1b.id(), allocation->frameworkId);
- EXPECT_EQ(agent3.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework1b.id(),
+ {{agent3.id(), agent3.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
+
// Total cluster resources: cpus=4, mem=2048.
// QUOTA_ROLE share = 1 (cpus=4, mem=2048) [quota: cpus=4, mem=2048]
@@ -2084,11 +2140,11 @@ TEST_F(HierarchicalAllocatorTest, QuotaAllocationGranularity)
// `framework1` will be offered all of `agent`'s resources because
// it is the only framework in the only role with unsatisfied quota
// and the allocator performs coarse-grained allocation.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
- EXPECT_TRUE(Resources(agent.resources()).contains(quota.info.guarantee()));
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources: cpus=1, mem=512.
// QUOTA_ROLE share = 1 (cpus=1, mem=512) [quota: cpus=0.5, mem=200]
@@ -2150,7 +2206,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(HierarchicalAllocatorTest, DRFWithQuota)
agent1,
None(),
agent1.resources(),
- {std::make_pair(framework1.id(), Resources(quota.info.guarantee()))});
+ {{framework1.id(), Resources(quota.info.guarantee())}});
// Total cluster resources (1 agent): cpus=1, mem=512.
// QUOTA_ROLE share = 0.25 (cpus=0.25, mem=128) [quota: cpus=0.25, mem=128]
@@ -2164,11 +2220,11 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(HierarchicalAllocatorTest, DRFWithQuota)
// `framework2` will be offered all of `agent1`'s resources because its
// share is 0.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent1.resources() - Resources(quota.info.guarantee()),
- Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework2.id(),
+ {{agent1.id(), Resources(agent1.resources()) - quota.info.guarantee()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
metrics = Metrics();
@@ -2205,10 +2261,12 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(HierarchicalAllocatorTest, DRFWithQuota)
// `framework2` will be offered all of `agent2`'s resources (coarse-grained
// allocation). `framework1` does not receive them even though it has a
// smaller allocation, since we have already satisfied its role's quota.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+
+ expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -2246,12 +2304,7 @@ TEST_F(HierarchicalAllocatorTest, QuotaAgainstStarvation)
agent1,
None(),
agent1.resources(),
- {std::make_pair(framework1.id(), agent1.resources())});
-
- // Process all triggered allocation events.
- //
- // NOTE: No allocations happen because all resources are already allocated.
- Clock::settle();
+ {{framework1.id(), agent1.resources()}});
// Total cluster resources (1 agent): cpus=1, mem=512.
// QUOTA_ROLE share = 1 (cpus=1, mem=512)
@@ -2265,10 +2318,11 @@ TEST_F(HierarchicalAllocatorTest, QuotaAgainstStarvation)
// Free cluster resources on `agent2` will be allocated to `framework2`
// because its share is 0.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources (2 identical agents): cpus=2, mem=1024.
// QUOTA_ROLE share = 0.5 (cpus=1, mem=512)
@@ -2296,10 +2350,11 @@ TEST_F(HierarchicalAllocatorTest, QuotaAgainstStarvation)
// Trigger the next batch allocation.
Clock::advance(flags.allocation_interval);
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// `framework2` continues declining offers.
allocator->recoverResources(
@@ -2315,10 +2370,11 @@ TEST_F(HierarchicalAllocatorTest, QuotaAgainstStarvation)
// Since `QUOTA_ROLE` is under quota, `agent2`'s resources will
// be allocated to `framework1`.
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework1.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources: cpus=2, mem=1024.
// QUOTA_ROLE share = 1 (cpus=2, mem=1024) [quota: cpus=2, mem=1024]
@@ -2385,10 +2441,12 @@ TEST_F(HierarchicalAllocatorTest, QuotaAbsentFramework)
// `agent2`, `framework` is not allocated anything. However, we
// can't easily test for the absence of an allocation from the
// framework side, so we make due with this instead.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent2.resources(), Resources::sum(allocation->resources));
+
+ Allocation expected = Allocation(
+ framework.id(),
+ {{agent2.id(), agent2.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources (2 agents): cpus=3, mem=1536.
// QUOTA_ROLE share = 0 [quota: cpus=2, mem=1024], but
@@ -2435,10 +2493,11 @@ TEST_F(HierarchicalAllocatorTest, MultiQuotaAbsentFrameworks)
// Due to the coarse-grained nature of the allocations, `framework` will
// get all `agent`'s resources.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -2486,7 +2545,7 @@ TEST_F(HierarchicalAllocatorTest, MultiQuotaWithFrameworks)
agent1,
None(),
agent1.resources(),
- {std::make_pair(framework1.id(), agent1.resources())});
+ {{framework1.id(), agent1.resources()}});
SlaveInfo agent2 = createSlaveInfo("cpus:1;mem:1024;disk:0");
allocator->addSlave(
@@ -2494,8 +2553,10 @@ TEST_F(HierarchicalAllocatorTest, MultiQuotaWithFrameworks)
agent2,
None(),
agent2.resources(),
- {std::make_pair(framework2.id(), agent2.resources())});
+ {{framework2.id(), agent2.resources()}});
+ // TODO(bmahler): Add assertions to test this is accurate!
+ //
// Total cluster resources (2 identical agents): cpus=2, mem=2048.
// QUOTA_ROLE1 share = 0.5 (cpus=1, mem=1024) [quota: cpus=1, mem=200]
// framework1 share = 1
@@ -2511,10 +2572,11 @@ TEST_F(HierarchicalAllocatorTest, MultiQuotaWithFrameworks)
// `framework2` will get all agent3's resources because its role is under
// quota, while other roles' quotas are satisfied.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(agent3.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework2.id(),
+ {{agent3.id(), agent3.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Total cluster resources (3 agents): cpus=4, mem=4096.
// QUOTA_ROLE1 share = 0.25 (cpus=1, mem=1024) [quota: cpus=1, mem=200]
@@ -2561,19 +2623,19 @@ TEST_F(HierarchicalAllocatorTest, ReservationWithinQuota)
agent1,
None(),
agent1.resources(),
- {std::make_pair(
+ {{
framework1.id(),
// The `mem` portion is used to test that reserved resources are
// accounted for, and the `cpus` portion is allocated to show that
// the result of DRF would be different if `mem` was not accounted.
- Resources::parse("cpus:2;mem(" + QUOTA_ROLE + "):256").get())});
+ Resources::parse("cpus:2;mem(" + QUOTA_ROLE + "):256").get()
+ }});
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
+ Allocation expected = Allocation(
+ framework2.id(),
+ {{agent1.id(), Resources::parse("cpus:6").get()}});
- EXPECT_EQ(Resources::parse("cpus:6").get(),
- Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Since the reserved resources account towards the quota as well as being
// accounted for DRF, we expect these resources to also be allocated to
@@ -2581,12 +2643,11 @@ TEST_F(HierarchicalAllocatorTest, ReservationWithinQuota)
SlaveInfo agent2 = createSlaveInfo("cpus:4");
allocator->addSlave(agent2.id(), agent2, None(), agent2.resources(), {});
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
+ expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), agent2.resources()}});
- EXPECT_EQ(Resources::parse("cpus:4").get(),
- Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -2634,10 +2695,11 @@ TEST_F(HierarchicalAllocatorTest, QuotaSetAsideReservedResources)
// `framework1` will be offered resources at `agent1` because the
// resources at `agent2` are reserved for a different role.
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(agent1.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{agent1.id(), agent1.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// `framework1` declines the resources on `agent1` for the duration
// of the test.
@@ -2655,7 +2717,7 @@ TEST_F(HierarchicalAllocatorTest, QuotaSetAsideReservedResources)
Clock::advance(flags.allocation_interval);
Clock::settle();
- allocation = allocations.get();
+ Future<Allocation> allocation = allocations.get();
EXPECT_TRUE(allocation.isPending());
// Create `framework2` in a non-quota'ed role.
@@ -2664,9 +2726,11 @@ TEST_F(HierarchicalAllocatorTest, QuotaSetAsideReservedResources)
// `framework2` will be offered the reserved resources at `agent2`
// because those resources are reserved for its role.
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(dynamicallyReserved, Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework2.id(),
+ {{agent2.id(), dynamicallyReserved}});
+
+ AWAIT_EXPECT_EQ(expected, allocation);
// `framework2` declines the resources on `agent2` for the duration
// of the test.
@@ -2712,10 +2776,11 @@ TEST_F(HierarchicalAllocatorTest, DeactivateAndReactivateFramework)
FrameworkInfo framework = createFrameworkInfo("role1");
allocator->addFramework(framework.id(), framework, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
allocator->recoverResources(
framework.id(),
@@ -2734,7 +2799,7 @@ TEST_F(HierarchicalAllocatorTest, DeactivateAndReactivateFramework)
// operations to be processed.
Clock::settle();
- allocation = allocations.get();
+ Future<Allocation> allocation = allocations.get();
EXPECT_TRUE(allocation.isPending());
// Reconnect the framework again.
@@ -2742,9 +2807,11 @@ TEST_F(HierarchicalAllocatorTest, DeactivateAndReactivateFramework)
// Framework will be offered all of agent's resources again
// after getting activated.
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -2767,10 +2834,11 @@ TEST_F(HierarchicalAllocatorTest, SuppressAndReviveOffers)
FrameworkInfo framework = createFrameworkInfo("role1");
allocator->addFramework(framework.id(), framework, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
// Here the revival is totally unnecessary but we should tolerate the
// framework's redundant REVIVE calls.
@@ -2780,7 +2848,7 @@ TEST_F(HierarchicalAllocatorTest, SuppressAndReviveOffers)
Clock::settle();
// Nothing is allocated because of no additional resources.
- allocation = allocations.get();
+ Future<Allocation> allocation = allocations.get();
EXPECT_TRUE(allocation.isPending());
allocator->recoverResources(
@@ -2803,9 +2871,11 @@ TEST_F(HierarchicalAllocatorTest, SuppressAndReviveOffers)
// Framework will be offered all of agent's resources again after
// reviving offers.
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -3056,15 +3126,17 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(
FrameworkInfo framework1 = createFrameworkInfo("roleA");
allocator->addFramework(framework1.id(), framework1, {}, true);
- Future<Allocation> allocation = allocations.get();
+ Allocation expectedAllocation = Allocation(
+ framework1.id(),
+ {{agent.id(), agent.resources()}});
- AWAIT_READY(allocation);
- ASSERT_EQ(framework1.id(), allocation->frameworkId);
+ Future<Allocation> allocation = allocations.get();
+ AWAIT_EXPECT_EQ(expectedAllocation, allocation);
allocator->recoverResources(
allocation->frameworkId,
agent.id(),
- allocation->resources.get(agent.id()).get(),
+ allocation->resources.at(agent.id()),
offerFilter);
JSON::Object expected;
@@ -3079,15 +3151,17 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(
FrameworkInfo framework2 = createFrameworkInfo("roleB");
allocator->addFramework(framework2.id(), framework2, {}, true);
- allocation = allocations.get();
+ expectedAllocation = Allocation(
+ framework2.id(),
+ {{agent.id(), agent.resources()}});
- AWAIT_READY(allocation);
- ASSERT_EQ(framework2.id(), allocation->frameworkId);
+ allocation = allocations.get();
+ AWAIT_EXPECT_EQ(expectedAllocation, allocation);
allocator->recoverResources(
allocation->frameworkId,
agent.id(),
- allocation->resources.get(agent.id()).get(),
+ allocation->resources.at(agent.id()),
offerFilter);
expected.values = {
@@ -3102,15 +3176,17 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(
FrameworkInfo framework3 = createFrameworkInfo("roleA");
allocator->addFramework(framework3.id(), framework3, {}, true);
- allocation = allocations.get();
+ expectedAllocation = Allocation(
+ framework3.id(),
+ {{agent.id(), agent.resources()}});
- AWAIT_READY(allocation);
- ASSERT_EQ(framework3.id(), allocation->frameworkId);
+ allocation = allocations.get();
+ AWAIT_EXPECT_EQ(expectedAllocation, allocation);
allocator->recoverResources(
allocation->frameworkId,
agent.id(),
- allocation->resources.get(agent.id()).get(),
+ allocation->resources.at(agent.id()),
offerFilter);
expected.values = {
@@ -3159,7 +3235,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(HierarchicalAllocatorTest, DominantShareMetrics)
allocator->recoverResources(
allocation->frameworkId,
agent1.id(),
- allocation->resources.get(agent1.id()).get(),
+ allocation->resources.at(agent1.id()),
None());
Clock::settle();
@@ -3292,24 +3368,25 @@ TEST_F(HierarchicalAllocatorTest, UpdateWeight)
initialize();
- // Define some constants to make the code read easily.
- const string SINGLE_RESOURCE = "cpus:2;mem:1024";
- const string DOUBLE_RESOURCES = "cpus:4;mem:2048";
- const string TRIPLE_RESOURCES = "cpus:6;mem:3072";
- const string FOURFOLD_RESOURCES = "cpus:8;mem:4096";
- const string TOTAL_RESOURCES = "cpus:12;mem:6144";
+ const Resources SINGLE_RESOURCES = Resources::parse("cpus:2;mem:1024").get();
+ const Resources DOUBLE_RESOURCES = SINGLE_RESOURCES + SINGLE_RESOURCES;
+ const Resources TRIPLE_RESOURCES = DOUBLE_RESOURCES + SINGLE_RESOURCES;
+ const Resources FOURFOLD_RESOURCES = DOUBLE_RESOURCES + DOUBLE_RESOURCES;
+
+ // There will be 6 agents.
+ const Resources TOTAL_RESOURCES = FOURFOLD_RESOURCES + DOUBLE_RESOURCES;
auto awaitAllocationsAndRecoverResources = [this](
- Resources& totalAllocatedResources,
- hashmap<FrameworkID, Allocation>& frameworkAllocations,
+ Resources* totalAllocatedResources,
+ hashmap<FrameworkID, Allocation>* frameworkAllocations,
int allocationsCount,
bool recoverResources) {
for (int i = 0; i < allocationsCount; i++) {
Future<Allocation> allocation = allocations.get();
AWAIT_READY(allocation);
- frameworkAllocations[allocation->frameworkId] = allocation.get();
- totalAllocatedResources += Resources::sum(allocation->resources);
+ (*frameworkAllocations)[allocation->frameworkId] = allocation.get();
+ (*totalAllocatedResources) += Resources::sum(allocation->resources);
if (recoverResources) {
// Recover the allocated resources so they can be offered
@@ -3330,16 +3407,15 @@ TEST_F(HierarchicalAllocatorTest, UpdateWeight)
// Register six agents with the same resources (cpus:2;mem:1024).
vector<SlaveInfo> agents;
for (size_t i = 0; i < 6; i++) {
- SlaveInfo agent = createSlaveInfo(SINGLE_RESOURCE);
+ SlaveInfo agent = createSlaveInfo(SINGLE_RESOURCES);
agents.push_back(agent);
allocator->addSlave(agent.id(), agent, None(), agent.resources(), {});
}
- // Total cluster resources (6 agents): cpus=12, mem=6144.
-
- // Framework1 registers with 'role1' which uses the default weight (1.0),
- // and all resources will be offered to this framework since it is the only
- // framework running so far.
+ // Add two frameworks with the same weight, both should receive
+ // the same amount of resources once the agents are added. However,
+ // since framework1 is added first, it will receive all of the
+ // resources, so we recover them once both frameworks are added.
FrameworkInfo framework1 = createFrameworkInfo("role1");
allocator->addFramework(framework1.id(), framework1, {}, true);
@@ -3352,35 +3428,15 @@ TEST_F(HierarchicalAllocatorTest, UpdateWeight)
// allocation.
Clock::settle();
- // Framework2 registers with 'role2' which also uses the default weight.
- // It will not get any offers due to all resources having outstanding offers
- // to framework1 when it registered.
FrameworkInfo framework2 = createFrameworkInfo("role2");
allocator->addFramework(framework2.id(), framework2, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
-
- // role1 share = 1 (cpus=12, mem=6144)
- // framework1 share = 1
- // role2 share = 0
- // framework2 share = 0
-
- ASSERT_EQ(framework1.id(), allocation->frameworkId);
- ASSERT_EQ(6u, allocation->resources.size());
- EXPECT_EQ(Resources::parse(TOTAL_RESOURCES).get(),
- Resources::sum(allocation->resources));
-
- // Recover all resources so they can be offered again next time.
- foreachpair (const SlaveID& slaveId,
- const Resources& resources,
- allocation->resources) {
- allocator->recoverResources(
- allocation->frameworkId,
- slaveId,
- resources,
- None());
- }
+ // Recover the allocation to framework1 so that the allocator
+ // can offer to both frameworks.
+ hashmap<FrameworkID, Allocation> frameworkAllocations;
+ Resources totalAllocatedResources;
+ awaitAllocationsAndRecoverResources(
+ &totalAllocatedResources, &frameworkAllocations, 1, true);
// Tests whether `framework1` and `framework2` each get half of the resources
// when their roles' weights are 1:1.
@@ -3397,22 +3453,24 @@ TEST_F(HierarchicalAllocatorTest, UpdateWeight)
// since each framework's role has a weight of 1.0 by default.
hashmap<FrameworkID, Allocation> frameworkAllocations;
Resources totalAllocatedResources;
- awaitAllocationsAndRecoverResources(totalAllocatedResources,
- frameworkAllocations, 2, true);
+ awaitAllocationsAndRecoverResources(
+ &totalAllocatedResources, &frameworkAllocations, 2, true);
+
+ // Both frameworks should get one allocation with three agents.
+ ASSERT_TRUE(frameworkAllocations.contains(framework1.id()));
+ ASSERT_TRUE(frameworkAllocations.contains(framework2.id()));
- // Framework1 should get one allocation with three agents.
- ASSERT_EQ(3u, frameworkAllocations[framework1.id()].resources.size());
- EXPECT_EQ(Resources::parse(TRIPLE_RESOURCES).get(),
- Resources::sum(frameworkAllocations[framework1.id()].resources));
- // Framework2 should also get one allocation with three agents.
- ASSERT_EQ(3u, frameworkAllocations[framework2.id()].resources.size());
- EXPECT_EQ(Resources::parse(TRIPLE_RESOURCES).get(),
- Resources::sum(frameworkAllocations[framework2.id()].resources));
+ Allocation allocation1 = frameworkAllocations.at(framework1.id());
+ Allocation allocation2 = frameworkAllocations.at(framework2.id());
+
+ EXPECT_EQ(TRIPLE_RESOURCES, Resources::sum(allocation1.resources));
+ EXPECT_EQ(TRIPLE_RESOURCES, Resources::sum(allocation2.resources));
// Check to ensure that these two allocations sum to the total resources;
// this check can ensure there are only two allocations in this case.
- EXPECT_EQ(Resources::parse(TOTAL_RESOURCES).get(), totalAllocatedResources);
+ EXPECT_EQ(TOTAL_RESOURCES,
+ totalAllocatedResources.createStrippedScalarQuantity());
}
// Tests whether `framework1` gets 1/3 of the resources and `framework2` gets
@@ -3435,22 +3493,22 @@ TEST_F(HierarchicalAllocatorTest, UpdateWeight)
// resources are offered with a ratio of 1:2 between both frameworks.
hashmap<FrameworkID, Allocation> frameworkAllocations;
Resources totalAllocatedResources;
- awaitAllocationsAndRecoverResources(totalAllocatedResources,
- frameworkAllocations, 2, true);
+ awaitAllocationsAndRecoverResources(
+ &totalAllocatedResources, &frameworkAllocations, 2, true);
+
+ ASSERT_TRUE(frameworkAllocations.contains(framework1.id()));
+ ASSERT_TRUE(frameworkAllocations.contains(framework2.id()));
- // Framework1 should get one allocation with two agents.
- ASSERT_EQ(2u, frameworkAllocations[framework1.id()].resources.size());
- EXPECT_EQ(Resources::parse(DOUBLE_RESOURCES).get(),
- Resources::sum(frameworkAllocations[framework1.id()].resources));
+ Allocation allocation1 = frameworkAllocations.at(framework1.id());
+ Allocation allocation2 = frameworkAllocations.at(framework2.id());
- // Framework2 should get one allocation with four agents.
- ASSERT_EQ(4u, frameworkAllocations[framework2.id()].resources.size());
- EXPECT_EQ(Resources::parse(FOURFOLD_RESOURCES).get(),
- Resources::sum(frameworkAllocations[framework2.id()].resources));
+ EXPECT_EQ(DOUBLE_RESOURCES, Resources::sum(allocation1.resources));
+ EXPECT_EQ(FOURFOLD_RESOURCES, Resources::sum(allocation2.resources));
// Check to ensure that these two allocations sum to the total resources;
// this check can ensure there are only two allocations in this case.
- EXPECT_EQ(Resources::parse(TOTAL_RESOURCES).get(), totalAllocatedResources);
+ EXPECT_EQ(TOTAL_RESOURCES,
+ totalAllocatedResources.createStrippedScalarQuantity());
}
// Tests whether `framework1` gets 1/6 of the resources, `framework2` gets
@@ -3484,27 +3542,27 @@ TEST_F(HierarchicalAllocatorTest, UpdateWeight)
// will get the proper resource ratio of 1:2:3.
hashmap<FrameworkID, Allocation> frameworkAllocations;
Resources totalAllocatedResources;
- awaitAllocationsAndRecoverResources(totalAllocatedResources,
- frameworkAllocations, 3, false);
+ awaitAllocationsAndRecoverResources(
+ &totalAllocatedResources, &frameworkAllocations, 3, false);
+
+ // Both frameworks should get one allocation with three agents.
+ ASSERT_TRUE(frameworkAllocations.contains(framework1.id()));
+ ASSERT_TRUE(frameworkAllocations.contains(framework2.id()));
+ ASSERT_TRUE(frameworkAllocations.contains(framework3.id()));
- // Framework1 should get one allocation with one agent.
- ASSERT_EQ(1u, frameworkAllocations[framework1.id()].resources.size());
- EXPECT_EQ(Resources::parse(SINGLE_RESOURCE).get(),
- Resources::sum(frameworkAllocations[framework1.id()].resources));
- // Framework2 should get one allocation with two agents.
- ASSERT_EQ(2u, frameworkAllocations[framework2.id()].resources.size());
- EXPECT_EQ(Resources::parse(DOUBLE_RESOURCES).get(),
- Resources::sum(frameworkAllocations[framework2.id()].resources));
+ Allocation allocation1 = frameworkAllocations.at(framework1.id());
+ Allocation allocation2 = frameworkAllocations.at(framework2.id());
+ Allocation allocation3 = frameworkAllocations.at(framework3.id());
- // Framework3 should get one allocation with three agents.
- ASSERT_EQ(3u, frameworkAllocations[framework3.id()].resources.size());
- EXPECT_EQ(Resources::parse(TRIPLE_RESOURCES).get(),
- Resources::sum(frameworkAllocations[framework3.id()].resources));
+ EXPECT_EQ(SINGLE_RESOURCES, Resources::sum(allocation1.resources));
+ EXPECT_EQ(DOUBLE_RESOURCES, Resources::sum(allocation2.resources));
+ EXPECT_EQ(TRIPLE_RESOURCES, Resources::sum(allocation3.resources));
- // Check to ensure that these three allocations sum to the total resources;
+ // Check to ensure that these two allocations sum to the total resources;
// this check can ensure there are only three allocations in this case.
- EXPECT_EQ(Resources::parse(TOTAL_RESOURCES).get(), totalAllocatedResources);
+ EXPECT_EQ(TOTAL_RESOURCES,
+ totalAllocatedResources.createStrippedScalarQuantity());
}
}
@@ -3530,10 +3588,11 @@ TEST_F(HierarchicalAllocatorTest, ReviveOffers)
FrameworkInfo framework = createFrameworkInfo("role1");
allocator->addFramework(framework.id(), framework, {}, true);
- Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ Allocation expected = Allocation(
+ framework.id(),
+ {{agent.id(), agent.resources()}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
Filters filter1000s;
filter1000s.set_refuse_seconds(1000.);
@@ -3547,16 +3606,14 @@ TEST_F(HierarchicalAllocatorTest, ReviveOffers)
Clock::advance(flags.allocation_interval);
Clock::settle();
- allocation = allocations.get();
+ Future<Allocation> allocation = allocations.get();
EXPECT_TRUE(allocation.isPending());
allocator->reviveOffers(framework.id());
// Framework will be offered all of agent's resources again
// after reviving offers.
- AWAIT_READY(allocation);
- EXPECT_EQ(framework.id(), allocation->frameworkId);
- EXPECT_EQ(agent.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
}
@@ -3605,12 +3662,12 @@ TEST_P(HierarchicalAllocatorTestWithParam, AllocateSharedResources)
allocator->addSlave(slave.id(), slave, None(), slave.resources(), {});
// Initially, all the resources are allocated to `framework1`.
+ Allocation expected = Allocation(
+ framework1.id(),
+ {{slave.id(), slave.resources()}});
+
Future<Allocation> allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework1.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(slave.resources(), Resources::sum(allocation->resources));
+ AWAIT_EXPECT_EQ(expected, allocation);
// Create a shared volume.
Resource volume = createDiskResource(
@@ -3626,7 +3683,7 @@ TEST_P(HierarchicalAllocatorTestWithParam, AllocateSharedResources)
// Ensure the CREATE operation can be applied.
Try<Resources> updated =
- Resources::sum(allocation->resources).apply(create);
+ allocation->resources.at(slave.id()).apply(create);
ASSERT_SOME(updated);
@@ -3635,7 +3692,7 @@ TEST_P(HierarchicalAllocatorTestWithParam, AllocateSharedResources)
allocator->updateAllocation(
framework1.id(),
slave.id(),
- Resources::sum(allocation->resources),
+ allocation->resources.at(slave.id()),
{create, launch});
// Now recover the resources, and expect the next allocation to contain
@@ -3650,12 +3707,11 @@ TEST_P(HierarchicalAllocatorTestWithParam, AllocateSharedResources)
// The offer to 'framework2` should contain the shared volume.
Clock::advance(flags.allocation_interval);
- allocation = allocations.get();
- AWAIT_READY(allocation);
- EXPECT_EQ(framework2.id(), allocation->frameworkId);
- EXPECT_EQ(1u, allocation->resources.size());
- EXPECT_TRUE(allocation->resources.contains(slave.id()));
- EXPECT_EQ(allocation->resources.at(slave.id()).shared(), Resources(volume));
+ expected = Allocation(
+ framework2.id(),
+ {{slave.id(), updated.get() - task.resources() + volume}});
+
+ AWAIT_EXPECT_EQ(expected, allocations.get());
}
@@ -4100,26 +4156,21 @@ TEST_P(HierarchicalAllocator_BENCHMARK_Test, SuppressOffers)
// Pause the clock because we want to manually drive the allocations.
Clock::pause();
- struct Allocation
+ struct OfferedResources
{
FrameworkID frameworkId;
SlaveID slaveId;
Resources resources;
};
- vector<Allocation> allocations;
+ vector<OfferedResources> offers;
- auto offerCallback = [&allocations](
+ auto offerCallback = [&offers](
const FrameworkID& frameworkId,
const hashmap<SlaveID, Resources>& resources)
{
foreachpair (const SlaveID& slaveId, const Resources& r, resources) {
- Allocation allocation;
- allocation.frameworkId = frameworkId;
- allocation.slaveId = slaveId;
- allocation.resources = r;
-
- allocations.push_back(std::move(allocation));
+ offers.push_back(OfferedResources{frameworkId, slaveId, r});
}
};
@@ -4197,17 +4248,17 @@ TEST_P(HierarchicalAllocator_BENCHMARK_Test, SuppressOffers)
for (size_t i = 0; i < allocationsCount; ++i) {
// Recover resources with no filters because we want to test the
// effect of suppression alone.
- foreach (const Allocation& allocation, allocations) {
+ foreach (const OfferedResources& offer, offers) {
allocator->recoverResources(
- allocation.frameworkId,
- allocation.slaveId,
- allocation.resources,
+ offer.frameworkId,
+ offer.slaveId,
+ offer.resources,
None());
}
// Wait for all declined offers to be processed.
Clock::settle();
- allocations.clear();
+ offers.clear();
// Suppress another batch of frameworks. For simplicity and readability
// we loop on allocationsCount. The implication here is that there can be
@@ -4231,7 +4282,7 @@ TEST_P(HierarchicalAllocator_BENCHMARK_Test, SuppressOffers)
watch.stop();
cout << "allocate() took " << watch.elapsed()
- << " to make " << allocations.size() << " offers with "
+ << " to make " << offers.size() << " offers with "
<< suppressCount << " out of "
<< frameworkCount << " frameworks suppressing offers"
<< endl;