Commit cc85938b authored by Shawn Routhier's avatar Shawn Routhier
Browse files

Merge branch 'trac3664' Add base LFC process code

This merge adds the basic code for handling lease file cleanup (LFC).
It provides the basic framework for the process as well as code to
do argument parsing.
parents da38f7ad 1aba1112
......@@ -1393,6 +1393,8 @@ AC_CONFIG_FILES([compatcheck/Makefile
src/bin/keactrl/keactrl.conf
src/bin/keactrl/tests/Makefile
src/bin/keactrl/tests/keactrl_tests.sh
src/bin/lfc/Makefile
src/bin/lfc/tests/Makefile
src/bin/perfdhcp/Makefile
src/bin/perfdhcp/tests/Makefile
src/bin/perfdhcp/tests/testdata/Makefile
......
......@@ -650,6 +650,7 @@ INPUT = ../src/bin/d2 \
../src/bin/dhcp6 \
../src/bin/perfdhcp \
../src/bin/sockcreator \
../src/bin/lfc \
../src/hooks/dhcp/user_chk \
../src/lib/asiolink \
../src/lib/cc \
......
# The following build order must be maintained.
SUBDIRS = dhcp4 dhcp6 d2 perfdhcp admin
SUBDIRS = dhcp4 dhcp6 d2 perfdhcp admin lfc
if CONFIG_BACKEND_JSON
SUBDIRS += keactrl
......
/kea-lfc
/kea-lfc.8
/lfc_messages.cc
/lfc_messages.h
/s-messages
\ No newline at end of file
SUBDIRS = . tests
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(KEA_CXXFLAGS)
if USE_CLANGPP
# Disable unused parameter warning caused by some Boost headers when compiling with clang
AM_CXXFLAGS += -Wno-unused-parameter
endif
if USE_STATIC_LINK
AM_LDFLAGS = -static
endif
CLEANFILES = lfc_messages.h lfc_messages.cc s-messages
man_MANS = kea-lfc.8
DISTCLEANFILES = $(man_MANS)
EXTRA_DIST = $(man_MANS) kea-lfc.xml
if GENERATE_DOCS
kea-lfc.8: kea-lfc.xml
@XSLTPROC@ --novalid --xinclude --nonet -o $@ \
http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl \
$(srcdir)/kea-lfc.xml
else
$(man_MANS):
@echo Man generation disabled. Creating dummy $@. Configure with --enable-generate-docs to enable it.
@echo Man generation disabled. Remove this file, configure with --enable-generate-docs, and rebuild Kea > $@
endif
lfc_messages.h lfc_messages.cc: s-messages
s-messages: lfc_messages.mes
$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/bin/lfc/lfc_messages.mes
touch $@
BUILT_SOURCES = lfc_messages.h lfc_messages.cc
# convenience archive
noinst_LTLIBRARIES = liblfc.la
liblfc_la_SOURCES =
liblfc_la_SOURCES += lfc_controller.h
liblfc_la_SOURCES += lfc_controller.cc
nodist_liblfc_la_SOURCES = lfc_messages.h lfc_messages.cc
EXTRA_DIST += lfc_messages.mes
sbin_PROGRAMS = kea-lfc
kea_lfc_SOURCES = main.cc
kea_lfc_LDADD = liblfc.la
kea_lfc_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
kea_lfc_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
kea_lfc_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
kea_lfc_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
kea_lfc_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
kea_lfc_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
kea_lfcdir = $(pkgdatadir)
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
[<!ENTITY mdash "&#8212;">]>
<!--
- Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
<refentry>
<refentryinfo>
<date>Feb 1, 2015</date>
</refentryinfo>
<refmeta>
<refentrytitle>kea-lfc</refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo>Kea</refmiscinfo>
</refmeta>
<refnamediv>
<refname>kea-lfc</refname>
<refpurpose>Lease File Cleanup process in Kea</refpurpose>
</refnamediv>
<docinfo>
<copyright>
<year>2015</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
<refsynopsisdiv>
<cmdsynopsis>
<command>kea-lfc</command>
<arg><option>-4|-6</option></arg>
<arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
<arg><option>-p <replaceable class="parameter">previous-file</replaceable></option></arg>
<arg><option>-i <replaceable class="parameter">copy-file</replaceable></option></arg>
<arg><option>-o <replaceable class="parameter">output-file</replaceable></option></arg>
<arg><option>-f <replaceable class="parameter">finish-file</replaceable></option></arg>
<arg><option>-v</option></arg>
<arg><option>-V</option></arg>
<arg><option>-d</option></arg>
<arg><option>-h</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>
The <command>kea-lfc</command> service process removes redundant
information for the files used to provide persistent storage for
the memfile data base backend. The service is written to run as
a stand alone process. While it can be started externally it
should be started by the Kea DHCP servers as desired and required.
</para>
</refsect1>
<refsect1>
<title>ARGUMENTS</title>
<para>The arguments are as follows:</para>
<variablelist>
<varlistentry>
<term><option>-d</option></term>
<listitem><para>
Verbose mode sets the logging level to debug. This is primarily
for development purposes in stand-alone mode.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<listitem><para>
version causes the version stamp to be printed.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-V</option></term>
<listitem><para>
Version causes a longer form of the version stamp to be printed.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option></term>
<listitem><para>
Help causes the usage string to be printed.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-4 | -6</option></term>
<listitem><para>
The protocol version of the lease files, must be one of 4 or 6.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-c</option></term>
<listitem><para>
Configuration file including the configuration for
<command>kea-lfc</command> process. It may also
contain configuration entries for other Kea services.
Currently <command>kea-lfc</command> gets all of its arguments from
the comamnd line, in the future it will be extended to get some arguments
from the config file.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-p</option></term>
<listitem><para>
Previous lease file - When <command>kea-lfc</command> starts this
is the result of any previous run of <command>kea-lfc</command>.
When <command>kea-lfc</command> finishes it is the result of this run.
If <command>kea-lfc</command> is interrupted before compelting
this file may not exist.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-i</option></term>
<listitem><para>
Input or copy of lease file - Before the DHCP server invokes
<command>kea-lfc</command> it will copy the current lease file
here and then call <command>kea-lfc</command> with this file.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-o</option></term>
<listitem><para>
Output lease file - The temporary file <command>kea-lfc</command>
should use to write the leases. Upon completion of writing this
this file it will be moved to the finish file (see below).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-f</option></term>
<listitem><para>
Finish or completion file - Another temporary file
<command>kea-lfc</command> uses for bookkeeping. When
<command>kea-lfc</command> completes writing the output
file it moves it to this file name. After
<command>kea-lfc</command> finishes deleting the other
files (previous and input) it moves this file to previous
lease file. By moving the files in this fashion the
<command>kea-lfc</command> and the DHCP server processes
can determine the correct file to use even if one of the
processes was interrupted before completing its task.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>HISTORY</title>
<para>
The <command>kea-lfc</command> process was first coded in January
2015 by the ISC Kea/DHCP team.
</para>
</refsect1>
</refentry><!--
- Local variables:
- mode: sgml
- End:
-->
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <lfc/lfc_controller.h>
#include <exceptions/exceptions.h>
#include <config.h>
#include <iostream>
#include <sstream>
#include <unistd.h>
using namespace std;
namespace isc {
namespace lfc {
/// @brief Defines the application name, it may be used to locate
/// configuration data and appears in log statements.
const char* LFCController::lfc_app_name_ = "DhcpLFC";
/// @brief Defines the executable name.
const char* LFCController::lfc_bin_name_ = "kea-lfc";
LFCController::LFCController()
: protocol_version_(0), verbose_(false), config_file_(""), previous_file_(""),
copy_file_(""), output_file_(""), finish_file_(""), pid_file_("") {
}
LFCController::~LFCController() {
}
void
LFCController::launch(int argc, char* argv[]) {
try {
parseArgs(argc, argv);
} catch (const InvalidUsage& ex) {
usage(ex.what());
throw; // rethrow it
}
}
void
LFCController::parseArgs(int argc, char* argv[]) {
int ch;
opterr = 0;
optind = 1;
while ((ch = getopt(argc, argv, ":46dvVp:i:o:c:f:")) != -1) {
switch (ch) {
case '4':
// Process DHCPv4 lease files.
protocol_version_ = 4;
break;
case '6':
// Process DHCPv6 lease files.
protocol_version_ = 6;
break;
case 'v':
// Print just Kea vesion and exit.
std::cout << getVersion(false) << std::endl;
exit(EXIT_SUCCESS);
case 'V':
// Print extended Kea vesion and exit.
std::cout << getVersion(true) << std::endl;
exit(EXIT_SUCCESS);
case 'd':
// Verbose output.
verbose_ = true;
break;
case 'p':
// Previous file name.
if (optarg == NULL) {
isc_throw(InvalidUsage, "Previous file name missing");
}
previous_file_ = optarg;
break;
case 'i':
// Copy file name.
if (optarg == NULL) {
isc_throw(InvalidUsage, "Copy file name missing");
}
copy_file_ = optarg;
break;
case 'o':
// Output file name.
if (optarg == NULL) {
isc_throw(InvalidUsage, "Output file name missing");
}
output_file_ = optarg;
break;
case 'f':
// Output file name.
if (optarg == NULL) {
isc_throw(InvalidUsage, "Finish file name missing");
}
finish_file_ = optarg;
break;
case 'c':
// Previous file name.
if (optarg == NULL) {
isc_throw(InvalidUsage, "Configuration file name missing");
}
config_file_ = optarg;
break;
case 'h':
usage("");
exit(EXIT_SUCCESS);
case '?':
// Unknown argument
isc_throw(InvalidUsage, "Unknown argument");
case ':':
// Missing option argument
isc_throw(InvalidUsage, "Missing option argument");
default:
// I don't think we should get here as the unknown arguments
// and missing options cases should cover everything else
isc_throw(InvalidUsage, "Invalid command line");
}
}
// Check for extraneous parameters.
if (argc > optind) {
isc_throw(InvalidUsage, "Extraneous parameters.");
}
if (protocol_version_ == 0) {
isc_throw(InvalidUsage, "DHCP version required");
}
if (previous_file_.empty()) {
isc_throw(InvalidUsage, "Previous file not specified");
}
if (copy_file_.empty()) {
isc_throw(InvalidUsage, "Copy file not specified");
}
if (output_file_.empty()) {
isc_throw(InvalidUsage, "Output file not specified");
}
if (finish_file_.empty()) {
isc_throw(InvalidUsage, "Finish file not specified");
}
if (config_file_.empty()) {
isc_throw(InvalidUsage, "Config file not specified");
}
// If verbose is set echo the input information
if (verbose_ == true) {
std::cerr << "Protocol version: DHCPv" << protocol_version_ << std::endl
<< "Previous lease file: " << previous_file_ << std::endl
<< "Copy lease file: " << copy_file_ << std::endl
<< "Output lease file: " << output_file_ << std::endl
<< "Finishn file: " << finish_file_ << std::endl
<< "Config file: " << config_file_ << std::endl
<< "PID file: " << pid_file_ << std::endl;
}
}
void
LFCController::usage(const std::string& text) {
if (text != "") {
std::cerr << "Usage error: " << text << std::endl;
}
std::cerr << "Usage: " << lfc_bin_name_ << std::endl
<< " [-4|-6] -p file -i file -o file -f file -c file" << std::endl
<< " -4 or -6 clean a set of v4 or v6 lease files" << std::endl
<< " -p <file>: previous lease file" << std::endl
<< " -i <file>: copy of lease file" << std::endl
<< " -o <file>: output lease file" << std::endl
<< " -f <file>: finish file" << std::endl
<< " -c <file>: configuration file" << std::endl
<< " -v: print version number and exit" << std::endl
<< " -V: print extended version inforamtion and exit" << std::endl
<< " -d: optional, verbose output " << std::endl
<< " -h: print this message " << std::endl
<< std::endl;
}
std::string
LFCController::getVersion(const bool extended) const{
std::stringstream version_stream;
version_stream << VERSION;
if (extended) {
version_stream << std::endl << EXTENDED_VERSION;
}
return (version_stream.str());
}
}; // namespace isc::lfc
}; // namespace isc
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef LFC_CONTROLLER_H
#define LFC_CONTROLLER_H
#include <exceptions/exceptions.h>
#include <string>
namespace isc {
namespace lfc {
/// @brief Exception thrown when the command line is invalid.
class InvalidUsage : public isc::Exception {
public:
InvalidUsage(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) { };
};
/// @brief Process controller for LFC process
///
/// This class provides the LFC process functions. These are used to:
/// manage the command line, check for already running instances,
/// invoke the code to process the lease files and finally to rename
/// the lease files as necessary.
///
/// @todo The current code simply processes the command line we still need to
/// -# handle PID file manipulation
/// -# invoke the code to read, process and write the lease files
/// -# rename and delete the shell files as required
class LFCController {
public:
/// @brief Defines the application name, it may be used to locate
/// configuration data and appears in log statements.
static const char* lfc_app_name_;
/// @brief Defines the executable name, by convention this should match
/// the executable name.
static const char* lfc_bin_name_;
/// @brief Constructor
LFCController();
/// @brief Destructor
~LFCController();
/// @brief Acts as the primary entry point to start execution
/// of the process. Provides the control logic:
///
/// -# parse command line arguments
/// -# verifies that it is the only instance
/// -# creates pid file (TBD)
/// -# .... TBD
/// -# remove pid file (TBD)
/// -# exit to the caller
///
/// @param argc Number of strings in the @c argv array.
/// @param argv Array of arguments passed in via the program's main function.
///
/// @throw InvalidUsage if the command line parameters are invalid.
void launch(int argc, char* argv[]);
/// @brief Process the command line arguments. It is the first
/// step taken after the process has been launched.
///
/// @param argc Number of strings in the @c argv array.
/// @param argv Array of arguments passed in via the program's main function.
///
/// @throw InvalidUsage if the command line parameters are invalid.
void parseArgs(int argc, char* argv[]);
/// @brief Prints the program usage text to std error.
///
/// @param text is a string message which will preceded the usage text.
/// This is intended to be used for specific usage violation messages.
void usage(const std::string& text);
/// @brief Gets the Kea version number for printing
///
/// @param extended is a boolean indicating if the version string
/// should be short (false) or extended (true)
std::string getVersion(const bool extended) const;
/// @name Accessor methods mainly used for testing purposes
//@{
/// @brief Gets the protocol version of the leaes files
///
/// @return Returns the value of the DHCP protocol version.
/// This can be 4 or 6 while in use and 0 before parsing
/// any arguments.
int getProtocolVersion() const {
return (protocol_version_);
}
/// @brief Gets the config file name
///
/// @return Returns the path to the config file
std::string getConfigFile() const {
return (config_file_);
}
/// @brief Gets the prevous file name
///
/// @return Returns the path to the previous file
std::string getPreviousFile() const {
return (previous_file_);
}
/// @brief Gets the copy file name
///
/// @return Returns the path to the copy file