Browse Source

[3147] Merge branch 'trac3147'

Adds use of lease type as a discriminator in DHCP6 lease queries in MySQL
back end.
Thomas Markwalder 11 years ago
parent
commit
65b6372b78

+ 5 - 5
src/lib/dhcpsrv/dhcpsrv_messages.mes

@@ -252,7 +252,7 @@ recommended.
 A debug message issued when the server is about to add an IPv4 lease
 with the specified address to the MySQL backend database.
 
-% DHCPSRV_MYSQL_ADD_ADDR6 adding IPv6 lease with address %1
+% DHCPSRV_MYSQL_ADD_ADDR6 adding IPv6 lease with address %1, lease type %2
 A debug message issued when the server is about to add an IPv6 lease
 with the specified address to the MySQL backend database.
 
@@ -275,7 +275,7 @@ the specified address from the MySQL database for the specified address.
 A debug message issued when the server is attempting to obtain an IPv4
 lease from the MySQL database for the specified address.
 
-% DHCPSRV_MYSQL_GET_ADDR6 obtaining IPv6 lease for address %1
+% DHCPSRV_MYSQL_GET_ADDR6 obtaining IPv6 lease for address %1, lease type %2
 A debug message issued when the server is attempting to obtain an IPv6
 lease from the MySQL database for the specified address.
 
@@ -289,12 +289,12 @@ A debug message issued when the server is attempting to obtain a set
 of IPv4 leases from the MySQL database for a client with the specified
 hardware address.
 
-% DHCPSRV_MYSQL_GET_IAID_DUID obtaining IPv4 leases for IAID %1 and DUID %2
+% DHCPSRV_MYSQL_GET_IAID_DUID obtaining IPv6 leases for IAID %1, DUID %2, lease type %3
 A debug message issued when the server is attempting to obtain a set of
 IPv6 lease from the MySQL database for a client with the specified IAID
 (Identity Association ID) and DUID (DHCP Unique Identifier).
 
-% DHCPSRV_MYSQL_GET_IAID_SUBID_DUID obtaining IPv4 leases for IAID %1, Subnet ID %2 and DUID %3
+% DHCPSRV_MYSQL_GET_IAID_SUBID_DUID obtaining IPv6 leases for IAID %1, Subnet ID %2, DUID %3, lease type %4
 A debug message issued when the server is attempting to obtain an IPv6
 lease from the MySQL database for a client with the specified IAID
 (Identity Association ID), Subnet ID and DUID (DHCP Unique Identifier).
@@ -321,7 +321,7 @@ be rolled back and not committed to the database.
 A debug message issued when the server is attempting to update IPv4
 lease from the MySQL database for the specified address.
 
-% DHCPSRV_MYSQL_UPDATE_ADDR6 updating IPv6 lease for address %1
+% DHCPSRV_MYSQL_UPDATE_ADDR6 updating IPv6 lease for address %1, lease type %2
 A debug message issued when the server is attempting to update IPv6
 lease from the MySQL database for the specified address.
 

+ 39 - 21
src/lib/dhcpsrv/mysql_lease_mgr.cc

@@ -163,21 +163,22 @@ TaggedStatement tagged_statements[] = {
                         "lease_type, iaid, prefix_len, "
                         "fqdn_fwd, fqdn_rev, hostname "
                             "FROM lease6 "
-                            "WHERE address = ?"},
+                            "WHERE address = ? AND lease_type = ?"},
     {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
                     "SELECT address, duid, valid_lifetime, "
                         "expire, subnet_id, pref_lifetime, "
                         "lease_type, iaid, prefix_len, "
                         "fqdn_fwd, fqdn_rev, hostname "
                             "FROM lease6 "
-                            "WHERE duid = ? AND iaid = ?"},
+                            "WHERE duid = ? AND iaid = ? AND lease_type = ?"},
     {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID,
                     "SELECT address, duid, valid_lifetime, "
                         "expire, subnet_id, pref_lifetime, "
                         "lease_type, iaid, prefix_len, "
                         "fqdn_fwd, fqdn_rev, hostname "
                             "FROM lease6 "
-                            "WHERE duid = ? AND iaid = ? AND subnet_id = ?"},
+                            "WHERE duid = ? AND iaid = ? AND subnet_id = ? "
+                            "AND lease_type = ?"},
     {MySqlLeaseMgr::GET_VERSION,
                     "SELECT version, minor FROM schema_version"},
     {MySqlLeaseMgr::INSERT_LEASE4,
@@ -1253,7 +1254,7 @@ MySqlLeaseMgr::openDatabase() {
                   mysql_error(mysql_));
     }
 
