#!/bin/bash
#
# Script to restart services automatically, if libraries or
# binaries have been updated.
#
# Copyright (c) 2023 SUSE Software Solutions Germany GmbH
# Author: Lars Vogdt
#
# All rights reserved.
#       
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#       
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#       
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the Novell nor the names of its contributors may be
#   used to endorse or promote products derived from this software without
#   specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

PATH=/bin:/usr/bin:/sbin:/usr/sbin
umask 027
DISTCONFIG='/etc/sysconfig/suse-online-update'
##################################################
# Default/Fallback values
# Don't change them here! Use $DISCONFIG instead
##################################################
LOGFILE='/var/log/systemupdate.log'
IGNORE_SERVICES_FROM_RESTART='dbus udev'
##################################################
LOGDIR=$(dirname "$LOGFILE")
LOGNAME='zypper_ps_restart'
HOST=$(hostname -s)
DEBUG='no'
ZYPPER='/usr/bin/zypper'

function cleanup_and_exit(){
    exit $1
}
trap cleanup_and_exit 0 1 2 3 7 13 15

function LOG(){
    local MESSAGE="$1" 
    local LOG_DATE=$(date "+%b %d %H:%M:%S")
    echo "$LOG_DATE $HOST $LOGNAME[$$]: $MESSAGE" >> $LOGFILE
    if [ "$DEBUG" = "yes" ]; then
        echo "DEBUG:    $MESSAGE"
    fi      
}

function usage(){
    echo "Usage: $0 [OPTION]"
    echo
    echo "       -d             : print debug output on console (default: $DEBUG)"
	echo "       -f <sysconfig> : use <sysconfig> as configuration file (default: $DISTCONFIG)"
	echo "       -l <logfile>   : use <logfile> as log file (default: $LOGFILE)"
    echo "       -h             : print this help"
    echo
}

while getopts 'df:l:h' OPT; do
    case "$OPT" in
        d) DEBUG='yes'
        ;;
        f) DISTCONFIG="$OPTARG"
        ;;
		l) LOGFILE="$OPTARG"
        ;;
		h) usage; exit 0;
        ;;
    esac
done
shift $(( OPTIND - 1 ))

# source our config
if [ -r "$DISTCONFIG" ]; then
    . "$DISTCONFIG"
else
	echo "$DISTCONFIG not found - using defaults" >&2
	if [ -w "$LOGFILE" ]; then LOG "$DISTCONFIG not found - using defaults"; fi
fi
if [ -z "$LOGFILE" ]; then
    echo "ERROR: LOGFILE is not defined" | $MAILX -s "[$LOGNAME] error on $FQHOSTNAME" $EMAIL
    cleanup_and_exit 1
fi
if [ ! -d "$LOGDIR" ]; then
    mkdir -p "$LOGDIR" || exit 1
    echo "$LOG_DATE $HOST $LOGNAME[$$]: created $LOGDIR" > "$LOGFILE"
fi
touch "$LOGFILE" || { echo "Could not create $LOGFILE"; cleanup_and_exit 1; }
if [ ! -w "$LOGFILE" ]; then
    echo "Could not write to $LOGFILE - please fix" >&2
    cleanup_and_exit 1
fi

if [ "$RESTART_PREFER_RELOAD" = "yes" ] ; then
    RESTART_CMD="try-reload-or-restart"
else
    RESTART_CMD="try-restart"
fi
#
# Start script
#
LOG "zypper_ps_restart started"
if [ -x "$ZYPPER" ]; then # >SLES10 SP2
	$ZYPPER ps --print %s 1>/dev/null 2>&1
	ZYPP_RET=$(echo $?)
	case "$ZYPP_RET" in
		0) 	for service in $(zypper ps --print %s); do 
			    if [[ $IGNORE_SERVICES_FROM_RESTART =~ (^|[[:space:]])$service($|[[:space:]]) ]]; then
				   echo "Will not handle $service, as it is in IGNORE_SERVICES_FROM_RESTART list." 
		    	else
				  case "$service" in 
					'firewalld')
					  if systemctl -q is-enabled fail2ban ; then
						LOG "Restarting services firewalld and fail2ban"
						systemctl stop fail2ban
						systemctl stop firewalld
						systemctl start firewalld
						systemctl start fail2ban
					  else
						LOG "Restarting firewalld"
						systemctl try-reload-or-restart firewalld
					  fi
				  ;;
				  *)
					LOG "Restarting $service"
					systemctl $RESTART_CMD $service.service || LOG "$service $RESTART_CMD failed" >&2; 
				  ;;
				esac
			  fi
			done
		;;
		2) LOG "RESTART_SERVICES is set to 'yes' in $DISTCONFIG, but your system does not support this. Please upgrade your system."
		;;
		*) LOG "An error occured while trying to execute '$ZYPPER ps --print %s' - please check the output while running this command manually"
		;;
	esac
else
	LOG "$ZYPPER not found or not executable. Please install package zypper"
fi
LOG "zypper_ps_restart finished"
cleanup_and_exit 0

