Commit 7fc34c94 authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[5580] Added developor and admin doc

parent 96b0712f
......@@ -780,6 +780,7 @@ INPUT = ../src/bin/agent \
../src/bin/lfc \
../src/hooks/dhcp/user_chk \
../src/hooks/dhcp/lease_cmds \
../src/hooks/dhcp/stat_cmds \
../src/lib/asiodns \
../src/lib/asiolink \
../src/lib/cc \
......
......@@ -54,6 +54,7 @@
* - @subpage hooksmgMaintenanceGuide
* - @subpage libdhcp_user_chk
* - @subpage libdhcp_lease_cmds
* - @subpage libdhcp_stat_cmds
*
* @section dhcpMaintenanceGuide DHCP Maintenance Guide
* - @subpage dhcp4
......
......@@ -8,7 +8,7 @@ dist_html_DATA = $(HTMLDOCS) kea-guide.css kea-logo-100x70.png
DOCBOOK = kea-guide.xml intro.xml quickstart.xml install.xml admin.xml config.xml
DOCBOOK += keactrl.xml dhcp4-srv.xml dhcp6-srv.xml lease-expiration.xml logging.xml
DOCBOOK += ddns.xml hooks.xml libdhcp.xml lfc.xml stats.xml ctrl-channel.xml faq.xml
DOCBOOK += hooks-host-cache.xml hooks-radius.xml
DOCBOOK += hooks-host-cache.xml hooks-radius.xml hooks-stat-cmds.xml
DOCBOOK += classify.xml shell.xml agent.xml
EXTRA_DIST = $(DOCBOOK)
......
<section xml:id="hooks-stat-cmds">
<title>stat_cmds: Supplemental Statistics Commands</title>
<para>
This library provides additional statistics commands for
retrieving lease statistics from kea-dhcp servers. These commands
were added to address an issue with obtaining accurate lease
statistics in deployments running multiple Kea servers that use
shared lease back end. The in-memory statistics kept by individual
servers only track lease changes made by that server. Thus in a
deployment with multiple servers, these statistics are incomplete.
In Kea 1.4, the MySQL and PostgreSQL back ends were modified to track
lease allocation changes as they occur via database triggers. Additionally,
all four lease back ends were extended to support retrieving lease
statistics for all subnets, a single subnet, or a range of subnets.
Finally, this library was constructed to provide commands for retrieving
these statistics. Additional statistics commands may be added to this
library in future releases.
</para>
<para>
The commands currently provided by this library are:
<itemizedlist>
<listitem>
<para><command>stat-lease4-get</command> - fetches DHCPv4 lease statistics</para>
</listitem>
<listitem>
<para><command>stat-lease6-get</command> - fetches DHCPv6 lease statistics</para>
</listitem>
</itemizedlist>
</para>
<para>
The Stat commands library is part of the open source code and is
available to every Kea user.
</para>
<para>
All commands use JSON syntax and can be issued either using directly to
the servers via the control channel (see <xref linkend="ctrl-channel"/>)
or via Control Agent (see <xref linkend="kea-ctrl-agent"/>).
</para>
<para>
This library may be loaded by both kea-dhcp4 and kea-dhcp6 servers.
It is loaded in the same way as other other libraries and currently has
no parameters:
</para>
<para>
<screen>
"Dhcp6": { <userinput>
"hooks-libraries": [
{
"library": "/path/libdhcp_stat_cmds.so"
}
...
] </userinput>
}
</screen>
</para>
<para>
In a deployment with multiple kea-dhcp servers sharing a common lease
storage, it may be loaded by any or all of the servers. However, one
thing to keep in mind is that a server's response to a stat-lease{4/6}-get
command will only contain data for subnets known to that server. In
other words, if subnet does not appear in a server's configuration, it
will not retrieve statistics for it.
</para>
<section>
<title>stat-lease4-get, stat-lease6-get commands</title>
<para>
The <command>stat-lease4-get</command> and <command>stat-lease6-get</command>
commands fetch lease statistics for a range of known subnets. The
range of subnets is determined through the use of optional command
input parameters:
<itemizedlist>
<listitem>
<para><command>subnet-id</command> - ID of the subnet for which
lease statistics should be fetched. Use this to get statistics for
a single subnet. If the subnet does not exist the command result
code will be 2 (i.e. CONTROL_RESULT_EMPTY).
</para>
</listitem>
<listitem>
<para><command>subnet-range</command> - A pair of subnet IDs which
describe an inclusive range of subnets for which statistics should
be retrieved. Note that fuzzy values are supported thus allowing
for a query for statistics using approximate ID values. If the
range does not include any known subnets, the command result code
will be 2 (i.e. CONTROL_RESULT_EMPTY).
<itemizedlist>
<listitem>
<command>first-subnet-id</command> - ID of the first
subnet in the range.
</listitem>
<listitem>
<command>last-subnet-id</command> - ID of the first
subnet in the range.
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
The use of subnet-id and subnet-range are mutually exclusive.
If no parameters are given, the result will contain data for all
known subnets. Note that in configurations with large numbers of
subnets, this can be result in a large response.
<para>
The following command would fetch lease statistcis for all known subnets from kea-dhcp4 server:
<screen>
{
"command": "stat-lease4-get",
"arguments": {
}
}
</screen>
</para>
<para>
The following command would fetch lease statistcis for subnet ID 10 from kea-dhcp6 server:
<screen>
{
"command": "stat-lease6-get",
"arguments": {
"subnet-id" : 10
}
}
</screen>
</para>
<para>
The following command would fetch lease statistcis for all subnets from subnet ID 10 through 50 from kea-dhcp4 server:
<screen>
{
"command": "stat-lease4-get",
"arguments": {
"subnet-range" {
"first-subnet-id": 10,
"last-subnet-id": 50,
}
}
}
</screen>
</para>
<para>
The response to the either command will contain three elements:
<itemizedlist>
<listitem>
<para><command>result</command> - numeric value indicating the outcome of the
command where:
<itemizedlist>
<listitem><command>0</command> - command was successful</listitem>
<listitem><command>1</command> - an error occurred, an explanation will
be the "text" element</listitem>
<listitem><command>2</command> - indicates the fetch found no matching data</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><command>text</command> - an explanation of the command outcome. When the command
succeeds it will contain the command name along with the number of rows returned.</para>
</listitem>
<listitem>
<para><command>arguments</command></para> - a map containing the data returned by the
command as the element "result-set", which patterned after SQL statement responses:
<itemizedlist>
<listitem><command>columns</command> - a list of text column labels.
The columns returned for DHCPv4 are:
<itemizedlist>
<listitem><command>subnet-id</command> - ID of the subnet</listitem>
<listitem><command>total-addresses</command> - total number of addresses
available for DHCPv4 management. In other words, this is the sum of all
addresses in all configured pools. This statistic changes only during
configuration changes. Note it does not take into account any addresses that
may be reserved due to host reservation.
</listitem>
<listitem><command>assigned-addresses</command> - number of assigned
addresses in a given subnet. It increases every time a new lease is
allocated (as a result of receiving a DHCPREQUEST message) and is decreased
every time a lease is released (a DHCPRELEASE message is received) or expires.
</listitem>
<listitem><command>declined-addresses</command> - number of IPv4 addresses
that are currently declined in a given subnet, so is a count of the number
of leases currently unavailable. Once a lease is recovered, this statistic
will be decreased. Ideally, this statistic should be zero. If this statistic
is non-zero (or worse increasing), a network administrator should investigate
if there is a misbehaving device in his network.
</listitem>
</itemizedlist>
The columns returned for DHCPv6 are:
<itemizedlist>
<listitem><command>subnet-id</command> - ID of the subnet</listitem>
<listitem><command>total-nas</command> - number of NA addresses available
for DHCPv6 management for a given subnet. In other words, this is the
sum of all addresses in all configured pools. This statistic changes
only during configuration changes. Note that it does not take into account
any addresses that may be reserved due to host reservation.
</listitem>
<listitem><command>assigned-nas</command> - number of NA addresses in a
the subnet that are assigned. This statistic increases every time a new
lease is allocated (as a result of receiving a REQUEST message) and is
decreased every time a lease is released (a RELEASE message is received)
or expires.
</listitem>
<listitem><command>declined-nas</command> - number of IPv6 addresses that
are currently declined and so counts the number of leases currently
unavailable. Once a lease is recovered, this statistic will be decreased.
Ideally, this statistic should be zero. If this statistic is non-zero
(or worse, increasing), the network administrator should investigate if
there is a misbehaving device in the network.
</listitem>
<listitem><command>total-pds</command> - total number of PD prefixes available
of DHCPv6 management for a given subnet. In other words, this is the sum
of all prefixes in all configured pools. This statistic changes only during
configuration changes. Note it does not take into account any prefixes that
may be reserved due to host reservation.
</listitem>
<listitem><command>assigned-pds</command> - number of PD prefixes in a given
subnet that are assigned. This statistic increases every time a new lease is
allocated (as a result of receiving a REQUEST message) and is decreased every
time a lease is released (a RELEASE message is received) or expires.
</listitem>
</itemizedlist>
</listitem>
<listitem><command>rows</command> - a list of rows, one per subnet ID. Each row
contains a data value for corresponding to and in the same order as each column
listed in "columns" for a given subnet.
</listitem>
<listitem><command>timestamp</command> - textual date and time the data was fetched,
expressed as GMT</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<para>
The response to a DHCPv4 command might look as follows:
<screen>
{
"result": 0,
"text": "stat-lease4-get: 2 rows found",
"arguments": {
"result-set": {
"columns": [ "subnet-id", "total-addresses", "assigned-addresses", "declined-addresses" ]
"rows": [
[ 10, 256, 111, 0 ], [ 20, 4098, 2034, 4 ]
],
"timestamp": "2018-05-04 15:03:37.000000"
}
}
}
</screen>
</para>
<para>
The response to a DHCPv6 command might look as follows:
<screen>
{
"result": 0,
"text": "stat-lease6-get: 2 rows found",
"arguments": {
"result-set": {
"columns": [ "subnet-id", "total-nas", "assigned-nas", "declined-nas", "total-pds", "assigned-pds" ]
"rows": [
[ 10, 256, 111, 0 ],
[ 20, 4098, 2034, 4 ]
],
"timestamp": "2018-05-04 15:03:37.000000"
}
}
}
</screen>
</para>
</para>
</para>
</section>
</section>
......@@ -2838,6 +2838,8 @@ both the command and the response.
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="hooks-host-cache.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="hooks-stat-cmds.xml"/>
</section>
......
......@@ -43,11 +43,11 @@ public:
isc::Exception(file, line, what) { };
};
///@brief Implements command handlinge for stat-lease<x>-get commands
///@brief Implements command handlinge for stat-leaseX-get commands
class LeaseStatCmdsImpl : private CmdsImpl {
public:
/// @brief Wrapper class stat-lease<x>-get command parameters.
/// @brief Wrapper class stat-leaseX-get command parameters.
class Parameters {
public:
/// @brief Specifies the subnet-id for a single subnet, or
......@@ -92,7 +92,7 @@ public:
int
statLease6GetHandler(CalloutHandle& handle);
/// @Brief Parses command arguments into stat-lease<x>-get parameters
/// @brief Parses command arguments into stat-leaseX-get parameters
/// @param cmd_args Element form of command arguments to parse
/// @throw BadValue if any of the following rules are broken:
///
......@@ -165,17 +165,17 @@ public:
/// @brief Adds a row of Lease4 stat values to a list of value rows
///
/// @param[out] value_rows list of rows to which to add
/// @param[out] subent_id id of the subnet of the new row. This value is
/// @param[out] subnet_id id of the subnet of the new row. This value is
/// also used for fetching the total addresses in the subnet
/// @param assigned number of assigned addresses in the subnet
/// @param assigned number of declined addresses in the subnet
/// @param declined number of declined addresses in the subnet
void addValueRow4(ElementPtr value_rows, const SubnetID &subnet_id,
int64_t assigned, int64_t declined);
/// @brief Adds a row of Lease6 stat values to a list of value rows
///
/// @param[out] value_rows list of rows to which to add
/// @param[out] subent_id id of the subnet of the new row. This value is
/// @param[out] subnet_id id of the subnet of the new row. This value is
/// also used for fetching the total NAs and PDs in the subnet
/// @param assigned number of assigned NAs in the subnet
/// @param declined number of declined NAs in the subnet
......
......@@ -21,78 +21,179 @@ particular its section about hooks.
@section stat_cmds Stat Commands Overview
Stat Commands (or stat_cmds) is a Hook library that can be loaded by Kea to
extend it with additional mechanisms.
The primary purpose of this library is to provide commands that manage leases.
As such, the whole library is structured around command handlers. When the
library is loaded it registers a number of handlers for new commands. When a
command is issued (be it directly via control channel or indirectly via REST
Stat Commands (or stat_cmds) is a Hook library that can be loaded by
either kea-dhcp4 and kea-dhcp6 servers to extend them with additional
statistics mechanisms.
The initial purpose of this library is provide supplemental commands for
obtaining accurate lease statistics in deployments that share lease storage
between multiple Kea DHCP servers. It is likely that additional statistics
related commands will be added to this library in future releases as use
cases for them arise.
The library is structured around command handlers. When the library is
loaded it registers handlers for new commands. When a command
is issued (be it directly via control channel or indirectly via REST
interface from control agent), the code receives a JSON command with
parameters. Those are parsed and then actual operation commences. This
operation always interacts with an instantiation of isc::dhcp::StatMgr
instance, which is Kea's way of storing leases. At the time of writing this text
(Aug. 2017), Kea supports four types of lease managers: memfile, MySQL,
PostgreSQL or Cassandra. The lease commands provided by this library
provide a unified interface for those backends.
As with other hooks, this one also keeps its code in a separate namespace which
parameters. The command is routed the appropriate handler, its parameters
are parsed and command executed accordingly. Lastly, a response is
constructed and shipped back to the client.
This lease statistics commands interact with both the isc::dhcp::StatsMgr
and the isc::dhcp::LeaseMgr instance. At the time of writing this text
(May, 2018), Kea supports four types of lease managers: memfile, MySQL,
PostgreSQL or Cassandra. The lease statistics commands provided by this
library provide a unified interface supported by all four of these backends.
As with other hooks, this one keeps its code in a separate namespace which
corresponds to the file name of the library: isc::stat_cmds.
For background on the design and design choices please refer to: <a
href="http://kea.isc.org/wiki/SharedLeaseStorageStats">Shared Lease Stats Design</a>
@section stat_cmdsCode Stat Commands Code Overview
The library operation starts with Kea calling the load() function (file
load_unload.cc). It instantiates an isc::stat_cmds::StatCmds object.
The constructor of that object registers all of the lease commands. For a list,
see @ref isc::stat_cmds::StatCmds class documentation. This class uses Pimpl
design pattern, thus the real implementation is hidden in isc::stat_cmds::StatCmdsImpl.
Almost every command has its own handler, except few that share the same handler
between v4 and v6 due to its similarity. For example
isc::stat_cmds::StatCmdsImpl::leaseAddHandler handles lease4-add and lease6-add
commands. Although the details differ between handlers, the general approach
is the same. First, it starts with parameters sanitization and then some
interaction with isc::dhcp::StatMgr is conducted.
For commands that do something with a specific lease (lease4-get, lease6-get,
lease4-del, lease6-del), there is a @ref isc::stat_cmds::StatCmdsImpl::Parameters
class that contains parsed elements.
For details see documentation and code of the following handlers:
- @ref isc::stat_cmds::StatCmdsImpl::leaseAddHandler (lease4-add, lease6-add)
- @ref isc::stat_cmds::StatCmdsImpl::leaseGetHandler (lease4-get, lease6-get)
- @ref isc::stat_cmds::StatCmdsImpl::lease4DelHandler (lease4-del)
- @ref isc::stat_cmds::StatCmdsImpl::lease6DelHandler (lease6-del)
- @ref isc::stat_cmds::StatCmdsImpl::lease4UpdateHandler (lease4-update)
- @ref isc::stat_cmds::StatCmdsImpl::lease6UpdateHandler (lease6-update)
- @ref isc::stat_cmds::StatCmdsImpl::lease4WipeHandler (lease4-wipe)
- @ref isc::stat_cmds::StatCmdsImpl::lease6WipeHandler (lease6-wipe)
@section stat_cmdsDesigns Stat Commands Design choices
The lease manipulation commands were implemented to provide a convenient interface
for sysadmins. The primary goal was to offer a way to interact with the live
lease database in unified way, regardless of the actual backend being used.
For some backends (MySQL, PostgreSQL and Cassandra) it is possible to interact
directly with the backend while Kea is running and possibly change its content. This
ability is both powerful and dangerous. In particular, only rudimentary
checks are enforced by the DB schemas (e.g. not possible to have two leases
for the same address). However, it does not prevent sysadmins from making
more obscure errors, like inserting leases for subnets that do not exist
or configuring an address that is topologically outside of the subnet to which
it should belong. These kind of checks are only possible by DHCP-aware
code, which this library provides.
Some of the queries may require a seemingly odd set of parameters. For example,
lease6-get query requires at least DUID, subnet-id and IAID to retrieve a lease
by DUID. The need for a sysadmin to know and specify an IAID is troublesome.
However, the guiding principle here was to use whatever queries were already
exposed by the lease manager and not introduce new indexes, unless absolutely
necessary. This ensures that there is no performance degradation when the
library is loaded. The only exception for that was lease4-wipe and lease6-wipe
commands that remove all leases from specific subnet. As there were no
queries that could retrieve or otherwise enumerate leases for a specific subnet,
a new query type and a new index had to be added.
Library operation starts with Kea calling the load() function (file
stat_cmds_callouts.cc). This function registers the command callout
functions for each of the libraries commands. For a list,
see @ref isc::stat_cmds::StatCmds class documentation. This class uses
the Pimpl design pattern, and thus the actual implementation is hidden
in @ref isc::stat_cmds::LeaseStatCmdsImpl.
Unlike similar libraries, the Pimpl class is differentiated from the
the StatCmds class by the prefix "Lease" and it is instantiated in the outer
handler (e.g. @ref isc::stat_cmds::StatCmds::statLease4GetHandler) rather than
the StatCmds constructor. This was done in the event that commands, unrelated
to lease statistics, are added to this library and that would be better served
by Pimpl derviations specific to them.
@subsection stat_cmdsLeaseStatCode Lease Stat Commands Code Overview
There are two shared lease statistic commands, "stat-lease4-get" and "stat-lease6-get".
Both of these support the same input parameters and have their own command handlers:
- @ref isc::stat_cmds::LeaseStatCmdsImpl::statLease4GetHandler (stat-lease4-get)
- @ref isc::stat_cmds::LeaseStatCmdsImpl::statLease6GetHandler (stat-lease6-get)
Briefly, the commands are intended to fetch the lease statistics per subnet
for the range of subnets described by the input parameters. JSON text structure
of the commands is as follows:
DHCPv4 command:
@code
{
"command": "stat-lease4-get",
"arguments": {
"subnet-id": x
"subnet-range": {
"first-subnet-id": x,
"last-subnet-id": y
}
}
}
where subnet-id and subnet-range are optional and mutually exclusive
@endcode
DHCPv6 command:
@code
{
"command": "stat-lease6-get",
"arguments": {
"subnet-id": x
"subnet-range": {
"first-subnet-id": x,
"last-subnet-id": y
}
}
}
where subnet-id and subnet-range are optional and mutually exclusive
@endcode
Command handling
for both commands is symetrical consists of the following steps:
-# The input parameters (if any) are parsed. Invalid values or
combinations if detected result in generating a CONTROL_RESULT_ERROR
response to the client. (See @ref isc::stat_cmds::LeaseStatCmdsImpl::getParameters
and @ref isc::stat_cmds::LeaseStatCmdsImpl::Parameters)
-# The parameters are used to identify the range of configured subnets
to include in the response. This is done by querying subnet configuration
housed by @ref isc::dhcp::CfgMgr. If the range contains no known subnets then a
CONTROL_RESULT_EMPTY response is sent back to the client.
-# The initial result-set response is constructed. Essentially this is
an @ref isc::data::Element tree, which converted to JSON would appear as follows:
@code
"result-set": {
"timestamp": "2018-03-22 09:43:30.815371",
"columns": ["<label-1>, <label-2>, ... ],
"rows": []
}
@endcode
-# The acutal lease statistics are then retrieved from @ref isc::dhcp::LeaseMgr instance
by invoking of the three functions based on the input parameters:
DHCPv4 functions:
- @ref isc::dhcp::LeaseMgr::startLeaseStatsQuery4
- @ref isc::dhcp::LeaseMgr::startSubnetLeaseStatsQuery4
- @ref isc::dhcp::LeaseMgr::startSubnetRangeLeaseStatsQuery4
DHCPv6 functions:
- @ref isc::dhcp::LeaseMgr::startLeaseStatsQuery6
- @ref isc::dhcp::LeaseMgr::startSubnetLeaseStatsQuery6
- @ref isc::dhcp::LeaseMgr::startSubnetRangeLeaseStatsQuery6
-# Iterate over the range of qualifying subnets adding a row of statistics for
each subnet to the result-set. Each row combines the subnet total(s) from isc::dhcp::StatsMgr
with the type and state counts from the lease query results. For subnets with no query
data (i.e. no leases), their rows have non-zero values for totals only.
-# Finally, a CONTROL_RESULT_SUCCESS repsonse is generated containing the populated result-set.
A DHCPv4 response might look like this:
@code
{
"result-set\": {
"columns\": [
"subnet-id", "total-addreses",
"assigned-addreses", "declined-addreses"
],
"rows\": [
[ 30, 256, 100, 2 ],
[ 40, 16, 0, 0 ],
[ 50, 256, 35, 0 ],
],
timestamp\": \"2018-05-04 15:03:37.000000\" }
}
@endcode
and DHCPv6 response might look like this:
@code
{
"result-set": {
"columns": [
"subnet-id", "total-nas", "assigned-nas",
"declined-nas", "total-pds", "assigned-pds"
],
"rows": [
[ 30, 16, 6, 0, 65536, 400 ],
[ 40, 16777216, 989837, 0, 0, 0 ]
],
"timestamp": "2018-05-04 15:03:37.000000" }
}
@endcode
*/
......@@ -40,9 +40,8 @@ public:
/// {
/// "command": "stat-lease4-get",
/// "arguments": {
/// "from_storage: true/false, // optional - maybe?
/// "subnet-id": x, // optional
/// "subnet-id-range": { // optional
/// "subnet-id": x // optional
/// "subnet-range": { // optional
/// "first-subnet-id": x, // id >= x
/// "last-subnet-id": y // id <= x
/// }
......@@ -84,9 +83,8 @@ public:
/// {
/// "command": "stat-lease6-get",
/// "arguments": {
/// "from_storage: true/false,
/// "subnet-id": x, // optional
/// "subnet-id-range": { // optional
/// "subnet-id": x // optional
/// "subnet-range": { // optional
/// "first-subnet-id": x, // id >= x
/// "last-subnet-id": y // id <= x
/// }
......
......@@ -606,7 +606,7 @@ public: