Browse Source

[2140] LeaseMgr improvements.

Tomek Mrugalski 12 years ago
parent
commit
2c7936f05e
3 changed files with 398 additions and 40 deletions
  1. 55 0
      src/lib/dhcp/lease_mgr.cc
  2. 95 40
      src/lib/dhcp/lease_mgr.h
  3. 248 0
      src/lib/dhcp/tests/lease_mgr_unittest.cc

+ 55 - 0
src/lib/dhcp/lease_mgr.cc

@@ -0,0 +1,55 @@
+// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <sstream>
+#include <iostream>
+#include <map>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+#include <exceptions/exceptions.h>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+#include "lease_mgr.h"
+
+using namespace std;
+
+using namespace isc::dhcp;
+
+LeaseMgr::LeaseMgr(const std::string& dbconfig) {
+
+    vector<string> tokens;
+
+    boost::split(tokens, dbconfig, boost::is_any_of("\t "));
+
+    BOOST_FOREACH(std::string token, tokens) {
+        size_t pos = token.find("=");
+        if (pos != string::npos) {
+            string name = token.substr(0, pos);
+            string value = token.substr(pos + 1, -1);
+            parameters_.insert(pair<string,string>(name, value));
+        } else {
+            isc_throw(InvalidParameter, "Cannot parse " << token
+                      << ", expected format is name=value");
+        }
+
+    }
+
+    /// @todo: Parse dbconfig string
+}
+
+LeaseMgr::~LeaseMgr() {
+}

+ 95 - 40
src/lib/dhcp/lease_mgr.h

@@ -15,8 +15,25 @@
 #include <string>
 #include <fstream>
 #include <vector>
+#include <map>
+#include <asiolink/io_address.h>
 #include <boost/shared_ptr.hpp>
-#include "benchmark.h"
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Holds Client identifier
+class ClientId {
+ public:
+    ClientId(const std::vector<uint8_t>& duid);
+    ClientId(const char *duid, size_t len);
+    ClientId(uint32_t id);
+    ClientId(const isc::asiolink::IOAddress& addr);
+    const std::vector<uint8_t> getClientId() const;
+    bool operator == (const ClientId& other);
+ protected:
+    std::vector<uint8_t> clientid_;
+};
 
 /// @brief Holds DUID (DHCPv6 Unique Identifier)
 ///
@@ -41,8 +58,7 @@ class DUID {
     bool operator == (const DUID& other);
  protected:
     std::vector<uint8_t> duid_;
-    
-}
+};
 
 /// @brief Structure that holds a lease for IPv4 address
 ///
@@ -241,86 +257,125 @@ typedef boost::shared_ptr<Lease6> Lease6Ptr;
 typedef boost::shared_ptr<const Lease6> ConstLease6Ptr;
 
 
-/// @brief In-memory + lease file database implementation
-///
-/// This is a simplified in-memory database that mimics ISC DHCP4 implementation.
-/// It uses STL and boost: std::map for storage, boost::shared ptr for memory
-/// management. It does use C file operations (fopen, fwrite, etc.), because
-/// C++ streams does not offer any easy way to flush their contents, like
-/// fflush() and fsync() does.
+/// @brief Abstract Lease Manager
 ///
