Implemented REMOVE_QUOTA Call in v1 master API.

Review: https://reviews.apache.org/r/49247/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/aaecd723
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/aaecd723
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/aaecd723

Branch: refs/heads/master
Commit: aaecd723048ad96e0df736271d3ae9df6f7bd815
Parents: 14b8c3a
Author: Abhishek Dasgupta <a10gu...@linux.vnet.ibm.com>
Authored: Tue Jun 28 11:01:15 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Tue Jun 28 11:01:15 2016 -0700

----------------------------------------------------------------------
 src/master/http.cpp          |  2 +-
 src/master/master.hpp        |  8 ++++
 src/master/quota_handler.cpp | 23 +++++++++-
 src/tests/api_tests.cpp      | 91 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 121 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/aaecd723/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index 7d6db2d..e827e69 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -595,7 +595,7 @@ Future<Response> Master::Http::api(
       return quotaHandler.set(call, principal);
 
     case mesos::master::Call::REMOVE_QUOTA:
-      return NotImplemented();
+      return quotaHandler.remove(call, principal);
 
     case mesos::master::Call::SUBSCRIBE: {
       Pipe pipe;

http://git-wip-us.apache.org/repos/asf/mesos/blob/aaecd723/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index daadebc..5c43f03 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -1000,6 +1000,10 @@ private:
         const Option<std::string>& principal) const;
 
     process::Future<process::http::Response> remove(
+        const mesos::master::Call& call,
+        const Option<std::string>& principal) const;
+
+    process::Future<process::http::Response> remove(
         const process::http::Request& request,
         const Option<std::string>& principal) const;
 
@@ -1076,6 +1080,10 @@ private:
         bool forced) const;
 
     process::Future<process::http::Response> _remove(
+        const std::string& role,
+        const Option<std::string>& principal) const;
+
+    process::Future<process::http::Response> __remove(
         const std::string& role) const;
 
     // To perform actions related to quota management, we require access to the

http://git-wip-us.apache.org/repos/asf/mesos/blob/aaecd723/src/master/quota_handler.cpp
----------------------------------------------------------------------
diff --git a/src/master/quota_handler.cpp b/src/master/quota_handler.cpp
index 0ad7bc9..bf6a613 100644
--- a/src/master/quota_handler.cpp
+++ b/src/master/quota_handler.cpp
@@ -432,6 +432,17 @@ Future<http::Response> Master::QuotaHandler::__set(
 
 
 Future<http::Response> Master::QuotaHandler::remove(
+    const mesos::master::Call& call,
+    const Option<string>& principal) const
+{
+  CHECK_EQ(mesos::master::Call::REMOVE_QUOTA, call.type());
+  CHECK(call.has_remove_quota());
+
+  return _remove(call.remove_quota().role(), principal);
+}
+
+
+Future<http::Response> Master::QuotaHandler::remove(
     const http::Request& request,
     const Option<string>& principal) const
 {
@@ -474,14 +485,22 @@ Future<http::Response> Master::QuotaHandler::remove(
         "': Role '" + role + "' has no quota set");
   }
 
+  return _remove(role, principal);
+}
+
+
+Future<http::Response> Master::QuotaHandler::_remove(
+    const string& role,
+    const Option<string>& principal) const
+{
   return authorizeRemoveQuota(principal, master->quotas[role].info)
     .then(defer(master->self(), [=](bool authorized) -> Future<http::Response> 
{
-      return !authorized ? Forbidden() : _remove(role);
+      return !authorized ? Forbidden() : __remove(role);
     }));
 }
 
 
-Future<http::Response> Master::QuotaHandler::_remove(const string& role) const
+Future<http::Response> Master::QuotaHandler::__remove(const string& role) const
 {
   // Remove quota from the quota-related local state. We do this before
   // updating the registry in order to make sure that we are not already

http://git-wip-us.apache.org/repos/asf/mesos/blob/aaecd723/src/tests/api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/api_tests.cpp b/src/tests/api_tests.cpp
index 32a0649..fd51fe9 100644
--- a/src/tests/api_tests.cpp
+++ b/src/tests/api_tests.cpp
@@ -1257,6 +1257,97 @@ TEST_P(MasterAPITest, SetQuota)
 }
 
 
+// This test verifies if we can remove a quota through `REMOVE_QUOTA` call,
+// after we set quota resources through `SET_QUOTA` call.
+TEST_P(MasterAPITest, RemoveQuota)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  v1::Resources quotaResources =
+    v1::Resources::parse("cpus:1;mem:512").get();
+
+  {
+    v1::master::Call v1Call;
+    v1Call.set_type(v1::master::Call::SET_QUOTA);
+
+    v1::quota::QuotaRequest* quotaRequest =
+      v1Call.mutable_set_quota()->mutable_quota_request();
+
+    // Use the force flag for setting quota that cannot be satisfied in
+    // this empty cluster without any agents.
+    quotaRequest->set_force(true);
+    quotaRequest->set_role("role1");
+    quotaRequest->mutable_guarantee()->CopyFrom(quotaResources);
+
+    ContentType contentType = GetParam();
+
+    // Send a quota request for the specified role.
+    Future<Response> response = process::http::post(
+        master.get()->pid,
+        "api/v1",
+        createBasicAuthHeaders(DEFAULT_CREDENTIAL),
+        serialize(contentType, v1Call),
+        stringify(contentType));
+
+    AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+  }
+
+  // Verify if the quota is set using `GET_QUOTA` call.
+  {
+    v1::master::Call v1Call;
+    v1Call.set_type(v1::master::Call::GET_QUOTA);
+
+    ContentType contentType = GetParam();
+
+    Future<v1::master::Response> v1Response =
+      post(master.get()->pid, v1Call, contentType);
+
+    AWAIT_READY(v1Response);
+    ASSERT_TRUE(v1Response->IsInitialized());
+    ASSERT_EQ(v1::master::Response::GET_QUOTA, v1Response->type());
+    ASSERT_EQ(1, v1Response->get_quota().status().infos().size());
+    EXPECT_EQ(quotaResources,
+      v1Response->get_quota().status().infos(0).guarantee());
+  }
+
+  // Remove the quota using `REMOVE_QUOTA` call.
+  {
+    v1::master::Call v1Call;
+    v1Call.set_type(v1::master::Call::REMOVE_QUOTA);
+    v1Call.mutable_remove_quota()->set_role("role1");
+
+    ContentType contentType = GetParam();
+
+    // Send a quota request for the specified role.
+    Future<Response> response = process::http::post(
+        master.get()->pid,
+        "api/v1",
+        createBasicAuthHeaders(DEFAULT_CREDENTIAL),
+        serialize(contentType, v1Call),
+        stringify(contentType));
+
+    AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+  }
+
+  // Verify if the quota is removed using `GET_QUOTA` call.
+  {
+    v1::master::Call v1Call;
+    v1Call.set_type(v1::master::Call::GET_QUOTA);
+
+    ContentType contentType = GetParam();
+
+    Future<v1::master::Response> v1Response =
+      post(master.get()->pid, v1Call, contentType);
+
+    AWAIT_READY(v1Response);
+    ASSERT_TRUE(v1Response->IsInitialized());
+    ASSERT_EQ(v1::master::Response::GET_QUOTA, v1Response->type());
+    ASSERT_EQ(0, v1Response->get_quota().status().infos().size());
+  }
+}
+
+
 // Test create and destroy persistent volumes through the master operator API.
 // In this test case, we create a persistent volume with the API, then launch a
 // task using the volume. Then we destroy the volume with the API after the 
task

Reply via email to