2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-29 13:07:50 +00:00

[(no branch, rebasing 1897-add-d2-server-hook-syntax)] [(no branch, rebasing 1897-add-d2-server-hook-syntax)] [#1897] Checkpoint before regen

This commit is contained in:
Francis Dupont 2021-05-26 20:09:25 +00:00
parent cac5733772
commit 9ab9a55342
10 changed files with 209 additions and 13 deletions

View File

@ -52,6 +52,7 @@
* - @subpage dhcpv4Hooks * - @subpage dhcpv4Hooks
* - @subpage dhcpv6Hooks * - @subpage dhcpv6Hooks
* - @subpage agentHooks * - @subpage agentHooks
* - @subpage d2Hooks
* - @subpage hooksComponentDeveloperGuide * - @subpage hooksComponentDeveloperGuide
* - @subpage hooksmgMaintenanceGuide * - @subpage hooksmgMaintenanceGuide
* - @subpage libdhcp_ha * - @subpage libdhcp_ha

View File

@ -12,7 +12,7 @@ endif
CLEANFILES = *.gcno *.gcda CLEANFILES = *.gcno *.gcda
EXTRA_DIST = d2.dox EXTRA_DIST = d2.dox d2_hooks.dox
EXTRA_DIST += d2_parser.yy EXTRA_DIST += d2_parser.yy
EXTRA_DIST += images/abstract_app_classes.svg images/add_state_model.svg EXTRA_DIST += images/abstract_app_classes.svg images/add_state_model.svg

View File

@ -53,6 +53,8 @@ D2CfgContext::D2CfgContext(const D2CfgContext& rhs) : ConfigBase(rhs) {
keys_ = rhs.keys_; keys_ = rhs.keys_;
control_socket_ = rhs.control_socket_; control_socket_ = rhs.control_socket_;
hooks_config_ = rhs.hooks_config_;
} }
D2CfgContext::~D2CfgContext() { D2CfgContext::~D2CfgContext() {
@ -101,6 +103,8 @@ D2CfgContext::toElement() const {
if (!isNull(control_socket_)) { if (!isNull(control_socket_)) {
d2->set("control-socket", UserContext::toElement(control_socket_)); d2->set("control-socket", UserContext::toElement(control_socket_));
} }
// Set hooks-librairies
d2->set("hooks-libraries", hooks_config_.toElement());
// Set DhcpDdns // Set DhcpDdns
ElementPtr result = Element::createMap(); ElementPtr result = Element::createMap();
result->set("DhcpDdns", d2); result->set("DhcpDdns", d2);
@ -313,6 +317,7 @@ std::list<std::list<std::string>>
D2CfgMgr::jsonPathsToRedact() const { D2CfgMgr::jsonPathsToRedact() const {
static std::list<std::list<std::string>> const list({ static std::list<std::list<std::string>> const list({
{"tsig-keys", "[]"}, {"tsig-keys", "[]"},
{"hooks-libraries", "[]", "parameters", "*"},
}); });
return list; return list;
} }

View File

@ -11,6 +11,7 @@
#include <cc/data.h> #include <cc/data.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <d2/d2_config.h> #include <d2/d2_config.h>
#include <hooks/hooks_config.h>
#include <process/d_cfg_mgr.h> #include <process/d_cfg_mgr.h>
#include <stdint.h> #include <stdint.h>
@ -102,6 +103,20 @@ public:
control_socket_ = control_socket; control_socket_ = control_socket;
} }
/// @brief Returns non-const reference to configured hooks libraries.
///
/// @return non-const reference to configured hooks libraries.
isc::hooks::HooksConfig& getHooksConfig() {
return (hooks_config_);
}
/// @brief Returns const reference to configured hooks libraries.
///
/// @return const reference to configured hooks libraries.
const isc::hooks::HooksConfig& getHooksConfig() const {
return (hooks_config_);
}
/// @brief Unparse a configuration object /// @brief Unparse a configuration object
/// ///
/// @return a pointer to a configuration /// @return a pointer to a configuration
@ -129,13 +144,14 @@ private:
/// @brief Pointer to the control-socket information. /// @brief Pointer to the control-socket information.
isc::data::ConstElementPtr control_socket_; isc::data::ConstElementPtr control_socket_;
/// @brief Configured hooks libraries.
isc::hooks::HooksConfig hooks_config_;
}; };
/// @brief Defines a pointer for DdnsDomain instances. /// @brief Defines a pointer for DdnsDomain instances.
typedef boost::shared_ptr<DdnsDomainListMgr> DdnsDomainListMgrPtr; typedef boost::shared_ptr<DdnsDomainListMgr> DdnsDomainListMgrPtr;
/// @brief DHCP-DDNS Configuration Manager /// @brief DHCP-DDNS Configuration Manager
/// ///
/// Provides the mechanisms for managing the DHCP-DDNS application's /// Provides the mechanisms for managing the DHCP-DDNS application's