-    // Set SQL mode options for the connection:  SQL mode governs how what 
+    // Set SQL mode options for the connection:  SQL mode governs how what
     // constitutes insertable data for a given column, and how to handle
     // invalid data.  We want to ensure we get the strictest behavior and
     // to reject invalid data with an error.
@@ -1374,7 +1375,8 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& lease) {
 bool
 MySqlLeaseMgr::addLease(const Lease6Ptr& lease) {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
-              DHCPSRV_MYSQL_ADD_ADDR6).arg(lease->addr_.toText());
+              DHCPSRV_MYSQL_ADD_ADDR6).arg(lease->addr_.toText())
+              .arg(lease->type_);
 
     // Create the MYSQL_BIND array for the lease
     std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);
@@ -1651,13 +1653,14 @@ MySqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const {
 
 
 Lease6Ptr
-MySqlLeaseMgr::getLease6(Lease6::LeaseType /* type - not used yet */,
+MySqlLeaseMgr::getLease6(Lease6::LeaseType lease_type,
                          const isc::asiolink::IOAddress& addr) const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
-              DHCPSRV_MYSQL_GET_ADDR6).arg(addr.toText());
+              DHCPSRV_MYSQL_GET_ADDR6).arg(addr.toText())
+              .arg(lease_type);
 
     // Set up the WHERE clause value
-    MYSQL_BIND inbind[1];
+    MYSQL_BIND inbind[2];
     memset(inbind, 0, sizeof(inbind));
 
     std::string addr6 = addr.toText();
@@ -1670,6 +1673,11 @@ MySqlLeaseMgr::getLease6(Lease6::LeaseType /* type - not used yet */,
     inbind[0].buffer_length = addr6_length;
     inbind[0].length = &addr6_length;
 
+    // LEASE_TYPE
+    inbind[1].buffer_type = MYSQL_TYPE_TINY;
+    inbind[1].buffer = reinterpret_cast<char*>(&lease_type);
+    inbind[1].is_unsigned = MLM_TRUE;
+
     Lease6Ptr result;
     getLease(GET_LEASE6_ADDR, inbind, result);
 
@@ -1678,13 +1686,14 @@ MySqlLeaseMgr::getLease6(Lease6::LeaseType /* type - not used yet */,
 
 
 Lease6Collection
-MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */,
+MySqlLeaseMgr::getLeases6(Lease6::LeaseType lease_type,
                           const DUID& duid, uint32_t iaid) const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
-              DHCPSRV_MYSQL_GET_IAID_DUID).arg(iaid).arg(duid.toText());
+              DHCPSRV_MYSQL_GET_IAID_DUID).arg(iaid).arg(duid.toText())
+              .arg(lease_type);
 
     // Set up the WHERE clause value
-    MYSQL_BIND inbind[2];
+    MYSQL_BIND inbind[3];
     memset(inbind, 0, sizeof(inbind));
 
     // In the following statement, the DUID is being read.  However, the
@@ -1712,6 +1721,11 @@ MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */,
     inbind[1].buffer = reinterpret_cast<char*>(&iaid);
     inbind[1].is_unsigned = MLM_TRUE;
 
+    // LEASE_TYPE
+    inbind[2].buffer_type = MYSQL_TYPE_TINY;
+    inbind[2].buffer = reinterpret_cast<char*>(&lease_type);
+    inbind[2].is_unsigned = MLM_TRUE;
+
     // ... and get the data
     Lease6Collection result;
     getLeaseCollection(GET_LEASE6_DUID_IAID, inbind, result);
@@ -1720,15 +1734,16 @@ MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */,
 }
 
 Lease6Collection
-MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */,
+MySqlLeaseMgr::getLeases6(Lease6::LeaseType lease_type,
                           const DUID& duid, uint32_t iaid,
                           SubnetID subnet_id) const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_MYSQL_GET_IAID_SUBID_DUID)
-              .arg(iaid).arg(subnet_id).arg(duid.toText());
+              .arg(iaid).arg(subnet_id).arg(duid.toText())
+              .arg(lease_type);
 
     // Set up the WHERE clause value
-    MYSQL_BIND inbind[3];
+    MYSQL_BIND inbind[4];
     memset(inbind, 0, sizeof(inbind));
 
     // See the earlier description of the use of "const_cast" when accessing
@@ -1751,14 +1766,16 @@ MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */,
     inbind[2].buffer = reinterpret_cast<char*>(&subnet_id);
     inbind[2].is_unsigned = MLM_TRUE;
 
