Kea  2.5.3
command_creator.cc
Go to the documentation of this file.
1 // Copyright (C) 2018-2023 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 <cc/command_interpreter.h>
11 #include <exceptions/exceptions.h>
12 #include <boost/pointer_cast.hpp>
13 
14 using namespace isc::data;
15 using namespace isc::dhcp;
16 using namespace std;
17 
18 namespace isc {
19 namespace ha {
20 
21 unordered_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 
30 unordered_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 
41 CommandCreator::createDHCPDisable(const unsigned int max_period,
42  const HAServerType& server_type) {
43  ElementPtr args;
44  args = Element::createMap();
45  args->set("origin", Element::create("ha-partner"));
46  // max-period is optional. A value of 0 means that it is not specified.
47  if (max_period > 0) {
48  args->set("max-period", Element::create(static_cast<long int>(max_period)));
49  }
50  ConstElementPtr command = config::createCommand("dhcp-disable", args);
51  insertService(command, server_type);
52  return (command);
53 }
54 
56 CommandCreator::createDHCPEnable(const HAServerType& server_type) {
57  ElementPtr args;
58  args = Element::createMap();
59  args->set("origin", Element::create("ha-partner"));
60  ConstElementPtr command = config::createCommand("dhcp-enable", args);
61  insertService(command, server_type);
62  return (command);
63 }
64 
66 CommandCreator::createHAReset(const HAServerType& server_type) {
67  ConstElementPtr command = config::createCommand("ha-reset");
68  insertService(command, server_type);
69  return (command);
70 }
71 
73 CommandCreator::createHeartbeat(const HAServerType& server_type) {
74  ConstElementPtr command = config::createCommand("ha-heartbeat");
75  insertService(command, server_type);
76  return (command);
77 }
78 
80 CommandCreator::createLease4Update(const Lease4& lease4) {
81  ElementPtr lease_as_json = lease4.toElement();
82  insertLeaseExpireTime(lease_as_json);
83  lease_as_json->set("force-create", Element::create(true));
84  lease_as_json->set("origin", Element::create("ha-partner"));
85  ConstElementPtr command = config::createCommand("lease4-update", lease_as_json);
86  insertService(command, HAServerType::DHCPv4);
87  return (command);
88 }
89 
91 CommandCreator::createLease4Delete(const Lease4& lease4) {
92  ElementPtr lease_as_json = lease4.toElement();
93  insertLeaseExpireTime(lease_as_json);
94  lease_as_json->set("origin", Element::create("ha-partner"));
95  ConstElementPtr command = config::createCommand("lease4-del", lease_as_json);
96  insertService(command, HAServerType::DHCPv4);
97  return (command);
98 }
99 
101 CommandCreator::createLease4GetAll() {
102  ConstElementPtr command = config::createCommand("lease4-get-all");
103  insertService(command, HAServerType::DHCPv4);
104  return (command);
105 }
106 
108 CommandCreator::createLease4GetPage(const Lease4Ptr& last_lease4,
109  const uint32_t limit) {
110  // Zero value is not allowed.
111  if (limit == 0) {
112  isc_throw(BadValue, "limit value for lease4-get-page command must not be 0");
113  }
114 
115  // Get the last lease returned on the previous page. A null pointer means that
116  // we're fetching first page. In that case a keyword "start" is used to indicate
117  // that first page should be returned.
118  ElementPtr from_element = Element::create(last_lease4 ? last_lease4->addr_.toText() : "start");
119  // Set the maximum size of the page.
120  ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
121  // Put both parameters into arguments map.
123  args->set("from", from_element);
124  args->set("limit", limit_element);
125 
126  // Create the command.
127  ConstElementPtr command = config::createCommand("lease4-get-page", args);
128  insertService(command, HAServerType::DHCPv4);
129  return (command);
130 }
131 
133 CommandCreator::createLease6BulkApply(const Lease6CollectionPtr& leases,
134  const Lease6CollectionPtr& deleted_leases) {
135  ElementPtr deleted_leases_list = Element::createList();
136  for (auto lease = deleted_leases->begin(); lease != deleted_leases->end();
137  ++lease) {
138  ElementPtr lease_as_json = (*lease)->toElement();
139  insertLeaseExpireTime(lease_as_json);
140  deleted_leases_list->add(lease_as_json);
141  }
142 
143  ElementPtr leases_list = Element::createList();
144  for (auto lease = leases->begin(); lease != leases->end();
145  ++lease) {
146  ElementPtr lease_as_json = (*lease)->toElement();
147  insertLeaseExpireTime(lease_as_json);
148  leases_list->add(lease_as_json);
149  }
150 
152  args->set("deleted-leases", deleted_leases_list);
153  args->set("leases", leases_list);
154  args->set("origin", Element::create("ha-partner"));
155 
156  ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
157  insertService(command, HAServerType::DHCPv6);
158  return (command);
159 }
160 
162 CommandCreator::createLease6BulkApply(LeaseUpdateBacklog& leases) {
163  ElementPtr deleted_leases_list = Element::createList();
164  ElementPtr leases_list = Element::createList();
165 
167  Lease6Ptr lease;
168  while ((lease = boost::dynamic_pointer_cast<Lease6>(leases.pop(op_type)))) {
169  ElementPtr lease_as_json = lease->toElement();
170  insertLeaseExpireTime(lease_as_json);
171  if (op_type == LeaseUpdateBacklog::DELETE) {
172  deleted_leases_list->add(lease_as_json);
173  } else {
174  leases_list->add(lease_as_json);
175  }
176  }
177 
179  args->set("deleted-leases", deleted_leases_list);
180  args->set("leases", leases_list);
181  args->set("origin", Element::create("ha-partner"));
182 
183  ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
184  insertService(command, HAServerType::DHCPv6);
185  return (command);
186 }
187 
189 CommandCreator::createLease6Update(const Lease6& lease6) {
190  ElementPtr lease_as_json = lease6.toElement();
191  insertLeaseExpireTime(lease_as_json);
192  lease_as_json->set("force-create", Element::create(true));
193  lease_as_json->set("origin", Element::create("ha-partner"));
194  ConstElementPtr command = config::createCommand("lease6-update", lease_as_json);
195  insertService(command, HAServerType::DHCPv6);
196  return (command);
197 }
198 
200 CommandCreator::createLease6Delete(const Lease6& lease6) {
201  ElementPtr lease_as_json = lease6.toElement();
202  insertLeaseExpireTime(lease_as_json);
203  lease_as_json->set("origin", Element::create("ha-partner"));
204  ConstElementPtr command = config::createCommand("lease6-del", lease_as_json);
205  insertService(command, HAServerType::DHCPv6);
206  return (command);
207 }
208 
210 CommandCreator::createLease6GetAll() {
211  ConstElementPtr command = config::createCommand("lease6-get-all");
212  insertService(command, HAServerType::DHCPv6);
213  return (command);
214 }
215 
217 CommandCreator::createLease6GetPage(const Lease6Ptr& last_lease6,
218  const uint32_t limit) {
219  // Zero value is not allowed.
220  if (limit == 0) {
221  isc_throw(BadValue, "limit value for lease6-get-page command must not be 0");
222  }
223 
224  // Get the last lease returned on the previous page. A null pointer means that
225  // we're fetching first page. In that case a keyword "start" is used to indicate
226  // that first page should be returned.
227  ElementPtr from_element = Element::create(last_lease6 ? last_lease6->addr_.toText() : "start");
228  // Set the maximum size of the page.
229  ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
230  // Put both parameters into arguments map.
232  args->set("from", from_element);
233  args->set("limit", limit_element);
234 
235  // Create the command.
236  ConstElementPtr command = config::createCommand("lease6-get-page", args);
237  insertService(command, HAServerType::DHCPv6);
238  return (command);
239 }
240 
242 CommandCreator::createMaintenanceNotify(const bool cancel, const HAServerType& server_type) {
243  auto args = Element::createMap();
244  args->set("cancel", Element::create(cancel));
245  auto command = config::createCommand("ha-maintenance-notify", args);
246  insertService(command, server_type);
247  return (command);
248 }
249 
251 CommandCreator::createSyncCompleteNotify(const HAServerType& server_type) {
252  auto command = config::createCommand("ha-sync-complete-notify");
253  insertService(command, server_type);
254  return (command);
255 }
256 
257 void
258 CommandCreator::insertLeaseExpireTime(ElementPtr& lease) {
259  if ((lease->getType() != Element::map) ||
260  (!lease->contains("cltt") || (lease->get("cltt")->getType() != Element::integer) ||
261  (!lease->contains("valid-lft") ||
262  (lease->get("valid-lft")->getType() != Element::integer)))) {
263  isc_throw(Unexpected, "invalid lease format");
264  }
265 
266  int64_t cltt = lease->get("cltt")->intValue();
267  int64_t valid_lifetime = lease->get("valid-lft")->intValue();
268  int64_t expire = cltt + valid_lifetime;
269  lease->set("expire", Element::create(expire));
270  lease->remove("cltt");
271 }
272 
273 void
274 CommandCreator::insertService(ConstElementPtr& command,
275  const HAServerType& server_type) {
276  ElementPtr service = Element::createList();
277  const string service_name = (server_type == HAServerType::DHCPv4 ? "dhcp4" : "dhcp6");
278  service->add(Element::create(service_name));
279 
280  // We have no better way of setting a new element here than
281  // doing const pointer cast. That's another reason why this
282  // functionality could be moved to the core code. We don't
283  // do it however, because we want to minimize concurrent
284  // code changes in the premium and core Kea repos.
285  (boost::const_pointer_cast<Element>(command))->set("service", service);
286 }
287 
288 } // end of namespace ha
289 } // 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:246
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:301
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:296
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:26
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:502
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition: lease.h:673
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:289
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:300
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition: lease.cc:386
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:513
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition: lease.cc:625