EVOLUTION-MANAGER
Edit File: ntopng-utils-manage-updates
#!/usr/bin/env bash # bin paths LSB_RELEASE="/usr/bin/lsb_release" APT_GET="/usr/bin/apt-get -qq" YUM="/usr/bin/yum" NTOPNG_CONFIG_TOOL="/usr/bin/ntopng-utils-manage-config" REDIS_CLI="/usr/bin/redis-cli" PRODUCT="ntopng" # redis keys REDIS_CHECK_FOR_UPDATES_KEY="ntopng.updates.check_for_updates" REDIS_NEW_VERSION_AVAILABLE_KEY="ntopng.updates.new_version" REDIS_RUN_UPGRADE_KEY="ntopng.updates.run_upgrade" REDIS_UPDATE_FAILURE_KEY="ntopng.updates.update_failure" REDIS_AUTO_UPDATES_KEY="ntopng.prefs.is_autoupdates_enabled" REDIS_IN_PROGRESS_KEY="ntopng.updates.in_progress" REDIS_PRODUCT_NAME_KEY="ntopng.product_name" ACTION="" QUIET=true LOGFILE_BASE="/var/log/ntopng-updates" LOGFILE="${LOGFILE_BASE}.log" RETAIN_NUM_LINES=1000 APT_SOURCE="ntop-stable.list" # Required by apt-get on Ubuntu 18 to run in non interactive mode export DEBIAN_FRONTEND="noninteractive" # Workaround for third-party installers not using absolute paths export PATH="$PATH:/sbin:/usr/sbin" # Read redis connection info REDIS_INFO=$(${NTOPNG_CONFIG_TOOL} -a print-redis-info) HOST=$(echo ${REDIS_INFO} | cut -d'=' -f2 | cut -d'@' -f1 | cut -d':' -f1) PORT=$(echo ${REDIS_INFO} | cut -d'=' -f2 | cut -d'@' -f1 | cut -d':' -f2 -s) PSWD=$(echo ${REDIS_INFO} | cut -d'=' -f2 | cut -d'@' -f1 | cut -d':' -f3 -s) DBID=$(echo ${REDIS_INFO} | cut -d'@' -f2 -s) REDIS_CLI_OPT="" if [ ! -z "${HOST}" ]; then REDIS_CLI_OPT="${REDIS_CLI_OPT}-h ${HOST} " fi if [ ! -z "${PORT}" ]; then REDIS_CLI_OPT="${REDIS_CLI_OPT}-p ${PORT} " fi if [ ! -z "${PSWD}" ]; then REDIS_CLI_OPT="${REDIS_CLI_OPT}-a ${PSWD} " fi if [ ! -z "${DBID}" ]; then REDIS_CLI_OPT="${REDIS_CLI_OPT}-n ${DBID} " fi # Detect OS OS="DEBIAN" if [ -x ${LSB_RELEASE} ]; then REDHAT=$(${LSB_RELEASE} -i | grep -i "CentOS\|RedHat\|Oracle\|Rocky\|AlmaLinux") if [ ! -z "${REDHAT}" ]; then OS="REDHAT" fi else if [ -f /etc/rocky-release ]; then OS="REDHAT" elif [ -f /etc/oracle-release ]; then OS="REDHAT" elif [ -f /etc/redhat-release ]; then OS="REDHAT" fi fi if [ "${OS}" == "DEBIAN" ]; then # Check for nEdge if dpkg --get-selections | grep -q "^nedge[[:space:]]*install$" >/dev/null; then PRODUCT="nedge" fi fi # Log init function logsetup { if [ ! -z "$1" ]; then LOGFILE="${LOGFILE_BASE}-$1.log" fi TMP=$(tail -n $RETAIN_NUM_LINES $LOGFILE 2>/dev/null) && echo "${TMP}" > $LOGFILE # Log to file and stdout (trigger crontab events, e.g. mail) #exec > >(tee -a $LOGFILE) # Log to file only exec > $LOGFILE exec 2>&1 } # Log function log { echo "$(date +"%b %d %T"): $*" } # Help function print_usage() { echo "${PRODUCT} updates utility" echo "" echo "Usage:" echo "`basename $0` -a check-updates" echo "`basename $0` -a check-updates-on-demand" echo "`basename $0` -a handle-upgrade-requests" echo "`basename $0` -a handle-on-demand-requests" echo "" echo "[-a check-updates]" echo "`basename $0` -a check-updates" echo "Check for ${PRODUCT} updates." echo "" echo "[-a check-updates-on-demand]" echo "`basename $0` -a check-updates-on-demand" echo "Check for requests for checking ${PRODUCT} updates." echo "" echo "[-a handle-upgrade-requests]" echo "`basename $0` -a handle-upgrade-requests" echo "Check for update requests and update ${PRODUCT}." echo "" echo "[-a handle-on-demand-requests]" echo "`basename $0` -a handle-on-demand-requests" echo "Check for requests from ${PRODUCT} (same as check-updates-on-demand + handle-upgrade-requests)." echo "" } POSITIONAL=() while [[ $# -gt 0 ]] do key="$1" case $key in -a|--action) ACTION="$2" shift shift ;; -v|--verbose) QUIET=false shift ;; *) POSITIONAL+=("$1") shift ;; esac done set -- "${POSITIONAL[@]}" # restore positional parameters if [[ ( $ACTION != "check-updates" && $ACTION != "check-updates-on-demand" && $ACTION != "handle-upgrade-requests" && $ACTION != "handle-on-demand-requests" ) ]]; then print_usage exit 1 fi # Uncomment to enable logging (moved to the single functions to reduce verbosity) #logsetup $ACTION #log Requested $ACTION function clear_failure() { ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_UPDATE_FAILURE_KEY} >/dev/null 2>&1 } function set_failure() { CLEANUP_REQ=$2 STATUS=$1 # Report failure status ${REDIS_CLI} ${REDIS_CLI_OPT} SET ${REDIS_UPDATE_FAILURE_KEY} "${STATUS}" >/dev/null 2>&1 if [ "${CLEANUP_REQ}" = "1" ]; then # Cleanup requests ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_CHECK_FOR_UPDATES_KEY} >/dev/null 2>&1 ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_RUN_UPGRADE_KEY} >/dev/null 2>&1 fi } function stall_check() { INSTANCES=$(pgrep -fc "$0 -a ${ACTION}") if [ $INSTANCES -gt 2 ]; then echo "Another instance is running with the same action" exit 0 fi } function maintenance_check() { APP_BIN="/usr/bin/${PRODUCT}" NOW=`date +'%s'` EXPIRY_EPOCH=`${APP_BIN} --check-maintenance | head -n 1 | tr -d '\n' | cut -d' ' -f 1` if [ "${EXPIRY_EPOCH}" = "Invalid" ]; then # Missing or expired or invalid license # Allow updates on missing license file as this does not # invalidate the license and handle community mode if [ `${APP_BIN} --check-license | grep Empty | wc -l ` -eq 0 ]; then # Expired or invalid license set_failure "no-license" 1 exit 0 fi elif echo "${EXPIRY_EPOCH}" | grep -q "^[0-9]\+$"; then if [ "${EXPIRY_EPOCH}" -gt "0" ] && [ "${EXPIRY_EPOCH}" -lt "${NOW}" ]; then # Expired maintenance set_failure "expired-maintenance" 1 exit 0 fi # else # Unable to read maintenance (Cloud license or app not found, ignore maintenance check) fi } function service_enabled_check() { SERVICE_ENABLED=$(/bin/systemctl is-enabled ${PRODUCT} 2>/dev/null) if [ ! "${SERVICE_ENABLED}" == "enabled" ]; then set_failure "service-not-enabled" 1 exit 0 fi } # Check if the user requested a ntopng update, and upgrade it in case function run_upgrade() { RESULT=1 # Check if upgrade is in progress (it can take more than 1 min) IN_PROGRESS=$(${REDIS_CLI} ${REDIS_CLI_OPT} GET ${REDIS_IN_PROGRESS_KEY} 2>/dev/null | grep 1) if [ "${IN_PROGRESS}" == "1" ]; then return fi # Set "in progress" flag ${REDIS_CLI} ${REDIS_CLI_OPT} SET ${REDIS_IN_PROGRESS_KEY} "1" EX 3600 >/dev/null 2>&1 logsetup $ACTION log Requested $ACTION clear_failure # Check if the product is under maintenance maintenance_check if [ "${OS}" == "DEBIAN" ]; then # Debian or Ubuntu # Update repo index #${APT_GET} update -o Dir::Etc::sourcelist="sources.list.d/${APT_SOURCE}" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" # Note: we are updating all the repos as ntopng may depend on old # packages no longer available in other repos, leading to an upgrade failure. ${APT_GET} update # Install #${APT_GET} upgrade --assume-yes --fix-broken --allow-unauthenticated --with-new-pkgs ${PRODUCT} # Note: using install instead of upgrade to avoid blocking the installation due to 'kept back' packages ${APT_GET} install --assume-yes --fix-broken --allow-unauthenticated ${PRODUCT} RESULT=$? # Check if installation is successful (we do not trust $?) #NTOPNG_VERSION=$(${APT_GET} --just-print upgrade 2>&1 | grep "Inst ${PRODUCT} " | cut -d'(' -f2 | cut -d' ' -f1) NTOPNG_VERSION=$(${APT_GET} --just-print install ${PRODUCT} 2>&1 | grep "Inst ${PRODUCT} " | cut -d'(' -f2 | cut -d' ' -f1) if [ -z "${NTOPNG_VERSION}" ]; then RESULT=0 fi else # CentOS # Install ${YUM} clean all ${YUM} check-update ${PRODUCT} ${YUM} -y install ${PRODUCT} RESULT=$? fi if [ $RESULT -eq 0 ]; then [ $QUIET = false ] && echo "${PRODUCT} updated successfully" # Cleanup new version available key ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_NEW_VERSION_AVAILABLE_KEY} >/dev/null 2>&1 clear_failure # Restart the service if not running (e.g. old prerm was disabling it) /bin/systemctl -q is-active ${PRODUCT} || /bin/systemctl restart ${PRODUCT} else [ $QUIET = false ] && echo "Unable to update" set_failure "upgrade-failure" 0 fi # Cleanup "in progress" flag ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_IN_PROGRESS_KEY} >/dev/null 2>&1 # Cleanup upgrade request key if any ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_RUN_UPGRADE_KEY} >/dev/null 2>&1 } # Check for new ntopng updates available function check_updates() { CRON_UPDATES=$1 NTOPNG_VERSION="" RESULT=1 logsetup $ACTION log Requested $ACTION clear_failure # Check if the product is under maintenance maintenance_check if [ "${OS}" == "DEBIAN" ]; then # Debian or Ubuntu # Update repo index ${APT_GET} update -o Dir::Etc::sourcelist="sources.list.d/${APT_SOURCE}" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" # Check for broken packages #${APT_GET} --just-print upgrade >/dev/null 2>&1 ${APT_GET} --just-print install ${PRODUCT} >/dev/null 2>&1 if [ ! $? -eq 0 ]; then # Something went wrong, trying to fix it ${APT_GET} --assume-yes --fix-broken install #${APT_GET} --just-print upgrade >/dev/null 2>&1 ${APT_GET} --just-print install ${PRODUCT} >/dev/null 2>&1 fi if [ ! $? -eq 0 ]; then # Something went wrong, unable to fix it set_failure "update-failure" 0 else # Check update and get version #NTOPNG_VERSION=$(${APT_GET} --just-print --assume-yes --with-new-pkgs upgrade 2>&1 | grep "Inst ${PRODUCT} " | cut -d'(' -f2 | cut -d' ' -f1) # Note: using install instead of upgrade to handle 'kept back' packages NTOPNG_VERSION=$(${APT_GET} --just-print --assume-yes install ${PRODUCT} 2>&1 | grep "Inst ${PRODUCT} " | cut -d'(' -f2 | cut -d' ' -f1) RESULT=0 fi else # CentOS # Check update and get version ${YUM} clean all NTOPNG_VERSION=$(${YUM} check-update ${PRODUCT} | grep ${PRODUCT} | tr -s ' ' | cut -d' ' -f2) RESULT=0 fi # If there is an update, set new version on redis, otherwise delete the current version (if any) if [ ! -z "${NTOPNG_VERSION}" ]; then ${REDIS_CLI} ${REDIS_CLI_OPT} SET ${REDIS_NEW_VERSION_AVAILABLE_KEY} ${NTOPNG_VERSION} EX 86400 >/dev/null 2>&1 # Reset failure reason if any clear_failure # Check if this is run by cron (not a manual check) if [ "${CRON_UPDATES}" = "1" ]; then # Check if automatic updates are enabled by the user AUTO_UPDATES=$(${REDIS_CLI} ${REDIS_CLI_OPT} GET ${REDIS_AUTO_UPDATES_KEY} 2>/dev/null | grep 1) if [ "${AUTO_UPDATES}" == "1" ]; then run_upgrade fi fi else ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_NEW_VERSION_AVAILABLE_KEY} >/dev/null 2>&1 if [ $RESULT -eq 0 ]; then clear_failure fi fi } # Check if the user requested a 'Check for updates' manually function check_updates_on_demand() { CHECK_FOR_UPDATES=$(${REDIS_CLI} ${REDIS_CLI_OPT} GET ${REDIS_CHECK_FOR_UPDATES_KEY} 2>/dev/null | grep 1) if [ "${CHECK_FOR_UPDATES}" == "1" ]; then stall_check check_updates 0 ${REDIS_CLI} ${REDIS_CLI_OPT} DEL ${REDIS_CHECK_FOR_UPDATES_KEY} >/dev/null 2>&1 fi } # Check if the user requested a ntopng update, and upgrade it in case function handle_upgrade_requests() { # Check redis for upgrade requests UPGRADE=$(${REDIS_CLI} ${REDIS_CLI_OPT} GET ${REDIS_RUN_UPGRADE_KEY} 2>/dev/null | grep 1) if [ "${UPGRADE}" == "1" ]; then stall_check run_upgrade fi } # Check OEM mode OEM_MODE=$(${REDIS_CLI} ${REDIS_CLI_OPT} EXISTS ${REDIS_PRODUCT_NAME_KEY} 2>/dev/null | grep 1) if [ "${OEM_MODE}" == "1" ]; then # Exit unless there is an OEM source file APT_SOURCE="ntop-oem.list" eval $(apt-config shell APT_ETC Dir::Etc) [ -e "/${APT_ETC}sources.list.d/${APT_SOURCE}" ] || exit 0 fi if [ $ACTION == "check-updates" ]; then # Run automatic update check when the ntopng service is enabled only service_enabled_check check_updates 1 elif [ $ACTION == "check-updates-on-demand" ]; then check_updates_on_demand elif [ $ACTION == "handle-upgrade-requests" ]; then handle_upgrade_requests elif [ $ACTION == "handle-on-demand-requests" ]; then # Same as check-updates-on-demand + handle-upgrade-requests check_updates_on_demand handle_upgrade_requests else # never reached echo "Unknown action $ACTION" exit 1 fi exit 0