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