Repository: mesos Updated Branches: refs/heads/master 454e7f2b7 -> cc3ee7aad
Added a test to ensure the amount of quota headroom is sufficient. This test verifies that quota headroom is correctly maintained when some roles have more reservations than their quota. We need to ensure that one role's excessive reservation is not counted towards another role's quota headroom. Review: https://reviews.apache.org/r/64699/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/044fce50 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/044fce50 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/044fce50 Branch: refs/heads/master Commit: 044fce508993c118c3fd52e9b8bc3a5472ea7734 Parents: c9933c5 Author: Meng Zhu <[email protected]> Authored: Mon Dec 18 20:24:49 2017 -0800 Committer: Benjamin Mahler <[email protected]> Committed: Mon Dec 18 21:15:30 2017 -0800 ---------------------------------------------------------------------- src/tests/hierarchical_allocator_tests.cpp | 94 +++++++++++++++++++++++++ 1 file changed, 94 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/044fce50/src/tests/hierarchical_allocator_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp index 4127d05..173e4fb 100644 --- a/src/tests/hierarchical_allocator_tests.cpp +++ b/src/tests/hierarchical_allocator_tests.cpp @@ -1757,6 +1757,100 @@ TEST_F(HierarchicalAllocatorTest, Reservations) } +// This test verifies that quota headroom is correctly maintained when some +// roles have more reservations than their quotas. +TEST_P(HierarchicalAllocatorTestWithReservations, + QuotaHeadroomWhenReservationsExceedQuota) +{ + Clock::pause(); + initialize(); + + // We start with two roles `QUOTA_ROLE_W_RESERVATION` and + // `QUOTA_ROLE_NO_RESERVATION` with the same quota (cpus:1;mem:1024) set. + // `QUOTA_ROLE_W_RESERVATION` will also have reservations twice of its quota. + // Thus we have its reservation amount equals to the combined quota of both + // roles. + const string QUOTA_ROLE_W_RESERVATION{"quota-role-w-reservation"}; + const string QUOTA_ROLE_NO_RESERVATION{"quota-role-no-reservation"}; + const string NON_QUOTA_ROLE{"non-quota-role"}; + + const Quota quota1 = + createQuota(QUOTA_ROLE_W_RESERVATION, "cpus:1;mem:1024"); + allocator->setQuota(QUOTA_ROLE_W_RESERVATION, quota1); + + const Quota quota2 = + createQuota(QUOTA_ROLE_NO_RESERVATION, "cpus:1;mem:1024"); + allocator->setQuota(QUOTA_ROLE_NO_RESERVATION, quota2); + + // Add `agent1` with reserved resources for `QUOTA_ROLE_W_RESERVATION`. + Resource::ReservationInfo reservation; + reservation.set_type(GetParam()); + reservation.set_role(QUOTA_ROLE_W_RESERVATION); + + Resources reserved = Resources::parse("cpus:2;mem:2048").get(); + reserved = reserved.pushReservation(reservation); + + SlaveInfo agent1 = createSlaveInfo(reserved); + allocator->addSlave( + agent1.id(), + agent1, + AGENT_CAPABILITIES(), + None(), + agent1.resources(), + {}); + + // No quota headroom needed for `QUOTA_ROLE_W_RESERVATION`. + // (cpus:1;mem:1024) quota headroom needed for `QUOTA_ROLE_NO_RESERVATION`. + // Combined quota headroom: (cpus:1;mem:1024) + + // No allocation will happen because there are no frameworks. + + // Add `agent2` with unreserved resources. + SlaveInfo agent2 = createSlaveInfo("cpus:1;mem:1024"); + allocator->addSlave( + agent2.id(), + agent2, + AGENT_CAPABILITIES(), + None(), + agent2.resources(), + {}); + + // Add `framework` under `NON_QUOTA_ROLE`. + // This will trigger a batch allocation. + FrameworkInfo framework = createFrameworkInfo({NON_QUOTA_ROLE}); + allocator->addFramework(framework.id(), framework, {}, true, {}); + + Clock::settle(); + + // No allocation should happen because resources on agent2 are + // set aside for the quota headroom. + Future<Allocation> allocation = allocations.get(); + EXPECT_TRUE(allocation.isPending()); + + // Add `agent3` with unreserved resources. + // This will trigger an event-driven allocation loop for agent3. + SlaveInfo agent3 = createSlaveInfo("cpus:1;mem:1024"); + allocator->addSlave( + agent3.id(), + agent3, + AGENT_CAPABILITIES(), + None(), + agent3.resources(), + {}); + + Clock::settle(); + + // All resources on `agent3` are allocated to `framework` because + // it is the only framework and quota headroom has been met by `agent1` + // and `agent2`. + Allocation expected = Allocation( + framework.id(), + {{NON_QUOTA_ROLE, {{agent3.id(), agent3.resources()}}}}); + + AWAIT_EXPECT_EQ(expected, allocation); +} + + // Checks that recovered resources are re-allocated correctly. TEST_F(HierarchicalAllocatorTest, RecoverResources) {
