Browse Source

[5332] Revamped lease_cmds hook lib to use hook callouts for command processing

The changes were patterned after what was done in subnets_cmds hook lib.

src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc
    New file which provides callout functions for each lease command
    as well as load() and unload() (formerly in load_unload.cc)

src/hooks/dhcp/lease_cmds/load_unload.cc
    File deleted

src/hooks/dhcp/lease_cmds/Makefile.am
    Added lease_cmds_callouts.cc
    Removed load_unload.cc

src/hooks/dhcp/lease_cmds/lease_cmds.h
src/hooks/dhcp/lease_cmds/lease_cmds.cc
    LeaseCmdsImpl - removed ctor, dtor, registerCommands, deregisterCommands,
    and changed handlers to non static

    LeaseCmds - added wrapper methods around LeaseCmdImpl handlers
Thomas Markwalder 7 years ago
parent
commit
03636abdf6

+ 1 - 1
src/hooks/dhcp/lease_cmds/Makefile.am

@@ -25,9 +25,9 @@ CLEANFILES = *.gcno *.gcda lease_cmds_messages.h lease_cmds_messages.cc s-messag
 noinst_LTLIBRARIES = liblease_cmds.la
 
 liblease_cmds_la_SOURCES  = lease_cmds.cc lease_cmds.h
+liblease_cmds_la_SOURCES += lease_cmds_callouts.cc
 liblease_cmds_la_SOURCES += lease_parser.h lease_parser.cc
 liblease_cmds_la_SOURCES += lease_cmds_log.cc lease_cmds_log.h
-liblease_cmds_la_SOURCES += load_unload.cc
 liblease_cmds_la_SOURCES += version.cc
 
 nodist_liblease_cmds_la_SOURCES = lease_cmds_messages.cc lease_cmds_messages.h

+ 112 - 170
src/hooks/dhcp/lease_cmds/lease_cmds.cc

