#! /bin/bash

# Do not run hooks when cumulus-installer uses apt-get
[ "$UPDATE_CUMULUS" = "No" ] && exit 0

trap cleanup 0 # after installer check

cleanup()
{
	policy=/usr/sbin/policy-rc.d
	grep -s -q 'Generated by apt-policy-rc-check' $policy && {
		rm -f $policy
		logger -t Policy "Removed $policy"
		}

	rm -f /run/need-policy
	cd /run && [ -d upgrade-services ] &&
		mv upgrade-services upgrade-services.$(date +%F-%T)

	logger -t Policy "Upgrade is finished"
	exit 0
}

[ -s /run/upgrade-services/list ] || {
	logger -t Policy "No services to stop or start"
	exit 0
}

cd /run/upgrade-services || exit 1

# for the list of services and init.d files that we got,
# we only get one per package, and many packages have multiple.
# so go from the services to list of packages that have those
# services or init.d files, then list those packages, and get
# all the services and init.d files in them (that are present
# in the filesystem).
# Then eliminate any services that are already in the stop or start lists,
# and for any remaining, check to see if they are enabled, and if
# so, add them to the stop and/or restart lists if not already
# present.  Not pretty, but not horribly slow at the end of an upgrade
# where things are cached, and it does work.
# somewhat complicated by packages that have both init.d and unit files
sed 's/:.*//' list | sort -u -o list.files
sed -e '/\.service/s,.*,/systemd/.*/&$,' \
	-e '/\.service/!s,.*,/etc/init.d/&$,'  list.files > list.regex
dpkg -S $(cat list.files) 2>/dev/null | tee dpkg-S | egrep -f list.regex |
	tee dpkg.matches | sed 's/:.*//' | sort -u -o dpkg.tolist
dpkg -L $(cat dpkg.tolist) 2>/dev/null | sort -u -o pkgfiles
egrep '/systemd/.*\.service$' pkgfiles | sed 's,.*/,,' > pkg.services
egrep '/etc/init.d/[^/]*$' pkgfiles | sed 's,/etc/init.d/,,' > pkg.inits
sed -e 's,.*/,,' -e 's,\.service$,,' pkg.services > pkg.svc.chkinit
fgrep -v -w -f pkg.svc.chkinit pkg.inits > pkg.nodup.inits
sort pkg.services pkg.nodup.inits -o pcheck
# not systemctl -q is-enabled, because static services like
# switchd-diag.service return 0, not 1.
for f in $(cat pcheck); do
	(echo -n $f ''; systemctl is-enabled $f) |
		sed -n '/enabled$/s/ enabled//p' >> extra.services.enabled
done

sed -n '/:stop/s/:.*//p' list | sort -u -o stop
sed -n '/:start/s/:.*//p' list | sort -u  -o start
comm -23 stop start > stoponly

# some packages are built with --no-start on their services,
# but with our new policy, we want to (re)start them as well,
# if they are enabled (or an instance is enabled), so look for
# those also
for serv in $(cat stoponly); do
	systemctl -a show -p Names,UnitFileState ${serv} ${serv}@'*' |\
	  sed -n -e '/Names=/N' -e 's/\n/ /' -e /enabled/s/Names=// \
	    -e '/enabled/s/ Unit.*//p' > tmp
	cat tmp >> start1
	fgrep -x -f tmp stoponly > nstop
	cmp -s stoponly nstop || mv nstop stoponly
	
done
[ -s start1 ] && sort -u start start1 -o start

stop=$(tr '\n' ' ' < stoponly)
start=$(tr '\n' ' ' < start)

# OK, now we have the (potential) extra list of enabled services.
# Process the list from the policy-rc.d script, and only add the
# ones not already present in stop OR start.

sort -u stop start -o extra-check
fgrep -v -x -f extra-check extra.services.enabled > extra.need.action

# Finally, we have the extra list.  Run it through both stop and start,
# because we don't know which lists they would have been on.  That will
# only slightly increase downtime.

newlist=$(tr '\n' ' ' < extra.need.action)
stop="$stop $newlist"
start="$start $newlist"

# some services we never want restarted, and they might come in through
# either mechanism
for drop in stopssh.service firstboot.service \
    cumulus-fastfailover.service; do
    stop="${stop//$drop}"
    start="${start//${drop}/}"
done

# Find any instance services with the same base name (usually, but
# not always, a vrf instance)
adds=
for serv in ${stop}; do
   nm=$(systemctl -a show -p Names ${serv%%.*}@'*')
   serv=${nm//Names=/}
   [ -n "$serv" ] && adds="$adds $serv"
done
stop="$stop $adds"

adds=
for serv in ${start}; do
   nm=$(systemctl -a show -p Names ${serv%%.*}@'*')
   serv=${nm//Names=/}
   [ -n "$serv" ] && adds="$adds $serv"
done
start="$start $adds"

# remove duplicates
start=$(echo "$start" | tr ' ' '\n' | sort -u | tr '\n' ' ')
stop=$(echo "$stop" | tr ' ' '\n' | sort -u | tr '\n' ' ')

stop="${stop## }" start="${start## }" # remove any leading  spaces
stop="${stop%% }" start="${start%% }" # remove any trailing spaces

[ -n "$start" ] && {
	# Only restart enabled, can get stop for disabled services
	# or service can be installed as disabled
	restart=
	for serv in $start; do
	  systemctl -q is-enabled $serv && restart="$restart $serv"
	done
}

[ -e /run/reboot-required ] && {
	logger -t Policy -s "System restart is required, not restarting services"
	[ -n "$stop" ] && logger -t Policy "Not stopping $stop"
	[ -n "$restart" ] && logger -t Policy "Not restarting $restart"
	exit 0
	}

norestart=/etc/cumulus/upgrade-norestart
[ -e "$norestart" ] && {
	logger -t Policy "System restart required by ${norestart}"
	[ -n "$stop" ] && logger -t Policy "Not stopping $stop"
	[ -n "$start" ] && logger -t Policy "Not restarting $start"
	echo ""
	echo "*** System restart required by ${norestart}"
	echo "*** Not stopping or restarting services"
	echo ""
	exit 0
	}


export stop start restart
# run in setsid so restarts (if any) complete even if ssh session
# goes away due to service being stopped
setsid bash  << EOF
[ -n "$stop" ] && {
	logger -t Policy "Stopping services: $stop"
	systemctl stop $stop
	logger -t Policy "Finished stopping services"
	}

[ -n "$start" ] && {
	if [ -z "${restart}" ]; then # no startable services enabled
		logger -t Policy "No enabled services to restart"
    else
        logger -t Policy "Restarting services: $restart"
        systemctl restart $restart
        logger -t Policy "Finished restarting services"
	fi
	}
EOF
