From a003cf7c484ea68eba5ace08ea6f40109236c388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 9 Sep 2024 13:05:02 +0200 Subject: [PATCH] Bump rousette to latest GIT hash Since we are using an old GCC we need to add a new requirement for rousette 'date' this is included in GCC 14+. --- package/Config.in | 1 + ...urrent-timezone-on-ARM-based-devices.patch | 29 ++ package/date-cpp/Config.in | 6 + package/date-cpp/date.hash | 3 + package/date-cpp/date.mk | 10 + package/libyang-cpp/libyang-cpp.hash | 2 +- package/libyang-cpp/libyang-cpp.mk | 2 +- package/rousette/Config.in | 2 +- package/rousette/rousette.hash | 2 +- package/rousette/rousette.mk | 4 +- package/sysrepo-cpp/sysrepo-cpp.hash | 2 +- package/sysrepo-cpp/sysrepo-cpp.mk | 2 +- .../UPSTREAM-port-to-libyang3.patch | 300 -------------- ...rom-a-required-dependency-to-an-opti.patch | 165 -------- .../0002-Add-optional-timeout-option.patch | 248 ----------- ...eouts-for-calls-to-sr_get_data-and-s.patch | 67 --- src/confd/yang/confd.inc | 12 +- .../ietf-restconf-monitoring@2017-01-26.yang | 150 +++++++ .../yang/ietf-yang-patch@2017-02-22.yang | 390 ++++++++++++++++++ 19 files changed, 606 insertions(+), 791 deletions(-) create mode 100644 package/date-cpp/0001-Fix-getting-current-timezone-on-ARM-based-devices.patch create mode 100644 package/date-cpp/Config.in create mode 100644 package/date-cpp/date.hash create mode 100644 package/date-cpp/date.mk delete mode 100644 patches/libyang-cpp/UPSTREAM-port-to-libyang3.patch delete mode 100644 patches/rousette/0001-Change-systemd-from-a-required-dependency-to-an-opti.patch delete mode 100644 patches/rousette/0002-Add-optional-timeout-option.patch delete mode 100644 patches/sysrepo-cpp/0001-Add-optional-timeouts-for-calls-to-sr_get_data-and-s.patch create mode 100644 src/confd/yang/ietf-restconf-monitoring@2017-01-26.yang create mode 100644 src/confd/yang/ietf-yang-patch@2017-02-22.yang diff --git a/package/Config.in b/package/Config.in index aaaed42ae..655034fc8 100644 --- a/package/Config.in +++ b/package/Config.in @@ -32,4 +32,5 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/libyang-cpp/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-cpp/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/rousette/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/nghttp2-asio/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/date-cpp/Config.in endmenu diff --git a/package/date-cpp/0001-Fix-getting-current-timezone-on-ARM-based-devices.patch b/package/date-cpp/0001-Fix-getting-current-timezone-on-ARM-based-devices.patch new file mode 100644 index 000000000..eb9532bf2 --- /dev/null +++ b/package/date-cpp/0001-Fix-getting-current-timezone-on-ARM-based-devices.patch @@ -0,0 +1,29 @@ +From c8ec120afa3a66674ef30b10490eeeb36d806eed Mon Sep 17 00:00:00 2001 +From: Tomas Pecka +Date: Fri, 17 Feb 2023 13:50:17 +0100 +Subject: [PATCH] Fix getting current timezone on ARM-based devices +Our software using date on buildroot ARM-based device terminates with an +uncaught exception. + terminate called after throwing an instance of 'std::runtime_error' + what(): posix/Etc/UTC not found in timezone database +I have applied workaround from [1]. +[1] https://github.com/HowardHinnant/date/issues/252 +Bug: https://github.com/HowardHinnant/date/issues/252 +--- + src/tz.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) +diff --git a/src/tz.cpp b/src/tz.cpp +index bd9fad4..eea48ce 100644 +--- a/src/tz.cpp ++++ b/src/tz.cpp +@@ -3925,7 +3925,7 @@ sniff_realpath(const char* timezone) + if (realpath(timezone, rp) == nullptr) + throw system_error(errno, system_category(), "realpath() failed"); + auto result = extract_tz_name(rp); +- return result != "posixrules"; ++ return result.find("posix") == decltype(result)::npos; + } + + const time_zone* +-- +2.39.2 diff --git a/package/date-cpp/Config.in b/package/date-cpp/Config.in new file mode 100644 index 000000000..ad8aba6ca --- /dev/null +++ b/package/date-cpp/Config.in @@ -0,0 +1,6 @@ +config BR2_PACKAGE_DATE_CPP + bool "date-cpp" + help + A date and time library based on the C++11/14/17 header + + https://github.com/HowardHinnant/date diff --git a/package/date-cpp/date.hash b/package/date-cpp/date.hash new file mode 100644 index 000000000..42db0bc47 --- /dev/null +++ b/package/date-cpp/date.hash @@ -0,0 +1,3 @@ +# Locally calculated +sha256 c90f6c00fb961170560299cbda28ca2d45804913aa8b2a9f36dbb8e0028d6930 LICENSE.txt +sha256 7a390f200f0ccd207e8cff6757e04817c1a0aec3e327b006b7eb451c57ee3538 date-3.0.1.tar.gz diff --git a/package/date-cpp/date.mk b/package/date-cpp/date.mk new file mode 100644 index 000000000..c181fe33a --- /dev/null +++ b/package/date-cpp/date.mk @@ -0,0 +1,10 @@ +DATE_CPP_VERSION = 3.0.1 +DATE_CPP_SITE = $(call github,HowardHinnant,date,v$(DATE_CPP_VERSION)) +DATE_CPP_INSTALL_STAGING = YES +DATE_CPP_LICENSE = MIT +DATE_CPP_LICENSE_FILES = LICENSE.txt +DATE_CPP_CONF_OPTS = \ + -DBUILD_TZ_LIB=ON \ + -DUSE_SYSTEM_TZ_DB:BOOL=ON \ + -DENABLE_DATE_TESTING=OFF +$(eval $(cmake-package)) diff --git a/package/libyang-cpp/libyang-cpp.hash b/package/libyang-cpp/libyang-cpp.hash index 41dac1de5..a3073cfe4 100644 --- a/package/libyang-cpp/libyang-cpp.hash +++ b/package/libyang-cpp/libyang-cpp.hash @@ -1,3 +1,3 @@ # Locally calculated sha256 82e3758011ec44c78e98d0777799d6e12aec5b8a64b32ebb20d0fe50e32488bb LICENSE -sha256 fc5ae5218d441afef697d4fc7912ddbe322060103c053d50fc2db829bd359458 libyang-cpp-b852ea3b9a2729da364f2c4122db05d882df37f2-br1.tar.gz +sha256 b1ae9848c9810462fdca89b83297d5992e9c0c00399c21f65a0eef183d4789b4 libyang-cpp-38e3399c99a82d3c0f693fb19ab1e1b3cd72aed9-br1.tar.gz diff --git a/package/libyang-cpp/libyang-cpp.mk b/package/libyang-cpp/libyang-cpp.mk index 7f6ae655a..72538d818 100644 --- a/package/libyang-cpp/libyang-cpp.mk +++ b/package/libyang-cpp/libyang-cpp.mk @@ -3,7 +3,7 @@ # CPP bindings for libyang # ################################################################################ -LIBYANG_CPP_VERSION = b852ea3b9a2729da364f2c4122db05d882df37f2 +LIBYANG_CPP_VERSION = 38e3399c99a82d3c0f693fb19ab1e1b3cd72aed9 LIBYANG_CPP_SITE = https://github.com/kernelkit/libyang-cpp.git LIBYANG_CPP_SITE_METHOD = git LIBYANG_CPP_LICENSE = BSD-3-Clause diff --git a/package/rousette/Config.in b/package/rousette/Config.in index bf03a8a6a..2b622e88d 100644 --- a/package/rousette/Config.in +++ b/package/rousette/Config.in @@ -2,7 +2,6 @@ config BR2_PACKAGE_ROUSETTE bool "rousette" depends on BR2_USE_MMU select BR2_PACKAGE_BOOST - select BR2_PACKAGE_BOOST_ATOMIC select BR2_PACKAGE_BOOST_THREAD select BR2_PACKAGE_BOOST_SYSTEM select BR2_PACKAGE_DOCOPT_CPP @@ -11,5 +10,6 @@ config BR2_PACKAGE_ROUSETTE select BR2_PACKAGE_NGHTTP2_ASIO select BR2_PACKAGE_SPDLOG select BR2_PACKAGE_SYSREPO_CPP + select BR2_PACKAGE_DATE help RESTconf server diff --git a/package/rousette/rousette.hash b/package/rousette/rousette.hash index 7fda09372..8bacd4dff 100644 --- a/package/rousette/rousette.hash +++ b/package/rousette/rousette.hash @@ -1,3 +1,3 @@ # Locally calculated sha256 cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 LICENSE -sha256 74b0d3115e73335399c5f8847fb7baa4d23497be75d12fccf56a754015af4c76 rousette-226a2410376e5befd0bf6dc180618a108b11b256-br1.tar.gz +sha256 3ba8a5dedff9a55af0b41ef07c8ffa2400f5a08bb70dfb18f850fa0416829f5e rousette-cf7a1d6eafc29ea708f18833ceb2f297dc2b7f74-br1.tar.gz diff --git a/package/rousette/rousette.mk b/package/rousette/rousette.mk index b4c50bb92..eea82c408 100644 --- a/package/rousette/rousette.mk +++ b/package/rousette/rousette.mk @@ -4,12 +4,12 @@ # ################################################################################ -ROUSETTE_VERSION = 226a2410376e5befd0bf6dc180618a108b11b256 +ROUSETTE_VERSION = cf7a1d6eafc29ea708f18833ceb2f297dc2b7f74 ROUSETTE_SITE = https://github.com/kernelkit/rousette.git ROUSETTE_SITE_METHOD = git ROUSETTE_LICENSE = Apache-2.0 ROUSETTE_LICENSE_FILES = LICENSE -ROUSETTE_DEPENDENCIES = boost docopt-cpp nghttp2-asio spdlog sysrepo-cpp linux-pam +ROUSETTE_DEPENDENCIES = boost docopt-cpp nghttp2-asio spdlog sysrepo-cpp linux-pam date-cpp ROUSETTE_CONF_OPTS = \ -DTESTAR=on \ diff --git a/package/sysrepo-cpp/sysrepo-cpp.hash b/package/sysrepo-cpp/sysrepo-cpp.hash index 35979bf6d..037ec66a6 100644 --- a/package/sysrepo-cpp/sysrepo-cpp.hash +++ b/package/sysrepo-cpp/sysrepo-cpp.hash @@ -1,3 +1,3 @@ # Locally calculated sha256 82e3758011ec44c78e98d0777799d6e12aec5b8a64b32ebb20d0fe50e32488bb LICENSE -sha256 74d7d89307c9fc188c7f23ae5128fe320a569f455a325286122eaa927a0d95ed sysrepo-cpp-99747f74e57a09c664251ea1f4e059e3f4f8e66a-br1.tar.gz +sha256 f675acde97f95058252b2b9338e9d05e755dd4bf394ab8d68ea6edbb8cd9d75c sysrepo-cpp-e59193c772fa0e5963eff216b4fbb574383a64f2-br1.tar.gz diff --git a/package/sysrepo-cpp/sysrepo-cpp.mk b/package/sysrepo-cpp/sysrepo-cpp.mk index 9f804a345..4cd5cbba9 100644 --- a/package/sysrepo-cpp/sysrepo-cpp.mk +++ b/package/sysrepo-cpp/sysrepo-cpp.mk @@ -4,7 +4,7 @@ # ################################################################################ -SYSREPO_CPP_VERSION = 99747f74e57a09c664251ea1f4e059e3f4f8e66a +SYSREPO_CPP_VERSION = e59193c772fa0e5963eff216b4fbb574383a64f2 SYSREPO_CPP_SITE = https://github.com/kernelkit/sysrepo-cpp.git SYSREPO_CPP_SITE_METHOD = git SYSREPO_CPP_LICENSE = BSD-3-Clause diff --git a/patches/libyang-cpp/UPSTREAM-port-to-libyang3.patch b/patches/libyang-cpp/UPSTREAM-port-to-libyang3.patch deleted file mode 100644 index 463a5e116..000000000 --- a/patches/libyang-cpp/UPSTREAM-port-to-libyang3.patch +++ /dev/null @@ -1,300 +0,0 @@ -From 0a09b00dab204bb5890978a17bb23c4c25280580 Mon Sep 17 00:00:00 2001 -From: Jan Kundrát -Date: Sun, 24 Mar 2024 20:41:25 +0100 -Subject: [PATCH] Port to libyang v3 - -Four parts, really: - -- some enum reshuffling when creating new nodes - -- a more capable XPath finding, but we have not been exporting any - "non-JSON XPaths", whatever that might be - -- system-ordered lists are now ordered alphabetically - -- a more capable error handling API - -Change-Id: Ic6de06f004c16e56cef93fae0136c07d903394c0 ---- - -diff --git a/.zuul.yaml b/.zuul.yaml -index d9d95e1..b41c490 100644 ---- a/.zuul.yaml -+++ b/.zuul.yaml -@@ -4,13 +4,13 @@ - - f38-gcc-cover: - required-projects: - - name: github/CESNET/libyang -- override-checkout: cesnet/2024-03--v2-latest -+ override-checkout: devel - - name: github/onqtam/doctest - override-checkout: v2.3.6 - - f38-clang-asan-ubsan: - required-projects: &projects - - name: github/CESNET/libyang -- override-checkout: cesnet/2024-03--v2-latest -+ override-checkout: devel - - name: github/onqtam/doctest - override-checkout: v2.4.11 - - f38-clang-tsan: -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 288b62a..6e54707 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -28,7 +28,7 @@ - option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON) - - find_package(PkgConfig REQUIRED) --pkg_check_modules(LIBYANG REQUIRED libyang>=2.1.140 IMPORTED_TARGET) -+pkg_check_modules(LIBYANG REQUIRED libyang>=2.2.3 IMPORTED_TARGET) - set(LIBYANG_CPP_PKG_VERSION "1.1.0") - - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -diff --git a/README.md b/README.md -index 5e79a23..9009a54 100644 ---- a/README.md -+++ b/README.md -@@ -8,8 +8,7 @@ - Object lifetimes are managed automatically via RAII. - - ## Dependencies --- [libyang](https://github.com/CESNET/libyang) - ~~the `devel` branch (even for the `master` branch of *libyang-cpp*)~~ -- - temporarily (March 2024) this requires the [pre-v3 API of libyang (commit `b3d079fc3`)](https://github.com/CESNET/libyang/tree/b3d079fc37ac119f5a2a4a120b86d1c7102c3a08) -+- [libyang v3](https://github.com/CESNET/libyang) - the `devel` branch (even for the `master` branch of *libyang-cpp*) - - C++20 compiler (e.g., GCC 10.x+, clang 10+) - - CMake 3.19+ - -diff --git a/include/libyang-cpp/Context.hpp b/include/libyang-cpp/Context.hpp -index 1dab9f3..6f6e233 100644 ---- a/include/libyang-cpp/Context.hpp -+++ b/include/libyang-cpp/Context.hpp -@@ -69,7 +69,9 @@ - LogLevel level; - std::string message; - ErrorCode code; -- std::optional path; -+ std::optional dataPath; -+ std::optional schemaPath; -+ uint64_t line; - ValidationErrorCode validationCode; - }; - -diff --git a/include/libyang-cpp/Enum.hpp b/include/libyang-cpp/Enum.hpp -index 3ded4d2..85dcc83 100644 ---- a/include/libyang-cpp/Enum.hpp -+++ b/include/libyang-cpp/Enum.hpp -@@ -115,11 +115,15 @@ - }; - - enum class CreationOptions : uint32_t { -- Update = 0x01, -- Output = 0x02, -- Opaque = 0x04, -- // BinaryLyb = 0x08, TODO -- CanonicalValue = 0x10 -+ Output = 0x01, -+ StoreOnly = 0x02, -+ // BinaryLyb = 0x04, TODO -+ CanonicalValue = 0x08, -+ ClearDefaultFromParents = 0x10, -+ Update = 0x20, -+ Opaque = 0x40, -+ PathWithOpaque = 0x80, -+ // LYD_NEW_ANY_USE_VALUE is not relevant - }; - - /** -diff --git a/src/Context.cpp b/src/Context.cpp -index 337070f..713c50f 100644 ---- a/src/Context.cpp -+++ b/src/Context.cpp -@@ -579,8 +579,10 @@ - .appTag = errIt->apptag ? std::optional{errIt->apptag} : std::nullopt, - .level = utils::toLogLevel(errIt->level), - .message = errIt->msg, -- .code = static_cast(errIt->no), -- .path = errIt->path ? std::optional{errIt->path} : std::nullopt, -+ .code = static_cast(errIt->err), -+ .dataPath = errIt->data_path ? std::optional{errIt->data_path} : std::nullopt, -+ .schemaPath = errIt->schema_path ? std::optional{errIt->schema_path} : std::nullopt, -+ .line = errIt->line, - .validationCode = utils::toValidationErrorCode(errIt->vecode) - }); - -diff --git a/src/DataNode.cpp b/src/DataNode.cpp -index ab8cb4a..0e609c4 100644 ---- a/src/DataNode.cpp -+++ b/src/DataNode.cpp -@@ -1187,7 +1187,8 @@ - const std::string& xpath) - { - ly_set* set; -- auto ret = lyd_find_xpath3(contextNode ? contextNode->m_node : nullptr, forest.m_node, xpath.c_str(), nullptr, &set); -+ auto ret = lyd_find_xpath3(contextNode ? contextNode->m_node : nullptr, forest.m_node, xpath.c_str(), -+ LY_VALUE_JSON, nullptr, nullptr, &set); - - throwIfError(ret, "libyang::findXPathAt:"); - -diff --git a/src/utils/enum.hpp b/src/utils/enum.hpp -index 7674fc6..5e02d24 100644 ---- a/src/utils/enum.hpp -+++ b/src/utils/enum.hpp -@@ -72,11 +72,14 @@ - { - return static_cast(flags); - } --static_assert(LYD_NEW_PATH_UPDATE == toCreationOptions(CreationOptions::Update)); --static_assert(LYD_NEW_PATH_OUTPUT == toCreationOptions(CreationOptions::Output)); --static_assert(LYD_NEW_PATH_OPAQ == toCreationOptions(CreationOptions::Opaque)); -+static_assert(LYD_NEW_VAL_OUTPUT == toCreationOptions(CreationOptions::Output)); -+static_assert(LYD_NEW_VAL_STORE_ONLY == toCreationOptions(CreationOptions::StoreOnly)); - // static_assert(LYD_NEW_PATH_BIN_VALUE == toCreationOptions(CreationOptions::BinaryLyb)); --static_assert(LYD_NEW_PATH_CANON_VALUE == toCreationOptions(CreationOptions::CanonicalValue)); -+static_assert(LYD_NEW_VAL_CANON == toCreationOptions(CreationOptions::CanonicalValue)); -+static_assert(LYD_NEW_META_CLEAR_DFLT == toCreationOptions(CreationOptions::ClearDefaultFromParents)); -+static_assert(LYD_NEW_PATH_UPDATE == toCreationOptions(CreationOptions::Update)); -+static_assert(LYD_NEW_PATH_OPAQ == toCreationOptions(CreationOptions::Opaque)); -+static_assert(LYD_NEW_PATH_WITH_OPAQ == toCreationOptions(CreationOptions::PathWithOpaque)); - - constexpr uint32_t toDuplicationOptions(const DuplicationOptions options) - { -diff --git a/tests/context.cpp b/tests/context.cpp -index d19f78b..cb629ef 100644 ---- a/tests/context.cpp -+++ b/tests/context.cpp -@@ -457,7 +457,9 @@ - .level = libyang::LogLevel::Error, - .message = "Invalid character sequence \"invalid\", expected a keyword.", - .code = libyang::ErrorCode::ValidationFailure, -- .path = "Line number 1.", -+ .dataPath = std::nullopt, -+ .schemaPath = std::nullopt, -+ .line = 1, - .validationCode = libyang::ValidationErrorCode::Syntax, - } - }; -@@ -476,7 +478,9 @@ - .level = libyang::LogLevel::Error, - .message = "Value \"9001\" is out of type int8 min/max bounds.", - .code = libyang::ErrorCode::ValidationFailure, -- .path = "Schema location \"/example-schema:leafInt8\".", -+ .dataPath = std::nullopt, -+ .schemaPath = "/example-schema:leafInt8", -+ .line = 0, - .validationCode = libyang::ValidationErrorCode::Data, - } - }; -@@ -491,7 +495,9 @@ - .level = libyang::LogLevel::Error, - .message = "Invalid type int8 empty value.", - .code = libyang::ErrorCode::ValidationFailure, -- .path = "Schema location \"/example-schema:leafInt8\".", -+ .dataPath = std::nullopt, -+ .schemaPath = "/example-schema:leafInt8", -+ .line = 0, - .validationCode = libyang::ValidationErrorCode::Data, - }, - libyang::ErrorInfo { -@@ -499,7 +505,9 @@ - .level = libyang::LogLevel::Error, - .message = "Value \"9001\" is out of type int8 min/max bounds.", - .code = libyang::ErrorCode::ValidationFailure, -- .path = "Schema location \"/example-schema:leafInt8\".", -+ .dataPath = std::nullopt, -+ .schemaPath = "/example-schema:leafInt8", -+ .line = 0, - .validationCode = libyang::ValidationErrorCode::Data, - } - }; -diff --git a/tests/data_node.cpp b/tests/data_node.cpp -index 15fb727..2d27979 100644 ---- a/tests/data_node.cpp -+++ b/tests/data_node.cpp -@@ -1026,12 +1026,12 @@ - "/example-schema:bigTree/one", - "/example-schema:bigTree/one/myLeaf", - "/example-schema:bigTree/two", -- "/example-schema:bigTree/two/myList[thekey='43221']", -- "/example-schema:bigTree/two/myList[thekey='43221']/thekey", -+ "/example-schema:bigTree/two/myList[thekey='213']", -+ "/example-schema:bigTree/two/myList[thekey='213']/thekey", - "/example-schema:bigTree/two/myList[thekey='432']", - "/example-schema:bigTree/two/myList[thekey='432']/thekey", -- "/example-schema:bigTree/two/myList[thekey='213']", -- "/example-schema:bigTree/two/myList[thekey='213']/thekey" -+ "/example-schema:bigTree/two/myList[thekey='43221']", -+ "/example-schema:bigTree/two/myList[thekey='43221']/thekey", - }; - - REQUIRE(res == expected); -@@ -1255,6 +1255,7 @@ - - DOCTEST_SUBCASE("DataNode::findXPath") - { -+ // libyang v3 sorts these alphabetically - const auto data3 = R"({ - "example-schema:person": [ - { -@@ -1308,13 +1309,13 @@ - auto set = node->findXPath("/example-schema:person"); - REQUIRE(set.size() == 3); - -- REQUIRE(set.front().path() == "/example-schema:person[name='John']"); -- REQUIRE(set.back().path() == "/example-schema:person[name='David']"); -+ REQUIRE(set.front().path() == "/example-schema:person[name='Dan']"); -+ REQUIRE(set.back().path() == "/example-schema:person[name='John']"); - - auto iter = set.begin(); -- REQUIRE((iter++)->path() == "/example-schema:person[name='John']"); - REQUIRE((iter++)->path() == "/example-schema:person[name='Dan']"); - REQUIRE((iter++)->path() == "/example-schema:person[name='David']"); -+ REQUIRE((iter++)->path() == "/example-schema:person[name='John']"); - REQUIRE(iter == set.end()); - REQUIRE_THROWS_WITH_AS(*iter, "Dereferenced an .end() iterator", std::out_of_range); - } -@@ -1324,23 +1325,23 @@ - auto set = node->findXPath("/example-schema:person"); - - REQUIRE((set.begin() + 0) == set.begin()); -- REQUIRE((set.begin() + 0)->path() == "/example-schema:person[name='John']"); -- REQUIRE((set.begin() + 1)->path() == "/example-schema:person[name='Dan']"); -- REQUIRE((set.begin() + 2)->path() == "/example-schema:person[name='David']"); -+ REQUIRE((set.begin() + 0)->path() == "/example-schema:person[name='Dan']"); -+ REQUIRE((set.begin() + 1)->path() == "/example-schema:person[name='David']"); -+ REQUIRE((set.begin() + 2)->path() == "/example-schema:person[name='John']"); - REQUIRE((set.begin() + 3) == set.end()); - REQUIRE_THROWS(set.begin() + 4); - - REQUIRE((set.end() - 0) == set.end()); -- REQUIRE((set.end() - 1)->path() == "/example-schema:person[name='David']"); -- REQUIRE((set.end() - 2)->path() == "/example-schema:person[name='Dan']"); -- REQUIRE((set.end() - 3)->path() == "/example-schema:person[name='John']"); -+ REQUIRE((set.end() - 1)->path() == "/example-schema:person[name='John']"); -+ REQUIRE((set.end() - 2)->path() == "/example-schema:person[name='David']"); -+ REQUIRE((set.end() - 3)->path() == "/example-schema:person[name='Dan']"); - REQUIRE((set.end() - 3) == set.begin()); - REQUIRE_THROWS(set.end() - 4); - - auto iter = set.end(); -+ REQUIRE((--iter)->path() == "/example-schema:person[name='John']"); - REQUIRE((--iter)->path() == "/example-schema:person[name='David']"); - REQUIRE((--iter)->path() == "/example-schema:person[name='Dan']"); -- REQUIRE((--iter)->path() == "/example-schema:person[name='John']"); - REQUIRE_THROWS(--iter); - } - -diff --git a/tests/pretty_printers.hpp b/tests/pretty_printers.hpp -index 6ae8934..6bbc16f 100644 ---- a/tests/pretty_printers.hpp -+++ b/tests/pretty_printers.hpp -@@ -59,7 +59,9 @@ - oss << "appTag: " << (err.appTag ? *err.appTag : "std::nullopt") << "\n "; - oss << "code: " << err.code << "\n "; - oss << "message: " << err.message << "\n "; -- oss << "path: " << (err.path ? *err.path : "std::nullopt") << "\n "; -+ oss << "dataPath: " << (err.dataPath ? *err.dataPath : "std::nullopt") << "\n "; -+ oss << "schemaPath: " << (err.schemaPath ? *err.schemaPath : "std::nullopt") << "\n "; -+ oss << "line: " << err.line << "\n "; - oss << "level: " << err.level << "\n "; - oss << "validationCode: " << err.validationCode << "\n }"; - return oss.str(); diff --git a/patches/rousette/0001-Change-systemd-from-a-required-dependency-to-an-opti.patch b/patches/rousette/0001-Change-systemd-from-a-required-dependency-to-an-opti.patch deleted file mode 100644 index 688984aed..000000000 --- a/patches/rousette/0001-Change-systemd-from-a-required-dependency-to-an-opti.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 02ff08f881c726b5b14eb489f4a906ec4b421a6f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= -Date: Tue, 25 Jun 2024 11:17:03 +0200 -Subject: [PATCH 1/2] Change systemd from a required dependency to an optional - dependency. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -Organization: Addiva Elektronik - -In addition to journal logging, enable logging to syslog and stdout. - -Signed-off-by: Mattias Walström -Change-Id: I90cb9169e8fdf9103c31bc983a1ec8a5de3dd26c ---- - CMakeLists.txt | 13 +++++++++++-- - README.md | 3 ++- - ci/pre.yaml | 6 ++++++ - src/configure.cmake.h.in | 3 +++ - src/restconf/main.cpp | 36 ++++++++++++++++++++++++++++++++---- - 5 files changed, 54 insertions(+), 7 deletions(-) - create mode 100644 src/configure.cmake.h.in - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 7f82660..1cd27b2 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -75,8 +75,14 @@ find_package(Boost REQUIRED COMPONENTS system thread) - - pkg_check_modules(SYSREPO-CPP REQUIRED IMPORTED_TARGET sysrepo-cpp>=1.1.0) - pkg_check_modules(LIBYANG-CPP REQUIRED IMPORTED_TARGET libyang-cpp>=1.1.0) --pkg_check_modules(SYSTEMD REQUIRED IMPORTED_TARGET libsystemd) -+pkg_check_modules(SYSTEMD IMPORTED_TARGET libsystemd) - pkg_check_modules(PAM REQUIRED IMPORTED_TARGET pam) -+pkg_check_modules(DOCOPT REQUIRED IMPORTED_TARGET docopt) -+if(SYSTEMD_FOUND) -+ set(HAVE_SYSTEMD TRUE) -+endif() -+ -+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/configure.cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/configure.cmake.h) - - add_library(rousette-http STATIC - src/http/EventStream.cpp -@@ -116,7 +122,10 @@ add_executable(watch-operational-ds - target_link_libraries(watch-operational-ds PUBLIC rousette-sysrepo) - - add_executable(rousette src/restconf/main.cpp) --target_link_libraries(rousette PUBLIC rousette-restconf PkgConfig::SYSTEMD) -+target_link_libraries(rousette PUBLIC rousette-restconf PkgConfig::DOCOPT) -+if(SYSTEMD_FOUND) -+ target_link_libraries(rousette PUBLIC PkgConfig::SYSTEMD) -+endif() - - install(TARGETS - # clock-demo -diff --git a/README.md b/README.md -index 68b4b99..55b8241 100644 ---- a/README.md -+++ b/README.md -@@ -37,12 +37,13 @@ The anonymous user access is disabled whenever these rules are not met. - - [nghttp2-asio](https://github.com/nghttp2/nghttp2-asio) - asynchronous C++ library for HTTP/2 - - [sysrepo-cpp](https://github.com/sysrepo/sysrepo-cpp) - object-oriented bindings of the [*sysrepo*](https://github.com/sysrepo/sysrepo) library - - [libyang-cpp](https://github.com/CESNET/libyang-cpp) - C++ bindings for *libyang* --- systemd - the shared library for logging to `sd-journal` - - [PAM](http://www.linux-pam.org/) - for authentication - - [spdlog](https://github.com/gabime/spdlog) - Very fast, header-only/compiled, C++ logging library -+- [docopt-cpp](https://github.com/docopt/docopt.cpp) - command-line argument parser - - Boost's system and thread - - C++20 compiler (e.g., GCC 10.x+, clang 10+) - - CMake 3.19+ -+- optionally systemd - the shared library for logging to `sd-journal` - - optionally for built-in tests, [Doctest](https://github.com/onqtam/doctest/) as a C++ unit test framework - - optionally for built-in tests, [trompeloeil](https://github.com/rollbear/trompeloeil) for mock objects in C++ - - optionally for built-in tests, [`pam_matrix` and `pam_wrapper`](https://cwrap.org/pam_wrapper.html) for PAM mocking -diff --git a/ci/pre.yaml b/ci/pre.yaml -index 51f1c66..325dbf4 100644 ---- a/ci/pre.yaml -+++ b/ci/pre.yaml -@@ -11,3 +11,9 @@ - name: pam_wrapper - state: present - become: true -+ -+ - name: install docopt-cpp -+ package: -+ name: docopt-cpp-devel -+ state: present -+ become: true -diff --git a/src/configure.cmake.h.in b/src/configure.cmake.h.in -new file mode 100644 -index 0000000..bc26981 ---- /dev/null -+++ b/src/configure.cmake.h.in -@@ -0,0 +1,3 @@ -+#pragma once -+ -+#cmakedefine HAVE_SYSTEMD -diff --git a/src/restconf/main.cpp b/src/restconf/main.cpp -index bba3cbf..2bc9a86 100644 ---- a/src/restconf/main.cpp -+++ b/src/restconf/main.cpp -@@ -9,14 +9,30 @@ - #include - #include - #include --#include -+ -+#include "configure.cmake.h" /* Expose HAVE_SYSTEMD */ -+ -+#ifdef HAVE_SYSTEMD -+ #include -+#endif -+#include - #include - #include - #include - #include -+#include - #include - #include - #include "restconf/Server.h" -+static const char usage[] = -+ R"(Rousette - RESTCONF server -+Usage: -+ rousette [--syslog] [--help] -+Options: -+ -h --help Show this screen. -+ --syslog Log to syslog. -+)"; -+#ifdef HAVE_SYSTEMD - - namespace { - /** @short Is stderr connected to journald? Not thread safe. */ -@@ -54,13 +70,25 @@ public: - } - }; - } -- --int main(int argc [[maybe_unused]], char* argv [[maybe_unused]] []) -+#endif -+int main(int argc, char* argv []) - { -- if (is_journald_active()) { -+ auto args = docopt::docopt(usage, {argv + 1, argv + argc}, true,""/* version */, true); -+ -+ if (args["--syslog"].asBool()) { -+ auto syslog_sink = std::make_shared("rousette", LOG_PID, LOG_USER, true); -+ auto logger = std::make_shared("rousette", syslog_sink); -+ spdlog::set_default_logger(logger); -+#ifdef HAVE_SYSTEMD -+ } else if (is_journald_active()) { - auto sink = std::make_shared>(); - auto logger = std::make_shared("rousette", sink); - spdlog::set_default_logger(logger); -+#endif -+ } else { -+ auto stdout_sink = std::make_shared(); -+ auto logger = std::make_shared("rousette", stdout_sink); -+ spdlog::set_default_logger(logger); - } - spdlog::set_level(spdlog::level::trace); - --- -2.34.1 - diff --git a/patches/rousette/0002-Add-optional-timeout-option.patch b/patches/rousette/0002-Add-optional-timeout-option.patch deleted file mode 100644 index 58e85a26a..000000000 --- a/patches/rousette/0002-Add-optional-timeout-option.patch +++ /dev/null @@ -1,248 +0,0 @@ -commit c83585452819b6e06008aba49237f46977a73a9a -Author: Mattias Walström -Date: Wed Jun 26 11:04:36 2024 +0200 - - Add optional timeout option - - Since rousette will fail applying a new configuration - on really slow systems and a lot of sysrepo callbacks. - - Change-Id: I61d92a1f64e4c3617587e544cfd9d6a4269e0d35 - -diff --git a/src/restconf/Server.cpp b/src/restconf/Server.cpp -index 5327b52..685bf78 100644 ---- a/src/restconf/Server.cpp -+++ b/src/restconf/Server.cpp -@@ -202,14 +202,13 @@ DataFormat chooseDataEncoding(const nghttp2::asio_http2::header_map& headers) - return {resContentType, resAccept ? *resAccept : libyang::DataFormat::JSON}; - } - --bool dataExists(sysrepo::Session session, const std::string& path) -+bool dataExists(sysrepo::Session session, const std::string& path, std::chrono::milliseconds timeout) - { -- if (auto data = session.getData(path)) { -- if (data->findPath(path)) { -+ if (auto data = session.getData(path, 0, sysrepo::GetOptions::Default,timeout)) { -+ if (data->findPath(path)) - return true; - } -- } -- return false; -+ return false; - } - - /** @brief Checks if node is a key node in a maybeList node list */ -@@ -261,7 +260,7 @@ struct RequestContext { - std::string payload; - }; - --void processActionOrRPC(std::shared_ptr requestCtx) -+void processActionOrRPC(std::shared_ptr requestCtx, std::chrono::milliseconds timeout) - { - requestCtx->sess.switchDatastore(sysrepo::Datastore::Operational); - auto ctx = requestCtx->sess.getContext(); -@@ -276,7 +275,7 @@ void processActionOrRPC(std::shared_ptr requestCtx) - if (rpcSchemaNode.nodeType() == libyang::NodeType::Action) { - // FIXME: This is race-prone: we check for existing action data node but before we send the RPC the node may be gone - auto [pathToParent, pathSegment] = asLibyangPathSplit(ctx, requestCtx->req.uri().path); -- if (!dataExists(requestCtx->sess, pathToParent)) { -+ if (!dataExists(requestCtx->sess, pathToParent,timeout)) { - throw ErrorResponse(400, "application", "operation-failed", "Action data node '" + requestCtx->lyPathOriginal + "' does not exist."); - } - } -@@ -287,7 +286,7 @@ void processActionOrRPC(std::shared_ptr requestCtx) - rpcNode->parseOp(requestCtx->payload, *requestCtx->dataFormat.request, libyang::OperationType::RpcRestconf); - } - -- auto rpcReply = requestCtx->sess.sendRPC(*rpcNode); -+ auto rpcReply = requestCtx->sess.sendRPC(*rpcNode, timeout); - - if (rpcReply.immediateChildren().empty()) { - requestCtx->res.write_head(204, {{"access-control-allow-origin", {"*", false}}}); -@@ -330,7 +329,7 @@ void processActionOrRPC(std::shared_ptr requestCtx) - } - } - --void processPost(std::shared_ptr requestCtx) -+void processPost(std::shared_ptr requestCtx, std::chrono::milliseconds timeout) - { - try { - auto ctx = requestCtx->sess.getContext(); -@@ -374,7 +373,7 @@ void processPost(std::shared_ptr requestCtx) - createdNodes.begin()->newMeta(*mod, "operation", "create"); // FIXME: check no other nc:operations in the tree - - requestCtx->sess.editBatch(*edit, sysrepo::DefaultOperation::Merge); -- requestCtx->sess.applyChanges(); -+ requestCtx->sess.applyChanges(timeout); - - requestCtx->res.write_head(201, - { -@@ -402,7 +401,7 @@ void processPost(std::shared_ptr requestCtx) - } - } - --void processPut(std::shared_ptr requestCtx) -+void processPut(std::shared_ptr requestCtx, std::chrono::milliseconds timeout) - { - try { - auto ctx = requestCtx->sess.getContext(); -@@ -410,7 +409,7 @@ void processPut(std::shared_ptr requestCtx) - // PUT / means replace everything - if (requestCtx->lyPathOriginal == "/") { - auto edit = ctx.parseData(requestCtx->payload, *requestCtx->dataFormat.request, libyang::ParseOptions::Strict | libyang::ParseOptions::NoState | libyang::ParseOptions::ParseOnly); -- requestCtx->sess.replaceConfig(edit); -+ requestCtx->sess.replaceConfig(edit, std::nullopt, timeout); - - requestCtx->res.write_head(edit ? 201 : 204, - { -@@ -422,7 +421,7 @@ void processPut(std::shared_ptr requestCtx) - } - - auto mod = ctx.getModuleImplemented("ietf-netconf"); -- bool nodeExisted = dataExists(requestCtx->sess, requestCtx->lyPathOriginal); -+ bool nodeExisted = dataExists(requestCtx->sess, requestCtx->lyPathOriginal, timeout); - std::optional edit; - std::optional replacementNode; - -@@ -471,7 +470,7 @@ void processPut(std::shared_ptr requestCtx) - replacementNode->newMeta(*mod, "operation", "replace"); // FIXME: check no other nc:operations in the tree - - requestCtx->sess.editBatch(*edit, sysrepo::DefaultOperation::Merge); -- requestCtx->sess.applyChanges(); -+ requestCtx->sess.applyChanges(timeout); - - requestCtx->res.write_head(nodeExisted ? 204 : 201, - { -@@ -551,7 +550,7 @@ Server::~Server() - server->join(); - } - --Server::Server(sysrepo::Connection conn, const std::string& address, const std::string& port) -+Server::Server(sysrepo::Connection conn, const std::string& address, const std::string& port, long timeout_seconds) - : nacm(conn) - , server{std::make_unique()} - , dwdmEvents{std::make_unique(conn.sessionStart())} -@@ -562,6 +561,8 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std:: - } - } - -+ std::chrono::milliseconds timeout(timeout_seconds * 1000); -+ - // RFC 8527, we must implement at least ietf-yang-library@2019-01-04 and support operational DS - if (auto mod = conn.sessionStart().getContext().getModuleImplemented("ietf-yang-library"); !mod || mod->revision() < "2019-01-04") { - throw std::runtime_error("Module ietf-yang-library of revision at least 2019-01-04 is not implemented"); -@@ -627,7 +628,7 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std:: - }); - - server->handle(restconfRoot, -- [conn /* intentionally by value, otherwise conn gets destroyed when the ctor returns */, this](const auto& req, const auto& res) mutable { -+ [conn /* intentionally by value, otherwise conn gets destroyed when the ctor returns */, this, timeout](const auto& req, const auto& res) mutable { - const auto& peer = http::peer_from_request(req); - spdlog::info("{}: {} {}", peer, req.method(), req.uri().raw_path); - -@@ -665,7 +666,7 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std:: - - case RestconfRequest::Type::GetData: - sess.switchDatastore(restconfRequest.datastore.value_or(sysrepo::Datastore::Operational)); -- if (auto data = sess.getData(restconfRequest.path); data) { -+ if (auto data = sess.getData(restconfRequest.path, 0, sysrepo::GetOptions::Default,timeout); data) { - res.write_head( - 200, - { -@@ -692,16 +693,16 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std:: - - auto requestCtx = std::make_shared(req, res, dataFormat, sess, restconfRequest.path); - -- req.on_data([requestCtx, restconfRequest /* intentional copy */](const uint8_t* data, std::size_t length) { -+ req.on_data([requestCtx, restconfRequest /* intentional copy */, timeout](const uint8_t* data, std::size_t length) { - if (length > 0) { // there are still some data to be read - requestCtx->payload.append(reinterpret_cast(data), length); - return; - } - - if (restconfRequest.type == RestconfRequest::Type::CreateOrReplaceThisNode) { -- processPut(requestCtx); -+ processPut(requestCtx, timeout); - } else { -- processPost(requestCtx); -+ processPost(requestCtx, timeout); - } - }); - break; -@@ -725,7 +726,7 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std:: - } - - sess.editBatch(*edit, sysrepo::DefaultOperation::Merge); -- sess.applyChanges(); -+ sess.applyChanges(timeout); - } catch (const sysrepo::ErrorWithCode& e) { - if (e.code() == sysrepo::ErrorCode::Unauthorized) { - throw ErrorResponse(403, "application", "access-denied", "Access denied.", restconfRequest.path); -@@ -747,11 +748,11 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std:: - case RestconfRequest::Type::Execute: { - auto requestCtx = std::make_shared(req, res, dataFormat, sess, restconfRequest.path); - -- req.on_data([requestCtx](const uint8_t* data, std::size_t length) { -+ req.on_data([requestCtx,timeout](const uint8_t* data, std::size_t length) { - if (length > 0) { - requestCtx->payload.append(reinterpret_cast(data), length); - } else { -- processActionOrRPC(requestCtx); -+ processActionOrRPC(requestCtx,timeout); - } - }); - break; -diff --git a/src/restconf/Server.h b/src/restconf/Server.h -index bf6fecc..b2c42f4 100644 ---- a/src/restconf/Server.h -+++ b/src/restconf/Server.h -@@ -24,11 +24,10 @@ class OpticalEvents; - namespace restconf { - - std::optional as_subtree_path(const std::string& path); -- - /** @short A RESTCONF-ish server */ - class Server { - public: -- explicit Server(sysrepo::Connection conn, const std::string& address, const std::string& port); -+ explicit Server(sysrepo::Connection conn, const std::string& address, const std::string& port, long timeout); - ~Server(); - - private: -diff --git a/src/restconf/main.cpp b/src/restconf/main.cpp -index 2bc9a86..e295f63 100644 ---- a/src/restconf/main.cpp -+++ b/src/restconf/main.cpp -@@ -27,9 +27,10 @@ - static const char usage[] = - R"(Rousette - RESTCONF server - Usage: -- rousette [--syslog] [--help] -+ rousette [--syslog] [--timeout ] [--help] - Options: - -h --help Show this screen. -+ -t --timeout Change default timeout in sysrepo (if not set, use sysrepo internal). - --syslog Log to syslog. - )"; - #ifdef HAVE_SYSTEMD -@@ -74,6 +75,10 @@ public: - int main(int argc, char* argv []) - { - auto args = docopt::docopt(usage, {argv + 1, argv + argc}, true,""/* version */, true); -+ long timeout = 0; -+ -+ if (args["--timeout"]) -+ timeout = args["--timeout"].asLong(); - - if (args["--syslog"].asBool()) { - auto syslog_sink = std::make_shared("rousette", LOG_PID, LOG_USER, true); -@@ -100,8 +105,7 @@ int main(int argc, char* argv []) - } - - auto conn = sysrepo::Connection{}; -- auto server = rousette::restconf::Server{conn, "::1", "10080"}; -- -+ auto server = rousette::restconf::Server{conn, "::1", "10080", timeout}; - signal(SIGTERM, [](int) {}); - signal(SIGINT, [](int) {}); - pause(); diff --git a/patches/sysrepo-cpp/0001-Add-optional-timeouts-for-calls-to-sr_get_data-and-s.patch b/patches/sysrepo-cpp/0001-Add-optional-timeouts-for-calls-to-sr_get_data-and-s.patch deleted file mode 100644 index b778df209..000000000 --- a/patches/sysrepo-cpp/0001-Add-optional-timeouts-for-calls-to-sr_get_data-and-s.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 36f2ad3c009f4234d906485439ead42a6fbb7adf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= -Date: Tue, 25 Jun 2024 16:18:07 +0200 -Subject: [PATCH] Add optional timeouts for calls to sr_get_data and - sr_get_node -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -Organization: Addiva Elektronik - -Signed-off-by: Mattias Walström - -Change-Id: Ia91eb6823e64322e37e661b60b369dfedc5677fb ---- - include/sysrepo-cpp/Session.hpp | 4 ++-- - src/Session.cpp | 8 ++++---- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/include/sysrepo-cpp/Session.hpp b/include/sysrepo-cpp/Session.hpp -index 7c5c71c..350df7a 100644 ---- a/include/sysrepo-cpp/Session.hpp -+++ b/include/sysrepo-cpp/Session.hpp -@@ -88,9 +88,9 @@ public: - void discardItems(const std::optional& xpath); - void moveItem(const std::string& path, const MovePosition move, const std::optional& keys_or_value, const std::optional& origin = std::nullopt, const EditOptions opts = sysrepo::EditOptions::Default); - // TODO: allow timeout argument -- std::optional getData(const std::string& path, int maxDepth = 0, const GetOptions opts = sysrepo::GetOptions::Default) const; -+ std::optional getData(const std::string& path, int maxDepth = 0, const GetOptions opts = sysrepo::GetOptions::Default, std::chrono::milliseconds timeout = std::chrono::milliseconds{0}) const; - // TODO: allow all arguments -- libyang::DataNode getOneNode(const std::string& path) const; -+ libyang::DataNode getOneNode(const std::string& path, std::chrono::milliseconds timeout = std::chrono::milliseconds{0}) const; - std::optional getPendingChanges() const; - void applyChanges(std::chrono::milliseconds timeout = std::chrono::milliseconds{0}); - void discardChanges(); -diff --git a/src/Session.cpp b/src/Session.cpp -index e9d2976..04b0333 100644 ---- a/src/Session.cpp -+++ b/src/Session.cpp -@@ -191,10 +191,10 @@ libyang::DataNode wrapSrData(std::shared_ptr sess, sr_data_t* - * @param opts GetOptions overriding default behaviour - * @returns std::nullopt if no matching data found, otherwise the requested data. - */ --std::optional Session::getData(const std::string& path, int maxDepth, const GetOptions opts) const -+std::optional Session::getData(const std::string& path, int maxDepth, const GetOptions opts, std::chrono::milliseconds timeout) const - { - sr_data_t* data; -- auto res = sr_get_data(m_sess.get(), path.c_str(), maxDepth, 0, toGetOptions(opts), &data); -+ auto res = sr_get_data(m_sess.get(), path.c_str(), maxDepth, timeout.count(), toGetOptions(opts), &data); - - throwIfError(res, "Session::getData: Couldn't get '"s + path + "'", m_sess.get()); - -@@ -219,10 +219,10 @@ std::optional Session::getData(const std::string& path, int m - * @param path XPath which corresponds to the data that should be retrieved. - * @returns the requested data node (as a disconnected node) - */ --libyang::DataNode Session::getOneNode(const std::string& path) const -+libyang::DataNode Session::getOneNode(const std::string& path, std::chrono::milliseconds timeout) const - { - sr_data_t* data; -- auto res = sr_get_node(m_sess.get(), path.c_str(), 0, &data); -+ auto res = sr_get_node(m_sess.get(), path.c_str(), timeout.count(), &data); - - throwIfError(res, "Session::getOneNode: Couldn't get '"s + path + "'", m_sess.get()); - --- -2.34.1 - diff --git a/src/confd/yang/confd.inc b/src/confd/yang/confd.inc index 866f5e157..927d1d79c 100644 --- a/src/confd/yang/confd.inc +++ b/src/confd/yang/confd.inc @@ -37,17 +37,23 @@ MODULES=( "ieee802-ethernet-interface@2019-06-21.yang" "infix-ethernet-interface@2024-02-27.yang" "infix-factory-default@2023-06-28.yang" + "infix-interfaces@2024-01-15.yang -e vlan-filtering" + + # from rousette + "ietf-restconf@2017-01-26.yang" + "ietf-yang-patch@2017-02-22.yang" + "ietf-restconf-monitoring@2017-01-26.yang" + # from sysrepo "sysrepo-plugind@2022-08-26.yang" # from netopeer "nc-notifications@2008-07-14.yang" "ietf-crypto-types@2023-12-28.yang -e encrypted-private-keys" - "ietf-netconf-server@2023-12-28.yang -e ssh-listen -e tls-listen -e ssh-call-home -e tls-call-home" + "ietf-netconf-server@2023-12-28.yang -e ssh-listen -e tls-listen -e ssh-call-home -e tls-call-home" "ietf-netconf-acm@2018-02-14.yang" "ietf-netconf@2013-09-29.yang -e writable-running -e candidate -e rollback-on-error -e validate -e startup -e url -e xpath -e confirmed-commit" "ietf-truststore@2023-12-28.yang -e central-truststore-supported -e certificates" "ietf-keystore@2023-12-28.yang -e central-keystore-supported -e inline-definitions-supported -e asymmetric-keys -e symmetric-keys" "ietf-tls-server@2023-12-28.yang -e server-ident-raw-public-key -e server-ident-x509-cert" - "ietf-restconf@2017-01-26.yang" - "infix-interfaces@2024-01-15.yang -e vlan-filtering" + ) diff --git a/src/confd/yang/ietf-restconf-monitoring@2017-01-26.yang b/src/confd/yang/ietf-restconf-monitoring@2017-01-26.yang new file mode 100644 index 000000000..e87b00baf --- /dev/null +++ b/src/confd/yang/ietf-restconf-monitoring@2017-01-26.yang @@ -0,0 +1,150 @@ +module ietf-restconf-monitoring { + namespace "urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"; + prefix "rcmon"; + + import ietf-yang-types { prefix yang; } + import ietf-inet-types { prefix inet; } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + + Author: Andy Bierman + + + Author: Martin Bjorklund + + + Author: Kent Watsen + "; + + description + "This module contains monitoring information for the + RESTCONF protocol. + + Copyright (c) 2017 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8040; see + the RFC itself for full legal notices."; + + revision 2017-01-26 { + description + "Initial revision."; + reference + "RFC 8040: RESTCONF Protocol."; + } + + container restconf-state { + config false; + description + "Contains RESTCONF protocol monitoring information."; + + container capabilities { + description + "Contains a list of protocol capability URIs."; + + leaf-list capability { + type inet:uri; + description + "A RESTCONF protocol capability URI."; + } + } + + container streams { + description + "Container representing the notification event streams + supported by the server."; + reference + "RFC 5277, Section 3.4, element."; + + list stream { + key name; + description + "Each entry describes an event stream supported by + the server."; + + leaf name { + type string; + description + "The stream name."; + reference + "RFC 5277, Section 3.4, element."; + } + + leaf description { + type string; + description + "Description of stream content."; + reference + "RFC 5277, Section 3.4, element."; + } + + leaf replay-support { + type boolean; + default false; + description + "Indicates if replay buffer is supported for this stream. + If 'true', then the server MUST support the 'start-time' + and 'stop-time' query parameters for this stream."; + reference + "RFC 5277, Section 3.4, element."; + } + + leaf replay-log-creation-time { + when "../replay-support" { + description + "Only present if notification replay is supported."; + } + type yang:date-and-time; + description + "Indicates the time the replay log for this stream + was created."; + reference + "RFC 5277, Section 3.4, + element."; + } + + list access { + key encoding; + min-elements 1; + description + "The server will create an entry in this list for each + encoding format that is supported for this stream. + The media type 'text/event-stream' is expected + for all event streams. This list identifies the + subtypes supported for this stream."; + + leaf encoding { + type string; + description + "This is the secondary encoding format within the + 'text/event-stream' encoding used by all streams. + The type 'xml' is supported for XML encoding. + The type 'json' is supported for JSON encoding."; + } + + leaf location { + type inet:uri; + mandatory true; + description + "Contains a URL that represents the entry point + for establishing notification delivery via + server-sent events."; + } + } + } + } + } + +} diff --git a/src/confd/yang/ietf-yang-patch@2017-02-22.yang b/src/confd/yang/ietf-yang-patch@2017-02-22.yang new file mode 100644 index 000000000..d0029ed21 --- /dev/null +++ b/src/confd/yang/ietf-yang-patch@2017-02-22.yang @@ -0,0 +1,390 @@ +module ietf-yang-patch { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-patch"; + prefix "ypatch"; + + import ietf-restconf { prefix rc; } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + + Author: Andy Bierman + + + Author: Martin Bjorklund + + + Author: Kent Watsen + "; + + description + "This module contains conceptual YANG specifications + for the YANG Patch and YANG Patch Status data structures. + + Note that the YANG definitions within this module do not + represent configuration data of any kind. + The YANG grouping statements provide a normative syntax + for XML and JSON message-encoding purposes. + + Copyright (c) 2017 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8072; see + the RFC itself for full legal notices."; + + revision 2017-02-22 { + description + "Initial revision."; + reference + "RFC 8072: YANG Patch Media Type."; + } + + typedef target-resource-offset { + type string; + description + "Contains a data resource identifier string representing + a sub-resource within the target resource. + The document root for this expression is the + target resource that is specified in the + protocol operation (e.g., the URI for the PATCH request). + + This string is encoded according to the same rules as those + for a data resource identifier in a RESTCONF request URI."; + reference + "RFC 8040, Section 3.5.3."; + } + + rc:yang-data "yang-patch" { + uses yang-patch; + } + + rc:yang-data "yang-patch-status" { + uses yang-patch-status; + } + + grouping yang-patch { + + description + "A grouping that contains a YANG container representing the + syntax and semantics of a YANG Patch edit request message."; + + container yang-patch { + description + "Represents a conceptual sequence of datastore edits, + called a patch. Each patch is given a client-assigned + patch identifier. Each edit MUST be applied + in ascending order, and all edits MUST be applied. + If any errors occur, then the target datastore MUST NOT + be changed by the YANG Patch operation. + + It is possible for a datastore constraint violation to occur + due to any node in the datastore, including nodes not + included in the 'edit' list. Any validation errors MUST + be reported in the reply message."; + + reference + "RFC 7950, Section 8.3."; + + leaf patch-id { + type string; + mandatory true; + description + "An arbitrary string provided by the client to identify + the entire patch. Error messages returned by the server + that pertain to this patch will be identified by this + 'patch-id' value. A client SHOULD attempt to generate + unique 'patch-id' values to distinguish between + transactions from multiple clients in any audit logs + maintained by the server."; + } + + leaf comment { + type string; + description + "An arbitrary string provided by the client to describe + the entire patch. This value SHOULD be present in any + audit logging records generated by the server for the + patch."; + } + + list edit { + key edit-id; + ordered-by user; + + description + "Represents one edit within the YANG Patch request message. + The 'edit' list is applied in the following manner: + + - The first edit is conceptually applied to a copy + of the existing target datastore, e.g., the + running configuration datastore. + - Each ascending edit is conceptually applied to + the result of the previous edit(s). + - After all edits have been successfully processed, + the result is validated according to YANG constraints. + - If successful, the server will attempt to apply + the result to the target datastore."; + + leaf edit-id { + type string; + description + "Arbitrary string index for the edit. + Error messages returned by the server that pertain + to a specific edit will be identified by this value."; + } + + leaf operation { + type enumeration { + enum create { + description + "The target data node is created using the supplied + value, only if it does not already exist. The + 'target' leaf identifies the data node to be + created, not the parent data node."; + } + enum delete { + description + "Delete the target node, only if the data resource + currently exists; otherwise, return an error."; + } + + enum insert { + description + "Insert the supplied value into a user-ordered + list or leaf-list entry. The target node must + represent a new data resource. If the 'where' + parameter is set to 'before' or 'after', then + the 'point' parameter identifies the insertion + point for the target node."; + } + enum merge { + description + "The supplied value is merged with the target data + node."; + } + enum move { + description + "Move the target node. Reorder a user-ordered + list or leaf-list. The target node must represent + an existing data resource. If the 'where' parameter + is set to 'before' or 'after', then the 'point' + parameter identifies the insertion point to move + the target node."; + } + enum replace { + description + "The supplied value is used to replace the target + data node."; + } + enum remove { + description + "Delete the target node if it currently exists."; + } + } + mandatory true; + description + "The datastore operation requested for the associated + 'edit' entry."; + } + + leaf target { + type target-resource-offset; + mandatory true; + description + "Identifies the target data node for the edit + operation. If the target has the value '/', then + the target data node is the target resource. + The target node MUST identify a data resource, + not the datastore resource."; + } + + leaf point { + when "(../operation = 'insert' or ../operation = 'move')" + + "and (../where = 'before' or ../where = 'after')" { + description + "This leaf only applies for 'insert' or 'move' + operations, before or after an existing entry."; + } + type target-resource-offset; + description + "The absolute URL path for the data node that is being + used as the insertion point or move point for the + target of this 'edit' entry."; + } + + leaf where { + when "../operation = 'insert' or ../operation = 'move'" { + description + "This leaf only applies for 'insert' or 'move' + operations."; + } + type enumeration { + enum before { + description + "Insert or move a data node before the data resource + identified by the 'point' parameter."; + } + enum after { + description + "Insert or move a data node after the data resource + identified by the 'point' parameter."; + } + + enum first { + description + "Insert or move a data node so it becomes ordered + as the first entry."; + } + enum last { + description + "Insert or move a data node so it becomes ordered + as the last entry."; + } + } + default last; + description + "Identifies where a data resource will be inserted + or moved. YANG only allows these operations for + list and leaf-list data nodes that are + 'ordered-by user'."; + } + + anydata value { + when "../operation = 'create' " + + "or ../operation = 'merge' " + + "or ../operation = 'replace' " + + "or ../operation = 'insert'" { + description + "The anydata 'value' is only used for 'create', + 'merge', 'replace', and 'insert' operations."; + } + description + "Value used for this edit operation. The anydata 'value' + contains the target resource associated with the + 'target' leaf. + + For example, suppose the target node is a YANG container + named foo: + + container foo { + leaf a { type string; } + leaf b { type int32; } + } + + The 'value' node contains one instance of foo: + + + + some value + 42 + + + "; + } + } + } + + } // grouping yang-patch + + grouping yang-patch-status { + + description + "A grouping that contains a YANG container representing the + syntax and semantics of a YANG Patch Status response + message."; + + container yang-patch-status { + description + "A container representing the response message sent by the + server after a YANG Patch edit request message has been + processed."; + + leaf patch-id { + type string; + mandatory true; + description + "The 'patch-id' value used in the request."; + } + + choice global-status { + description + "Report global errors or complete success. + If there is no case selected, then errors + are reported in the 'edit-status' container."; + + case global-errors { + uses rc:errors; + description + "This container will be present if global errors that + are unrelated to a specific edit occurred."; + } + leaf ok { + type empty; + description + "This leaf will be present if the request succeeded + and there are no errors reported in the 'edit-status' + container."; + } + } + + container edit-status { + description + "This container will be present if there are + edit-specific status responses to report. + If all edits succeeded and the 'global-status' + returned is 'ok', then a server MAY omit this + container."; + + list edit { + key edit-id; + + description + "Represents a list of status responses, + corresponding to edits in the YANG Patch + request message. If an 'edit' entry was + skipped or not reached by the server, + then this list will not contain a corresponding + entry for that edit."; + + leaf edit-id { + type string; + description + "Response status is for the 'edit' list entry + with this 'edit-id' value."; + } + + choice edit-status-choice { + description + "A choice between different types of status + responses for each 'edit' entry."; + leaf ok { + type empty; + description + "This 'edit' entry was invoked without any + errors detected by the server associated + with this edit."; + } + case errors { + uses rc:errors; + description + "The server detected errors associated with the + edit identified by the same 'edit-id' value."; + } + } + } + } + } + } // grouping yang-patch-status + +}