]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[3534] It is now possible to revert to a selected previous configuration.
authorMarcin Siodelski <marcin@isc.org>
Mon, 1 Sep 2014 15:32:47 +0000 (17:32 +0200)
committerMarcin Siodelski <marcin@isc.org>
Mon, 1 Sep 2014 15:32:47 +0000 (17:32 +0200)
src/lib/dhcpsrv/cfgmgr.cc
src/lib/dhcpsrv/cfgmgr.h
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc

index 0176fc0e500014a921603164d483238266811a75..8145587b6d0b10b2fd4a6180e5bb7e8c12781a0e 100644 (file)
@@ -396,6 +396,39 @@ CfgMgr::rollback() {
     }
 }
 
+void
+CfgMgr::revert(const size_t index) {
+    ensureCurrentAllocated();
+    if (index == 0) {
+        isc_throw(isc::OutOfRange, "invalid commit index 0 when reverting"
+                  " to an old configuration");
+    } else if (index > configs_.size() - 1) {
+        isc_throw(isc::OutOfRange, "unable to revert to commit index '"
+                  << index << "', only '" << configs_.size() - 1
+                  << "' previous commits available");
+    }
+
+    // Let's rollback an existing configuration to make sure that the last
+    // configuration on the list is the current one. Note that all remaining
+    // operations in this function should be exception free so there shouldn't
+    // be a problem that the revert operation fails and the staging
+    // configuration is destroyed by this rollback.
+    rollback();
+
+    // Get the iterator to the current configuration and then advance to the
+    // desired one.
+    ConfigurationList::const_reverse_iterator it = configs_.rbegin();
+    std::advance(it, index);
+
+    // Copy the desired configuration to the new staging configuration. The
+    // staging configuration is re-created here because we rolled back earlier
+    // in this function.
+    (*it)->copy(*getStagingCfg());
+
+    // Make the staging configuration a current one.
+    commit();
+}
+
 ConstConfigurationPtr
 CfgMgr::getCurrentCfg() {
     ensureCurrentAllocated();
index 1baaeab843cc9f8a906298a71484fa855bd7d99e..42509ee00eb9fcef077d864aa545584f11b99723 100644 (file)
@@ -424,6 +424,23 @@ public:
     /// This function is exception safe.
     void rollback();
 
+    /// @brief Reverts to one of the previous configurations.
+    ///
+    /// This function reverts to selected previous configuration. The previous
+    /// configuration is entirely copied to a new @c Configuration instance. This
+    /// new instance has a unique sequence id (sequence id is not copied). The
+    /// previous configuration (being copied) is not modified by this operation.
+    ///
+    /// The configuration to be copied is identified by the index value which
+    /// is the distance between the current (most recent) and desired
+    /// configuration. If the index is out of range an exception is thrown.
+    ///
+    /// @warning Revert operation will rollback any changes to the staging
+    /// configuration (if it exists).
+    ///
+    /// @throw isc::OutOfRange if the specified index is out of range.
+    void revert(const size_t index);
+
     /// @brief Returns a pointer to the current configuration.
     ///
     /// This function returns pointer to the current configuration. If the
index d3579f7e4f555abe5f18ea92e814bac50e65eb50..5cc8c02fc268fb31d10f4ea409ff5c41866436c3 100644 (file)
@@ -1209,6 +1209,54 @@ TEST_F(CfgMgrTest, staging) {
     EXPECT_EQ(0, config->getLoggingInfo().size());
 }
 
+// This test verifies that it is possible to revert to an old configuration.
+TEST_F(CfgMgrTest, revert) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    // Let's create 5 unique configurations: differing by a debug level in the
+    // range of 10 to 14.
+    for (int i = 0; i < 5; ++i) {
+        ConfigurationPtr config = cfg_mgr.getStagingCfg();
+        LoggingInfo logging_info;
+        logging_info.debuglevel_ = i + 10;
+        config->addLoggingInfo(logging_info);
+        cfg_mgr.commit();
+    }
+
+    // Now we have 5 configurations with:
+    // - debuglevel = 99 (a default one)
+    // - debuglevel = 10
+    // - debuglevel = 11
+    // - debuglevel = 12
+    // - debuglevel = 13
+    // - debuglevel = 14 (current)
+
+    // Hence, the maximum index of the configuration to revert is 5 (which
+    // points to the configuration with debuglevel = 99). For the index greater
+    // than 5 we should get an exception.
+    ASSERT_THROW(cfg_mgr.revert(6), isc::OutOfRange);
+    // Value of 0 also doesn't make sense.
+    ASSERT_THROW(cfg_mgr.revert(0), isc::OutOfRange);
+
+    // We should be able to revert to configuration with debuglevel = 10.
+    ASSERT_NO_THROW(cfg_mgr.revert(4));
+    // And this configuration should be now the current one and the debuglevel
+    // of this configuration is 10.
+    EXPECT_EQ(10, cfg_mgr.getCurrentCfg()->getLoggingInfo()[0].debuglevel_);
+
+    // The new set of configuration is now as follows:
+    // - debuglevel = 99
+    // - debuglevel = 10
+    // - debuglevel = 11
+    // - debuglevel = 12
+    // - debuglevel = 13
+    // - debuglevel = 14
+    // - debuglevel = 10 (current)
+    // So, reverting to configuration having index 3 means that the debug level
+    // of the current configuration will become 12.
+    ASSERT_NO_THROW(cfg_mgr.revert(3));
+    EXPECT_EQ(12, cfg_mgr.getCurrentCfg()->getLoggingInfo()[0].debuglevel_);
+}
+
 /// @todo Add unit-tests for testing:
 /// - addActiveIface() with invalid interface name
 /// - addActiveIface() with the same interface twice