]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#4094] Checkpoint: UT needed
authorFrancis Dupont <fdupont@isc.org>
Thu, 11 Sep 2025 14:23:21 +0000 (16:23 +0200)
committerFrancis Dupont <fdupont@isc.org>
Mon, 15 Sep 2025 19:44:28 +0000 (21:44 +0200)
14 files changed:
doc/sphinx/arm/ctrl-channel.rst
doc/sphinx/arm/lfc.rst
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp4/ctrl_dhcp4_srv.h
src/bin/dhcp6/ctrl_dhcp6_srv.cc
src/bin/dhcp6/ctrl_dhcp6_srv.h
src/lib/dhcpsrv/dhcpsrv_messages.cc
src/lib/dhcpsrv/dhcpsrv_messages.h
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/lease_mgr.cc
src/lib/dhcpsrv/lease_mgr.h
src/lib/dhcpsrv/memfile_lease_mgr.cc
src/lib/dhcpsrv/memfile_lease_mgr.h
src/share/api/kea-lfc-start.json [new file with mode: 0644]

index 652fa525afa7bfb405d7dbbc522a08681ac0eba7..3405fd2788ce6bcbad5a16f820a0e000f5e4c0e4 100644 (file)
@@ -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
 =======================================
 
index f28756ad16cc01809880f5ef386cc85b1179b71c..3d824e6d6aafcbc10da8dd06c98fc0e4db3729e4 100644 (file)
@@ -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
index 41b64d7eee7719f081999c351c7e145055a8496c..a013dd9532b5a9a0cc26c7b87f0db79513959522 100644 (file)
@@ -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");
index b2f5a98fed1051f43b55028da94ecd2e93dcacf5..445a5df0269c61fa322b47ce3dea320bf9f2817a 100644 (file)
@@ -12,6 +12,7 @@
 #include <cc/data.h>
 #include <cc/command_interpreter.h>
 #include <util/reconnect_ctl.h>
+#include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <dhcp4/dhcp4_srv.h>
 
@@ -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.
index c7d9b072fbc2c719bbf762746d71fbda7a79a2c9..b3b9868207f3295a4c6cf87844bc7565e077aa7d 100644 (file)
@@ -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");
index 0fc5118cd14d855320ac5d933bdd15966d2b1f16..23183fa05cdc9643e711cc0dfce41b3189f0d106 100644 (file)
@@ -12,6 +12,7 @@
 #include <cc/data.h>
 #include <cc/command_interpreter.h>
 #include <util/reconnect_ctl.h>
+#include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/timer_mgr.h>
 #include <dhcp6/dhcp6_srv.h>
 
@@ -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.
index 9dea368556e2917ff6c7db14095bd24085377843..3f106c63945cb676032af8fb8bf4757e3a16a404 100644 (file)
@@ -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",
index 926efc9bb683ab9b5c18be226cfc6b0444f3f554..7f6fc855ccce67d0d074ab4c21682caba0805e48 100644 (file)
@@ -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;
index 81806625e524772ebdad28bc8cea58423eec6469..8bdd6dcfbe21fac7ea780158624acf611a13de51 100644 (file)
@@ -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
index 9ac34b8bdaa518b29b43360999baee7d93b3d91a..9994cd1f611e4fde840abe49af2755f235a83c09 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 
+#include <cc/command_interpreter.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/option_custom.h>
 #include <dhcpsrv/cfgmgr.h>
@@ -29,6 +30,7 @@
 #include <time.h>
 
 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
index 364ffd65ffc762d5ac6a38f779047639714f8839..7610e3904205fe1300d4d00ff5966a2d33d6f811 100644 (file)
@@ -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.
index 00371308dafec5f121688bbb4f5693f2a3095fd5..92d804d492f517b00137b15bad351700e1c9b336 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 
 #include <asiolink/addr_utilities.h>
+#include <cc/command_interpreter.h>
 #include <dhcpsrv/cfg_consistency.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/dhcpsrv_exceptions.h>
@@ -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<typename LeaseFileType>
 void
 Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& 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<LeaseFileType>& 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_));
index cd3213ec9bd118bd6ac8d4b6e4636624b78bcb42..6a2ae69616ae58b1f23d5d170078a1192db5b2ae 100644 (file)
@@ -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 (file)
index 0000000..356b187
--- /dev/null
@@ -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 <xref linkend=\"command-kea-lfc-start\"/>",
+    "name": "kea-lfc-start",
+    "support": [
+        "kea-dhcp4",
+        "kea-dhcp6"
+    ]
+}