Browse Source

[2404] Add ability to update an IPv4 lease

Stephen Morris 12 years ago
parent
commit
3b2c2c14fb

+ 41 - 6
src/lib/dhcpsrv/mysql_lease_mgr.cc

@@ -115,6 +115,11 @@ TaggedStatement tagged_statements[] = {
                         "expire, subnet_id, pref_lifetime, "
                         "lease_type, iaid, prefix_len) "
                             "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"},
+    {MySqlLeaseMgr::UPDATE_LEASE4,
+                    "UPDATE lease4 SET address = ?, hwaddr = ?, "
+                        "client_id = ?, valid_lifetime = ?, expire = ?, "
+                        "subnet_id = ? "
+                            "WHERE address = ?"},
     {MySqlLeaseMgr::UPDATE_LEASE6,
                     "UPDATE lease6 SET address = ?, duid = ?, "
                         "valid_lifetime = ?, expire = ?, subnet_id = ?, "
@@ -1294,9 +1299,42 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
 
 
 void
-MySqlLeaseMgr::updateLease4(const Lease4Ptr& /* lease4 */) {
-    isc_throw(NotImplemented, "MySqlLeaseMgr::updateLease4(const Lease4Ptr&) "
-              "not implemented yet");
+MySqlLeaseMgr::updateLease4(const Lease4Ptr& lease) {
+    const StatementIndex stindex = UPDATE_LEASE4;
+
+    // Create the MYSQL_BIND array for the data being updated
+    std::vector<MYSQL_BIND> bind = exchange4_->createBindForSend(lease);
+
+    // Set up the WHERE clause and append it to the MYSQL_BIND array
+    MYSQL_BIND where;
+    memset(&where, 0, sizeof(where));
+
+    uint32_t addr4 = static_cast<uint32_t>(lease->addr_);
+    where.buffer_type = MYSQL_TYPE_LONG;
+    where.buffer = reinterpret_cast<char*>(&addr4);
+    where.is_unsigned = my_bool(1);
+    bind.push_back(where);
+
+    // Bind the parameters to the statement
+    int status = mysql_stmt_bind_param(statements_[stindex], &bind[0]);
+    checkError(status, stindex, "unable to bind parameters");
+
+    // Execute
+    status = mysql_stmt_execute(statements_[stindex]);
+    checkError(status, stindex, "unable to execute");
+
+    // See how many rows were affected.  The statement should only update a
+    // single row.
+    int affected_rows = mysql_stmt_affected_rows(statements_[stindex]);
+    if (affected_rows == 0) {
+        isc_throw(NoSuchLease, "unable to update lease for address " <<
+                  lease->addr_.toText() << " as it does not exist");
+    } else if (affected_rows > 1) {
+        // Should not happen - primary key constraint should only have selected
+        // one row.
+        isc_throw(DbOperationError, "apparently updated more than one lease "
+                  "that had the address " << lease->addr_.toText());
+    }
 }
 
 
@@ -1372,9 +1410,6 @@ MySqlLeaseMgr::deleteLease4(const isc::asiolink::IOAddress& addr) {
     // See how many rows were affected.  Note that the statement may delete
     // multiple rows.
     return (mysql_stmt_affected_rows(statements_[stindex]) > 0);
-    isc_throw(NotImplemented, "MySqlLeaseMgr::deleteLease4(const IOAddress&) "
-              "not implemented yet");
-    return (false);
 }
 
 

+ 1 - 0
src/lib/dhcpsrv/mysql_lease_mgr.h

@@ -365,6 +365,7 @@ public:
         GET_VERSION,                // Obtain version number
         INSERT_LEASE4,              // Add entry to lease4 table
         INSERT_LEASE6,              // Add entry to lease6 table
+        UPDATE_LEASE4,              // Update a Lease4 entry
         UPDATE_LEASE6,              // Update a Lease6 entry
         NUM_STATEMENTS              // Number of statements
     };

+ 45 - 4
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc

@@ -1067,11 +1067,8 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) {
 // Adds leases to the database and checks that they can be accessed via
 // a combination of DIUID and IAID.
 TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetId) {
-    // Get the leases to be used for the test.
+    // Get the leases to be used for the test and add them to the database.
     vector<Lease6Ptr> leases = createLeases6();
-    ASSERT_LE(6, leases.size());    // Expect to access leases 0 through 5
-
-    // Add them to the database
     for (int i = 0; i < leases.size(); ++i) {
         EXPECT_TRUE(lmptr_->addLease(leases[i]));
     }
@@ -1103,6 +1100,50 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetId) {
 }
 
 
+// Update lease4 tests
+
+TEST_F(MySqlLeaseMgrTest, updateLease4) {
+    // Get the leases to be used for the test and add them to the database.
+    vector<Lease4Ptr> leases = createLeases4();
+    for (int i = 0; i < leases.size(); ++i) {
+        EXPECT_TRUE(lmptr_->addLease(leases[i]));
+    }
+
+    // Modify some fields in lease 1 (not the address) and update it.
+    ++leases[1]->subnet_id_;
+    leases[1]->valid_lft_ *= 2;
+    lmptr_->updateLease4(leases[1]);
+
+    // ... and check what is returned is what is expected.
+    Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1]);
+    ASSERT_TRUE(l_returned);
+    detailCompareLease(leases[1], l_returned);
+
+    // Alter the lease again and check.
+    ++leases[1]->subnet_id_;
+    leases[1]->cltt_ += 6;
+    lmptr_->updateLease4(leases[1]);
+
+    // Explicitly clear the returned pointer before getting new data to ensure
+    // that the new data is returned.
+    l_returned.reset();
+    l_returned = lmptr_->getLease4(ioaddress4_[1]);
+    ASSERT_TRUE(l_returned);
+    detailCompareLease(leases[1], l_returned);
+
+    // Check we can do an update without changing data.
+    lmptr_->updateLease4(leases[1]);
+    l_returned.reset();
+    l_returned = lmptr_->getLease4(ioaddress4_[1]);
+    ASSERT_TRUE(l_returned);
+    detailCompareLease(leases[1], l_returned);
+
+    // Try updating a lease not in the database.
+    lmptr_->deleteLease4(ioaddress4_[2]);
+    EXPECT_THROW(lmptr_->updateLease4(leases[2]), isc::dhcp::NoSuchLease);
+}
+
+
 
 // @brief Lease6 Update Tests
 //