-    Lease6Ptr result;
-    getLease(GET_LEASE6_DUID_IAID_SUBID, inbind, result);
+    // LEASE_TYPE
+    inbind[3].buffer_type = MYSQL_TYPE_TINY;
+    inbind[3].buffer = reinterpret_cast<char*>(&lease_type);
+    inbind[3].is_unsigned = MLM_TRUE;
 
-    /// @todo: Implement getting one than more lease at the time
-    Lease6Collection collection;
-    collection.push_back(result);
+    // ... and get the data
+    Lease6Collection result;
+    getLeaseCollection(GET_LEASE6_DUID_IAID_SUBID, inbind, result);
 
-    return (collection);
+    return (result);
 }
 
 // Update lease methods.  These comprise common code that handles the actual
@@ -1823,7 +1840,8 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
     const StatementIndex stindex = UPDATE_LEASE6;
 
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
-              DHCPSRV_MYSQL_UPDATE_ADDR6).arg(lease->addr_.toText());
+              DHCPSRV_MYSQL_UPDATE_ADDR6).arg(lease->addr_.toText())
+              .arg(lease->type_);
 
     // Create the MYSQL_BIND array for the data being updated
     std::vector<MYSQL_BIND> bind = exchange6_->createBindForSend(lease);

+ 106 - 10
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc

@@ -824,8 +824,7 @@ TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSubnetId) {
 ///
 /// Adds leases to the database and checks that they can be accessed via
 /// a combination of DIUID and IAID.
-/// @todo: update this test once type checking/filtering is implemented
-TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) {
+TEST_F(MySqlLeaseMgrTest, getLeases6DuidIaid) {
     // Get the leases to be used for the test.
     vector<Lease6Ptr> leases = createLeases6();
     ASSERT_LE(6, leases.size());    // Expect to access leases 0 through 5
@@ -840,8 +839,8 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) {
                                                    *leases[1]->duid_,
                                                    leases[1]->iaid_);
 
-    // Should be three leases, matching leases[1], [4] and [5].
-    ASSERT_EQ(3, returned.size());
+    // Should be two leases, matching leases[1] and [4].
+    ASSERT_EQ(2, returned.size());
 
     // Easiest way to check is to look at the addresses.
     vector<string> addresses;
@@ -852,7 +851,6 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) {
     sort(addresses.begin(), addresses.end());
     EXPECT_EQ(straddress6_[1], addresses[0]);
     EXPECT_EQ(straddress6_[4], addresses[1]);
-    EXPECT_EQ(straddress6_[5], addresses[2]);
 
     // Check that nothing is returned when either the IAID or DUID match
     // nothing.
@@ -871,8 +869,7 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) {
 // @brief Get Lease4 by DUID and IAID (2)
 //
 // Check that the system can cope with a DUID of any size.
-/// @todo: update this test once type checking/filtering is implemented
-TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSize) {
+TEST_F(MySqlLeaseMgrTest, getLeases6DuidIaidSize) {
 
     // Create leases, although we need only one.
     vector<Lease6Ptr> leases = createLeases6();
@@ -902,6 +899,104 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSize) {
     // tests.
 }
 
+/// @brief Check that getLease6 methods discriminate by lease type.
+///
+/// Adds six leases, two per lease type all with the same duid and iad but
+/// with alternating subnet_ids.
+/// It then verifies that all of getLeases6() method variants correctly
+/// discriminate between the leases based on lease type alone.
+TEST_F(MySqlLeaseMgrTest, lease6LeaseTypeCheck) {
+
+    Lease6Ptr empty_lease(new Lease6());
+
+    DuidPtr duid(new DUID(vector<uint8_t>(8, 0x77)));
+
+    // Initialize unused fields.
+    empty_lease->t1_ = 0;                             // Not saved
+    empty_lease->t2_ = 0;                             // Not saved
+    empty_lease->fixed_ = false;                      // Unused
+    empty_lease->comments_ = std::string("");         // Unused
+    empty_lease->iaid_ = 142;
+    empty_lease->duid_ = DuidPtr(new DUID(*duid));
+    empty_lease->subnet_id_ = 23;
+    empty_lease->preferred_lft_ = 100;
+    empty_lease->valid_lft_ = 100;
+    empty_lease->cltt_ = 100;
+    empty_lease->fqdn_fwd_ = true;
+    empty_lease->fqdn_rev_ = true;
+    empty_lease->hostname_ = "myhost.example.com.";
+    empty_lease->prefixlen_ = 4;
+
+    // Make Two leases per lease type, all with the same  DUID, IAID but
+    // alternate the subnet_ids.
+    vector<Lease6Ptr> leases;
+    for (int i = 0; i < 6; ++i) {
+          Lease6Ptr lease(new Lease6(*empty_lease));
+          lease->type_ = leasetype6_[i / 2];
+          lease->addr_ = IOAddress(straddress6_[i]);
+          lease->subnet_id_ += (i % 2);
+          leases.push_back(lease);
+          EXPECT_TRUE(lmptr_->addLease(lease));
+     }
+
+    // Verify getting a single lease by type and address.
+    for (int i = 0; i < 6; ++i) {
+        // Look for exact match for each lease type.
+        Lease6Ptr returned = lmptr_->getLease6(leasetype6_[i / 2],
+                                               leases[i]->addr_);
+        // We should match one per lease type.
+        ASSERT_TRUE(returned);
+        EXPECT_TRUE(*returned == *leases[i]);
+
+        // Same address but wrong lease type, should not match.
+        returned = lmptr_->getLease6(leasetype6_[i / 2 + 1], leases[i]->addr_);
+        ASSERT_FALSE(returned);
+    }
+
+    // Verify getting a collection of leases by type, DUID, and IAID.
+    // Iterate over the lease types, asking for leases based on
+    // lease type, DUID, and IAID.
+    for (int i = 0; i < 3; ++i) {
+        Lease6Collection returned = lmptr_->getLeases6(leasetype6_[i],
+                                                       *duid, 142);
+        // We should match two per lease type.
+        ASSERT_EQ(2, returned.size());
+
+        // Collection order returned is not guaranteed.
+        // Easiest way to check is to look at the addresses.
+        vector<string> addresses;
+        for (Lease6Collection::const_iterator it = returned.begin();
+            it != returned.end(); ++it) {
+            addresses.push_back((*it)->addr_.toText());
+        }
+        sort(addresses.begin(), addresses.end());
+
+        // Now verify that the lease addresses match.
+        EXPECT_EQ(addresses[0], leases[(i * 2)]->addr_.toText());
+        EXPECT_EQ(addresses[1], leases[(i * 2 + 1)]->addr_.toText());
+    }
+
+    // Verify getting a collection of leases by type, DUID, IAID, and subnet id.
+    // Iterate over the lease types, asking for leases based on
+    // lease type, DUID, IAID, and subnet_id.
+    for (int i = 0; i < 3; ++i) {
+        Lease6Collection returned = lmptr_->getLeases6(leasetype6_[i],
+                                                   *duid, 142, 23);
+        // We should match one per lease type.
+        ASSERT_EQ(1, returned.size());
+        EXPECT_TRUE(*(returned[0]) == *leases[i * 2]);
+    }
+
+    // Verify getting a single lease by type, duid, iad, and subnet id.
+    for (int i = 0; i < 6; ++i) {
+        Lease6Ptr returned = lmptr_->getLease6(leasetype6_[i / 2],
+                                                *duid, 142, (23 + (i % 2)));
+        // We should match one per lease type.
+        ASSERT_TRUE(returned);
+        EXPECT_TRUE(*returned == *leases[i]);
+    }
+}
+
 /// @brief Check GetLease6 methods - access by DUID/IAID/SubnetID
 ///
 /// Adds leases to the database and checks that they can be accessed via
@@ -939,6 +1034,7 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetId) {
     EXPECT_FALSE(returned);
 }
 
