#!/bin/bash set -x fifo="" GIT_SSL_NO_VERIFY=true init_fifo () { trap "rm -f $fifo" EXIT if [ $? -eq 0 ]; then # set trap if [[ ! -p "$fifo" ]]; then mkfifo "$fifo" if [ $? -eq 0 ]; then # fifo created echo "created fifo=$fifo" return 0 fi fi fi return 1 } read_config() { fifo_dir=$(cat "$1" | jq -r .fifo_dir) if [ -z "$fifo_dir" ]; then return 1 fi fifo=$(cat "$1" | jq -r .fifo) if [ -z "$fifo" ]; then return 1 fi fifo="${fifo_dir}/$fifo" return 0 } wait_for_trigger() { if [[ "$1" -eq -1 ]]; then # wait for external impulse if read line <$fifo; then if [ "$line" = "quit" ] || [ "$line" = "update" ]; then echo "$line" fi fi else sleep $1 echo "sleep" fi } # APISM has al least two TCP-ports open: 7778 and 7779. To check for a running # APISM it is therefore enough to check for the port 7778. netcat will return 0 # if the port 7778 is open. check_for_apism() { return 0 nc localhost 7778 if [ $? -eq 0 ]; then return 0 fi return 1 } ######################### send_to_ismas.txt ################################### # #M=GH_APP # #C=REQ_ISMASParameter # #J={} # { # "DEV_ID": { # "Device_Type": "2020", # "Custom_ID": 999, # "Device_ID": 1 # }, # "REQ_ISMASParameter_#1": {} # } # # APISM should respond with (something like this): # # { # "REQ_ISMASPARAMETER#69553_Response": { # "Aknoledge": "OK" # }, # "Dev_ID": { # "Device_Type": "ISMAS", # "Custom_ID": 999, # "Device_ID": 2 # }, # "Fileupload": [ # { "IPK": "BladiBlupp.Zip", # "MD5": "01234567890123456789012345678901"} # ], # "Parameter": { # "Location": "An der Bahn 11", # "Group": "G1", # "Zone": "Z1", # "Name": "Bruno", # "SecNumber": "0", # "LastAcc": "1", # "GPSLat": "49,6019", # "GPSLon": "12,1258" # } # } # # where the interesting part is contained in "FileUpload". # check_for_updates() { # ismas_response=$(cat send_to_ismas.txt; sleep 1) | nc localhost 7778) return 0 } backup_previous_version() { return 0 } fetch_updates() { return 0 } check_updates() { return 0 } revert_updates() { return 0 } lock_before_installing_updates() { return 0 } do_update_dry_run() { return 0 } do_update() { return 0 } fallback_to_previous_version() { return 0; } unlock_after_installing_updates() { return 0; } cleanup_previous_version() { return 0 } send_reboot_message_to_system_controller() { return 0 } ############################################################################### # # UPDATE CONTROLLER # ############################################################################### UpdateController() { local trigger_reboot=false local check_apism_count=0 local try_update_count=0 local try_lock_count=0 local try_unlock_count=0 local trigger_timeout=-1 # read config parameters # read_config # By default (trigger_timeout==-1), UpdateController can only be triggered # from some external source to perform an update. while : do trigger=$(wait_for_trigger $trigger_timeout) echo "trigger=$trigger" if [ "$trigger" = "quit" ]; then $trigger_reboot = true elif [ "$trigger" != "update" ]; then continue fi if $trigger_reboot; then echo "CRITICAL send message to reboot the PSA" send_reboot_message_to_system_controller continue fi # Is APISM running, listening on the correct ports etc. ? while : do if ! check_for_apism; then var=$((var+1)) check_apism_count=$((check_apism_count+1)) if [[ "$check_apism_count" -eq 5 ]]; then trigger_reboot=true check_apism_count=0 echo "ERROR APISM not working" continue 2 fi echo "[$check_apism_count]: $(date +'%Y-%m-%d %T') check APISM" sleep 60s else # APISM up and working check_apism_count=0 break fi done echo "$(date +'%Y-%m-%d %T') checking for updates..." exit 1 # Are there new updates available ? if ! check_for_updates; then echo "DEBUG no updates available" continue fi echo "$(date +'%Y-%m-%d %T') fetching updates..." exit 1 # Fetch new updates (using git) while : do if ! fetch_updates; then try_updates_count=$((try_updates_count+1)) if [[ "$try_updates_count" -eq 5 ]]; then trigger_reboot=true echo "ERROR fetching updates" continue 2 fi sleep 60s else # Fetched updates successfully try_updates_count=0 break fi done # Check the updates for: # * correct MD5 # * compatibility with PSA # ... if ! check_updates; then echo "ERROR check_updates" revert_updates trigger_reboot=true continue fi # perform a dry-run and check if everything might work as expected. if ! do_update_dry_run; then echo "ERROR do_update_dry_run" revert_updates trigger_reboot=true continue fi # Backup before any updates in case some previous test was wrong if ! backup_previous_version; then echo "ERROR backup_previous_version" revert_updates trigger_reboot=true continue fi # Lock the PSA so all other tasks on the PSA are in sync with the update while : do if ! lock_before_installing_updates; then try_lock_count=$((try_lock_count+1)) if [[ "$try_lock_count" -eq 5 ]]; then revert_updates fallback_to_previous_version trigger_reboot=true echo "ERROR locking PSA" continue 2 fi sleep 60s else # Locked PSA successfully try_lock_count=0 break fi done # Actually do the update if ! do_update; then echo "ERROR do_update" revert_updates fallback_to_previous_version trigger_reboot=true continue fi while : do # If all went well, the PSA can return to normal operation if ! unlock_after_installing_updates; then try_unlock_count=$((try_unlock_count+1)) if [[ "$try_unlock_count" -eq 5 ]]; then revert_updates fallback_to_previous_version trigger_reboot=true echo "ERROR unlocking PSA" continue 2 fi sleep 60s else # Unlocked PSA successfully try_unlock_count=0 break fi done # Cleanup. if ! cleanup_previous_version; then echo "ERROR cleanup_previous_version" fi done } ############################################################################### if [ $# -ne 1 ] ; then echo "Usage: $0 filename" exit 1 else if read_config "$1" ; then init_fifo UpdateController fi fi