Kea: netconf_config.cc Source File

| Kea 3.2.0-git

netconf_config.cc
Go to the documentation of this file.
1// Copyright (C) 2018-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <asiolink/io_error.h>
10#include <config/unix_command_config.h>
11#include <exceptions/exceptions.h>
12#include <netconf/netconf_cfg_mgr.h>
13#include <netconf/netconf_log.h>
14
15#include <sstream>
16#include <string>
17
18using namespace std;
19using namespace isc::process;
20using namespace isc::data;
21using namespace isc::http;
22
23namespace isc {
24namespace netconf {
25
26// *********************** CfgControlSocket *************************
27
28CfgControlSocket::CfgControlSocket(Type type, const string& name,
29 const Url& url)
30 : type_(type), name_(name), url_(url) {
31}
32
33 CfgControlSocket::Type
34CfgControlSocket::stringToType(const string& type) {
35 if (type == "unix") {
36 return (CfgControlSocket::Type::UNIX);
37 } else if (type == "http") {
38 return (CfgControlSocket::Type::HTTP);
39 } else if (type == "stdout") {
40 return (CfgControlSocket::Type::STDOUT);
41 }
42
43 isc_throw(BadValue, "Unknown control socket type: " << type);
44}
45
46const string
47CfgControlSocket::typeToString(CfgControlSocket::Type type) {
48 switch (type) {
49 case CfgControlSocket::Type::UNIX:
50 return ("unix");
51 case CfgControlSocket::Type::HTTP:
52 return ("http");
53 case CfgControlSocket::Type::STDOUT:
54 return ("stdout");
55 default:
56 isc_throw(BadValue, "Unknown control socket type: " << type);
57 }
58}
59
60 ElementPtr
61CfgControlSocket::toElement() const {
62 ElementPtr result = Element::createMap();
63 // Set user-context
64 contextToElement(result);
65 // Set type
66 result->set("socket-type", Element::create(typeToString(type_)));
67 // Set name
68 result->set("socket-name", Element::create(name_));
69 // Set url
70 result->set("socket-url", Element::create(url_.toText()));
71 return (result);
72}
73
74// *********************** CfgServer *************************
75CfgServer::CfgServer(const string& model, CfgControlSocketPtr ctrl_sock)
76 : model_(model), boot_update_(true), subscribe_changes_(true),
77 subscribe_notifications_(true), validate_changes_(true),
78 control_socket_(ctrl_sock) {
79}
80
81string
82CfgServer::toText() const {
83 ostringstream s;
84 s << "model: " << model_ << ", control socket: ";
85 if (!control_socket_) {
86 s << "none";
87 } else {
88 switch (control_socket_->getType()) {
89 case CfgControlSocket::Type::UNIX:
90 s << "UNIX:'" << control_socket_->getName() << "'";
91 break;
92 case CfgControlSocket::Type::HTTP:
93 s << "HTTP:'" << control_socket_->getUrl().toText() << "'";
94 break;
95 case CfgControlSocket::Type::STDOUT:
96 s << "STDOUT";
97 break;
98 }
99 }
100 return (s.str());
101}
102
103 ElementPtr
104CfgServer::toElement() const {
105 ElementPtr result = Element::createMap();
106 // Set user-context
107 contextToElement(result);
108 // Set model
109 result->set("model", Element::create(model_));
110 // Set boot-update
111 result->set("boot-update", Element::create(boot_update_));
112 // Set subscribe-changes
113 result->set("subscribe-changes", Element::create(subscribe_changes_));
114 // Set validate-changes
115 result->set("validate-changes", Element::create(validate_changes_));
116 // Set control-socket
117 if (control_socket_) {
118 result->set("control-socket", control_socket_->toElement());
119 }
120 return (result);
121}
122
123ostream&
124 operator<<(ostream& os, const CfgServer& server) {
125 os << server.toText();
126 return (os);
127}
128
129// *************************** PARSERS ***********************************
130
131// *********************** ControlSocketConfigParser *************************
132
133 CfgControlSocketPtr
134ControlSocketConfigParser::parse(ConstElementPtr ctrl_sock_config, const std::string& service) {
135 CfgControlSocketPtr result;
136 string type_str = getString(ctrl_sock_config, "socket-type");
137 string name = getString(ctrl_sock_config, "socket-name");
138 string url_str = getString(ctrl_sock_config, "socket-url");
139 ConstElementPtr user_context = ctrl_sock_config->get("user-context");
140
141 if (type_str.size() == 0) {
142 isc_throw(ConfigError, "socket-type is mandatory and is not set");
143 }
144
145 // Type must be valid.
146 CfgControlSocket::Type type;
147 try {
148 type = CfgControlSocket::stringToType(type_str);
149 } catch (exception const& ex) {
150 isc_throw(ConfigError, ex.what() << " '" << type_str << "' ("
151 << getPosition("socket-type", ctrl_sock_config) << ")");
152 }
153
154 // Check the combination of settings.
155 switch (type) {
156 case CfgControlSocket::Type::UNIX:
157 if (name.size() == 0) {
158 isc_throw(ConfigError, "socket-name must not be empty when socket type is configured to unix");
159 }
160 isc::config::UnixCommandConfig::validatePath(name);
161 break;
162 case CfgControlSocket::Type::HTTP:
163 if (name.size() != 0) {
164 isc_throw(ConfigError, "socket-name is extraneous when socket type is configured to http");
165 }
166 break;
167 case CfgControlSocket::Type::STDOUT:
168 if (name.size() != 0) {
169 isc_throw(ConfigError, "socket-name is extraneous when socket type is configured to stdout");
170 }
171 break;
172 default:
173 isc_throw(ConfigError, "Unknown control socket type: " << type);
174 break;
175 }
176
177 // Url must be valid.
178 Url url(url_str);
179 if (!url.isValid()) {
180 isc_throw(ConfigError, "invalid control socket url: "
181 << url.getErrorMessage() << " '" << url_str << "' ("
182 << getPosition("socket-url", ctrl_sock_config) << ")");
183 }
184
185 if (type == CfgControlSocket::Type::UNIX) {
186 isc::config::UnixCommandConfig::validatePath(name);
187 }
188
189 // Create the control socket.
190 try {
191 result.reset(new CfgControlSocket(type, name, url));
192 } catch (exception const& ex) {
193 isc_throw(ConfigError, ex.what() << " ("
194 << ctrl_sock_config->getPosition() << ")");
195 }
196
197 // Add user-context.
198 if (user_context) {
199 result->setContext(user_context);
200 }
201
202 std::ostringstream msg;
203 switch (type) {
204 case CfgControlSocket::Type::UNIX:
205 msg << "with socket name: " << name;
206 break;
207 case CfgControlSocket::Type::HTTP:
208 msg << "with url: " << url_str;
209 break;
210 case CfgControlSocket::Type::STDOUT:
211 msg << "suited for logging";
212 break;
213 }
214 LOG_INFO(netconf_logger, NETCONF_CONTROL_SOCKET_INFO)
215 .arg(service)
216 .arg(type_str)
217 .arg(msg.str());
218
219 return (result);
220}
221
222// *********************** ServerConfigParser *************************
223
224 CfgServerPtr
225ServerConfigParser::parse(ConstElementPtr server_config, const string& service) {
226 CfgServerPtr result;
227 string model = getString(server_config, "model");
228 ConstElementPtr user_context = server_config->get("user-context");
229 ConstElementPtr ctrl_sock_config = server_config->get("control-socket");
230 CfgControlSocketPtr ctrl_sock;
231 if (ctrl_sock_config) {
232 ControlSocketConfigParser parser;
233 ctrl_sock = parser.parse(ctrl_sock_config, service);
234 }
235 try {
236 result.reset(new CfgServer(model, ctrl_sock));
237 } catch (exception const& ex) {
238 isc_throw(ConfigError, ex.what() << " ("
239 << server_config->getPosition() << ")");
240 }
241
242 // Add flags.
243 result->setBootUpdate(getBoolean(server_config, "boot-update"));
244 result->setSubscribeChanges(getBoolean(server_config, "subscribe-changes"));
245 result->setValidateChanges(getBoolean(server_config, "validate-changes"));
246
247 // Add user-context.
248 if (user_context) {
249 result->setContext(user_context);
250 }
251
252 return (result);
253}
254
255} // namespace netconf
256} // namespace isc
Element::create
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:299
Element::createMap
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition exceptions/exceptions.h:132
isc::ConfigError
An exception that is thrown if an error occurs while configuring any server.
Definition dhcp_config_error.h:43
isc::config::UnixCommandConfig::validatePath
static std::string validatePath(const std::string socket_path)
Validates a path against the supported path for unix control sockets.
Definition unix_command_config.cc:125
isc::data::SimpleParser::getPosition
static const data::Element::Position & getPosition(const std::string &name, const data::ConstElementPtr parent)
Utility method that returns position of an element.
Definition lib/cc/simple_parser.cc:158
isc::data::SimpleParser::getString
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
Definition lib/cc/simple_parser.cc:60
isc::data::SimpleParser::getBoolean
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
Definition lib/cc/simple_parser.cc:108
isc::http::Url
Represents an URL.
Definition url.h:20
isc::http::Url::getErrorMessage
std::string getErrorMessage() const
Returns parsing error message.
Definition url.h:52
isc::http::Url::isValid
bool isValid() const
Checks if the URL is valid.
Definition url.h:47
isc::netconf::CfgControlSocket
Represents a Control Socket.
Definition netconf_config.h:70
isc::netconf::CfgControlSocket::toElement
isc::data::ElementPtr toElement() const override final
Unparse a configuration object.
Definition netconf_config.cc:61
isc::netconf::CfgControlSocket::Type
Type
Defines the list of possible control socket types.
Definition netconf_config.h:73
isc::netconf::CfgControlSocket::STDOUT
@ STDOUT
Definition netconf_config.h:76
isc::netconf::CfgControlSocket::HTTP
@ HTTP
Definition netconf_config.h:75
isc::netconf::CfgControlSocket::UNIX
@ UNIX
Definition netconf_config.h:74
isc::netconf::CfgControlSocket::CfgControlSocket
CfgControlSocket(Type type, const std::string &name, const isc::http::Url &url)
Constructor.
Definition netconf_config.cc:28
isc::netconf::CfgControlSocket::typeToString
static const std::string typeToString(CfgControlSocket::Type type)
Converts CfgControlSocket::Type to string.
Definition netconf_config.cc:47
isc::netconf::CfgControlSocket::stringToType
static Type stringToType(const std::string &type)
Converts socket type name to CfgControlSocket::Type.
Definition netconf_config.cc:34
isc::netconf::CfgServer
Represents a Managed CfgServer.
Definition netconf_config.h:149
isc::netconf::CfgServer::CfgServer
CfgServer(const std::string &model, CfgControlSocketPtr ctrl_sock)
Constructor.
Definition netconf_config.cc:75
isc::netconf::CfgServer::toElement
isc::data::ElementPtr toElement() const override final
Unparse a configuration object.
Definition netconf_config.cc:104
isc::netconf::CfgServer::toText
std::string toText() const
Returns a text representation for the server.
Definition netconf_config.cc:82
isc::netconf::ControlSocketConfigParser
Parser for CfgControlSocket.
Definition netconf_config.h:293
isc::netconf::ControlSocketConfigParser::parse
CfgControlSocketPtr parse(data::ConstElementPtr ctrl_sock_config, const std::string &service="")
Performs the actual parsing of the given "control-socket" element.
Definition netconf_config.cc:134
isc::netconf::ServerConfigParser::parse
CfgServerPtr parse(data::ConstElementPtr server_config, const std::string &service="")
Performs the actual parsing of the given value from the "managed-servers" map.
Definition netconf_config.cc:225
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
io_error.h
LOG_INFO
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
isc::data
Definition base_stamped_element.cc:12
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
isc::http
Definition auth_config.h:19
isc::netconf
Definition control_socket.cc:20
isc::netconf::netconf_logger
isc::log::Logger netconf_logger(NETCONF_LOGGER_NAME)
Base logger for the netconf agent.
Definition netconf_log.h:49
isc::netconf::operator<<
ostream & operator<<(ostream &os, const CfgServer &server)
Dumps the contents of a CfgServer as text to a output stream.
Definition netconf_config.cc:124
isc::netconf::NETCONF_CONTROL_SOCKET_INFO
const isc::log::MessageID NETCONF_CONTROL_SOCKET_INFO
Definition netconf_messages.h:17
isc::netconf::CfgServerPtr
std::shared_ptr< CfgServer > CfgServerPtr
Defines a pointer for CfgServer instances.
Definition netconf_config.h:272
isc::netconf::CfgControlSocketPtr
std::shared_ptr< CfgControlSocket > CfgControlSocketPtr
Defines a pointer for CfgControlSocket instances.
Definition netconf_config.h:143
isc::process
Definition cb_ctl_base.h:22
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18
netconf_cfg_mgr.h
netconf_log.h
Contains declarations for loggers used by the Kea netconf agent.
isc::data::UserContext::contextToElement
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition user_context.cc:15
unix_command_config.h