From bb1b12733e1a90c8d4fefa00c75cb4100395e40b Mon Sep 17 00:00:00 2001 From: "Daniel F. Dickinson" Date: Mon, 20 Aug 2018 20:06:31 -0400 Subject: [PATCH] nut: Backport fixes from master Backport and squash the following commits from master: 5790053eb nut: Add missing conffiles ceff68837 nut: Reorganize nut-server to clarify nut-driver f6a2a97d2 nut: Use 'real' procd init for nut-monitor 918a62f91 nut: Make FSD really work a2f64b3ba nut: Reduce user error with POWERDOWNFLAG 461393810 nut: Use quotes around filenames 1b6dbe7a7 nut: Remove duplicate/extraneous lines 0a49d0ffb nut: Fix checking for path before it exists 3b5a8eee8 nut: Various startup fixes for monitor and server 44e57d4bd nut: Fix variables for NUT drivers 36fd59dc7 nut: Fix extraneous config_get 192b0f164 nut: Fix a typo in setting a driver parameter f48b060fa nut: Fix upsd runs as root And bump PKG_RELEASE Signed-off-by: Daniel F. Dickinson --- net/nut/Makefile | 24 ++- net/nut/files/nut-cgi.init | 2 +- net/nut/files/nut-monitor.init | 141 ++++++++------ net/nut/files/nut-server.init | 347 ++++++++++++++++++++++++--------- net/nut/files/nut_monitor | 4 +- net/nut/files/nut_server | 1 + net/nut/files/nutshutdown | 41 ++++ 7 files changed, 395 insertions(+), 165 deletions(-) create mode 100755 net/nut/files/nutshutdown diff --git a/net/nut/Makefile b/net/nut/Makefile index 2a253f8c08..06bde9ba69 100644 --- a/net/nut/Makefile +++ b/net/nut/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nut PKG_VERSION:=2.7.4 -PKG_RELEASE:=7 +PKG_RELEASE:=8 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.networkupstools.org/source/2.7/ @@ -63,22 +63,22 @@ define Package/nut/install endef define Package/nut-server/install + # Server portion $(INSTALL_DIR) $(1)/etc/nut $(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_DIR) $(1)/usr/share/nut - $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/nut-server.init $(1)/etc/init.d/nut-server $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/upsd $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/upsdrvctl $(1)/usr/sbin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/share/nut/cmdvartab $(1)/usr/share/nut/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/share/nut/driver.list $(1)/usr/share/nut/ $(INSTALL_DIR) $(1)/etc/config $(INSTALL_CONF) ./files/nut_server $(1)/etc/config/nut_server - ln -sf /var/etc/nut/nut.conf $(1)/etc/nut/nut.conf - ln -sf /var/etc/nut/ups.conf $(1)/etc/nut/ups.conf ln -sf /var/etc/nut/upsd.users $(1)/etc/nut/upsd.users ln -sf /var/etc/nut/upsd.conf $(1)/etc/nut/upsd.conf + # Driver common portion + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/upsdrvctl $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/share/nut/driver.list $(1)/usr/share/nut/ + ln -sf /var/etc/nut/ups.conf $(1)/etc/nut/ups.conf endef define Package/nut-common @@ -96,6 +96,10 @@ $(call Package/nut/description/Default) This package contains the common files. endef +define Package/nut-common/conffiles +/etc/nut/nut.conf +endef + define Package/nut-common/install $(INSTALL_DIR) $(1)/etc/nut $(INSTALL_DIR) $(1)/usr/lib @@ -107,6 +111,7 @@ define Package/nut-server $(call Package/nut/Default) TITLE+= (server) DEPENDS:=nut +nut-common + USERID:=nut=113:nut=113 endef define Package/nut-server/description @@ -120,6 +125,9 @@ endef define Package/nut-server/conffiles /etc/config/nut_server +/etc/nut/upsd.conf +/etc/nut/upsd.users +/etc/nut/ups.conf endef define Package/nut-upsmon @@ -141,6 +149,7 @@ endef define Package/nut-upsmon/conffiles /etc/config/nut_monitor +/etc/nut/upsmon.conf endef define Package/nut-upsmon/install @@ -149,6 +158,7 @@ define Package/nut-upsmon/install $(INSTALL_DIR) $(1)/etc/init.d $(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_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 @@ -342,7 +352,7 @@ define DriverPackage define Package/nut-driver-$(2) $(call Package/nut/Default) TITLE:=$(2) (NUT $(1) driver) - DEPENDS:=nut +nut-common + DEPENDS:=nut +nut-server $(if $(filter $(1),snmp),DEPENDS+= @NUT_DRIVER_SNMP) $(if $(filter $(1),usb),DEPENDS+= @NUT_DRIVER_USB) $(if $(filter $(1),serial),DEPENDS+= @NUT_DRIVER_SERIAL) diff --git a/net/nut/files/nut-cgi.init b/net/nut/files/nut-cgi.init index d63d98ba95..13f1297fe7 100755 --- a/net/nut/files/nut-cgi.init +++ b/net/nut/files/nut-cgi.init @@ -25,7 +25,7 @@ nut_upscgi_add() { system="$system:$port"; fi config_get displayname "$cfg" displayname - echo "MONITOR $system \"$displayname\"" >> $UPSCGI_C + echo "MONITOR $system \"$displayname\"" >> "$UPSCGI_C" } start() { diff --git a/net/nut/files/nut-monitor.init b/net/nut/files/nut-monitor.init index af81407810..6a390b4ef4 100755 --- a/net/nut/files/nut-monitor.init +++ b/net/nut/files/nut-monitor.init @@ -1,61 +1,60 @@ #!/bin/sh /etc/rc.common -START=60 +START=51 USE_PROCD=1 UPSMON_C=/var/etc/nut/upsmon.conf nut_upsmon_conf() { local cfg="$1" - echo "# Config file automatically generated from UCI config" > $UPSMON_C + echo "# Config file automatically generated from UCI config" > "$UPSMON_C" config_get runas "$cfg" runas "nut" [ -n "$runas" ] && echo "RUN_AS_USER $runas" >> $UPSMON_C config_get val "$cfg" minsupplies 1 - echo "MINSUPPLIES $val" >> $UPSMON_C + echo "MINSUPPLIES $val" >> "$UPSMON_C" - config_get val "$cfg" shutdowncmd "/sbin/halt" - echo "SHUTDOWNCMD \"$val\"" >> $UPSMON_C + config_get val "$cfg" shutdowncmd "/usr/sbin/nutshutdown" + echo "SHUTDOWNCMD \"$val\"" >> "$UPSMON_C" config_get val "$cfg" notifycmd - [ -n "$val" ] && echo "NOTIFYCMD \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYCMD \"$val\"" >> "$UPSMON_C" config_get val "$cfg" pollfreq 5 - echo "POLLFREQ $val" >> $UPSMON_C + echo "POLLFREQ $val" >> "$UPSMON_C" config_get val "$cfg" pollfreqalert 5 - echo "POLLFREQALERT $val" >> $UPSMON_C + echo "POLLFREQALERT $val" >> "$UPSMON_C" config_get val "$cfg" hostsync 15 - echo "HOSTSYNC $val" >> $UPSMON_C + echo "HOSTSYNC $val" >> "$UPSMON_C" config_get val "$cfg" deadtime 15 - echo "DEADTIME $val" >> $UPSMON_C + echo "DEADTIME $val" >> "$UPSMON_C" - config_get val "$cfg" powerdownflag /var/run/killpower - echo "POWERDOWNFLAG $val" >> $UPSMON_C + echo "POWERDOWNFLAG /var/run/killpower" >> "$UPSMON_C" config_get val "$cfg" onlinemsg - [ -n "$val" ] && echo "NOTIFYMSG ONLINE \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG ONLINE \"$val\"" >> "$UPSMON_C" config_get val "$cfg" onbattmsg - [ -n "$val" ] && echo "NOTIFYMSG ONBATT \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG ONBATT \"$val\"" >> "$UPSMON_C" config_get val "$cfg" lowbattmsg - [ -n "$val" ] && echo "NOTIFYMSG LOWBATT \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG LOWBATT \"$val\"" >> "$UPSMON_C" config_get val "$cfg" fsdmsg - [ -n "$val" ] && echo "NOTIFYMSG FSD \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG FSD \"$val\"" >> "$UPSMON_C" config_get val "$cfg" commokmsg - [ -n "$val" ] && echo "NOTIFYMSG COMMOK \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG COMMOK \"$val\"" >> "$UPSMON_C" config_get val "$cfg" commbadmsg - [ -n "$val" ] && echo "NOTIFYMSG COMMBAD \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG COMMBAD \"$val\"" >> "$UPSMON_C" config_get val "$cfg" shutdownmsg - [ -n "$val" ] && echo "NOTIFYMSG SHUTDOWN \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG SHUTDOWN \"$val\"" >> "$UPSMON_C" config_get val "$cfg" replbattmsg - [ -n "$val" ] && echo "NOTIFYMSG REPLBATT \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG REPLBATT \"$val\"" >> "$UPSMON_C" config_get val "$cfg" nocommmsg - [ -n "$val" ] && echo "NOTIFYMSG NOCOMM \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG NOCOMM \"$val\"" >> "$UPSMON_C" config_get val "$cfg" noparentmsg - [ -n "$val" ] && echo "NOTIFYMSG NOPARENT \"$val\"" >> $UPSMON_C + [ -n "$val" ] && echo "NOTIFYMSG NOPARENT \"$val\"" >> "$UPSMON_C" notifylist() { local value="$1" @@ -85,34 +84,36 @@ nut_upsmon_conf() { val="" config_list_foreach "$cfg" defaultnotify notifylist default="$optval" - echo "NOTIFYFLAG ONLINE $(setnotify "$cfg" onlinenotify)" >> $UPSMON_C - echo "NOTIFYFLAG ONBATT $(setnotify "$cfg" onbattnotify)" >> $UPSMON_C - echo "NOTIFYFLAG LOWBATT $(setnotify "$cfg" lowbatnotify)" >> $UPSMON_C - echo "NOTIFYFLAG FSD $(setnotify "$cfg" fsdnotify)" >> $UPSMON_C - echo "NOTIFYFLAG COMMOK $(setnotify "$cfg" commoknotify)" >> $UPSMON_C - echo "NOTIFYFLAG COMMBAD $(setnotify "$cfg" commbadnotify)" >> $UPSMON_C - echo "NOTIFYFLAG SHUTDOWN $(setnotify "$cfg" shutdownnotify)" >> $UPSMON_C - echo "NOTIFYFLAG REPLBATT $(setnotify "$cfg" repolbattnotify)" >> $UPSMON_C - echo "NOTIFYFLAG NOCOMM $(setnotify "$cfg" nocommnotify)" >> $UPSMON_C - echo "NOTIFYFLAG NOPARENT $(setnotify "$cfg" noparentnotify)" >> $UPSMON_C + echo "NOTIFYFLAG ONLINE $(setnotify "$cfg" onlinenotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG ONBATT $(setnotify "$cfg" onbattnotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG LOWBATT $(setnotify "$cfg" lowbatnotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG FSD $(setnotify "$cfg" fsdnotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG COMMOK $(setnotify "$cfg" commoknotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG COMMBAD $(setnotify "$cfg" commbadnotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG SHUTDOWN $(setnotify "$cfg" shutdownnotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG REPLBATT $(setnotify "$cfg" repolbattnotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG NOCOMM $(setnotify "$cfg" nocommnotify)" >> "$UPSMON_C" + echo "NOTIFYFLAG NOPARENT $(setnotify "$cfg" noparentnotify)" >> "$UPSMON_C" config_get val "$cfg" rbwarntime 43200 - echo "RBWARNTIME $val" >> $UPSMON_C + echo "RBWARNTIME $val" >> "$UPSMON_C" config_get val "$cfg" nocommwarntime 300 - echo "NOCOMMWARNTIME $val" >> $UPSMON_C + echo "NOCOMMWARNTIME $val" >> "$UPSMON_C" config_get val "$cfg" finaldelay 5 - echo "FINALDELAY $val" >> $UPSMON_C + echo "FINALDELAY $val" >> "$UPSMON_C" config_get val "$cfg" certpath - if [ -n "$val" ]; then echo "CERTPATH $val" >> $UPSMON_C; fi + if [ -n "$val" ]; then echo "CERTPATH $val" >> "$UPSMON_C"; fi config_get_bool val "$cfg" certverify 0 - if [ -n "$val" ]; then echo "CERTVERIFY $val" >> $UPSMON_C; fi + if [ -n "$val" ]; then echo "CERTVERIFY $val" >> "$UPSMON_C"; fi config_get_bool val "$cfg" forcessl 0 - if [ -n "$val" ]; then echo "FORCESSL $val" >> $UPSMON_C; fi + if [ -n "$val" ]; then echo "FORCESSL $val" >> "$UPSMON_C"; fi + + havemon=1 } nut_upsmon_add() { @@ -126,12 +127,6 @@ nut_upsmon_add() { local password local system - # if UPSMON_C is a symlink we're only doing generated config - [ -L $UPSMON_C ] && { - rm -f $UPSMON_C - nut_upsmon_conf "" - } - config_get upsname "$cfg" upsname config_get hostname "$cfg" hostname localhost config_get port "$cfg" port @@ -142,40 +137,56 @@ nut_upsmon_add() { if [ -n "$port" ]; then system="$system:$port"; fi - echo "MONITOR $system $powervalue $username $password $type" >> $UPSMON_C + echo "MONITOR $system $powervalue $username $password $type" >> "$UPSMON_C" + + havems=1 } -start_service() { - mkdir -p "$(dirname "$UPSMON_C")" - chmod 750 "$(dirname "$UPSMON_C")" +build_config() { + local runas + mkdir -m 0750 -p "$(dirname "$UPSMON_C")" config_load nut_monitor - config_foreach nut_upsmon_conf upsmon config_foreach nut_upsmon_add master master config_foreach nut_upsmon_add slave slave - [ -z "$(cat /var/etc/nut/nut.conf)" ] && echo "MODE=netclient" >>/var/etc/nut/nut.conf - - chmod 640 $UPSMON_C - chmod 640 /var/etc/nut/nut.conf - - chown ${runas:-root}:$(id -gn ${runas:-root}) /var/etc/nut - chown ${runas:-root}:$(id -gn ${runas:-root}) /var/etc/nut/nut.conf - chown ${runas:-root}:$(id -gn ${runas:-root}) $UPSMON_C - - [ -d /var/run/nut ] || { - mkdir -m 0750 -p /var/run/nut - chown ${runas:-root}:$(id -gn ${runas:-root}) /var/run/nut + [ ! -s "$(cat /var/etc/nut/nut.conf)" ] && { + echo "MODE=netclient" >>/var/etc/nut/nut.conf + chmod 640 /var/etc/nut/nut.conf + chgrp $(id -gn ${runas:-root}) /var/etc/nut/nut.conf } - exec $DEBUG /usr/sbin/upsmon $UPSMON_OPTIONS + [ -s "$UPSMON_C" ] && chmod 640 "$UPSMON_C" + [ -s "$UPSMON_C" ] && chgrp $(id -gn ${runas:-root}) "$UPSMON_C" } -stop_service() { - exec /usr/sbin/upsmon -c stop +start_service() { + local havemon havems + build_config + + [ "$havemon" != 1 ] && return + [ "$havems" != 1 ] && return + + procd_open_instance "upsmon" + procd_set_param respawn + procd_set_param stderr 0 + procd_set_param stdout 1 + procd_set_param command /usr/sbin/upsmon -D + procd_close_instance } reload_service() { - exec /usr/sbin/upsmon -c reload + if pgrep upsmon >/dev/null 2>/dev/null; then + build_config + /usr/sbin/upsmon -c reload + else + stop + sleep 2 + start_service + fi +} + +service_triggers() { + procd_add_reload_trigger "nut_monitor" } diff --git a/net/nut/files/nut-server.init b/net/nut/files/nut-server.init index e064dd7213..045b29d48d 100755 --- a/net/nut/files/nut-server.init +++ b/net/nut/files/nut-server.init @@ -6,47 +6,79 @@ # START=50 -RUN_D=/var/run -PID_F=$RUN_D/upsd.pid -UPS_C=/var/etc/nut/ups.conf USERS_C=/var/etc/nut/upsd.users UPSD_C=/var/etc/nut/upsd.conf +UPS_C=/var/etc/nut/ups.conf USE_PROCD=1 +get_write_driver_config() { + local cfg="$1" + local var="$2" + local def="$3" + local flag="$4" + local val + + [ -z "$flag" ] && { + config_get val "$cfg" "$var" "$def" + [ -n "$val" ] && [ "$val" != "0" ] && echo "$var = $val" >>"$UPS_C" + } + + [ -n "$flag" ] && { + config_get_bool val "$cfg" "$var" "$def" + [ "$val" = 1 ] && echo "$var" >>"$UPS_C" + } +} + +upsd_statepath() { + local cfg="$1" + local statepath + + config_get statepath "$cfg" statepath "/var/run/nut" + STATEPATH="$statepath" +} + +upsd_runas() { + local cfg="$1" + local runas + + [ -n "$RUNAS" ] && return + + config_get runas "$cfg" runas "nut" + RUNAS="$runas" +} + listen_address() { local cfg="$1" config_get address "$cfg" address "::1" config_get port "$cfg" port - echo "LISTEN $address $port" >>$UPSD_C -} - -upsd_statepath() { - local cfg="$1" - config_get statepath "$cfg" statepath + echo "LISTEN $address $port" >>"$UPSD_C" } upsd_config() { local cfg="$1" - local maxage maxconn certfile + local maxage maxconn certfile runas statepath # Note runas support requires you make sure USB device file is readable by # the runas user - config_get runas "$cfg" runas + config_get runas "$cfg" runas "nut" + RUNAS="$runas" + + config_get statepath "$cfg" statepath "/var/run/nut" + STATEPATH="$statepath" config_get maxage "$cfg" maxage - [ -n "$maxage" ] && echo "MAXAGE $maxage" >>$UPSD_C + [ -n "$maxage" ] && echo "MAXAGE $maxage" >>"$UPSD_C" - config_get statepath "$cfg" statepath - [ -n "$statepath" ] && echo "STATEPATH $statepath" >>$UPSD_C + [ -n "$statepath" ] && echo "STATEPATH $statepath" >>"$UPSD_C" config_get maxconn "$cfg" maxconn - [ -n "$maxconn" ] && echo "MAXCONN $maxconn" >>$UPSD_C + [ -n "$maxconn" ] && echo "MAXCONN $maxconn" >>"$UPSD_C" #NOTE: certs only apply to SSL-enabled version config_get certfile "$cfg" certfile - [ -n "$certfile" ] && echo "CERTFILE $certfile" >>$UPSD_C + [ -n "$certfile" ] && echo "CERTFILE $certfile" >>"$UPSD_C" } nut_user_add() { @@ -55,104 +87,241 @@ nut_user_add() { local val config_get val "$cfg" username "$1" - echo "[$val]" >> $USERS_C + echo "[$val]" >> "$USERS_C" config_get val "$cfg" password - echo " password = $val" >> $USERS_C + echo " password = $val" >> "$USERS_C" config_get val "$cfg" actions for a in $val; do - echo " actions = $a" >> $USERS_C + echo " actions = $a" >> "$USERS_C" done instcmd() { local val="$1" - echo " instcmds = $val" >> $USERS_C + echo " instcmds = $val" >> "$USERS_C" } config_list_foreach "$cfg" instcmd instcmd config_get val "$cfg" upsmon if [ -n "$val" ]; then - echo " upsmon $val" >> $USERS_C + echo " upsmon $val" >> "$USERS_C" fi } +build_server_config() { + mkdir -m 0755 -p "$(dirname "$UPSD_C")" + rm -f "$USERS_C" + rm -f "$UPSD_C" + rm -f /var/etc/nut/nut.conf + + echo "# Config file automatically generated from UCI config" > "$USERS_C" + echo "# Config file automatically generated from UCI config" > "$UPSD_C" + + config_foreach nut_user_add user + config_foreach listen_address listen_address + config_foreach upsd_config upsd + echo "MODE=netserver" >>/var/etc/nut/nut.conf + + chmod 0640 "$USERS_C" + chmod 0640 "$UPSD_C" + chmod 0644 /var/etc/nut/nut.conf + + [ -d "${STATEPATH}" ] || { + mkdir -m 0750 -p "${STATEPATH}" + } + + if [ -n "$RUNAS" ]; then + chown $RUNAS:$(id -gn $RUNAS) "${STATEPATH}" + chgrp $(id -gn $RUNAS) "$USERS_C" + chgrp $(id -gn $RUNAS) "$UPSD_C" + fi + haveserver=1 +} + +build_driver_config() { + local cfg="$1" + + echo "[$cfg]" >>"$UPS_C" + + get_write_driver_config "$cfg" driver "usbhid-ups" + get_write_driver_config "$cfg" port "auto" + get_write_driver_config "$cfg" sdorder + get_write_driver_config "$cfg" desc + get_write_driver_config "$cfg" nolock 0 1 + get_write_driver_config "$cfg" ignorelb 0 1 + get_write_driver_config "$cfg" mfr + get_write_driver_config "$cfg" model + get_write_driver_config "$cfg" serial + get_write_driver_config "$cfg" sdtime + get_write_driver_config "$cfg" offdelay + get_write_driver_config "$cfg" ondelay + get_write_driver_config "$cfg" pollfreq + get_write_driver_config "$cfg" vendor + get_write_driver_config "$cfg" product + get_write_driver_config "$cfg" bus + get_write_driver_config "$cfg" interruptonly 0 1 + get_write_driver_config "$cfg" interruptsize + get_write_driver_config "$cfg" maxreport + get_write_driver_config "$cfg" vendorid + get_write_driver_config "$cfg" productid + get_write_driver_config "$cfg" community + get_write_driver_config "$cfg" snmp_version + get_write_driver_config "$cfg" snmp_retries + get_write_driver_config "$cfg" snmp_timeout + get_write_driver_config "$cfg" notransferoids 0 1 + get_write_driver_config "$cfg" maxstartdelay + get_write_driver_config "$cfg" retrydelay + get_write_driver_config "$cfg" synchronous + get_write_driver_config "$cfg" other + get_write_driver_config "$cfg" otherflag + + defoverride() { + local overvar="$1" + local defover="$2" + local overtype="$(echo "$overvar" | tr '.' '_')" + + config_get overval "${defover}_${overtype}" value + [ -n "$overval" ] && echo "${defover}.${overvar} = $overval" >>"$UPS_C" + } + + config_list_foreach "$cfg" override defoverride override + config_list_foreach "$cfg" default defoverride default + + other() { + local othervar="$1" + local othervarflag="$2" + + if [ "$othervarflag" = "otherflag" ]; then + config_get_bool otherval "${othervarflag}_${overtype}" value + [ "$otherval" = "1" ] && echo "${othervarflag}_${othervar}" >>"$UPS_C" + else + config_get otherval "${othervarflag}_${overtype}" value + [ -n "$otherval" ] && echo "${othervarflag}_${othervar} = $otherval" >>"$UPS_C" + fi + } + + config_list_foreach "$cfg" override defoverride override + config_list_foreach "$cfg" default defoverride default + config_list_foreach "$cfg" default other other + config_list_foreach "$cfg" default other otherflag + echo "" >>$UPS_C + havedriver=1 +} + +build_global_driver_config() { + local cfg="$1" + + # Global driver config + get_write_driver_config "$cfg" chroot + get_write_driver_config "$cfg" driverpath + get_write_driver_config "$cfg" maxstartdelay + get_write_driver_config "$cfg" maxretry + get_write_driver_config "$cfg" retrydelay + get_write_driver_config "$cfg" pollinterval + get_write_driver_config "$cfg" synchronous + config_get runas "$cfg" user "nut" + RUNAS="$runas" + upsd_runas + + echo "" >>$UPS_C +} + +build_config() { + local RUNAS=nut + local STATEPATH=/var/run/nut + + mkdir -m 0755 -p "$(dirname "$UPS_C")" + rm -f "$UPS_C" + echo "# Config file automatically generated from UCI config" > "$UPS_C" + chmod 0640 "$UPS_C" + + config_load nut_server + config_foreach upsd_statepath upsd + + config_foreach build_global_driver_config driver_global + config_foreach build_driver_config driver + [ -n "$RUNAS" ] && chgrp $(id -gn $RUNAS) "$UPS_C" + + build_server_config +} + +start_driver_instance() { + local cfg="$1" + local requested="$2" + local driver + local STATEPATH=/var/run/nut + local RUNAS=nut + + [ "$havedriver" != 1 ] && return + + # If wanting a specific instance, only start it + [ "$requested" != "$cfg" ] && [ x"$requested" != x ] && return 0 + + mkdir -m 0755 -p "$(dirname "$UPS_C")" + + [ ! -s "$UPS_C" ] && build_config + + # Avoid hotplug inadvertenly restarting driver during + # forced shutdown + [ -f /var/run/killpower ] && return 0 + [ -d /var/run/nut ] && [ -f /var/run/nut/disable-hotplug ] && return 0 + + + config_foreach upsd_statepath upsd + + if [ -n "$RUNAS" ]; then + chown $RUNAS:$(id -gn $RUNAS) "${STATEPATH}" + fi + + config_get driver "$cfg" driver "usbhid-ups" + procd_open_instance "$cfg" + procd_set_param respawn + procd_set_param stderr 0 + procd_set_param stdout 1 + procd_set_param command /lib/nut/${driver} -D -a "$cfg" ${RUNAS:+-u $RUNAS} + procd_close_instance +} + +start_server_instance() { + local RUNAS + build_config + + [ "$haveserver" != 1 ] && return + + procd_open_instance "upsd" + procd_set_param respawn + procd_set_param stderr 0 + procd_set_param stdout 1 + procd_set_param command /usr/sbin/upsd -D ${RUNAS:+-u $RUNAS} + procd_close_instance +} + start_service() { - local runas statepath + local havedriver haveserver + local STATEPATH=/var/run/nut - mkdir -p /var/etc/nut - chmod -R 750 /var/etc/nut - - rm -f $UPSD_C - rm -f $USERS_C - rm -f $UPSD_C - rm -f /var/etc/nut/nut.conf - - echo "# Config file automatically generated from UCI config" > $UPS_C - echo "# Config file automatically generated from UCI config" > $USERS_C - echo "# Config file automatically generated from UCI config" > $UPSD_C - - local in_driver have_drivers - config_cb() { - if [ "$1" != "driver" ]; then - in_driver= - else - echo "[$2]" >> $UPS_C - in_driver=true - have_drivers=true - fi - } - option_cb() { - if [ "$in_driver" = "true" ]; then - echo " $1 = $2" >> $UPS_C - fi - } + # Avoid hotplug inadvertenly restarting driver during + # forced shutdown + [ -f /var/run/killpower ] && return 0 + [ -f /var/run/nut/disable-hotplug ] && return 0 config_load nut_server - config_foreach nut_user_add user - config_foreach upsd_config upsd - config_foreach listen_address listen_address + build_config + config_foreach start_driver_instance driver "$@" - echo "MODE=netserver" >>/var/etc/nut/nut.conf - - chmod 0640 $USERS_C - chmod 0640 $UPS_C - chmod 0640 $UPSD_C - chmod 0640 /var/etc/nut/nut.conf - [ -d "${statepath:-/var/run/nut}" ] || { - mkdir -m 0750 -p "${statepath:-/var/run/nut}" - chown $runas:$(id -gn $runas) "${statepath:-/var/run/nut}" - } - - if [ -n "$runas" ]; then - chown -R $runas:$(id -gn $runas) /var/etc/nut - fi - - if [ "$have_drivers" = "true" ]; then - $DEBUG /usr/sbin/upsd ${runas:+-u $runas} $OPTIONS - $DEBUG /usr/sbin/upsdrvctl ${runas:+-u $runas} start - fi -} - - -nut_driver_stop() { - local cfg="$1" - local driver - - config_get driver "$cfg" driver - - [ -r ${statepath:-/var/run/nut}/$driver-$cfg ] && /usr/sbin/upsdrvctl stop $cfg -} - -stop_service() { - [ -r $PID_F ] && /usr/sbin/upsd -c stop - config_load ups - config_foreach upsd_statepath upsd - config_foreach nut_driver_stop driver + start_server_instance "upsd" } reload_service() { - upsd -c reload + stop + sleep 2 + local havedriver haveserver + start +} + +service_triggers() { + procd_add_reload_trigger "nut_server" } diff --git a/net/nut/files/nut_monitor b/net/nut/files/nut_monitor index 0b71e95cf0..0ba37863b6 100644 --- a/net/nut/files/nut_monitor +++ b/net/nut/files/nut_monitor @@ -1,14 +1,13 @@ #config upsmon 'upsmon' # option runas run-as-user # option minsupplies 1 -# option shutdowncmd /sbin/halt +# option shutdowncmd '/usr/sbin/nutshutdown' # option notifycmd /path/to/cmd # list defaultnotify SYSLOG # option pollfreq 5 # option pollfreqalert 5 # option hostsync 15 # option deadtime 15 -# option powerdownflags /var/run/killpower # option onlinemsg "online message" # option onbattmsg "on battery message" # option lowbattmsg "low battery message" @@ -51,4 +50,3 @@ # option powervalue 1 # option username upsuser # option password upspassword - diff --git a/net/nut/files/nut_server b/net/nut/files/nut_server index bebd169db6..464d56303b 100644 --- a/net/nut/files/nut_server +++ b/net/nut/files/nut_server @@ -19,5 +19,6 @@ # option maxage 15 # option statepath /var/run/nut # option maxconn 1024 +# option runas nut # NB: certificates only apply to SSL-enabled version # option certfile /usr/local/etc/upsd.pem diff --git a/net/nut/files/nutshutdown b/net/nut/files/nutshutdown new file mode 100755 index 0000000000..e4fd962cd7 --- /dev/null +++ b/net/nut/files/nutshutdown @@ -0,0 +1,41 @@ +#!/bin/sh +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +. /lib/functions.sh + +mount -o remount,ro /overlay /overlay +mount -o remount,ro / / + +stop_instance() { + /etc/init.d/nut-server stop "$1" +} + +shutdown_instance() { + local cfg="$1" + config_get driver "$cfg" driver "usbhid-ups" + /lib/nut/${driver} -a "$cfg" -k +} + +[ -f /var/run/killpower ] && { + [ -f /etc/config/nut_server ] && { + config_load nut_server + + # Can't FSD unless drivers are stopped + config_foreach stop_instance driver + # Driver will wait 'offdelay' before shutting down + config_foreach shutdown_instance driver + # So this can happen + poweroff + # And just in case + sleep 120 + # Uh-oh failed to poweroff UPS + reboot -f + } || { + poweroff + } +} || { + poweroff +}