Synology DS416
UPS: APC Back-UPS NS 650M1

/bin/sh -> bash

#####################################################################
# This is /usr/syno/etc/nut/ups.conf copied from a DS416

pollinterval = 5
[ups]
	driver = usbhid-ups
	port = auto
	#pollonly
	#community = name
	#snmp_version = v2c
	#mibs = auto
	#secName = Synology
	#secLevel = noAuthNoPriv
	#authProtocol = MD5
	#authPassword = 111111111111
	#privProtocol = DES
	#privPassword = 222222222222

#####################################################################
# This is /usr/syno/etc/nut/upsd.conf copied from a DS416

LISTEN 192.168.1.70
LISTEN 2601:cf:8200:43d0:211:32ff:fe63:60d7
LISTEN fe80::211:32ff:fe63:60d7
LISTEN 127.0.0.1
LISTEN ::1

#####################################################################
# This is /usr/syno/etc/nut/upsd.users copied from a DS416

[monuser]
		password = secret
		upsmon master

#####################################################################
# This is /usr/syno/etc/nut/upsmon.conf copied from a DS416

RUN_AS_USER root
MONITOR ups at localhost 1 monuser secret master
MINSUPPLIES 1
SHUTDOWNCMD ""
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
NOTIFYFLAG ONLINE EXEC
NOTIFYFLAG ONBATT EXEC
NOTIFYFLAG LOWBATT EXEC
NOTIFYFLAG NOCOMM EXEC
NOTIFYFLAG COMMBAD IGNORE
NOTIFYFLAG COMMOK IGNORE
NOTIFYFLAG SHUTDOWN IGNORE
NOTIFYFLAG FSD EXEC
NOTIFYFLAG NOPARENT SYSLOG
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5

#####################################################################
# This is /usr/syno/etc/nut/upssched.conf copied from a DS416

CMDSCRIPT /usr/syno/bin/synoups
PIPEFN /var/run/upssched.pipe
LOCKFN /var/run/upssched.lock
AT ONLINE * EXECUTE online
AT ONLINE * CANCEL-TIMER fsd
AT LOWBATT * EXECUTE lowbatt
AT NOCOMM * EXECUTE nocomm
AT FSD * EXECUTE fsd
AT ONBATT * EXECUTE onbatt

#####################################################################
# This is /usr/syno/bin/synoupscommon copied from a DS416

#!/bin/sh
# Copyright (c) 2000-2012 Synology Inc. All rights reserved.
UPS_STATE="/var/state/ups"
UPS_ROOT="/tmp/ups"
UPS_LOCK=$UPS_ROOT"/ups.lock"
UPSSCHED_CONF="/usr/syno/etc/ups/upssched.conf"
SYNOINFO_CONF="/etc/synoinfo.conf"
SYNOINFO=$SYNOINFO_CONF
SYNOINFO_CONF_DEFAULT="/etc.defaults/synoinfo.conf"
UPSMON_CONF="/usr/syno/etc/ups/upsmon.conf"
UPSMON_CONF_BACKUP="/usr/syno/etc.defaults/ups/upsmon.conf"
UPS_CONF="/usr/syno/etc/ups/ups.conf"
UPS_CONF_BACKUP="/usr/syno/etc.defaults/ups/ups.conf"
NUTSCAN_USB_H="/usr/syno/etc/ups/nutscan-usb.h"

if [ ! -d $UPS_ROOT ]; then
	mkdir -p $UPS_ROOT
fi

SupportUPS=`/bin/get_key_value $SYNOINFO_CONF_DEFAULT supportups`
case "$SupportUPS" in
[Yy][Ee][Ss])
	;;
*)
	echo "UPS is not support here."
	exit
	;;
esac

EnableUPS=`/bin/get_key_value $SYNOINFO_CONF ups_enabled`
case "$EnableUPS" in
[Yy][Ee][Ss])
	MasterEnabled=1;;
*)
	MasterEnabled=0;;
esac

EnableSlave=`/bin/get_key_value $SYNOINFO_CONF upsslave_enabled`
case "$EnableSlave" in
[Yy][Ee][Ss])
	SlaveEnabled=1;;
*)
	SlaveEnabled=0;;
esac

UpsMode=`/bin/get_key_value $SYNOINFO_CONF ups_mode`
# ups_mode will be empty when upgrade to 4.2
if [ "x" = "x${UpsMode}" ]; then
	UpsMode="usb"
fi

StatClient=`ps -aux |grep '/usr/sbin/upsmon'|grep -cv grep`

SafeMV() {
	mv $1 $2.$$
	mv $2.$$ $2
}

UpdateUpsdConf() {
	local RAD_F_LISTEN="/usr/syno/etc/ups/upsd.conf"
	local RAD_V_IF_HEAD="Link encap"
	local RAD_V_WL_HEAD="wlan"
	local RAD_V_V6IP="inet6"
	local RAD_V_V4IP="inet"
	local IS_WLAN=0

	echo "" > $RAD_F_LISTEN
	ifconfig | while read LINE; do
		if echo "$LINE"|grep -q "$RAD_V_IF_HEAD" && echo "$LINE"|grep -q "$RAD_V_WL_HEAD"; then
			IS_WLAN=1
		elif [ "x" == "x$LINE" ]; then
			IS_WLAN=0
		fi

		if echo "$LINE"|grep -q "$RAD_V_V6IP"; then
			# work around wifi ipv6 bind fail
			if [ 0 == $IS_WLAN ];then
				echo -e "LISTEN `echo $LINE|/usr/bin/awk '/inet6 /{print$3}'|/usr/bin/cut -d '/' -f 1`" >> $RAD_F_LISTEN
			fi
		elif echo "$LINE"|grep -q "$RAD_V_V4IP"; then
			echo -e "LISTEN `echo $LINE|/usr/bin/awk '/inet /{print$2}'|/usr/bin/cut -d ':' -f 2`" >> $RAD_F_LISTEN
		fi
	done
}

StartServer() {
	UpdateUpsdConf

	local cntDaemon=`ps -aux |grep '/usr/sbin/upsd'|grep -cv grep`
	if [ $cntDaemon -gt 0 ]; then
		kill -HUP `cat /var/state/ups/upsd.pid`
	else
		/usr/sbin/upsd
	fi
}

StartClient() {
	local cntMon=`ps -aux |grep '/usr/sbin/upsmon'|grep -cv grep`
	if [ $cntMon -gt 0 ]; then
		kill -HUP `cat /var/run/upsmon.pid`
	fi
	/usr/sbin/upsmon $1
}

StopUps() {
	ShowLog "Stop UPS Daemon"

	killall upsmon > /dev/null 2>&1
	killall upssched > /dev/null 2>&1
	killall upsd > /dev/null 2>&1
	/usr/bin/upsdrvctl stop

	#we need to check the process stopped, in some low level DS, it sometimes costs much time
	WaitStop	

	return 0
}

ForceStopUps() {
	ShowLog "Stop UPS timeout, Force stop UPS"

	killall -9 upsmon > /dev/null 2>&1
	killall -9 upssched > /dev/null 2>&1
	killall -9 upsd > /dev/null 2>&1
	/usr/bin/upsdrvctl stop
	sleep 3
}

WaitStop() {
	for i in `seq 1 1 3`; do
		sleep 3
		local P_COUNT=`ps -aux |grep -E "(upsd|upsmon|a ups)"|grep -cv grep`
		if [ 0 -eq $P_COUNT ]; then
			return 0
		fi
	done
	ForceStopUps
	return 255
}

CheckUpsmonConf() {
	local conf_size=`stat $UPSMON_CONF |grep Size|cut -d" " -f 4`
	# mode: local/remote
	local mode=$1
	local server_ip="0.0.0.0"

	if [ 0 -eq $conf_size ]; then
		if [ -f $UPSMON_CONF_BACKUP ]; then
			/bin/cp $UPSMON_CONF_BACKUP $UPSMON_CONF
		else
			ShowLog "synoupscommon: cannot rescue $UPSMON_CONF"
		fi
	fi

	if [ "$mode" == "local" ]; then
		/bin/sed -i "/^MONITOR/c\\MONITOR ups@localhost 1 monuser secret master" $UPSMON_CONF
	elif [ "$mode" == "remote" ]; then
		if [ $# -ne 2 ]; then
			ShowLog "synoupscommon: CheckUpsmonConf(): remote mode need set server_ip"
			return 1
		fi
		server_ip=$2
		/bin/sed -i "/^MONITOR/c\\MONITOR ups@${server_ip} 1 monuser secret slave" $UPSMON_CONF
	fi

	return 0
}

ShowLog() {
	echo $1
	logger -p err -- $1
}

#####################################################################
# This is /usr/syno/bin/synoups copied from a DS416

#!/bin/sh
# Copyright (c) 2008-2010 Synology Inc. All rights reserved.

. /usr/syno/bin/synoupscommon

if [ "x$1" = "x" -o "x$1" = "x-h" ]; then
	echo "Copyright (c) 2008-2010 Synology Inc. All rights reserved."
	echo "Usage: `basename $0` { online | lowbatt | nocomm | fsd }"
	exit
fi

UPSMode=`/bin/get_key_value $SYNOINFO ups_mode`
RUN_HA=$(/usr/syno/sbin/synohacore --is_ha_running)
SZF_HA_RC="/var/packages/HighAvailability/target/etc/rc.ha"
SYNOBOOTBIN="/usr/syno/bin/synobootseq"
case "${UPSMode}" in
[Ss][Nn][Mm][Pp] | [Uu][Ss][Bb])
	UPSMaster=1
	EnabledKey="ups_enabled"
	UPSMonServer="localhost"
	;;
*)
	UPSMaster=0
	EnabledKey="upsslave_enabled"
	UPSMonServer=`/bin/get_key_value $SYNOINFO upsslave_server`
	if [ "x$UPSMonServer" = "x" ]; then
		UPSMonServer="localhost"
	elif [ 0 -lt `echo ${UPSMonServer}|grep -c ':'` ]; then
		UPSMonServer="[${UPSMonServer}]"
	fi
	;;
esac

UPSEnabled=`/bin/get_key_value $SYNOINFO ${EnabledKey}`
case "$UPSEnabled" in
[Yy][Ee][Ss])
	;;
*)
	echo "UPS is not enable."
	exit
	;;
esac

UPSSafeShutdown=`/bin/get_key_value $SYNOINFO ups_safeshutdown`
case "${UPSSafeShutdown}" in
[Nn][Oo])
	UPSSafeShutdown=0;;
*)
	UPSSafeShutdown=1;;
esac

SZF_SAFEMODE="/tmp/ups.safedown"
SZF_SAFEMODE_DONE="/tmp/safeModeDone"
SZF_ONBATT="/tmp/ups.onbatt"

SYSLOG() {
	logger -p user.err -t synoups "$1"
}

UPSStatusGet() {
	ups_stat=`/usr/bin/upsc ups@${UPSMonServer} ups.status 2>/dev/null`
	if [ $? -ne 0 ]; then
		echo "ERR"
		return 255
	fi
	for status in $ups_stat ; do
		case "$status" in
		"OL"|"OB"|"LB")
			echo "$status"
			return
			;;
		esac
	done
	echo "ERR"
}

