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

[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 @@
<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>-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>-o <replaceable class="parameter">output-file</replaceable></option></arg>
<arg><option>-f <replaceable class="parameter">finish-file</replaceable></option></arg>
......@@ -117,7 +118,7 @@
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
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>
......@@ -126,7 +127,18 @@
<varlistentry>
<term><option>-p</option></term>
<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>.
When <command>kea-lfc</command> finishes it is the result of this run.
If <command>kea-lfc</command> is interrupted before compelting
......
......@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <lfc/lfc_controller.h>
#include <util/pid_file.h>
#include <exceptions/exceptions.h>
#include <config.h>
#include <iostream>
......@@ -21,6 +22,7 @@
#include <stdlib.h>
using namespace std;
using namespace isc::util;
namespace isc {
namespace lfc {
......@@ -42,12 +44,38 @@ LFCController::~LFCController() {
void
LFCController::launch(int argc, char* argv[]) {
try {
parseArgs(argc, argv);
} catch (const InvalidUsage& ex) {
usage(ex.what());
throw; // rethrow it
}
try {
parseArgs(argc, argv);
} catch (const InvalidUsage& ex) {
usage(ex.what());
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
......@@ -56,7 +84,7 @@ LFCController::parseArgs(int argc, char* argv[]) {
opterr = 0;
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) {
case '4':
// Process DHCPv4 lease files.
......@@ -84,9 +112,17 @@ LFCController::parseArgs(int argc, char* argv[]) {
break;
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) {
isc_throw(InvalidUsage, "Previous file name missing");
isc_throw(InvalidUsage, "Previous (ex) file name missing");
}
previous_file_ = optarg;
break;
......@@ -108,7 +144,7 @@ LFCController::parseArgs(int argc, char* argv[]) {
break;
case 'f':
// Output file name.
// Finish file name.
if (optarg == NULL) {
isc_throw(InvalidUsage, "Finish file name missing");
}
......@@ -116,7 +152,7 @@ LFCController::parseArgs(int argc, char* argv[]) {
break;
case 'c':
// Previous file name.
// Configuration file name
if (optarg == NULL) {
isc_throw(InvalidUsage, "Configuration file name missing");
}
......@@ -151,6 +187,10 @@ LFCController::parseArgs(int argc, char* argv[]) {
isc_throw(InvalidUsage, "DHCP version required");
}
if (pid_file_.empty()) {
isc_throw(InvalidUsage, "PID file not specified");
}
if (previous_file_.empty()) {
isc_throw(InvalidUsage, "Previous file not specified");
}
......@@ -174,12 +214,12 @@ LFCController::parseArgs(int argc, char* argv[]) {
// 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;
<< "Previous or ex 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;
}
}
......@@ -190,9 +230,10 @@ LFCController::usage(const std::string& text) {
}
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
<< " -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
<< " -o <file>: output lease file" << std::endl
<< " -f <file>: finish file" << std::endl
......
......@@ -59,10 +59,10 @@ public:
/// of the process. Provides the control logic:
///
/// -# parse command line arguments
/// -# verifies that it is the only instance
/// -# creates pid file (TBD)
/// -# verify that it is the only instance
/// -# create pid file
/// -# .... TBD
/// -# remove pid file (TBD)
/// -# remove pid file
/// -# exit to the caller
///
/// @param argc Number of strings in the @c argv array.
......@@ -111,7 +111,7 @@ public:
return (config_file_);
}
/// @brief Gets the prevous file name
/// @brief Gets the previous file name
///
/// @return Returns the path to the previous file
std::string getPreviousFile() const {
......
......@@ -45,7 +45,7 @@ TEST(LFCControllerTest, fullCommandLine) {
// Verify that standard options can be parsed without error
char* argv[] = { const_cast<char*>("progName"),
const_cast<char*>("-4"),
const_cast<char*>("-p"),
const_cast<char*>("-x"),
const_cast<char*>("previous"),
const_cast<char*>("-i"),
const_cast<char*>("copy"),
......@@ -54,8 +54,10 @@ TEST(LFCControllerTest, fullCommandLine) {
const_cast<char*>("-c"),
const_cast<char*>("config"),
const_cast<char*>("-f"),
const_cast<char*>("finish") };
int argc = 12;
const_cast<char*>("finish"),
const_cast<char*>("-p"),
const_cast<char*>("pid") };
int argc = 14;
ASSERT_NO_THROW(lfc_controller.parseArgs(argc, argv));
......@@ -66,6 +68,7 @@ TEST(LFCControllerTest, fullCommandLine) {
EXPECT_EQ(lfc_controller.getCopyFile(), "copy");
EXPECT_EQ(lfc_controller.getOutputFile(), "output");
EXPECT_EQ(lfc_controller.getFinishFile(), "finish");
EXPECT_EQ(lfc_controller.getPidFile(), "pid");
}
/// @brief Verify that parsing a correct but incomplete line fails.
......@@ -80,7 +83,7 @@ TEST(LFCControllerTest, notEnoughData) {
// to the parse routine via the argc variable.
char* argv[] = { const_cast<char*>("progName"),
const_cast<char*>("-4"),
const_cast<char*>("-p"),
const_cast<char*>("-x"),
const_cast<char*>("previous"),
const_cast<char*>("-i"),
const_cast<char*>("copy"),
......@@ -89,11 +92,13 @@ TEST(LFCControllerTest, notEnoughData) {
const_cast<char*>("-c"),
const_cast<char*>("config"),
const_cast<char*>("-f"),
const_cast<char*>("finish") };
const_cast<char*>("finish"),
const_cast<char*>("-p"),
const_cast<char*>("pid") };
int argc = 1;
for (; argc < 12; ++argc) {
for (; argc < 14; ++argc) {
EXPECT_THROW(lfc_controller.parseArgs(argc, argv), InvalidUsage)
<< "test failed for argc = " << argc;
}
......@@ -114,7 +119,7 @@ TEST(LFCControllerTest, tooMuchData) {
char* argv[] = { const_cast<char*>("progName"),
const_cast<char*>("-4"),
const_cast<char*>("-p"),
const_cast<char*>("-x"),
const_cast<char*>("previous"),
const_cast<char*>("-i"),
const_cast<char*>("copy"),
......@@ -124,11 +129,13 @@ TEST(LFCControllerTest, tooMuchData) {
const_cast<char*>("config"),
const_cast<char*>("-f"),
const_cast<char*>("finish"),
const_cast<char*>("-p"),
const_cast<char*>("pid"),
const_cast<char*>("some"),
const_cast<char*>("other"),
const_cast<char*>("args"),
};
int argc = 15;
int argc = 17;
// We expect an error as we have arguments that aren't valid
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