Kea 2.7.6
command_creator.cc
Go to the documentation of this file.
1// Copyright (C) 2018-2024 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 <command_creator.h>
10#include <ha_service_states.h>
13#include <boost/pointer_cast.hpp>
14
15using namespace isc::data;
16using namespace isc::dhcp;
17using namespace std;
18
19namespace isc {
20namespace ha {
21
22unordered_set<string> CommandCreator::ha_commands4_ = {
23 "list-commands", "status-get",
24 "dhcp-disable", "dhcp-enable",
25 "ha-reset", "ha-heartbeat",
26 "lease4-update", "lease4-del",
27 "lease4-get-all", "lease4-get-page",
28 "ha-maintenance-notify", "ha-sync-complete-notify"
29};
30
31unordered_set<string> CommandCreator::ha_commands6_ = {
32 "list-commands", "status-get",
33 "dhcp-disable", "dhcp-enable",
34 "ha-reset", "ha-heartbeat",
35 "lease6-bulk-apply",
36 "lease6-update", "lease6-del",
37 "lease6-get-all", "lease6-get-page",
38 "ha-maintenance-notify", "ha-sync-complete-notify"
39};
40
42CommandCreator::createDHCPDisable(const unsigned int origin_id,
43 const unsigned int max_period,
44 const HAServerType& server_type) {
45 ElementPtr args;
46 args = Element::createMap();
47 args->set("origin-id", Element::create(origin_id));
48 // Add for backward compatibility with Kea 2.4.0 and earlier.
49 args->set("origin", Element::create("ha-partner"));
50 // max-period is optional. A value of 0 means that it is not specified.
51 if (max_period > 0) {
52 args->set("max-period", Element::create(static_cast<long int>(max_period)));
53 }
54 ConstElementPtr command = config::createCommand("dhcp-disable", args);
55 insertService(command, server_type);
56 return (command);
57}
58
60CommandCreator::createDHCPEnable(const unsigned int origin_id,
61 const HAServerType& server_type) {
62 ElementPtr args;
63 args = Element::createMap();
64 args->set("origin-id", Element::create(origin_id));
65 // Add for backward compatibility with Kea 2.4.0 and earlier.
66 args->set("origin", Element::create("ha-partner"));
67 ConstElementPtr command = config::createCommand("dhcp-enable", args);
68 insertService(command, server_type);
69 return (command);
70}
71
73CommandCreator::createHAReset(const std::string& server_name,
74 const HAServerType& server_type) {
75 auto args = Element::createMap();
76 args->set("server-name", Element::create(server_name));
77 ConstElementPtr command = config::createCommand("ha-reset", args);
78 insertService(command, server_type);
79 return (command);
80}
81
83CommandCreator::createHeartbeat(const std::string& server_name,
84 const HAServerType& server_type) {
85 auto args = Element::createMap();
86 args->set("server-name", Element::create(server_name));
87 ConstElementPtr command = config::createCommand("ha-heartbeat", args);
88 insertService(command, server_type);
89 return (command);
90}
91
94 ElementPtr lease_as_json = lease4.toElement();
95 insertLeaseExpireTime(lease_as_json);
96 lease_as_json->set("force-create", Element::create(true));
97 lease_as_json->set("origin", Element::create("ha-partner"));
98 ConstElementPtr command = config::createCommand("lease4-update", lease_as_json);
99 insertService(command, HAServerType::DHCPv4);
100 return (command);
101}
102
105 ElementPtr lease_as_json = lease4.toElement();
106 insertLeaseExpireTime(lease_as_json);
107 lease_as_json->set("origin", Element::create("ha-partner"));
108 ConstElementPtr command = config::createCommand("lease4-del", lease_as_json);
109 insertService(command, HAServerType::DHCPv4);
110 return (command);
111}
112
115 ConstElementPtr command = config::createCommand("lease4-get-all");
116 insertService(command, HAServerType::DHCPv4);
117 return (command);
118}
119
122 const uint32_t limit) {
123 // Zero value is not allowed.
124 if (limit == 0) {
125 isc_throw(BadValue, "limit value for lease4-get-page command must not be 0");
126 }
127
128 // Get the last lease returned on the previous page. A null pointer means that
129 // we're fetching first page. In that case a keyword "start" is used to indicate
130 // that first page should be returned.
131 ElementPtr from_element = Element::create(last_lease4 ? last_lease4->addr_.toText() : "start");
132 // Set the maximum size of the page.
133 ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
134 // Put both parameters into arguments map.
136 args->set("from", from_element);
137 args->set("limit", limit_element);
138
139 // Create the command.
140 ConstElementPtr command = config::createCommand("lease4-get-page", args);
141 insertService(command, HAServerType::DHCPv4);
142 return (command);
143}
144
147 const Lease6CollectionPtr& deleted_leases) {
148 ElementPtr leases_list = Element::createList();
149 ElementPtr deleted_leases_list = Element::createList();
150 for (auto const& lease : *deleted_leases) {
151 ElementPtr lease_as_json = lease->toElement();
152 insertLeaseExpireTime(lease_as_json);
153 // If the deleted lease is in the released state it means that it
154 // should be preserved in the database. It is treated as released
155 // but can be re-allocated to the same client later (lease affinity).
156 // Such a lease should be updated by the partner rather than deleted.
157 if (lease->state_ == Lease6::STATE_RELEASED) {
158 leases_list->add(lease_as_json);
159 } else {
160 deleted_leases_list->add(lease_as_json);
161 }
162 }
163
164 for (auto const& lease : *leases) {
165 ElementPtr lease_as_json = lease->toElement();
166 insertLeaseExpireTime(lease_as_json);
167 leases_list->add(lease_as_json);
168 }
169
171 args->set("deleted-leases", deleted_leases_list);
172 args->set("leases", leases_list);
173 args->set("origin", Element::create("ha-partner"));
174
175 ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
176 insertService(command, HAServerType::DHCPv6);
177 return (command);
178}
179
182 ElementPtr deleted_leases_list = Element::createList();
183 ElementPtr leases_list = Element::createList();
184
186 Lease6Ptr lease;
187 while ((lease = boost::dynamic_pointer_cast<Lease6>(leases.pop(op_type)))) {
188 ElementPtr lease_as_json = lease->toElement();
189 insertLeaseExpireTime(lease_as_json);
190 if (op_type == LeaseUpdateBacklog::DELETE) {
191 deleted_leases_list->add(lease_as_json);
192 } else {
193 leases_list->add(lease_as_json);
194 }
195 }
196
198 args->set("deleted-leases", deleted_leases_list);
199 args->set("leases", leases_list);
200 args->set("origin", Element::create("ha-partner"));
201
202 ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
203 insertService(command, HAServerType::DHCPv6);
204 return (command);
205}
206
209 ElementPtr lease_as_json = lease6.toElement();
210 insertLeaseExpireTime(lease_as_json);
211 lease_as_json->set("force-create", Element::create(true));
212 lease_as_json->set("origin", Element::create("ha-partner"));
213 ConstElementPtr command = config::createCommand("lease6-update", lease_as_json);
214 insertService(command, HAServerType::DHCPv6);
215 return (command);
216}
217
220 ElementPtr lease_as_json = lease6.toElement();
221 insertLeaseExpireTime(lease_as_json);
222 lease_as_json->set("origin", Element::create("ha-partner"));
223 ConstElementPtr command = config::createCommand("lease6-del", lease_as_json);
224 insertService(command, HAServerType::DHCPv6);
225 return (command);
226}
227
230 ConstElementPtr command = config::createCommand("lease6-get-all");
231 insertService(command, HAServerType::DHCPv6);
232 return (command);
233}
234
237 const uint32_t limit) {
238 // Zero value is not allowed.
239 if (limit == 0) {
240 isc_throw(BadValue, "limit value for lease6-get-page command must not be 0");
241 }
242
243 // Get the last lease returned on the previous page. A null pointer means that
244 // we're fetching first page. In that case a keyword "start" is used to indicate
245 // that first page should be returned.
246 ElementPtr from_element = Element::create(last_lease6 ? last_lease6->addr_.toText() : "start");
247 // Set the maximum size of the page.
248 ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
249 // Put both parameters into arguments map.
251 args->set("from", from_element);
252 args->set("limit", limit_element);
253
254 // Create the command.
255 ConstElementPtr command = config::createCommand("lease6-get-page", args);
256 insertService(command, HAServerType::DHCPv6);
257 return (command);
258}
259
261CommandCreator::createMaintenanceNotify(const std::string& server_name,
262 const bool cancel,
263 const int state,
264 const HAServerType& server_type) {
265 auto args = Element::createMap();
266 args->set("server-name", Element::create(server_name));
267 args->set("cancel", Element::create(cancel));
268 args->set("state", Element::create(stateToString(state)));
269 auto command = config::createCommand("ha-maintenance-notify", args);
270 insertService(command, server_type);
271 return (command);
272}
273
275CommandCreator::createSyncCompleteNotify(const unsigned int origin_id,
276 const std::string& server_name,
277 const HAServerType& server_type) {
278 auto args = Element::createMap();
279 args->set("server-name", Element::create(server_name));
280 args->set("origin-id", Element::create(origin_id));
281 // Add for backward compatibility with Kea 2.5.5 to Kea 2.5.7.
282 // The origin parameter was introduced for this command in Kea 2.5.5 but
283 // renamed to origin-id to be consistent with the origin-id used in
284 // dhcp-enable and dhcp-disable commands starting from Kea 2.5.8.
285 args->set("origin", Element::create(origin_id));
286 auto command = config::createCommand("ha-sync-complete-notify", args);
287 insertService(command, server_type);
288 return (command);
289}
290
291void
292CommandCreator::insertLeaseExpireTime(ElementPtr& lease) {
293 if ((lease->getType() != Element::map) ||
294 (!lease->contains("cltt") || (lease->get("cltt")->getType() != Element::integer) ||
295 (!lease->contains("valid-lft") ||
296 (lease->get("valid-lft")->getType() != Element::integer)))) {
297 isc_throw(Unexpected, "invalid lease format");
298 }
299
300 int64_t cltt = lease->get("cltt")->intValue();
301 int64_t valid_lifetime = lease->get("valid-lft")->intValue();
302 int64_t expire = cltt + valid_lifetime;
303 lease->set("expire", Element::create(expire));
304 lease->remove("cltt");
305}
306
307void
308CommandCreator::insertService(ConstElementPtr& command,
309 const HAServerType& server_type) {
311 const string service_name = (server_type == HAServerType::DHCPv4 ? "dhcp4" : "dhcp6");
312 service->add(Element::create(service_name));
313
314 // We have no better way of setting a new element here than
315 // doing const pointer cast. That's another reason why this
316 // functionality could be moved to the core code. We don't
317 // do it however, because we want to minimize concurrent
318 // code changes in the premium and core Kea repos.
319 (boost::const_pointer_cast<Element>(command))->set("service", service);
320}
321
322} // end of namespace ha
323} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when an unexpected error condition occurs.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
static data::ConstElementPtr createLease4Delete(const dhcp::Lease4 &lease4)
Creates lease4-del command.
static data::ConstElementPtr createHeartbeat(const std::string &server_name, const HAServerType &server_type)
Creates ha-heartbeat command for DHCP server.
static std::unordered_set< std::string > ha_commands4_
List of commands used by the High Availability in v4.
static data::ConstElementPtr createLease4Update(const dhcp::Lease4 &lease4)
Creates lease4-update command.
static data::ConstElementPtr createLease6Update(const dhcp::Lease6 &lease6)
Creates lease6-update command.
static data::ConstElementPtr createSyncCompleteNotify(const unsigned int origin_id, const std::string &server_name, const HAServerType &server_type)
Creates ha-sync-complete-notify command.
static data::ConstElementPtr createLease6Delete(const dhcp::Lease6 &lease6)
Creates lease6-del command.
static data::ConstElementPtr createLease6BulkApply(const dhcp::Lease6CollectionPtr &leases, const dhcp::Lease6CollectionPtr &deleted_leases)
Creates lease6-bulk-apply command.
static data::ConstElementPtr createLease4GetAll()
Creates lease4-get-all command.
static data::ConstElementPtr createLease6GetPage(const dhcp::Lease6Ptr &lease6, const uint32_t limit)
Creates lease6-get-page command.
static data::ConstElementPtr createDHCPDisable(const unsigned int origin_id, const unsigned int max_period, const HAServerType &server_type)
Creates dhcp-disable command for DHCP server.
static data::ConstElementPtr createDHCPEnable(const unsigned int origin_id, const HAServerType &server_type)
Creates dhcp-enable command for DHCP server.
static data::ConstElementPtr createMaintenanceNotify(const std::string &server_name, const bool cancel, const int state, const HAServerType &server_type)
Creates ha-maintenance-notify command.
static std::unordered_set< std::string > ha_commands6_
List of commands used by the High Availability in v6.
static data::ConstElementPtr createHAReset(const std::string &server_name, const HAServerType &server_type)
Creates ha-reset command.
static data::ConstElementPtr createLease6GetAll()
Creates lease6-get-all command.
static data::ConstElementPtr createLease4GetPage(const dhcp::Lease4Ptr &lease4, const uint32_t limit)
Creates lease4-get-page command.
Queue holding a backlog of unsent lease updates.
dhcp::LeasePtr pop(OpType &op_type)
Returns the next lease update and removes it from the queue.
OpType
Type of the lease update (operation type).
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
ConstElementPtr createCommand(const std::string &command)
Creates a standard command message with no argument (of the form { "command": "my_command" }...
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:508
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition lease.h:676
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:295
HAServerType
Lists possible server types for which HA service is created.
std::string stateToString(int state)
Returns state name.
Defines the logger used by the top-level component of kea-lfc.
Structure that holds a lease for IPv4 address.
Definition lease.h:303
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition lease.cc:389
Structure that holds a lease for IPv6 address and/or prefix.
Definition lease.h:516
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition lease.cc:628