@@ -35,116 +35,77 @@ namespace lease_cmds {
 /// @brief Wrapper class around reservation command handlers.
 class LeaseCmdsImpl {
 public:
-    LeaseCmdsImpl();
-
-    ~LeaseCmdsImpl();
-
-/// @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.
-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;
-
-    /// @brief Specifies subnet-id (always used)
-    SubnetID subnet_id;
-
-    /// @brief Specifies IPv4/v6 address (used when query_type is TYPE_ADDR)
-    IOAddress addr;
-
-    /// @brief Specifies hardware address (used when query_type is TYPE_HWADDR)
-    HWAddrPtr hwaddr;
-
-    /// @brief Specifies identifier value (used when query_type is TYPE_DUID)
-    isc::dhcp::DuidPtr duid;
-
-    /// @brief Attempts to covert text to one of specified types
+    /// @brief Parameters specified for reservation-get and reservation-del
     ///
-    /// Supported values are: "address", hw-address and duid.
+    /// 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)
     ///
-    /// @param txt text to be converted
-    /// @return value converted to Parameters::Type
-    /// @throw BadValue if unsupported type is specified
-    static Type txtToType(const std::string& txt) {
-        if (txt == "address") {
-            return (Parameters::TYPE_ADDR);
-        } else if (txt == "hw-address") {
-            return (Parameters::TYPE_HWADDR);
-        } else if (txt == "duid") {
-            return (Parameters::TYPE_DUID);
-        } else {
-            isc_throw(BadValue, "Incorrect identifier type: "
-                      << txt << ", the only supported values are: "
-                      "address, hw-address, duid");
+    /// This class stores those parameters and is used to pass them around.
+    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;
+
+        /// @brief Specifies subnet-id (always used)
+        SubnetID subnet_id;
+
+        /// @brief Specifies IPv4/v6 address (used when query_type is TYPE_ADDR)
+        IOAddress addr;
+
+        /// @brief Specifies hardware address (used when query_type is TYPE_HWADDR)
+        HWAddrPtr hwaddr;
+
+        /// @brief Specifies identifier value (used when query_type is TYPE_DUID)
+        isc::dhcp::DuidPtr duid;
+
+        /// @brief Attempts to covert text to one of specified types
+        ///
+        /// Supported values are: "address", hw-address and duid.
+        ///
+        /// @param txt text to be converted
+        /// @return value converted to Parameters::Type
+        /// @throw BadValue if unsupported type is specified
+        static Type txtToType(const std::string& txt) {
+            if (txt == "address") {
+                return (Parameters::TYPE_ADDR);
+            } else if (txt == "hw-address") {
+                return (Parameters::TYPE_HWADDR);
+            } else if (txt == "duid") {
+                return (Parameters::TYPE_DUID);
+            } else {
+                isc_throw(BadValue, "Incorrect identifier type: "
+                          << txt << ", the only supported values are: "
+                          "address, hw-address, duid");
+            }
         }
-    }
-
-    /// @brief specifies parameter types (true = query by address, false =
-    ///         query by identifier-type,identifier)
-    Type query_type;
 
-    /// @brief Lease type (NA,TA or PD) used for v6 leases
-    Lease::Type lease_type;
+        /// @brief specifies parameter types (true = query by address, false =
+        ///         query by identifier-type,identifier)
+        Type query_type;
 
-    /// @brief IAID identifier used for v6 leases
-    uint32_t iaid;
-
-    /// @brief Default constructor.
-    Parameters()
-        :addr("::"), query_type(TYPE_ADDR), lease_type(Lease::TYPE_NA),
-         iaid(0) {
-    }
-};
+        /// @brief Lease type (NA,TA or PD) used for v6 leases
+        Lease::Type lease_type;
 
-private:
+        /// @brief IAID identifier used for v6 leases
+        uint32_t iaid;
 
-    /// @brief Registers commands:
-    ///
-    /// Registers:
-    /// - lease4-add
-    /// - lease6-add
-    /// - lease4-get
-    /// - lease6-get
-    /// - lease4-del
-    /// - lease6-del
-    /// - lease4-update
-    /// - lease6-update
-    /// - lease4-wipe
-    /// - lease6-wipe
-
-    /// @throw Unexpected if CommandMgr is not available (should not happen)
-    void registerCommands();
-
-    /// @brief Deregisters commands:
-    ///
-    /// Deregisters:
-    /// - lease4-add
-    /// - lease6-add
-    /// - lease4-get
-    /// - lease6-get
-    /// - lease4-del
-    /// - lease6-del
-    /// - lease4-update
-    /// - lease6-update
-    /// - lease4-wipe
-    /// - lease6-wipe
-    ///
-    /// @throw Unexpected if CommandMgr is not available (should not happen)
-    void deregisterCommands();
+        /// @brief Default constructor.
+        Parameters()
+            :addr("::"), query_type(TYPE_ADDR), lease_type(Lease::TYPE_NA),
+             iaid(0) {
+        }
+    };
 
+public:
     /// @brief lease4-add, lease6-add command handler
     ///
     /// This command attempts to add a lease.
@@ -192,7 +153,7 @@ private:
     /// @param command should be 'lease4-add' or 'lease6-add'
     /// @param args must contain host reservation definition.
     /// @return result of the operation
-    static ConstElementPtr
+    ConstElementPtr
     leaseAddHandler(const string& command, ConstElementPtr args);
 
     /// @brief lease4-get, lease6-get command handler
@@ -237,7 +198,7 @@ private:
     /// @param command "lease4-get" or "lease6-get"
     /// @param args must contain host reservation definition.
     /// @return result of the operation (includes lease details, if found)
-    static ConstElementPtr
+    ConstElementPtr
     leaseGetHandler(const string& command, ConstElementPtr args);
 
     /// @brief lease4-del command handler
@@ -267,7 +228,7 @@ private:
     /// @param command should be 'lease4-del' (but it's ignored)
     /// @param args must contain host reservation definition.
     /// @return result of the operation (host will be included as parameters, if found)
-    static ConstElementPtr
+    ConstElementPtr
     lease4DelHandler(const string& command, ConstElementPtr args);
 
     /// @brief lease6-del command handler
@@ -300,7 +261,7 @@ private:
     /// @param command should be 'lease6-del' (but it's ignored)
     /// @param args must contain host reservation definition.
     /// @return result of the operation (host will be included as parameters, if found)
-    static ConstElementPtr
+    ConstElementPtr
     lease6DelHandler(const string& command, ConstElementPtr args);
 
     /// @brief lease4-update handler
@@ -323,7 +284,7 @@ private:
     ///
     /// @param command - should be "lease4-update", but it is ignored
     /// @param args arguments that describe the lease being updated.
-    static ConstElementPtr
+    ConstElementPtr
     lease4UpdateHandler(const string& command, ConstElementPtr args);
 
     /// @brief lease6-update handler
@@ -347,7 +308,7 @@ private:
     ///
     /// @param command - should be "lease6-update" (but it is ignored)
     /// @param args arguments that describe the lease being updated.
-    static ConstElementPtr
+    ConstElementPtr
     lease6UpdateHandler(const string& command, ConstElementPtr args);
 
     /// @brief lease4-wipe handler
@@ -366,7 +327,7 @@ private:
     /// }";
     /// @param command - should be "lease4-wipe" (but is ignored)
     /// @param args arguments that describe the lease being updated.
-    static ConstElementPtr
+    ConstElementPtr
     lease4WipeHandler(const string& command, ConstElementPtr args);
 
     /// @brief lease6-wipe handler
@@ -385,7 +346,7 @@ private:
     /// }";
     /// @param command - should be "lease4-wipe" (but is ignored)
     /// @param args arguments that describe the lease being updated.
-    static ConstElementPtr
+    ConstElementPtr
     lease6WipeHandler(const string& command, ConstElementPtr args);
 
     /// @brief Extracts parameters required for reservation-get and reservation-del
@@ -397,64 +358,9 @@ private:
     /// @param args arguments passed to command
     /// @return parsed parameters
     /// @throw BadValue if input arguments don't make sense.
-    static Parameters getParameters(bool v6, const ConstElementPtr& args);
+    Parameters getParameters(bool v6, const ConstElementPtr& args);
 };
 
