kea-custom-hooks
FeM custom hooks libraries for Kea DHCP
init.cpp
Go to the documentation of this file.
1
10#include <hooks/hooks.h>
11#include <log/logger.h>
12#include <log/macros.h>
13
14#include "Exporter.hpp"
15#include "common.hpp"
16#include "exceptions.hpp"
17#include "util/ArpwatchRPC.hpp"
20
21#include "log_admindb_arpwatch_exporter.h"
22
23namespace arpwatch
24{
25// NOLINTBEGIN(*-non-const-global-variables)
26std::unique_ptr<arpwatch::Exporter> exporter;
27std::vector<HiredisAdapter> redis_adapters;
28std::unique_ptr<HiredisMultiAdapter> redis_multi_adapter;
29std::unique_ptr<ArpwatchRPC> arpwatch_rpc;
30// NOLINTEND(*-non-const-global-variables)
31} // namespace arpwatch
32
33namespace
34{
35void create_redis_adapters_from_config(isc::hooks::LibraryHandle& handle);
36void create_arpwatch_rpc_from_config(isc::hooks::LibraryHandle& handle);
37void assert_config_exists(const isc::data::ConstElementPtr& config_element, const std::string& key);
38template <typename T>
39void try_add_server(T& raw_server);
40void create_exporter();
41} // namespace
42
43extern "C" {
44
48int load(isc::hooks::LibraryHandle& handle)
49{
50 isc::log::Logger logger("arpwatch-exporter");
51 try {
52 create_redis_adapters_from_config(handle);
53 create_arpwatch_rpc_from_config(handle);
54 create_exporter();
55 }
56 catch (InitFailure& f) {
57 f.log(logger);
58 return 1;
59 }
60
61 arpwatch::exporter->start_worker();
62
63 return 0;
64}
65
69int unload()
70{
71 arpwatch::exporter->stop_worker();
72
73 arpwatch::exporter.reset(nullptr);
74 arpwatch::redis_multi_adapter.reset(nullptr);
76 arpwatch::arpwatch_rpc.reset(nullptr);
77 return 0;
78}
79}
80
81namespace
82{
83void create_redis_adapters_from_config(isc::hooks::LibraryHandle& handle)
84{
85 isc::log::Logger logger("arpwatch-exporter");
86 auto raw_server_list = handle.getParameter("servers");
87
88 if (!raw_server_list) {
89 LOG_WARN(logger, arpwatch::CONFIG_NO_REDIS_SERVERS);
90 return;
91 }
92
93 auto server_list = [&raw_server_list]() {
94 try {
95 return raw_server_list->listValue();
96 }
97 catch (isc::data::TypeError& e) {
98 throw InvalidConfig("servers", "List", raw_server_list->str());
99 }
100 }();
101
102 for (auto& raw_server : server_list) {
103 try_add_server(raw_server);
104 }
105
106 arpwatch::redis_adapters.shrink_to_fit();
107
108 std::vector<HiredisMultiAdapter::adapter_refw_t> adapter_ref_list;
109 adapter_ref_list.reserve(arpwatch::redis_adapters.size());
110 for (auto& a : arpwatch::redis_adapters) {
111 adapter_ref_list.emplace_back(a);
112 }
113
114 arpwatch::redis_multi_adapter = std::make_unique<HiredisMultiAdapter>(adapter_ref_list);
115}
116
117void create_arpwatch_rpc_from_config(isc::hooks::LibraryHandle& handle)
118{
119 const auto rpc_url_raw{handle.getParameter("arpwatch-rpc-url")};
120 assert_config_exists(rpc_url_raw, "arpwatch-rpc-url");
121 const auto rpc_url = [&rpc_url_raw]() {
122 try {
123 return rpc_url_raw->stringValue();
124 }
125 catch (isc::data::TypeError& e) {
126 throw InvalidConfig("arpwatc-rpc-url", "String", rpc_url_raw->str());
127 }
128 }();
129
130 arpwatch::arpwatch_rpc = std::make_unique<ArpwatchRPC>(rpc_url);
131}
132
133void assert_config_exists(const isc::data::ConstElementPtr& config_element, const std::string& key)
134{
135 if (!config_element) {
137 }
138}
139
140template <typename T>
141void try_add_server(T& raw_server)
142{
143 assert_config_exists(raw_server, "servers.{}");
144 auto server = [&raw_server]() {
145 try {
146 return raw_server->mapValue();
147 }
148 catch (isc::data::TypeError& e) {
149 throw InvalidConfig("servers.{}", "Map", raw_server->str());
150 }
151 }();
152
153 auto raw_server_ip = [&server]() {
154 try {
155 return server.at("ip");
156 }
157 catch (std::out_of_range&) {
158 throw InvalidConfig("servers.{}.ip", "IP-Adress", "empty");
159 }
160 }();
161 assert_config_exists(raw_server_ip, "servers.{}.ip");
162 auto raw_server_port = [&server]() {
163 try {
164 return server.at("port");
165 }
166 catch (std::out_of_range&) {
167 return isc::data::ConstElementPtr(
168 new isc::data::IntElement(HiredisAdapter::REDIS_DEFAULT_PORT));
169 }
170 }();
171 assert_config_exists(raw_server_port, "servers.{}.port");
172
173 auto server_ip = [&raw_server_ip]() {
174 try {
175 return raw_server_ip->stringValue();
176 }
177 catch (isc::data::TypeError& e) {
178 throw InvalidConfig("server.{}.ip", "IP-Adress", raw_server_ip->str());
179 }
180 }();
181 auto server_port = [&raw_server_port]() {
182 try {
183 return raw_server_port->intValue();
184 }
185 catch (isc::data::TypeError& e) {
186 throw InvalidConfig("server.{}.port", "Port number", raw_server_port->str());
187 }
188 }();
189
190 isc::log::Logger logger("arpwatch-exporter");
191 LOG_INFO(logger, arpwatch::CONFIG_REDIS_SERVER_ADD).arg(server_ip).arg(server_port);
192 arpwatch::redis_adapters.emplace_back(server_ip, server_port);
193}
194
195void create_exporter()
196{
198 std::make_unique<arpwatch::Exporter>(*arpwatch::redis_multi_adapter, *arpwatch::arpwatch_rpc);
199}
200} // namespace
int unload()
Unitialization/cleanup point for admindb-arpwatch-exporter.
Definition: init.cpp:69
int load(isc::hooks::LibraryHandle &handle)
Initialization/starting point for admindb-arpwatch-exporter.
Definition: init.cpp:48
static constexpr int REDIS_DEFAULT_PORT
A failure during initialization has happened.
Definition: exceptions.hpp:19
virtual void log(isc::log::Logger &logger) const
Definition: exceptions.hpp:35
Parts of the hook configuration are invalid.
Definition: exceptions.hpp:46
Common forward declaration for classes and variables.
Collection of exceptions which are thrown by admindb-arpwatch-exporter.
isc::log::Logger logger
Definition: init.cpp:28
std::unique_ptr< ArpwatchRPC > arpwatch_rpc
Definition: init.cpp:29
std::unique_ptr< arpwatch::Exporter > exporter
Definition: init.cpp:26
std::vector< HiredisAdapter > redis_adapters
Definition: init.cpp:27
std::unique_ptr< HiredisMultiAdapter > redis_multi_adapter
Definition: init.cpp:28