-/// IPv4 address is used as a key in the hash.
+/// This is an abstract API for lease database backends. It provides unified
+/// interface to all backends. As this is an abstract class, it should not
+/// be used directly, but rather specialized derived class should be used
+/// instead.
 class LeaseMgr {
 public:
 
+    /// Client Hardware address
+    typedef std::vector<uint8_t> HWAddr;
+
     /// @brief The sole lease manager constructor
     ///
-    /// @param filename name of the lease file (will be overwritten)
-    /// @param sync should operations be
-    LeaseMgr(const std::string& filename, bool sync);
+    /// dbconfig is a generic way of passing parameters. Parameters
+    /// are passed in the "name=value" format, separated by spaces.
+    /// Values may be enclosed in double quotes, if needed.
+    ///
+    /// @param dbconfig database configuration
+    LeaseMgr(const std::string& dbconfig);
 
     /// @brief Destructor (closes file)
-    ~LeaseMgr();
+    virtual ~LeaseMgr();
 
-    /// @brief adds an IPv4 lease
+    /// @brief Adds an IPv4 lease.
     ///
     /// @param lease lease to be added
-    bool addLease(Lease4Ptr lease);
+    virtual bool addLease(Lease4Ptr lease) = 0;
 
-    /// @brief adds a IPv6 lease
+    /// @brief Adds an IPv6 lease.
     ///
     /// @param lease lease to be added
-    bool addLease(Lease6Ptr lease);
+    virtual bool addLease(Lease6Ptr lease) = 0;
 
-    /// @brief returns existing IPv4 lease
+    /// @brief Returns existing IPv4 lease for specified IPv4 address.
     ///
     /// @param addr address of the searched lease
     ///
-    /// @return smart pointer to the lease (or NULL if lease is not found)
-    Lease4Ptr getLease4(isc::asiolink::IOAddress addr);
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr) const = 0;
 
-#error "Implement this"
-    Lease4Ptr getLease4(hwaddress );
+    /// @brief Returns existing IPv4 lease for specified hardware address.
+    ///
+    /// @param hwaddr hardware address of the client
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(const HWAddr& hwaddr) const = 0;
 
-    Lease4Ptr getLease4(client-id);
+    /// @brief Returns existing IPv4 lease for specified client-id
+    ///
+    /// @param clientid client identifier
+    virtual Lease4Ptr getLease4(const ClientId& clientid) const = 0;
 
-    /// @brief returns existing IPv4 lease
+    /// @brief Returns existing IPv6 lease for a given IPv6 address.
     ///
     /// @param addr address of the searched lease
     ///
-    /// @return smart pointer to the lease (or NULL if lease is not found)
-    Lease6Ptr getLease6(isc::asiolink::IOAddress addr);
-
-#error "Implement this"
-    Lease6Ptr getLease6(DUID);
-
-    Lease6Ptr getLease6(DUID, iaid);
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease6Ptr getLease6(isc::asiolink::IOAddress addr) const = 0;
 
+    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+    ///
+    /// @param duid client DUID
+    /// @param iaid IA identifier
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease6Ptr getLease6(const DUID& duid, uint32_t iaid) const = 0;
 
-#error "Implement this"
-    bool updateLease4(Lease4Ptr lease4);
+    /// @brief Updates IPv4 lease.
+    ///
+    /// @param lease4 The lease to be updated.
+    ///
+    /// If no such lease is present, an exception will be thrown.
+    virtual void updateLease4(Lease4Ptr lease4) = 0;
 
-    bool updateLease6(Lease6Ptr lease6);
+    /// @brief Updates IPv4 lease.
+    ///
+    /// @param lease4 The lease to be updated.
+    ///
+    /// If no such lease is present, an exception will be thrown.
+    virtual void updateLease6(Lease6Ptr lease6) = 0;
 
     /// @brief Deletes a lease.
     ///
     /// @param addr IPv4 address of the lease to be deleted.
     ///
     /// @return true if deletion was successful, false if no such lease exists
-    bool deleteLease4(uint32_t addr);
+    virtual bool deleteLease4(uint32_t addr) = 0;
 
     /// @brief Deletes a lease.
     ///
     /// @param addr IPv4 address of the lease to be deleted.
     ///
     /// @return true if deletion was successful, false if no such lease exists
-    bool deleteLease6(isc::asiolink::IOAddress addr);
+    virtual bool deleteLease6(isc::asiolink::IOAddress addr) = 0;
 
-protected:
+    /// @brief Returns backend name.
+    ///
+    /// Each backend have specific name, e.g. "mysql" or "sqlite".
+    virtual std::string getName() const = 0;
 
