You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by mz...@apache.org on 2018/12/05 17:15:26 UTC

[mesos] branch master updated: Added tests to ensure correct quota accounting.

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

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


The following commit(s) were added to refs/heads/master by this push:
     new ed02fb0  Added tests to ensure correct quota accounting.
ed02fb0 is described below

commit ed02fb0ca406808db1b61ed3a3c821f1192e553e
Author: Meng Zhu <mz...@mesosphere.io>
AuthorDate: Tue Jul 31 12:55:34 2018 -0700

    Added tests to ensure correct quota accounting.
    
    Added two allocator tests to ensure reserving and
    unreserving allocated resources do not affect
    quota accounting.
    
    Review: https://reviews.apache.org/r/68138
---
 src/tests/hierarchical_allocator_tests.cpp | 141 +++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)

diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp
index 3034d46..ee49b83 100644
--- a/src/tests/hierarchical_allocator_tests.cpp
+++ b/src/tests/hierarchical_allocator_tests.cpp
@@ -1699,6 +1699,147 @@ TEST_P(HierarchicalAllocatorTestWithReservations,
   EXPECT_TRUE(allocations.get().isPending());
 }
 
+// This test ensures that reserving already allocated resources would not
+// affect quota allocation.
+TEST_F(HierarchicalAllocatorTest, QuotaAccountingReserveAllocatedResources)
+{
+  Clock::pause();
+  initialize();
+
+  const string QUOTA_ROLE{"quota-role"};
+
+  // Create `framework` and set quota for its role.
+
+  const Quota quota = createQuota(QUOTA_ROLE, "cpus:10;mem:1024");
+  allocator->setQuota(QUOTA_ROLE, quota);
+
+  FrameworkInfo framework = createFrameworkInfo({QUOTA_ROLE});
+  allocator->addFramework(framework.id(), framework, {}, true, {});
+
+  Resources agentResources = CHECK_NOTERROR(Resources::parse("cpus:5;mem:512"));
+
+  // Add `agent1`. This will trigger an event-driven allocation.
+  SlaveInfo agent1 = createSlaveInfo(agentResources);
+  allocator->addSlave(
+      agent1.id(), agent1, AGENT_CAPABILITIES(), None(), agentResources, {});
+
+  // All of agent1's resources will be offered to `framework`
+  // as part of its quota.
+  Allocation expected =
+    Allocation(framework.id(), {{QUOTA_ROLE, {{agent1.id(), agentResources}}}});
+
+  Future<Allocation> allocation = allocations.get();
+  AWAIT_EXPECT_EQ(expected, allocation);
+
+  // `framework` unsatisfied quota: cpus:5;mem:512
+
+  // Let `framework` reserve its allocated resources on agent1.
+  Resources reserveResources = agentResources;
+  reserveResources.allocate(QUOTA_ROLE);
+  reserveResources = reserveResources.pushReservation(
+      createDynamicReservationInfo(QUOTA_ROLE, "principal"));
+
+  Offer::Operation reserve = RESERVE(reserveResources);
+
+  // Update the allocation in the allocator with a `RESERVE` operation.
+  allocator->updateAllocation(
+      framework.id(),
+      agent1.id(),
+      allocation->resources.at(QUOTA_ROLE).at(agent1.id()),
+      CHECK_NOTERROR(getResourceConversions(reserve)));
+
+  // Reserving allocated resources does not change unsatisfied quota.
+  // `framework` unsatisfied quota: cpus:5;mem:512
+
+  // Add `agent2` with twice the resources as that of `agent1`.
+  // This will trigger an event-driven allocation.
+  SlaveInfo agent2 = createSlaveInfo(agentResources + agentResources);
+  allocator->addSlave(
+      agent2.id(), agent2, AGENT_CAPABILITIES(), None(), agentResources, {});
+
+  // `agent2` will be chopped and half of its resources will be allocated to
+  // `framework` to meet its unsatisfied quota.
+  expected =
+    Allocation(framework.id(), {{QUOTA_ROLE, {{agent2.id(), agentResources}}}});
+
+  AWAIT_EXPECT_EQ(expected, allocations.get());
+}
+
+
+// This test ensures that unreserving allocated resources would not affect
+// quota allocation.
+TEST_F(HierarchicalAllocatorTest, QuotaAccountingUnreserveAllocatedResources)
+{
+  Clock::pause();
+  initialize();
+
+  // Create `framework` and set quota for its role.
+
+  const Quota quota = createQuota("quota-role", "cpus:1;mem:1024");
+  allocator->setQuota("quota-role", quota);
+
+  FrameworkInfo framework = createFrameworkInfo({"quota-role"});
+  allocator->addFramework(framework.id(), framework, {}, true, {});
+
+  Resources reservedResources =
+    CHECK_NOTERROR(Resources::parse("cpus(quota-role):1;mem(quota-role):1024"));
+
+  // Add `agent1` with reserved resources for "quota-role" that matches exactly
+  // its quota. This will trigger an event-driven allocation.
+  SlaveInfo agent1 = createSlaveInfo(reservedResources);
+  allocator->addSlave(
+      agent1.id(),
+      agent1,
+      AGENT_CAPABILITIES(),
+      None(),
+      agent1.resources(),
+      {});
+
+  // All of agent1's resources will be offered to `framework` to satisfy
+  // all of its quota.
+  Allocation expected = Allocation(
+      framework.id(), {{"quota-role", {{agent1.id(), agent1.resources()}}}});
+
+  AWAIT_EXPECT_EQ(expected, allocations.get());
+
+  // Add `agent2` with unreserved resources. This will trigger an event-driven
+  // allocation.
+  SlaveInfo agent2 = createSlaveInfo("cpus:1;mem:1024");
+  allocator->addSlave(
+      agent2.id(),
+      agent2,
+      AGENT_CAPABILITIES(),
+      None(),
+      agent2.resources(),
+      {});
+
+  Clock::settle();
+
+  // No allocation should be made because `framework` is under "quota-role"
+  // and its quota is already satisfied by `agent1`.
+  Future<Allocation> allocation = allocations.get();
+  EXPECT_TRUE(allocation.isPending());
+
+  // Unreserve the allocated resources on `agent1`.
+  reservedResources.allocate("quota-role");
+  Offer::Operation unreserve = UNRESERVE(reservedResources);
+
+  allocator->updateAllocation(
+      framework.id(),
+      agent1.id(),
+      reservedResources,
+      CHECK_NOTERROR(getResourceConversions(unreserve)));
+
+  // Trigger the next allocation cycle.
+  Clock::advance(flags.allocation_interval);
+  Clock::settle();
+
+  // Still no allocation should be made because un-reserving allocated resources
+  // does not affect allocated resource quantities. "quota-role"'s quota is
+  // still satisfied by allocated resources on `agent1`.
+  EXPECT_TRUE(allocation.isPending());
+}
+
 
 // Checks that resources on a slave that are statically reserved to
 // a role are only offered to frameworks in that role.