From: Francis Dupont Date: Thu, 11 Sep 2025 14:23:21 +0000 (+0200) Subject: [#4094] Checkpoint: UT needed X-Git-Tag: Kea-3.1.2~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=68113af72ddc29fdbe2b22c46ced1e8370adaedc;p=thirdparty%2Fkea.git [#4094] Checkpoint: UT needed --- diff --git a/doc/sphinx/arm/ctrl-channel.rst b/doc/sphinx/arm/ctrl-channel.rst index 652fa525af..3405fd2788 100644 --- a/doc/sphinx/arm/ctrl-channel.rst +++ b/doc/sphinx/arm/ctrl-channel.rst @@ -890,6 +890,18 @@ command-line argument. This command does not take any parameters. "command": "version-get" } +.. isccmd:: kea-lfc-start +.. _command-kea-lfc-start: + +The ``kea-lfc-start`` Command +----------------------------- + +The isccmd:`kea-lfc-start` command starts the ``kea-lfc`` process which +cleans up the lease file (see :ref:`kea-lfc`). It takes no argument and +returns an error when the lease backend is not the ``memfile`` or when +the ``persist`` parameter of the ``lease-database`` was configured to +``false`` (but not when ``lfc-interval`` is ``0``). + Commands Supported by the DHCPv4 Server ======================================= diff --git a/doc/sphinx/arm/lfc.rst b/doc/sphinx/arm/lfc.rst index f28756ad16..3d824e6d6a 100644 --- a/doc/sphinx/arm/lfc.rst +++ b/doc/sphinx/arm/lfc.rst @@ -14,7 +14,8 @@ the files used to provide persistent storage for the memfile database backend. This service is written to run as a standalone process. While :iscman:`kea-lfc` can be started externally, there is usually no need to -do so. :iscman:`kea-lfc` is run on a periodic basis by the Kea DHCP servers. +do so. :iscman:`kea-lfc` is run on a periodic basis by the Kea DHCP servers, +and since Kea 3.1.2 can be started using the ``kea-lfc-start`` command. The process operates on a set of files, using them to receive input and output of the lease entries and to indicate what stage the process is diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc index 41b64d7eee..a013dd9532 100644 --- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc +++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc @@ -1212,6 +1212,15 @@ ControlledDhcpv4Srv::commandStatisticSetMaxSampleAgeAllHandler(const string&, return (answer); } +ConstElementPtr +ControlledDhcpv4Srv::commandLfcStartHandler(const string&, ConstElementPtr) { + if (LeaseMgrFactory::haveInstance()) { + return (LeaseMgrFactory::instance().lfcStartHandler()); + } + return (createAnswer(CONTROL_RESULT_COMMAND_UNSUPPORTED, + "no lease backend")); +} + isc::data::ConstElementPtr ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) { ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance(); @@ -1510,6 +1519,9 @@ ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t server_port /*= DHCP4_SERVER_P CommandMgr::instance().registerCommand("dhcp-disable", std::bind(&ControlledDhcpv4Srv::commandDhcpDisableHandler, this, ph::_1, ph::_2)); + CommandMgr::instance().registerCommand("kea-lfc-start", + std::bind(&ControlledDhcpv4Srv::commandLfcStartHandler, this, ph::_1, ph::_2)); + CommandMgr::instance().registerCommand("leases-reclaim", std::bind(&ControlledDhcpv4Srv::commandLeasesReclaimHandler, this, ph::_1, ph::_2)); @@ -1603,6 +1615,7 @@ ControlledDhcpv4Srv::~ControlledDhcpv4Srv() { CommandMgr::instance().deregisterCommand("config-write"); CommandMgr::instance().deregisterCommand("dhcp-disable"); CommandMgr::instance().deregisterCommand("dhcp-enable"); + CommandMgr::instance().deregisterCommand("kea-lfc-start"); CommandMgr::instance().deregisterCommand("leases-reclaim"); CommandMgr::instance().deregisterCommand("subnet4-select-test"); CommandMgr::instance().deregisterCommand("subnet4o6-select-test"); diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.h b/src/bin/dhcp4/ctrl_dhcp4_srv.h index b2f5a98fed..445a5df026 100644 --- a/src/bin/dhcp4/ctrl_dhcp4_srv.h +++ b/src/bin/dhcp4/ctrl_dhcp4_srv.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -368,6 +369,19 @@ private: commandStatisticSetMaxSampleAgeAllHandler(const std::string& command, isc::data::ConstElementPtr args); + /// @brief handler for processing 'kea-lfc-start' command + /// + /// This handler processes kea-lfc-start command, which cleans up + /// the lease file (the backup file of the memfile lease backend). + /// @ref isc::dhcp::LeaseMgr::lfcStartHandler + /// + /// @param command (ignored) + /// @param args (ignored) + /// @return process information wrapped in a response + isc::data::ConstElementPtr + commandLfcStartHandler(const std::string& command, + isc::data::ConstElementPtr args); + /// @brief Reclaims expired IPv4 leases and reschedules timer. /// /// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases4. diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc index c7d9b072fb..b3b9868207 100644 --- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc +++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc @@ -979,6 +979,15 @@ ControlledDhcpv6Srv::commandStatisticSetMaxSampleAgeAllHandler(const string&, return (answer); } +ConstElementPtr +ControlledDhcpv6Srv::commandLfcStartHandler(const string&, ConstElementPtr) { + if (LeaseMgrFactory::haveInstance()) { + return (LeaseMgrFactory::instance().lfcStartHandler()); + } + return (createAnswer(CONTROL_RESULT_COMMAND_UNSUPPORTED, + "no lease backend")); +} + isc::data::ConstElementPtr ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) { ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance(); @@ -1300,6 +1309,9 @@ ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t server_port /*= DHCP6_SERVER_P CommandMgr::instance().registerCommand("dhcp-disable", std::bind(&ControlledDhcpv6Srv::commandDhcpDisableHandler, this, ph::_1, ph::_2)); + CommandMgr::instance().registerCommand("kea-lfc-start", + std::bind(&ControlledDhcpv6Srv::commandLfcStartHandler, this, ph::_1, ph::_2)); + CommandMgr::instance().registerCommand("leases-reclaim", std::bind(&ControlledDhcpv6Srv::commandLeasesReclaimHandler, this, ph::_1, ph::_2)); @@ -1390,6 +1402,7 @@ ControlledDhcpv6Srv::~ControlledDhcpv6Srv() { CommandMgr::instance().deregisterCommand("config-write"); CommandMgr::instance().deregisterCommand("dhcp-disable"); CommandMgr::instance().deregisterCommand("dhcp-enable"); + CommandMgr::instance().deregisterCommand("kea-lfc-start"); CommandMgr::instance().deregisterCommand("leases-reclaim"); CommandMgr::instance().deregisterCommand("subnet6-select-test"); CommandMgr::instance().deregisterCommand("server-tag-get"); diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.h b/src/bin/dhcp6/ctrl_dhcp6_srv.h index 0fc5118cd1..23183fa05c 100644 --- a/src/bin/dhcp6/ctrl_dhcp6_srv.h +++ b/src/bin/dhcp6/ctrl_dhcp6_srv.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -355,6 +356,19 @@ private: commandStatisticSetMaxSampleAgeAllHandler(const std::string& command, isc::data::ConstElementPtr args); + /// @brief handler for processing 'kea-lfc-start' command + /// + /// This handler processes kea-lfc-start command, which cleans up + /// the lease file (the backup file of the memfile lease backend). + /// @ref isc::dhcp::LeaseMgr::lfcStartHandler + /// + /// @param command (ignored) + /// @param args (ignored) + /// @return process information wrapped in a response + isc::data::ConstElementPtr + commandLfcStartHandler(const std::string& command, + isc::data::ConstElementPtr args); + /// @brief Reclaims expired IPv6 leases and reschedules timer. /// /// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases6. diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.cc b/src/lib/dhcpsrv/dhcpsrv_messages.cc index 9dea368556..3f106c6394 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.cc +++ b/src/lib/dhcpsrv/dhcpsrv_messages.cc @@ -133,6 +133,7 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_LEASE_LOAD_ROW_ERROR = "DHCPSRV extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_EXECUTE = "DHCPSRV_MEMFILE_LFC_EXECUTE"; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL = "DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL"; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL = "DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL"; +extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_RESCHEDULED = "DHCPSRV_MEMFILE_LFC_RESCHEDULED"; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SETUP = "DHCPSRV_MEMFILE_LFC_SETUP"; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SPAWN_FAIL = "DHCPSRV_MEMFILE_LFC_SPAWN_FAIL"; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_START = "DHCPSRV_MEMFILE_LFC_START"; @@ -313,6 +314,7 @@ const char* values[] = { "DHCPSRV_MEMFILE_LFC_EXECUTE", "executing Lease File Cleanup using: %1", "DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL", "failed to rename the current lease file %1 to %2, reason: %3", "DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL", "failed to reopen lease file %1 after preparing input file for lease file cleanup, reason: %2, new leases will not persist!", + "DHCPSRV_MEMFILE_LFC_RESCHEDULED", "rescheduled Lease File Cleanup", "DHCPSRV_MEMFILE_LFC_SETUP", "setting up the Lease File Cleanup interval to %1 sec", "DHCPSRV_MEMFILE_LFC_SPAWN_FAIL", "lease file cleanup failed to run because kea-lfc process couldn't be spawned", "DHCPSRV_MEMFILE_LFC_START", "starting Lease File Cleanup", diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.h b/src/lib/dhcpsrv/dhcpsrv_messages.h index 926efc9bb6..7f6fc855cc 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.h +++ b/src/lib/dhcpsrv/dhcpsrv_messages.h @@ -134,6 +134,7 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_LEASE_LOAD_ROW_ERROR; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_EXECUTE; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_RENAME_FAIL; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_LEASE_FILE_REOPEN_FAIL; +extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_RESCHEDULED; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SETUP; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_SPAWN_FAIL; extern const isc::log::MessageID DHCPSRV_MEMFILE_LFC_START; diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index 81806625e5..8bdd6dcfbe 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -748,6 +748,11 @@ failed to re-open or re-create the lease file after renaming the lease file for lease file cleanup. The server continues to operate but leases do not persist to disk. +% DHCPSRV_MEMFILE_LFC_RESCHEDULED rescheduled Lease File Cleanup +An informational message issued when the memfile lease database backend +rescheduled the periodic Lease File Cleanup at the reception of a +"kea-lfc-start" command. + % DHCPSRV_MEMFILE_LFC_SETUP setting up the Lease File Cleanup interval to %1 sec An informational message logged when the memfile lease database backend configures the LFC to be executed periodically. The argument holds the diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc index 9ac34b8bda..9994cd1f61 100644 --- a/src/lib/dhcpsrv/lease_mgr.cc +++ b/src/lib/dhcpsrv/lease_mgr.cc @@ -6,6 +6,7 @@ #include +#include #include #include #include @@ -29,6 +30,7 @@ #include using namespace isc::asiolink; +using namespace isc::config; using namespace isc::data; using namespace isc::db; using namespace isc::dhcp; @@ -1304,5 +1306,12 @@ LeaseMgr::byRemoteId6size() const { return (0); } +ConstElementPtr +LeaseMgr::lfcStartHandler() { + ostringstream msg; + msg << "lease backend `" << getName() << "' is not 'memfile'"; + return (createAnswer(CONTROL_RESULT_COMMAND_UNSUPPORTED, msg.str())); +} + } // namespace isc::dhcp } // namespace isc diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h index 364ffd65ff..7610e39042 100644 --- a/src/lib/dhcpsrv/lease_mgr.h +++ b/src/lib/dhcpsrv/lease_mgr.h @@ -1065,6 +1065,13 @@ public: /// @return Always 0. virtual size_t byRemoteId6size() const; + /// @brief Handler for kea-lfc-start command. + /// + /// Derived by the memfile backend. + /// + /// @returns By default an error saying the backend is not the memfile one. + virtual isc::data::ConstElementPtr lfcStartHandler(); + protected: /// Extended information / Bulk Lease Query shared interface. diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 00371308da..92d804d492 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -42,6 +43,7 @@ const char* KEA_LFC_EXECUTABLE_ENV_NAME = "KEA_LFC_EXECUTABLE"; } // namespace using namespace isc::asiolink; +using namespace isc::config; using namespace isc::data; using namespace isc::db; using namespace isc::util; @@ -2465,8 +2467,6 @@ Memfile_LeaseMgr::getLFCExitStatus() const { void Memfile_LeaseMgr::lfcCallback() { - LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_START); - // Check if we're in the v4 or v6 space and use the appropriate file. if (lease_file4_) { MultiThreadingCriticalSection cs; @@ -2494,15 +2494,15 @@ Memfile_LeaseMgr::lfcSetup(bool conversion_needed) { << lfc_interval_str << " specified"); } - if (lfc_interval > 0 || conversion_needed) { - lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this))); - lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed); - } + lfc_setup_.reset(new LFCSetup(std::bind(&Memfile_LeaseMgr::lfcCallback, this))); + lfc_setup_->setup(lfc_interval, lease_file4_, lease_file6_, conversion_needed); } template void Memfile_LeaseMgr::lfcExecute(boost::shared_ptr& lease_file) { + LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_START); + bool do_lfc = true; // Check the status of the LFC instance. @@ -2561,6 +2561,29 @@ Memfile_LeaseMgr::lfcExecute(boost::shared_ptr& lease_file) { } } +ConstElementPtr +Memfile_LeaseMgr::lfcStartHandler() { + if (!persistLeases(V4) && !persistLeases(V6)) { + std::ostringstream msg; + msg << "'persist` parameter of `memfile` lease backend " + << "was configured to `false`"; + return (createAnswer(CONTROL_RESULT_COMMAND_UNSUPPORTED, msg.str())); + } + MultiThreadingCriticalSection cs; + // Reschedule the periodic lfc run. + if (TimerMgr::instance()->isTimerRegistered("memfile-lfc")) { + TimerMgr::instance()->cancel("memfile-lfc"); + TimerMgr::instance()->setup("memfile-lfc"); + LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LFC_RESCHEDULED); + } + if (lease_file4_) { + lfcExecute(lease_file4_); + } else if (lease_file6_) { + lfcExecute(lease_file6_); + } + return (createAnswer(CONTROL_RESULT_SUCCESS, "kea-lfc started")); +} + LeaseStatsQueryPtr Memfile_LeaseMgr::startLeaseStatsQuery4() { LeaseStatsQueryPtr query(new MemfileLeaseStatsQuery4(storage4_)); diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index cd3213ec9b..6a2ae69616 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -1552,6 +1552,11 @@ public: /// @return Always return 0 as this function is a noop for not SQL backends. virtual size_t upgradeExtendedInfo4(const LeasePageSize& page_size) override; + /// @brief Handler for kea-lfc-start command. + /// + /// @returns Status of command. + virtual isc::data::ConstElementPtr lfcStartHandler() override; + protected: /// Extended information / Bulk Lease Query shared interface. diff --git a/src/share/api/kea-lfc-start.json b/src/share/api/kea-lfc-start.json new file mode 100644 index 0000000000..356b187f91 --- /dev/null +++ b/src/share/api/kea-lfc-start.json @@ -0,0 +1,19 @@ +{ + "access": "write", + "avail": "3.1.2", + "brief": [ + "This command starts the kea-lfc process which cleas nup the lease file. ", + "This command does not take any parameters." + ], + "cmd-syntax": [ + "{", + " \"command\": \"kea-lfc-start\"", + "}" + ], + "description": "See ", + "name": "kea-lfc-start", + "support": [ + "kea-dhcp4", + "kea-dhcp6" + ] +}