Kea  1.9.9-git
command_creator.cc
Go to the documentation of this file.
1 // Copyright (C) 2018-2021 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 
17 namespace isc {
18 namespace ha {
19 
21 CommandCreator::createDHCPDisable(const unsigned int max_period,
22  const HAServerType& server_type) {
23  ElementPtr args;
24  args = Element::createMap();
25  args->set("origin", Element::create("ha-partner"));
26  // max-period is optional. A value of 0 means that it is not specified.
27  if (max_period > 0) {
28  args->set("max-period", Element::create(static_cast<long int>(max_period)));
29  }
30  ConstElementPtr command = config::createCommand("dhcp-disable", args);
31  insertService(command, server_type);
32  return (command);
33 }
34 
36 CommandCreator::createDHCPEnable(const HAServerType& server_type) {
37  ElementPtr args;
38  args = Element::createMap();
39  args->set("origin", Element::create("ha-partner"));
40  ConstElementPtr command = config::createCommand("dhcp-enable", args);
41  insertService(command, server_type);
42  return (command);
43 }
44 
46 CommandCreator::createHAReset(const HAServerType& server_type) {
47  ConstElementPtr command = config::createCommand("ha-reset");
48  insertService(command, server_type);
49  return (command);
50 }
51 
53 CommandCreator::createHeartbeat(const HAServerType& server_type) {
54  ConstElementPtr command = config::createCommand("ha-heartbeat");
55  insertService(command, server_type);
56  return (command);
57 }
58 
60 CommandCreator::createLease4Update(const Lease4& lease4) {
61  ElementPtr lease_as_json = lease4.toElement();
62  insertLeaseExpireTime(lease_as_json);
63  lease_as_json->set("force-create", Element::create(true));
64  ConstElementPtr command = config::createCommand("lease4-update", lease_as_json);
65  insertService(command, HAServerType::DHCPv4);
66  return (command);
67 }
68 
70 CommandCreator::createLease4Delete(const Lease4& lease4) {
71  ElementPtr lease_as_json = lease4.toElement();
72  insertLeaseExpireTime(lease_as_json);
73  ConstElementPtr command = config::createCommand("lease4-del", lease_as_json);
74  insertService(command, HAServerType::DHCPv4);
75  return (command);
76 }
77 
79 CommandCreator::createLease4GetAll() {
80  ConstElementPtr command = config::createCommand("lease4-get-all");
81  insertService(command, HAServerType::DHCPv4);
82  return (command);
83 }
84 
86 CommandCreator::createLease4GetPage(const Lease4Ptr& last_lease4,
87  const uint32_t limit) {
88  // Zero value is not allowed.
89  if (limit == 0) {
90  isc_throw(BadValue, "limit value for lease4-get-page command must not be 0");
91  }
92 
93  // Get the last lease returned on the previous page. A null pointer means that
94  // we're fetching first page. In that case a keyword "start" is used to indicate
95  // that first page should be returned.
96  ElementPtr from_element = Element::create(last_lease4 ? last_lease4->addr_.toText() : "start");
97  // Set the maximum size of the page.
98  ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
99  // Put both parameters into arguments map.
101  args->set("from", from_element);
102  args->set("limit", limit_element);
103 
104  // Create the command.
105  ConstElementPtr command = config::createCommand("lease4-get-page", args);
106  insertService(command, HAServerType::DHCPv4);
107  return (command);
108 }
109 
111 CommandCreator::createLease6BulkApply(const Lease6CollectionPtr& leases,
112  const Lease6CollectionPtr& deleted_leases) {
113  ElementPtr deleted_leases_list = Element::createList();
114  for (auto lease = deleted_leases->begin(); lease != deleted_leases->end();
115  ++lease) {
116  ElementPtr lease_as_json = (*lease)->toElement();
117  insertLeaseExpireTime(lease_as_json);
118  deleted_leases_list->add(lease_as_json);
119  }
120 
121  ElementPtr leases_list = Element::createList();
122  for (auto lease = leases->begin(); lease != leases->end();
123  ++lease) {
124  ElementPtr lease_as_json = (*lease)->toElement();
125  insertLeaseExpireTime(lease_as_json);
126  leases_list->add(lease_as_json);
127  }
128 
130  args->set("deleted-leases", deleted_leases_list);
131  args->set("leases", leases_list);
132 
133  ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
134  insertService(command, HAServerType::DHCPv6);
135  return (command);
136 }
137 
139 CommandCreator::createLease6BulkApply(LeaseUpdateBacklog& leases) {
140  ElementPtr deleted_leases_list = Element::createList();
141  ElementPtr leases_list = Element::createList();
142 
144  Lease6Ptr lease;
145  while ((lease = boost::dynamic_pointer_cast<Lease6>(leases.pop(op_type)))) {
146  ElementPtr lease_as_json = lease->toElement();
147  insertLeaseExpireTime(lease_as_json);
148  if (op_type == LeaseUpdateBacklog::DELETE) {
149  deleted_leases_list->add(lease_as_json);
150  } else {
151  leases_list->add(lease_as_json);
152  }
153  }
154 
156  args->set("deleted-leases", deleted_leases_list);
157  args->set("leases", leases_list);
158 
159  ConstElementPtr command = config::createCommand("lease6-bulk-apply", args);
160  insertService(command, HAServerType::DHCPv6);
161  return (command);
162 }
163 
165 CommandCreator::createLease6Update(const Lease6& lease6) {
166  ElementPtr lease_as_json = lease6.toElement();
167  insertLeaseExpireTime(lease_as_json);
168  lease_as_json->set("force-create", Element::create(true));
169  ConstElementPtr command = config::createCommand("lease6-update", lease_as_json);
170  insertService(command, HAServerType::DHCPv6);
171  return (command);
172 }
173 
175 CommandCreator::createLease6Delete(const Lease6& lease6) {
176  ElementPtr lease_as_json = lease6.toElement();
177  insertLeaseExpireTime(lease_as_json);
178  ConstElementPtr command = config::createCommand("lease6-del", lease_as_json);
179  insertService(command, HAServerType::DHCPv6);
180  return (command);
181 }
182 
184 CommandCreator::createLease6GetAll() {
185  ConstElementPtr command = config::createCommand("lease6-get-all");
186  insertService(command, HAServerType::DHCPv6);
187  return (command);
188 }
189 
191 CommandCreator::createLease6GetPage(const Lease6Ptr& last_lease6,
192  const uint32_t limit) {
193  // Zero value is not allowed.
194  if (limit == 0) {
195  isc_throw(BadValue, "limit value for lease6-get-page command must not be 0");
196  }
197 
198  // Get the last lease returned on the previous page. A null pointer means that
199  // we're fetching first page. In that case a keyword "start" is used to indicate
200  // that first page should be returned.
201  ElementPtr from_element = Element::create(last_lease6 ? last_lease6->addr_.toText() : "start");
202  // Set the maximum size of the page.
203  ElementPtr limit_element = Element::create(static_cast<long long int>(limit));
204  // Put both parameters into arguments map.
206  args->set("from", from_element);
207  args->set("limit", limit_element);
208 
209  // Create the command.
210  ConstElementPtr command = config::createCommand("lease6-get-page", args);
211  insertService(command, HAServerType::DHCPv6);
212  return (command);
213 }
214 
216 CommandCreator::createMaintenanceNotify(const bool cancel, const HAServerType& server_type) {
217  auto args = Element::createMap();
218  args->set("cancel", Element::create(cancel));
219  auto command = config::createCommand("ha-maintenance-notify", args);
220  insertService(command, server_type);
221  return (command);
222 }
223 
224 void
225 CommandCreator::insertLeaseExpireTime(ElementPtr& lease) {
226  if ((lease->getType() != Element::map) ||
227  (!lease->contains("cltt") || (lease->get("cltt")->getType() != Element::integer) ||
228  (!lease->contains("valid-lft") ||
229  (lease->get("valid-lft")->getType() != Element::integer)))) {
230  isc_throw(Unexpected, "invalid lease format");
231  }
232 
233  int64_t cltt = lease->get("cltt")->intValue();
234  int64_t valid_lifetime = lease->get("valid-lft")->intValue();
235  int64_t expire = cltt + valid_lifetime;
236  lease->set("expire", Element::create(expire));
237  lease->remove("cltt");
238 }
239 
240 void
241 CommandCreator::insertService(ConstElementPtr& command,
242  const HAServerType& server_type) {
243  ElementPtr service = Element::createList();
244  const std::string service_name = (server_type == HAServerType::DHCPv4 ? "dhcp4" : "dhcp6");
245  service->add(Element::create(service_name));
246 
247  // We have no better way of setting a new element here than
248  // doing const pointer cast. That's another reason why this
249  // functionality could be moved to the core code. We don't
250  // do it however, because we want to minimize concurrent
251  // code changes in the premium and core Kea repos.
252  (boost::const_pointer_cast<Element>(command))->set("service", service);
253 }
254 
255 } // end of namespace ha
256 } // end of namespace isc
Structure that holds a lease for IPv4 address.
Definition: lease.h:294
OpType
Type of the lease update (operation type).
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
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:267
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:262
#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:283
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.
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition: lease.cc:639
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:503
Defines the logger used by the top-level component of kea-dhcp-ddns.
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:222
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition: lease.h:644
The Element class represents a piece of data, used by the command channel and configuration parts...
Definition: data.h:66
dhcp::LeasePtr pop(OpType &op_type)
Returns the next lease update and removes it from the queue.
virtual isc::data::ElementPtr toElement() const
Return the JSON representation of a lease.
Definition: lease.cc:425
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:492
Queue holding a backlog of unsent lease updates.