From 0def643e09ea88e72ef71266fa09a185067a82a3 Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Sat, 26 Aug 2017 15:35:39 -0500 Subject: [PATCH] feature: Notify about failed updates, block detectable bad updates (#7188) * Feature: Notify about failed updates, block detectable bad updates Ability to post notifications when the update fails. Detect and roll back updates that will cause broken installs. (Needs testing) Add severity to notifications, critical (2) notifications will display a toast. This will be used for removing in-tree dependencies and raising the minimum php version. * Improve naming a bit add phpdoc to new_notification In case multiple notifications are created, remove them all. * Remove notifications when update is disabled. * update travis to use db testing * added missing index --- .travis.yml | 3 +- daily.php | 23 +++++++++- daily.sh | 61 ++++++++++++++++++++---- html/index.php | 8 ++++ html/pages/notifications.inc.php | 79 ++++++++++++++++++++++---------- includes/notifications.php | 56 +++++++++++++++++++--- misc/db_schema.yaml | 4 +- sql-schema/205.sql | 3 ++ 8 files changed, 194 insertions(+), 43 deletions(-) create mode 100644 sql-schema/205.sql diff --git a/.travis.yml b/.travis.yml index 28e8d1d0e4..788b7e9958 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ matrix: fast_finish: true include: - php: 7.1 + env: EXECUTE_BUILD_SCHEMA=true - php: 7.0 env: SKIP_STYLE_CHECK=1 - php: 5.3 @@ -17,7 +18,7 @@ matrix: - php: 5.5 env: SKIP_STYLE_CHECK=1 - php: 5.6 - env: SKIP_STYLE_CHECK=1 EXECUTE_BUILD_DOCS=true EXECUTE_BUILD_SCHEMA=false + env: SKIP_STYLE_CHECK=1 EXECUTE_BUILD_DOCS=true # - php: hhvm # env: SKIP_STYLE_CHECK=1 diff --git a/daily.php b/daily.php index 71ab462bb6..1f0ca5950a 100644 --- a/daily.php +++ b/daily.php @@ -8,8 +8,9 @@ $init_modules = array('alerts'); require __DIR__ . '/includes/init.php'; +include_once __DIR__ . '/includes/notifications.php'; -$options = getopt('f:d:o:'); +$options = getopt('f:d:o:t:r:'); if (isset($options['d'])) { echo "DEBUG\n"; @@ -97,8 +98,26 @@ if ($options['f'] === 'device_perf') { } } +if ($options['f'] === 'set_notification') { + if ($options['t'] === 'update') { + $title = 'Error: Daily update failed'; + + if ($options['r']) { + remove_notification($title); + } else { + new_notification( + $title, + 'The daily update script (daily.sh) has failed. Please check output by hand. If you need assistance, ' + . 'visit the LibreNMS Website to find out how.', + 2, + 'daily.sh' + ); + } + } +} + if ($options['f'] === 'notifications') { - include_once 'includes/notifications.php'; + post_notifications(); } if ($options['f'] === 'bill_data') { diff --git a/daily.sh b/daily.sh index e40c5154bd..e98091cc2b 100755 --- a/daily.sh +++ b/daily.sh @@ -22,6 +22,7 @@ # 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" # set log_file, using librenms $config['log_dir'], if set # otherwise we default to /logs @@ -95,6 +96,25 @@ call_daily_php() { done } +####################################### +# Set critical notifications for the user +# Globals: +# LIBRENMS_DIR +# Arguments: +# args: +# Type: update +# Result: 1 for success, 0 for failure +# Returns: +# Exit-Code of Command +####################################### +set_notification() { + local args="$@"; + local arg_type=$1; + local arg_result=$2; + + php "${LIBRENMS_DIR}/daily.php" -f set_notification -t ${arg_type} -r ${arg_result}; +} + ####################################### # Entry into program # Globals: @@ -122,28 +142,51 @@ main () { 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 + ${DAILY_SCRIPT} no-code-update + set_notification update 0 # make sure there are no update notifications if update is disabled exit - elif [[ "$up" == "1" ]]; then + fi + + # make sure the vendor directory is clean + git checkout vendor/ --quiet > /dev/null 2>&1 + + update_res=0 + if [[ "$up" == "1" ]]; then # Update to Master-Branch - git checkout vendor/ --quiet > /dev/null 2>&1 old_ver=$(git show --pretty="%H" -s HEAD) status_run 'Updating to latest codebase' 'git pull --quiet' 'update' + update_res=$? new_ver=$(git show --pretty="%H" -s HEAD) - if [ "$old_ver" != "$new_ver" ]; then - status_run "Updated from $old_ver to $new_ver" '' - fi elif [[ "$up" == "3" ]]; then # Update to last Tag - git checkout vendor/ --quiet > /dev/null 2>&1 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')) - if [[ "$old_ver" != "$new_ver" ]]; then + fi + + if (( $update_res > 0 )); then + set_notification update 0 + fi + + if [[ "$old_ver" != "$new_ver" ]]; then +# status_run 'Updating Composer packages' "${COMPOSER} install --no-dev" 'update' + + # Run post update checks + if [ ! -f "${LIBRENMS_DIR}/vendor/autoload.php" ]; then + status_run "Reverting update, check the output of composer diagnose" "git checkout $old_ver" 'update' + set_notification update 0 + else status_run "Updated from $old_ver to $new_ver" '' + set_notification update 1 # only clear the error if update was a success fi fi @@ -156,7 +199,7 @@ main () { if [[ -z "$cnf" ]] || [[ "$cnf" == "0" ]] || [[ "$cnf" == "false" ]]; then # Call ourself again in case above pull changed or added something to daily.sh - $DAILY_SCRIPT post-pull + ${DAILY_SCRIPT} post-pull fi else case $arg in diff --git a/html/index.php b/html/index.php index 26e40d9991..c7a6e59b8f 100644 --- a/html/index.php +++ b/html/index.php @@ -302,6 +302,14 @@ if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `last_polled` <= DATE_ADD( $msg_box[] = array('type' => 'warning', 'message' => "It appears as though you have some devices that haven't completed polling within the last 15 minutes, you may want to check that out :)",'title' => 'Devices unpolled'); } +foreach (dbFetchRows('SELECT * FROM `notifications` WHERE `severity` > 1') as $notification) { + $msg_box[] = array( + 'type' => 'error', + 'message' => "${notification['body']}", + 'title' => $notification['title'] + ); +} + if (is_array($msg_box)) { echo("