43
src/bin/d2/d2_hooks.dox Normal file
View File

@ -0,0 +1,43 @@
// Copyright (C) 2021 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/.
/**
@page d2Hooks The Hooks API for the DDNS Server
@section d2HooksIntroduction Introduction
The Kea DDNS Server features "Hooks" API that allows the user-written
code to be integrated with the DDNS Server and handle some
of the control commands. The hooks library can be either used to provide
support for the new commands (not supported natively by the DDNS Server)
or "override" implementation of the existing handlers. The hooks library
signals to the DDNS Server that it has processed the given command by
setting "next step status" value to SKIP.
The hooks library can also be used to perform some additional tasks
related to reception of the control command instead of handling it, e.g.
logging or notifying some external service about reception of the
command.
@section d2HooksHookPoints Hooks in the DDNS Server
@subsection d2HooksD2SrvConfigured d2_srv_configured
- @b Arguments:
- name: @b io_context, type: isc::asiolink::IOServicePtr, direction: <b>in</b>
- name: @b json_config, type: isc::data::ConstElementPtr, direction: <b>in</b>
- name: @b server_config, type: isc::d2::D2CfgContextPtr, direction: <b>in</b>
- @b Description: this callout is executed when the server has completed
its (re)configuration. The server provides received and parsed configuration
structures to the hook library. It also provides a pointer to the IOService
object which is used by the server to run asynchronous operations. The hooks
libraries can use this IOService object to schedule asynchronous tasks which
are triggered by the D2 server's main loop. The hook library should hold the
provided pointer until the library is unloaded.
- <b>Next step status</b>: Status codes returned by the callouts installed on
this hook point are ignored.
*/

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") /* Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
This Source Code Form is subject to the terms of the Mozilla Public 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 License, v. 2.0. If a copy of the MPL was not distributed with this
@ -126,6 +126,8 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
return isc::d2::D2Parser::make_SUB_DDNS_DOMAINS(driver.loc_); return isc::d2::D2Parser::make_SUB_DDNS_DOMAINS(driver.loc_);
case D2ParserContext::PARSER_DNS_SERVER: case D2ParserContext::PARSER_DNS_SERVER:
return isc::d2::D2Parser::make_SUB_DNS_SERVER(driver.loc_); return isc::d2::D2Parser::make_SUB_DNS_SERVER(driver.loc_);
case D2ParserContext::PARSER_HOOKS_LIBRARY:
return isc::d2::D2Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
} }
} }
%} %}
@ -420,6 +422,33 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
} }
} }
\"hooks-libraries\" {
switch(driver.ctx_) {
case isc::d2::D2ParserContext::DHCPDDNS:
return isc::d2::D2Parser::make_HOOKS_LIBRARIES(driver.loc_);
default:
return isc::d2::D2Parser::make_STRING("hooks-libraries", driver.loc_);
}
}
\"parameters\" {
switch(driver.ctx_) {
case isc::d2::D2ParserContext::HOOKS_LIBRARIES:
return isc::d2::D2Parser::make_PARAMETERS(driver.loc_);
default:
return isc::d2::D2Parser::make_STRING("parameters", driver.loc_);
}
}
\"library\" {
switch(driver.ctx_) {
case isc::d2::D2ParserContext::HOOKS_LIBRARIES:
return isc::d2::D2Parser::make_LIBRARY(driver.loc_);
default:
return isc::d2::D2Parser::make_STRING("library", driver.loc_);
}
}
\"loggers\" { \"loggers\" {
switch(driver.ctx_) { switch(driver.ctx_) {
case isc::d2::D2ParserContext::DHCPDDNS: case isc::d2::D2ParserContext::DHCPDDNS:

View File

@ -75,6 +75,10 @@ using namespace std;
SOCKET_TYPE "socket-type" SOCKET_TYPE "socket-type"
SOCKET_NAME "socket-name" SOCKET_NAME "socket-name"
HOOKS_LIBRARIES "hooks-libraries"
LIBRARY "library"
PARAMETERS "parameters"
LOGGERS "loggers" LOGGERS "loggers"
NAME "name" NAME "name"
OUTPUT_OPTIONS "output_options" OUTPUT_OPTIONS "output_options"
@ -97,6 +101,7 @@ using namespace std;
SUB_DDNS_DOMAINS SUB_DDNS_DOMAINS
SUB_DNS_SERVER SUB_DNS_SERVER
SUB_DNS_SERVERS SUB_DNS_SERVERS
SUB_HOOKS_LIBRARY
; ;
%token <std::string> STRING "constant string" %token <std::string> STRING "constant string"
@ -126,6 +131,7 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
| SUB_DDNS_DOMAINS { ctx.ctx_ = ctx.DDNS_DOMAINS; } sub_ddns_domains | SUB_DDNS_DOMAINS { ctx.ctx_ = ctx.DDNS_DOMAINS; } sub_ddns_domains
| SUB_DNS_SERVER { ctx.ctx_ = ctx.DNS_SERVERS; } sub_dns_server | SUB_DNS_SERVER { ctx.ctx_ = ctx.DNS_SERVERS; } sub_dns_server
| SUB_DNS_SERVERS { ctx.ctx_ = ctx.DNS_SERVERS; } sub_dns_servers | SUB_DNS_SERVERS { ctx.ctx_ = ctx.DNS_SERVERS; } sub_dns_servers
| SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
; ;
// ---- generic JSON parser --------------------------------- // ---- generic JSON parser ---------------------------------
@ -259,6 +265,7 @@ dhcpddns_param: ip_address
| reverse_ddns | reverse_ddns
| tsig_keys | tsig_keys
| control_socket | control_socket
| hooks_libraries
| loggers | loggers
| user_context | user_context
| comment | comment
@ -716,6 +723,73 @@ control_socket_name: SOCKET_NAME {
ctx.leave(); ctx.leave();
}; };
// --- hooks libraries -----------------------------------------
hooks_libraries: HOOKS_LIBRARIES {
ctx.unique("hooks-libraries", ctx.loc2pos(@1));
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("hooks-libraries", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.HOOKS_LIBRARIES);
} COLON LSQUARE_BRACKET hooks_libraries_list RSQUARE_BRACKET {
ctx.stack_.pop_back();
ctx.leave();
};
hooks_libraries_list: %empty
| not_empty_hooks_libraries_list
;
not_empty_hooks_libraries_list: hooks_library
| not_empty_hooks_libraries_list COMMA hooks_library
;
hooks_library: LCURLY_BRACKET {
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->add(m);
ctx.stack_.push_back(m);
} hooks_params RCURLY_BRACKET {
// The library hooks parameter is required
ctx.require("library", ctx.loc2pos(@1), ctx.loc2pos(@4));
ctx.stack_.pop_back();
};
sub_hooks_library: LCURLY_BRACKET {
// Parse the hooks-libraries list entry map
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.push_back(m);
} hooks_params RCURLY_BRACKET {
// The library hooks parameter is required
ctx.require("library", ctx.loc2pos(@1), ctx.loc2pos(@4));
// parsing completed
};
hooks_params: hooks_param
| hooks_params COMMA hooks_param
| unknown_map_entry
;
hooks_param: library
| parameters
;
library: LIBRARY {
ctx.unique("library", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr lib(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("library", lib);
ctx.leave();
};
parameters: PARAMETERS {
ctx.unique("parameters", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
} COLON map_value {
ctx.stack_.back()->set("parameters", $4);
ctx.leave();
};
// --- loggers entry ----------------------------------------- // --- loggers entry -----------------------------------------
loggers: LOGGERS { loggers: LOGGERS {

View File

@ -1,4 +1,4 @@
// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // 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 // License, v. 2.0. If a copy of the MPL was not distributed with this
@ -9,6 +9,8 @@
#include <d2/d2_config.h> #include <d2/d2_config.h>
#include <d2/d2_simple_parser.h> #include <d2/d2_simple_parser.h>
#include <cc/data.h> #include <cc/data.h>
#include <hooks/hooks_manager.h>
#include <hooks/hooks_parser.h>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
using namespace isc::data; using namespace isc::data;
@ -196,7 +198,7 @@ D2SimpleParser::setManagerDefaults(ElementPtr global,
void D2SimpleParser::parse(const D2CfgContextPtr& ctx, void D2SimpleParser::parse(const D2CfgContextPtr& ctx,
const isc::data::ConstElementPtr& config, const isc::data::ConstElementPtr& config,
bool /*check_only*/) { bool check_only) {
// TSIG keys need to parse before the Domains, so we can catch Domains // TSIG keys need to parse before the Domains, so we can catch Domains
// that specify undefined keys. Create the necessary parsing order now. // that specify undefined keys. Create the necessary parsing order now.
// addToParseOrder("tsig-keys"); // addToParseOrder("tsig-keys");
@ -276,14 +278,32 @@ void D2SimpleParser::parse(const D2CfgContextPtr& ctx,
ctx->setControlSocketInfo(socket); ctx->setControlSocketInfo(socket);
} }
// Finally, let's get the hook libs!
using namespace isc::hooks;
HooksConfig& libraries = ctx->getHooksConfig();
ConstElementPtr hooks = config->get("hooks-libraries");
if (hooks) {
HooksLibrariesParser hooks_parser;
hooks_parser.parse(libraries, hooks);
libraries.verifyLibraries(hooks->getPosition());
}
// Attempt to create the new client config. This ought to fly as // Attempt to create the new client config. This ought to fly as
// we already validated everything. // we already validated everything.
D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout, D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout,
ncr_protocol, ncr_format)); ncr_protocol, ncr_format));
ctx->getD2Params() = params; ctx->getD2Params() = params;
if (!check_only) {
// This occurs last as if it succeeds, there is no easy way
// revert it. As a result, the failure to commit a subsequent
// change causes problems when trying to roll back.
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
libraries.loadLibraries();
}
} }
}
}; }
};

