diff options
Diffstat (limited to 'src/lib/process/libprocess.dox')
-rw-r--r-- | src/lib/process/libprocess.dox | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/lib/process/libprocess.dox b/src/lib/process/libprocess.dox new file mode 100644 index 0000000..2ea2e5c --- /dev/null +++ b/src/lib/process/libprocess.dox @@ -0,0 +1,195 @@ +// Copyright (C) 2016-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/** + @page libprocess libkea-process - Controllable Process Layer (CPL) + +@section cpl Controllable Process Layer (CPL) +During the design and development of D2 (Kea's DHCP-DDNS process), an abstract +layer for process control, called the Controllable Process Layer or CPL, was +created. Kea's DHCP servers were initially developed prior to D2 and thus +before CPL existed. + +Out of short term convenience and the fact that only D2 was using it, the CPL +was initially developed as part of D2 in src/bin/d2. In order to use CPL for +new Kea processes, it has since been moved into its own library, libkea-process. +The following sections describe the architecture of CPL and how it can be used to implement new daemons in Kea. + +The CPL provides the essentials for a controllable, configurable, +asynchronous process. They are the result of an effort to distill the +common facets of process control currently duplicated in Kea's +DHCP servers into a reusable construct. The classes which form this abstract +base are shown in the following class diagram: + +@image html abstract_app_classes.svg "Controllable Process Layer Classes" + +- isc::process::DControllerBase - provides all of the services necessary to manage +an application process class derived from isc::d2::DProcess. These services include: + - Command line argument handling + - Process instantiation and initialization + - Support for stand-alone execution + - Process event loop invocation and shutdown + + It creates and manages an instance of isc::process::DProcessBase. The CPL is + designed for asynchronous event processing applications. It is constructed + to use ASIO library for IO processing. @c DControllerBase owns an + isc::asiolink::IOService instance and it passes this into the @c + DProcessBase constructor. It is this @c IOService that is used to drive the + process's event loop. The controller is designed to provide any interfaces + between the process it controls and the outside world. + + @c DControllerBase provides configuration for its process via a JSON file + specified as a mandatory command line argument. The file structure is + expected be as follows: + + { "<module-name>": {<module-config>} } + + where: + - module-name : is a label which uniquely identifies the + configuration data for the (i.e. the controlled process.) + It is the value returned by @ref + isc::process::DControllerBase::getAppName() + + - module-config: a set of zero or more JSON elements which comprise + application's configuration values. Element syntax is governed + by those elements supported in isc::cc. + + The file may contain an arbitrary number of other modules. + + @todo Eventually, some sort of secure socket interface which supports remote + control operations such as configuration changes or status reporting will + likely be implemented. + +- isc::process::DProcessBase - defines an asynchronous-event processor (i.e. +application) which provides a uniform interface to: + - Instantiate and initialize a process instance + - "Run" the application by starting its event loop + - Inject events to control the process +It owns an instance of @c DCfgMgrBase. + +- isc::process::DCfgMgrBase - provides the mechanisms for managing an application's +configuration. This includes services for parsing sets of configuration +values, storing the parsed information in its converted form, and retrieving +the information on demand. It owns an instance of @c DCfgContextBase, which +provides a "global" context for information that is accessible before, during, +and after parsing. + +- isc::process::DCfgContextBase - implements a container for configuration +information or "context". It provides a single enclosure for the storage of +configuration parameters or any other information that needs to accessible +within a given context. + +The following sequence diagram shows how a configuration from file moves +through the CPL layer: + +@image html config_from_file_sequence.svg "CPL Configuration From File Sequence" + +The CPL classes will likely move into a common library. + +@section cplSignals CPL Signal Handling + +CPL supports interaction with the outside world via OS signals. The default +implementation supports the following signal driven behavior: +- SIGHUP receipt of this signal will cause a reloading of the configuration +file. +- SIGINT/SIGTERM receipt of either of these signals will initiate an +orderly shutdown. + +CPL applications wait for for process asynchronous IO events through +isc::asiolink::IOService::run() or its variants. These calls are not +interrupted upon signal receipt as is the select() function and while +boost::asio provides a signal mechanism it requires linking in additional +libraries. Therefore, CPL provides its own signal handling mechanism to +propagate an OS signal such as SIGHUP to an IOService as a ready event with a +callback. + +isc::process::DControllerBase uses two mechanisms to carry out signal handling. It +uses isc::util::SignalSet to catch OS signals, and isc::process::IOSignalQueue to +propagate them to its isc::asiolink::IOService as instances of +isc::process::IOSignal. + +This CPL signaling class hierarchy is illustrated in the following diagram: + +@image html cpl_signal_classes.svg "CPL Signal Classes" + +The mechanics of isc::process::IOSignal are straight forward. Upon construction it +is given the target isc::asiolink::IOService, the value of the OS signal to +send (e.g. SIGINT, SIGHUP...), and an isc::process::IOSignalHandler. This handler +should contain the logic the caller would normally execute in its OS signal +handler. Each isc::process::IOSignal instance has a unique identifier called its +sequence_id. + +Internally, IOSignal creates a 1 ms, one-shot timer, on the given +IOService. When the timer expires its event handler invokes the caller's +IOSignalHandler passing it the sequence_id of the IOSignal. + +Sending IOSignals is done through an isc::process::IOSignalQueue. This class is +used to create the signals, house them until they are delivered, and dequeue +them so they can be been handled. To generate an IOSignal when an OS signal +arrives, the process's OS signal handler need only call +isc::process::IOSignalQueue::pushSignal() with the appropriate values. + +To dequeue the IOSignal inside the caller's IOSignalHandler, one simply +invokes isc::process::IOSignalQueue::popSignal() passing it the sequence_id +parameter passed to the handler. This method returns a pointer to +instigating IOSignal from which the value of OS signal (i.e. SIGINT, +SIGUSR1...) can be obtained. Note that calling popSignal() removes the +IOSignalPtr from the queue, which should reduce its reference count to +zero upon exiting the handler (unless a deliberate copy of it is made). + +A typical isc::process::IOSignalHandler might be structured as follows: +@code + + void processSignal(IOSignalId sequence_id) { + // Pop the signal instance off the queue. + IOSignalPtr signal = io_signal_queue_->popSignal(sequence_id); + + int os_signal_value = signal->getSignum(); + : + // logic based on the signal value + : + } + +@endcode + +IOSignal's handler invocation code will catch, log ,and then swallow any +exceptions thrown by an IOSignalHandler. This is done to protect the integrity +IOService context. + +The following sequence diagram depicts the initialization of signal handling +during startup and the subsequent receipt of a SIGHUP: + +@image html cpl_signal_sequence.svg "CPL Signal Handling Sequence" + +@section redact Redact Passwords + +There are two tools to remove sensitive data as passwords or secrets from logs: + - redactedAccessString for database access strings + - redactConfig for full configurations + +The jsonPathsToRedact method must be defined in derived classes following this +procedure: + - Get all possible JSON paths from the root of the configuration to leaves that + fulfill the role of map keys and which contain "password" or "secret". + - For each of these paths, remove the root node and the leaf node. + - Include all the paths in the method. Duplicate subpaths are expected in the + case of common subpaths to different leaves. + +There are two special syntaxes: + - "[]" suggests that the searched element is a list. This is required for all + lists and is for performance gain. + - "*" as a last element in a JSON path tells the redacter to look in all + elements that follow for elements that contain "password" and "secret". This is + when the particular configuration that is targeted by the "*" does not have a + well defined structure, such as is the case for "parameters" in the + "hooks-libraries" map in "Dhcp4" and "Dhcp6". + +@section cplMTConsiderations Multi-Threading Consideration for Controllable Process Layer + +By default this library is not thread safe and currently there is no known +exception. + +*/ |