]> git.99rst.org Git - openwrt-packages.git/commitdiff
nut: belatedly add migration for nut-monitor changes
authorDaniel F. Dickinson <redacted>
Sat, 30 May 2026 22:23:15 +0000 (18:23 -0400)
committerJosef Schlehofer <redacted>
Thu, 2 Jul 2026 04:43:08 +0000 (06:43 +0200)
Add previously missed migration script (uci-defaults) for changes
to nut-monitor initscript.

Created with the help of iterative code reviews by
Qwen3.6-27B (LLM model) running on llama.cpp (local LLM server),
controlled by LATE.

Signed-off-by: Daniel F. Dickinson <redacted>
net/nut/Makefile
net/nut/files/nut-monitor-migrate.default [new file with mode: 0644]

index 2a8f2d7458845539965c171f43ca79245a70cc2e..7301ca5e440a695c08c7aec9191812e9a2c21ff8 100644 (file)
@@ -161,23 +161,25 @@ process. Every UPS that is defined in the upsmon.conf configuration file
 is assigned a power value and a type (secondary or primary).
 endef
 
-define Package/nut-upsmon/conffiles
-/etc/config/nut_monitor
-/etc/nut/upsmon.conf
-endef
-
 define Package/nut-upsmon/install
        $(INSTALL_DIR) $(1)/etc/nut
        $(INSTALL_DIR) $(1)/usr/sbin
        $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_DIR) $(1)/etc/uci-defaults
        $(INSTALL_BIN) ./files/nut-monitor.init $(1)/etc/init.d/nut-monitor
        $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/upsmon $(1)/usr/sbin/
        $(INSTALL_BIN) ./files/nutshutdown $(1)/usr/sbin/nutshutdown
+       $(INSTALL_DATA) ./files/nut-monitor-migrate.default $(1)/etc/uci-defaults/80-nut-monitor-migrate
        $(INSTALL_DIR) $(1)/etc/config
        $(INSTALL_CONF) ./files/nut_monitor $(1)/etc/config/nut_monitor
        ln -sf /var/etc/nut/upsmon.conf $(1)/etc/nut/upsmon.conf
 endef
 
+define Package/nut-upsmon/conffiles
+/etc/config/nut_monitor
+/etc/nut/upsmon.conf
+endef
+
 define Package/nut-upsmon-sendmail-notify
        $(call Package/nut/Default)
        TITLE+= (upsmon with notifications via sendmail)
@@ -287,10 +289,6 @@ other uses that are possible.
 You can alternatively write your own script and save some space.
 endef
 
-define Package/nut-upssched/conffiles
-/etc/nut/upssched.conf
-endef
-
 define Package/nut-upssched/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_DIR) $(1)/usr/sbin
@@ -302,6 +300,10 @@ define Package/nut-upssched/install
        $(INSTALL_DATA) ./files/nut-sched.default $(1)/etc/uci-defaults/nut-upssched
 endef
 
+define Package/nut-upssched/conffiles
+/etc/nut/upssched.conf
+endef
+
 define Package/nut-web-cgi
        $(call Package/nut/Default)
        TITLE+= Web CGI interface
@@ -354,15 +356,15 @@ This package contains the service definition for announcing the
 attached UPS via mDNS/DNS-SD.
 endef
 
-define Package/nut-avahi-service/conffiles
-/etc/avahi/services/nut.service
-endef
-
 define Package/nut-avahi-service/install
        $(INSTALL_DIR) $(1)/etc/avahi/services
        $(INSTALL_CONF) ./files/nut.service $(1)/etc/avahi/services/
 endef
 
+define Package/nut-avahi-service/conffiles
+/etc/avahi/services/nut.service
+endef
+
 # Dealing with all of the drivers is very repetitive, but the previous
 # maintainer had a neat solution which just needed some tweaking.
 define DriverPackage
@@ -373,7 +375,7 @@ define DriverPackage
                $(if $(filter $(1),snmp),DEPENDS+= @NUT_DRIVER_SNMP)
                $(if $(filter $(1),usb),DEPENDS+= @NUT_DRIVER_USB)
                $(if $(filter $(1),serial),DEPENDS+= @NUT_DRIVER_SERIAL)
-                $(if $(filter $(1),neon),DEPENDS+= @NUT_DRIVER_NEON)
+               $(if $(filter $(1),neon),DEPENDS+= @NUT_DRIVER_NEON)
         endef
        # Deliberately empty description in order to trigger a build failure.
        # It should be overridden by the list below, and when updating to a
