Kea: daemon.cc Source File

| Kea 3.0.0

daemon.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2025 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 <cc/data.h>
10#include <process/daemon.h>
11#include <process/log_parser.h>
12#include <exceptions/exceptions.h>
13#include <log/logger_name.h>
14#include <log/logger_support.h>
15#include <process/config_base.h>
16#include <process/redact_config.h>
17#include <util/filesystem.h>
18
19#include <functional>
20#include <sstream>
21#include <fstream>
22
23#include <errno.h>
24
25using namespace isc::data;
26using namespace isc::util::file;
27
32namespace isc {
33namespace process {
34
35bool Daemon::verbose_ = false;
36
37std::string Daemon::proc_name_("");
38
39std::string Daemon::default_logger_name_("kea");
40
41Daemon::Daemon()
42 : signal_set_(), config_file_(""),
43 pid_file_dir_(PIDFILE_DIR), pid_file_(), am_file_author_(false),
44 exit_value_(EXIT_SUCCESS) {
45
46 // The pid_file_dir can be overridden via environment variable
47 // This is primarily intended to simplify testing
48 const char* const env = getenv("KEA_PIDFILE_DIR");
49 if (env) {
50 pid_file_dir_ = env;
51 }
52}
53
54Daemon::~Daemon() {
55 if (pid_file_ && am_file_author_) {
56 pid_file_->deleteFile();
57 }
58}
59
60 void Daemon::cleanup() {
61}
62
63 void Daemon::shutdown() {
64}
65
66 void Daemon::configureLogger(const ConstElementPtr& log_config,
67 const ConfigPtr& storage) {
68
69 if (log_config) {
70 ConstElementPtr loggers = log_config->get("loggers");
71 if (loggers) {
72 LogConfigParser parser(storage);
73 parser.parseConfiguration(loggers, verbose_);
74 }
75 }
76}
77
78void
79Daemon::setVerbose(bool verbose) {
80 verbose_ = verbose;
81}
82
83bool
84Daemon::getVerbose() {
85 return (verbose_);
86}
87
88 void Daemon::loggerInit(const char* name, bool verbose) {
89
90 setenv("KEA_LOGGER_DESTINATION", "stdout", 0);
91
92 // Initialize logger system
93 isc::log::initLogger(name, isc::log::DEBUG, isc::log::MAX_DEBUG_LEVEL, 0);
94
95 // Apply default configuration (log INFO or DEBUG to stdout)
96 isc::log::setDefaultLoggingOutput(verbose);
97}
98
99std::string Daemon::getVersion(bool /*extended*/) {
100 isc_throw(isc::NotImplemented, "Daemon::getVersion() called");
101}
102
103std::string
104Daemon::getConfigFile() const {
105 return (config_file_);
106}
107
108void
109Daemon::setConfigFile(const std::string& config_file) {
110 config_file_ = config_file;
111}
112
113void
114Daemon::checkConfigFile() const {
115 if (config_file_.empty()) {
116 isc_throw(isc::BadValue, "config file name is not set");
117 }
118
119 // Create Path instance from the config_file_ pathname, and
120 // check the file name component.
121 Path file(config_file_);
122 if (file.stem().empty()) {
123 isc_throw(isc::BadValue, "config file:" << config_file_
124 << " is missing file name");
125 }
126}
127
128void
129Daemon::checkWriteConfigFile(std::string& file) {
130 Path path(file);
131 // from checkConfigFile().
132 if (path.stem().empty()) {
133 isc_throw(isc::BadValue, "config file:" << file
134 << " is missing file name");
135 }
136 Path current(config_file_);
137 if (current.parentDirectory() == path.parentDirectory()) {
138 // Same parent directories!
139 return;
140 }
141 if (path.parentDirectory().empty()) {
142 // Note the current parent directory can't be empty here.
143 file = current.parentDirectory() + file;
144 return;
145 }
146 isc_throw(isc::BadValue, "file " << file << " must be in the same "
147 << "directory as the config file (" << config_file_ << ")");
148}
149
150std::string
151Daemon::getProcName() {
152 return (proc_name_);
153}
154
155void
156Daemon::setProcName(const std::string& proc_name) {
157 proc_name_ = proc_name;
158}
159
160std::string
161Daemon::getPIDFileDir() const {
162 return(pid_file_dir_);
163}
164
165void
166Daemon::setPIDFileDir(const std::string& pid_file_dir) {
167 pid_file_dir_ = pid_file_dir;
168}
169
170std::string
171Daemon::getPIDFileName() const {
172 if (pid_file_) {
173 return (pid_file_->getFilename());
174 }
175
176 return ("");
177}
178
179void
180Daemon::setPIDFileName(const std::string& pid_file_name) {
181 if (pid_file_) {
182 isc_throw(isc::InvalidOperation, "Daemon::setConfigFile"
183 " file name already set to:" << pid_file_->getFilename());
184 }
185
186 if (pid_file_name.empty()) {
187 isc_throw(isc::BadValue, "Daemon::setPIDFileName"
188 " file name may not be empty");
189 }
190
191 pid_file_.reset(new util::PIDFile(pid_file_name));
192}
193
194std::string
195Daemon::makePIDFileName() const {
196 if (config_file_.empty()) {
197 isc_throw(isc::InvalidOperation,
198 "Daemon::makePIDFileName config file name is not set");
199 }
200
201 // Create Path instance from the config_file_ pathname, so we can
202 // extract the fname component.
203 Path file(config_file_);
204 if (file.stem().empty()) {
205 isc_throw(isc::BadValue, "Daemon::makePIDFileName config file:"
206 << config_file_ << " is missing file name");
207 }
208
209 if (proc_name_.empty()) {
210 isc_throw(isc::InvalidOperation,
211 "Daemon::makePIDFileName process name is not set");
212 }
213
214 // Make the pathname for the PID file from the runtime directory,
215 // configuration name and process name.
216 std::ostringstream stream;
217 stream << pid_file_dir_ << "/" << file.stem()
218 << "." << proc_name_ << ".pid";
219
220 return(stream.str());
221};
222
223void
224Daemon::createPIDFile(int pid) {
225 // If pid_file_ hasn't been instantiated explicitly, then do so
226 // using the default name.
227 if (!pid_file_) {
228 setPIDFileName(makePIDFileName());
229 }
230
231 // If we find a pre-existing file containing a live PID we bail.
232 int chk_pid = pid_file_->check();
233 if (chk_pid > 0) {
234 isc_throw(DaemonPIDExists, "Daemon::createPIDFile: PID: " << chk_pid
235 << " exists, PID file: " << getPIDFileName());
236 }
237
238 if (pid == 0) {
239 // Write the PID of the current process
240 pid_file_->write();
241 } else {
242 // Write the PID we were given
243 pid_file_->write(pid);
244 }
245
246 am_file_author_ = true;
247}
248
249size_t
250Daemon::writeConfigFile(const std::string& config_file,
251 ConstElementPtr cfg) const {
252 if (!cfg) {
253 isc_throw(Unexpected, "Can't write configuration: conversion to JSON failed");
254 }
255
256 std::ofstream out(config_file, std::ios::trunc);
257 if (!out.good()) {
258 isc_throw(Unexpected, "Unable to open file " + config_file + " for writing");
259 }
260
261 // Write the actual content using pretty printing.
262 prettyPrint(cfg, out);
263
264 size_t bytes = static_cast<size_t>(out.tellp());
265
266 out.close();
267
268 return (bytes);
269}
270
271std::list<std::list<std::string>>
272Daemon::jsonPathsToRedact() const {
273 static std::list<std::list<std::string>> const list;
274 return list;
275}
276
277 isc::data::ConstElementPtr
278Daemon::redactConfig(isc::data::ConstElementPtr const& config) {
279 isc::data::ConstElementPtr result(config);
280 for (std::list<std::string>& json_path : jsonPathsToRedact()) {
281 result = isc::process::redactConfig(result, json_path);
282 }
283 return result;
284}
285
286} // namespace process
287} // namespace isc
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition exceptions/exceptions.h:132
isc::InvalidOperation
A generic exception that is thrown if a function is called in a prohibited way.
Definition exceptions/exceptions.h:143
isc::NotImplemented
A generic exception that is thrown when a function is not implemented.
Definition exceptions/exceptions.h:166
isc::Unexpected
A generic exception that is thrown when an unexpected error condition occurs.
Definition exceptions/exceptions.h:153
isc::process::DaemonPIDExists
Exception thrown when the PID file points to a live PID.
Definition daemon.h:25
isc::process::Daemon::getConfigFile
std::string getConfigFile() const
Returns config file name.
Definition daemon.cc:104
isc::process::Daemon::writeConfigFile
virtual size_t writeConfigFile(const std::string &config_file, isc::data::ConstElementPtr cfg=isc::data::ConstElementPtr()) const
Writes current configuration to specified file.
Definition daemon.cc:250
isc::process::Daemon::getVersion
static std::string getVersion(bool extended)
returns Kea version on stdout and exits.
Definition daemon.cc:99
isc::process::Daemon::setVerbose
static void setVerbose(const bool verbose)
Sets or clears verbose mode.
Definition daemon.cc:79
isc::process::Daemon::getPIDFileName
std::string getPIDFileName() const
Returns the current PID file name.
Definition daemon.cc:171
isc::process::Daemon::jsonPathsToRedact
virtual std::list< std::list< std::string > > jsonPathsToRedact() const
Return a list of all paths that contain passwords or secrets.
Definition daemon.cc:272
isc::process::Daemon::Daemon
Daemon()
Default constructor.
Definition daemon.cc:41
isc::process::Daemon::shutdown
virtual void shutdown()
Initiates shutdown procedure for the whole server.
Definition daemon.cc:63
isc::process::Daemon::getPIDFileDir
std::string getPIDFileDir() const
Returns the directory used when forming default PID file name.
Definition daemon.cc:161
isc::process::Daemon::~Daemon
virtual ~Daemon()
Destructor.
Definition daemon.cc:54
isc::process::Daemon::signal_set_
isc::asiolink::IOSignalSetPtr signal_set_
A pointer to the object installing custom signal handlers.
Definition daemon.h:266
isc::process::Daemon::configureLogger
static void configureLogger(const isc::data::ConstElementPtr &log_config, const isc::process::ConfigPtr &storage)
Configures logger.
Definition daemon.cc:66
isc::process::Daemon::getVerbose
static bool getVerbose()
Returns if running in verbose mode.
Definition daemon.cc:84
isc::process::Daemon::loggerInit
static void loggerInit(const char *log_name, bool verbose)
Initializes logger.
Definition daemon.cc:88
isc::process::Daemon::checkWriteConfigFile
void checkWriteConfigFile(std::string &file)
Checks the to-be-written configuration file name.
Definition daemon.cc:129
isc::process::Daemon::getProcName
static std::string getProcName()
returns the process name This value is used as when forming the default PID file name
Definition daemon.cc:151
isc::process::Daemon::cleanup
virtual void cleanup()
Performs final deconfiguration.
Definition daemon.cc:60
isc::process::Daemon::redactConfig
isc::data::ConstElementPtr redactConfig(isc::data::ConstElementPtr const &config)
Redact a configuration.
Definition daemon.cc:278
isc::process::Daemon::checkConfigFile
void checkConfigFile() const
Checks the configuration file name.
Definition daemon.cc:114
isc::process::Daemon::setPIDFileName
void setPIDFileName(const std::string &pid_file_name)
Sets PID file name.
Definition daemon.cc:180
isc::process::Daemon::setProcName
static void setProcName(const std::string &proc_name)
Sets the process name.
Definition daemon.cc:156
isc::process::Daemon::createPIDFile
void createPIDFile(int pid=0)
Creates the PID file.
Definition daemon.cc:224
isc::process::Daemon::setPIDFileDir
void setPIDFileDir(const std::string &pid_file_dir)
Sets the PID file directory.
Definition daemon.cc:166
isc::process::Daemon::makePIDFileName
std::string makePIDFileName() const
Manufacture the pid file name.
Definition daemon.cc:195
isc::process::Daemon::setConfigFile
void setConfigFile(const std::string &config_file)
Sets the configuration file name.
Definition daemon.cc:109
isc::process::LogConfigParser
Configures log4cplus by translating Kea configuration structures.
Definition log_parser.h:43
isc::process::LogConfigParser::parseConfiguration
void parseConfiguration(const isc::data::ConstElementPtr &log_config, bool verbose=false)
Parses specified configuration.
Definition log_parser.cc:38
isc::util::PIDFile
Class to help with processing PID files.
Definition pid_file.h:40
config_base.h
daemon.h
data.h
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
filesystem.h
log_parser.h
logger_name.h
logger_support.h
Logging initialization functions.
isc::config
Definition command_interpreter.cc:23
isc::data
Definition base_stamped_element.cc:12
isc::data::prettyPrint
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition data.cc:1547
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
isc::log::initLogger
void initLogger(const string &root, isc::log::Severity severity, int dbglevel, const char *file, bool buffer)
Run-time initialization.
Definition logger_support.cc:43
isc::log::MAX_DEBUG_LEVEL
const int MAX_DEBUG_LEVEL
Definition logger_level.h:36
isc::log::setDefaultLoggingOutput
void setDefaultLoggingOutput(bool verbose)
Reset root logger characteristics.
Definition logger_support.cc:52
isc::log::DEBUG
@ DEBUG
Definition logger_level.h:25
isc::process
Definition cb_ctl_base.h:22
isc::process::ConfigPtr
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition config_base.h:176
isc::process::redactConfig
ConstElementPtr redactConfig(ConstElementPtr const &element, list< string > const &json_path, string obscure)
Redact a configuration.
Definition redact_config.cc:92
isc::util::file
Definition filesystem.cc:28
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148
redact_config.h
isc::util::file::Path
Paths on a filesystem.
Definition filesystem.h:83
isc::util::file::Path::parentDirectory
std::string parentDirectory() const
Get the parent directory.
Definition filesystem.cc:159
isc::util::file::Path::stem
std::string stem() const
Get the base name of the file without the extension.
Definition filesystem.cc:164