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/01/22 09:28:21 UTC
[03/10] mesos git commit: Added tests for offer filters.
Added tests for offer filters.
Review: https://reviews.apache.org/r/42629/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/ecfb8d53
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/ecfb8d53
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/ecfb8d53
Branch: refs/heads/master
Commit: ecfb8d53da58cc694ef885c929873042618dc16e
Parents: 447d814
Author: Alexander Rukletsov <ru...@gmail.com>
Authored: Thu Jan 21 23:29:06 2016 -0800
Committer: Benjamin Mahler <be...@gmail.com>
Committed: Thu Jan 21 23:59:36 2016 -0800
----------------------------------------------------------------------
src/tests/hierarchical_allocator_tests.cpp | 233 ++++++++++++++++++++++++
1 file changed, 233 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/ecfb8d53/src/tests/hierarchical_allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hierarchical_allocator_tests.cpp b/src/tests/hierarchical_allocator_tests.cpp
index 516c5cf..aa364ea 100644
--- a/src/tests/hierarchical_allocator_tests.cpp
+++ b/src/tests/hierarchical_allocator_tests.cpp
@@ -446,6 +446,239 @@ TEST_F(HierarchicalAllocatorTest, ReservedDRF)
}
+// This test ensures that an offer filter larger than the
+// allocation interval effectively filters out resources.
+TEST_F(HierarchicalAllocatorTest, OfferFilter)
+{
+ // 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();
+
+ // We put both frameworks into the same role, but we could also
+ // have had separate roles; this should not influence the test.
+ const string ROLE{"role"};
+
+ hashmap<FrameworkID, Resources> EMPTY;
+
+ initialize();
+
+ FrameworkInfo framework1 = createFrameworkInfo(ROLE);
+
+ SlaveInfo agent1 = createSlaveInfo("cpus:1;mem:512;disk:0");
+
+ allocator->addFramework(
+ framework1.id(),
+ framework1,
+ hashmap<SlaveID, Resources>());
+
+ allocator->addSlave(
+ agent1.id(),
+ agent1,
+ None(),
+ agent1.resources(),
+ EMPTY);
+
+ // `framework1` will be offered all of `agent1` resources
+ // because it is the only framework in the cluster.
+ Future<Allocation> allocation = allocations.get();
+ AWAIT_READY(allocation);
+ EXPECT_EQ(framework1.id(), allocation.get().frameworkId);
+ EXPECT_EQ(agent1.resources(), Resources::sum(allocation.get().resources));
+
+ // Now `framework1` declines the offer and sets a filter
+ // with the duration greater than the allocation interval.
+ Duration filterTimeout = flags.allocation_interval * 2;
+ Filters offerFilter;
+ offerFilter.set_refuse_seconds(filterTimeout.secs());
+
+ allocator->recoverResources(
+ framework1.id(),
+ agent1.id(),
+ allocation.get().resources.get(agent1.id()).get(),
+ offerFilter);
+
+ // Ensure the offer filter timeout is set before advancing the clock.
+ Clock::settle();
+
+ // Trigger a batch allocation.
+ Clock::advance(flags.allocation_interval);
+ Clock::settle();
+
+ // There should be no allocation due to the offer filter.
+ allocation = allocations.get();
+ ASSERT_TRUE(allocation.isPending());
+
+ // Ensure the offer filter times out (2x the allocation interval)
+ // and the next batch allocation occurs.
+ Clock::advance(flags.allocation_interval);
+ Clock::settle();
+
+ // The next batch allocation should offer resources to `framework1`.
+ AWAIT_READY(allocation);
+ EXPECT_EQ(framework1.id(), allocation.get().frameworkId);
+ EXPECT_EQ(agent1.resources(), Resources::sum(allocation.get().resources));
+}
+
+
+// This test ensures that an offer filter is not removed earlier than
+// the next batch allocation. See MESOS-4302 for more information.
+//
+// NOTE: If we update the code to allocate upon resource recovery
+// (MESOS-3078), this test should still pass in that the small offer
+// filter timeout should lead to the next allocation for the agent
+// applying the filter.
+TEST_F(HierarchicalAllocatorTest, SmallOfferFilterTimeout)
+{
+ // 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();
+
+ // We put both frameworks into the same role, but we could also
+ // have had separate roles; this should not influence the test.
+ const string ROLE{"role"};
+
+ hashmap<FrameworkID, Resources> EMPTY;
+
+ // Explicitly set the allocation interval to make sure
+ // it is greater than the offer filter timeout.
+ master::Flags flags_;
+ flags_.allocation_interval = Minutes(1);
+
+ initialize(flags_);
+
+ // We start with the following cluster setup.
+ // Total cluster resources (1 agent): cpus=1, mem=512.
+ // ROLE1 share = 1 (cpus=1, mem=512)
+ // framework1 share = 1 (cpus=1, mem=512)
+ // framework2 share = 0
+
+ FrameworkInfo framework1 = createFrameworkInfo(ROLE);
+ FrameworkInfo framework2 = createFrameworkInfo(ROLE);
+
+ SlaveInfo agent1 = createSlaveInfo("cpus:1;mem:512;disk:0");
+
+ allocator->addFramework(
+ framework1.id(),
+ framework1,
+ hashmap<SlaveID, Resources>());
+
+ allocator->addFramework(
+ framework2.id(),
+ framework2,
+ hashmap<SlaveID, Resources>());
+
+ allocator->addSlave(
+ agent1.id(),
+ agent1,
+ None(),
+ agent1.resources(),
+ {std::make_pair(framework1.id(), agent1.resources())});
+
+ // Process all triggered allocation events.
+ // NOTE: No allocations happen because there are no resources to allocate.
+ Clock::settle();
+
+ // Add one more agent with some free resources.
+ SlaveInfo agent2 = createSlaveInfo("cpus:1;mem:512;disk:0");
+ allocator->addSlave(
+ agent2.id(),
+ agent2,
+ None(),
+ agent2.resources(),
+ EMPTY);
+
+ // Process the allocation triggered by the agent addition.
+ Clock::settle();
+
+ // `framework2` will be offered all of `agent2` resources
+ // because its share (0) is smaller than `framework1`.
+ Future<Allocation> allocation = allocations.get();
+ AWAIT_READY(allocation);
+ EXPECT_EQ(framework2.id(), allocation.get().frameworkId);
+ EXPECT_EQ(agent2.resources(), Resources::sum(allocation.get().resources));
+
+ // Total cluster resources (2 agents): cpus=2, mem=1024.
+ // ROLE1 share = 1 (cpus=2, mem=1024)
+ // framework1 share = 0.5 (cpus=1, mem=512)
+ // framework2 share = 0.5 (cpus=1, mem=512)
+
+ // Now `framework2` declines the offer and sets a filter
+ // for 1 second, which is less than the allocation interval.
+ Duration filterTimeout = Seconds(1);
+ ASSERT_GT(flags.allocation_interval, filterTimeout);
+
+ Filters offerFilter;
+ offerFilter.set_refuse_seconds(filterTimeout.secs());
+
+ allocator->recoverResources(
+ framework2.id(),
+ agent2.id(),
+ allocation.get().resources.get(agent2.id()).get(),
+ offerFilter);
+
+ // Total cluster resources (2 agents): cpus=2, mem=1024.
+ // ROLE1 share = 0.5 (cpus=1, mem=512)
+ // framework1 share = 1 (cpus=1, mem=512)
+ // framework2 share = 0
+
+ // The offer filter times out. Since the allocator ensures that
+ // offer filters are removed after at least one batch allocation
+ // has occurred, we expect that after the timeout elapses, the
+ // filter will remain active for the next allocation and the
+ // resources are allocated to `framework1`.
+ Clock::advance(filterTimeout);
+ Clock::settle();
+
+ // Trigger a batch allocation.
+ Clock::advance(flags.allocation_interval);
+ Clock::settle();
+
+ // Since the filter is applied, resources are offered to `framework1`
+ // even though its share is greater than `framework2`.
+ allocation = allocations.get();
+ AWAIT_READY(allocation);
+ EXPECT_EQ(framework1.id(), allocation.get().frameworkId);
+ EXPECT_EQ(agent2.resources(), Resources::sum(allocation.get().resources));
+
+ // Total cluster resources (2 agents): cpus=2, mem=1024.
+ // ROLE1 share = 1 (cpus=2, mem=1024)
+ // framework1 share = 1 (cpus=2, mem=1024)
+ // framework2 share = 0
+
+ // The filter should be removed now than the batch
+ // allocation has occurred!
+
+ // Now `framework1` declines the offer.
+ allocator->recoverResources(
+ framework1.id(),
+ agent2.id(),
+ allocation.get().resources.get(agent2.id()).get(),
+ None());
+
+ // Total cluster resources (2 agents): cpus=2, mem=1024.
+ // ROLE1 share = 0.5 (cpus=1, mem=512)
+ // framework1 share = 1 (cpus=1, mem=512)
+ // framework2 share = 0
+
+ // Trigger a batch allocation.
+ Clock::advance(flags.allocation_interval);
+ Clock::settle();
+
+ // Since the filter is removed, resources are offered to `framework2`.
+ allocation = allocations.get();
+ AWAIT_READY(allocation);
+ EXPECT_EQ(framework2.id(), allocation.get().frameworkId);
+ EXPECT_EQ(agent2.resources(), Resources::sum(allocation.get().resources));
+
+ // Total cluster resources (2 agents): cpus=2, mem=1024.
+ // ROLE1 share = 1 (cpus=2, mem=1024)
+ // framework1 share = 0.5 (cpus=1, mem=512)
+ // framework2 share = 0.5 (cpus=1, mem=512)
+}
+
+
// This test ensures that agents which are scheduled for maintenance are
// properly sent inverse offers after they have accepted or reserved resources.
TEST_F(HierarchicalAllocatorTest, MaintenanceInverseOffers)