Parcourir la source

[5395] Support retrieving leases and deleting leases by client identifier.

Marcin Siodelski il y a 7 ans
Parent
commit
cf00a00b68

+ 45 - 13
src/hooks/dhcp/lease_cmds/lease_cmds.cc

@@ -39,24 +39,17 @@ namespace lease_cmds {
 /// @brief Wrapper class around reservation command handlers.
 class LeaseCmdsImpl : private CmdsImpl {
 public:
-    /// @brief Parameters specified for reservation-get and reservation-del
-    ///
-    /// As both call types (get and delete) need specify which reservation to
-    /// act on, they have the same set of parameters. In particular, those
-    /// two call types support the following sets of parameters:
-    /// - address
-    /// - subnet-id, identifier-type, identifier-value (v4)
-    /// - subnet-id, lease-type, iaid, identifier-type, identifier-value (v6)
-    ///
-    /// This class stores those parameters and is used to pass them around.
+
+    /// @brief Parameters specified for lease commands.
     class Parameters {
     public:
 
         /// @brief specifies type of query (by IP addr, by hwaddr, by DUID)
         typedef enum {
-            TYPE_ADDR,    ///< query by IP address (either v4 or v6)
-            TYPE_HWADDR,  ///< query by hardware address (v4 only)
-            TYPE_DUID     ///< query by DUID (v6 only)
+            TYPE_ADDR,      ///< query by IP address (either v4 or v6)
+            TYPE_HWADDR,    ///< query by hardware address (v4 only)
+            TYPE_DUID,      ///< query by DUID (v6 only)
+            TYPE_CLIENT_ID  ///< query by client identifier (v4 only).
         } Type;
 
         /// @brief Specifies subnet-id (always used)
@@ -71,6 +64,9 @@ public:
         /// @brief Specifies identifier value (used when query_type is TYPE_DUID)
         isc::dhcp::DuidPtr duid;
 
+        /// @brief Specifies identifier value (used when query_type is TYPE_CLIENT_ID)
+        isc::dhcp::ClientIdPtr client_id;
+
         /// @brief Attempts to covert text to one of specified types
         ///
         /// Supported values are: "address", hw-address and duid.
@@ -85,6 +81,8 @@ public:
                 return (Parameters::TYPE_HWADDR);
             } else if (txt == "duid") {
                 return (Parameters::TYPE_DUID);
+            } else if (txt == "client-id") {
+                return (Parameters::TYPE_CLIENT_ID);
             } else {
                 isc_throw(BadValue, "Incorrect identifier type: "
                           << txt << ", the only supported values are: "
@@ -345,6 +343,10 @@ LeaseCmdsImpl::getParameters(bool v6, const ConstElementPtr& params) {
         x.hwaddr = HWAddrPtr(new HWAddr(hw));
         break;
     }
+    case Parameters::TYPE_CLIENT_ID: {
+        x.client_id = ClientId::fromText(ident->stringValue());
+        break;
+    }
     case Parameters::TYPE_DUID: {
         DUID duid = DUID::fromText(ident->stringValue());
         x.duid = DuidPtr(new DUID(duid));
@@ -411,6 +413,19 @@ LeaseCmdsImpl::leaseGetHandler(CalloutHandle& handle) {
             }
             break;
 
+        case Parameters::TYPE_CLIENT_ID:
+            if (v4) {
+                if (!p.client_id) {
+                    isc_throw(InvalidParameter, "Program error: Query by client-id "
+                                                "requires client-id to be specified");
+                }
+
+                lease4 = LeaseMgrFactory::instance().getLease4(*p.client_id, p.subnet_id);
+            } else {
+                isc_throw(isc::InvalidParameter, "Query by client-id is not allowed in v6.");
+            }
+            break;
+
         default: {
             isc_throw(InvalidOperation, "Unknown query type: " << static_cast<int>(p.query_type));
             break;
@@ -473,6 +488,23 @@ LeaseCmdsImpl::lease4DelHandler(CalloutHandle& handle) {
             addr = lease4->addr_;
             break;
 
+        case Parameters::TYPE_CLIENT_ID:
+            if (!p.client_id) {
+                isc_throw(InvalidParameter, "Program error: Query by client-id "
+                                            "requires client-id to be specified");
+            }
+
+            // Let's see if there's such a lease at all.
+            lease4 = LeaseMgrFactory::instance().getLease4(*p.client_id, p.subnet_id);
+            if (!lease4) {
+                setErrorResponse(handle, "IPv4 lease not found.", CONTROL_RESULT_EMPTY);
+                return (0);
+            }
+
+            // Found it, can use it as is.
+            addr = lease4->addr_;
+            break;
+
         case Parameters::TYPE_DUID:
             isc_throw(InvalidParameter, "Delete by duid is not allowed in v4.");
             break;

+ 94 - 1
src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc

@@ -1047,7 +1047,7 @@ TEST_F(LeaseCmdsTest, Lease4GetByAddr) {
     ASSERT_TRUE(lease);
 
     // Let's check if the response makes any sense.
-    checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
+    checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", true);
 }
 
 // Checks that lease4-get can handle a situation when the query is
@@ -1122,6 +1122,53 @@ TEST_F(LeaseCmdsTest, Lease6GetByAddr6NotFound) {
     testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
 }
 
+// Checks that lease4-get can handle a situation when the query is
+// well formed, but the lease is not there.
+TEST_F(LeaseCmdsTest, Lease4GetByClientIdNotFound) {
+
+    // Initialize lease manager (false = v4, false = don't add a lease)
+    initLeaseMgr(false, false);
+
+    // No such lease.
+    string cmd =
+        "{\n"
+        "    \"command\": \"lease4-get\",\n"
+        "    \"arguments\": {"
+        "        \"identifier-type\": \"client-id\","
+        "        \"identifier\": \"01:02:03:04\","
+        "        \"subnet-id\": 44"
+        "    }\n"
+        "}";
+    string exp_rsp = "Lease not found.";
+    ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+// Check that lease4-get can find a lease by client identifier.
+TEST_F(LeaseCmdsTest, Lease4GetByClientId) {
+    // Initialize lease manager (false = v4, true = add a lease)
+    initLeaseMgr(false, true);
+
+    string cmd =
+        "{\n"
+        "    \"command\": \"lease4-get\",\n"
+        "    \"arguments\": {"
+        "        \"identifier-type\": \"client-id\","
+        "        \"identifier\": \"42:42:42:42:42:42:42:42\","
+        "        \"subnet-id\": 44"
+        "    }\n"
+        "}";
+    string exp_rsp = "IPv4 lease found.";
+    ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+    // Now check that the lease parameters were indeed returned.
+    ASSERT_TRUE(rsp);
+    ConstElementPtr lease = rsp->get("arguments");
+    ASSERT_TRUE(lease);
+
+    // Let's check if the response makes any sense.
+    checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
+}
+
 // Checks that lease6-get(subnet-id, addr) can handle a situation when
 // the query is correctly formed, but the lease is not there.
 TEST_F(LeaseCmdsTest, Lease6GetByDuidNotFound) {
@@ -1794,6 +1841,52 @@ TEST_F(LeaseCmdsTest, Lease4DelByHWAddr) {
     EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
 }
 
+// Checks that lease4-del can handle a situation when the query is
+// well formed, but the lease is not there.
+TEST_F(LeaseCmdsTest, Lease4DelByClientIdNotFound) {
+
+    // Initialize lease manager (false = v4, true = add a lease)
+    initLeaseMgr(false, true);
+
+    // No such lease.
+    string cmd =
+        "{\n"
+        "    \"command\": \"lease4-del\",\n"
+        "    \"arguments\": {"
+        "        \"identifier-type\": \"client-id\","
+        "        \"identifier\": \"01:02:03:04\","
+        "        \"subnet-id\": 44"
+        "    }\n"
+        "}";
+    string exp_rsp = "IPv4 lease not found.";
+    ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+    // Make sure the lease is still there.
+    EXPECT_TRUE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
+// Checks that lease4-del can find and delete a lease by client identifier.
+TEST_F(LeaseCmdsTest, Lease4DelByClientId) {
+    // Initialize lease manager (false = v4, true = add a lease)
+    initLeaseMgr(false, true);
+
+    // Invalid
+    string cmd =
+        "{\n"
+        "    \"command\": \"lease4-del\",\n"
+        "    \"arguments\": {"
+        "        \"identifier-type\": \"client-id\","
+        "        \"identifier\": \"42:42:42:42:42:42:42:42\","
+        "        \"subnet-id\": 44"
+        "    }\n"
+        "}";
+    string exp_rsp = "IPv4 lease deleted.";
+    ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+    // Make sure the lease is really gone.
+    EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
 // Checks that lease6-del(addr) can handle a situation when
 // the query is correctly formed, but the lease is not there.
 TEST_F(LeaseCmdsTest, Lease6DelByAddr6NotFound) {