UPSShutdown() {
	if [ $UPSMaster -ne 1 ]; then
		echo "Slave waits for safe shutdown" >> $SZF_SAFEMODE
		touch /var/.NormalShutdown
		SYSLOG "UPS waits for safe shutdown."
		return
	fi
	OL=0
	LB=0
	while [ $OL -ne 2 -a $LB -ne 2 ]; do
		sleep 10
		St=`UPSStatusGet`
		if [ "$St" = "OL" ]; then
			OL=`expr $OL + 1`
			LB=0
		else
			LB=`expr $LB + 1`
			OL=0
		fi
		echo "OL=$OL LB=$LB" >> $SZF_SAFEMODE
	done
	if [ $OL -eq 2 ]; then
		synologset1 sys warn 0x11300012
		echo "UPS back to On-Line and reboot." >> $SZF_SAFEMODE
		$SYNOBOOTBIN --unset-safe-shutdown
		telinit 6
	elif [ $LB -eq 2 ]; then
		touch /var/.NormalShutdown
		if [ $UPSSafeShutdown -eq 0 ]; then
			echo "Waiting UPS exhausted." >> $SZF_SAFEMODE
			SYSLOG "Waiting UPS exhausted."
		else
			echo "UPS safe shutdown." >> $SZF_SAFEMODE
			SYSLOG "UPS safe shutdown."

			shutdown_retry=0
			while [ $shutdown_retry -ne 3 ]; do
				StopUps
				/usr/bin/upsdrvctl shutdown
				if [ $? -eq 0 ]; then
					return 0
				fi
				shutdown_retry=`expr $shutdown_retry + 1`
				echo "UPS shutdown retry ... $shutdown_retry" >> $SZF_SAFEMODE
				echo "UPS shutdown retry ... $shutdown_retry" > /dev/kmsg
				# omron driver will reset usb (~30s) when command timeout
				sleep 40
			done
			echo "UPS shutdown fail." >> $SZF_SAFEMODE
			echo "UPS shutdown fail" > /dev/kmsg
		fi
	fi
}

UPSSafeMode() {
	if [ -f $SZF_SAFEMODE ]; then
		return
	fi

	$SYNOBOOTBIN --is-shutdown
	if [ $? -eq 0 ]; then
		SYSLOG "[UPS] System is shutting down. Ignore onbattery event."
		return
	fi

	SYSLOG "[UPS] Check Boot Status."
	$SYNOBOOTBIN --is-ready
	while [ $? -ne 0 ]
	do
		sleep 2
		$SYNOBOOTBIN --is-ready
	done

	St=`UPSStatusGet`
	if [ "$St" = "OL" ]; then
		SYSLOG "WARNING: UPS is On-Line"
		return
	fi
	echo "$1" > $SZF_SAFEMODE

	/usr/syno/bin/synologset1 sys warn 0x11300011
	SYSLOG "[UPS] Server is going to Safe Mode. It will stop all services and umount all volumes."

	if [ "yes" = "$RUN_HA" ]; then
		$SZF_HA_RC ups-safemode
	fi

	$SYNOBOOTBIN --set-safe-shutdown
	# we should hook synopoweroff not only reboot
	/usr/syno/sbin/synopoweroff -fr
}

UPSRestart() {
	if [ -f $SZF_ONBATT ]; then
		rm $SZF_ONBATT
		if [ ! -f $SZF_SAFEMODE ]; then
			/usr/syno/bin/synologset1 sys info 0x11300012
			/usr/syno/bin/synonotify UPSOnAC
		fi
	fi
	if [ ! -f $SZF_SAFEMODE ]; then
		return
	fi
	echo "UPS back on-line, so wait to reboot" >> $SZF_SAFEMODE
	sleep 30
	St=`UPSStatusGet`
	timeout=$((3*60))

	if [ "$St" = "OL" ]; then
		SYSLOG "[UPS] Check Safe Mode Done."
		while [ ! -f $SZF_SAFEMODE_DONE ] && [ $timeout -gt 0 ]
		do
			sleep 2
			timeout=`expr $timeout - 2`
		done

		if [ "yes" = "$RUN_HA" ]; then
			$SZF_HA_RC ups-restart &
		fi
		synologset1 sys warn 0x11300012
		SYSLOG "UPS back to On-Line and reboot."
		$SYNOBOOTBIN --unset-safe-shutdown
		telinit 6
	fi
}

ONBatt() {
	if [ ! -f $SZF_ONBATT ]; then
		touch $SZF_ONBATT
		SYSLOG "UPS on battery."
	fi
}

FLOCK_FILE="/tmp/synoups.lock"
{
flock -x 99

case "$1" in
online)
	UPSRestart
	;;
onbatt)
	ONBatt
	;;
lowbatt | nocomm)
	UPSSafeMode $1
	;;
fsd)
	/usr/sbin/upsmon -c fsd
	UPSSafeMode $1
	;;
shutdownups)
	UPSShutdown
	;;
esac

flock -u 99
} 99>$FLOCK_FILE
