Kea 2.5.9
cfgmgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-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>
9#include <dhcp/iface_mgr.h>
10#include <dhcp/libdhcp++.h>
11#include <dhcpsrv/cfgmgr.h>
12#include <dhcpsrv/dhcpsrv_log.h>
13#include <sstream>
14#include <string>
15
16using namespace isc::asiolink;
17using namespace isc::util;
18
19namespace isc {
20namespace dhcp {
21
22const size_t CfgMgr::CONFIG_LIST_SIZE = 10;
23
24CfgMgr&
26 static CfgMgr cfg_mgr;
27 return (cfg_mgr);
28}
29
32 return (datadir_);
33}
34
35void
36CfgMgr::setDataDir(const std::string& datadir, bool unspecified) {
37 datadir_ = Optional<std::string>(datadir, unspecified);
38}
39
40void
42 ensureCurrentAllocated();
43 // Note that D2ClientMgr::setD2Config() actually attempts to apply the
44 // configuration by stopping its sender and opening a new one and so
45 // forth per the new configuration.
46 d2_client_mgr_->setD2ClientConfig(new_config);
47
48 // Manager will throw if the set fails, if it succeeds
49 // we'll update our SrvConfig, configuration_, with the D2ClientConfig
50 // used. This is largely bookkeeping in case we ever want to compare
51 // configuration_ to another SrvConfig.
52 configuration_->setD2ClientConfig(new_config);
53}
54
55bool
57 return (d2_client_mgr_->ddnsEnabled());
58}
59
62 return (d2_client_mgr_->getD2ClientConfig());
63}
64
67 return (*d2_client_mgr_);
68}
69
70void
71CfgMgr::ensureCurrentAllocated() {
72 if (!configuration_ || configs_.empty()) {
73 configuration_.reset(new SrvConfig());
74 configs_.push_back(configuration_);
75 }
76}
77
78void
80 if (configuration_) {
81 configuration_->removeStatistics();
82 }
83 configs_.clear();
84 external_configs_.clear();
85 D2ClientConfigPtr d2_default_conf(new D2ClientConfig());
86 setD2ClientConfig(d2_default_conf);
87}
88
89void
91 ensureCurrentAllocated();
92
93 // First we need to remove statistics. The new configuration can have fewer
94 // subnets. Also, it may change subnet-ids. So we need to remove them all
95 // and add it back.
96 configuration_->removeStatistics();
97
98 if (!configs_.back()->sequenceEquals(*configuration_)) {
99 configuration_ = configs_.back();
100 // Keep track of the maximum size of the configs history. Before adding
101 // new element, we have to remove the oldest one.
102 if (configs_.size() > CONFIG_LIST_SIZE) {
103 SrvConfigList::iterator it = configs_.begin();
104 std::advance(it, configs_.size() - CONFIG_LIST_SIZE);
105 configs_.erase(configs_.begin(), it);
106 }
107 }
108
109 // Set the last commit timestamp.
110 auto now = boost::posix_time::second_clock::universal_time();
111 configuration_->setLastCommitTime(now);
112
113 // Now we need to set the statistics back.
114 configuration_->updateStatistics();
115
116 configuration_->configureLowerLevelLibraries();
117}
118
119void
121 ensureCurrentAllocated();
122 if (!configuration_->sequenceEquals(*configs_.back())) {
123 configs_.pop_back();
124 }
125}
126
127void
128CfgMgr::revert(const size_t index) {
129 ensureCurrentAllocated();
130 if (index == 0) {
131 isc_throw(isc::OutOfRange, "invalid commit index 0 when reverting"
132 " to an old configuration");
133 } else if (index > configs_.size() - 1) {
134 isc_throw(isc::OutOfRange, "unable to revert to commit index '"
135 << index << "', only '" << configs_.size() - 1
136 << "' previous commits available");
137 }
138
139 // Let's rollback an existing configuration to make sure that the last
140 // configuration on the list is the current one. Note that all remaining
141 // operations in this function should be exception free so there shouldn't
142 // be a problem that the revert operation fails and the staging
143 // configuration is destroyed by this rollback.
144 rollback();
145
146 // Get the iterator to the current configuration and then advance to the
147 // desired one.
148 SrvConfigList::const_reverse_iterator it = configs_.rbegin();
149 std::advance(it, index);
150
151 // Copy the desired configuration to the new staging configuration. The
152 // staging configuration is re-created here because we rolled back earlier
153 // in this function.
154 (*it)->copy(*getStagingCfg());
155
156 // Make the staging configuration a current one.
157 commit();
158}
159
162 ensureCurrentAllocated();
163 return (configuration_);
164}
165
168 ensureCurrentAllocated();
169 if (configuration_->sequenceEquals(*configs_.back())) {
170 uint32_t sequence = configuration_->getSequence();
171 configs_.push_back(SrvConfigPtr(new SrvConfig(++sequence)));
172 }
173 return (configs_.back());
174}
175
178 uint32_t seq = 0;
179
180 if (!external_configs_.empty()) {
181 seq = external_configs_.rbegin()->second->getSequence() + 1;
182 }
183
184 SrvConfigPtr srv_config(new SrvConfig(seq));
185 external_configs_[seq] = srv_config;
186 return (srv_config);
187}
188
189void
190CfgMgr::mergeIntoStagingCfg(const uint32_t seq) {
191 mergeIntoCfg(getStagingCfg(), seq);
192}
193
194void
195CfgMgr::mergeIntoCurrentCfg(const uint32_t seq) {
196 try {
197 // First we need to remove statistics.
198 getCurrentCfg()->removeStatistics();
199 mergeIntoCfg(getCurrentCfg(), seq);
200
201 } catch (...) {
202 // Make sure the statistics is updated even if the merge failed.
203 getCurrentCfg()->updateStatistics();
204 throw;
205 }
206 getCurrentCfg()->updateStatistics();
207}
208
209void
210CfgMgr::mergeIntoCfg(const SrvConfigPtr& target_config, const uint32_t seq) {
211 auto source_config = external_configs_.find(seq);
212 if (source_config != external_configs_.end()) {
213 target_config->merge(*source_config->second);
214 external_configs_.erase(source_config);
215
216 } else {
217 isc_throw(BadValue, "the external configuration with the sequence number "
218 "of " << seq << " was not found");
219 }
220}
221
223 : datadir_(DHCP_DATA_DIR, true), d2_client_mgr_(new D2ClientMgr()), family_(AF_INET) {
224 // DHCP_DATA_DIR must be set set with -DDHCP_DATA_DIR="..." in Makefile.am
225 // Note: the definition of DHCP_DATA_DIR needs to include quotation marks
226 // See AM_CPPFLAGS definition in Makefile.am
227}
228
230}
231
232} // end of isc::dhcp namespace
233} // end of isc namespace
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 if a parameter given to a method would refer to or modify out-of-r...
Configuration Manager.
Definition: cfgmgr.h:70
util::Optional< std::string > getDataDir() const
returns path do the data directory
Definition: cfgmgr.cc:31
CfgMgr()
Protected constructor.
Definition: cfgmgr.cc:222
const D2ClientConfigPtr & getD2ClientConfig() const
Fetches the DHCP-DDNS configuration pointer.
Definition: cfgmgr.cc:61
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
Definition: cfgmgr.cc:66
void clear()
Removes current, staging and all previous configurations.
Definition: cfgmgr.cc:79
SrvConfigPtr createExternalCfg()
Creates an external configuration and returns pointer to it.
Definition: cfgmgr.cc:177
void setD2ClientConfig(D2ClientConfigPtr &new_config)
Updates the DHCP-DDNS client configuration to the given value.
Definition: cfgmgr.cc:41
void rollback()
Removes staging configuration.
Definition: cfgmgr.cc:120
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
virtual ~CfgMgr()
virtual destructor
Definition: cfgmgr.cc:229
void mergeIntoStagingCfg(const uint32_t seq)
Merges external configuration with the given sequence number into the staging configuration.
Definition: cfgmgr.cc:190
void mergeIntoCurrentCfg(const uint32_t seq)
Merges external configuration with the given sequence number into the current configuration.
Definition: cfgmgr.cc:195
void setDataDir(const std::string &datadir, bool unspecified=true)
Sets new data directory.
Definition: cfgmgr.cc:36
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
bool ddnsEnabled()
Convenience method for checking if DHCP-DDNS updates are enabled.
Definition: cfgmgr.cc:56
void revert(const size_t index)
Reverts to one of the previous configurations.
Definition: cfgmgr.cc:128
static const size_t CONFIG_LIST_SIZE
A number of configurations held by CfgMgr.
Definition: cfgmgr.h:76
void commit()
Commits the staging configuration.
Definition: cfgmgr.cc:90
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:57
D2ClientMgr isolates Kea from the details of being a D2 client.
Definition: d2_client_mgr.h:81
Specifies current DHCP configuration.
Definition: srv_config.h:184
A template representing an optional value.
Definition: optional.h:36
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< D2ClientConfig > D2ClientConfigPtr
Defines a pointer for D2ClientConfig instances.
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:1267
Defines the logger used by the top-level component of kea-lfc.