+
 // @brief Get Lease4 by DUID, IAID & subnet ID (2)
 //
 // Check that the system can cope with a DUID of any size.
@@ -1051,7 +1147,7 @@ TEST_F(MySqlLeaseMgrTest, updateLease6) {
 
     // ... and check what is returned is what is expected.
     l_returned.reset();
-    l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]);
+    l_returned = lmptr_->getLease6(Lease6::LEASE_IA_PD, ioaddress6_[1]);
     ASSERT_TRUE(l_returned);
     detailCompareLease(leases[1], l_returned);
 
@@ -1063,14 +1159,14 @@ TEST_F(MySqlLeaseMgrTest, updateLease6) {
     lmptr_->updateLease6(leases[1]);
 
     l_returned.reset();
-    l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]);
+    l_returned = lmptr_->getLease6(Lease6::LEASE_IA_TA, ioaddress6_[1]);
     ASSERT_TRUE(l_returned);
     detailCompareLease(leases[1], l_returned);
 
     // Check we can do an update without changing data.
     lmptr_->updateLease6(leases[1]);
     l_returned.reset();
-    l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]);
+    l_returned = lmptr_->getLease6(Lease6::LEASE_IA_TA, ioaddress6_[1]);
     ASSERT_TRUE(l_returned);
     detailCompareLease(leases[1], l_returned);