#!/usr/bin/env bash ################################################################################ # Copyright (C) 2015 Daniel Preussker, QuxLabs UG # Copyright (C) 2016 Layne "Gorian" Breitkreutz # Copyright (C) 2017 Tony Murray # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ################################################################################ ####################################### # CONSTANTS ####################################### # define DAILY_SCRIPT as the full path to this script and LIBRENMS_DIR as the directory this script is in DAILY_SCRIPT=$(readlink -f "$0") LIBRENMS_DIR=$(dirname "$DAILY_SCRIPT") COMPOSER="php ${LIBRENMS_DIR}/scripts/composer_wrapper.php --no-interaction" # set log_file, using librenms $config['log_dir'], if set # otherwise we default to /logs LOG_DIR=$(php -r "@include '${LIBRENMS_DIR}/config.php'; echo isset(\$config['log_dir']) ? \$config['log_dir'] : '${LIBRENMS_DIR}/logs';") # get the librenms user LIBRENMS_USER=$(php -r "@include '${LIBRENMS_DIR}/config.php'; echo isset(\$config['user']) ? \$config['user'] : 'root';") LIBRENMS_USER_ID=$(id -u "$LIBRENMS_USER") ####################################### # Fancy-Print and run commands # Globals: # LOG_DIR # Arguments: # Text # Command # Returns: # Exit-Code of Command ####################################### status_run() { # Explicitly define our arguments local args="$@"; local arg_text=$1; local arg_command=$2; local arg_option=$3; local log_file; local exit_code; local tmp; local log_file=${LOG_DIR}/daily.log; # set log_file, using librenms $config['log_dir'], if set # otherwise we default to ./logs/daily.log printf "%-50s" "${arg_text}"; echo "${arg_text}" >> ${log_file} tmp=$(bash -c "${arg_command}" 2>&1); exit_code=$? echo "${tmp}" >> ${log_file} echo "Returned: ${exit_code}" >> ${log_file} # print OK if the command ran successfully # or FAIL otherwise (non-zero exit code) if [[ "${exit_code}" == "0" ]]; then printf " \033[0;32mOK\033[0m\n"; else printf " \033[0;31mFAIL\033[0m\n"; if [[ "${arg_option}" == "update" ]]; then php "${LIBRENMS_DIR}/daily.php" -f notify -o "${tmp}" fi if [[ ! -z "${tmp}" ]]; then # print output in case of failure echo "${tmp}" fi fi return ${exit_code} } ####################################### # Call daily.php # Globals: # LIBRENMS_DIR # Arguments: # args: # Array of arguments to pass to # daily.php # Returns: # Exit-Code of Command ####################################### call_daily_php() { local args=( "$@" ); for arg in "${args[@]}"; do php "${LIBRENMS_DIR}/daily.php" -f "${arg}"; done } ####################################### # Send result of a notifiable process to php code for processing # Globals: # LIBRENMS_DIR # Arguments: # args: # Type: update # Result: 1 for success, 0 for failure # Returns: # Exit-Code of Command ####################################### set_notifiable_result() { local args="$@"; local arg_type=$1; local arg_result=$2; php "${LIBRENMS_DIR}/daily.php" -f handle_notifiable -t ${arg_type} -r ${arg_result}; } ####################################### # Check the PHP version and branch and switch to the appropriate branch # Returns: # Exit-Code: 0 >= min ver, 1 < min ver ####################################### check_php_ver() { local branch=$(git rev-parse --abbrev-ref HEAD) local ver_res=$(php -r "echo (int)version_compare(PHP_VERSION, '5.6.4', '<');") if [[ "$branch" == "php53" ]] && [[ "$ver_res" == "0" ]]; then status_run "Supported PHP version, switched back to master branch." 'git checkout master' branch="master" elif [[ "$branch" != "php53" ]] && [[ "$ver_res" == "1" ]]; then status_run "Unsupported PHP version, switched to php53 branch." 'git checkout php53' branch="php53" fi set_notifiable_result phpver ${ver_res} return ${ver_res}; } ####################################### # Entry into program # Globals: # LIBRENMS_DIR # Arguments: # # Returns: # Exit-Code of Command ####################################### main () { local arg="$1"; local old_version="$2"; local new_version="$3"; local old_version="${old_version:=unset}" # if $1 is unset, make it mismatch for pre-update daily.sh cd ${LIBRENMS_DIR}; # if not running as $LIBRENMS_USER (unless $LIBRENMS_USER = root), relaunch if [[ "$LIBRENMS_USER" != "root" ]]; then # only try to su if we are root (or sudo) if [[ "$EUID" -eq 0 ]]; then echo "Re-running ${DAILY_SCRIPT} as ${LIBRENMS_USER} user" sudo -u "$LIBRENMS_USER" "$DAILY_SCRIPT" "$@" exit; fi if [[ "$EUID" -ne "$LIBRENMS_USER_ID" ]]; then printf "\033[0;93mWARNING\033[0m: You should run this script as ${LIBRENMS_USER}\n"; fi fi # make sure autoload.php exists before trying to run any php that may require it if [ ! -f "${LIBRENMS_DIR}/vendor/autoload.php" ]; then ${COMPOSER} install --no-dev fi if [[ -z "$arg" ]]; then up=$(php daily.php -f update >&2; echo $?) if [[ "$up" == "0" ]]; then ${DAILY_SCRIPT} no-code-update set_notifiable_result update 1 # make sure there are no update notifications if update is disabled exit fi check_php_ver php_ver_ret=$? # make sure the vendor directory is clean git checkout vendor/ --quiet > /dev/null 2>&1 update_res=0 if [[ "$up" == "1" ]] || [[ "$php_ver_ret" == "1" ]]; then # Update current branch to latest local branch=$(git rev-parse --abbrev-ref HEAD) if [[ "$branch" == "HEAD" ]]; then # if the branch is HEAD, then we are not on a branch, checkout master git checkout master fi old_ver=$(git rev-parse --short HEAD) status_run 'Updating to latest codebase' 'git pull --quiet' 'update' update_res=$? new_ver=$(git rev-parse --short HEAD) elif [[ "$up" == "3" ]]; then # Update to last Tag old_ver=$(git describe --exact-match --tags $(git log -n1 --pretty='%h')) status_run 'Updating to latest release' 'git fetch --tags && git checkout $(git describe --tags $(git rev-list --tags --max-count=1))' 'update' update_res=$? new_ver=$(git describe --exact-match --tags $(git log -n1 --pretty='%h')) fi if (( $update_res > 0 )); then set_notifiable_result update 0 fi # Call ourself again in case above pull changed or added something to daily.sh ${DAILY_SCRIPT} post-pull ${old_ver} ${new_ver} else case $arg in no-code-update) # Updates of the code are disabled, just check for schema updates # and clean up the db. status_run 'Updating SQL-Schema' 'php includes/sql-schema/update.php' status_run 'Cleaning up DB' "$DAILY_SCRIPT cleanup" ;; post-pull) # Check for missing vendor dir if [ ! -f vendor/autoload.php ]; then git checkout 609676a9f8d72da081c61f82967e1d16defc0c4e -- vendor/ git reset HEAD vendor/ # don't add vendor directory to the index fi status_run 'Updating Composer packages' "${COMPOSER} install --no-dev" 'update' # Check if we need to revert (Must be in post pull so we can update it) if [[ "$old_version" != "$new_version" ]]; then check_php_ver # check php version and switch branches # new_version may be incorrect if we just switch branches... ignoring that detail status_run "Updated from $old_version to $new_version" '' set_notifiable_result update 1 # only clear the error if update was a success fi # List all tasks to do after pull in the order of execution status_run 'Updating SQL-Schema' 'php includes/sql-schema/update.php' status_run 'Updating submodules' "$DAILY_SCRIPT submodules" status_run 'Cleaning up DB' "$DAILY_SCRIPT cleanup" status_run 'Fetching notifications' "$DAILY_SCRIPT notifications" status_run 'Caching PeeringDB data' "$DAILY_SCRIPT peeringdb" ;; cleanup) # Cleanups local options=("refresh_alert_rules" "refresh_os_cache" "syslog" "eventlog" "authlog" "perf_times" "callback" "device_perf" "purgeusers" "bill_data" "alert_log" "rrd_purge" "ports_purge"); call_daily_php "${options[@]}"; ;; submodules) # Init+Update our submodules git submodule --quiet init git submodule --quiet update ;; notifications) # Get notifications local options=("notifications"); call_daily_php "${options[@]}"; ;; peeringdb) local options=("peeringdb"); call_daily_php "${options[@]}"; ;; esac fi } main "$@"