View File

@ -1,4 +1,4 @@
// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // 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 // License, v. 2.0. If a copy of the MPL was not distributed with this
@ -175,6 +175,8 @@ D2ParserContext::contextName()
return ("ncr-protocol"); return ("ncr-protocol");
case NCR_FORMAT: case NCR_FORMAT:
return ("ncr-format"); return ("ncr-format");
case HOOKS_LIBRARIES:
return ("hooks-libraries");
default: default:
return ("__unknown__"); return ("__unknown__");
} }

View File

@ -1,4 +1,4 @@
// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // 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 // License, v. 2.0. If a copy of the MPL was not distributed with this
@ -69,7 +69,10 @@ public:
PARSER_DNS_SERVER, PARSER_DNS_SERVER,
///< Used for parsing a list of DNS servers. ///< Used for parsing a list of DNS servers.
PARSER_DNS_SERVERS PARSER_DNS_SERVERS,
///< Used for parsing content of hooks libraries.
PARSER_HOOKS_LIBRARY
} ParserType; } ParserType;
/// @brief Default constructor. /// @brief Default constructor.
@ -233,7 +236,10 @@ public:
NCR_PROTOCOL, NCR_PROTOCOL,
/// Used while parsing DhcpDdns/ncr-format /// Used while parsing DhcpDdns/ncr-format
NCR_FORMAT NCR_FORMAT,
/// Used while parsing DhcpDdns/hooks-libraries.
HOOKS_LIBRARIES
} ParserContext; } ParserContext;