[prev in list] [next in list] [prev in thread] [next in thread]
List: mesos-commits
Subject: [2/2] mesos git commit: Quota: Added a test for offer rescinding.
From: joris () apache ! org
Date: 2015-11-25 23:35:22
Message-ID: 49d26600d7b44afdb1b94a872ff25cad () git ! apache ! org
[Download RAW message or body]
Quota: Added a test for offer rescinding.
Review: https://reviews.apache.org/r/40396
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/91b1fa4e
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/91b1fa4e
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/91b1fa4e
Branch: refs/heads/master
Commit: 91b1fa4e3fec60d455e279c1da24f4060edcf15b
Parents: 64ec5d4
Author: Alexander Rukletsov <rukletsov@gmail.com>
Authored: Wed Nov 25 17:37:46 2015 -0500
Committer: Joris Van Remoortere <joris.van.remoortere@gmail.com>
Committed: Wed Nov 25 18:35:02 2015 -0500
----------------------------------------------------------------------
src/tests/master_quota_tests.cpp | 166 +++++++++++++++++++++++++++++++++-
1 file changed, 163 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/91b1fa4e/src/tests/master_quota_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_quota_tests.cpp b/src/tests/master_quota_tests.cpp
index 2934332..15edb27 100644
--- a/src/tests/master_quota_tests.cpp
+++ b/src/tests/master_quota_tests.cpp
@@ -17,6 +17,7 @@
*/
#include <string>
+#include <vector>
#include <gmock/gmock.h>
@@ -43,6 +44,7 @@
#include "tests/mesos.hpp"
using std::string;
+using std::vector;
using google::protobuf::RepeatedPtrField;
@@ -516,9 +518,6 @@ TEST_F(MasterQuotaTest, RemoveSingleQuota)
// request.
// * Multiple quotas in the cluster, insufficient free resources for a new
// request.
-// * Multiple quotas in the cluster, sufficient free resources for a new
-// request, but some resources are blocked in outstanding offers
-// (rescinding).
// * Deactivated or disconnected agents are not considered during quota
// capability heuristics.
@@ -801,6 +800,167 @@ TEST_F(MasterQuotaTest, AvailableResourcesMultipleAgents)
}
+// Checks that a quota request succeeds if there are sufficient total
+// resources in the cluster, even though they are blocked in outstanding
+// offers, i.e. quota request rescinds offers.
+TEST_F(MasterQuotaTest, AvailableResourcesAfterRescinding)
+{
+ TestAllocator<> allocator;
+ EXPECT_CALL(allocator, initialize(_, _, _, _));
+
+ Try<PID<Master>> master = StartMaster(&allocator);
+ ASSERT_SOME(master);
+
+ // Start one agent and wait until it registers.
+ Future<Resources> agent1TotalResources;
+ EXPECT_CALL(allocator, addSlave(_, _, _, _, _))
+ .WillOnce(DoAll(InvokeAddSlave(&allocator),
+ FutureArg<3>(&agent1TotalResources)));
+
+ Try<PID<Slave>> agent1 = StartSlave();
+ ASSERT_SOME(agent1);
+
+ AWAIT_READY(agent1TotalResources);
+ EXPECT_EQ(defaultAgentResources, agent1TotalResources.get());
+
+ // Start another agent and wait until it registers.
+ Future<Resources> agent2TotalResources;
+ EXPECT_CALL(allocator, addSlave(_, _, _, _, _))
+ .WillOnce(DoAll(InvokeAddSlave(&allocator),
+ FutureArg<3>(&agent2TotalResources)));
+
+ Try<PID<Slave>> agent2 = StartSlave();
+ ASSERT_SOME(agent2);
+
+ AWAIT_READY(agent2TotalResources);
+ EXPECT_EQ(defaultAgentResources, agent2TotalResources.get());
+
+ // Start one more agent and wait until it registers.
+ Future<Resources> agent3TotalResources;
+ EXPECT_CALL(allocator, addSlave(_, _, _, _, _))
+ .WillOnce(DoAll(InvokeAddSlave(&allocator),
+ FutureArg<3>(&agent3TotalResources)));
+
+ Try<PID<Slave>> agent3 = StartSlave();
+ ASSERT_SOME(agent3);
+
+ AWAIT_READY(agent3TotalResources);
+ EXPECT_EQ(defaultAgentResources, agent3TotalResources.get());
+
+ // We start with the following cluster setup.
+ // Total cluster resources (3 identical agents): cpus=6, mem=3072.
+ // role1 share = 0
+ // role2 share = 0
+
+ // We create a "hoarding" framework that will hog the resources but
+ // will not use them.
+ FrameworkInfo frameworkInfo1 = createFrameworkInfo(ROLE1);
+ MockScheduler sched1;
+ MesosSchedulerDriver framework1(
+ &sched1, frameworkInfo1, master.get(), DEFAULT_CREDENTIAL);
+
+ // We use `offers` to capture offers from the `resourceOffers()` callback.
+ Future<vector<Offer>> offers;
+
+ // Set expectations for the first offer and launch the framework.
+ EXPECT_CALL(sched1, registered(&framework1, _, _));
+ EXPECT_CALL(sched1, resourceOffers(&framework1, _))
+ .WillOnce(FutureArg<1>(&offers));
+
+ framework1.start();
+
+ // In the first offer, expect offers from all available agents.
+ AWAIT_READY(offers);
+ ASSERT_EQ(3u, offers.get().size());
+
+ // `framework1` hoards the resources, i.e. does not accept them.
+ // Now we add two new frameworks to `ROLE2`, for which we should
+ // make space if we can.
+
+ FrameworkInfo frameworkInfo2 = createFrameworkInfo(ROLE2);
+ MockScheduler sched2;
+ MesosSchedulerDriver framework2(
+ &sched2, frameworkInfo2, master.get(), DEFAULT_CREDENTIAL);
+
+ Future<Nothing> registered2;
+ EXPECT_CALL(sched2, registered(&framework2, _, _))
+ .WillOnce(FutureSatisfy(®istered2));
+
+ FrameworkInfo frameworkInfo3 = createFrameworkInfo(ROLE2);
+ MockScheduler sched3;
+ MesosSchedulerDriver framework3(
+ &sched3, frameworkInfo3, master.get(), DEFAULT_CREDENTIAL);
+
+ Future<Nothing> registered3;
+ EXPECT_CALL(sched3, registered(&framework3, _, _))
+ .WillOnce(FutureSatisfy(®istered3));
+
+ framework2.start();
+ framework3.start();
+
+ AWAIT_READY(registered2);
+ AWAIT_READY(registered3);
+
+ // There should be no offers made to `framework2` and `framework3`
+ // since there are no free resources.
+ EXPECT_CALL(sched2, resourceOffers(&framework2, _))
+ .Times(0);
+ EXPECT_CALL(sched3, resourceOffers(&framework3, _))
+ .Times(0);
+
+ // Total cluster resources (3 identical agents): cpus=6, mem=3072.
+ // role1 share = 1 (cpus=6, mem=3072)
+ // framework1 share = 1
+ // role2 share = 0
+ // framework2 share = 0
+ // framework3 share = 0
+
+ // We request quota for a portion of resources which is smaller than
+ // the total cluster capacity and can fit into any single agent.
+ Resources quotaResources = Resources::parse("cpus:1;mem:512", ROLE2).get();
+
+ // Once the quota request reaches the master, it should trigger a series
+ // of rescinds. Even though quota request resources can be satisfied with
+ // resources from a single agent, offers from two agents must be rescinded,
+ // because there are two frameworks in the quota'ed role `ROLE2`.
+ EXPECT_CALL(sched1, offerRescinded(&framework1, _))
+ .Times(2);
+
+ // Send a quota request for the specified role.
+ Future<QuotaInfo> receivedQuotaRequest;
+ EXPECT_CALL(allocator, setQuota(Eq(ROLE2), _))
+ .WillOnce(DoAll(InvokeSetQuota(&allocator),
+ FutureArg<1>(&receivedQuotaRequest)));
+
+ Future<Response> response = process::http::post(
+ master.get(),
+ "quota",
+ createBasicAuthHeaders(DEFAULT_CREDENTIAL),
+ createRequestBody(quotaResources));
+
+ // At some point before the response is sent, offers are rescinded,
+ // but resources are not yet allocated. At this moment the cluster
+ // state looks like this.
+
+ // Total cluster resources (3 identical agents): cpus=6, mem=3072.
+ // role1 share = 0.33 (cpus=2, mem=1024)
+ // framework1 share = 1
+ // role2 share = 0
+ // framework2 share = 0
+ // framework3 share = 0
+
+ AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) << response.get().body;
+
+ // The quota request is granted and reached the allocator. Make sure nothing
+ // got lost in-between.
+ AWAIT_READY(receivedQuotaRequest);
+ EXPECT_EQ(ROLE2, receivedQuotaRequest.get().role());
+ EXPECT_EQ(quotaResources, Resources(receivedQuotaRequest.get().guarantee()));
+
+ Shutdown();
+}
+
+
// These tests ensure quota implements declared functionality. Note that the
// tests here are allocator-agnostic, which means we expect every allocator to
// implement basic quota guarantees.
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic