scripts/cluster/apt.check.update.sh

371 lines
10 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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
# 1. Create a temp file
# 2. Disable SGE queue
# 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="${#}"
[ -z "${DEBUG}" ] && DEBUG=1
## Export DEBUG for sub-script
export DEBUG
readonly APT_TMP_FILE="/tmp/.apt.upgrade"
## Colors
readonly PURPLE='\033[1;35m'
readonly RED='\033[0;31m'
readonly RESET='\033[0m'
readonly COLOR_DEBUG="${PURPLE}"
# }}}
usage() { # {{{
cat <<- EOF
usage: $PROGNAME [-a|-d|-h|-t]
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}
- 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
OPTIONS:
-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.
-d,--debug
Enable debug messages.
-h,--help
Print this help message.
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}"
return 0
}
# }}}
define_vars() { # {{{
## If sge_hostname wasn't defined (environment variable,…)
if [ -z "${sge_hostname}" ]; then
## Use local host for sge_hostname
sge_hostname="$(hostname -f)"
fi
## If max_attempts wasn't defined
if [ -z "${max_attempts}" ]; then
## Allow maximum 3 attempts before disable a host
max_attempts="3"
fi
## 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;')
}
# }}}
is_apt_upgrade_absent() { # {{{
## Count the number of upgradable packages and substract 1 for the header
local_apt_upgrade_number="$(apt list --upgradable 2>/dev/null \
| wc -l \
| awk '{print $1-1}')"
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}"
}
# }}}
is_apt_upgrade_present() { # {{{
## Count the number of upgradable packages and substract 1 for the header
local_apt_upgrade_number="$(apt list --upgradable 2>/dev/null \
| wc -l \
| awk '{print $1-1}')"
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}"
}
# }}}
is_sge_slots_more_than_percentage() { # {{{
local_percentage="${1}"
## Get the expected percentage of total SGE slots
local_sge_slots_percentage=$(echo "${sge_slots}" \
| awk -v percentage="0.${local_percentage}" '{ print int($1 * percentage) }')
if [ "${sge_slots_used}" -ge "${local_sge_slots_percentage}" ]; then
## Used slots is greater or equal than expected percentage
return_sge_slots_percentage="0"
## Simple debug message to valid current variable
debug_message "is_sge_slots_more_than_percentage \
Used slots has reached ${RED}${local_percentage}%${COLOR_DEBUG} of total slots: ${RED}${sge_slots_used:=/dev/null}${COLOR_DEBUG}/${sge_slots}."
else
return_sge_slots_percentage="1"
## Simple debug message to valid current variable
debug_message "is_sge_slots_more_than_percentage \
Used slots did not reach ${RED}${local_percentage}%${COLOR_DEBUG} of total slots: ${RED}${sge_slots_used:=/dev/null}${COLOR_DEBUG}/${sge_slots}."
fi
return "${return_sge_slots_percentage}"
}
# }}}
is_pending_upgrade_more_than_attempts() { # {{{
local_attempts="${1}"
local_line_size="24"
local_max_file_size="$(( ${local_attempts} * ${local_line_size} ))"
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)."
if [ $(find "${APT_TMP_FILE}" -type f -size +"${local_max_file_size}"c 2>/dev/null) ]; then
## 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."
else
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."
fi
return "${return_pending_upgrade_more_than_attempts}"
}
# }}}
is_sge_slots_empty() { # {{{
if [ "${sge_slots_used}" -eq "0" ]; then
## 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 \
SGE slots currently in use: ${RED}${sge_slots_used:=/dev/null}${COLOR_DEBUG}."
return "${return_sge_slots_empty}"
}
# }}}
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}"
}
# }}}
main() { # {{{
## Define all vars
define_vars
## If NO APT package upgrade is available {{{
### Ensure to remove any temp file related to APT upgrades
### Exit
is_apt_upgrade_absent \
&& rm -f -- "${APT_TMP_FILE}" \
&& exit 0
## }}}
## If APT package upgrade(s) is available AND
is_apt_upgrade_present \
&& {
## 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
## }}}
## If pending upgrade since max_attempts (default: 3) {{{
## APT package upgrade is available
### Create a temp file
### Disable SGE queue
is_pending_upgrade_more_than_attempts "${max_attempts}" \
&& 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
## }}}
## After all just add content to a temp file (+1 attempt) {{{
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
## }}}
}
}
# }}}
# Manage arguments # {{{
# This code can't be in a function due to argument management
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
-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
DEBUG=0
;;
-h|--help ) ## help
usage
## Exit after help informations
exit 0
;;
* ) ## unknow option
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
# }}}
main
exit 255