utils: Allow to remove values from sysrepo
Allow removing nodes in valuesPush so we can change and/or remove some
values from Sysrepo in one go.
The deletion of a node is implemented as NETCONF (RFC 6241 [1]) "remove"
operation. The remove operation deletes the data if present. If not, the
operation is a no-op.
If "delete" operation was used, the data would be removed (if present)
too. But if the data are not present it would result in an error [1].
We'd like to avoid the error without implementing a function that checks
if the data are present (see next commits).
[1] https://tools.ietf.org/html/rfc6241#page-38
Change-Id: Id4a0a83265f36a7bdac30a1c2d8247d25551d598
diff --git a/src/utils/sysrepo.cpp b/src/utils/sysrepo.cpp
index bd1b506..9716a6e 100644
--- a/src/utils/sysrepo.cpp
+++ b/src/utils/sysrepo.cpp
@@ -51,8 +51,34 @@
sr_log_set_cb(spdlog_sr_log_cb);
}
-void valuesToYang(const std::map<std::string, std::string>& values, std::shared_ptr<::sysrepo::Session> session, std::shared_ptr<libyang::Data_Node>& parent)
+void valuesToYang(const std::map<std::string, std::string>& values, const std::vector<std::string>& removePaths, std::shared_ptr<::sysrepo::Session> session, std::shared_ptr<libyang::Data_Node>& parent)
{
+ auto netconf = session->get_context()->get_module("ietf-netconf");
+
+ for (const auto& propertyName : removePaths) {
+ if (!parent) {
+ parent = std::make_shared<libyang::Data_Node>(
+ session->get_context(),
+ propertyName.c_str(),
+ nullptr,
+ LYD_ANYDATA_CONSTSTRING,
+ LYD_PATH_OPT_EDIT);
+ } else {
+ parent->new_path(
+ session->get_context(),
+ propertyName.c_str(),
+ nullptr,
+ LYD_ANYDATA_CONSTSTRING,
+ LYD_PATH_OPT_EDIT);
+ }
+
+ auto deletion = parent->find_path(propertyName.c_str());
+ if (deletion->number() != 1) {
+ throw std::logic_error {"Cannot find XPath " + propertyName + " for deletion in libyang's new_path() output"};
+ }
+ deletion->data()[0]->insert_attr(netconf, "operation", "remove");
+ }
+
for (const auto& [propertyName, value] : values) {
if (!parent) {
parent = std::make_shared<libyang::Data_Node>(
@@ -72,23 +98,23 @@
}
}
-/** @brief Set values into 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, std::shared_ptr<::sysrepo::Session> session, sr_datastore_t datastore)
+/** @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, std::shared_ptr<::sysrepo::Session> session, sr_datastore_t datastore)
{
sr_datastore_t oldDatastore = session->session_get_ds();
session->session_switch_ds(datastore);
- valuesPush(values, session);
+ valuesPush(values, removePaths, session);
session->apply_changes();
session->session_switch_ds(oldDatastore);
}
-/** @brief Set values into Sysrepo's current datastore. */
-void valuesPush(const std::map<std::string, std::string>& values, std::shared_ptr<::sysrepo::Session> session)
+/** @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, std::shared_ptr<::sysrepo::Session> session)
{
libyang::S_Data_Node edit;
- valuesToYang(values, session, edit);
+ valuesToYang(values, removePaths, session, edit);
session->edit_batch(edit, "merge");
session->apply_changes();