cfgmgr.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <asiolink/io_address.h>
  16. #include <dhcp/iface_mgr.h>
  17. #include <dhcp/libdhcp++.h>
  18. #include <dhcpsrv/cfgmgr.h>
  19. #include <dhcpsrv/dhcpsrv_log.h>
  20. #include <dhcpsrv/subnet_id.h>
  21. #include <stats/stats_mgr.h>
  22. #include <sstream>
  23. #include <string>
  24. using namespace isc::asiolink;
  25. using namespace isc::util;
  26. using namespace isc::stats;
  27. namespace isc {
  28. namespace dhcp {
  29. const size_t CfgMgr::CONFIG_LIST_SIZE = 10;
  30. CfgMgr&
  31. CfgMgr::instance() {
  32. static CfgMgr cfg_mgr;
  33. return (cfg_mgr);
  34. }
  35. void
  36. CfgMgr::addOptionSpace4(const OptionSpacePtr& space) {
  37. if (!space) {
  38. isc_throw(InvalidOptionSpace,
  39. "provided option space object is NULL.");
  40. }
  41. OptionSpaceCollection::iterator it = spaces4_.find(space->getName());
  42. if (it != spaces4_.end()) {
  43. isc_throw(InvalidOptionSpace, "option space " << space->getName()
  44. << " already added.");
  45. }
  46. spaces4_.insert(make_pair(space->getName(), space));
  47. }
  48. void
  49. CfgMgr::addOptionSpace6(const OptionSpacePtr& space) {
  50. if (!space) {
  51. isc_throw(InvalidOptionSpace,
  52. "provided option space object is NULL.");
  53. }
  54. OptionSpaceCollection::iterator it = spaces6_.find(space->getName());
  55. if (it != spaces6_.end()) {
  56. isc_throw(InvalidOptionSpace, "option space " << space->getName()
  57. << " already added.");
  58. }
  59. spaces6_.insert(make_pair(space->getName(), space));
  60. }
  61. std::string CfgMgr::getDataDir() {
  62. return (datadir_);
  63. }
  64. bool
  65. CfgMgr::isDuplicate(const Subnet6& subnet) const {
  66. for (Subnet6Collection::const_iterator subnet_it = subnets6_.begin();
  67. subnet_it != subnets6_.end(); ++subnet_it) {
  68. if ((*subnet_it)->getID() == subnet.getID()) {
  69. return (true);
  70. }
  71. }
  72. return (false);
  73. }
  74. void
  75. CfgMgr::setD2ClientConfig(D2ClientConfigPtr& new_config) {
  76. d2_client_mgr_.setD2ClientConfig(new_config);
  77. }
  78. bool
  79. CfgMgr::ddnsEnabled() {
  80. return (d2_client_mgr_.ddnsEnabled());
  81. }
  82. const D2ClientConfigPtr&
  83. CfgMgr::getD2ClientConfig() const {
  84. return (d2_client_mgr_.getD2ClientConfig());
  85. }
  86. D2ClientMgr&
  87. CfgMgr::getD2ClientMgr() {
  88. return (d2_client_mgr_);
  89. }
  90. void
  91. CfgMgr::ensureCurrentAllocated() {
  92. if (!configuration_ || configs_.empty()) {
  93. configuration_.reset(new SrvConfig());
  94. configs_.push_back(configuration_);
  95. }
  96. }
  97. void
  98. CfgMgr::clear() {
  99. if (configuration_) {
  100. configuration_->removeStatistics();
  101. }
  102. configs_.clear();
  103. ensureCurrentAllocated();
  104. }
  105. void
  106. CfgMgr::commit() {
  107. ensureCurrentAllocated();
  108. // First we need to remove statistics. The new configuration can have fewer
  109. // subnets. Also, it may change subnet-ids. So we need to remove them all
  110. // and add it back.
  111. configuration_->removeStatistics();
  112. if (!configs_.back()->sequenceEquals(*configuration_)) {
  113. configuration_ = configs_.back();
  114. // Keep track of the maximum size of the configs history. Before adding
  115. // new element, we have to remove the oldest one.
  116. if (configs_.size() > CONFIG_LIST_SIZE) {
  117. SrvConfigList::iterator it = configs_.begin();
  118. std::advance(it, configs_.size() - CONFIG_LIST_SIZE);
  119. configs_.erase(configs_.begin(), it);
  120. }
  121. }
  122. // Now we need to set the statistics back.
  123. configuration_->updateStatistics();
  124. }
  125. void
  126. CfgMgr::rollback() {
  127. ensureCurrentAllocated();
  128. if (!configuration_->sequenceEquals(*configs_.back())) {
  129. configs_.pop_back();
  130. }
  131. }
  132. void
  133. CfgMgr::revert(const size_t index) {
  134. ensureCurrentAllocated();
  135. if (index == 0) {
  136. isc_throw(isc::OutOfRange, "invalid commit index 0 when reverting"
  137. " to an old configuration");
  138. } else if (index > configs_.size() - 1) {
  139. isc_throw(isc::OutOfRange, "unable to revert to commit index '"
  140. << index << "', only '" << configs_.size() - 1
  141. << "' previous commits available");
  142. }
  143. // Let's rollback an existing configuration to make sure that the last
  144. // configuration on the list is the current one. Note that all remaining
  145. // operations in this function should be exception free so there shouldn't
  146. // be a problem that the revert operation fails and the staging
  147. // configuration is destroyed by this rollback.
  148. rollback();
  149. // Get the iterator to the current configuration and then advance to the
  150. // desired one.
  151. SrvConfigList::const_reverse_iterator it = configs_.rbegin();
  152. std::advance(it, index);
  153. // Copy the desired configuration to the new staging configuration. The
  154. // staging configuration is re-created here because we rolled back earlier
  155. // in this function.
  156. (*it)->copy(*getStagingCfg());
  157. // Make the staging configuration a current one.
  158. commit();
  159. }
  160. ConstSrvConfigPtr
  161. CfgMgr::getCurrentCfg() {
  162. ensureCurrentAllocated();
  163. return (configuration_);
  164. }
  165. SrvConfigPtr
  166. CfgMgr::getStagingCfg() {
  167. ensureCurrentAllocated();
  168. if (configuration_->sequenceEquals(*configs_.back())) {
  169. uint32_t sequence = configuration_->getSequence();
  170. configs_.push_back(SrvConfigPtr(new SrvConfig(++sequence)));
  171. }
  172. return (configs_.back());
  173. }
  174. CfgMgr::CfgMgr()
  175. : datadir_(DHCP_DATA_DIR), echo_v4_client_id_(true),
  176. d2_client_mgr_(), verbose_mode_(false) {
  177. // DHCP_DATA_DIR must be set set with -DDHCP_DATA_DIR="..." in Makefile.am
  178. // Note: the definition of DHCP_DATA_DIR needs to include quotation marks
  179. // See AM_CPPFLAGS definition in Makefile.am
  180. }
  181. CfgMgr::~CfgMgr() {
  182. }
  183. }; // end of isc::dhcp namespace
  184. }; // end of isc namespace