From 0b5a305799b661510361e2d7e41b4ce9cb33632f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Fri, 13 Dec 2024 13:47:39 +0100 Subject: [PATCH] Move operational data about software state from confd => yanger Statd is now responsible for operational, move last big part (infix-system-software) to yanger. --- configs/aarch64_defconfig | 2 + configs/aarch64_minimal_defconfig | 2 + configs/x86_64_defconfig | 2 + configs/x86_64_minimal_defconfig | 2 + package/Config.in | 1 + package/rauc-installation-status/Config.in | 7 + .../rauc-installation-status.mk | 20 ++ src/confd/src/infix-system-software.c | 189 ------------------ src/rauc-installation-status/LICENSE | 14 ++ src/rauc-installation-status/Makefile.am | 25 +++ src/rauc-installation-status/configure.ac | 29 +++ .../de.pengutronix.rauc.Installer.xml | 108 ++++++++++ .../rauc-installation-status.c | 60 ++++++ src/statd/python/yanger/yanger.py | 57 ++++++ 14 files changed, 329 insertions(+), 189 deletions(-) create mode 100644 package/rauc-installation-status/Config.in create mode 100644 package/rauc-installation-status/rauc-installation-status.mk create mode 100644 src/rauc-installation-status/LICENSE create mode 100644 src/rauc-installation-status/Makefile.am create mode 100644 src/rauc-installation-status/configure.ac create mode 100644 src/rauc-installation-status/de.pengutronix.rauc.Installer.xml create mode 100644 src/rauc-installation-status/rauc-installation-status.c diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 4070f7bbd..62dd557ad 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -105,6 +105,7 @@ BR2_PACKAGE_RAUC=y BR2_PACKAGE_RAUC_DBUS=y BR2_PACKAGE_RAUC_GPT=y BR2_PACKAGE_RAUC_NETWORK=y +BR2_PACKAGE_RAUC_JSON=y BR2_PACKAGE_SYSKLOGD=y BR2_PACKAGE_SYSKLOGD_LOGGER=y BR2_PACKAGE_WATCHDOGD=y @@ -161,6 +162,7 @@ BR2_PACKAGE_TETRIS=y BR2_PACKAGE_ROUSETTE=y BR2_PACKAGE_LIBINPUT=y BR2_PACKAGE_HOST_PYTHON_YANGDOC=y +BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y DISK_IMAGE_BOOT_BIN=y TRUSTED_KEYS=y TRUSTED_KEYS_DEVELOPMENT=y diff --git a/configs/aarch64_minimal_defconfig b/configs/aarch64_minimal_defconfig index 102b80dfc..abcd8f11e 100644 --- a/configs/aarch64_minimal_defconfig +++ b/configs/aarch64_minimal_defconfig @@ -88,6 +88,7 @@ BR2_PACKAGE_RAUC=y BR2_PACKAGE_RAUC_DBUS=y BR2_PACKAGE_RAUC_GPT=y BR2_PACKAGE_RAUC_NETWORK=y +BR2_PACKAGE_RAUC_JSON=y BR2_PACKAGE_SYSKLOGD=y BR2_PACKAGE_SYSKLOGD_LOGGER=y BR2_PACKAGE_WATCHDOGD=y @@ -134,6 +135,7 @@ BR2_PACKAGE_MCD=y BR2_PACKAGE_MDNS_ALIAS=y BR2_PACKAGE_LIBINPUT=y BR2_PACKAGE_ROUSETTE=y +BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y DISK_IMAGE_BOOT_BIN=y TRUSTED_KEYS=y TRUSTED_KEYS_DEVELOPMENT=y diff --git a/configs/x86_64_defconfig b/configs/x86_64_defconfig index 06f80eb40..c9b88924e 100644 --- a/configs/x86_64_defconfig +++ b/configs/x86_64_defconfig @@ -105,6 +105,7 @@ BR2_PACKAGE_RAUC=y BR2_PACKAGE_RAUC_DBUS=y BR2_PACKAGE_RAUC_GPT=y BR2_PACKAGE_RAUC_NETWORK=y +BR2_PACKAGE_RAUC_JSON=y BR2_PACKAGE_SYSKLOGD=y BR2_PACKAGE_SYSKLOGD_LOGGER=y BR2_PACKAGE_WATCHDOGD=y @@ -164,6 +165,7 @@ BR2_PACKAGE_PODMAN_DRIVER_VFS=y BR2_PACKAGE_TETRIS=y BR2_PACKAGE_ROUSETTE=y BR2_PACKAGE_HOST_PYTHON_YANGDOC=y +BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y TRUSTED_KEYS=y TRUSTED_KEYS_DEVELOPMENT=y GNS3_APPLIANCE_RAM=512 diff --git a/configs/x86_64_minimal_defconfig b/configs/x86_64_minimal_defconfig index b7eee3189..eac7370a4 100644 --- a/configs/x86_64_minimal_defconfig +++ b/configs/x86_64_minimal_defconfig @@ -88,6 +88,7 @@ BR2_PACKAGE_RAUC=y BR2_PACKAGE_RAUC_DBUS=y BR2_PACKAGE_RAUC_GPT=y BR2_PACKAGE_RAUC_NETWORK=y +BR2_PACKAGE_RAUC_JSON=y BR2_PACKAGE_SYSKLOGD=y BR2_PACKAGE_SYSKLOGD_LOGGER=y BR2_PACKAGE_WATCHDOGD=y @@ -137,6 +138,7 @@ BR2_PACKAGE_LOWDOWN=y BR2_PACKAGE_MCD=y BR2_PACKAGE_MDNS_ALIAS=y BR2_PACKAGE_ROUSETTE=y +BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y TRUSTED_KEYS=y TRUSTED_KEYS_DEVELOPMENT=y GNS3_APPLIANCE_RAM=512 diff --git a/package/Config.in b/package/Config.in index 4fe7dbd6c..628d1f935 100644 --- a/package/Config.in +++ b/package/Config.in @@ -40,5 +40,6 @@ 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" +source "$BR2_EXTERNAL_INFIX_PATH/package/rauc-installation-status/Config.in" endmenu diff --git a/package/rauc-installation-status/Config.in b/package/rauc-installation-status/Config.in new file mode 100644 index 000000000..c2ea73e8e --- /dev/null +++ b/package/rauc-installation-status/Config.in @@ -0,0 +1,7 @@ +config BR2_PACKAGE_RAUC_INSTALLATION_STATUS + bool rauc-installation-status + help + Simple tool to read the installation status and errors + from rauc in a JSON format. + + https://github.com/kernelkit/infix \ No newline at end of file diff --git a/package/rauc-installation-status/rauc-installation-status.mk b/package/rauc-installation-status/rauc-installation-status.mk new file mode 100644 index 000000000..9036e275a --- /dev/null +++ b/package/rauc-installation-status/rauc-installation-status.mk @@ -0,0 +1,20 @@ +################################################################################ +# +# rauc installation status +# +################################################################################ + +RAUC_INSTALLATION_STATUS_VERSION = 1.0 +RAUC_INSTALLATION_STATUS_LICENSE = ISC +RAUC_INSTALLATION_STATUS_LICENSE_FILES = LICENSE +RAUC_INSTALLATION_STATUS_SITE_METHOD = local +RAUC_INSTALLATION_STATUS_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/rauc-installation-status +RAUC_INSTALLATION_STATUS_REDISTRIBUTE = NO +RAUC_INSTALLATION_STATUS_AUTORECONF = YES +RAUC_INSTALLATION_STATUS_DEPENDENCIES = host-pkgconf jansson libglib2 +RAUC_INSTALLATION_STATUS_CONF_OPTS = --disable-silent-rules +define RAUC_INSTALLATION_STATUS_CONF_ENV + CFLAGS="$(INFIX_CFLAGS)" +endef + +$(eval $(autotools-package)) diff --git a/src/confd/src/infix-system-software.c b/src/confd/src/infix-system-software.c index 03c205dd5..e6e81ab7e 100644 --- a/src/confd/src/infix-system-software.c +++ b/src/confd/src/infix-system-software.c @@ -7,7 +7,6 @@ #include "core.h" #include "rauc-installer.h" -#define SW_STATE_PATH_ "/ietf-system:system-state/infix-system:software" static RaucInstaller *infix_system_sw_new_rauc(void) { @@ -25,191 +24,6 @@ static RaucInstaller *infix_system_sw_new_rauc(void) return rauc; } -static sr_error_t infix_system_sw_state_fill_installer(struct lyd_node *inst, - RaucInstaller *rauc) -{ - struct lyd_node *progress; - GVariant *props, *val; - const char *strval; - - strval = rauc_installer_get_operation(rauc); - if (strval && strval[0] && - lyd_new_term(inst, NULL, "operation", strval, 0, NULL)) - return SR_ERR_INTERNAL; - - strval = rauc_installer_get_last_error(rauc); - if (strval && strval[0] && - lyd_new_term(inst, NULL, "last-error", strval, 0, NULL)) - return SR_ERR_INTERNAL; - - props = rauc_installer_get_progress(rauc); - if (props) { - if (lyd_new_inner(inst, NULL, "progress", 0, &progress)) - return SR_ERR_INTERNAL; - - g_variant_get(props, "(@isi)", &val, &strval, NULL); - - if (lyd_new_term(progress, NULL, "percentage", - g_variant_print(val, FALSE), 0, NULL)) - return SR_ERR_INTERNAL; - - if (strval && strval[0] && - lyd_new_term(progress, NULL, "message", strval, 0, NULL)) - return SR_ERR_INTERNAL; - } - return SR_ERR_OK; -} - -static sr_error_t infix_system_sw_state_fill_slot(struct lyd_node *slot, - GVariant *props) -{ - static const char *strprops[] = { - "bootname", - "class", - "state", - "sha256", - NULL - }; - struct lyd_node *section; - const char **strprop; - const char *strval; - GVariant *val; - - for (strprop = strprops; *strprop; strprop++) { - if (g_variant_lookup(props, *strprop, "s", &strval) && - lyd_new_term(slot, NULL, *strprop, strval, 0, NULL)) - return SR_ERR_INTERNAL; - } - - if (g_variant_lookup(props, "size", "@t", &val) && - lyd_new_term(slot, NULL, "size", g_variant_print(val, FALSE), 0, NULL)) - return SR_ERR_INTERNAL; - - - if (lyd_new_inner(slot, NULL, "bundle", 0, §ion)) - return SR_ERR_INTERNAL; - - if (g_variant_lookup(props, "bundle.compatible", "s", &strval) && - lyd_new_term(section, NULL, "compatible", strval, 0, NULL)) - return SR_ERR_INTERNAL; - - if (g_variant_lookup(props, "bundle.version", "s", &strval) && - lyd_new_term(section, NULL, "version", strval, 0, NULL)) - return SR_ERR_INTERNAL; - - - if (lyd_new_inner(slot, NULL, "installed", 0, §ion)) - return SR_ERR_INTERNAL; - - if (g_variant_lookup(props, "installed.timestamp", "s", &strval) && - lyd_new_term(section, NULL, "datetime", strval, 0, NULL)) - return SR_ERR_INTERNAL; - - if (g_variant_lookup(props, "installed.count", "@u", &val) && - lyd_new_term(section, NULL, "count", g_variant_print(val, FALSE), 0, NULL)) - return SR_ERR_INTERNAL; - - - if (lyd_new_inner(slot, NULL, "activated", 0, §ion)) - return SR_ERR_INTERNAL; - - if (g_variant_lookup(props, "activated.timestamp", "s", &strval) && - lyd_new_term(section, NULL, "datetime", strval, 0, NULL)) - return SR_ERR_INTERNAL; - - if (g_variant_lookup(props, "activated.count", "@u", &val) && - lyd_new_term(section, NULL, "count", g_variant_print(val, FALSE), 0, NULL)) - return SR_ERR_INTERNAL; - - return SR_ERR_OK; -} - -static sr_error_t infix_system_sw_state_fill(struct lyd_node *sw, - RaucInstaller *rauc) -{ - struct lyd_node *slot, *inst; - GVariant *slots, *props; - GError *raucerr = NULL; - GVariantIter slotiter; - sr_error_t srerr; - char *slotname; - const char *val; - - val = rauc_installer_get_compatible(rauc); - if (val && val[0] && lyd_new_term(sw, NULL, "compatible", val, 0, NULL)) - return SR_ERR_INTERNAL; - - val = rauc_installer_get_variant(rauc); - if (val && val[0] && lyd_new_term(sw, NULL, "variant", val, 0, NULL)) - return SR_ERR_INTERNAL; - - val = rauc_installer_get_boot_slot(rauc); - if (val && val[0] && lyd_new_term(sw, NULL, "booted", val, 0, NULL)) - return SR_ERR_INTERNAL; - - if (lyd_new_inner(sw, NULL, "installer", 0, &inst)) - return SR_ERR_INTERNAL; - - srerr = infix_system_sw_state_fill_installer(inst, rauc); - if (srerr) - return srerr; - - if (!rauc_installer_call_get_slot_status_sync(rauc, &slots, NULL, &raucerr)) { - /* Slot status is not available while an installation - * is in progress, so we don't consider that an error. - */ - g_error_free(raucerr); - return SR_ERR_OK; - } - - for (g_variant_iter_init(&slotiter, slots); - g_variant_iter_next(&slotiter, "(s@a{sv})", &slotname, &props);) { - if (lyd_new_list(sw, NULL, "slot", 0, &slot, slotname)) - return SR_ERR_INTERNAL; - - srerr = infix_system_sw_state_fill_slot(slot, props); - if (srerr) - break; - } - - return srerr; -} - -static int infix_system_sw_state(sr_session_ctx_t *session, uint32_t sub_id, - const char *module, const char *path, - const char *request_path, uint32_t request_id, - struct lyd_node **parent, void *priv) -{ - sr_error_t srerr = SR_ERR_INTERNAL; - const struct lys_module *ixsys; - const struct ly_ctx *ly; - RaucInstaller *rauc; - struct lyd_node *sw; - - DEBUG("%s", path); - - rauc = infix_system_sw_new_rauc(); - if (!rauc) - return SR_ERR_INTERNAL; - - ly = sr_acquire_context(sr_session_get_connection(session)); - ixsys = ly_ctx_get_module_implemented(ly, "infix-system"); - sr_release_context(sr_session_get_connection(session)); - if (!ixsys) { - ERROR("infix-system module not found"); - goto out; - } - - if (lyd_new_inner(*parent, ixsys, "software", 0, &sw)) - goto out; - - srerr = infix_system_sw_state_fill(sw, rauc); -out: - g_object_unref(rauc); - return srerr; -} - - static int infix_system_sw_install(sr_session_ctx_t *session, uint32_t sub_id, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, @@ -243,9 +57,6 @@ int infix_system_sw_init(struct confd *confd) { int rc = 0; - REGISTER_OPER(confd->session, "ietf-system", SW_STATE_PATH_, - infix_system_sw_state, NULL, 0, &confd->sub); - REGISTER_RPC(confd->session, "/infix-system:install-bundle", infix_system_sw_install, NULL, &confd->sub); diff --git a/src/rauc-installation-status/LICENSE b/src/rauc-installation-status/LICENSE new file mode 100644 index 000000000..65e3295d8 --- /dev/null +++ b/src/rauc-installation-status/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2024 The KernelKit Authors + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + diff --git a/src/rauc-installation-status/Makefile.am b/src/rauc-installation-status/Makefile.am new file mode 100644 index 000000000..a6cca2c0c --- /dev/null +++ b/src/rauc-installation-status/Makefile.am @@ -0,0 +1,25 @@ +AM_CPPFLAGS = -D_DEFAULT_SOURCE -D_XOPEN_SOURCE -D_GNU_SOURCE +bin_PROGRAMS = rauc-installation-status +rauc_installation_status_SOURCES = rauc-installation-status.c + +rauc_installation_status_CFLAGS = \ + $(glib_CFLAGS) \ + $(jansson_CFLAGS) \ + $(CFLAGS) +rauc_installation_status_LDADD = \ + $(glib_LIBS) \ + $(jansson_LIBS) + +BUILT_SOURCES = $(rauc_installer_sources) +EXTRA_DIST = de.pengutronix.rauc.Installer.xml + +rauc_installer_sources = rauc-installer.c rauc-installer.h +$(rauc_installer_sources): de.pengutronix.rauc.Installer.xml + $(AM_V_GEN) gdbus-codegen \ + --generate-c-code rauc-installer \ + --c-generate-autocleanup all \ + --c-namespace Rauc \ + --interface-prefix de.pengutronix.rauc. \ + $< + +nodist_rauc_installation_status_SOURCES = $(rauc_installer_sources) diff --git a/src/rauc-installation-status/configure.ac b/src/rauc-installation-status/configure.ac new file mode 100644 index 000000000..0e7b579e8 --- /dev/null +++ b/src/rauc-installation-status/configure.ac @@ -0,0 +1,29 @@ +AC_PREREQ(2.61) +AC_INIT([rauc-installation-status], [1.0], [https://github.com/kernelkit/infix/issues]) +AM_INIT_AUTOMAKE(1.11 foreign subdir-objects) +AM_SILENT_RULES(yes) + +AC_CONFIG_FILES([ + Makefile +]) + +AC_PROG_CC +AC_PROG_INSTALL +LT_INIT + + +PKG_PROG_PKG_CONFIG + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.50 gio-2.0 gio-unix-2.0]) +PKG_CHECK_MODULES([jansson], [jansson >= 2.0.0]) + + +LIBDIR=`eval echo $libdir` +LIBDIR=`eval echo $LIBDIR` + +AC_SUBST(LIBDIR) + +AC_OUTPUT diff --git a/src/rauc-installation-status/de.pengutronix.rauc.Installer.xml b/src/rauc-installation-status/de.pengutronix.rauc.Installer.xml new file mode 100644 index 000000000..2a92de4fa --- /dev/null +++ b/src/rauc-installation-status/de.pengutronix.rauc.Installer.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/rauc-installation-status/rauc-installation-status.c b/src/rauc-installation-status/rauc-installation-status.c new file mode 100644 index 000000000..bb98ebb3d --- /dev/null +++ b/src/rauc-installation-status/rauc-installation-status.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +#include +#include +#include + +#include "rauc-installer.h" + +static RaucInstaller *infix_system_sw_new_rauc(void) { + RaucInstaller *rauc; + GError *raucerr = NULL; + + rauc = rauc_installer_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "de.pengutronix.rauc", "/", NULL, &raucerr); + if (raucerr) { + fprintf(stderr, "Unable to connect to RAUC: %s\n", raucerr->message); + g_error_free(raucerr); + return NULL; + } + + return rauc; +} + + +int main(int argc, char **argv) +{ + json_t *json, *progress; + RaucInstaller *rauc; + const char *strval; + GVariant *props; + char *output; + + + rauc = infix_system_sw_new_rauc(); + if (!rauc) + return 1; + + json = json_object(); + if (!json) + return 1; + + strval = rauc_installer_get_operation(rauc); + if (strval && strval[0]) + json_object_set_new(json, "operation", json_string(strval)); + + props = rauc_installer_get_progress(rauc); + if(props) { + GVariant *val; + progress = json_object(); + g_variant_get(props, "(@isi)", &val, &strval, NULL); + json_object_set_new(progress, "percentage", json_string(g_variant_print(val, FALSE))); + json_object_set_new(progress, "message", json_string(strval)); + json_object_set_new(json, "progress", progress); + } + output = json_dumps(json, 0); + printf("%s", output); + free(output); + json_decref(json); + + return 0; +} diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py index cca4b903b..5f0da062a 100755 --- a/src/statd/python/yanger/yanger.py +++ b/src/statd/python/yanger/yanger.py @@ -1080,7 +1080,64 @@ def add_system_ntp(out): source.append(src) insert(out, "infix-system:ntp", "sources", "source", source) + +def add_system_software_installer(out): + data = run_json_cmd(["rauc-installation-status"], "") + installer={} + progress={} + + if data.get("operation"): + installer["operation"] = data["operation"] + if data.get("progress"): + if data.get("percentage"): + progress["percentage"] = data["percentage"] + if data.get("message"): + progress["message"] = data["message"] + installer["progress"] = progress + insert(out, "installer", installer) + +def add_system_software(out): + data = run_json_cmd(["rauc", "status", "--detailed", "--output-format=json"], "rauc-status.json") + software = {} + software["compatible"] = data["compatible"] + software["variant"] = data["variant"] + software["booted"] = data["booted"] + software["installer"] = {} + slots=[] + for slot in data["slots"]: + for key, value in slot.items(): + new = {} + new["name"] = key + new["bootname"] = slot[key].get("bootname") + new["class"] = slot[key].get("class") + new["state"] = slot[key].get("state") + new["bundle"] = {} + + if value.get("slot_status",{}).get("bundle", {}).get("compatible"): + new["bundle"]["compatible"] = value.get("slot_status",{}).get("bundle", {}).get("compatible") + if value.get("slot_status", {}).get("bundle", {}).get("version"): + new["bundle"]["version"] = value.get("slot_status", {}).get("bundle", {}).get("version") + if value.get("checksum", {}).get("size"): + new["size"] = value.get("checksum", {}).get("size") + if value.get("checksum", {}).get("sha256"): + new["sha256"] = value.get("checksum", {}).get("sha256") + new["installed"] = {} + if value.get("installed", {}).get("timestamp"): + new["installed"]["datetime"] = value.get("installed", {}).get("timestamp") + if value.get("installed", {}).get("count"): + new["installed"]["count"] = value.get("installed", {}).get("count") + new["activated"] = {} + if value.get("activated", {}).get("timestamp"): + new["activated"]["datetime"] = value.get("activated", {}).get("timestamp") + if value.get("activated", {}).get("count"): + new["activated"]["count"] = value.get("activated", {}).get("count") + slots.append(new) + software["slot"] = slots + add_system_software_installer(software) + insert(out, "infix-system:software", software) + def add_system(yang_data): + add_system_software(yang_data) add_system_ntp(yang_data) def main():