]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#93] Added mysql_cb hooks library.
authorMarcin Siodelski <marcin@isc.org>
Fri, 14 Sep 2018 07:37:47 +0000 (09:37 +0200)
committerMarcin Siodelski <marcin@isc.org>
Mon, 8 Oct 2018 14:39:22 +0000 (16:39 +0200)
12 files changed:
src/hooks/dhcp/Makefile.am
src/hooks/dhcp/mysql_cb/.gitignore [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/Makefile.am [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/mysql_cb_callouts.cc [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.h [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/tests/.gitignore [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/tests/Makefile.am [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/tests/run_unittests.cc [new file with mode: 0644]
src/hooks/dhcp/mysql_cb/version.cc [new file with mode: 0644]

index d8e33e26c86bb32a1251508ef5579190c6bfa2f1..0bb9b878e379bd8f9e83b35ec3ee00e1d8810154 100644 (file)
@@ -1 +1,7 @@
-SUBDIRS = high_availability lease_cmds stat_cmds user_chk
+SUBDIRS = high_availability lease_cmds
+
+if HAVE_MYSQL
+SUBDIRS += mysql_cb
+endif
+
+SUBDIRS += stat_cmds user_chk
diff --git a/src/hooks/dhcp/mysql_cb/.gitignore b/src/hooks/dhcp/mysql_cb/.gitignore
new file mode 100644 (file)
index 0000000..2b15432
--- /dev/null
@@ -0,0 +1,3 @@
+/mysql_cb_messages.cc
+/mysql_cb_messages.h
+/s-messages
diff --git a/src/hooks/dhcp/mysql_cb/Makefile.am b/src/hooks/dhcp/mysql_cb/Makefile.am
new file mode 100644 (file)
index 0000000..ae7aef4
--- /dev/null
@@ -0,0 +1,61 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS  = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES) $(MYSQL_CPPFLAGS)
+AM_CXXFLAGS  = $(KEA_CXXFLAGS)
+
+# Define rule to build logging source files from message file
+mysql_cb_messages.h mysql_cb_messages.cc: s-messages
+s-messages: mysql_cb_messages.mes
+       $(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes
+       touch $@
+
+# Tell automake that the message files are built as part of the build process
+# (so that they are built before the main library is built).
+BUILT_SOURCES = mysql_cb_messages.h mysql_cb_messages.cc
+
+# Ensure that the message file is included in the distribution
+EXTRA_DIST = mysql_cb_messages.mes
+EXTRA_DIST += ha.dox
+
+# Get rid of generated message files on a clean
+CLEANFILES = *.gcno *.gcda mysql_cb_messages.h mysql_cb_messages.cc s-messages
+
+# convenience archive
+
+noinst_LTLIBRARIES = libmysqlcb.la
+
+libmysqlcb_la_SOURCES  = mysql_cb_callouts.cc
+libmysqlcb_la_SOURCES += mysql_cb_dhcp4.cc mysql_cb_dhcp4.h
+libmysqlcb_la_SOURCES += version.cc
+
+nodist_libmysqlcb_la_SOURCES = mysql_cb_messages.cc mysql_cb_messages.h
+
+libmysqlcb_la_CXXFLAGS = $(AM_CXXFLAGS)
+libmysqlcb_la_CPPFLAGS = $(AM_CPPFLAGS)
+
+# install the shared object into $(libdir)/hooks
+lib_hooksdir = $(libdir)/hooks
+lib_hooks_LTLIBRARIES = libdhcp_mysql_cb.la
+
+libdhcp_mysql_cb_la_SOURCES  =
+libdhcp_mysql_cb_la_LDFLAGS  = $(AM_LDFLAGS) $(MYSQL_LIBS)o
+libdhcp_mysql_cb_la_LDFLAGS  += -avoid-version -export-dynamic -module
+
+libdhcp_mysql_cb_la_LIBADD  = libmysqlcb.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/eval/libkea-eval.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/stats/libkea-stats.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/mysql/libkea-mysql.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/database/libkea-database.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/cc/libkea-cc.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la
+libdhcp_mysql_cb_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_callouts.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_callouts.cc
new file mode 100644 (file)
index 0000000..44df1e9
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (C) 2018 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/.
+
+// 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 <config.h>
+#include <hooks/hooks.h>
+
+using namespace isc::hooks;
+
+extern "C" {
+
+/// @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) {
+    return (0);
+}
+
+/// @brief This function is called when the library is unloaded.
+///
+/// @return 0 if deregistration was successful, 1 otherwise
+int unload() {
+    return (0);
+}
+
+
+} // end extern "C"
diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
new file mode 100644 (file)
index 0000000..faa8424
--- /dev/null
@@ -0,0 +1,438 @@
+// Copyright (C) 2018 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/.
+
+#include <database/db_exceptions.h>
+#include <mysql_cb_dhcp4.h>
+#include <mysql/mysql_connection.h>
+#include <mysql.h>
+#include <mysqld_error.h>
+#include <array>
+#include <utility>
+#include <vector>
+
+using namespace isc::db;
+
+namespace {
+
+class Binding;
+
+typedef boost::shared_ptr<Binding> BindingPtr;
+
+class Binding {
+public:
+
+    enum_field_types getType() const {
+        return (bind_.buffer_type);
+    }
+
+    MYSQL_BIND& getMySqlBinding() {
+        return (bind_);
+    }
+
+    void setBufferValue(const std::string& value) {
+        buffer_.assign(value.begin(), value.end());
+        bind_.buffer = &buffer_[0];
+        bind_.buffer_length = value.size();
+    }
+
+    template<typename T>
+    T getValue() const {
+        const T* value = reinterpret_cast<const T*>(&buffer_[0]);
+        return (*value);
+    }
+
+    bool amNull() const {
+        return (null_value_ == MLM_TRUE);
+    }
+
+    static BindingPtr createString(const unsigned long length = 512) {
+        BindingPtr binding(new Binding(MYSQL_TYPE_STRING));
+        binding->setBufferLength(length);
+        return (binding);
+    }
+
+    static BindingPtr createString(const std::string& value) {
+        BindingPtr binding(new Binding(MYSQL_TYPE_STRING));
+        binding->setBufferValue(value);
+        return (binding);
+    }
+
+    static BindingPtr createTimestamp() {
+        BindingPtr binding(new Binding(MYSQL_TYPE_TIMESTAMP));
+        binding->setBufferLength(sizeof(MYSQL_TIME));
+        return (binding);
+    }
+
+private:
+
+    Binding(enum_field_types buffer_type)
+        : buffer_(), length_(0), null_value_(MLM_FALSE) {
+        bind_.buffer_type = buffer_type;
+        bind_.length = &length_;
+        bind_.is_null = &null_value_;
+    }
+
+    void setBufferLength(const unsigned long length) {
+        length_ = length;
+        buffer_.resize(length_);
+        bind_.buffer = &buffer_[0];
+        bind_.buffer_length = length_;
+    }
+
+    std::vector<uint8_t> buffer_;
+
+    unsigned long length_;
+
+    my_bool null_value_;
+
+    MYSQL_BIND bind_;
+};
+
+typedef std::vector<BindingPtr> BindingCollection;
+
+class DatabaseExchange {
+public:
+
+    typedef std::function<void()> ConsumeResultFun;
+
+    void selectQuery(MYSQL_STMT* statement,
+                     const BindingCollection& in_bindings,
+                     BindingCollection& out_bindings,
+                     ConsumeResultFun process_result) {
+        std::vector<MYSQL_BIND> in_bind_vec;
+        for (BindingPtr in_binding : in_bindings) {
+            in_bind_vec.push_back(in_binding->getMySqlBinding());
+        }
+
+        int status = 0;
+
+        if (!in_bind_vec.empty()) {
+            status = mysql_stmt_bind_param(statement, &in_bind_vec[0]);
+        }
+
+        std::vector<MYSQL_BIND> out_bind_vec;
+        for (BindingPtr out_binding : out_bindings) {
+            out_bind_vec.push_back(out_binding->getMySqlBinding());
+        }
+
+        if (!out_bind_vec.empty()) {
+            status = mysql_stmt_bind_result(statement, &out_bind_vec[0]);
+        }
+
+        status = mysql_stmt_execute(statement);
+
+        status = mysql_stmt_store_result(statement);
+
+        MySqlFreeResult fetch_release(statement);
+        while ((status = mysql_stmt_fetch(statement)) ==
+               MLM_MYSQL_FETCH_SUCCESS) {
+            try {
+                process_result();
+            } catch (...) {
+                throw;
+            }
+        }
+    }
+
+};
+
+}
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Implementation of the MySQL Configuration Backend.
+class MySqlConfigBackendDHCPv4Impl {
+public:
+
+    /// @brief Statement tags.
+    ///
+    /// The contents of the enum are indexes into the list of SQL statements.
+    /// It is assumed that the order is such that the indices of statements
+    /// reading the database are less than those of statements modifying the
+    /// database.
+    enum StatementIndex {
+        GET_SUBNET4_ID,
+        NUM_STATEMENTS
+    };
+
+    /// @brief Constructor.
+    ///
+    /// @param parameters A data structure relating keywords and values
+    /// concerned with the database.
+    MySqlConfigBackendDHCPv4Impl(const DatabaseConnection::ParameterMap& parameters);
+
+    /// @brief Destructor.
+    ~MySqlConfigBackendDHCPv4Impl();
+
+    /// @brief Represents connection to the MySQL database.
+    MySqlConnection conn_;
+};
+
+/// @brief Array of tagged statements.
+typedef std::array<TaggedStatement, MySqlConfigBackendDHCPv4Impl::NUM_STATEMENTS>
+TaggedStatementArray;
+
+/// @brief Prepared MySQL statements used by the backend to insert and
+/// retrieve data from the database.
+TaggedStatementArray tagged_statements = { {
+    { MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_ID,
+      "SELECT hostname FROM hosts WHERE dhcp4_subnet_id = ?" }
+}
+};
+
+MySqlConfigBackendDHCPv4Impl::
+MySqlConfigBackendDHCPv4Impl(const DatabaseConnection::ParameterMap& parameters)
+    : conn_(parameters) {
+    // Open the database.
+    conn_.openDatabase();
+
+    // Test schema version before we try to prepare statements.
+    std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
+                                               MYSQL_SCHEMA_VERSION_MINOR);
+/*    std::pair<uint32_t, uint32_t> db_version = getVersion();
+    if (code_version != db_version) {
+        isc_throw(DbOpenError, "MySQL schema version mismatch: need version: "
+                  << code_version.first << "." << code_version.second
+                  << " found version:  " << db_version.first << "."
+                  << db_version.second);
+    } */
+
+    // Enable autocommit. In case transaction is explicitly used, this
+    // setting will be overwritten for the transaction. However, there are
+    // cases when lack of autocommit could cause transactions to hang
+    // until commit or rollback is explicitly called. This already
+    // caused issues for some unit tests which were unable to cleanup
+    // the database after the test because of pending transactions.
+    // Use of autocommit will eliminate this problem.
+    my_bool result = mysql_autocommit(conn_.mysql_, 1);
+    if (result != 0) {
+        isc_throw(DbOperationError, mysql_error(conn_.mysql_));
+    }
+
+    // Prepare query statements. Those are will be only used to retrieve
+    // information from the database, so they can be used even if the
+    // database is read only for the current user.
+    conn_.prepareStatements(tagged_statements.begin(),
+                            tagged_statements.end());
+//                            tagged_statements.begin() + WRITE_STMTS_BEGIN);
+}
+
+MySqlConfigBackendDHCPv4Impl::~MySqlConfigBackendDHCPv4Impl() {
+    // Free up the prepared statements, ignoring errors. (What would we do
+    // about them? We're destroying this object and are not really concerned
+    // with errors on a database connection that is about to go away.)
+    for (int i = 0; i < conn_.statements_.size(); ++i) {
+        if (conn_.statements_[i] != NULL) {
+            (void) mysql_stmt_close(conn_.statements_[i]);
+            conn_.statements_[i] = NULL;
+        }
+    }
+}
+
+MySqlConfigBackendDHCPv4::
+MySqlConfigBackendDHCPv4(const DatabaseConnection::ParameterMap& parameters)
+    : impl_(new MySqlConfigBackendDHCPv4Impl(parameters)) {
+}
+
+Subnet4Ptr
+MySqlConfigBackendDHCPv4::getSubnet4(const ServerSelector& selector,
+                                     const std::string& subnet_prefix) const {
+}
+
+Subnet4Ptr
+MySqlConfigBackendDHCPv4::getSubnet4(const ServerSelector& selector,
+                                     const SubnetID& subnet_id) const {
+    BindingCollection in_bindings;
+    in_bindings.push_back(Binding::createString("1024"));
+
+    BindingCollection out_bindings;
+    out_bindings.push_back(Binding::createString());
+
+    DatabaseExchange xchg;
+    xchg.selectQuery(impl_->conn_.statements_[MySqlConfigBackendDHCPv4Impl::GET_SUBNET4_ID],
+                     in_bindings, out_bindings,
+                     [&out_bindings]() {
+        uint32_t hostname = out_bindings[0]->getValue<uint32_t>();
+    });
+
+    return (Subnet4Ptr());
+}
+
+Subnet4Collection
+MySqlConfigBackendDHCPv4::getAllSubnets4(const ServerSelector& selector) const {
+}
+
+Subnet4Collection
+MySqlConfigBackendDHCPv4::getModifiedSubnets4(const ServerSelector& selector,
+                                              const boost::posix_time::ptime& modification_time) const {
+}
+
+SharedNetwork4Ptr
+MySqlConfigBackendDHCPv4::getSharedNetwork4(const ServerSelector& selector,
+                                            const std::string& name) const {
+}
+
+SharedNetwork4Collection
+MySqlConfigBackendDHCPv4::getAllSharedNetworks4(const ServerSelector& selector) const {
+}
+
+SharedNetwork4Collection
+MySqlConfigBackendDHCPv4::getModifiedSharedNetworks4(const ServerSelector& selector,
+                                                     const boost::posix_time::ptime& modification_time) const {
+}
+
+OptionDefinitionPtr
+MySqlConfigBackendDHCPv4::getOptionDef4(const ServerSelector& selector,
+                                        const uint16_t code,
+                                        const std::string& space) const {
+}
+
+OptionDefContainer
+MySqlConfigBackendDHCPv4::getAllOptionDefs4(const ServerSelector& selector) const {
+}
+
+OptionDefContainer
+MySqlConfigBackendDHCPv4::getModifiedOptionDefs4(const ServerSelector& selector,
+                                                 const boost::posix_time::ptime& modification_time) const {
+}
+
+util::OptionalValue<std::string>
+MySqlConfigBackendDHCPv4::getGlobalStringParameter4(const ServerSelector& selector,
+                                                    const std::string& name) const {
+}
+util::OptionalValue<int64_t>
+MySqlConfigBackendDHCPv4::getGlobalNumberParameter4(const ServerSelector& selector,
+                                                    const std::string& name) const {
+}
+
+std::map<std::string, std::string>
+MySqlConfigBackendDHCPv4::getAllGlobalParameters4(const ServerSelector& selector) const {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateSubnet4(const ServerSelector& selector,
+                                              const Subnet4Ptr& subnet) {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateSharedNetwork4(const ServerSelector& selector,
+                                                     const SharedNetwork4Ptr& shared_network) {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateOptionDef4(const ServerSelector& selector,
+                                                 const OptionDefinitionPtr& option_def) {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateOption4(const ServerSelector& selector,
+                                              const OptionPtr& option) {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateOption4(const ServerSelector& selector,
+                                              const SubnetID& subnet_id,
+                                              const OptionPtr& option) {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateOption4(const ServerSelector& selector,
+                                              const asiolink::IOAddress& pool_start_address,
+                                              const asiolink::IOAddress& pool_end_address,
+                                              const OptionPtr& option) {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateGlobalParameter4(const ServerSelector& selector,
+                                                       const std::string& name,
+                                                       const std::string& value) {
+}
+
+void
+MySqlConfigBackendDHCPv4::createUpdateGlobalParameter4(const ServerSelector& selector,
+                                                       const std::string& name,
+                                                       const int64_t value) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteSubnet4(const ServerSelector& selector,
+                                        const std::string& subnet_prefix) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteSubnet4(const ServerSelector& selector,
+                                        const SubnetID& subnet_id) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteAllSubnets4(const ServerSelector& selector) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteSharedNetwork4(const ServerSelector& selector,
+                                               const std::string& name) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteAllSharedNetworks4(const ServerSelector& selector) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteOptionDef4(const ServerSelector& selector,
+                                           const uint16_t code,
+                                           const std::string& space) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteAllOptionDefs4(const ServerSelector& selector) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteOption4(const ServerSelector& selector,
+                                        const uint16_t code,
+                                        const std::string& space) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteOption4(const ServerSelector& selector,
+                                        const SubnetID& subnet_id,
+                                        const uint16_t code,
+                                        const std::string& space) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteOption4(const ServerSelector& selector,
+                                        const asiolink::IOAddress& pool_start_address,
+                                        const asiolink::IOAddress& pool_end_address,
+                                        const uint16_t code,
+                                        const std::string& space) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteGlobalParameter4(const ServerSelector& selector,
+                                                 const std::string& name) {
+}
+
+void
+MySqlConfigBackendDHCPv4::deleteAllGlobalParameters4(const ServerSelector& selector) {
+}
+
+std::string
+MySqlConfigBackendDHCPv4::getType() const {
+    return ("mysql");
+}
+
+std::string
+MySqlConfigBackendDHCPv4::getHost() const {
+}
+
+uint16_t
+MySqlConfigBackendDHCPv4::getPort() const {
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.h b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.h
new file mode 100644 (file)
index 0000000..f0bf2d2
--- /dev/null
@@ -0,0 +1,353 @@
+// Copyright (C) 2018 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/.
+
+#ifndef MYSQL_CONFIG_BACKEND_DHCP4_H
+#define MYSQL_CONFIG_BACKEND_DHCP4_H
+
+#include <database/database_connection.h>
+#include <dhcpsrv/config_backend_dhcp4.h>
+#include <boost/shared_ptr.hpp>
+
+namespace isc {
+namespace dhcp {
+
+class MySqlConfigBackendDHCPv4Impl;
+
+/// @brief Implementation of the MySql Configuration Backend for
+/// Kea DHCPv4 server.
+class MySqlConfigBackendDHCPv4 : public ConfigBackendDHCPv4 {
+public:
+
+    /// @brief Constructor.
+    ///
+    /// @param parameters A data structure relating keywords and values
+    /// concerned with the database.
+    explicit MySqlConfigBackendDHCPv4(const db::DatabaseConnection::ParameterMap& parameters);
+
+    /// @brief Retrieves a single subnet by subnet_prefix.
+    ///
+    /// @param selector Server selector.
+    /// @param subnet_prefix Prefix of the subnet to be retrieved.
+    /// @return Pointer to the retrieved subnet or NULL if not found.
+    virtual Subnet4Ptr
+    getSubnet4(const db::ServerSelector& selector,
+               const std::string& subnet_prefix) const;
+
+    /// @brief Retrieves a single subnet by subnet identifier.
+    ///
+    /// @param selector Server selector.
+    /// @param subnet_id Identifier of a subnet to be retrieved.
+    /// @return Pointer to the retrieved subnet or NULL if not found.
+    virtual Subnet4Ptr
+    getSubnet4(const db::ServerSelector& selector, const SubnetID& subnet_id) const;
+
+    /// @brief Retrieves all subnets.
+    ///
+    /// @param selector Server selector.
+    /// @return Collection of subnets or empty collection if no subnet found.
+    virtual Subnet4Collection
+    getAllSubnets4(const db::ServerSelector& selector) const;
+
+    /// @brief Retrieves subnets modified after specified time.
+    ///
+    /// @param selector Server selector.
+    /// @param modification_time Lower bound subnet modification time.
+    /// @return Collection of subnets or empty collection if no subnet found.
+    virtual Subnet4Collection
+    getModifiedSubnets4(const db::ServerSelector& selector,
+                        const boost::posix_time::ptime& modification_time) const;
+
+    /// @brief Retrieves shared network by name.
+    ///
+    /// @param selector Server selector.
+    /// @param name Name of the shared network to be retrieved.
+    /// @return Pointer to the shared network or NULL if not found.
+    virtual SharedNetwork4Ptr
+    getSharedNetwork4(const db::ServerSelector& selector,
+                      const std::string& name) const;
+
+    /// @brief Retrieves all shared networks.
+    ///
+    /// @param selector Server selector.
+    /// @return Collection of shared network or empty collection if
+    /// no shared network found.
+    virtual SharedNetwork4Collection
+    getAllSharedNetworks4(const db::ServerSelector& selector) const;
+
+    /// @brief Retrieves shared networks modified after specified time.
+    ///
+    /// @param selector Server selector.
+    /// @param modification_time Lower bound shared network modification time.
+    /// @return Collection of shared network or empty collection if
+    /// no shared network found.
+    virtual SharedNetwork4Collection
+    getModifiedSharedNetworks4(const db::ServerSelector& selector,
+                               const boost::posix_time::ptime& modification_time) const;
+
+    /// @brief Retrieves single option definition by code and space.
+    ///
+    /// @param selector Server selector.
+    /// @param code Code of the option to be retrieved.
+    /// @param space Option space of the option to be retrieved.
+    /// @return Pointer to the option definition or NULL if not found.
+    virtual OptionDefinitionPtr
+    getOptionDef4(const db::ServerSelector& selector, const uint16_t code,
+                  const std::string& space) const;
+
+    /// @brief Retrieves all option definitions.
+    ///
+    /// @param selector Server selector.
+    /// @return Collection of option definitions or empty collection if
+    /// no option definition found.
+    virtual OptionDefContainer
+    getAllOptionDefs4(const db::ServerSelector& selector) const;
+
+    /// @brief Retrieves option definitions modified after specified time.
+    ///
+    /// @param selector Server selector.
+    /// @param modification_time Lower bound option definition modification
+    /// time.
+    /// @return Collection of option definitions or empty collection if
+    /// no option definition found.
+    virtual OptionDefContainer
+    getModifiedOptionDefs4(const db::ServerSelector& selector,
+                           const boost::posix_time::ptime& modification_time) const;
+
+    /// @brief Retrieves global string parameter value.
+    ///
+    /// @param selector Server selector.
+    /// @param name Name of the global parameter to be retrieved.
+    /// @return Value of the global string parameter.
+    virtual util::OptionalValue<std::string>
+    getGlobalStringParameter4(const db::ServerSelector& selector,
+                              const std::string& name) const;
+
+    /// @brief Retrieves global number parameter.
+    ///
+    /// @param selector Server selector.
+    /// @param name Name of the parameter to be retrieved.
+    virtual util::OptionalValue<int64_t>
+    getGlobalNumberParameter4(const db::ServerSelector& selector,
+                              const std::string& name) const;
+
+    /// @brief Retrieves all global parameters as strings.
+    ///
+    /// @param selector Server selector.
+    virtual std::map<std::string, std::string>
+    getAllGlobalParameters4(const db::ServerSelector& selector) const;
+
+    /// @brief Creates or updates a subnet.
+    ///
+    /// @param selector Server selector.
+    /// @param subnet Subnet to be added or updated.
+    virtual void
+    createUpdateSubnet4(const db::ServerSelector& selector,
+                        const Subnet4Ptr& subnet);
+
+    /// @brief Creates or updates a shared network.
+    ///
+    /// @param selector Server selector.
+    /// @param shared_network Shared network to be added or updated.
+    virtual void
+    createUpdateSharedNetwork4(const db::ServerSelector& selector,
+                               const SharedNetwork4Ptr& shared_network);
+
+    /// @brief Creates or updates an option definition.
+    ///
+    /// @param selector Server selector.
+    /// @param option_def Option definition to be added or updated.
+    virtual void
+    createUpdateOptionDef4(const db::ServerSelector& selector,
+                           const OptionDefinitionPtr& option_def);
+
+    /// @brief Creates or updates global option.
+    ///
+    /// @param selector Server selector.
+    /// @param option Option to be added or updated.
+    virtual void
+    createUpdateOption4(const db::ServerSelector& selector,
+                        const OptionPtr& option);
+
+    /// @brief Creates or updates subnet level option.
+    ///
+    /// @param selector Server selector.
+    /// @param subnet_id Identifier of a subnet to which option belongs.
+    /// @param option Option to be added or updated.
+    virtual void
+    createUpdateOption4(const db::ServerSelector& selector,
+                        const SubnetID& subnet_id,
+                        const OptionPtr& option);
+
+    /// @brief Creates or updates pool level option.
+    ///
+    /// @param selector Server selector.
+    /// @param pool_start_address Lower bound address of the pool to which
+    /// the option belongs.
+    /// @param pool_end_address Upper bound address of the pool to which the
+    /// option belongs.
+    /// @param option Option to be added or updated.
+    virtual void
+    createUpdateOption4(const db::ServerSelector& selector,
+                        const asiolink::IOAddress& pool_start_address,
+                        const asiolink::IOAddress& pool_end_address,
+                        const OptionPtr& option);
+
+    /// @brief Creates or updates global string parameter.
+    ///
+    /// @param selector Server selector.
+    /// @param name Name of the global parameter.
+    /// @param value Value of the global parameter.
+    virtual void
+    createUpdateGlobalParameter4(const db::ServerSelector& selector,
+                                 const std::string& name,
+                                 const std::string& value);
+
+    /// @brief Creates or updates global number parameter.
+    ///
+    /// @param selector Server selector.
+    /// @param name Name of the global parameter.
+    /// @param value Value of the global parameter.
+    virtual void
+    createUpdateGlobalParameter4(const db::ServerSelector& selector,
+                                 const std::string& name,
+                                 const int64_t value);
+    
+    /// @brief Deletes subnet by prefix.
+    ///
+    /// @param selector Server selector.
+    /// @param subnet_prefix Prefix of the subnet to be deleted.
+    virtual void
+    deleteSubnet4(const db::ServerSelector& selector,
+                  const std::string& subnet_prefix);
+
+    /// @brief Deletes subnet by identifier.
+    ///
+    /// @param selector Server selector.
+    /// @param subnet_id Identifier of the subnet to be deleted.
+    virtual void
+    deleteSubnet4(const db::ServerSelector& selector, const SubnetID& subnet_id);
+
+    /// @brief Deletes all subnets.
+    ///
+    /// @param selector Server selector.
+    virtual void
+    deleteAllSubnets4(const db::ServerSelector& selector);
+
+    /// @brief Deletes shared network by name.
+    ///
+    /// @param selector Server selector.
+    /// @param name Name of the shared network to be deleted.
+    virtual void
+    deleteSharedNetwork4(const db::ServerSelector& selector,
+                         const std::string& name);
+
+    /// @brief Deletes all shared networks.
+    ///
+    /// @param selector Server selector.
+    virtual void
+    deleteAllSharedNetworks4(const db::ServerSelector& selector);
+
+    /// @brief Deletes option definition.
+    ///
+    /// @param selector Server selector.
+    /// @param code Code of the option to be deleted.
+    /// @param space Option space of the option to be deleted.
+    virtual void
+    deleteOptionDef4(const db::ServerSelector& selector, const uint16_t code,
+                     const std::string& space);
+
+    /// @brief Deletes all option definitions.
+    ///
+    /// @param selector Server selector.
+    virtual void
+    deleteAllOptionDefs4(const db::ServerSelector& selector);
+
+    /// @brief Deletes global option.
+    ///
+    /// @param selector Server selector.
+    /// @param code Code of the option to be deleted.
+    /// @param space Option space of the option to be deleted.
+    virtual void
+    deleteOption4(const db::ServerSelector& selector, const uint16_t code,
+                  const std::string& space);
+
+    /// @brief Deletes subnet level option.
+    ///
+    /// @param selector Server selector.
+    /// @param subnet_id Identifier of the subnet to which deleted option
+    /// belongs.
+    /// @param code Code of the deleted option.
+    /// @param space Option space of the deleted option.
+    virtual void
+    deleteOption4(const db::ServerSelector& selector, const SubnetID& subnet_id,
+                  const uint16_t code, const std::string& space);
+
+    /// @brief Deletes pool level option.
+    ///
+    /// @param selector Server selector.
+    /// @param pool_start_address Lower bound address of the pool to which
+    /// deleted option belongs.
+    /// @param pool_end_address Upper bound address of the pool to which the
+    /// deleted option belongs.
+    /// @param code Code of the deleted option.
+    /// @param space Option space of the deleted option.
+    virtual void
+    deleteOption4(const db::ServerSelector& selector,
+                  const asiolink::IOAddress& pool_start_address,
+                  const asiolink::IOAddress& pool_end_address,
+                  const uint16_t code,
+                  const std::string& space);
+
+    /// @brief Deletes global parameter.
+    ///
+    /// @param selector Server selector.
+    /// @param name Name of the global parameter to be deleted.
+    virtual void
+    deleteGlobalParameter4(const db::ServerSelector& selector,
+                           const std::string& name);
+
+    /// @brief Deletes all global parameters.
+    ///
+    /// @param selector Server selector.
+    virtual void
+    deleteAllGlobalParameters4(const db::ServerSelector& selector);
+
+    /// @brief Returns backend type in the textual format.
+    ///
+    /// @return "mysql".
+    virtual std::string getType() const;
+
+    /// @brief Returns backend host.
+    ///
+    /// This is used by the @c BaseConfigBackendPool to select backend
+    /// when @c BackendSelector is specified.
+    ///
+    /// @return host on which the database is located.
+    virtual std::string getHost() const;
+
+    /// @brief Returns backend port number.
+    ///
+    /// This is used by the @c BaseConfigBackendPool to select backend
+    /// when @c BackendSelector is specified.
+    ///
+    /// @return Port number on which database service is available.
+    virtual uint16_t getPort() const;
+
+private:
+
+    /// @brief Pointer to the implementation of the @c MySqlConfigBackendDHCPv4
+    /// class.
+    boost::shared_ptr<MySqlConfigBackendDHCPv4Impl> impl_;
+
+};
+
+/// @brief Pointer to the @c MySqlConfigBackendDHCPv4 class.
+typedef boost::shared_ptr<MySqlConfigBackendDHCPv4> MySqlConfigBackendDHCPv4Ptr;
+
+} // end of namespace isc::cb
+} // end of namespace isc
+
+#endif // MYSQL_CONFIG_BACKEND_DHCP4_H
diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes b/src/hooks/dhcp/mysql_cb/mysql_cb_messages.mes
new file mode 100644 (file)
index 0000000..b03f62a
--- /dev/null
@@ -0,0 +1,3 @@
+# Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+
+$NAMESPACE isc::cb
diff --git a/src/hooks/dhcp/mysql_cb/tests/.gitignore b/src/hooks/dhcp/mysql_cb/tests/.gitignore
new file mode 100644 (file)
index 0000000..98266a2
--- /dev/null
@@ -0,0 +1 @@
+/mysql_cb_unittests
\ No newline at end of file
diff --git a/src/hooks/dhcp/mysql_cb/tests/Makefile.am b/src/hooks/dhcp/mysql_cb/tests/Makefile.am
new file mode 100644 (file)
index 0000000..5546b73
--- /dev/null
@@ -0,0 +1,58 @@
+SUBDIRS = .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/mysql_cb -I$(top_srcdir)/src/hooks/dhcp/mysql_cb
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
+
+AM_CXXFLAGS = $(KEA_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+# Unit test data files need to get installed.
+EXTRA_DIST =
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS_ENVIRONMENT = \
+       $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+
+TESTS =
+if HAVE_GTEST
+TESTS += mysql_cb_unittests
+
+mysql_cb_unittests_SOURCES  = mysql_cb_dhcp4_unittest.cc
+mysql_cb_unittests_SOURCES += run_unittests.cc
+
+mysql_cb_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
+
+mysql_cb_unittests_LDFLAGS  = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
+
+mysql_cb_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+
+mysql_cb_unittests_LDADD  = $(top_builddir)/src/hooks/dhcp/mysql_cb/libmysqlcb.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/mysql/testutils/libmysqltest.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/mysql/libkea-mysql.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/database/libkea-database.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
+mysql_cb_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+mysql_cb_unittests_LDADD += $(LOG4CPLUS_LIBS)
+mysql_cb_unittests_LDADD += $(CRYPTO_LIBS)
+mysql_cb_unittests_LDADD += $(BOOST_LIBS)
+mysql_cb_unittests_LDADD += $(GTEST_LDADD)
+endif
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
new file mode 100644 (file)
index 0000000..feb191b
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (C) 2018 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/.
+
+#include <config.h>
+#include <mysql_cb_dhcp4.h>
+#include <mysql/testutils/mysql_schema.h>
+#include <gtest/gtest.h>
+
+using namespace isc::db;
+using namespace isc::db::test;
+using namespace isc::dhcp;
+
+namespace {
+
+class MySqlConfigBackendDHCPv4Test : public ::testing::Test {
+public:
+
+    MySqlConfigBackendDHCPv4Test() {
+        destroyMySQLSchema();
+        createMySQLSchema();
+
+        try {
+            DatabaseConnection::ParameterMap params =
+                DatabaseConnection::parse(validMySQLConnectionString());
+            cbptr_.reset(new MySqlConfigBackendDHCPv4(params));
+
+        } catch (...) {
+            std::cerr << "*** ERROR: unable to open database. The test\n"
+                         "*** environment is broken and must be fixed before\n"
+                         "*** the MySQL tests will run correctly.\n"
+                         "*** The reason for the problem is described in the\n"
+                         "*** accompanying exception output.\n";
+            throw;
+        }
+    }
+
+    virtual ~MySqlConfigBackendDHCPv4Test() {
+        cbptr_.reset();
+        destroyMySQLSchema();
+    }
+
+    MySqlConfigBackendDHCPv4Ptr cbptr_;
+};
+
+TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4) {
+    cbptr_->getSubnet4(ServerSelector::UNASSIGNED(), SubnetID(1));
+}
+
+
+}
diff --git a/src/hooks/dhcp/mysql_cb/tests/run_unittests.cc b/src/hooks/dhcp/mysql_cb/tests/run_unittests.cc
new file mode 100644 (file)
index 0000000..3b1baf9
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright (C) 2017-2018 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/.
+
+#include <config.h>
+
+#include <log/logger_support.h>
+#include <gtest/gtest.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+    isc::log::initLogger();
+    int result = RUN_ALL_TESTS();
+
+    return (result);
+}
diff --git a/src/hooks/dhcp/mysql_cb/version.cc b/src/hooks/dhcp/mysql_cb/version.cc
new file mode 100644 (file)
index 0000000..32834ce
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright (C) 2018 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/.
+
+#include <config.h>
+#include <hooks/hooks.h>
+
+extern "C" {
+
+/// @brief returns Kea hooks version.
+int version() {
+    return (KEA_HOOKS_VERSION);
+}
+
+}