-};
+    /// @brief Returns description of the backend.
+    ///
+    /// This description may be multiline text that describes the backend.
+    virtual std::string getDescription() const = 0;
 
+    /// @brief Returns backend version.
+    virtual std::string getVersion() const = 0;
 
+    /// @todo: Add pool management here
 
+    /// @todo: Add host management here
+protected:
 
+    /// @brief list of parameters passed in dbconfig
+    std::map<std::string, std::string> parameters_;
 };
+
+
+}; // end of isc::dhcp namespace
+
+}; // end of isc namespace

+ 248 - 0
src/lib/dhcp/tests/lease_mgr_unittest.cc

@@ -0,0 +1,248 @@
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+#include <gtest/gtest.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp/lease_mgr.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+class Memfile_LeaseMgr : public LeaseMgr {
+public:
+
+    /// @brief The sole lease manager constructor
+    ///
+    /// dbconfig is a generic way of passing parameters. Parameters
+    /// are passed in the "name=value" format, separated by spaces.
+    /// Values may be enclosed in double quotes, if needed.
+    ///
+    /// @param dbconfig database configuration
+    Memfile_LeaseMgr(const std::string& dbconfig);
+
+    /// @brief Destructor (closes file)
+    virtual ~Memfile_LeaseMgr();
+
+    /// @brief Adds an IPv4 lease.
+    ///
+    /// @param lease lease to be added
+    virtual bool addLease(Lease4Ptr lease);
+
+    /// @brief Adds an IPv6 lease.
+    ///
+    /// @param lease lease to be added
+    virtual bool addLease(Lease6Ptr lease);
+
+    /// @brief Returns existing IPv4 lease for specified IPv4 address.
+    ///
+    /// @param addr address of the searched lease
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr) const;
+
+    /// @brief Returns existing IPv4 lease for specified hardware address.
+    ///
+    /// @param hwaddr hardware address of the client
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(const HWAddr& hwaddr) const;
+
+    /// @brief Returns existing IPv4 lease for specified client-id
+    ///
+    /// @param clientid client identifier
+    virtual Lease4Ptr getLease4(const ClientId& clientid) const;
+
+    /// @brief Returns existing IPv6 lease for a given IPv6 address.
+    ///
+    /// @param addr address of the searched lease
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    Lease6Ptr getLease6(isc::asiolink::IOAddress addr) const;
+
+    /// @brief Returns existing IPv6 lease for a given DUID+IA combination
+    ///
+    /// @param duid client DUID
+    /// @param iaid IA identifier
+    ///
+    /// @return smart pointer to the lease (or NULL if a lease is not found)
+    Lease6Ptr getLease6(const DUID& duid, uint32_t iaid) const;
+
+    /// @brief Updates IPv4 lease.
+    ///
+    /// @param lease4 The lease to be updated.
+    ///
+    /// If no such lease is present, an exception will be thrown.
+    void updateLease4(Lease4Ptr lease4);
+
+    /// @brief Updates IPv4 lease.
+    ///
+    /// @param lease4 The lease to be updated.
+    ///
+    /// If no such lease is present, an exception will be thrown.
+    void updateLease6(Lease6Ptr lease6);
+
+    /// @brief Deletes a lease.
+    ///
+    /// @param addr IPv4 address of the lease to be deleted.
+    ///
+    /// @return true if deletion was successful, false if no such lease exists
+    bool deleteLease4(uint32_t addr);
+
+    /// @brief Deletes a lease.
+    ///
+    /// @param addr IPv4 address of the lease to be deleted.
+    ///
+    /// @return true if deletion was successful, false if no such lease exists
+    bool deleteLease6(isc::asiolink::IOAddress addr);
+
+    /// @brief Returns backend name.
+    ///
+    /// Each backend have specific name, e.g. "mysql" or "sqlite".
+    std::string getName() const { return "memfile"; }
+
+    /// @brief Returns description of the backend.
+    ///
+    /// This description may be multiline text that describes the backend.
+    std::string getDescription() const;
+
+    /// @brief Returns backend version.
+    std::string getVersion() const { return "test-version"; }
+protected:
+
+
+};
+
+Memfile_LeaseMgr::Memfile_LeaseMgr(const std::string& dbconfig)
+    : LeaseMgr(dbconfig) {
+}
+
+Memfile_LeaseMgr::~Memfile_LeaseMgr() {
+}
+
+bool Memfile_LeaseMgr::addLease(boost::shared_ptr<isc::dhcp::Lease4>) {
+    return (false);
+}
+
+bool Memfile_LeaseMgr::addLease(boost::shared_ptr<isc::dhcp::Lease6>) {
+    return (false);
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(isc::asiolink::IOAddress) const {
+    return (Lease4Ptr());
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& ) const {
+    return (Lease4Ptr());
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& ) const {
+    return (Lease4Ptr());
+}
+
+Lease6Ptr Memfile_LeaseMgr::getLease6(isc::asiolink::IOAddress) const {
+    return (Lease6Ptr());
+}
+
+Lease6Ptr Memfile_LeaseMgr::getLease6(const DUID& , uint32_t ) const {
+    return (Lease6Ptr());
+}
+
+void Memfile_LeaseMgr::updateLease4(Lease4Ptr ) {
+}
+
+void Memfile_LeaseMgr::updateLease6(Lease6Ptr ) {
+
+}
+
+bool Memfile_LeaseMgr::deleteLease4(uint32_t ) {
+    return (false);
+}
+
+bool Memfile_LeaseMgr::deleteLease6(isc::asiolink::IOAddress ) {
+    return (false);
+}
+
+std::string Memfile_LeaseMgr::getDescription() const {
+    return (string("This is a dummy memfile backend implementation.\n"
+                   "It does not offer any useful lease management and its only\n"
+                   "purpose is to test abstract lease manager API."));
+}
+
+#if 0
+bool Memfile_LeaseMgr::addLease(Lease4Ptr lease) {
+    if (ip4Hash_.find(lease->addr) != ip4Hash_.end()) {
+        // there is such an address already in the hash
+        return false;
+    }
+    ip4Hash_.insert(pair<uint32_t, Lease4Ptr>(lease->addr, lease));
+    lease->hostname = "add";
+    writeLease(lease);
+    return (true);
+}
+
+Lease4Ptr Memfile_LeaseMgr::getLease(uint32_t addr) {
+    leaseIt x = ip4Hash_.find(addr);
+    if (x != ip4Hash_.end()) {
+        return x->second; // found
+    }
+
+    // not found
+    return Lease4Ptr();
+}
+
+Lease4Ptr Memfile_LeaseMgr::updateLease(uint32_t addr, uint32_t new_cltt) {
+    leaseIt x = ip4Hash_.find(addr);
+    if (x != ip4Hash_.end()) {
+        x->second->cltt = new_cltt;
+        x->second->hostname = "update";
+        writeLease(x->second);
+        return x->second;
+    }
+    return Lease4Ptr();
+}
+
+bool Memfile_LeaseMgr::deleteLease(uint32_t addr) {
+    leaseIt x = ip4Hash_.find(addr);
+    if (x != ip4Hash_.end()) {
+        x->second->hostname = "delete";
+        writeLease(x->second);
+        ip4Hash_.erase(x);
+        return true;
+    }
+    return false;
+}
+#endif
+
+namespace {
+// empty class for now, but may be extended once Addr6 becomes bigger
+class LeaseMgrTest : public ::testing::Test {
+public:
+    LeaseMgrTest() {
+    }
+};
+
+TEST_F(LeaseMgrTest, constructor) {
+
+    LeaseMgr * leaseMgr = new Memfile_LeaseMgr("param1=value1");
+
+    delete leaseMgr;
+}
+
+}; // end of anonymous namespace