From e4f8a223c0797372875d1e891b4247fc0107a7cd Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Thu, 5 Feb 2015 15:59:06 +0100 Subject: [PATCH] [3669] Re-organized the LFC in Memfile_LeaseMgr to use updated ProcessSpawn --- src/lib/dhcpsrv/memfile_lease_mgr.cc | 387 ++++++++++++------ src/lib/dhcpsrv/memfile_lease_mgr.h | 195 +++++---- .../tests/memfile_lease_mgr_unittest.cc | 24 +- 3 files changed, 394 insertions(+), 212 deletions(-) diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 0672073ec8..8b138ee28b 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -41,13 +42,190 @@ 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; +namespace isc { +namespace dhcp { + +/// @brief Represents a configuration for Lease File Cleanup. +/// +/// This class is solely used by the @c Memfile_LeaseMgr as a configuration +/// information storage for %Lease File Cleanup. Internally, it creates +/// the interval timer and assigns a callback function (pointer to which is +/// passed in the constructor), which will be called at the specified +/// intervals to perform the cleanup. It is also responsible for creating +/// and maintaing the object which is used to spawn the new process which +/// executes the @c kea-lfc program. +/// +/// This functionality is enclosed in a separate class so as the implementation +/// details are not exposed in the @c Memfile_LeaseMgr header file and +/// to maintain a single place with the LFC configuration, instead of multiple +/// members and functions scattered in the @c Memfile_LeaseMgr class. +class LFCSetup { +public: + + /// @brief Constructor. + /// + /// Assigns a pointer to the function triggered to perform the cleanup. + /// This pointer should point to the appropriate method of the + /// @c Memfile_LeaseMgr class. + /// + /// @param callback A pointer to the callback function. + /// @param io_service An io service used to create the interval timer. + LFCSetup(asiolink::IntervalTimer::Callback callback, + asiolink::IOService& io_service); + + /// @brief Sets the new configuration for the %Lease File Cleanup. + /// + /// @param lfc_interval An interval in seconds at which the cleanup should + /// be performed. + /// @param lease_file4 A pointer to the DHCPv4 lease file to be cleaned up + /// or NULL. If this is NULL, the @c lease_file6 must be non-null. + /// @param lease_file6 A pointer to the DHCPv6 lease file to be cleaned up + /// or NULL. If this is NULL, the @c lease_file4 must be non-null. + void setup(const uint32_t lfc_interval, + const boost::shared_ptr& lease_file4, + const boost::shared_ptr& lease_file6); + + /// @brief Spawns a new process. + void execute(); + + /// @brief Returns interval at which the cleanup is performed. + /// + /// @return Interval in milliseconds. + long getInterval() const; + + /// @brief Checks if the lease file cleanup is in progress. + /// + /// @return true if the lease file cleanup is being executed. + bool isRunning() const; + + /// @brief Returns exit code of the last completed cleanup. + int getExitStatus() const; + +private: + + /// @brief Interval timer for LFC. + asiolink::IntervalTimer timer_; + + /// @brief A pointer to the @c ProcessSpawn object used to execute + /// the LFC. + boost::scoped_ptr process_; + + /// @brief A pointer to the callback function executed by the timer. + asiolink::IntervalTimer::Callback callback_; + + /// @brief A PID of the last executed LFC process. + pid_t pid_; +}; + +LFCSetup::LFCSetup(asiolink::IntervalTimer::Callback callback, + asiolink::IOService& io_service) + : timer_(io_service), process_(), callback_(callback), pid_(0) { +} + +void +LFCSetup::setup(const uint32_t lfc_interval, + const boost::shared_ptr& lease_file4, + const boost::shared_ptr& lease_file6) { + + // If LFC is enabled, we have to setup the interval timer and prepare for + // executing the kea-lfc process. + if (lfc_interval > 0) { + std::string executable; + char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME); + if (c_executable == NULL) { + executable = KEA_LFC_EXECUTABLE; + + } else { + executable = c_executable; + } + + // Set the timer to call callback function periodically. + LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_SETUP).arg(lfc_interval); + // Multiple the lfc_interval value by 1000 as this value specifies + // a timeout in seconds, whereas the setup() method expects the + // timeout in milliseconds. + timer_.setup(callback_, 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("-x"); + args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file, + Memfile_LeaseMgr::FILE_PREVIOUS)); + // Input file. + args.push_back("-i"); + args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file, + Memfile_LeaseMgr::FILE_INPUT)); + // Output file. + args.push_back("-o"); + args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file, + Memfile_LeaseMgr::FILE_OUTPUT)); + // Finish file. + args.push_back("-f"); + args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file, + Memfile_LeaseMgr::FILE_FINISH)); + // PID file. + args.push_back("-p"); + args.push_back(Memfile_LeaseMgr::appendSuffix(lease_file, + Memfile_LeaseMgr::FILE_PID)); + + // The configuration file is currently unused. + args.push_back("-c"); + args.push_back("ignored-path"); + + // Create the process (do not start it yet). + process_.reset(new util::ProcessSpawn(executable, args)); + } +} + +long +LFCSetup::getInterval() const { + return (timer_.getInterval()); +} + +void +LFCSetup::execute() { + try { + LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_EXECUTE) + .arg(process_->getCommandLine()); + pid_ = process_->spawn(); + std::cout << process_->getCommandLine() << std::endl; + + } catch (const ProcessSpawnError& ex) { + LOG_ERROR(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_SPAWN_FAIL); + } +} + +bool +LFCSetup::isRunning() const { + return (process_ && process_->isRunning(pid_)); +} + +int +LFCSetup::getExitStatus() const { + if (!process_) { + isc_throw(InvalidOperation, "unable to obtain LFC process exit code: " + " the process is NULL"); + } + return (process_->getExitStatus(pid_)); +} + + Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters) - : LeaseMgr(parameters), lfc_timer_(*getIOService()), - lfc_process_() { + : LeaseMgr(parameters), + lfc_setup_(new LFCSetup(boost::bind(&Memfile_LeaseMgr::lfcCallback, this), + *getIOService())) + { // Check the universe and use v4 file or v6 file. std::string universe = getParameter("universe"); if (universe == "4") { @@ -466,7 +644,7 @@ Memfile_LeaseMgr::appendSuffix(const std::string& file_name, uint32_t Memfile_LeaseMgr::getIOServiceExecInterval() const { - return (static_cast(lfc_timer_.getInterval() / 1000)); + return (static_cast(lfc_setup_->getInterval() / 1000)); } std::string @@ -528,79 +706,67 @@ Memfile_LeaseMgr::initLeaseFilePath(Universe u) { return (lease_file); } -void -Memfile_LeaseMgr::lfcSetup() { - std::string lfc_interval_str = "0"; - try { - lfc_interval_str = getParameter("lfc-interval"); - } catch (const std::exception& ex) { - // Ignore and default to 0. +template +void Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename, + boost::shared_ptr& lease_file, + StorageType& storage) { + // Check if the instance of the LFC is running right now. If it is + // running, we refuse to load leases as the LFC may be writing to the + // lease files right now. When the user retries server configuration + // it should go through. + /// @todo Consider applying a timeout for an LFC and retry when this + /// timeout elapses. + PIDFile pid_file(appendSuffix(filename, FILE_PID)); + if (pid_file.check()) { + isc_throw(DbOpenError, "unable to load leases from files while the " + "lease file cleanup is in progress"); } - uint32_t lfc_interval = 0; - try { - lfc_interval = boost::lexical_cast(lfc_interval_str); - } catch (boost::bad_lexical_cast& ex) { - isc_throw(isc::BadValue, "invalid value of the lfc-interval " - << lfc_interval_str << " specified"); - } + storage.clear(); - // If LFC is enabled, we have to setup the interval timer and prepare for - // executing the kea-lfc process. - if (lfc_interval > 0) { - std::string executable; - char* c_executable = getenv(KEA_LFC_EXECUTABLE_ENV_NAME); - if (c_executable == NULL) { - executable = KEA_LFC_EXECUTABLE; + // Load the leasefile.completed, if exists. + lease_file.reset(new LeaseFileType(std::string(filename + ".completed"))); + if (lease_file->exists()) { + LeaseFileLoader::load(*lease_file, storage, + MAX_LEASE_ERRORS); - } else { - executable = c_executable; + } else { + // If the leasefile.completed doesn't exist, let's load the leases + // from leasefile.2 and leasefile.1, if they exist. + lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS))); + if (lease_file->exists()) { + LeaseFileLoader::load(*lease_file, storage, + MAX_LEASE_ERRORS); } - // 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); - // Multiple the lfc_interval value by 1000 as this value specifies - // a timeout in seconds, whereas the setup() method expects the - // timeout in milliseconds. - 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(); + lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT))); + if (lease_file->exists()) { + LeaseFileLoader::load(*lease_file, storage, + MAX_LEASE_ERRORS); + } + } - // 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("-x"); - 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)); - // PID file. - args.push_back("-p"); - args.push_back(appendSuffix(lease_file, FILE_PID)); + // Always load leases from the primary lease file. If the lease file + // doesn't exist it will be created by the LeaseFileLoader. Note + // that the false value passed as the last parameter to load + // function causes the function to leave the file open after + // it is parsed. This file will be used by the backend to record + // future lease updates. + lease_file.reset(new LeaseFileType(filename)); + LeaseFileLoader::load(*lease_file, storage, + MAX_LEASE_ERRORS, false);; +} - // 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(executable, args)); - } +bool +Memfile_LeaseMgr::isLFCRunning() const { + return (lfc_setup_->isRunning()); } +int +Memfile_LeaseMgr::getLFCExitStatus() const { + return (lfc_setup_->getExitStatus()); +} void Memfile_LeaseMgr::lfcCallback() { @@ -608,16 +774,37 @@ Memfile_LeaseMgr::lfcCallback() { // Check if we're in the v4 or v6 space and use the appropriate file. if (lease_file4_) { - leaseFileCleanup(lease_file4_); + lfcExecute(lease_file4_); } else if (lease_file6_) { - leaseFileCleanup(lease_file6_); + lfcExecute(lease_file6_); + } +} + +void +Memfile_LeaseMgr::lfcSetup() { + std::string lfc_interval_str = "0"; + try { + lfc_interval_str = getParameter("lfc-interval"); + } catch (const std::exception& ex) { + // Ignore and default to 0. + } + + uint32_t lfc_interval = 0; + try { + lfc_interval = boost::lexical_cast(lfc_interval_str); + } catch (boost::bad_lexical_cast& ex) { + isc_throw(isc::BadValue, "invalid value of the lfc-interval " + << lfc_interval_str << " specified"); + } + if (lfc_interval > 0) { + lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_); } } template -void Memfile_LeaseMgr::leaseFileCleanup(boost::shared_ptr& lease_file) { +void Memfile_LeaseMgr::lfcExecute(boost::shared_ptr& lease_file) { bool do_lfc = true; // This string will hold a reason for the failure to rote the lease files. std::string error_string = "(no details)"; @@ -665,14 +852,7 @@ void Memfile_LeaseMgr::leaseFileCleanup(boost::shared_ptr& lease_ // Once we have rotated files as needed, start the new kea-lfc process // to perform a cleanup. if (do_lfc) { - try { - lfc_process_->spawn(); - LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_EXECUTE) - .arg(lfc_process_->getCommandLine()); - - } catch (const ProcessSpawnError& ex) { - LOG_ERROR(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_SPAWN_FAIL); - } + lfc_setup_->execute(); } else { LOG_ERROR(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_ROTATION_FAIL) @@ -682,53 +862,6 @@ void Memfile_LeaseMgr::leaseFileCleanup(boost::shared_ptr& lease_ } } -template -void Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename, - boost::shared_ptr& lease_file, - StorageType& storage) { - // Check if the instance of the LFC is running right now. If it is - // running, we refuse to load leases as the LFC may be writing to the - // lease files right now. When the user retries server configuration - // it should go through. - /// @todo Consider applying a timeout for an LFC and retry when this - /// timeout elapses. - PIDFile pid_file(appendSuffix(filename, FILE_PID)); - if (pid_file.check()) { - isc_throw(DbOpenError, "unable to load leases from files while the " - "lease file cleanup is in progress"); - } - - storage.clear(); - - // Load the leasefile.completed, if exists. - lease_file.reset(new LeaseFileType(std::string(filename + ".completed"))); - if (lease_file->exists()) { - LeaseFileLoader::load(*lease_file, storage, - MAX_LEASE_ERRORS); - - } else { - // If the leasefile.completed doesn't exist, let's load the leases - // from leasefile.2 and leasefile.1, if they exist. - lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_PREVIOUS))); - if (lease_file->exists()) { - LeaseFileLoader::load(*lease_file, storage, - MAX_LEASE_ERRORS); - } - lease_file.reset(new LeaseFileType(appendSuffix(filename, FILE_INPUT))); - if (lease_file->exists()) { - LeaseFileLoader::load(*lease_file, storage, - MAX_LEASE_ERRORS); - } - } - - // Always load leases from the primary lease file. If the lease file - // doesn't exist it will be created by the LeaseFileLoader. Note - // that the false value passed as the last parameter to load - // function causes the function to leave the file open after - // it is parsed. This file will be used by the backend to record - // future lease updates. - lease_file.reset(new LeaseFileType(filename)); - LeaseFileLoader::load(*lease_file, storage, - MAX_LEASE_ERRORS, false);; -} +} // end of namespace isc::dhcp +} // end of namespace isc diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 45df609c9c..41e8e3b2ac 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -29,6 +29,8 @@ namespace isc { namespace dhcp { +class LFCSetup; + /// @brief Concrete implementation of a lease database backend using flat file. /// /// This class implements a lease database backend using CSV files to store @@ -105,7 +107,7 @@ public: /// @brief Specifies universe (V4, V6) /// - /// This enumeration is used by various functions in Memfile Lease Manager, + /// This enumeration is used by various functions in Memfile %Lease Manager, /// to identify the lease type referred to. In particular, it is used by /// functions operating on the lease files to distinguish between lease /// files for DHCPv4 and DHCPv6. @@ -114,18 +116,10 @@ public: V6 }; - /// @brief Types of the lease files used by the Lease File Cleanup. - /// - /// This enumeration is used by a method which appends the appropriate - /// suffix to the lease file name. - enum LFCFileType { - FILE_CURRENT, - FILE_INPUT, - FILE_PREVIOUS, - FILE_OUTPUT, - FILE_FINISH, - FILE_PID - }; + /// @name Methods implementing the API of the lease database backend. + /// The following methods are implementing the API of the + /// @c LeaseMgr to manage leases. + //@{ /// @brief The sole lease manager constructor /// @@ -335,12 +329,30 @@ public: /// support transactions, this is a no-op. virtual void rollback(); + //@} + + /// @name Public type and method used to determine file names for LFC. + //@{ + + /// @brief Types of the lease files used by the %Lease File Cleanup. + /// + /// This enumeration is used by a method which appends the appropriate + /// suffix to the lease file name. + enum LFCFileType { + FILE_CURRENT, + FILE_INPUT, + FILE_PREVIOUS, + FILE_OUTPUT, + FILE_FINISH, + FILE_PID + }; + /// @brief Appends appropriate suffix to the file name. /// /// The suffix is selected using the LFC file type specified as a /// parameter. Each file type uses a unique suffix or no suffix: /// - Current File: no suffix - /// - Lease File Copy or Input File: ".1" + /// - %Lease File Copy or Input File: ".1" /// - Previous File: ".2" /// - LFC Output File: ".output" /// - LFC Finish File: ".completed" @@ -353,11 +365,18 @@ public: /// @return A lease file name with a suffix appended. static std::string appendSuffix(const std::string& file_name, const LFCFileType& file_type); + //@} + + + /// @name Miscellaneous public convenience methods. + /// The following methods allow for retrieving useful information + /// about the state of the backend. + //@{ /// @brief Returns the interval at which the @c IOService events should /// be released. /// - /// The Memfile backend may install a timer to execute the Lease File + /// The Memfile backend may install a timer to execute the %Lease File /// Cleanup periodically. If this timer is installed, the method returns /// the LFC interval in milliseconds. /// @@ -393,35 +412,10 @@ public: /// server shut down. bool persistLeases(Universe u) const; -protected: - - /// @brief A callback function triggering Lease File Cleanup. - /// - /// This method is virtual so as it can be overriden and customized in - /// the unit tests. In particular, the unit test which checks that the - /// callback function has been executed would override this function - /// to increase the execution counter each time it is executed. - /// - /// @todo Once the callback is implemented, there is a need to - /// extend the documentation of this method. Currently, it simply - /// logs that it has been called. - virtual void lfcCallback(); + //@} private: - /// @brief Setup the periodic Lease File Cleanup. - /// - /// 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. By default the backend will use - /// the path to the kea-lfc in the Kea installation directory. If - /// the unit tests need to override this path (with the path in the - /// Kea build directory, the @c KEA_LFC_EXECUTABLE environmental - /// variable should be set to hold an absolute path to the kea-lfc - /// excutable. - void lfcSetup(); /// @brief Initialize the location of the lease file. /// @@ -440,31 +434,6 @@ private: /// argument to this function. std::string initLeaseFilePath(Universe u); - /// @brief Performs a lease file cleanup for DHCPv4 or DHCPv6. - /// - /// This method performs all the actions necessary to prepare for the - /// execution of the LFC and if these actions are sucessful, it executes - /// the @c kea-lfc application as a background process to process (cleanup) - /// the lease files. - /// - /// For the design and the terminology used in this description refer to - /// the http://kea.isc.org/wiki/LFCDesign. - /// - /// If the method finds that the Lease File Copy exists it simply runs - /// the @c kea-lfc application. - /// - /// If the Lease File Copy doesn't exist it moves the Current Lease File - /// to Lease File Copy, and then recreates the Current Lease File without - /// any lease entries. If the file has been successfully moved, it runs - /// the @c kea-lfc application. - /// - /// @param lease_file A pointer to the object representing the Current - /// Lease File (DHCPv4 or DHCPv6 lease file). - /// - /// @tparam LeaseFileType One of @c CSVLeaseFile4 or @c CSVLeaseFile6. - template - void leaseFileCleanup(boost::shared_ptr& lease_file); - /// @brief Load leases from the persistent storage. /// /// This method loads DHCPv4 or DHCPv6 leases from lease files in the @@ -492,7 +461,7 @@ private: /// /// @note: When the server starts up or is reconfigured it will try to /// read leases from the lease files using this method. It is possible - /// that the Lease File Cleanup is performed upon the lease files to + /// that the %Lease File Cleanup is performed upon the lease files to /// be read by this method. This may result in conflicts between the /// server process and the LFC. To prevent it, the method checks if the /// instance of the @c kea-lfc is running (using the PID file) before it @@ -533,19 +502,93 @@ private: /// @brief Holds the pointer to the DHCPv6 lease file IO. boost::shared_ptr lease_file6_; - /// @brief A timer scheduled to perform Lease File Cleanup. - asiolink::IntervalTimer lfc_timer_; +public: + + /// @name Public methods to retrieve information about the LFC process state. + /// These methods are meant to be used by unit tests to retrieve the + /// state of the spawned LFC process before validating the result of + /// the lease file cleanup. + //@{ + + /// @brief Checks if the process performing lease file cleanup is running. + /// + /// @return true if the process performing lease file cleanup is running. + bool isLFCRunning() const; + + /// @brief Returns the status code returned by the last executed + /// LFC process. + int getLFCExitStatus() const; + //@} + + + /// @name Protected methods used for %Lease File Cleanup. + /// The following methods are protected so as they can be accessed and + /// tested by unit tests. + //@{ protected: - /// @brief An object representing the kea-lfc process. + /// @brief A callback function triggering %Lease File Cleanup (LFC). + /// + /// This method is executed periodically to start the lease file cleanup. + /// It checks whether the file is a DHCPv4 lease file or DHCPv6 lease file + /// and executes the @c Memfile_LeaseMgr::lfcExecute private method + /// with the appropriate parameters. + /// + /// This method is virtual so as it can be overridden and customized in + /// the unit tests. In particular, the unit test which checks that the + /// callback function has been executed would override this function + /// to increase the execution counter each time it is executed. + virtual void lfcCallback(); + //@} + + /// @name Private methods and members used for %Lease File Cleanup. + //@{ + +private: + + /// @brief Setup the periodic %Lease File Cleanup. /// - /// This object is created when the LFC is configured to be executed - /// periodically. It holds the path to kea-lfc program and the - /// arguments. When the LFC timer kicks the lease file cleanup - /// this object is used to spawn the kea-lfc as a background - /// process. - boost::scoped_ptr lfc_process_; + /// 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. By default the backend will use + /// the path to the kea-lfc in the Kea installation directory. If + /// the unit tests need to override this path (with the path in the + /// Kea build directory, the @c KEA_LFC_EXECUTABLE environmental + /// variable should be set to hold an absolute path to the kea-lfc + /// excutable. + void lfcSetup(); + + /// @brief Performs a lease file cleanup for DHCPv4 or DHCPv6. + /// + /// This method performs all the actions necessary to prepare for the + /// execution of the LFC and if these actions are successful, it executes + /// the @c kea-lfc application as a background process to process (cleanup) + /// the lease files. + /// + /// For the design and the terminology used in this description refer to + /// the http://kea.isc.org/wiki/LFCDesign. + /// + /// If the method finds that the %Lease File Copy exists it simply runs + /// the @c kea-lfc application. + /// + /// If the %Lease File Copy doesn't exist it moves the Current %Lease File + /// to Lease File Copy, and then recreates the Current Lease File without + /// any lease entries. If the file has been successfully moved, it runs + /// the @c kea-lfc application. + /// + /// @param lease_file A pointer to the object representing the Current + /// %Lease File (DHCPv4 or DHCPv6 lease file). + /// + /// @tparam LeaseFileType One of @c CSVLeaseFile4 or @c CSVLeaseFile6. + template + void lfcExecute(boost::shared_ptr& lease_file); + + /// @brief A pointer to the Lease File Cleanup configuration. + boost::scoped_ptr lfc_setup_; + //@} }; diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc index 57fc668e99..ad4b34994c 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc @@ -94,7 +94,6 @@ public: } using Memfile_LeaseMgr::lfcCallback; - using Memfile_LeaseMgr::lfc_process_; }; /// @brief Test fixture class for @c Memfile_LeaseMgr @@ -227,11 +226,11 @@ public: /// @param timeout Timeout in seconds. /// /// @return true if the process ended, false otherwise - bool waitForProcess(const util::ProcessSpawn& process, + bool waitForProcess(const Memfile_LeaseMgr& lease_mgr, const uint8_t timeout) { uint32_t iterations = 0; const uint32_t iterations_max = timeout * 1000; - while (process.isRunning() && (iterations < iterations_max)) { + while (lease_mgr.isLFCRunning() && (iterations < iterations_max)) { usleep(1000); ++iterations; } @@ -439,10 +438,12 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup4) { EXPECT_EQ(new_file_contents, current_file.readFile()); // Wait for the LFC process to complete. - ASSERT_TRUE(waitForProcess(*lease_mgr->lfc_process_, 2)); + ASSERT_TRUE(waitForProcess(*lease_mgr, 2)); // And make sure it has returned an exit status of 0. - EXPECT_EQ(0, lease_mgr->lfc_process_->getExitStatus()); + EXPECT_EQ(0, lease_mgr->getLFCExitStatus()) + << "Executing the LFC process failed: make sure that" + " the kea-lfc program has been compiled."; // Check if we can still write to the lease file. std::vector hwaddr_vec(6); @@ -515,10 +516,13 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup6) { EXPECT_EQ(new_file_contents, current_file.readFile()); // Wait for the LFC process to complete. - ASSERT_TRUE(waitForProcess(*lease_mgr->lfc_process_, 2)); + ASSERT_TRUE(waitForProcess(*lease_mgr, 2)); // And make sure it has returned an exit status of 0. - EXPECT_EQ(0, lease_mgr->lfc_process_->getExitStatus()); + EXPECT_EQ(0, lease_mgr->getLFCExitStatus()) + << "Executing the LFC process failed: make sure that" + " the kea-lfc program has been compiled."; + // Check if we can still write to the lease file. std::vector duid_vec(13); @@ -578,10 +582,12 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanupStartFail) { ASSERT_NO_THROW(lease_mgr->lfcCallback()); // Wait for the LFC process to complete. - ASSERT_TRUE(waitForProcess(*lease_mgr->lfc_process_, 2)); + ASSERT_TRUE(waitForProcess(*lease_mgr, 2)); // And make sure it has returned an error. - EXPECT_EQ(EXIT_FAILURE, lease_mgr->lfc_process_->getExitStatus()); + EXPECT_EQ(EXIT_FAILURE, lease_mgr->getLFCExitStatus()) + << "Executing the LFC process failed: make sure that" + " the kea-lfc program has been compiled."; } // Test that the backend returns a correct value of the interval -- 2.47.3