Migrate to libyang2
libnetconf2: getSchema and getConfig were no longer used in netconf-cli,
so I deleted them. They can get readded once the bindings get split into
a separate project.
sysrepo_access: Some sr_val stuff was removed.
YangSchema: type descriptions are not available
availableNodes returns only input nodes for RPC nodes
impl_getSchemaNode: no longer disables error printing
libyang: No longer supports leafrefs without the leaf it points to.
Depends-on: https://cesnet-gerrit-czechlight/c/CzechLight/dependencies/+/5171
Depends-on: https://gerrit.cesnet.cz/c/CzechLight/dependencies/+/5171
Change-Id: Ie49381a003a61a7bb028be7b2fa1d9d926ac4e58
diff --git a/tests/mock/sysrepo_subscription.cpp b/tests/mock/sysrepo_subscription.cpp
index 8faffa5..d4827bb 100644
--- a/tests/mock/sysrepo_subscription.cpp
+++ b/tests/mock/sysrepo_subscription.cpp
@@ -21,29 +21,44 @@
{
}
- int operator()(
- sysrepo::S_Session sess,
- [[maybe_unused]] const char* module_name,
- [[maybe_unused]] const char* xpath,
- [[maybe_unused]] sr_event_t event,
- [[maybe_unused]] uint32_t request_id)
+ sysrepo::ErrorCode operator()(
+ sysrepo::Session sess,
+ uint32_t /* sub_id */,
+ std::string_view module_name,
+ std::optional<std::string_view> /* sub_xpath */,
+ sysrepo::Event event,
+ uint32_t /* request_id */)
{
using namespace std::string_literals;
- if (event == SR_EV_CHANGE) {
- return SR_ERR_OK;
+ if (event == sysrepo::Event::Change) {
+ return sysrepo::ErrorCode::Ok;
}
- auto it = sess->get_changes_iter(("/"s + module_name + ":*//.").c_str());
+ for (const auto& it : sess.getChanges(("/"s + module_name.data() + ":*//.").c_str())) {
+ auto xpath = it.node.path();
+ std::optional<std::string> oldValue;
+ std::optional<std::string> newValue;
+ if (it.operation == sysrepo::ChangeOperation::Deleted) {
+ oldValue = it.node.schema().nodeType() == libyang::NodeType::Leaf || it.node.schema().nodeType() == libyang::NodeType::Leaflist ?
+ std::optional<std::string>{it.node.asTerm().valueStr()} :
+ std::nullopt;
+ } else {
+ oldValue = std::optional<std::string>{it.previousValue};
+ newValue = it.node.schema().nodeType() == libyang::NodeType::Leaf || it.node.schema().nodeType() == libyang::NodeType::Leaflist ?
+ std::optional<std::string>{it.node.asTerm().valueStr()} :
+ std::nullopt;
- while (auto change = sess->get_change_next(it)) {
- auto xpath = (change->new_val() ? change->new_val() : change->old_val())->xpath();
+ }
+ std::optional<std::string> previousList;
- auto oldValue = change->old_val() ? std::optional{change->old_val()->val_to_string()} : std::nullopt;
- auto newValue = change->new_val() ? std::optional{change->new_val()->val_to_string()} : std::nullopt;
- m_recorder->write(xpath, oldValue, newValue);
+ if (it.previousList) {
+ previousList = std::string{*it.previousList};
+ }
+
+ m_recorder->write(it.operation, std::string{xpath}, oldValue, newValue, previousList);
}
- return SR_ERR_OK;
+ return sysrepo::ErrorCode::Ok;
}
private:
@@ -55,111 +70,39 @@
DataSupplier::~DataSupplier() = default;
-SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec, sr_datastore_t ds)
- : m_connection(std::make_shared<sysrepo::Connection>())
+SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec, sysrepo::Datastore ds)
+ : m_subscription([&moduleName, &rec, ds] { // This is an immediately invoked lambda.
+ return sysrepo::Connection{}.sessionStart(ds).onModuleChange(moduleName.c_str(),
+ rec ? sysrepo::ModuleChangeCb{MyCallback{moduleName, rec}}
+ : sysrepo::ModuleChangeCb{[](auto, auto, auto, auto, auto, auto) { return sysrepo::ErrorCode::Ok; }});
+ }())
{
- m_session = std::make_shared<sysrepo::Session>(m_connection, ds);
- m_subscription = std::make_shared<sysrepo::Subscribe>(m_session);
- sysrepo::ModuleChangeCb cb;
- if (rec) {
- cb = MyCallback{moduleName, rec};
- } else {
- cb = [](auto, auto, auto, auto, auto) { return SR_ERR_OK; };
- }
-
- m_subscription->module_change_subscribe(moduleName.c_str(), cb);
}
-
-struct leafDataToSysrepoVal {
- leafDataToSysrepoVal(sysrepo::S_Val v, const std::string& xpath)
- : v(v)
- , xpath(xpath)
- {
- }
-
- void operator()(const binary_& what)
- {
- v->set(xpath.c_str(), what.m_value.c_str(), SR_BINARY_T);
- }
-
- void operator()(const enum_& what)
- {
- v->set(xpath.c_str(), what.m_value.c_str(), SR_ENUM_T);
- }
-
- void operator()(const identityRef_& what)
- {
- v->set(xpath.c_str(), (what.m_prefix->m_name + what.m_value).c_str(), SR_IDENTITYREF_T);
- }
-
- void operator()(const empty_)
- {
- v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T);
- }
-
- void operator()(const std::string& what)
- {
- v->set(xpath.c_str(), what.c_str());
- }
-
- void operator()(const bits_& what)
- {
- std::stringstream ss;
- std::copy(what.m_bits.begin(), what.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
- v->set(xpath.c_str(), ss.str().c_str());
- }
-
- template <typename Type>
- void operator()(const Type what)
- {
- v->set(xpath.c_str(), what);
- }
-
- void operator()([[maybe_unused]] const special_ what)
- {
- throw std::logic_error("Attempted to create a SR val from a special_ value");
- }
-
- ::sysrepo::S_Val v;
- std::string xpath;
-};
-
class OperationalDataCallback {
public:
OperationalDataCallback(const DataSupplier& dataSupplier)
: m_dataSupplier(dataSupplier)
{
}
- int operator()(
- [[maybe_unused]] sysrepo::S_Session sess,
- [[maybe_unused]] const char* module_name,
- const char* path,
- [[maybe_unused]] const char* request_xpath,
- [[maybe_unused]] uint32_t request_id,
- libyang::S_Data_Node& parent)
+ sysrepo::ErrorCode operator()(
+ sysrepo::Session session,
+ [[maybe_unused]] uint32_t subscriptionId,
+ [[maybe_unused]] std::string_view moduleName,
+ std::optional<std::string_view> subXPath,
+ [[maybe_unused]] std::optional<std::string_view> requestXPath,
+ [[maybe_unused]] uint32_t requestId,
+ std::optional<libyang::DataNode>& output)
{
- auto data = m_dataSupplier.get_data(path);
- libyang::S_Data_Node res;
+ auto data = m_dataSupplier.get_data(subXPath->data());
for (const auto& [p, v] : data) {
- if (!res) {
- res = std::make_shared<libyang::Data_Node>(
- sess->get_context(),
- p.c_str(),
- v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
- LYD_ANYDATA_CONSTSTRING,
- 0);
+ if (!output) {
+ output = session.getContext().newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
} else {
- res->new_path(
- sess->get_context(),
- p.c_str(),
- v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
- LYD_ANYDATA_CONSTSTRING,
- 0);
+ output->newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
}
}
- parent = res;
- return SR_ERR_OK;
+ return sysrepo::ErrorCode::Ok;
}
private:
@@ -167,9 +110,6 @@
};
OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier)
- : m_connection(std::make_shared<sysrepo::Connection>())
- , m_session(std::make_shared<sysrepo::Session>(m_connection))
- , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session))
+ : m_subscription(sysrepo::Connection{}.sessionStart().onOperGet(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str()))
{
- m_subscription->oper_get_items_subscribe(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str());
}