scripts/cluster/apt.check.update.sh

370 lines
9.1 KiB
Bash
Executable File
Raw Permalink 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 [-d|-e|-h]
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}
OPTIONS:
-d,--debug
Enable debug messages.
-e,--empty
Check APT upgrades only if SGE slots are empty
-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 EMPTY_ONLY_MODE wasn't defined (argument, environment variable,…) {{{
if [ -z "${EMPTY_ONLY_MODE}" ]; then
### Set False by default
EMPTY_ONLY_MODE="1"
fi
## }}}
## Script used to disable SGE queue(s)
sge_disable_host_queue_script="${PROGDIR}/sge.disable.host.queue.sh"
## 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;')
## SGE queues state file
cluster_dir="/opt/ipr/cluster"
sge_queue_flag_pattern="${cluster_dir}/.sge.*.disable"
}
# }}}
is_sge_host() { # {{{
## Check if SGE commands (qconf) are available
if [ "$(command -v qconf)" ]; then
debug_message "is_sge_host \
SGE seems present on this host."
### And verify if the host is fully configured as a submit host
if qconf -ss 2>/dev/null | grep --word-regexp --quiet $(hostname -f); then
debug_message "is_sge_host \
The host seems configured as a SGE submit host."
return_is_sge_host="0"
else
return_is_sge_host="1"
debug_message "is_sge_host \
This host is not yet configured as a SGE submit host."
fi
else
return_is_sge_host="1"
debug_message "is_sge_host \
SGE is not present on this host."
fi
return "${return_is_sge_host}"
}
# }}}
is_sge_master_available() { # {{{
## Check with Netcat if SGE master (sge_qmaster) is reachable from this host.
### -z: Only scan for listening daemons, without sending any data to them.
### -w 10: Timeout the test after 10 seconds.
if nc -z -w 10 "${sge_master_uri}" "${sge_master_port}"; then
return_is_sge_master_available="0"
debug_message "is_sge_master_available \
SGE Master (${sge_master_uri}:${sge_master_port}) is reachable from this host."
else
return_is_sge_master_available="1"
debug_message "is_sge_master_available \
SGE Master (${sge_master_uri}:${sge_master_port}) is not reachable from this host."
fi
return "${return_is_sge_master_available}"
}
# }}}
APT_PACKAGE_LIST_IS_UP_TO_DATE='false'
ensure_apt_package_list_is_up_to_date()
{
if [ "$APT_PACKAGE_LIST_IS_UP_TO_DATE" = 'false' ]
then
apt update &> /dev/null
APT_PACKAGE_LIST_IS_UP_TO_DATE='true'
fi
}
get_num_outdated_packages()
{
# ensure that the package list is up to date, because "apt list --upgradable" doesn't automatically do it
ensure_apt_package_list_is_up_to_date
## Count the number of upgradable packages and substract 1 for the header
local num_outdated_packages="$(apt list --upgradable 2>/dev/null \
| wc -l \
| awk '{print $1-1}')"
echo "${num_outdated_packages}"
}
some_packages_are_outdated()
{
local num_outdated_packages=''
num_outdated_packages=$(get_num_outdated_packages)
debug_message "some_packages_are_outdated \
number of outdated packages on this system: ${RED}${num_outdated_packages:=/dev/null}${COLOR_DEBUG}."
local return_code=''
case "${num_outdated_packages}" in
0 )
return_code='1' # some_packages_are_outdated = false
;;
* )
return_code='0' # some_packages_are_outdated = true
;;
esac
return "${return_code}"
}
is_file_present() { # {{{
local_file_present="${1}"
## File doesn't exist by default
return_is_file_present="1"
### Check if the file exists
# shellcheck disable=SC2086
if find ${local_file_present} > /dev/null 2>&1; then
return_is_file_present="0"
debug_message "is_file_present \
The file ${RED}${local_file_present}${COLOR_DEBUG} exists."
else
return_is_file_present="1"
debug_message "is_file_present \
The file ${RED}${local_file_present}${COLOR_DEBUG} doesn't exist."
fi
return "${return_is_file_present}"
}
# }}}
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}"
}
# }}}
main() { # {{{
## Test if SGE Master is reachable {{{
### If sge_master_uri wasn't defined (environment variable,…) {{{
if [ -z "${sge_master_uri}" ]; then
## Get SGE master from current configuration
sge_master_uri=$(grep --max-count=1 -- "" /var/lib/gridengine/default/common/act_qmaster 2>/dev/null || echo "localhost")
fi
### }}}
### If sge_master_port wasn't defined (environment variable,…) {{{
if [ -z "${sge_master_port}" ]; then
## Use local host for sge_master_port
sge_master_port="6444"
fi
### }}}
### If SGE Master is not reachable from this host {{{
#### Exit
is_sge_master_available \
|| exit 0
### }}}
## }}}
## If SGE is not yet available on this host {{{
### Exit
is_sge_host \
|| exit 0
## }}}
## Define all vars
define_vars
## If NO APT packages are out of date {{{
### Ensure to remove any temp file related to APT upgrades
### AND Exit
if [ ! "$(some_packages_are_outdated)" ]
then
rm -f -- "${APT_TMP_FILE}" \
&& exit 0
fi
## }}}
## If APT temp file already exists {{{
### Exit
is_file_present "${APT_TMP_FILE}" \
&& exit 0
## }}}
## If SGE flag files already exists {{{
### Check if APT package upgrade is available
### Create APT temp file
### AND Exit
is_file_present "${sge_queue_flag_pattern}" \
&& some_packages_are_outdated \
&& touch "${APT_TMP_FILE}" && echo "APT upgrade is available." >> "${APT_TMP_FILE}" \
&& exit 0
## }}}
## If EMPTY_ONLY_MODE is set {{{
### Verify empty slots
### OR Exit
if [ "${EMPTY_ONLY_MODE}" -eq "0" ]; then
### If SGE slots are not empty
### Exit
is_sge_slots_empty \
|| exit 0
fi
## }}}
## If APT package upgrade is available {{{
### Create APT temp file
### Disable SGE queue
### AND Exit
some_packages_are_outdated \
&& touch "${APT_TMP_FILE}" && echo "APT upgrade is available." >> "${APT_TMP_FILE}" \
&& sh "${sge_disable_host_queue_script}" \
&& 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
-d|--debug ) ## debug
DEBUG=0
;;
-e|--empty ) ## Empty only mode
EMPTY_ONLY_MODE="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