Commit c1372a95 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3669] Memfile spawns kea-lfc for lease file cleanup.

parent 06d26f88
......@@ -17,6 +17,7 @@
#include <dhcpsrv/lease_file_loader.h>
#include <dhcpsrv/memfile_lease_mgr.h>
#include <exceptions/exceptions.h>
#include <util/process_spawn.h>
#include <cstdio>
#include <iostream>
#include <sstream>
......@@ -26,13 +27,17 @@ namespace {
/// @brief Maximum number of errors to read the leases from the lease file.
const uint32_t MAX_LEASE_ERRORS = 100;
const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE";
} // end of anonymous namespace
using namespace isc;
using namespace isc::dhcp;
using namespace isc::util;
Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
: LeaseMgr(parameters), lfc_timer_(*getIOService()) {
: LeaseMgr(parameters), lfc_timer_(*getIOService()),
lfc_process_() {
// Check the universe and use v4 file or v6 file.
std::string universe = getParameter("universe");
if (universe == "4") {
......@@ -57,7 +62,7 @@ Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_NO_STORAGE);
} else {
initTimers();
lfcSetup();
}
}
......@@ -511,7 +516,7 @@ Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
}
void
Memfile_LeaseMgr::initTimers() {
Memfile_LeaseMgr::lfcSetup() {
std::string lfc_interval_str = "0";
try {
lfc_interval_str = getParameter("lfc-interval");
......@@ -527,18 +532,51 @@ Memfile_LeaseMgr::initTimers() {
<< lfc_interval_str << " specified");
}
// If LFC is enabled, we have to setup the interval timer and prepare for
// executing the kea-lfc process.
if (lfc_interval > 0) {
char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME);
// Set the timer to call callback function periodically.
asiolink::IntervalTimer::Callback cb =
boost::bind(&Memfile_LeaseMgr::lfcCallback, this);
LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_SETUP).arg(lfc_interval);
lfc_timer_.setup(cb, lfc_interval * 1000);
// Start preparing the command line for kea-lfc.
// Gather the base file name.
std::string lease_file = lease_file4_ ? lease_file4_->getFilename() :
lease_file6_->getFilename();
// Create the other names by appending suffixes to the base name.
util::ProcessArgs args;
// Universe: v4 or v6.
args.push_back(lease_file4_ ? "-4" : "-6");
// Previous file.
args.push_back("-p");
args.push_back(appendSuffix(lease_file, FILE_PREVIOUS));
// Input file.
args.push_back("-i");
args.push_back(appendSuffix(lease_file, FILE_INPUT));
// Output file.
args.push_back("-o");
args.push_back(appendSuffix(lease_file, FILE_OUTPUT));
// Finish file.
args.push_back("-f");
args.push_back(appendSuffix(lease_file, FILE_FINISH));
// The configuration file is currently unused.
args.push_back("-c");
args.push_back("ignored-path");
// Create the process (do not start it yet).
lfc_process_.reset(new util::ProcessSpawn(std::string(c_executable), args));
}
}
void
Memfile_LeaseMgr::lfcCallback() {
/// @todo Extend this method to spawn the new process which will
/// perform the Lease File Cleanup in background.
LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_START);
// Check if we're in the v4 or v6 space and use the appropriate file.
......@@ -554,14 +592,25 @@ Memfile_LeaseMgr::lfcCallback() {
template<typename LeaseFileType>
void Memfile_LeaseMgr::
leaseFileCleanup(boost::shared_ptr<LeaseFileType>& lease_file) {
// Check if the copy of the lease file exists already. If it does, it
// is an indication that another LFC instance may be in progress, in
// which case we don't want to rotate the current lease file to avoid
// overriding the contents of the existing file.
CSVFile lease_file_copy(appendSuffix(lease_file->getFilename(), FILE_INPUT));
if (!lease_file_copy.exists()) {
// Close the current file so as we can move it to the copy file.
lease_file->close();
// Move the current file to the copy file.
rename(lease_file->getFilename().c_str(),
lease_file_copy.getFilename().c_str());
// Now that we moved the current file, we need to create a new one.
lease_file.reset(new LeaseFileType(lease_file->getFilename()));
// Leave the new file open for writing.
lease_file->open();
}
// Once we have rotated files as needed, start the new kea-lfc process
// to perform a cleanup.
lfc_process_->spawn();
}
template<typename LeaseObjectType, typename LeaseFileType, typename StorageType>
......
......@@ -21,7 +21,9 @@
#include <dhcpsrv/csv_lease_file6.h>
#include <dhcpsrv/memfile_lease_storage.h>
#include <dhcpsrv/lease_mgr.h>
#include <util/process_spawn.h>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
namespace isc {
......@@ -405,11 +407,15 @@ protected:
private:
/// @brief Initialize the timers used to perform repeating tasks.
/// @brief Setup the periodic Lease File Cleanup.
///
/// Currently only one timer is supported. This timer executes the
/// Lease File Cleanup periodically.
void initTimers();
/// This method checks if the @c lfc-interval configuration parameter
/// is set to a non-zero value and sets up the interval timer to
/// perform the Lease File Cleanup periodically. It also prepares the
/// path and arguments for the @c kea-lfc application which will be
/// executed to perform the cleanup.
void lfcSetup();
/// @brief Initialize the location of the lease file.
///
/// This method uses the parameters passed as a map to the constructor to
......@@ -485,6 +491,10 @@ private:
/// @brief A timer scheduled to perform Lease File Cleanup.
asiolink::IntervalTimer lfc_timer_;
protected:
boost::scoped_ptr<util::ProcessSpawn> lfc_process_;
};
}; // end of isc::dhcp namespace
......
......@@ -4,6 +4,7 @@ AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dhcpsrv/tests\"
AM_CPPFLAGS += -DDHCP_DATA_DIR=\"$(abs_top_builddir)/src/lib/dhcpsrv/tests\"
AM_CPPFLAGS += -DKEA_LFC_BUILD_DIR=\"$(abs_top_builddir)/src/bin/lfc\"
AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
AM_CXXFLAGS = $(KEA_CXXFLAGS)
......
......@@ -29,8 +29,9 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <queue>
#include <sstream>
#include <unistd.h>
using namespace std;
using namespace isc;
......@@ -90,6 +91,7 @@ public:
}
using Memfile_LeaseMgr::lfcCallback;
using Memfile_LeaseMgr::lfc_process_;
};
/// @brief Test fixture class for @c Memfile_LeaseMgr
......@@ -105,6 +107,10 @@ public:
io_service_(),
fail_on_callback_(false) {
std::ostringstream s;
s << KEA_LFC_BUILD_DIR << "/kea-lfc";
setenv("KEA_LFC_EXECUTABLE", s.str().c_str(), 1);
// Remove lease files and products of Lease File Cleanup.
removeFiles(getLeaseFilePath("leasefile4_0.csv"));
removeFiles(getLeaseFilePath("leasefile6_0.csv"));
......@@ -212,6 +218,24 @@ public:
}
}
/// @brief Waits for the specified process to finish.
///
/// @param process An object which started the process.
/// @param timeout Timeout in seconds.
///
/// @return true if the process ended, false otherwise
bool waitForProcess(const util::ProcessSpawn& process,
const uint8_t timeout) {
uint32_t iterations = 0;
const uint32_t iterations_max = timeout * 1000;
while (process.isRunning() && (iterations < iterations_max)) {
usleep(1000);
++iterations;
}
return (iterations < iterations_max);
}
/// @brief Object providing access to v4 lease IO.
LeaseFileIO io4_;
......@@ -399,6 +423,10 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup) {
ASSERT_TRUE(current_file.exists());
EXPECT_EQ(new_file_contents, current_file.readFile());
ASSERT_TRUE(waitForProcess(*lease_mgr->lfc_process_, 2));
EXPECT_EQ(0, lease_mgr->lfc_process_->getExitStatus());
}
// Test that the backend returns a correct value of the interval
......@@ -416,11 +444,13 @@ TEST_F(MemfileLeaseMgrTest, getIOServiceExecInterval) {
// lfc-interval = 10
pmap["lfc-interval"] = "10";
lease_mgr.reset();
lease_mgr.reset(new LFCMemfileLeaseMgr(pmap));
EXPECT_EQ(10, lease_mgr->getIOServiceExecInterval());
// lfc-interval = 20
pmap["lfc-interval"] = "20";
lease_mgr.reset();
lease_mgr.reset(new LFCMemfileLeaseMgr(pmap));
EXPECT_EQ(20, lease_mgr->getIOServiceExecInterval());
......
Supports Markdown
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