2020-06-04 14:37:01 +02:00
#!/bin/sh
# This script will check if any APT upgrade is available and
# will prepare the host in order to apply upgrade with another script
2020-06-18 08:45:28 +02:00
# 1. Create a temp file
# 2. Disable SGE queue
2020-06-04 14:37:01 +02:00
# This script can be call by a cronjob (eg. weekly)
# Another script should try to apply upgrades also with cron (eg. hourly)
# Vars {{{
readonly PROGNAME = $( basename " ${ 0 } " )
readonly PROGDIR = $( readlink -m $( dirname " ${ 0 } " ) )
readonly ARGS = " ${ * } "
readonly NBARGS = " ${# } "
2020-09-24 15:18:09 +02:00
[ -z " ${ DEBUG } " ] && DEBUG = 1
2020-06-04 14:37:01 +02:00
## Export DEBUG for sub-script
export DEBUG
2020-06-18 08:45:28 +02:00
readonly APT_TMP_FILE = "/tmp/.apt.upgrade"
2020-06-04 14:37:01 +02:00
## Colors
readonly PURPLE = '\033[1;35m'
readonly RED = '\033[0;31m'
readonly RESET = '\033[0m'
readonly COLOR_DEBUG = " ${ PURPLE } "
# }}}
usage( ) { # {{{
cat <<- EOF
2020-11-30 15:31:02 +01:00
usage: $PROGNAME [ -a| -d| -h| -t]
2020-06-04 14:37:01 +02:00
Verify if any APT package upgrade is available and
try to prepare the host by :
* Disabling SGE queue
EXAMPLES :
- Verify upgrade and prepare the current host
${ PROGNAME }
2020-09-24 15:18:09 +02:00
2020-11-30 15:31:02 +01:00
- Prepare the current host ( if pending upgrade) only after 6 runs
if sge_slots_used is under 75 % of total SGE slots.
${ PROGNAME } --attempts 6
2020-09-24 15:18:09 +02:00
OPTIONS :
2020-11-30 15:31:02 +01:00
-a,--attempt,--attempts,-t,--tries INT_MAX_ATTEMPTS
Number of time this script must be run to disable the host
if sge_slots_used is under 75 % of total SGE slots.
2020-09-24 15:18:09 +02:00
-d,--debug
Enable debug messages.
-h,--help
Print this help message.
2020-06-04 14:37:01 +02:00
EOF
}
# }}}
debug_message( ) { # {{{
local_message = " ${ 1 } "
## Print message if DEBUG is enable (=0)
[ " ${ DEBUG } " -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' " DEBUG − ${ PROGNAME } : ${ local_message } "
2020-08-20 10:02:11 +02:00
return 0
2020-06-04 14:37:01 +02:00
}
# }}}
2020-09-24 15:44:01 +02:00
define_vars( ) { # {{{
2020-11-30 15:31:02 +01:00
## If sge_hostname wasn't defined (environment variable,…)
2020-09-24 15:44:01 +02:00
if [ -z " ${ sge_hostname } " ] ; then
## Use local host for sge_hostname
sge_hostname = " $( hostname -f) "
fi
2020-11-30 15:31:02 +01:00
## If max_attempts wasn't defined
if [ -z " ${ max_attempts } " ] ; then
## Allow maximum 3 attempts before disable a host
max_attempts = "3"
fi
2020-09-25 13:39:27 +02:00
## Script used to disable SGE queue(s)
sge_disable_host_queue_script = " ${ PROGDIR } /sge.disable.host.queue.sh "
## Get the number of total SGE slots
sge_slots = $( qhost -h " ${ sge_hostname : =/dev/null } " -q -xml \
| grep --max-count= 1 -- "'slots'" \
| sed 's;.*<queuevalue.*>\(.*\)</queuevalue>;\1;' )
## Get the number of SGE used slots
sge_slots_used = $( qhost -h " ${ sge_hostname : =/dev/null } " -q -xml \
| grep --max-count= 1 -- "'slots_used'" \
| sed 's;.*<queuevalue.*>\(.*\)</queuevalue>;\1;' )
2020-09-24 15:44:01 +02:00
}
# }}}
2020-06-15 13:49:25 +02:00
is_apt_upgrade_absent( ) { # {{{
2020-06-04 14:37:01 +02:00
## Count the number of upgradable packages and substract 1 for the header
2020-06-25 08:50:17 +02:00
local_apt_upgrade_number = " $( apt list --upgradable 2>/dev/null \
2020-06-04 16:52:10 +02:00
| wc -l \
| awk '{print $1-1}' ) "
2020-06-04 14:37:01 +02:00
case " ${ local_apt_upgrade_number } " in
0 ) ## No available upgrade
return_apt_upgrade_absent = "0"
; ;
* ) ## Upgrade seems available
return_apt_upgrade_absent = "1"
; ;
esac
## Simple debug message to valid current variable
debug_message " is_apt_upgrade_absent − \
APT upgrade available for this system: ${ RED } ${ local_apt_upgrade_number : =/dev/null } ${ COLOR_DEBUG } ."
return " ${ return_apt_upgrade_absent } "
}
# }}}
2020-06-15 13:49:25 +02:00
is_apt_upgrade_present( ) { # {{{
2020-06-04 14:37:01 +02:00
## Count the number of upgradable packages and substract 1 for the header
2020-06-25 08:50:17 +02:00
local_apt_upgrade_number = " $( apt list --upgradable 2>/dev/null \
2020-06-04 16:52:10 +02:00
| wc -l \
| awk '{print $1-1}' ) "
2020-06-04 14:37:01 +02:00
case " ${ local_apt_upgrade_number } " in
0 ) ## No available upgrade
return_apt_upgrade_present = "1"
; ;
* ) ## Upgrade seems available
return_apt_upgrade_present = "0"
; ;
esac
## Simple debug message to valid current variable
debug_message " is_apt_upgrade_present − \
APT upgrade available for this system: ${ RED } ${ local_apt_upgrade_number : =/dev/null } ${ COLOR_DEBUG } ."
return " ${ return_apt_upgrade_present } "
2020-09-24 15:44:01 +02:00
}
# }}}
is_sge_slots_more_than_percentage( ) { # {{{
local_percentage = " ${ 1 } "
## Get the expected percentage of total SGE slots
2020-09-25 13:39:27 +02:00
local_sge_slots_percentage = $( echo " ${ sge_slots } " \
2020-09-24 15:44:01 +02:00
| awk -v percentage = " 0. ${ local_percentage } " '{ print int($1 * percentage) }' )
2020-09-25 13:39:27 +02:00
if [ " ${ sge_slots_used } " -ge " ${ local_sge_slots_percentage } " ] ; then
2020-09-24 15:44:01 +02:00
## Used slots is greater or equal than expected percentage
return_sge_slots_percentage = "0"
## Simple debug message to valid current variable
2020-09-25 13:24:20 +02:00
debug_message " is_sge_slots_more_than_percentage − \
2020-09-25 13:39:27 +02:00
Used slots has reached ${ RED } ${ local_percentage } %${ COLOR_DEBUG } of total slots: ${ RED } ${ sge_slots_used : =/dev/null } ${ COLOR_DEBUG } /${ sge_slots } ."
2020-09-24 15:44:01 +02:00
else
return_sge_slots_percentage = "1"
## Simple debug message to valid current variable
2020-09-25 13:24:20 +02:00
debug_message " is_sge_slots_more_than_percentage − \
2020-09-25 13:39:27 +02:00
Used slots did not reach ${ RED } ${ local_percentage } %${ COLOR_DEBUG } of total slots: ${ RED } ${ sge_slots_used : =/dev/null } ${ COLOR_DEBUG } /${ sge_slots } ."
2020-09-24 15:44:01 +02:00
fi
return " ${ return_sge_slots_percentage } "
2020-09-25 13:24:20 +02:00
}
# }}}
2020-11-30 14:45:23 +01:00
is_pending_upgrade_more_than_attempts( ) { # {{{
2020-09-25 13:24:20 +02:00
2020-11-30 14:45:23 +01:00
local_attempts = " ${ 1 } "
2020-09-25 13:24:20 +02:00
2020-11-30 17:50:27 +01:00
local_line_size = "26"
2020-09-25 13:24:20 +02:00
2020-11-30 14:45:23 +01:00
local_max_file_size = " $(( ${ local_attempts } * ${ local_line_size } )) "
2020-09-25 13:24:20 +02:00
2020-11-30 14:45:23 +01:00
debug_message " is_pending_upgrade_more_than_attempts ( ${ local_attempts } ) − \
Check if ${ APT_TMP_FILE } has a size bigger than ${ RED } ${ local_max_file_size : =/dev/null } ${ COLOR_DEBUG } bytes ( ${ local_attempts } attempts * ${ local_line_size } bytes size for one line) ."
2020-09-25 13:24:20 +02:00
if [ $( find " ${ APT_TMP_FILE } " -type f -size +" ${ local_max_file_size } " c 2>/dev/null) ] ; then
2020-11-30 14:45:23 +01:00
## Temp file seems to exist for more than the maximum attempts
return_pending_upgrade_more_than_attempts = "0"
debug_message " is_pending_upgrade_more_than_attempts − \
There is pending upgrade( s) for more than ${ RED } ${ local_attempts : =/dev/null } ${ COLOR_DEBUG } attempts."
2020-09-25 13:24:20 +02:00
else
2020-11-30 14:45:23 +01:00
return_pending_upgrade_more_than_attempts = "1"
debug_message " is_pending_upgrade_more_than_attempts − \
NO pending upgrades for more than ${ RED } ${ local_attempts : =/dev/null } ${ COLOR_DEBUG } attempts."
2020-09-25 13:24:20 +02:00
fi
2020-11-30 14:45:23 +01:00
return " ${ return_pending_upgrade_more_than_attempts } "
2020-09-25 13:24:20 +02:00
2020-09-25 11:36:12 +02:00
}
# }}}
is_sge_slots_empty( ) { # {{{
2020-09-25 13:39:27 +02:00
if [ " ${ sge_slots_used } " -eq "0" ] ; then
2020-09-25 11:36:12 +02:00
## Used slots is null
return_sge_slots_empty = "0"
else
return_sge_slots_empty = "1"
fi
## Simple debug message to valid current variable
debug_message " is_sge_slots_empty − \
2020-09-25 13:39:27 +02:00
SGE slots currently in use: ${ RED } ${ sge_slots_used : =/dev/null } ${ COLOR_DEBUG } ."
2020-09-25 11:36:12 +02:00
return " ${ return_sge_slots_empty } "
2020-09-24 14:56:27 +02:00
}
# }}}
is_pending_job_empty( ) { # {{{
## Count the number of pending jobs (qw state only)
## Excluding root's jobs
local_pending_jobs = " $( qstat -s p -u '*' \
| grep --count --perl-regexp -- " (?=.*?\bqw\b)((?!root).)* $" ) "
case " ${ local_pending_jobs } " in
0 ) ## Pending jobs list is empty
return_pending_job_empty = "0"
; ;
* ) ## Some jobs are waiting
return_pending_job_empty = "1"
; ;
esac
## Simple debug message to valid current variable
debug_message " is_pending_job_empty − \
Pending jobs for the compute cluster: ${ RED } ${ local_pending_jobs : =/dev/null } ${ COLOR_DEBUG } ."
return " ${ return_pending_job_empty } "
2020-06-04 14:37:01 +02:00
}
# }}}
main( ) { # {{{
2020-09-24 15:44:01 +02:00
## Define all vars
define_vars
2020-09-24 14:56:27 +02:00
## If NO APT package upgrade is available {{{
2020-06-18 08:45:28 +02:00
### Ensure to remove any temp file related to APT upgrades
2020-06-04 14:37:01 +02:00
### Exit
is_apt_upgrade_absent \
2020-06-18 08:45:28 +02:00
&& rm -f -- " ${ APT_TMP_FILE } " \
2020-06-04 14:37:01 +02:00
&& exit 0
2020-09-24 14:56:27 +02:00
## }}}
2020-09-25 15:08:51 +02:00
## If APT package upgrade(s) is available AND
2020-06-04 14:37:01 +02:00
is_apt_upgrade_present \
2020-09-25 15:08:51 +02:00
&& {
## If SGE used slots is more than 75% of total slots {{{
## APT package upgrade is available
### Create a temp file
### Disable SGE queue
is_sge_slots_more_than_percentage "75" \
&& touch " ${ APT_TMP_FILE } " && echo "APT upgrade is available." >> " ${ APT_TMP_FILE } " \
&& sh " ${ sge_disable_host_queue_script } " \
&& exit 0
## }}}
2020-11-30 15:31:02 +01:00
## If pending upgrade since max_attempts (default: 3) {{{
2020-09-25 15:08:51 +02:00
## APT package upgrade is available
### Create a temp file
### Disable SGE queue
2020-11-30 15:31:02 +01:00
is_pending_upgrade_more_than_attempts " ${ max_attempts } " \
2020-09-25 15:08:51 +02:00
&& touch " ${ APT_TMP_FILE } " && echo "APT upgrade is available." >> " ${ APT_TMP_FILE } " \
&& sh " ${ sge_disable_host_queue_script } " \
&& exit 0
## }}}
## If SGE used slots is NULL {{{
## APT package upgrade is available
### Create a temp file
### Disable SGE queue
is_sge_slots_empty \
&& touch " ${ APT_TMP_FILE } " && echo "APT upgrade is available." >> " ${ APT_TMP_FILE } " \
&& sh " ${ sge_disable_host_queue_script } " \
&& exit 0
## }}}
## If pending job list is empty {{{
## APT package upgrade is available
### Create a temp file
### Disable SGE queue
is_pending_job_empty \
&& touch " ${ APT_TMP_FILE } " && echo "APT upgrade is available." >> " ${ APT_TMP_FILE } " \
&& sh " ${ sge_disable_host_queue_script } " \
&& exit 0
## }}}
2020-11-30 15:31:02 +01:00
## After all just add content to a temp file (+1 attempt) {{{
2020-09-25 15:08:51 +02:00
touch " ${ APT_TMP_FILE } " && echo "APT upgrade is available." >> " ${ APT_TMP_FILE } " \
&& debug_message "main − Add content to temp file for pending upgrade(s)." \
&& exit 0
## }}}
}
2020-06-04 14:37:01 +02:00
}
# }}}
2020-09-24 15:18:09 +02:00
# Manage arguments # {{{
2020-11-30 15:31:02 +01:00
# This code can't be in a function due to argument management
2020-09-24 15:18:09 +02:00
if [ ! " ${ NBARGS } " -eq "0" ] ; then
manage_arg = "0"
## If the first argument is not an option
if ! printf -- '%s' " ${ 1 } " | grep -q -E -- "^-+" ;
then
## Print help message and exit
printf '%b\n' " ${ RED } Invalid option: ${ 1 } ${ RESET } "
printf '%b\n' "---"
usage
exit 1
fi
# Parse all options (start with a "-") one by one
while printf -- '%s' " ${ 1 } " | grep -q -E -- "^-+" ; do
case " ${ 1 } " in
2020-11-30 15:31:02 +01:00
-a| --attempt| --attempts| -t| --tries ) ## Fix the maximum attempts
## Move to the next argument
shift
## Define max_attempts with this argument
max_attempts = " ${ 1 } "
; ;
-d| --debug ) ## debug
2020-09-24 15:18:09 +02:00
DEBUG = 0
; ;
2020-11-30 15:31:02 +01:00
-h| --help ) ## help
2020-09-24 15:18:09 +02:00
usage
## Exit after help informations
exit 0
; ;
2020-11-30 15:31:02 +01:00
* ) ## unknow option
2020-09-24 15:18:09 +02:00
printf '%b\n' " ${ RED } Invalid option: ${ 1 } ${ RESET } "
printf '%b\n' "---"
usage
exit 1
; ;
esac
debug_message " Arguments management − \
${ RED } ${ 1 } ${ COLOR_DEBUG } option managed."
## Move to the next argument
shift
manage_arg = $(( manage_arg+1))
done
debug_message " Arguments management − \
${ RED } ${ manage_arg } ${ COLOR_DEBUG } argument( s) successfully managed."
else
debug_message " Arguments management − \
No arguments/options to manage."
fi
# }}}
2020-06-04 14:37:01 +02:00
main
2020-06-15 13:49:25 +02:00
exit 255