Use atomic discards for the operational DS
Port away from sysrepo::Connection::discardOperationalChanges() because
sysrepo now supports discarding via the usual sr_edit_batch(), yay.
The actual changes are slightly different, some high-level leaf-list
instances for example are apparently not reported.
Change-Id: I3c4f7e5aabe65c52f557c4cd060e0a6fbc316e16
Depends-on: https://gerrit.cesnet.cz/c/CzechLight/dependencies/+/6243
Depends-on: https://gerrit.cesnet.cz/c/CzechLight/sysrepo-ietf-alarms/+/6248
diff --git a/src/ietf-hardware/sysrepo/Sysrepo.cpp b/src/ietf-hardware/sysrepo/Sysrepo.cpp
index 444a714..b06a72e 100644
--- a/src/ietf-hardware/sysrepo/Sysrepo.cpp
+++ b/src/ietf-hardware/sysrepo/Sysrepo.cpp
@@ -60,11 +60,11 @@
}
}
- for (const auto& component : deletedComponents) {
- conn.discardOperationalChanges(component);
- }
+ std::vector<std::string> discards;
+ discards.reserve(deletedComponents.size());
+ std::copy(deletedComponents.begin(), deletedComponents.end(), std::back_inserter(discards));
- utils::valuesPush(hwStateValues, {}, m_session, ::sysrepo::Datastore::Operational);
+ utils::valuesPush(hwStateValues, {}, discards, m_session, ::sysrepo::Datastore::Operational);
prevValues = std::move(hwStateValues);
std::this_thread::sleep_for(m_pollInterval);
diff --git a/src/system/Firmware.cpp b/src/system/Firmware.cpp
index 9c34aeb..1e6bca5 100644
--- a/src/system/Firmware.cpp
+++ b/src/system/Firmware.cpp
@@ -43,7 +43,7 @@
std::optional<libyang::DataNode> dataNode;
auto session = m_srConn.sessionStart();
- utils::valuesToYang(data, {}, session, dataNode);
+ utils::valuesToYang(data, {}, {}, session, dataNode);
session.sendNotification(*dataNode, sysrepo::Wait::No); // No need to wait, it's just a notification.
},
[this](int32_t retVal, const std::string& lastError) {
@@ -131,7 +131,7 @@
data[CZECHLIGHT_SYSTEM_FIRMWARE_MODULE_PREFIX + "installation/message"] = m_installMessage;
}
- utils::valuesToYang(data, {}, session, parent);
+ utils::valuesToYang(data, {}, {}, session, parent);
return ::sysrepo::ErrorCode::Ok;
};
diff --git a/src/system/IETFInterfaces.cpp b/src/system/IETFInterfaces.cpp
index 1aab3f7..0dd3d30 100644
--- a/src/system/IETFInterfaces.cpp
+++ b/src/system/IETFInterfaces.cpp
@@ -204,7 +204,7 @@
values[yangPrefix + "/out-errors"] = std::to_string(rtnl_link_get_stat(link.get(), RTNL_LINK_TX_ERRORS));
}
- utils::valuesToYang(values, {}, session, parent);
+ utils::valuesToYang(values, {}, {}, session, parent);
return sysrepo::ErrorCode::Ok;
};
@@ -212,14 +212,14 @@
m_srSubscribe->onOperGet(
IETF_INTERFACES_MODULE_NAME, [this](auto session, auto, auto, auto, auto, auto, auto& parent) {
- utils::valuesToYang(collectNeighboursIP(m_rtnetlink, AF_INET, m_log), {}, session, parent);
+ utils::valuesToYang(collectNeighboursIP(m_rtnetlink, AF_INET, m_log), {}, {}, session, parent);
return sysrepo::ErrorCode::Ok;
},
IETF_INTERFACES + "/interface/ietf-ip:ipv4/neighbor");
m_srSubscribe->onOperGet(
IETF_INTERFACES_MODULE_NAME, [this](auto session, auto, auto, auto, auto, auto, auto& parent) {
- utils::valuesToYang(collectNeighboursIP(m_rtnetlink, AF_INET6, m_log), {}, session, parent);
+ utils::valuesToYang(collectNeighboursIP(m_rtnetlink, AF_INET6, m_log), {}, {}, session, parent);
return sysrepo::ErrorCode::Ok;
},
IETF_INTERFACES + "/interface/ietf-ip:ipv6/neighbor");
@@ -232,7 +232,7 @@
if (action == NL_ACT_DEL) {
std::lock_guard<std::mutex> lock(m_mtx);
- utils::valuesPush(std::vector<utils::YANGPair>{}, {IETF_INTERFACES + "/interface[name='" + name + "']"}, m_srSession, sysrepo::Datastore::Operational);
+ utils::valuesPush(std::vector<utils::YANGPair>{}, {IETF_INTERFACES + "/interface[name='" + name + "']"}, {}, m_srSession, sysrepo::Datastore::Operational);
} else if (action == NL_ACT_CHANGE || action == NL_ACT_NEW) {
std::map<std::string, std::string> values;
std::vector<std::string> deletePaths;
@@ -252,7 +252,7 @@
values[IETF_INTERFACES + "/interface[name='" + name + "']/oper-status"] = operStatusToString(rtnl_link_get_operstate(link), m_log);
std::lock_guard<std::mutex> lock(m_mtx);
- utils::valuesPush(values, deletePaths, m_srSession, sysrepo::Datastore::Operational);
+ utils::valuesPush(values, deletePaths, {}, m_srSession, sysrepo::Datastore::Operational);
} else {
m_log->warn("Unhandled cache update action {} ({})", action, nlActionToString(action));
}
@@ -287,7 +287,7 @@
}
std::lock_guard<std::mutex> lock(m_mtx);
- utils::valuesPush(values, deletePaths, m_srSession, sysrepo::Datastore::Operational);
+ utils::valuesPush(values, deletePaths, {}, m_srSession, sysrepo::Datastore::Operational);
}
void IETFInterfaces::onRouteUpdate(rtnl_route*, int)
@@ -404,6 +404,6 @@
}
std::lock_guard<std::mutex> lock(m_mtx);
- utils::valuesPush(values, {}, m_srSession, sysrepo::Datastore::Operational);
+ utils::valuesPush(values, {}, {}, m_srSession, sysrepo::Datastore::Operational);
}
}
diff --git a/src/system/IETFSystem.cpp b/src/system/IETFSystem.cpp
index 8595465..5439d09 100644
--- a/src/system/IETFSystem.cpp
+++ b/src/system/IETFSystem.cpp
@@ -132,7 +132,7 @@
{IETF_SYSTEM_STATE_MODULE_PREFIX + "platform/os-version", osReleaseContents.at("VERSION")},
};
- utils::valuesPush(opsSystemStateData, {}, m_srSession, sysrepo::Datastore::Operational);
+ utils::valuesPush(opsSystemStateData, {}, {}, m_srSession, sysrepo::Datastore::Operational);
}
void IETFSystem::initSystemRestart()
@@ -222,7 +222,7 @@
values[IETF_SYSTEM_DNS_PATH + "/server[name='"s + e + "']/udp-and-tcp/address"] = e;
}
- utils::valuesToYang(values, {}, session, parent);
+ utils::valuesToYang(values, {}, {}, session, parent);
return sysrepo::ErrorCode::Ok;
};
diff --git a/src/system/LED.cpp b/src/system/LED.cpp
index 07a9843..35ac43d 100644
--- a/src/system/LED.cpp
+++ b/src/system/LED.cpp
@@ -104,7 +104,7 @@
}
}
- utils::valuesPush(data, {}, m_srSession, sysrepo::Datastore::Operational);
+ utils::valuesPush(data, {}, {}, m_srSession, sysrepo::Datastore::Operational);
std::this_thread::sleep_for(POLL_INTERVAL);
}
diff --git a/src/utils/sysrepo.cpp b/src/utils/sysrepo.cpp
index ddafbac..0147b49 100644
--- a/src/utils/sysrepo.cpp
+++ b/src/utils/sysrepo.cpp
@@ -64,12 +64,12 @@
sr_log_set_cb(spdlog_sr_log_cb);
}
-void valuesToYang(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent)
+void valuesToYang(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent)
{
- valuesToYang(mapToVector(values), removePaths, std::move(session), parent);
+ valuesToYang(mapToVector(values), removePaths, discardPaths, std::move(session), parent);
}
-void valuesToYang(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent)
+void valuesToYang(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent)
{
auto netconf = session.getContext().getModuleImplemented("ietf-netconf");
auto log = spdlog::get("main");
@@ -99,26 +99,39 @@
parent->newPath(propertyName, value, libyang::CreationOptions::Output);
}
}
+
+ for (const auto& propertyName : discardPaths) {
+ log->trace("Processing node discard {}", propertyName);
+
+ auto discard = session.getContext().newOpaqueJSON("sysrepo", "discard-items", libyang::JSON{propertyName});
+
+ if (!parent) {
+ parent = discard;
+ } else {
+ parent->insertSibling(*discard);
+ parent->newPath(propertyName, std::nullopt, libyang::CreationOptions::Opaque);
+ }
+ }
}
/** @brief Set or remove values in Sysrepo's specified datastore. It changes the datastore and after the data are applied, the original datastore is restored. */
-void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session, sysrepo::Datastore datastore)
+void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session, sysrepo::Datastore datastore)
{
auto oldDatastore = session.activeDatastore();
session.switchDatastore(datastore);
- valuesPush(values, removePaths, session);
+ valuesPush(values, removePaths, discardPaths, session);
session.switchDatastore(oldDatastore);
}
/** @brief Set or remove paths in Sysrepo's current datastore. */
-void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session)
+void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session)
{
if (values.empty() && removePaths.empty()) return;
std::optional<libyang::DataNode> edit;
- valuesToYang(values, removePaths, session, edit);
+ valuesToYang(values, removePaths, discardPaths, session, edit);
if (edit) {
session.editBatch(*edit, sysrepo::DefaultOperation::Merge);
@@ -127,24 +140,24 @@
}
/** @brief Set or remove values in Sysrepo's specified datastore. It changes the datastore and after the data are applied, the original datastore is restored. */
-void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, sysrepo::Session session, sysrepo::Datastore datastore)
+void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, sysrepo::Session session, sysrepo::Datastore datastore)
{
auto oldDatastore = session.activeDatastore();
session.switchDatastore(datastore);
- valuesPush(values, removePaths, session);
+ valuesPush(values, removePaths, discardPaths, session);
session.switchDatastore(oldDatastore);
}
/** @brief Set or remove paths in Sysrepo's current datastore. */
-void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, sysrepo::Session session)
+void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, sysrepo::Session session)
{
if (values.empty() && removePaths.empty())
return;
std::optional<libyang::DataNode> edit;
- valuesToYang(values, removePaths, session, edit);
+ valuesToYang(values, removePaths, discardPaths, session, edit);
if (edit) {
session.editBatch(*edit, sysrepo::DefaultOperation::Merge);
diff --git a/src/utils/sysrepo.h b/src/utils/sysrepo.h
index 5f83352..7f8a244 100644
--- a/src/utils/sysrepo.h
+++ b/src/utils/sysrepo.h
@@ -20,13 +20,13 @@
YANGPair(std::string xpath, std::string value);
};
-void valuesToYang(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent);
-void valuesToYang(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent);
+void valuesToYang(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent);
+void valuesToYang(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session, std::optional<libyang::DataNode>& parent);
-void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session);
-void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session);
-void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session, sysrepo::Datastore datastore);
-void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, ::sysrepo::Session session, sysrepo::Datastore datastore);
+void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session);
+void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session);
+void valuesPush(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session, sysrepo::Datastore datastore);
+void valuesPush(const std::vector<YANGPair>& values, const std::vector<std::string>& removePaths, const std::vector<std::string>& discardPaths, ::sysrepo::Session session, sysrepo::Datastore datastore);
void initLogsSysrepo();
void ensureModuleImplemented(::sysrepo::Session session, const std::string& module, const std::string& revision);