Compare commits
14 Commits
c032d5d528
...
40e8786391
Author | SHA1 | Date | |
---|---|---|---|
40e8786391 | |||
3586951772 | |||
71bc436a8c | |||
c1938c5b53 | |||
bcc503d59c | |||
c1eca2b7bf | |||
35600ec429 | |||
a9003c5073 | |||
89ef5c69b6 | |||
086a2c1585 | |||
fd40ba31a1 | |||
fa41ed36ab | |||
b1d22acdd6 | |||
8763eccab3 |
@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"fifo_dir" : "/tmp",
|
|
||||||
"fifo" : "update_controller_fifo",
|
|
||||||
"workspace" : "workspace",
|
|
||||||
"GIT_SSL_NO_VERIFY" : true,
|
"GIT_SSL_NO_VERIFY" : true,
|
||||||
|
"working_directory" : ".",
|
||||||
|
"workspace_dir" : "workspace",
|
||||||
|
"customer_location" : "szeged",
|
||||||
"customer_id" : "281",
|
"customer_id" : "281",
|
||||||
"zone_group" : "1",
|
"zone_group" : "1",
|
||||||
"zone" : "1",
|
"zone" : "1",
|
||||||
"customer_location" : "szeged",
|
|
||||||
"repository_path" : "https://git.mimbach49.de/GerhardHoffmann"
|
"repository_path" : "https://git.mimbach49.de/GerhardHoffmann"
|
||||||
}
|
}
|
||||||
|
@ -1,396 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -x
|
|
||||||
|
|
||||||
fifo=""
|
|
||||||
customer_id=""
|
|
||||||
customer_repository=""
|
|
||||||
customer_location=""
|
|
||||||
customer_base_dir=""
|
|
||||||
|
|
||||||
source ./log_helpers.sh
|
|
||||||
source ./update_helpers.sh
|
|
||||||
source ./git_helpers.sh
|
|
||||||
source ./opkg_helpers.sh
|
|
||||||
|
|
||||||
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() {
|
|
||||||
local func="${FUNCNAME[0]}"
|
|
||||||
|
|
||||||
# check fifo settings
|
|
||||||
fifo_dir=$(cat "$1" | jq -r .fifo_dir)
|
|
||||||
if [ -z "$fifo_dir" ]; then
|
|
||||||
log_fatal "$func: fifo_dir not set in $1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fifo=$(cat "$1" | jq -r .fifo)
|
|
||||||
if [ -z "$fifo" ]; then
|
|
||||||
log_fatal "$func: fifo not set in $1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fifo="${fifo_dir}/$fifo"
|
|
||||||
log_debug "$func:${LINENO}: fifo is $fifo"
|
|
||||||
|
|
||||||
# check customer_id
|
|
||||||
customer_id="$(cat "$1" | jq -r .customer_id)"
|
|
||||||
if [ -z "$customer_id" ]; then
|
|
||||||
log_fatal "$func:${LINENO} customer_id not set in $1"
|
|
||||||
fi
|
|
||||||
customer_id="customer_$customer_id"
|
|
||||||
log_info "$func:${LINENO}: customer-id is $customer_id"
|
|
||||||
|
|
||||||
# check customer_repository
|
|
||||||
repository_path="$(cat "$1" | jq -r .repository_path)"
|
|
||||||
if [ -z "$repository_path" ]; then
|
|
||||||
log_fatal "$func:${LINENO}: repository path not set in $1"
|
|
||||||
fi
|
|
||||||
repository_path="${repository_path}/${customer_id}.git"
|
|
||||||
log_info "$func:${LINENO}: repository path is $repository_path"
|
|
||||||
|
|
||||||
# check zone_group
|
|
||||||
local zone_group="$(cat "$1" | jq -r .zone_group)"
|
|
||||||
if [ -z "$zone_group" ]; then
|
|
||||||
log_fatal "$func:${LINENO}: zone_group not set in $1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# check zone
|
|
||||||
local zone="$(cat "$1" | jq -r .zone)"
|
|
||||||
if [ -z "$zone" ]; then
|
|
||||||
log_fatal "$func:${LINENO}: zone not set in $1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# check customer_location
|
|
||||||
local customer_location="$(cat "$1" | jq -r .customer_location)"
|
|
||||||
if [ -z "$customer_location" ]; then
|
|
||||||
log_fatal "$func:${LINENO}: customer_location not set in $1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
customer_base_dir="$PWD/workspace/${customer_id}/${customer_location}"
|
|
||||||
customer_base_dir="${customer_base_dir}/${zone_group}/${zone}"
|
|
||||||
|
|
||||||
log_info "$func:${LINENO}: customer-base-dir is $customer_base_dir"
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_trigger() {
|
|
||||||
local func="${FUNCNAME[0]}"
|
|
||||||
if [[ "$1" -eq -1 ]]; then
|
|
||||||
# wait for external impulse
|
|
||||||
log_debug "$func:${LINENO}: waiting on $fifo"
|
|
||||||
if read line <$fifo; then
|
|
||||||
if [ "$line" = "quit" ] || [ "$line" = "update" ]; then
|
|
||||||
log_debug "$func:${LINENO}: received=$line"
|
|
||||||
printf "%s\n" $line
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
sleep $1
|
|
||||||
log_debug "$func:${LINENO}: 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)
|
|
||||||
if ! pull_customer_repository customer_281; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
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
|
|
||||||
local func="${FUNCNAME[0]}"
|
|
||||||
|
|
||||||
# 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
|
|
||||||
log_crit "$func:${LINENO}: 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
|
|
||||||
log_crit "$func:${LINENO}: ERROR APISM not working"
|
|
||||||
continue 2
|
|
||||||
fi
|
|
||||||
log_debug "$func:${LINENO}: [$check_apism_count]: check APISM"
|
|
||||||
sleep 60s
|
|
||||||
else
|
|
||||||
# APISM up and working
|
|
||||||
check_apism_count=0
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
log_debug "$func:${LINENO}: checking for updates..."
|
|
||||||
# exit 1
|
|
||||||
|
|
||||||
# Are there new updates available ?
|
|
||||||
if ! check_for_updates; then
|
|
||||||
log_info "$func:${LINENO}: DEBUG no updates available"
|
|
||||||
extract_changed_files
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_debug "$func:${LINENO}: 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
|
|
@ -1,17 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# set -x
|
# set -x
|
||||||
|
|
||||||
source ./log_helpers.sh
|
# if [ ${git_helpers_sourced:-1} = "1" ]; then
|
||||||
|
# readonly git_helpers_sourced=${BASH_SOURCE[0]}
|
||||||
|
#else
|
||||||
|
# return 0
|
||||||
|
#fi
|
||||||
|
|
||||||
GIT_SSL_NO_VERIFY=true
|
|
||||||
|
# source ./log_helpers
|
||||||
|
|
||||||
|
readonly GIT_SSL_NO_VERIFY=true
|
||||||
|
readonly repository_already_up_to_date=2
|
||||||
|
|
||||||
#
|
#
|
||||||
exec_git_command () {
|
exec_git_command () {
|
||||||
local func="${FUNCNAME[0]}"
|
local func="${FUNCNAME[0]}"
|
||||||
|
|
||||||
log_debug "$func:${LINENO} exec-ing $1"
|
log_debug "$func:${LINENO} exec-ing [$*]"
|
||||||
|
|
||||||
exec {fd}< <($1)
|
exec {fd}< <($@)
|
||||||
local ps_pid=$! # remember pid of process substitution
|
local ps_pid=$! # remember pid of process substitution
|
||||||
|
|
||||||
local git_result=""
|
local git_result=""
|
||||||
@ -35,15 +43,13 @@ latest_commit () {
|
|||||||
local c=$(git reflog | grep "HEAD@{0}" | cut -d" " -f1)
|
local c=$(git reflog | grep "HEAD@{0}" | cut -d" " -f1)
|
||||||
if ! [ -z "$c" ]; then
|
if ! [ -z "$c" ]; then
|
||||||
if grep -qE "^[[:xdigit:]]{6,}$" <<< $c; then
|
if grep -qE "^[[:xdigit:]]{6,}$" <<< $c; then
|
||||||
log_debug "$func: commit -> $c"
|
log_debug "$func:${LINENO} commit -> $c"
|
||||||
printf "%s\n" $c
|
printf "%s\n" $c
|
||||||
else
|
else
|
||||||
log_crit "$func: wrong format for commit c=$c"
|
log_crit "$func:${LINENO} wrong format for commit c=$c"
|
||||||
printf ""
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
log_crit "$func: 'git reflog' result empty"
|
log_crit "$func:${LINENO} 'git reflog' result empty"
|
||||||
printf ""
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,10 +85,22 @@ clone_customer_repository () {
|
|||||||
# check if the directory is empty. If so, clone the
|
# check if the directory is empty. If so, clone the
|
||||||
# customer repository
|
# customer repository
|
||||||
if ! find ./workspace -mindepth 1 -maxdepth 1 | read; then
|
if ! find ./workspace -mindepth 1 -maxdepth 1 | read; then
|
||||||
log_debug "$func: cloning ${1} ..."
|
log_debug "$func:${LINENO} cloning ${1} ..."
|
||||||
( cd ./workspace && git clone "$1" ; )
|
if { cd ./workspace ; }; then
|
||||||
if [ $? -eq 0 ]; then
|
$(exec_git_command git clone "$1")
|
||||||
log_debug "$func: cloning ${1} done"
|
if [ $? -eq 0 ]; then
|
||||||
|
log_debug "$func:${LINENO} cloning ${1} done"
|
||||||
|
cd - ; return 0
|
||||||
|
fi
|
||||||
|
cd -
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# the directory is not empty, so we assume the customer-repository
|
||||||
|
# has been cloned alread
|
||||||
|
if ! [[ -d ./workspace/$customer_id ]]; then
|
||||||
|
local m="wrong repository: $(ls -d './workspace/*')"
|
||||||
|
log_fatal "$func:${LINENO} $m"
|
||||||
|
else
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -104,7 +122,7 @@ cd_customer_repository () {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! cd $repository_dir; then
|
if ! { cd $repository_dir; } ; then
|
||||||
log_crit "$func:${LINENO}: cannot change to $repository_dir!"
|
log_crit "$func:${LINENO}: cannot change to $repository_dir!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -136,29 +154,22 @@ pull_customer_repository () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
log_debug "$func:${LINENO}: commit_before_pull=$commit_before_pull"
|
log_debug "$func:${LINENO}: commit_before_pull=$commit_before_pull"
|
||||||
|
|
||||||
exec {fd}< <(git pull)
|
local git_result=$(exec_git_command 'git pull')
|
||||||
local ps_pid=$! # remember pid of process substitution
|
|
||||||
|
|
||||||
local git_result=""
|
|
||||||
while read t <&$fd; do
|
|
||||||
if ! [ -z "$t" ]; then
|
|
||||||
git_result="${git_result}$t"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exec {fd}>&- # close fd (i.e. process substitution)
|
|
||||||
wait $ps_pid # wait for the subshell to finish
|
|
||||||
|
|
||||||
if [ -z "$git_result" ]; then
|
if [ -z "$git_result" ]; then
|
||||||
log_warn "$func:${LINENO}: git result empty" ; cd_home;
|
log_warn "$func:${LINENO}: git result empty" ; cd_home;
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# see 'man -Pless\ +/parameter/pattern/string/bash'
|
||||||
|
git_result=${git_result//[$'\r\n\t']/ }
|
||||||
|
|
||||||
log_debug "$func:${LINENO} git-pull-result=${git_result}"
|
log_debug "$func:${LINENO} git-pull-result=${git_result}"
|
||||||
|
|
||||||
if [ "$git_result" = "Already up to date." ]; then
|
if grep -qE "^Already\s+\up\s+\to\s+date.*$" <<< $git_result; then
|
||||||
log_warn "$func:${LINENO}: $PWD already up to date."
|
log_warn "$func:${LINENO}: repository $PWD already up to date."
|
||||||
|
read $1 <<< 'yes'
|
||||||
cd_home ; return 1
|
cd_home ; return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -166,7 +177,7 @@ pull_customer_repository () {
|
|||||||
if [ -z $commit_after_pull ]; then
|
if [ -z $commit_after_pull ]; then
|
||||||
cd_home ; return 1
|
cd_home ; return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log_debug "$func:${LINENO}: commit_after_pull=$commit_after_pull"
|
log_debug "$func:${LINENO}: commit_after_pull=$commit_after_pull"
|
||||||
|
|
||||||
# Note: # 'git pull' is a 'git fetch' followed by a 'git merge'.
|
# Note: # 'git pull' is a 'git fetch' followed by a 'git merge'.
|
||||||
@ -228,14 +239,26 @@ pull_customer_repository () {
|
|||||||
cd_home ; return 1
|
cd_home ; return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
cd_home ; return 0
|
||||||
}
|
}
|
||||||
# pull_customer_repository customer_281
|
# pull_customer_repository customer_281
|
||||||
|
|
||||||
changed_files () {
|
changed_file_names () {
|
||||||
local func="${FUNCNAME[0]}"
|
local func="${FUNCNAME[0]}"
|
||||||
if cd_customer_repository ; then
|
if cd_customer_repository ; then
|
||||||
printf "%s\n" $(exec_git_command 'git diff --stat master@{1} master')
|
local git_res=$(exec_git_command 'git diff --stat master@{1} master')
|
||||||
cd_home
|
git_res=${git_res//[$'\r\n\t']/ }
|
||||||
|
log_debug "$func:${LINENO}: git_res=$git_res"
|
||||||
|
local file_names=""
|
||||||
|
for f in 'update.conf' 'opkg_commands' ; do
|
||||||
|
if grep -qE ".*${f}.*?" <<< $git_res; then
|
||||||
|
file_names="$f $file_names"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
cd_home ; printf "$file_names"
|
||||||
|
else
|
||||||
|
log_crit "$func:${LINENO}: cannot cd to $customer_repository "\
|
||||||
|
"while in $PWD"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
@ -1,12 +1,24 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# set -x
|
# set -x
|
||||||
|
|
||||||
|
#if [ ${log_helpers_sourced:-1} = "1" ]; then
|
||||||
|
# readonly log_helpers_sourced=${BASH_SOURCE[0]}
|
||||||
|
#else
|
||||||
|
# return 0
|
||||||
|
#fi
|
||||||
|
|
||||||
|
readonly log_file=/var/log/update_controller.log
|
||||||
|
if ! [ -f "$log_file" ]; then
|
||||||
|
touch $log_file
|
||||||
|
fi
|
||||||
|
|
||||||
readonly DEBUG=0
|
readonly DEBUG=0
|
||||||
readonly INFO=1
|
readonly INFO=1
|
||||||
readonly WARN=2
|
readonly WARN=2
|
||||||
readonly CRIT=3
|
readonly CRIT=3
|
||||||
readonly FATAL=4
|
readonly ERROR=4
|
||||||
readonly MAX_DEBUG_LEVEL=5
|
readonly FATAL=5
|
||||||
|
readonly MAX_DEBUG_LEVEL=6
|
||||||
|
|
||||||
log_level=0
|
log_level=0
|
||||||
|
|
||||||
@ -21,17 +33,12 @@ dbg_level () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log() {
|
log() {
|
||||||
local log_file=/var/log/update_controller.log
|
if [[ $(("$(wc -l < $log_file)")) -ge $((100000)) ]]; then
|
||||||
if [ -f "$log_file" ]; then
|
|
||||||
touch $log_file
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$(wc -l < $log_file)" > "100000" ]]; then
|
|
||||||
# remove first line
|
# remove first line
|
||||||
sed -e 1d -i $log_file
|
sed -e 1d -i $log_file
|
||||||
fi
|
fi
|
||||||
local msg="$(date +'%Y-%m-%d_%T'): $*"
|
local msg="$(date +'%Y-%m-%d_%T'): $*"
|
||||||
printf "$msg\n" >&2
|
printf "log:$msg\n" >&2
|
||||||
printf "$msg\n" >> $log_file
|
printf "$msg\n" >> $log_file
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +66,12 @@ log_crit() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
if [ $log_level -le $ERROR ]; then
|
||||||
|
log "ERROR $*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
log_fatal() {
|
log_fatal() {
|
||||||
if [ $log_level -le $FATAL ]; then
|
if [ $log_level -le $FATAL ]; then
|
||||||
log "FATAL $*"
|
log "FATAL $*"
|
283
opkg.sh
283
opkg.sh
@ -1,283 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# set -x
|
|
||||||
|
|
||||||
compute_md5 () {
|
|
||||||
execdownload_opkg {fd}< <(md5sum "$1") # open fd readable for P.S.
|
|
||||||
cs_pid=$! # remember pid of P.S.
|
|
||||||
md5=""
|
|
||||||
while read t <&$fd; do
|
|
||||||
if ! [ -z "$t" ]; then
|
|
||||||
t=($t) # md5sum returns two values:
|
|
||||||
# the hash plus the filename
|
|
||||||
md5="${md5}$t"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exec {fd}>&- # close fd (i.e. process substitution)
|
|
||||||
wait $cs_pid # wait for the subshell to finish
|
|
||||||
echo $md5
|
|
||||||
}
|
|
||||||
|
|
||||||
md5_for_ini_files() {
|
|
||||||
ini_directory="$1"
|
|
||||||
ini_files=("ISMASMgr.ini" "sysconfig.ini" "SystemControl.ini")
|
|
||||||
|
|
||||||
local data="\"ini\": {"$'\n'
|
|
||||||
|
|
||||||
for f in "${ini_files[@]}"; do
|
|
||||||
ini_file=${ini_directory}/$f
|
|
||||||
md5=`compute_md5 $ini_file`
|
|
||||||
data+="\"$ini_file\":\"$md5\","
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ "$data" =~ ^.*,$ ]]; then
|
|
||||||
data=${data%?}
|
|
||||||
fi
|
|
||||||
|
|
||||||
data+="},"
|
|
||||||
echo $data
|
|
||||||
}
|
|
||||||
|
|
||||||
md5_for_conf_files() {
|
|
||||||
conf_directory="$1"
|
|
||||||
conf_files=("emp.conf" "printer.conf" "device.conf")
|
|
||||||
|
|
||||||
local data="\"conf\": {"$'\n'
|
|
||||||
|
|
||||||
for f in "${conf_files[@]}"; do
|
|
||||||
conf_file=${conf_directory}/$f
|
|
||||||
md5=`compute_md5 $conf_file`
|
|
||||||
data+="\"$conf_file\":\"$md5\","
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ "$data" =~ ^.*,$ ]]; then
|
|
||||||
data=${data%?}
|
|
||||||
fi
|
|
||||||
|
|
||||||
data+="},"
|
|
||||||
echo $data
|
|
||||||
}
|
|
||||||
|
|
||||||
write_config() {
|
|
||||||
local path="$1"
|
|
||||||
if [ "${path: -1}" == "/" ]; then # remove trailing '/'
|
|
||||||
path=${path%?}
|
|
||||||
fi
|
|
||||||
|
|
||||||
local data="{ "$'\n'
|
|
||||||
data+=`md5_for_ini_files "$path/opt/app/sysconfig"`
|
|
||||||
data+=`md5_for_conf_files "$path/etc/psa_config"`
|
|
||||||
data+="
|
|
||||||
\"opkg\" : {"
|
|
||||||
local cnt=0
|
|
||||||
for package_name in $(opkg list-installed); # list names of installed packages
|
|
||||||
do
|
|
||||||
if ! grep -q "^[a-zA-Z]" <<< $package_name; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$package_name" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
cnt=$((cnt+1))
|
|
||||||
|
|
||||||
printf "%3d:%s\n" "$cnt" "$package_name"
|
|
||||||
|
|
||||||
# Format of package info:
|
|
||||||
#
|
|
||||||
# Package: openssh-scp
|
|
||||||
# Version: 7.8p1+git-r0
|
|
||||||
# Depends: libc6 (>= 2.28), update-alternatives-opkg
|
|
||||||
# Status: install ok installed
|
|
||||||
# Section: console/network
|
|
||||||
# Architecture: cortexa9t2hf-neon
|
|
||||||
# Maintainer: Poky <poky@yoctoproject.org>
|
|
||||||
# MD5Sum: dfffcbb088cd5f180be5e9ee2ad030fe
|
|
||||||
# Size: 32700
|
|
||||||
# Filename: openssh-scp_7.8p1+git-r0_cortexa9t2hf-neon.ipk
|
|
||||||
# Source: openssh_7.8p1+git.bb
|
|
||||||
# Description: A suite of security-related network....
|
|
||||||
# Installed-Size: 58920
|
|
||||||
# Installed-Time: 1654699615
|
|
||||||
#
|
|
||||||
# process substitution (P.S):
|
|
||||||
# run 'opkg info' synchronously to parent script
|
|
||||||
|
|
||||||
exec {fd}< <(opkg info "$package_name") # open fd readable for P.S.
|
|
||||||
cs_pid=$! # remember pid of P.S.
|
|
||||||
|
|
||||||
while read package_info_line <&$fd; do
|
|
||||||
if [[ $package_info_line == Package* ]]; then
|
|
||||||
package=(${package_info_line// / })
|
|
||||||
package="\"${package[1]}\": {"
|
|
||||||
elif [[ $package_info_line == MD5Sum* ]]; then
|
|
||||||
md5sum=(${package_info_line// / })
|
|
||||||
md5sum="\"${md5sum[0]%?}\": \"${md5sum[1]}\","
|
|
||||||
elif [[ $package_info_line == Filename* ]]; then
|
|
||||||
filename=(${package_info_line// / })
|
|
||||||
filename="\"${filename[0]%?}\": \"${filename[1]}\","
|
|
||||||
elif [[ $package_info_line == Installed-Time* ]]; then
|
|
||||||
installed_time=(${package_info_line// / })
|
|
||||||
installed_time="\"${installed_time[0]%?}\": \"${installed_time[1]}\"
|
|
||||||
},"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exec {fd}>&- # close fd (i.e. process substitution)
|
|
||||||
wait $cs_pid # wait for the subshell to finish
|
|
||||||
|
|
||||||
# use 8 spaces
|
|
||||||
data="$data
|
|
||||||
$package
|
|
||||||
$md5sum
|
|
||||||
$filename
|
|
||||||
$installed_time"
|
|
||||||
|
|
||||||
# break
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ "$data" =~ ^.*,$ ]]; then
|
|
||||||
data=${data%?}
|
|
||||||
fi
|
|
||||||
|
|
||||||
data="$data
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
echo "$data" > "${path}/$2"
|
|
||||||
# echo $(cat "/tmp/test.txt" | jq -C --indent 4 '.') > /tmp/test2.txt
|
|
||||||
}
|
|
||||||
# write_config "/home/root/szeged/customer_281/szeged/1/1/" "test.txt"
|
|
||||||
|
|
||||||
# Download opkg-package. After the download, extract data.tar.gz to
|
|
||||||
# access e.g. atbqt.
|
|
||||||
download_opkg_package () {
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
atbqt) # hier weitere packete eintragen
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
printf "ERROR $1 has wrong format\n" >&2
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exec {fdd}< <(opkg --download-only download "$1") # open fd readable for P.S.
|
|
||||||
cs_pid=$! # remember pid of P.S.
|
|
||||||
|
|
||||||
opkg_result=""
|
|
||||||
while read result <&$fdd; do
|
|
||||||
if ! [ -z "$result" ]; then
|
|
||||||
opkg_result+="$result"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exec {fdd}>&- # close fd (i.e. process substitution)
|
|
||||||
wait $cs_pid # wait for the subshell to finish
|
|
||||||
|
|
||||||
if [ -z "$opkg_result" ]; then
|
|
||||||
printf "ERROR empty opkg_result\n" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -qF "$1" <<< $opkg_result; then
|
|
||||||
printf "ERROR opkg_result [$opkg_result] does not contain $1\n" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -qF "$2" <<< $opkg_result; then
|
|
||||||
printf "ERROR opkg_result [$opkg_result] does not contain $2\n" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# printf "%s\n" $opkg_result
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
# download_opkg_package "atbqt" "atbqt_1.0.0-r1_cortexa9t2hf-neon.ipk"
|
|
||||||
|
|
||||||
ar_extract_opkg_package_data () {
|
|
||||||
return 0
|
|
||||||
|
|
||||||
cp $1 "/tmp"
|
|
||||||
# mv $1 "/tmp"
|
|
||||||
cd /tmp
|
|
||||||
# ar -x $1
|
|
||||||
#if [ $? ne 0 ]; then
|
|
||||||
data_file="data.tar.xz"
|
|
||||||
if ! [ -f "$data_file" ]; then
|
|
||||||
printf "ERROR %s does not exist\n" "$data_file" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd -
|
|
||||||
return 0
|
|
||||||
|
|
||||||
tar -qxvf $data_file
|
|
||||||
|
|
||||||
|
|
||||||
echo $pwd
|
|
||||||
}
|
|
||||||
# ar_extract_opkg_package_data "atbqt_1.0.0-r1_cortexa9t2hf-neon.ipk"
|
|
||||||
|
|
||||||
tar_extract_opkg_package_data () {
|
|
||||||
exec {ftar}< <(tar -xvf "$2" -C "$1") # use process substitution
|
|
||||||
cs_pid=$!
|
|
||||||
exec {ftar}>&-
|
|
||||||
wait $cs_pid
|
|
||||||
|
|
||||||
binary="$1/$3"
|
|
||||||
if ! [ -f "$binary" ]; then
|
|
||||||
printf "ERROR %s does not exist\n" "$binary" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
# tar_extract_opkg_package_data "/tmp" "data.tar.xz" "opt/app/ATBAPP/ATBQT"
|
|
||||||
|
|
||||||
read_atbqt_version () {
|
|
||||||
version=$(/tmp/opt/app/ATBAPP/ATBQT -v)
|
|
||||||
version=(${version// / })
|
|
||||||
|
|
||||||
# ATB APP: Version: 20221220_1038_00318q git describe: 4.5.2-65-gf1799aa3_00318/Nexobility_dev
|
|
||||||
# printf "%s\n" "${version[@]}"
|
|
||||||
|
|
||||||
if [ ${#version[@]} -lt 7 ]; then
|
|
||||||
printf "ERROR %s has wrong format\n" "${version[@]}" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "${version[3]} ${version[6]}"
|
|
||||||
}
|
|
||||||
# xxx=`read_atbqt_version`
|
|
||||||
# echo $xxx
|
|
||||||
# set -x
|
|
||||||
check_atbqt_version () {
|
|
||||||
if ! `download_opkg_package "$1" "$2"`; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! `ar_extract_opkg_package_data "$2"`; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! `tar_extract_opkg_package_data "/tmp" "data.tar.xz" "opt/app/ATBAPP/ATBQT"`; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
version=`read_atbqt_version`
|
|
||||||
version=(${version// / })
|
|
||||||
|
|
||||||
if [ "${version[0]}" = "$3" ] && [ "${version[1]}" = "$4" ]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
# check_atbqt_version "atbqt" \
|
|
||||||
# "atbqt_1.0.0-r1_cortexa9t2hf-neon.ipk" \
|
|
||||||
# "20221220_1038_00318q" \
|
|
||||||
# "4.5.2-65-gf1799aa3_00318/Nexobility_dev"
|
|
||||||
|
|
64
read_config
Executable file
64
read_config
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# set -x
|
||||||
|
|
||||||
|
#if [ ${read_config_sourced:-1} = "1" ]; then
|
||||||
|
# readonly read_config_sourced=${BASH_SOURCE[0]}
|
||||||
|
#else
|
||||||
|
# return 0
|
||||||
|
#fi
|
||||||
|
|
||||||
|
# source ./log_helpers
|
||||||
|
|
||||||
|
# read config file (JSON syntax)
|
||||||
|
#
|
||||||
|
read_config() {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
|
||||||
|
# check customer_id
|
||||||
|
__customer_id="$(cat "$1" | jq -r .customer_id)"
|
||||||
|
if [ -z "$__customer_id" ]; then
|
||||||
|
log_fatal "$func:${LINENO} customer_id not set in $1"
|
||||||
|
fi
|
||||||
|
readonly customer_id="customer_${__customer_id}"
|
||||||
|
log_info "$func:${LINENO}: customer-id is $customer_id"
|
||||||
|
|
||||||
|
# check customer_repository
|
||||||
|
__repository_path="$(cat "$1" | jq -r .repository_path)"
|
||||||
|
if [ -z "$__repository_path" ]; then
|
||||||
|
log_fatal "$func:${LINENO}: repository path not set in $1"
|
||||||
|
fi
|
||||||
|
readonly repository_path="${__repository_path}/${customer_id}.git"
|
||||||
|
log_info "$func:${LINENO}: repository path is $repository_path"
|
||||||
|
|
||||||
|
# check zone_group
|
||||||
|
local zone_group="$(cat "$1" | jq -r .zone_group)"
|
||||||
|
if [ -z "$zone_group" ]; then
|
||||||
|
log_fatal "$func:${LINENO}: zone_group not set in $1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check zone
|
||||||
|
local zone="$(cat "$1" | jq -r .zone)"
|
||||||
|
if [ -z "$zone" ]; then
|
||||||
|
log_fatal "$func:${LINENO}: zone not set in $1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check customer_location
|
||||||
|
local customer_location="$(cat "$1" | jq -r .customer_location)"
|
||||||
|
if [ -z "$customer_location" ]; then
|
||||||
|
log_fatal "$func:${LINENO}: customer_location not set in $1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local workspace="$(cat "$1" | jq -r .workspace_dir)"
|
||||||
|
__customer_base_dir="$PWD/${workspace}/${customer_id}/${customer_location}"
|
||||||
|
|
||||||
|
readonly customer_base_dir="${__customer_base_dir}/${zone_group}/${zone}"
|
||||||
|
log_info "$func:${LINENO}: customer-base-dir is $customer_base_dir"
|
||||||
|
|
||||||
|
readonly opkg_cmds_file="${customer_base_dir}/etc/psa_update/opkg_commands"
|
||||||
|
log_info "$func:${LINENO}: opkg_cmds_file is $opkg_cmds_file"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# read_config UpdateController.conf
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# set -x
|
# set -x
|
||||||
|
|
||||||
source ./log_helpers.sh
|
source ./log_helpers
|
||||||
source ./git_helpers.sh
|
source ./git_helpers
|
||||||
|
|
||||||
extract_changed_files () {
|
extract_changed_files () {
|
||||||
local func="${FUNCNAME[0]}"
|
local func="${FUNCNAME[0]}"
|
||||||
|
163
update_psa
Executable file
163
update_psa
Executable file
@ -0,0 +1,163 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# set -x
|
||||||
|
|
||||||
|
source ./log_helpers
|
||||||
|
source ./git_helpers
|
||||||
|
|
||||||
|
# source ./update_helpers.sh
|
||||||
|
# source ./opkg_helpers.sh
|
||||||
|
source ./update_psa_helpers
|
||||||
|
|
||||||
|
source ./read_config
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# update_psa
|
||||||
|
#
|
||||||
|
# Implementing the UpdateController (see below). UpdateController is waiting
|
||||||
|
# for an external trigger by the DeviceController (DC). The trigger is sent via
|
||||||
|
# an UNIX-pipe (=fifo). When DC triggers UpdateController, it has to check if
|
||||||
|
# an update is possible, i.e. is has to lock the PSA for the update procedure.
|
||||||
|
# UpdateController will send back the update-result to DeviceController
|
||||||
|
# which unlocks the PSA to return to nomal operation.
|
||||||
|
#
|
||||||
|
# If UpdateController has been triggered, it checks out a predefined git-
|
||||||
|
# repository. As a sanity check it makes sure that there are some changes in
|
||||||
|
# the repository. In case there are no changes, it issues an error message
|
||||||
|
# to DC and returns to its wait-state.
|
||||||
|
#
|
||||||
|
# Otherwise it checks if the changed files are correct (using md5) and if
|
||||||
|
# the new files are valid for the PSA. If there is some problem, it issues an
|
||||||
|
# error message to DC, reverts the git-repository to its previous state and
|
||||||
|
# returns to its wait-state.
|
||||||
|
#
|
||||||
|
# Otherwise it makes a backup of the current state of the PSA, and if there
|
||||||
|
# are opkg-packages to install it runs a dry installation process using opkg.
|
||||||
|
# In case of error, it issues an error message to DC, deletes the backup,
|
||||||
|
# reverts # the git-repository to its previous state and returns to its
|
||||||
|
# wait-state.
|
||||||
|
#
|
||||||
|
# Otherwise, it copies all new files to their target locations and in case
|
||||||
|
# of opkg-packages, it installs the packages.
|
||||||
|
#
|
||||||
|
# In case of error it restores the previous state using the backup and
|
||||||
|
# reinstalls the previous opkg-package(s). It issues an error message to
|
||||||
|
# DC and returns to its wait-state.
|
||||||
|
#
|
||||||
|
# Otherwise the update went well, and it does some cleanup, sends a success
|
||||||
|
# message to DC and returns to its wait-state.
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# UPDATE PROCEDURE
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
update() {
|
||||||
|
local try_update_count=0
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
|
||||||
|
# read config parameters
|
||||||
|
# read_config
|
||||||
|
|
||||||
|
log_debug "$func:${LINENO}: fetch/merge updates..."
|
||||||
|
|
||||||
|
# Fetch new updates (using git)
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
local repository_is_already_up_to_date=""
|
||||||
|
if ! fetch_customer_updates repository_is_already_up_to_date; then
|
||||||
|
if [ "$repository_is_already_up_to_date" = "yes" ]; then
|
||||||
|
log_error "$func:${LINENO}: $customer_id is up-to-date"\
|
||||||
|
"-> no files to update -> no psa update"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
try_updates_count=$((try_updates_count+1))
|
||||||
|
if [[ "$try_updates_count" -eq 5 ]]; then
|
||||||
|
log_error "$func:${LINENO}: fetch/merging failed" ; exit 1
|
||||||
|
fi
|
||||||
|
sleep 60s
|
||||||
|
else
|
||||||
|
# Fetched updates successfully
|
||||||
|
try_updates_count=0
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Backup before any updates in case some previous test was wrong
|
||||||
|
if ! backup_previous_version; then
|
||||||
|
log_error "$func:${LINENO}: backup failed"
|
||||||
|
revert_customer_repository ; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
files=$(changed_file_names)
|
||||||
|
if ! check_md5_for_changed_customer_files $files ; then
|
||||||
|
log_error "$func:${LINENO}: new customer files wrong"
|
||||||
|
revert_customer_repository ; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -qE ".*opkg_commands.*?" <<< $files; then
|
||||||
|
# read opkg_cmds: each line respresents an opkg-command
|
||||||
|
readarray opkg_commands < <(cat $opkg_cmds_file)
|
||||||
|
for opkg_command in "${opkg_commands[@]}"; do
|
||||||
|
if grep -qE "^\s*[#]+.*?$" <<< $opkg_command; then
|
||||||
|
continue # found comment line
|
||||||
|
fi
|
||||||
|
|
||||||
|
# FIXME: sollte nicht gebraucht werden
|
||||||
|
opkg_command=${opkg_command//[$'\r\n\t']/ }
|
||||||
|
local package=$(printf '%s' "$opkg_command" | awk '{ print $NF }')
|
||||||
|
|
||||||
|
local opkg_output=()
|
||||||
|
if ! exec_opkg_info "$package" opkg_output; then
|
||||||
|
log_error "$func:${LINENO}: opkg --noaction $opkg_command failed"
|
||||||
|
revert_customer_repository ; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# FIXME: sollte am anfang so gesetzt werden
|
||||||
|
SAVEIFS=$IFS
|
||||||
|
IFS=$'\n'
|
||||||
|
if ! check_md5_for_opkg_packages opkg_output; then
|
||||||
|
log_error "$func:${LINENO}: wrong md5sum for some opkg packages"
|
||||||
|
revert_customer_repository ; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=$SAVEIFS
|
||||||
|
|
||||||
|
# perform a dry-run and check if everything might work as expected.
|
||||||
|
|
||||||
|
# Actually execute the opkg command
|
||||||
|
if ! exec_opkg $opkg_command; then
|
||||||
|
log_error "$func:${LINENO}: do_update failed"
|
||||||
|
fallback_to_previous_version
|
||||||
|
revert_customer_repository ; exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
log_info "$func:${LINENO}: no opkg commnds to execute"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup.
|
||||||
|
if ! cleanup_previous_version; then
|
||||||
|
log_error "$func:${LINENO}: cleanup_previous_version failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "$func:${LINENO}: success"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
if [ $# -ne 1 ] ; then
|
||||||
|
echo "Usage: $0 filename"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
# if [ -z $IFS ]; then
|
||||||
|
# IFS=$'\n'
|
||||||
|
# fi
|
||||||
|
|
||||||
|
if read_config "$1" ; then
|
||||||
|
# set -x
|
||||||
|
if clone_customer_repository $repository_path ; then
|
||||||
|
update
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
157
update_psa_helpers
Normal file
157
update_psa_helpers
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# if [ ${git_helpers_sourced:-1} = "1" ]; then
|
||||||
|
# readonly git_helpers_sourced=${BASH_SOURCE[0]}
|
||||||
|
#else
|
||||||
|
# return 0
|
||||||
|
#fi
|
||||||
|
|
||||||
|
exec_opkg_command () {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
|
||||||
|
log_debug "$func:${LINENO} exec-ing [$*]"
|
||||||
|
|
||||||
|
exec {fd}< <($@)
|
||||||
|
local ps_pid=$! # remember pid of process substitution
|
||||||
|
|
||||||
|
local opkg_result=""
|
||||||
|
while read tmp <&$fd; do
|
||||||
|
if ! [ -z "$tmp" ]; then
|
||||||
|
opkg_result="${opkg_result}$tmp"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exec {fd}>&- # close fd (i.e. process substitution)
|
||||||
|
wait $ps_pid # wait for the subshell to finish
|
||||||
|
|
||||||
|
printf '%s' "$opkg_result"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch/merge updates from predefined repository using git.
|
||||||
|
#
|
||||||
|
fetch_customer_updates() {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
if ! pull_customer_repository $1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if the fetched/merged files have the correct md5 and are
|
||||||
|
# valid for the PSA.
|
||||||
|
#
|
||||||
|
check_md5_for_changed_customer_files () {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
#for file in ($1); do
|
||||||
|
# Check the updates for correct MD5
|
||||||
|
# log_error "$func:${LINENO}: new customer files wrong"
|
||||||
|
# revert_customer_repository ; exit 1
|
||||||
|
# fi
|
||||||
|
#done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
check_md5_for_opkg_packages () {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
local -n opkg_output_ref=$1
|
||||||
|
local package=""
|
||||||
|
local md5sum=""
|
||||||
|
local filename=""
|
||||||
|
for line in ${opkg_output_ref[@]}; do
|
||||||
|
if grep -qE "^\s*Package\s*:.*?$" <<< "$line"; then
|
||||||
|
package=${line#*:* }
|
||||||
|
printf 'package=%s\n' "$package"
|
||||||
|
elif grep -qE "^\s*MD5Sum\s*:.*?$" <<< "$line"; then
|
||||||
|
md5sum=${line#*:* }
|
||||||
|
printf 'md5sum=%s\n' "$md5sum"
|
||||||
|
elif grep -qE "^\s*Filename\s*:.*?$" <<< "$line"; then
|
||||||
|
filename=${line#*:* }
|
||||||
|
printf 'filename=%s\n' "$filename"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log_debug "$func:${LINENO}: $package | $md5sum | $filename"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# In case the new checked-out files are not correct, revert the git
|
||||||
|
# repository to its previous state.
|
||||||
|
#
|
||||||
|
revert_customer_repository() {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup before the update-process.
|
||||||
|
#
|
||||||
|
backup_previous_version () {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_opkg_info () {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
log_info "$func:${LINENO}: executing $opkg_command"
|
||||||
|
|
||||||
|
opkg_result=$(exec_opkg_command "opkg info $1")
|
||||||
|
|
||||||
|
# make sure the keywords start with '\n'
|
||||||
|
opkg_result=$(sed -E -e "s/(^.*)(Package)(.*$)/\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Version)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Depends)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Status)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Architecture)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Maintainer)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(MD5Sum)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Filename)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Source)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Description)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Installed-Size)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Section)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*[^-])(Size)(.*$)/\1\n\2\3/g"\
|
||||||
|
-e "s/(^.*)(Installed-Time)(.*$)/\1\n\2\3/g" <<< "$opkg_result")
|
||||||
|
|
||||||
|
local -n output_ref=$2
|
||||||
|
|
||||||
|
readarray -d $'\n' output_ref < <(printf '%s' "$opkg_result")
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
log_error "$func:${LINENO}: readarray finished with error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "$func:${LINENO}: ... done"
|
||||||
|
log_info "$func:${LINENO}: opkg_result=${output_ref[@]}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try to install new opkg-packages (in case the are some
|
||||||
|
# in the new git-checkout).
|
||||||
|
#
|
||||||
|
exec_opkg_no_action() {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
local opkg_command_no_action="opkg --noaction $1"
|
||||||
|
log_info "$func:${LINENO}: executing $opkg_command_no_action"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install the new packages using opkg.
|
||||||
|
#
|
||||||
|
exec_opkg () {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# In case there was some error, re-install the previous package(s)
|
||||||
|
# and use the backup to restore any conf/ini-files.
|
||||||
|
#
|
||||||
|
fallback_to_previous_version() {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# If all went well, then execute all necessary cleanup steps.
|
||||||
|
#
|
||||||
|
cleanup_previous_version() {
|
||||||
|
local func="${FUNCNAME[0]}"
|
||||||
|
return 0
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user