Commit 06b3c504 authored by Shawn Routhier's avatar Shawn Routhier
Browse files

[trac3687] Add PIDFile class to manage PID files

Add the PIDFile class to manage PID files (check, write, delete)

Update the LFC code to use the PIDFile class to run only a single
instance at a time.
parent 1e892105
...@@ -46,7 +46,8 @@ ...@@ -46,7 +46,8 @@
<command>kea-lfc</command> <command>kea-lfc</command>
<arg><option>-4|-6</option></arg> <arg><option>-4|-6</option></arg>
<arg><option>-c <replaceable class="parameter">config-file</replaceable></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>-p <replaceable class="parameter">pid-file</replaceable></option></arg>
<arg><option>-x <replaceable class="parameter">previous-file</replaceable></option></arg>
<arg><option>-i <replaceable class="parameter">copy-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>-o <replaceable class="parameter">output-file</replaceable></option></arg>
<arg><option>-f <replaceable class="parameter">finish-file</replaceable></option></arg> <arg><option>-f <replaceable class="parameter">finish-file</replaceable></option></arg>
...@@ -117,7 +118,7 @@ ...@@ -117,7 +118,7 @@
Configuration file including the configuration for Configuration file including the configuration for
<command>kea-lfc</command> process. It may also <command>kea-lfc</command> process. It may also
contain configuration entries for other Kea services. contain configuration entries for other Kea services.
Currently <command>kea-lfc</command> gets all of its arguments from 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 the comamnd line, in the future it will be extended to get some arguments
from the config file. from the config file.
</para></listitem> </para></listitem>
...@@ -126,7 +127,18 @@ ...@@ -126,7 +127,18 @@
<varlistentry> <varlistentry>
<term><option>-p</option></term> <term><option>-p</option></term>
<listitem><para> <listitem><para>
Previous lease file - When <command>kea-lfc</command> starts this PID file - When the <command>kea-lfc</command> process starts
it attempts to determine if another instance of the process is
already running by examining the pid file. If one is running
it aborts the new process. If one isn't running it writes its
pid into the pid file.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-x</option></term>
<listitem><para>
Previous or ex lease file - When <command>kea-lfc</command> starts this
is the result of any previous run of <command>kea-lfc</command>. 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. When <command>kea-lfc</command> finishes it is the result of this run.
If <command>kea-lfc</command> is interrupted before compelting If <command>kea-lfc</command> is interrupted before compelting
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
#include <lfc/lfc_controller.h> #include <lfc/lfc_controller.h>
#include <util/pid_file.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
#include <config.h> #include <config.h>
#include <iostream> #include <iostream>
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
#include <stdlib.h> #include <stdlib.h>
using namespace std; using namespace std;
using namespace isc::util;
namespace isc { namespace isc {
namespace lfc { namespace lfc {
...@@ -42,12 +44,38 @@ LFCController::~LFCController() { ...@@ -42,12 +44,38 @@ LFCController::~LFCController() {
void void
LFCController::launch(int argc, char* argv[]) { LFCController::launch(int argc, char* argv[]) {
try { try {
parseArgs(argc, argv); parseArgs(argc, argv);
} catch (const InvalidUsage& ex) { } catch (const InvalidUsage& ex) {
usage(ex.what()); usage(ex.what());
throw; // rethrow it throw; // rethrow it
} }
std::cerr << "Starting lease file cleanup" << std::endl;
// verify we are the only instance
PIDFile pid_file(pid_file_);
if (pid_file.check() == true) {
// Already running instance, bail out
std::cerr << "LFC instance already running" << std::endl;
return;
}
// create the pid file for this instance
try {
pid_file.write();
} catch (const PIDFileError& pid_ex) {
std::cerr << pid_ex.what() << std::endl;
return;
}
// do other work (TBD)
std::cerr << "Add code to perform lease cleanup" << std::endl;
// delete the pid file for this instance
pid_file.deleteFile();
std::cerr << "LFC complete" << std::endl;
} }
void void
...@@ -56,7 +84,7 @@ LFCController::parseArgs(int argc, char* argv[]) { ...@@ -56,7 +84,7 @@ LFCController::parseArgs(int argc, char* argv[]) {
opterr = 0; opterr = 0;
optind = 1; optind = 1;
while ((ch = getopt(argc, argv, ":46dvVp:i:o:c:f:")) != -1) { while ((ch = getopt(argc, argv, ":46dvVp:x:i:o:c:f:")) != -1) {
switch (ch) { switch (ch) {
case '4': case '4':
// Process DHCPv4 lease files. // Process DHCPv4 lease files.
...@@ -84,9 +112,17 @@ LFCController::parseArgs(int argc, char* argv[]) { ...@@ -84,9 +112,17 @@ LFCController::parseArgs(int argc, char* argv[]) {
break; break;
case 'p': case 'p':
// Previous file name. // PID file name.
if (optarg == NULL) {
isc_throw(InvalidUsage, "PID file name missing");
}
pid_file_ = optarg;
break;
case 'x':
// Previous (or ex) file name.
if (optarg == NULL) { if (optarg == NULL) {
isc_throw(InvalidUsage, "Previous file name missing"); isc_throw(InvalidUsage, "Previous (ex) file name missing");
} }
previous_file_ = optarg; previous_file_ = optarg;
break; break;
...@@ -108,7 +144,7 @@ LFCController::parseArgs(int argc, char* argv[]) { ...@@ -108,7 +144,7 @@ LFCController::parseArgs(int argc, char* argv[]) {
break; break;
case 'f': case 'f':
// Output file name. // Finish file name.
if (optarg == NULL) { if (optarg == NULL) {
isc_throw(InvalidUsage, "Finish file name missing"); isc_throw(InvalidUsage, "Finish file name missing");
} }
...@@ -116,7 +152,7 @@ LFCController::parseArgs(int argc, char* argv[]) { ...@@ -116,7 +152,7 @@ LFCController::parseArgs(int argc, char* argv[]) {
break; break;
case 'c': case 'c':
// Previous file name. // Configuration file name
if (optarg == NULL) { if (optarg == NULL) {
isc_throw(InvalidUsage, "Configuration file name missing"); isc_throw(InvalidUsage, "Configuration file name missing");
} }
...@@ -151,6 +187,10 @@ LFCController::parseArgs(int argc, char* argv[]) { ...@@ -151,6 +187,10 @@ LFCController::parseArgs(int argc, char* argv[]) {
isc_throw(InvalidUsage, "DHCP version required"); isc_throw(InvalidUsage, "DHCP version required");
} }
if (pid_file_.empty()) {
isc_throw(InvalidUsage, "PID file not specified");
}
if (previous_file_.empty()) { if (previous_file_.empty()) {
isc_throw(InvalidUsage, "Previous file not specified"); isc_throw(InvalidUsage, "Previous file not specified");
} }
...@@ -174,12 +214,12 @@ LFCController::parseArgs(int argc, char* argv[]) { ...@@ -174,12 +214,12 @@ LFCController::parseArgs(int argc, char* argv[]) {
// If verbose is set echo the input information // If verbose is set echo the input information
if (verbose_ == true) { if (verbose_ == true) {
std::cerr << "Protocol version: DHCPv" << protocol_version_ << std::endl std::cerr << "Protocol version: DHCPv" << protocol_version_ << std::endl
<< "Previous lease file: " << previous_file_ << std::endl << "Previous or ex lease file: " << previous_file_ << std::endl
<< "Copy lease file: " << copy_file_ << std::endl << "Copy lease file: " << copy_file_ << std::endl
<< "Output lease file: " << output_file_ << std::endl << "Output lease file: " << output_file_ << std::endl
<< "Finishn file: " << finish_file_ << std::endl << "Finishn file: " << finish_file_ << std::endl
<< "Config file: " << config_file_ << std::endl << "Config file: " << config_file_ << std::endl
<< "PID file: " << pid_file_ << std::endl; << "PID file: " << pid_file_ << std::endl;
} }
} }
...@@ -190,9 +230,10 @@ LFCController::usage(const std::string& text) { ...@@ -190,9 +230,10 @@ LFCController::usage(const std::string& text) {
} }
std::cerr << "Usage: " << lfc_bin_name_ << 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|-6] -p file -x 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 << " -4 or -6 clean a set of v4 or v6 lease files" << std::endl
<< " -p <file>: previous lease file" << std::endl << " -p <file>: PID file" << std::endl
<< " -x <file>: previous or ex lease file" << std::endl
<< " -i <file>: copy of lease file" << std::endl << " -i <file>: copy of lease file" << std::endl
<< " -o <file>: output lease file" << std::endl << " -o <file>: output lease file" << std::endl
<< " -f <file>: finish file" << std::endl << " -f <file>: finish file" << std::endl
......
...@@ -59,10 +59,10 @@ public: ...@@ -59,10 +59,10 @@ public:
/// of the process. Provides the control logic: /// of the process. Provides the control logic:
/// ///
/// -# parse command line arguments /// -# parse command line arguments
/// -# verifies that it is the only instance /// -# verify that it is the only instance
/// -# creates pid file (TBD) /// -# create pid file
/// -# .... TBD /// -# .... TBD
/// -# remove pid file (TBD) /// -# remove pid file
/// -# exit to the caller /// -# exit to the caller
/// ///
/// @param argc Number of strings in the @c argv array. /// @param argc Number of strings in the @c argv array.
...@@ -111,7 +111,7 @@ public: ...@@ -111,7 +111,7 @@ public:
return (config_file_); return (config_file_);
} }
/// @brief Gets the prevous file name /// @brief Gets the previous file name
/// ///
/// @return Returns the path to the previous file /// @return Returns the path to the previous file
std::string getPreviousFile() const { std::string getPreviousFile() const {
......
...@@ -45,7 +45,7 @@ TEST(LFCControllerTest, fullCommandLine) { ...@@ -45,7 +45,7 @@ TEST(LFCControllerTest, fullCommandLine) {
// Verify that standard options can be parsed without error // Verify that standard options can be parsed without error
char* argv[] = { const_cast<char*>("progName"), char* argv[] = { const_cast<char*>("progName"),
const_cast<char*>("-4"), const_cast<char*>("-4"),
const_cast<char*>("-p"), const_cast<char*>("-x"),
const_cast<char*>("previous"), const_cast<char*>("previous"),
const_cast<char*>("-i"), const_cast<char*>("-i"),
const_cast<char*>("copy"), const_cast<char*>("copy"),
...@@ -54,8 +54,10 @@ TEST(LFCControllerTest, fullCommandLine) { ...@@ -54,8 +54,10 @@ TEST(LFCControllerTest, fullCommandLine) {
const_cast<char*>("-c"), const_cast<char*>("-c"),
const_cast<char*>("config"), const_cast<char*>("config"),
const_cast<char*>("-f"), const_cast<char*>("-f"),
const_cast<char*>("finish") }; const_cast<char*>("finish"),
int argc = 12; const_cast<char*>("-p"),
const_cast<char*>("pid") };
int argc = 14;
ASSERT_NO_THROW(lfc_controller.parseArgs(argc, argv)); ASSERT_NO_THROW(lfc_controller.parseArgs(argc, argv));
...@@ -66,6 +68,7 @@ TEST(LFCControllerTest, fullCommandLine) { ...@@ -66,6 +68,7 @@ TEST(LFCControllerTest, fullCommandLine) {
EXPECT_EQ(lfc_controller.getCopyFile(), "copy"); EXPECT_EQ(lfc_controller.getCopyFile(), "copy");
EXPECT_EQ(lfc_controller.getOutputFile(), "output"); EXPECT_EQ(lfc_controller.getOutputFile(), "output");
EXPECT_EQ(lfc_controller.getFinishFile(), "finish"); EXPECT_EQ(lfc_controller.getFinishFile(), "finish");
EXPECT_EQ(lfc_controller.getPidFile(), "pid");
} }
/// @brief Verify that parsing a correct but incomplete line fails. /// @brief Verify that parsing a correct but incomplete line fails.
...@@ -80,7 +83,7 @@ TEST(LFCControllerTest, notEnoughData) { ...@@ -80,7 +83,7 @@ TEST(LFCControllerTest, notEnoughData) {
// to the parse routine via the argc variable. // to the parse routine via the argc variable.
char* argv[] = { const_cast<char*>("progName"), char* argv[] = { const_cast<char*>("progName"),
const_cast<char*>("-4"), const_cast<char*>("-4"),
const_cast<char*>("-p"), const_cast<char*>("-x"),
const_cast<char*>("previous"), const_cast<char*>("previous"),
const_cast<char*>("-i"), const_cast<char*>("-i"),
const_cast<char*>("copy"), const_cast<char*>("copy"),
...@@ -89,11 +92,13 @@ TEST(LFCControllerTest, notEnoughData) { ...@@ -89,11 +92,13 @@ TEST(LFCControllerTest, notEnoughData) {
const_cast<char*>("-c"), const_cast<char*>("-c"),
const_cast<char*>("config"), const_cast<char*>("config"),
const_cast<char*>("-f"), const_cast<char*>("-f"),
const_cast<char*>("finish") }; const_cast<char*>("finish"),
const_cast<char*>("-p"),
const_cast<char*>("pid") };
int argc = 1; int argc = 1;
for (; argc < 12; ++argc) { for (; argc < 14; ++argc) {
EXPECT_THROW(lfc_controller.parseArgs(argc, argv), InvalidUsage) EXPECT_THROW(lfc_controller.parseArgs(argc, argv), InvalidUsage)
<< "test failed for argc = " << argc; << "test failed for argc = " << argc;
} }
...@@ -114,7 +119,7 @@ TEST(LFCControllerTest, tooMuchData) { ...@@ -114,7 +119,7 @@ TEST(LFCControllerTest, tooMuchData) {
char* argv[] = { const_cast<char*>("progName"), char* argv[] = { const_cast<char*>("progName"),
const_cast<char*>("-4"), const_cast<char*>("-4"),
const_cast<char*>("-p"), const_cast<char*>("-x"),
const_cast<char*>("previous"), const_cast<char*>("previous"),
const_cast<char*>("-i"), const_cast<char*>("-i"),
const_cast<char*>("copy"), const_cast<char*>("copy"),
...@@ -124,11 +129,13 @@ TEST(LFCControllerTest, tooMuchData) { ...@@ -124,11 +129,13 @@ TEST(LFCControllerTest, tooMuchData) {
const_cast<char*>("config"), const_cast<char*>("config"),
const_cast<char*>("-f"), const_cast<char*>("-f"),
const_cast<char*>("finish"), const_cast<char*>("finish"),
const_cast<char*>("-p"),
const_cast<char*>("pid"),
const_cast<char*>("some"), const_cast<char*>("some"),
const_cast<char*>("other"), const_cast<char*>("other"),
const_cast<char*>("args"), const_cast<char*>("args"),
}; };
int argc = 15; int argc = 17;
// We expect an error as we have arguments that aren't valid // We expect an error as we have arguments that aren't valid
EXPECT_THROW(lfc_controller.parseArgs(argc, argv), InvalidUsage); EXPECT_THROW(lfc_controller.parseArgs(argc, argv), InvalidUsage);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment