Kea  1.5.0
host_data_source_factory.cc
Go to the documentation of this file.
1 // Copyright (C) 2015-2018 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 <dhcpsrv/dhcpsrv_log.h>
11 #include <dhcpsrv/hosts_log.h>
12 #include <log/logger_support.h>
13 
14 #ifdef HAVE_MYSQL
16 #endif
17 
18 #ifdef HAVE_PGSQL
20 #endif
21 
22 #ifdef HAVE_CQL
24 #endif
25 
26 #include <boost/algorithm/string.hpp>
27 #include <boost/foreach.hpp>
28 #include <boost/scoped_ptr.hpp>
29 
30 #include <algorithm>
31 #include <iostream>
32 #include <iterator>
33 #include <map>
34 #include <sstream>
35 #include <utility>
36 
37 using namespace isc::db;
38 using namespace std;
39 
40 namespace isc {
41 namespace dhcp {
42 
43 map<string, HostDataSourceFactory::Factory> HostDataSourceFactory::map_;
44 
45 void
46 HostDataSourceFactory::add(HostDataSourceList& sources,
47  const string& dbaccess) {
48  // Parse the access string and create a redacted string for logging.
50  DatabaseConnection::parse(dbaccess);
51 
52  // Get the database type and open the corresponding database
53  DatabaseConnection::ParameterMap::iterator it = parameters.find("type");
54  if (it == parameters.end()) {
55  isc_throw(InvalidParameter, "Host database configuration does not "
56  "contain the 'type' keyword");
57  }
58 
59  string db_type = it->second;
60  auto index = map_.find(db_type);
61 
62  // No match?
63  if (index == map_.end()) {
64  isc_throw(InvalidType, "The type of host backend: '" <<
65  db_type << "' is not currently supported");
66  }
67 
68  // Call the factory and push the pointer on sources.
69  sources.push_back(boost::shared_ptr<BaseHostDataSource>(index->second(parameters)));
70 
71  // Check the factory did not return NULL.
72  if (!sources.back()) {
73  sources.pop_back();
74  isc_throw(Unexpected, "Hosts database " << db_type <<
75  " factory returned NULL");
76  }
77 }
78 
79 bool
80 HostDataSourceFactory::del(HostDataSourceList& sources,
81  const string& db_type) {
82  for (auto it = sources.begin(); it != sources.end(); ++it) {
83  if ((*it)->getType() != db_type) {
84  continue;
85  }
86  LOG_DEBUG(hosts_logger, DHCPSRV_DBG_TRACE, HOSTS_CFG_CLOSE_HOST_DATA_SOURCE)
87  .arg(db_type);
88  sources.erase(it);
89  return (true);
90  }
91  return (false);
92 }
93 
94 bool
95 HostDataSourceFactory::registerFactory(const string& db_type,
96  const Factory& factory,
97  bool no_log) {
98  if (map_.count(db_type)) {
99  return (false);
100  }
101  map_.insert(pair<string, Factory>(db_type, factory));
102 
103  // We are dealing here with static logger initialization fiasco.
104  // registerFactory may be called from constructors of static global
105  // objects for built in backends. The logging is not initialized yet,
106  // so the LOG_DEBUG would throw.
107  if (!no_log) {
108  LOG_DEBUG(hosts_logger, DHCPSRV_DBG_TRACE, HOSTS_BACKEND_REGISTER)
109  .arg(db_type);
110  }
111  return (true);
112 }
113 
114 bool
115 HostDataSourceFactory::deregisterFactory(const string& db_type, bool no_log) {
116  auto index = map_.find(db_type);
117  if (index != map_.end()) {
118  map_.erase(index);
119  if (!no_log) {
121  HOSTS_BACKEND_DEREGISTER)
122  .arg(db_type);
123  }
124  return (true);
125  } else {
126  return (false);
127  }
128 }
129 
130 bool
131 HostDataSourceFactory::registeredFactory(const std::string& db_type) {
132  auto index = map_.find(db_type);
133  return (index != map_.end());
134 }
135 
136 void
137 HostDataSourceFactory::printRegistered() {
138  std::stringstream txt;
139 
140  for (auto x : map_) {
141  txt << x.first << " ";
142  }
143 
144  LOG_INFO(hosts_logger, HOSTS_BACKENDS_REGISTERED).arg(txt.str());
145 }
146 
147 } // namespace dhcp
148 } // namespace isc
149 
150 //
151 // Register database backends
152 //
153 
154 using namespace isc::dhcp;
155 
156 namespace {
157 
158 #ifdef HAVE_MYSQL
159 struct MySqlHostDataSourceInit {
160  // Constructor registers
161  MySqlHostDataSourceInit() {
162  HostDataSourceFactory::registerFactory("mysql", factory, true);
163  }
164 
165  // Destructor deregisters
166  ~MySqlHostDataSourceInit() {
167  HostDataSourceFactory::deregisterFactory("mysql", true);
168  }
169 
170  // Factory class method
171  static HostDataSourcePtr
172  factory(const DatabaseConnection::ParameterMap& parameters) {
173  LOG_INFO(hosts_logger, DHCPSRV_MYSQL_HOST_DB)
175  return (HostDataSourcePtr(new MySqlHostDataSource(parameters)));
176  }
177 };
178 
179 // Database backend will be registered at object initialization
180 MySqlHostDataSourceInit mysql_init_;
181 #endif
182 
183 #ifdef HAVE_PGSQL
184 struct PgSqlHostDataSourceInit {
185  // Constructor registers
186  PgSqlHostDataSourceInit() {
187  HostDataSourceFactory::registerFactory("postgresql", factory, true);
188  }
189 
190  // Destructor deregisters
191  ~PgSqlHostDataSourceInit() {
192  HostDataSourceFactory::deregisterFactory("postgresql", true);
193  }
194 
195  // Factory class method
196  static HostDataSourcePtr
197  factory(const DatabaseConnection::ParameterMap& parameters) {
198  LOG_INFO(hosts_logger, DHCPSRV_PGSQL_HOST_DB)
200  return (HostDataSourcePtr(new PgSqlHostDataSource(parameters)));
201  }
202 };
203 
204 // Database backend will be registered at object initialization
205 PgSqlHostDataSourceInit pgsql_init_;
206 #endif
207 
208 #ifdef HAVE_CQL
209 struct CqlHostDataSourceInit {
210  // Constructor registers
211  CqlHostDataSourceInit() {
212  HostDataSourceFactory::registerFactory("cql", factory, true);
213  }
214 
215  // Destructor deregisters
216  ~CqlHostDataSourceInit() {
217  HostDataSourceFactory::deregisterFactory("cql", true);
218  }
219 
220  // Factory class method
221  static HostDataSourcePtr
222  factory(const DatabaseConnection::ParameterMap& parameters) {
223  LOG_INFO(dhcpsrv_logger, DHCPSRV_CQL_HOST_DB)
225  return (HostDataSourcePtr(new CqlHostDataSource(parameters)));
226  }
227 };
228 
229 // Database backend will be registered at object initialization
230 CqlHostDataSourceInit cql_init_;
231 #endif
232 
233 } // end of anonymous namespace
isc::dhcp::hosts_logger
isc::log::Logger hosts_logger("hosts")
Logger for the HostMgr and the code it calls.
Definition: hosts_log.h:51
isc::db::InvalidType
Invalid type exception.
Definition: database_connection.h:45
isc::Unexpected
A generic exception that is thrown when an unexpected error condition occurs.
Definition: exceptions/exceptions.h:153
hosts_log.h
isc::db
Definition: cql_connection.cc:29
isc::dhcp::MySqlHostDataSource
MySQL Host Data Source.
Definition: mysql_host_data_source.h:30
cql_host_data_source.h
isc::db::DatabaseConnection::redactedAccessString
static std::string redactedAccessString(const ParameterMap &parameters)
Redact database access string.
Definition: database_connection.cc:66
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
LOG_DEBUG
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
isc::InvalidParameter
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
Definition: exceptions/exceptions.h:124
dhcpsrv_log.h
isc::dhcp::HostDataSourceList
std::vector< HostDataSourcePtr > HostDataSourceList
HostDataSource list.
Definition: base_host_data_source.h:254
isc::dhcp::DHCPSRV_DBG_TRACE
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
isc::dhcp
Definition: ctrl_dhcp4_srv.cc:75
mysql_host_data_source.h
pgsql_host_data_source.h
isc::dhcp::CqlHostDataSource
Cassandra host data source.
Definition: cql_host_data_source.h:56
isc::db::DatabaseConnection::parse
static ParameterMap parse(const std::string &dbaccess)
Parse database access string.
Definition: database_connection.cc:37
isc::dhcp::PgSqlHostDataSource
PostgreSQL Host Data Source.
Definition: pgsql_host_data_source.h:35
isc::dhcp::HostDataSourcePtr
boost::shared_ptr< BaseHostDataSource > HostDataSourcePtr
HostDataSource pointer.
Definition: base_host_data_source.h:251
host_data_source_factory.h
isc::db::DatabaseConnection::ParameterMap
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Definition: database_connection.h:152
isc::dhcp::HostDataSourceFactory::Factory
boost::function< HostDataSourcePtr(const db::DatabaseConnection::ParameterMap &)> Factory
Type of host data source factory.
Definition: host_data_source_factory.h:82
LOG_INFO
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
isc::dhcp::dhcpsrv_logger
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
logger_support.h
Logging initialization functions.