-LeaseCmdsImpl::LeaseCmdsImpl() {
-    registerCommands();
-}
-
-LeaseCmdsImpl::~LeaseCmdsImpl() {
-    deregisterCommands();
-}
-
-void LeaseCmdsImpl::registerCommands() {
-    /// @todo: Use registration mechanism once #5314 is merged.
-    /// See #5321 discussion.
-    CommandMgr::instance().registerCommand("lease4-add",
-        boost::bind(&LeaseCmdsImpl::leaseAddHandler, _1, _2));
-    CommandMgr::instance().registerCommand("lease6-add",
-        boost::bind(&LeaseCmdsImpl::leaseAddHandler, _1, _2));
-
-    CommandMgr::instance().registerCommand("lease4-get",
-        boost::bind(&LeaseCmdsImpl::leaseGetHandler, _1, _2));
-    CommandMgr::instance().registerCommand("lease6-get",
-        boost::bind(&LeaseCmdsImpl::leaseGetHandler, _1, _2));
-
-    CommandMgr::instance().registerCommand("lease4-del",
-    boost::bind(&LeaseCmdsImpl::lease4DelHandler, _1, _2));
-    CommandMgr::instance().registerCommand("lease6-del",
-    boost::bind(&LeaseCmdsImpl::lease6DelHandler, _1, _2));
-
-    CommandMgr::instance().registerCommand("lease4-update",
-    boost::bind(&LeaseCmdsImpl::lease4UpdateHandler, _1, _2));
-    CommandMgr::instance().registerCommand("lease6-update",
-    boost::bind(&LeaseCmdsImpl::lease6UpdateHandler, _1, _2));
-
-    CommandMgr::instance().registerCommand("lease4-wipe",
-    boost::bind(&LeaseCmdsImpl::lease4WipeHandler, _1, _2));
-    CommandMgr::instance().registerCommand("lease6-wipe",
-    boost::bind(&LeaseCmdsImpl::lease6WipeHandler, _1, _2));
-}
-
-void LeaseCmdsImpl::deregisterCommands() {
-    /// @todo: Use deregistration mechanism once #5321 discussion is done
-    CommandMgr::instance().deregisterCommand("lease4-add");
-    CommandMgr::instance().deregisterCommand("lease6-add");
-
-    CommandMgr::instance().deregisterCommand("lease4-get");
-    CommandMgr::instance().deregisterCommand("lease6-get");
-
-    CommandMgr::instance().deregisterCommand("lease4-del");
-    CommandMgr::instance().deregisterCommand("lease6-del");
-
-    CommandMgr::instance().deregisterCommand("lease4-update");
-    CommandMgr::instance().deregisterCommand("lease6-update");
-
-    CommandMgr::instance().deregisterCommand("lease4-wipe");
-    CommandMgr::instance().deregisterCommand("lease6-wipe");
-}
-
 ConstElementPtr
 LeaseCmdsImpl::leaseAddHandler(const std::string& name,
                                ConstElementPtr params) {
@@ -883,12 +789,48 @@ LeaseCmdsImpl::lease6WipeHandler(const string& /*cmd*/, ConstElementPtr params)
     }
 }
 
