Commit 9994f64b authored by Marcin Siodelski's avatar Marcin Siodelski

[#93] Added mysql_cb hooks library.

parent 2a565dc8
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
/mysql_cb_messages.cc
/mysql_cb_messages.h
/s-messages
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
// 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"
// 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
// 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,