Kea  2.1.7-git
command_creator.cc
Go to the documentation of this file.
1 // Copyright (C) 2018-2022 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  ConstElementPtr command = config::createCommand("lease4-update", lease_as_json);
85  insertService(command, HAServerType::DHCPv4);
86  return (command);
87 }
88 
90 CommandCreator::createLease4Delete(const Lease4& lease4) {
91  ElementPtr lease_as_json = lease4.toElement();
92  insertLeaseExpireTime(lease_as_json);
93  ConstElementPtr command = config::createCommand("lease4-del", lease_as_json);
94  insertService(command, HAServerType::DHCPv4);
95  return (command);
96 }
97 
99 CommandCreator::createLease4GetAll() {
100  ConstElementPtr command = config::createCommand("lease4-get-all");
101  insertService(command, HAServerType::DHCPv4);
102  return (command);
103 }
104 
106 CommandCreator::createLease4GetPage(const Lease4Ptr& last_lease4,
107  const uint32_t limit) {
108  // Zero value is not allowed.
109  if (limit == 0) {
110  isc_throw(BadValue, "limit value for lease4-get-page command must not be 0");
111  }
112 
113  // Get the last lease returned on the previous page. A null pointer means that
114  // we're fetching first page. In that case a keyword "start" is used to indicate
115  // that first page should be returned.
116  ElementPtr from_element = Element::create(last_lease4 ? last_lease4->addr_.toText() : "start");
117  // Set the maximum size of the page.
118  ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
119  // Put both parameters into arguments map.
121  args->set("from", from_element);
122  args->set("limit", limit_element);
123 
124  // Create the command.
125  ConstElementPtr command = config::createCommand("lease4-get-page", args);
126  insertService(command, HAServerType::DHCPv4);
127  return (command);
128 }
129 
131 CommandCreator::createLease6BulkApply(const Lease6CollectionPtr& leases,
132  const Lease6CollectionPtr& deleted_leases) {
133  ElementPtr deleted_leases_list = Element::createList();
134  for (auto lease = deleted_leases->begin(); lease != deleted_leases->end();
135  ++lease) {
136  ElementPtr lease_as_json = (*lease)->toElement();
137  insertLeaseExpireTime(lease_as_json);
138  deleted_leases_list->add(lease_as_json);
139  }
140 
141  ElementPtr leases_list = Element::createList();
142  for (auto lease = leases->begin(); lease != leases->end();
143  ++lease) {
144  ElementPtr lease_as_json = (*lease)->toElement();
145  insertLeaseExpireTime(lease_as_json);
146  leases_list->add(lease_as_json);
147  }
148 
150  args->set("deleted-leases", deleted_leases_list);
151  args->set("leases", leases_list);
152 
153  ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
154  insertService(command, HAServerType::DHCPv6);
155  return (command);
156 }
157 
159 CommandCreator::createLease6BulkApply(LeaseUpdateBacklog& leases) {
160  ElementPtr deleted_leases_list = Element::createList();
161  ElementPtr leases_list = Element::createList();
162 
164  Lease6Ptr lease;
165  while ((lease = boost::dynamic_pointer_cast<Lease6>(leases.pop(op_type)))) {
166  ElementPtr lease_as_json = lease->toElement();
167  insertLeaseExpireTime(lease_as_json);
168  if (op_type == LeaseUpdateBacklog::DELETE) {
169  deleted_leases_list->add(lease_as_json);
170  } else {
171  leases_list->add(lease_as_json);
172  }
173  }
174 
176  args->set("deleted-leases", deleted_leases_list);
177  args->set("leases", leases_list);
178 
179  ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
180  insertService(command, HAServerType::DHCPv6);
181  return (command);
182 }
183 
185 CommandCreator::createLease6Update(const Lease6& lease6) {
186  ElementPtr lease_as_json = lease6.toElement();
187  insertLeaseExpireTime(lease_as_json);
188  lease_as_json->set("force-create", Element::create(true));
189  ConstElementPtr command = config::createCommand("lease6-update", lease_as_json);
190  insertService(command, HAServerType::DHCPv6);
191  return (command);
192 }
193 
195 CommandCreator::createLease6Delete(const Lease6& lease6) {
196  ElementPtr lease_as_json = lease6.toElement();
197  insertLeaseExpireTime(lease_as_json);
198  ConstElementPtr command = config::createCommand("lease6-del", lease_as_json);
199  insertService(command, HAServerType::DHCPv6);
200  return (command);
201 }
202 
204 CommandCreator::createLease6GetAll() {
205  ConstElementPtr command = config::createCommand("lease6-get-all");
206  insertService(command, HAServerType::DHCPv6);
207  return (command);
208 }
209 
211 CommandCreator::createLease6GetPage(const Lease6Ptr& last_lease6,
212  const uint32_t limit) {
213  // Zero value is not allowed.
214  if (limit == 0) {
215  isc_throw(BadValue, "limit value for lease6-get-page command must not be 0");
216  }
217 
218  // Get the last lease returned on the previous page. A null pointer means that
219  // we're fetching first page. In that case a keyword "start" is used to indicate
220  // that first page should be returned.
221  ElementPtr from_element = Element::create(last_lease6 ? last_lease6->addr_.toText() : "start");
222  // Set the maximum size of the page.
223  ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
224  // Put both parameters into arguments map.
226  args->set("from", from_element);
227  args->set("limit", limit_element);
228 
229  // Create the command.
230  ConstElementPtr command = config::createCommand("lease6-get-page", args);
231  insertService(command, HAServerType::DHCPv6);
232  return (command);
233 }
234 
236 CommandCreator::createMaintenanceNotify(const bool cancel, const HAServerType& server_type) {
237  auto args = Element::createMap();
238  args->set("cancel", Element::create(cancel));
239  auto command = config::createCommand("ha-maintenance-notify", args);
240  insertService(command, server_type);
241  return (command);
242 }
243 
245 CommandCreator::createSyncCompleteNotify(const HAServerType& server_type) {
246  auto command = config::createCommand("ha-sync-complete-notify");
247  insertService(command, server_type);
248  return (command);
249 }
250 
251 void
252 CommandCreator::insertLeaseExpireTime(ElementPtr& lease) {
253  if ((lease->getType() != Element::map) ||
254  (!lease->contains("cltt") || (lease->get("cltt")->getType() != Element::integer) ||
255  (!lease->contains("valid-lft") ||
256  (lease->get("valid-lft")->getType() != Element::integer)))) {
257  isc_throw(Unexpected, "invalid lease format");
258  }
259 
260  int64_t cltt = lease->get("cltt")->intValue();
261  int64_t valid_lifetime = lease->get("valid-lft")->intValue();
262  int64_t expire = cltt + valid_lifetime;
263  lease->set("expire", Element::create(expire));
264  lease->remove("cltt");
265 }
266 
267 void
268 CommandCreator::insertService(ConstElementPtr& command,
269  const HAServerType& server_type) {
270  ElementPtr service = Element::createList();
271  const string service_name = (server_type == HAServerType::DHCPv4 ? "dhcp4" : "dhcp6");
272  service->add(Element::create(service_name));
273 
274  // We have no better way of setting a new element here than
275  // doing const pointer cast. That's another reason why this
276  // functionality could be moved to the core code. We don't
277  // do it however, because we want to minimize concurrent
278  // code changes in the premium and core Kea repos.
279  (boost::const_pointer_cast<Element>(command))->set("service", service);
280 }
281 
282 } // end of namespace ha
283 } // end of namespace isc
Structure that holds a lease for IPv4 address.
Definition: lease.h:289
OpType
Type of the lease update (operation type).
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition: lease.cc:428
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
STL namespace.
HAServerType
Lists possible server types for which HA service is created.
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:286
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:281
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:278
ConstElementPtr createCommand(const std::string &command)
Creates a standard command message with no argument (of the form { "command": "my_command" }) ...
A generic exception that is thrown when an unexpected error condition occurs.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:498
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition: lease.cc:642
Defines the logger used by the top-level component of kea-lfc.
This file contains several functions and constants that are used for handling commands and responses ...
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:241
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition: lease.h:639
The Element class represents a piece of data, used by the command channel and configuration parts...
Definition: data.h:70
dhcp::LeasePtr pop(OpType &op_type)
Returns the next lease update and removes it from the queue.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:487
Queue holding a backlog of unsent lease updates.