diff --git a/net/nut/files/nut-monitor-migrate.default b/net/nut/files/nut-monitor-migrate.default
new file mode 100644 (file)
index 0000000..ff65a39
--- /dev/null
@@ -0,0 +1,246 @@
+#!/bin/sh
+# Script is sourced not executed, but shebang helps tools recognize this as
+# a shell script.
+
+# In recent (relevant) versions of shellcheck busybox is a valid shell type
+# shellcheck shell=busybox
+
+# uci-defaults script to migrate old uci config for notifications and monitor sections,
+# to the new. Applied during install or on first boot after install, if setting on install
+# fails
+
+# IPKG_INSTROOT is intentionally only set when building an image and
+# is intentionally empty on a live OpenWrt device
+
+# Only run this uci-defaults script on a live OpenWrt device
+[ -z "${IPKG_INSTROOT}" ] || exit 0
+
+# Loads needed OpenWrt functions
+# shellcheck source=net/nut/files/functions.sh.functions
+. /lib/functions.sh || {
+       # As the uci-defaults environment in which this runs does not have logging
+       # available, nor is stderr captured or displayed on the console, these messages
+       # exist only to assist when debugging manual runs of the script.
+       printf "'%s': ERROR: '%s'\n" nut-monitor-migrate "Unable to source 'functions.sh' in 'nut-monitor-migrate' uci-default script. Bailing"
+       exit 1
+}
+
+# Adds notification flag (value) to 'notify_flags' from caller
+# shellcheck disable=SC2329,SC2317
+get_notify_flags() {
+       local value="$1"
+
+       append notify_flags "$value" "+"
+}
+
+# shellcheck disable=SC2329,SC2317
+convert_flags() {
+       local notify_flags="$1"
+       local working_flags=""
+       local flag_val
+
+       # In input flags can be in any order. If any of the input flags are IGNORE,
+       # the output should only contain IGNORE. If the input contains only SYSLOG
+       # or only EXEC, use as is. If the input contains both SYSLOG and EXEC (in
+       # any order) the output must be SYSLOG+EXEC
+       for flag_val in IGNORE SYSLOG EXEC; do
+               # If the notify_flags contains $flag_val
+               case "$notify_flags" in
+               "$flag_val"+* | *+"$flag_val" | "$flag_val")
+                       case "$flag_val" in
+                       IGNORE)
+                               working_flags="IGNORE"
+                               printf "%s" "$working_flags"
+                               return
+                               ;;
+                       SYSLOG)
+                               # If working flags exists, it already has a non SYSLOG value
+                               # SYSLOG must come first in the final flags, so append
+                               # old working_flags to SYSLOG with delimiter '+', and make
+                               # that the new working_flags
+                               if [ "$working_flags" = "EXEC" ]; then
+                                       working_flags="${flag_val}+${working_flags}"
+                               else
+                                       working_flags="$flag_val"
+                               fi
+                               ;;
+                       EXEC)
+                               # append to an empty variable just returns the value to be
+                               # appended without a delimiter, so we do not need to check
+                               # for already having a value in 'working_flags'
+                               append working_flags "$flag_val" "+"
+                               ;;
+                       esac
+                       ;;
+               esac
+       done
+       printf "%s" "$working_flags"
+}
+
+# As the uci-defaults environment in which this runs does not have logging
+# available, nor is stderr captured or displayed on the console, these messages
+# exist only to assist when debugging manual runs of the script.
+# shellcheck disable=SC2329,SC2317
+log_migration_error() {
+       local reason="$1"
+
+       printf "'%s': ERROR: '%s'\n" "nut-monitor-migrate" "$reason" >&2
+}
+
+# shellcheck disable=SC2329,SC2317
+get_notification_flags() {
+       local uci_option="$1"
+       local cfg="$2"
+       local notify_flags=""
+       # accumulates flags in notify_flags via get_notify_flags
+       config_list_foreach "$cfg" "$uci_option" get_notify_flags
+       convert_flags "$notify_flags"
+}
+
+# shellcheck disable=SC2329,SC2317
+process_upsmon_section() {
+       local cfg="$1"
+       local notify_type flag_name notify_msg notify_section
+       local notification_name notify_flags_as_var upsmon_final_flags
+       # List of notification messages options in existing (to be converted)
+       # UCI config for nut_monitor
+       local nut_notify_message_types="onlinemsg onbattmsg lowbattmsg fsdmsg commokmsg"
+       append nut_notify_message_types "commbadmsg shutdownmsg replbattmsg"
+       append nut_notify_message_types "nocommmsmsg nocommmsg noparentmsg"
+
+       # We need word-splitting to iterate over nut_notify_message_types
+       # This is a local variable defined by us, so it is safe to do this.
+       # We still disable globbing of the word-split
+       set -f
+       for notify_type in $nut_notify_message_types; do
+               # Transform <prefix>msg into <prefix>notify (flag_name) and <PREFIX> (notification_name)
+               flag_name="${notify_type/msg/notify}"
+               notification_name="${notify_type/msg/}"
+               # busybox ash does not support case transformation via variable  parameter substitution,
+               # so we use tr.
+               notification_name="$(printf '%s' "$notification_name" | tr '[:lower:]' '[:upper:]')"
+               # Transform wrong NOCOMMS to NOCOMM (typo in nocommsmsg which should
+               # have been nocommmsg in previous script)
+               if [ "$notification_name" = "NOCOMMMS" ]; then
+                       notification_name="NOCOMM"
+               fi
+               config_get notify_msg "$cfg" "$notify_type"
+               config_get notify_flags_as_var "$cfg" "$flag_name"
+               if [ -n "$notify_msg" ] || [ -n "$notify_flags_as_var" ]; then
+                       notify_section="$(uci -q add nut_monitor notifications)"
+                       if [ -z "$notify_section" ]; then
+                               log_migration_error "Failed to add notifications section"
+                               # We don't want to prevent other sections from being processed
+                               # if this one fails, so do not error exit, but keep going.
+                               continue
+                       fi
+                       if ! uci -q rename nut_monitor."$notify_section"="$notification_name"; then
+                               log_migration_error "Failed to rename '$notify_section' to '$notification_name'"
+                               # We don't want to prevent other sections from being processed
+                               # if this one fails, so do not error exit, but keep going.
+                               continue
+                       fi
+               fi
+               if [ -n "$notify_msg" ]; then
+                       if ! uci -q set nut_monitor."$notification_name".message="$notify_msg"; then
+                               log_migration_error "Failed to add message for '$notification_name'"
+                               continue
+                       fi
+               fi
+               upsmon_final_flags="$(get_notification_flags "$flag_name" "$cfg")"
+               if [ -n "$upsmon_final_flags" ]; then
+                       if ! uci -q set nut_monitor."$notification_name".flag="$upsmon_final_flags"; then
+                               log_migration_error "Failed to add flag(s) to '$notification_name'"
+                               continue
+                       fi
+               fi
+
+               # Keep going even if deleting old flag fails. It won't be used
+               # anyway, and partial success is better than none.
+               if [ -n "$cfg" ] && [ -n "$notify_flags_as_var" ] && ! uci -q delete nut_monitor."$cfg"."$flag_name"; then
+                       log_migration_error "Failed to delete old flag '$flag_name' from '$cfg'"
+               fi
+               # Keep going even if deleting old notification message fails. It
+               # won't be used anyway, and partial success is better than none.
+               if [ -n "$cfg" ] && [ -n "$notify_msg" ] && ! uci -q delete nut_monitor."$cfg"."$notify_type"; then
+                       log_migration_error "Failed to delete old notification type '$notify_type' from '$cfg'"
+               fi
+       done
+       set +f
+       upsmon_final_flags="$(get_notification_flags "defaultnotify" "$cfg")"
+       if [ -n "$upsmon_final_flags" ]; then
+               if ! uci -q set nut_monitor."$cfg".defaultnotify="$upsmon_final_flags"; then
+                       log_migration_error "Failed to update defaultnotify for '$cfg'"
+               fi
+       fi
+}
+
+# shellcheck disable=SC2329,SC2317
+process_primary_secondary() {
+       local cfg="$1"
+       local monitor_type="$2"
+       local upsname hostname port powervalue username password section
+
+       section="$(uci -q add nut_monitor monitor)" || {
+               log_migration_error "Failed to add monitor section to replace '$cfg'"
+               # Do not error exit as we do not want to stop other sections from being
+               # processed
+               return 0
+       }
+
+       if [ -n "$section" ]; then
+               {
+                       uci -q set nut_monitor."$section".type="$monitor_type" || return 1
+
+                       # Empty values are allowed and should remain as such in the new
+                       # section.
+                       config_get upsname "$cfg" upsname
+                       config_get hostname "$cfg" hostname
+                       config_get port "$cfg" port
+                       config_get powervalue "$cfg" powervalue
+                       config_get username "$cfg" username
+                       config_get password "$cfg" password
+
+                       uci -q set nut_monitor."$section".upsname="$upsname" || return 1
+                       uci -q set nut_monitor."$section".hostname="$hostname" || return 1
+                       uci -q set nut_monitor."$section".port="$port" || return 1
+                       uci -q set nut_monitor."$section".powervalue="$powervalue" || return 1
+                       uci -q set nut_monitor."$section".username="$username" || return 1
+                       uci -q set nut_monitor."$section".password="$password" || return 1
+
+                       # Delete the old section with name config (of type primary
+                       # or secondary)
+                       uci -q delete nut_monitor."$cfg" || return 1
+                       # Rename the nut_monitor section '$section' we created, above, with
+                       # the name of the old section. This requires that the old section
+                       # with the same name has already been removed.
+                       # In the event of delete failure, the new section is present, but
+                       # with the name assigned when the new section was created.
+                       uci -q rename nut_monitor."$section"="$cfg" || return 1
+                       return 0
+               } || {
+                       log_migration_error "Error converting primary/secondary section '$cfg'"
+                       # Do not error exit as we do not want to stop other sections from
+                       # being processed
+                       return 0
+               }
+       else
+               log_migration_error "Name of monitor section to replace '$cfg' was empty"
+               # Do not error exit as we do not want to stop other sections from being
+               # processed
+               return 0
+
+       fi
+}
+
+config_load nut_monitor || {
+       echo "nut-monitor-migrate: FATAL: Failed to load nut_monitor"
+       exit 1
+}
+config_foreach process_upsmon_section upsmon
+config_foreach process_primary_secondary master primary
+config_foreach process_primary_secondary slave secondary
+
+uci commit nut_monitor
+
+exit 0
git clone https://git.99rst.org/PROJECT