Add support for executing RPCs
Creating a temporary YangAccess for RPC input means I need to somehow
give the right libyang schemas. For that reason I supply a callable
which is able to fetch the schema and create a YangAccess instance for
ProxyDatastore.
The ProxyDatastore class now has a simple mechanism for deciding whether
to use the normal datastore and the temporary based on a path prefix.
Change-Id: Ib455f53237598bc2620161a44fb89c48ddfeb6e3
diff --git a/src/yang_access.cpp b/src/yang_access.cpp
index 8277ef1..ebe39f1 100644
--- a/src/yang_access.cpp
+++ b/src/yang_access.cpp
@@ -31,6 +31,15 @@
: m_ctx(lyWrap(ly_ctx_new(nullptr, LY_CTX_DISABLE_SEARCHDIR_CWD)))
, m_datastore(lyWrap<lyd_node>(nullptr))
, m_schema(std::make_shared<YangSchema>(libyang::create_new_Context(m_ctx.get())))
+ , m_validation_mode(LYD_OPT_DATA)
+{
+}
+
+YangAccess::YangAccess(std::shared_ptr<YangSchema> schema)
+ : m_ctx(schema->m_context->swig_ctx(), [](auto) {})
+ , m_datastore(lyWrap<lyd_node>(nullptr))
+ , m_schema(schema)
+ , m_validation_mode(LYD_OPT_RPC)
{
}
@@ -103,7 +112,12 @@
void YangAccess::validate()
{
auto datastore = m_datastore.release();
- lyd_validate(&datastore, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB, m_ctx.get());
+
+ if (m_validation_mode == LYD_OPT_RPC) {
+ lyd_validate(&datastore, m_validation_mode, nullptr);
+ } else {
+ lyd_validate(&datastore, m_validation_mode | LYD_OPT_DATA_NO_YANGLIB, m_ctx.get());
+ }
m_datastore = lyWrap(datastore);
}
@@ -116,8 +130,12 @@
auto set = lyWrap(lyd_find_path(m_datastore.get(), path == "/" ? "/*" : path.c_str()));
auto setWrapper = libyang::Set(set.get(), nullptr);
-
- lyNodesToTree(res, setWrapper.data());
+ std::optional<std::string> ignoredXPathPrefix;
+ if (m_datastore->schema->nodetype == LYS_RPC) {
+ auto path = std::unique_ptr<char, decltype(&free)>(lys_path(m_datastore->schema, 0), &free);
+ ignoredXPathPrefix = joinPaths(path.get(), "/");
+ }
+ lyNodesToTree(res, setWrapper.data(), ignoredXPathPrefix);
return res;
}
@@ -218,6 +236,9 @@
getErrorsAndThrow();
}
for (const auto& [k, v] : input) {
+ if (v.type() == typeid(special_) && boost::get<special_>(v).m_value != SpecialValue::PresenceContainer) {
+ continue;
+ }
auto node = lyd_new_path(root.get(), m_ctx.get(), joinPaths(path, k).c_str(), (void*)leafDataToString(v).c_str(), LYD_ANYDATA_CONSTSTRING, 0);
if (!node) {
getErrorsAndThrow();