Kea 3.3.3
command_creator.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
13
14#include <boost/pointer_cast.hpp>
15
16using namespace isc::data;
17using namespace isc::dhcp;
18using namespace std;
19
20namespace isc {
21namespace ha {
22
23unordered_set<string> CommandCreator::ha_commands4_ = {
24 "list-commands", "status-get",
25 "dhcp-disable", "dhcp-enable",
26 "ha-reset", "ha-heartbeat",
27 "lease4-update", "lease4-del",
28 "lease4-get-all", "lease4-get-page",
29 "ha-maintenance-notify", "ha-sync-complete-notify"
30};
31
32unordered_set<string> CommandCreator::ha_commands6_ = {
33 "list-commands", "status-get",
34 "dhcp-disable", "dhcp-enable",
35 "ha-reset", "ha-heartbeat",
36 "lease6-bulk-apply",
37 "lease6-update", "lease6-del",
38 "lease6-get-all", "lease6-get-page",
39 "ha-maintenance-notify", "ha-sync-complete-notify"
40};
41
43CommandCreator::createDHCPDisable(const unsigned int origin_id,
44 const unsigned int max_period,
45 const HAServerType& server_type) {
46 ElementPtr args;
47 args = Element::createMap();
48 args->set("origin-id", Element::create(origin_id));
49 // Add for backward compatibility with Kea 2.4.0 and earlier.
50 args->set("origin", Element::create("ha-partner"));
51 // max-period is optional. A value of 0 means that it is not specified.
52 if (max_period > 0) {
53 args->set("max-period", Element::create(static_cast<long int>(max_period)));
54 }
55 ConstElementPtr command = config::createCommand("dhcp-disable", args);
56 insertService(command, server_type);
57 return (command);
58}
59
61CommandCreator::createDHCPEnable(const unsigned int origin_id,
62 const HAServerType& server_type) {
63 ElementPtr args;
64 args = Element::createMap();
65 args->set("origin-id", Element::create(origin_id));
66 // Add for backward compatibility with Kea 2.4.0 and earlier.
67 args->set("origin", Element::create("ha-partner"));
68 ConstElementPtr command = config::createCommand("dhcp-enable", args);
69 insertService(command, server_type);
70 return (command);
71}
72
74CommandCreator::createHAReset(const std::string& server_name,
75 const HAServerType& server_type) {
76 auto args = Element::createMap();
77 args->set("server-name", Element::create(server_name));
78 ConstElementPtr command = config::createCommand("ha-reset", args);
79 insertService(command, server_type);
80 return (command);
81}
82
84CommandCreator::createHeartbeat(const std::string& server_name,
85 const HAServerType& server_type) {
86 auto args = Element::createMap();
87 args->set("server-name", Element::create(server_name));
88 ConstElementPtr command = config::createCommand("ha-heartbeat", args);
89 insertService(command, server_type);
90 return (command);
91}
92
95 ElementPtr lease_as_json = lease4.toElement();
96 insertLeaseExpireTime(lease_as_json);
97 lease_as_json->set("force-create", Element::create(true));
98 lease_as_json->set("origin", Element::create("ha-partner"));
99 ConstElementPtr command = config::createCommand("lease4-update", lease_as_json);
100 insertService(command, HAServerType::DHCPv4);
101 return (command);
102}
103
106 ElementPtr lease_as_json = lease4.toElement();
107 insertLeaseExpireTime(lease_as_json);
108 lease_as_json->set("origin", Element::create("ha-partner"));
109 ConstElementPtr command = config::createCommand("lease4-del", lease_as_json);
110 insertService(command, HAServerType::DHCPv4);
111 return (command);
112}
113
116 ConstElementPtr command = config::createCommand("lease4-get-all");
117 insertService(command, HAServerType::DHCPv4);
118 return (command);
119}
120
123 const uint32_t limit) {
124 // Zero value is not allowed.
125 if (limit == 0) {
126 isc_throw(BadValue, "limit value for lease4-get-page command must not be 0");
127 }
128
129 // Get the last lease returned on the previous page. A null pointer means that
130 // we're fetching first page. In that case a keyword "start" is used to indicate
131 // that first page should be returned.
132 ElementPtr from_element = Element::create(last_lease4 ? last_lease4->addr_.toText() : "start");
133 // Set the maximum size of the page.
134 ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
135 // Put both parameters into arguments map.
137 args->set("from", from_element);
138 args->set("limit", limit_element);
139
140 // Create the command.
141 ConstElementPtr command = config::createCommand("lease4-get-page", args);
142 insertService(command, HAServerType::DHCPv4);
143 return (command);
144}
145
148 const Lease6CollectionPtr& deleted_leases) {
149 ElementPtr leases_list = Element::createList();
150 ElementPtr deleted_leases_list = Element::createList();
151 for (auto const& lease : *deleted_leases) {
152 ElementPtr lease_as_json = lease->toElement();
153 insertLeaseExpireTime(lease_as_json);
154 // If the deleted lease is in the released state it means that it
155 // should be preserved in the database. It is treated as released
156 // but can be re-allocated to the same client later (lease affinity).
157 // Such a lease should be updated by the partner rather than deleted.
158 if (lease->state_ == Lease6::STATE_RELEASED) {
159 leases_list->add(lease_as_json);
160 } else {
161 deleted_leases_list->add(lease_as_json);
162 }
163 }
164
165 for (auto const& lease : *leases) {
166 ElementPtr lease_as_json = lease->toElement();
167 insertLeaseExpireTime(lease_as_json);
168 leases_list->add(lease_as_json);
169 }
170
172 args->set("deleted-leases", deleted_leases_list);
173 args->set("leases", leases_list);
174 args->set("origin", Element::create("ha-partner"));
175
176 ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
177 insertService(command, HAServerType::DHCPv6);
178 return (command);
179}
180
183 ElementPtr deleted_leases_list = Element::createList();
184 ElementPtr leases_list = Element::createList();
185
187 Lease6Ptr lease;
188 while ((lease = boost::dynamic_pointer_cast<Lease6>(leases.pop(op_type)))) {
189 ElementPtr lease_as_json = lease->toElement();
190 insertLeaseExpireTime(lease_as_json);
191 if (op_type == LeaseUpdateBacklog::DELETE) {
192 deleted_leases_list->add(lease_as_json);
193 } else {
194 leases_list->add(lease_as_json);
195 }
196 }
197
199 args->set("deleted-leases", deleted_leases_list);
200 args->set("leases", leases_list);
201 args->set("origin", Element::create("ha-partner"));
202
203 ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
204 insertService(command, HAServerType::DHCPv6);
205 return (command);
206}
207
210 ElementPtr lease_as_json = lease6.toElement();
211 insertLeaseExpireTime(lease_as_json);
212 lease_as_json->set("force-create", Element::create(true));
213 lease_as_json->set("origin", Element::create("ha-partner"));
214 ConstElementPtr command = config::createCommand("lease6-update", lease_as_json);
215 insertService(command, HAServerType::DHCPv6);
216 return (command);
217}
218
221 ElementPtr lease_as_json = lease6.toElement();
222 insertLeaseExpireTime(lease_as_json);
223 lease_as_json->set("origin", Element::create("ha-partner"));
224 ConstElementPtr command = config::createCommand("lease6-del", lease_as_json);
225 insertService(command, HAServerType::DHCPv6);
226 return (command);
227}
228
231 ConstElementPtr command = config::createCommand("lease6-get-all");
232 insertService(command, HAServerType::DHCPv6);
233 return (command);
234}
235
238 const uint32_t limit) {
239 // Zero value is not allowed.
240 if (limit == 0) {
241 isc_throw(BadValue, "limit value for lease6-get-page command must not be 0");
242 }
243
244 // Get the last lease returned on the previous page. A null pointer means that
245 // we're fetching first page. In that case a keyword "start" is used to indicate
246 // that first page should be returned.
247 ElementPtr from_element = Element::create(last_lease6 ? last_lease6->addr_.toText() : "start");
248 // Set the maximum size of the page.
249 ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
250 // Put both parameters into arguments map.
252 args->set("from", from_element);
253 args->set("limit", limit_element);
254
255 // Create the command.
256 ConstElementPtr command = config::createCommand("lease6-get-page", args);
257 insertService(command, HAServerType::DHCPv6);
258 return (command);
259}
260
262CommandCreator::createMaintenanceNotify(const std::string& server_name,
263 const bool cancel,
264 const int state,
265 const HAServerType& server_type) {
266 auto args = Element::createMap();
267 args->set("server-name", Element::create(server_name));
268 args->set("cancel", Element::create(cancel));
269 args->set("state", Element::create(stateToString(state)));
270 auto command = config::createCommand("ha-maintenance-notify", args);
271 insertService(command, server_type);
272 return (command);
273}
274
276CommandCreator::createSyncCompleteNotify(const unsigned int origin_id,
277 const std::string& server_name,
278 const HAServerType& server_type) {
279 auto args = Element::createMap();
280 args->set("server-name", Element::create(server_name));
281 args->set("origin-id", Element::create(origin_id));
282 // Add for backward compatibility with Kea 2.5.5 to Kea 2.5.7.
283 // The origin parameter was introduced for this command in Kea 2.5.5 but
284 // renamed to origin-id to be consistent with the origin-id used in
285 // dhcp-enable and dhcp-disable commands starting from Kea 2.5.8.
286 args->set("origin", Element::create(origin_id));
287 auto command = config::createCommand("ha-sync-complete-notify", args);
288 insertService(command, server_type);
289 return (command);
290}
291
292void
293CommandCreator::insertLeaseExpireTime(ElementPtr& lease) {
294 if ((lease->getType() != Element::map) ||
295 (!lease->contains("cltt") || (lease->get("cltt")->getType() != Element::integer) ||
296 (!lease->contains("valid-lft") ||
297 (lease->get("valid-lft")->getType() != Element::integer)))) {
298 isc_throw(Unexpected, "invalid lease format");
299 }
300
301 int64_t cltt = lease->get("cltt")->intValue();
302 int64_t valid_lifetime = lease->get("valid-lft")->intValue();
303 int64_t expire = cltt + valid_lifetime;
304 lease->set("expire", Element::create(expire));
305 lease->remove("cltt");
306}
307
308void
309CommandCreator::insertService(ConstElementPtr& command,
310 const HAServerType& server_type) {
312 const string service_name = (server_type == HAServerType::DHCPv4 ? "dhcp4" : "dhcp6");
313 service->add(Element::create(service_name));
314
315 // We have no better way of setting a new element here than
316 // doing const pointer cast. That's another reason why this
317 // functionality could be moved to the core code. We don't
318 // do it however, because we want to minimize concurrent
319 // code changes in the premium and core Kea repos.
320 (boost::const_pointer_cast<Element>(command))->set("service", service);
321}
322
323} // end of namespace ha
324} // end of namespace isc
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:300
@ map
Definition data.h:160
@ integer
Definition data.h:153
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:355
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:350
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 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:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:530
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition lease.h:698
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:317
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:325
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition lease.cc:393
Structure that holds a lease for IPv6 address and/or prefix.
Definition lease.h:538
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition lease.cc:646
static constexpr uint32_t STATE_RELEASED
Released lease held in the database for lease affinity.
Definition lease.h:80