-LeaseCmds::LeaseCmds()
-    :impl_(new LeaseCmdsImpl()) {
+ConstElementPtr
+LeaseCmds::leaseAddHandler(const string& command, ConstElementPtr args) {
+    return(impl_->leaseAddHandler(command, args));
+}
+
+ConstElementPtr
+LeaseCmds::leaseGetHandler(const string& command, ConstElementPtr args) {
+    return(impl_->leaseGetHandler(command, args));
+}
+
+ConstElementPtr
+LeaseCmds::lease4DelHandler(const string& command, ConstElementPtr args) {
+    return(impl_->lease4DelHandler(command, args));
+}
+
+ConstElementPtr
+LeaseCmds::lease6DelHandler(const string& command, ConstElementPtr args) {
+    return(impl_->lease6DelHandler(command, args));
 }
 
-LeaseCmds::~LeaseCmds() {
-    impl_.reset();
+ConstElementPtr
+LeaseCmds::lease4UpdateHandler(const string& command, ConstElementPtr args) {
+    return(impl_->lease4UpdateHandler(command, args));
+}
+
+ConstElementPtr
+LeaseCmds::lease6UpdateHandler(const string& command, ConstElementPtr args) {
+    return(impl_->lease6UpdateHandler(command, args));
+}
+
+ConstElementPtr
+LeaseCmds::lease4WipeHandler(const string& command, ConstElementPtr args) {
+    return(impl_->lease4WipeHandler(command, args));
+}
+
+ConstElementPtr
+LeaseCmds::lease6WipeHandler(const string& command, ConstElementPtr args) {
+    return(impl_->lease6WipeHandler(command, args));
+}
+
+LeaseCmds::LeaseCmds()
+    :impl_(new LeaseCmdsImpl()) {
 }
 
 };

+ 251 - 36
src/hooks/dhcp/lease_cmds/lease_cmds.h

@@ -7,6 +7,7 @@
 #ifndef LEASE_CMDS_H
 #define LEASE_CMDS_H
 
+#include <cc/data.h>
 #include <boost/shared_ptr.hpp>
 
 namespace isc {
@@ -15,48 +16,262 @@ namespace lease_cmds {
 /// @brief Forward declaration of implementation class.
 class LeaseCmdsImpl;
 
-/// @brief A wrapper class that provides convenient initialization to the library.
+/// @brief Implements the logic for processing commands pertaining to
+/// lease manipulation.
 ///
-/// This is a wrapper class that simply registers extra commands when
-/// instantiated and deregisters them when the instance is destroyed.
-///
-/// For an actual implementation, see @ref LeaseCmdsImpl class in lease_cmds.cc file.
+/// This class is used by the callouts implementing command handlers for
+/// lease manipulations.
 class LeaseCmds {
 public:
-
-    /// @brief Initializes additional lease commands.
-    ///
-    /// It registers the following commands:
-    /// - lease4-add
-    /// - lease6-add
-    /// - lease4-get
-    /// - lease6-get
-    /// - lease4-del
-    /// - lease6-del
-    /// - lease4-update
-    /// - lease6-update
-    /// - lease4-del-all
-    /// - lease6-del-all
-    ///
-    /// @throw Unexpected If any of the above fails.
+    /// @brief Constructor.
+    ///
+    /// It creates an instance of the @c LeaseCmdsImpl.
     LeaseCmds();
 
-    /// @brief Destructor
-    ///
-    /// Unregisters commands:
-    /// - lease4-add
-    /// - lease6-add
-    /// - lease4-get
-    /// - lease6-get
-    /// - lease4-del
-    /// - lease6-del
-    /// - lease4-update
-    /// - lease6-update
-    /// - lease4-del-all
-    /// - lease6-del-all
-    ~LeaseCmds();
-private:
+    /// @brief lease4-add, lease6-add command handler
+    ///
+    /// This command attempts to add a lease.
+    ///
+    /// An example full command looks as follows. Note that the args
+    /// parameter is expected to contain the "arguments" portion of it.
+    /// This function covers both v4 and v6 leases.
+    ///
+    /// Example command for v4:
+    /// {
+    ///     "command": "lease4-add",
+    ///     "parameters": {
+    ///         "address": "192.0.2.1",
+    ///         "hwaddr": "00:01:02:03:04:05",
+    ///         "client-id": "this-is-a-client",
+    ///         "valid-lft": 3600,
+    ///         "expire": 12345678,
+    ///         "subnet-id": 1,
+    ///         "fqdn-fwd": true,
+    ///         "fqdn-rev": true,
+    ///         "hostname": "myhost.example.org",
+    ///         "state": 0
+    ///     }
+    /// }
+    /// Example command for v6:
+    /// {
+    ///     "command": "lease6-add",
+    ///     "arguments": {
+    ///         "subnet-id": 66,
+    ///         "ip-address": "2001:db8:abcd::",
+    ///         "type": "IA_PD",
+    ///         "prefix-len": 48,
+    ///         "duid": "01:02:03:04:05:06:07:08",
+    ///         "iaid": 1234,
+    ///         "preferred-lft": 500,
+    ///         "valid-lft": 1000,
+    ///         "expire": 12345678,
+    ///         "fqdn-fwd": true,
+    ///         "fqdn-rev": true,
+    ///         "hostname": "urania.example.org""
+    ///     }
+    /// }
 
+    ///
+    /// @param command should be 'lease4-add' or 'lease6-add'
+    /// @param args must contain host reservation definition.
+    /// @return result of the operation
+    data::ConstElementPtr
+    leaseAddHandler(const std::string& command, data::ConstElementPtr args);
+
+    /// @brief lease4-get, lease6-get command handler
+    ///
+    /// This command attempts to retrieve a lease that match selected criteria.
+    /// The following types of parameters are supported:
+    /// - (subnet-id, address) for both v4 and v6
+    /// - (subnet-id, identifier-type, identifier) for v4
+    /// - (subnet-id, type, iana, identifier-type, identifier) for v6
+    ///
+    /// Example command for query by (subnet-id, address):
+    /// {
+    ///     "command": "lease4-get",
+    ///     "arguments": {
+    ///         "subnet-id": 1,
+    ///         "ip-address": "192.0.2.202"
+    ///     }
+    /// }
+    ///
+    /// Example command for query by (subnet-id, identifier-type, identifier)
+    /// {
+    ///     "command": "lease4-get",
+    ///     "arguments": {
+    ///         "subnet-id": 1,
+    ///         "identifier-type": "hw-address",
+    ///         "identifier": "00:01:02:03:04:05"
+    ///     }
+    /// }
+    ///
+    /// Example command for query by (subnet-id, type, iana, identifier-type,
+    ///                               identifier):
+    /// {
+    ///     "command": "lease6-get",
+    ///     "arguments": {
+    ///     "subnet-id": 66,
+    ///     "iaid": 42,
+    ///     "type": "IA_NA",
+    ///     "identifier-type": "duid",
+    ///     "identifier": "77:77:77:77:77:77:77:77"
+    ///     }
+    /// }
+    /// @param command "lease4-get" or "lease6-get"
+    /// @param args must contain host reservation definition.
+    /// @return result of the operation (includes lease details, if found)
+    data::ConstElementPtr
+    leaseGetHandler(const std::string& command, data::ConstElementPtr args);
+
+    /// @brief lease4-del command handler
+    ///
+    /// This command attempts to delete an IPv4 lease that match selected
+    /// criteria. Two types of parameters are supported: (subnet-id, address) or
+    /// (subnet-id, identifier-type, identifier).
+    ///
+    /// Example command for deletion by (subnet-id, address):
+    /// {
+    ///     "command": "lease4-del",
+    ///     "arguments": {
+    ///         "subnet-id": 1,
+    ///         "ip-address": "192.0.2.202"
+    ///     }
+    /// }
+    ///
+    /// Example command for deletion by (subnet-id, identifier-type, identifier)
+    /// {
+    ///     "command": "lease4-del",
+    ///     "arguments": {
+    ///         "subnet-id": 1,
+    ///         "identifier-type": "hw-address",
+    ///         "identifier": "00:01:02:03:04:05"
+    ///     }
+    /// }";
+    /// @param command should be 'lease4-del' (but it's ignored)
+    /// @param args must contain host reservation definition.
+    /// @return result of the operation (host will be included as parameters, if found)
+    data::ConstElementPtr
+    lease4DelHandler(const std::string& command, data::ConstElementPtr args);
+
+    /// @brief lease6-del command handler
+    ///
+    /// This command attempts to delete a lease that match selected criteria.
+    /// Two types of parameters are supported: (subnet-id, address) or
+    /// (subnet-id, type, iaid, identifier-type, identifier).
+    ///
+    /// Example command for deletion by (subnet-id, address):
+    /// {
+    ///     "command": "lease6-del",
+    ///     "arguments": {
+    ///         "subnet-id": 1,
+    ///         "ip-address": "192.0.2.202"
+    ///     }
+    /// }
+    ///
+    /// Example command for deletion by (subnet-id, type, iaid, identifier-type,
+    /// identifier):
+    /// {
+    ///     "command": "lease6-del",
+    ///     "arguments": {
+    ///         "subnet-id": 1,
+    ///         "type": "IA_NA",
+    ///         "iaid": 123456,
+    ///         "identifier-type": "hw-address",
+    ///         "identifier": "00:01:02:03:04:05"
+    ///     }
+    /// }";
+    /// @param command should be 'lease6-del' (but it's ignored)
+    /// @param args must contain host reservation definition.
+    /// @return result of the operation (host will be included as parameters, if found)
+    data::ConstElementPtr
+    lease6DelHandler(const std::string& command, data::ConstElementPtr args);
+
+    /// @brief lease4-update handler
+    ///
+    /// This command attempts to update existing IPv4 lease. The parameters
+    /// specified will replace existing lease. The only condition is that
+    /// the IP address must not change. If you want to change the IP address,
+    /// please use lease4-del and lease4-add instead.
+    ///
+    /// Example command:
+    /// {
+    ///     "command": "lease4-update",
+    ///     "arguments": {
+    ///         "subnet-id": 44,
+    ///         "ip-address": "192.0.2.1",
+    ///         "hw-address": "1a:1b:1c:1d:1e:1f",
+    ///         "hostname": "newhostname.example.org"
+    ///     }
+    /// };
+    ///
+    /// @param command - should be "lease4-update", but it is ignored
+    /// @param args arguments that describe the lease being updated.
+    data::ConstElementPtr
+    lease4UpdateHandler(const std::string& command, data::ConstElementPtr args);
+
+    /// @brief lease6-update handler
+    ///
+    /// This command attempts to update existing IPv6 lease. The parameters
+    /// specified will replace existing lease. The only condition is that
+    /// the IP address must not change. If you want to change the IP address,
+    /// please use lease6-del and lease6-add instead.
+    ///
+    /// Example command:
+    /// {
+    ///     "command": "lease6-update",
+    ///     "arguments": {
+    ///         "subnet-id": 66,
+    ///         "ip-address": "2001:db8::1",
+    ///         "iaid": 7654321,
+    ///         "duid": "88:88:88:88:88:88:88:88",
+    ///         "hostname": "newhostname.example.org"
+    ///     }
+    /// }";
+    ///
+    /// @param command - should be "lease6-update" (but it is ignored)
+    /// @param args arguments that describe the lease being updated.
+    data::ConstElementPtr
+    lease6UpdateHandler(const std::string& command, data::ConstElementPtr args);
+
+    /// @brief lease4-wipe handler
+    ///
+    /// This commands attempts to remove all IPv4 leases from a specific
+    /// subnet. Currently the leases are removed from the database,
+    /// without any processing (like calling hooks or doing DDNS
+    /// cleanups).
+    ///
+    /// Example command:
+    /// {\n"
+    ///     "command": "lease4-wipe",\n"
+    ///     "arguments": {"
+    ///         "subnet-id": 44
+    ///     }\n"
+    /// }";
+    /// @param command - should be "lease4-wipe" (but is ignored)
+    /// @param args arguments that describe the lease being updated.
+    data::ConstElementPtr
+    lease4WipeHandler(const std::string& command, data::ConstElementPtr args);
+
+    /// @brief lease6-wipe handler
+    ///
+    /// This commands attempts to remove all IPv4 leases from a specific
+    /// subnet. Currently the leases are removed from the database,
+    /// without any processing (like calling hooks or doing DDNS
+    /// cleanups).
+    ///
+    /// Example command:
+    /// {\n"
+    ///     "command": "lease4-wipe",\n"
+    ///     "arguments": {"
+    ///         "subnet-id": 44
+    ///     }\n"
+    /// }";
+    /// @param command - should be "lease4-wipe" (but is ignored)
+    /// @param args arguments that describe the lease being updated.
+    data::ConstElementPtr
+    lease6WipeHandler(const std::string& command, data::ConstElementPtr args);
+
+private:
     /// Pointer to the actual implementation
     boost::shared_ptr<LeaseCmdsImpl> impl_;
 };

+ 331 - 0
src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc

@@ -0,0 +1,331 @@
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the End User License
+// Agreement. See COPYING file in the premium/ directory.
+
+
+// Functions accessed by the hooks framework use C linkage to avoid the name
+// mangling that accompanies use of the C++ compiler as well as to avoid
+// issues related to namespaces.
+
+#include <lease_cmds.h>
+#include <lease_cmds_log.h>
+#include <cc/command_interpreter.h>
+#include <hooks/hooks.h>
+
+using namespace isc::config;
+using namespace isc::data;
+using namespace isc::hooks;
+using namespace isc::lease_cmds;
+
+extern "C" {
+
+/// @brief This is a command callout for 'lease4-add' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease4_add(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.leaseAddHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_ADD4_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease6-add' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease6_add(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.leaseAddHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_ADD6_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease4-get' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease4_get(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.leaseGetHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_GET4_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease6-get' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease6_get(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.leaseGetHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_GET6_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease4-update' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease4_update(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.lease4UpdateHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_UPDATE4_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease6-update' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease6_update(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.lease6UpdateHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_UPDATE6_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease4-del' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease4_del(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.lease4DelHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_DEL4_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease6-del' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease6_del(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.lease6DelHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_DEL6_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease4-wipe' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease4_wipe(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.lease4WipeHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_WIPE4_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This is a command callout for 'lease6-wipe' command.
+///
+/// @param handle Callout handle used to retrieve a command and
+/// provide a response.
+/// @return 0 if this callout has been invoked successfully,
+/// 1 otherwise.
+int lease6_wipe(CalloutHandle& handle) {
+    ConstElementPtr response;
+
+    try {
+        ConstElementPtr command;
+        handle.getArgument("command", command);
+        ConstElementPtr args;
+        std::string cmd_name = parseCommand(args, command);
+        LeaseCmds lease_cmds;
+
+        response = lease_cmds.lease6WipeHandler(cmd_name, args);
+    } catch (const std::exception& ex) {
+        response = createAnswer(CONTROL_RESULT_ERROR, ex.what());
+
+        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_WIPE6_MALFORMED)
+            .arg(ex.what());
+    }
+
+    handle.setArgument("response", response);
+    return (0);
+}
+
+/// @brief This function is called when the library is loaded.
+///
+/// @param handle library handle
+/// @return 0 when initialization is successful, 1 otherwise
+int load(LibraryHandle& handle) {
+    handle.registerCommandCallout("lease4-add", lease4_add);
+    handle.registerCommandCallout("lease6-add", lease6_add);
+    handle.registerCommandCallout("lease4-get", lease4_get);
+    handle.registerCommandCallout("lease6-get", lease6_get);
+    handle.registerCommandCallout("lease4-del", lease4_del);
+    handle.registerCommandCallout("lease6-del", lease6_del);
+    handle.registerCommandCallout("lease4-update", lease4_update);
+    handle.registerCommandCallout("lease6-update", lease6_update);
+    handle.registerCommandCallout("lease4-wipe", lease4_wipe);
+    handle.registerCommandCallout("lease6-wipe", lease6_wipe);
+
+    LOG_INFO(lease_cmds_logger, LEASE_CMDS_INIT_OK);
+    return (0);
+}
+
+/// @brief This function is called when the library is unloaded.
+///
+/// @return 0 if deregistration was successful, 1 otherwise
+int unload() {
+    LOG_INFO(lease_cmds_logger, LEASE_CMDS_DEINIT_OK);
+    return (0);
+}
+
+} // end extern "C"

+ 68 - 28
src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes

@@ -1,13 +1,28 @@
 # Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
 
-% LEASE_CMDS_INIT_FAILED loading Lease Commands hooks library failed: %1
-This error message indicates an error during loading the Lease Commands
-hooks library. The details of the error are provided as argument of
-the log message.
+% LEASE_CMDS_ADD4 lease4-add command successful (parameters: %1)
+The lease4-add command has been successful. Parameters of the host
+added are logged.
 
-% LEASE_CMDS_INIT_OK loading Lease Commands hooks library successful
-This info message indicates that the Lease Commands hooks library has been
-loaded successfully. Enjoy!
+% LEASE_CMDS_ADD4_FAILED lease4-add command failed (parameters: %1, reason: %2)
+The lease4-add command has failed. Both the reason as well as the
+parameters passed are logged.
+
+% LEASE_CMDS_ADD4_MALFORMED lease4-add is malformed, reason: %1
+The JSON text received by the lease4-add handler was not a properly formed
+control channel command.
+
+% LEASE_CMDS_ADD6 lease6-add command successful (parameters: %1)
+The lease6-add command has been successful. Parameters of the host
+added are logged.
+
+% LEASE_CMDS_ADD6_FAILED Lease6-add command failed (parameters: %1, reason: %2)
+The lease6-add command has failed. Both the reason as well as the
+parameters passed are logged.
+
+% LEASE_CMDS_ADD6_MALFORMED lease6-add is malformed, reason: %1
+The JSON text received by the lease6-add handler was not a properly formed
+control channel command.
 
 % LEASE_CMDS_DEINIT_FAILED unloading Lease Commands hooks library failed: %1
 This error message indicates an error during unloading the Lease Commands
@@ -18,34 +33,59 @@ the log message.
 This info message indicates that the Lease Commands hooks library has been
 removed successfully.
 
-% LEASE_CMDS_ADD4_FAILED lease4-add command failed (parameters: %1, reason: %2)
-The lease4-add command has failed. Both the reason as well as the
-parameters passed are logged.
-
-% LEASE_CMDS_ADD6_FAILED Lease6-add command failed (parameters: %1, reason: %2)
-The lease6-add command has failed. Both the reason as well as the
-parameters passed are logged.
-
-% LEASE_CMDS_ADD4 lease4-add command successful (parameters: %1)
-The lease4-add command has been successful. Parameters of the host
-added are logged.
-
-% LEASE_CMDS_ADD6 lease6-add command successful (parameters: %1)
-The lease6-add command has been successful. Parameters of the host
-added are logged.
+% LEASE_CMDS_DEL4 lease4-del command successful (parameters: %1)
+The attempt to delete an IPv4 lease (lease4-del command) has been successful.
+Parameters of the host removed are logged.
 
 % LEASE_CMDS_DEL4_FAILED lease4-del command failed (parameters: %1, reason: %2)
 The attempt to delete an IPv4 lease (lease4-del command) has failed. Both the
 reason as well as the parameters passed are logged.
 
+% LEASE_CMDS_DEL4_MALFORMED lease4-del is malformed, reason: %1
+The JSON text received by the lease4-del handler was not a properly formed
+control channel command.
+
+% LEASE_CMDS_DEL6 lease4-del command successful (parameters: %1)
+The attempt to delete an IPv4 lease (lease4-del command) has been successful.
+Parameters of the host removed are logged.
+
 % LEASE_CMDS_DEL6_FAILED lease6-del command failed (parameters: %1, reason: %2)
 The attempt to delete an IPv6 lease (lease4-del command) has failed. Both the
 reason as well as the parameters passed are logged.
 
-% LEASE_CMDS_DEL4 lease4-del command successful (parameters: %1)
-The attempt to delete an IPv4 lease (lease4-del command) has been successful.
-Parameters of the host removed are logged.
+% LEASE_CMDS_DEL6_MALFORMED lease6-del is malformed, reason: %1
+The JSON text received by the lease6-del handler was not a properly formed
+control channel command.
 
-% LEASE_CMDS_DEL6 lease4-del command successful (parameters: %1)
-The attempt to delete an IPv4 lease (lease4-del command) has been successful.
-Parameters of the host removed are logged.
+% LEASE_CMDS_GET4_MALFORMED lease4-get is malformed, reason: %1
+The JSON text received by the lease4-get handler was not a properly formed
+control channel command.
+
+% LEASE_CMDS_GET6_MALFORMED lease6-get is malformed, reason: %1
+The JSON text received by the lease6-get handler was not a properly formed
+control channel command.
+
+% LEASE_CMDS_INIT_FAILED loading Lease Commands hooks library failed: %1
+This error message indicates an error during loading the Lease Commands
+hooks library. The details of the error are provided as argument of
+the log message.
+
+% LEASE_CMDS_INIT_OK loading Lease Commands hooks library successful
+This info message indicates that the Lease Commands hooks library has been
+loaded successfully. Enjoy!
+
+% LEASE_CMDS_UPDATE4_MALFORMED lease4-update is malformed, reason: %1
+The JSON text received by the lease4-update handler was not a properly formed
+control channel command.
+
+% LEASE_CMDS_UPDATE6_MALFORMED lease6-update is malformed, reason: %1
+The JSON text received by the lease6-update handler was not a properly formed
+control channel command.
+
+% LEASE_CMDS_WIPE4_MALFORMED lease4-wipe is malformed, reason: %1
+The JSON text received by the lease4-wipe handler was not a properly formed
+control channel command.
+
+% LEASE_CMDS_WIPE6_MALFORMED lease6-wipe is malformed, reason: %1
+The JSON text received by the lease6-wipe handler was not a properly formed
+control channel command.

+ 0 - 63
src/hooks/dhcp/lease_cmds/load_unload.cc

@@ -1,63 +0,0 @@
-// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-/// @file load_unload.cc Defines the load and unload hooks library functions.
-
-#include <config.h>
-#include <lease_cmds.h>
-#include <lease_cmds_log.h>
-#include <string>
-#include <hooks/hooks.h>
-#include <exceptions/exceptions.h>
-
-using namespace isc::hooks;
-using namespace isc::lease_cmds;
-
-boost::shared_ptr<LeaseCmds> instance;
-
-extern "C" {
-
-/// @brief This function is called when the library is loaded.
-///
-/// This function creates LeaseCmds object that registers
-/// additional commands.
-///
-/// @param handle library handle (ignored)
-/// @return 0 when initialization is successful, 1 otherwise
-int load(LibraryHandle& /*handle*/) {
-
-    try {
-        instance.reset(new LeaseCmds());
-    } catch (const isc::Unexpected& ex) {
-        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_INIT_FAILED)
-            .arg(ex.what());
-        return (1);
-    }
-
-    LOG_INFO(lease_cmds_logger, LEASE_CMDS_INIT_OK);
-    return (0);
-}
-
-/// @brief This function is called when the library is unloaded.
-///
-/// This function creates LeaseCmds object that deregisters
-/// additional commands.
-///
-/// @return 0 if deregistration was successful, 1 otherwise
-int unload() {
-    try {
-        instance.reset();
-    } catch (const isc::Unexpected& ex) {
-        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_DEINIT_FAILED)
-            .arg(ex.what());
-        return (1);
-    }
-
-    LOG_INFO(lease_cmds_logger, LEASE_CMDS_DEINIT_OK);
-    return (0);
-}
-
-}