Skip to content

Commit

Permalink
update firmware workflow to align with latest dev agent (#11)
Browse files Browse the repository at this point in the history
* align workflow with current thin-edge.io development

* persist logging across A/B updates

* change ownership of build folder after running bakery
  • Loading branch information
reubenmiller authored Nov 29, 2023
1 parent 2954e47 commit 859d91e
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 47 deletions.
1 change: 0 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ customize:
# Create the image that can be flashed to an SD card or applied using the rugpi interface
bake:
./run-bakery --config "{{IMAGE_CONFIG}}" bake "{{CUSTOM_TAR}}" "{{OUTPUT_IMAGE}}"
[ -n "$CI" ] && sudo chmod 777 build/*
@echo ""
@echo "Compressing image"
xz -0 -v "{{OUTPUT_IMAGE}}"
Expand Down
16 changes: 8 additions & 8 deletions recipes/tedge-firmware-update/files/firmware_update.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,43 @@ next = ["scheduled"]
next = ["executing"]

[executing]
script = "/usr/bin/rugpi_workflow.sh executing --id ${.topic.cmd_id} --on-success download"
script = "/usr/bin/rugpi_workflow.sh executing --on-success download"
next = ["download"]

[download]
script = "/usr/bin/rugpi_workflow.sh download --id ${.topic.cmd_id} --url ${.payload.remoteUrl} --on-success install --on-error failed"
script = "/usr/bin/rugpi_workflow.sh download --url ${.payload.remoteUrl} --on-success install --on-error failed"
next = ["install"]

[install]
script = "/usr/bin/rugpi_workflow.sh install --id ${.topic.cmd_id} --url ${.payload.url} --on-success restart --on-restart restart --on-error failed"
script = "/usr/bin/rugpi_workflow.sh install --url ${.payload.url} --on-success restart --on-restart restart --on-error failed"
next = ["commit", "restart", "failed"]

[restart]
script = "restart"
next = ["restarting", "restarted", "failed_restart"]

[restarted]
script = "/usr/bin/rugpi_workflow.sh restarted --id ${.topic.cmd_id} --on-success verify"
script = "/usr/bin/rugpi_workflow.sh restarted --on-success verify"
next = ["verify"]

[failed_restart]
script = "/usr/bin/rugpi_workflow.sh failed_restart --id ${.topic.cmd_id} --on-success failed --on-error failed"
script = "/usr/bin/rugpi_workflow.sh failed_restart --on-success failed --on-error failed"
next = ["failed"]

[verify]
script = "/usr/bin/rugpi_workflow.sh verify --id ${.topic.cmd_id} --firmware-name ${.payload.name} --firmware-version ${.payload.version} --url ${.payload.remoteUrl} --on-success commit --on-restart rollback_restart --on-error failed"
script = "/usr/bin/rugpi_workflow.sh verify --firmware-name ${.payload.name} --firmware-version ${.payload.version} --url ${.payload.remoteUrl} --on-success commit --on-restart rollback_restart --on-error failed"
next = ["commit", "rollback_restart", "failed"]

[commit]
script = "/usr/bin/rugpi_workflow.sh commit --id ${.topic.cmd_id} --firmware-name ${.payload.name} --firmware-version ${.payload.version} --url ${.payload.remoteUrl} --on-success successful --on-restart rollback_restart --on-error failed"
script = "/usr/bin/rugpi_workflow.sh commit --firmware-name ${.payload.name} --firmware-version ${.payload.version} --url ${.payload.remoteUrl} --on-success successful --on-restart rollback_restart --on-error failed"
next = ["successful", "rollback_restart"]

[rollback_restart]
script = "restart"
next = ["restarting", "rollback_successful", "failed"]

[rollback_successful]
script = "/usr/bin/rugpi_workflow.sh rollback_successful --id ${.topic.cmd_id} --on-success failed"
script = "/usr/bin/rugpi_workflow.sh rollback_successful --on-success failed"
next = ["failed"]

[successful]
Expand Down
68 changes: 31 additions & 37 deletions recipes/tedge-firmware-update/files/rugpi_workflow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ ON_RESTART="restart"
FIRMWARE_NAME=
FIRMWARE_VERSION=
FIRMWARE_URL=
CMD_ID=x
FIRMWARE_META_FILE=/etc/tedge/.firmware
LOG_FILE=/etc/tedge/firmware_update.log
MANUAL_DOWNLOAD=0

# Use temp directory so that the file can't accidentally persist across partitions
Expand All @@ -20,7 +18,7 @@ SUDO="sudo"
_WORKDIR=$(pwd)

# Change to a directory which is readable otherwise rugpi-ctrl can have problems reading the mounts
cd /
cd /tmp || cd /

HOT=$(rugpi-ctrl system info | grep Hot | cut -d: -f2 | xargs)
DEFAULT=$(rugpi-ctrl system info | grep Default | cut -d: -f2 | xargs)
Expand All @@ -30,27 +28,26 @@ shift


log() {
msg="$(date +%Y-%m-%dT%H:%M:%S) [cmd=$CMD_ID, current=$ACTION] $*"
msg="$(date +%Y-%m-%dT%H:%M:%S) [current=$ACTION] $*"
echo "$msg" >&2

# publish to pub for better resolution
current_partition=$(get_current_partition)
tedge mqtt pub -q 2 te/device/main///e/firmware_update "{\"text\":\"Firmware Workflow: [$ACTION] $*\",\"command_id\":\"$CMD_ID\",\"state\":\"$ACTION\",\"partition\":\"$current_partition\"}"
tedge mqtt pub -q 2 te/device/main///e/firmware_update "{\"text\":\"Firmware Workflow: [$ACTION] $*\",\"state\":\"$ACTION\",\"partition\":\"$current_partition\"}"
sleep 1

if [ -n "$LOG_FILE" ]; then
echo "$msg" >> "$LOG_FILE"
fi
}

local_log() {
# Only log locally and don't push to the cloud
msg="$(date +%Y-%m-%dT%H:%M:%S) [cmd=$CMD_ID, current=$ACTION] $*"
msg="$(date +%Y-%m-%dT%H:%M:%S) [current=$ACTION] $*"
echo "$msg" >&2
}

if [ -n "$LOG_FILE" ]; then
echo "$msg" >> "$LOG_FILE"
fi
next_state_with_context() {
echo ":::begin-tedge:::"
echo "$1"
echo ":::end-tedge:::"
sleep 1
}

next_state() {
Expand All @@ -61,13 +58,16 @@ next_state() {
reason="$2"
fi

message=
if [ -n "$reason" ]; then
log "Moving to next State: $status. reason=$reason"
printf '{"status":"%s","reason":"%s"}\n' "$status" "$reason"
message=$(printf '{"status":"%s","reason":"%s"}' "$status" "$reason")
else
log "Moving to next State: $status"
printf '{"status":"%s"}\n' "$status"
message=$(printf '{"status":"%s"}' "$status")
fi

next_state_with_context "$message"
sleep 1
}

Expand All @@ -76,10 +76,6 @@ next_state() {
#
while [ $# -gt 0 ]; do
case "$1" in
--id)
CMD_ID="$2"
shift
;;
--firmware-name)
FIRMWARE_NAME="$2"
shift
Expand All @@ -88,6 +84,10 @@ while [ $# -gt 0 ]; do
FIRMWARE_VERSION="$2"
shift
;;
--url)
FIRMWARE_URL="$2"
shift
;;
--on-success)
ON_SUCCESS="$2"
shift
Expand All @@ -100,10 +100,6 @@ while [ $# -gt 0 ]; do
ON_RESTART="$2"
shift
;;
--url)
FIRMWARE_URL="$2"
shift
;;
esac
shift
done
Expand Down Expand Up @@ -158,11 +154,9 @@ get_next_partition() {
executing() {
current_partition=$(get_current_partition)
next_partition=$(get_next_partition "$current_partition")
{
echo "---------------------------------------------------------------------------"
echo "Firmware update (id=$CMD_ID): $current_partition -> $next_partition"
echo "---------------------------------------------------------------------------"
} >> "$LOG_FILE"
echo "---------------------------------------------------------------------------"
echo "Firmware update: $current_partition -> $next_partition"
echo "---------------------------------------------------------------------------"
log "Starting firmware update. Current partition is $(get_current_partition), so update will be applied to $next_partition"
}

Expand Down Expand Up @@ -190,7 +184,7 @@ download() {
;;
*)
# Assume url is actually a file and just go to the next state
printf '{"status":"%s","url":"%s"}\n' "$status" "$url"
next_state_with_context "$(printf '{"status":"%s","url":"%s"}\n' "$status" "$url")"
return 0
;;
esac
Expand All @@ -208,10 +202,10 @@ download() {
log "Manually downloading artifact from $tedge_url and saving to $local_file"
wget -c -O "$local_file" "$tedge_url" >&2
log "Downloaded file from: $tedge_url"
printf '{"status":"%s","url":"%s"}\n' "$status" "$local_file"
next_state_with_context "$(printf '{"status":"%s","url":"%s"}\n' "$status" "$local_file")"
else
log "Converted to local url: $url => $tedge_url"
printf '{"status":"%s","url":"%s"}\n' "$status" "$tedge_url"
next_state_with_context "$(printf '{"status":"%s","url":"%s"}\n' "$status" "$tedge_url")"
fi
}

Expand All @@ -221,13 +215,13 @@ install() {
case "$url" in
http://*.img|https://*.img)
log "Executing: wget -c -q -t 0 -O - '$url' | $SUDO rugpi-ctrl update install --stream --no-reboot -"
wget -c -q -t 0 -O - "$url" | $SUDO rugpi-ctrl update install --stream --no-reboot - >>"$LOG_FILE" 2>&1
wget -c -q -t 0 -O - "$url" | $SUDO rugpi-ctrl update install --stream --no-reboot -
;;

# Assume a xz compressed file
http://*|https://*)
log "Executing: wget -c -q -t 0 -O - '$url' | xz -d | $SUDO rugpi-ctrl update install --stream --no-reboot -"
wget -c -q -t 0 -O - "$url" | xz -d | $SUDO rugpi-ctrl update install --stream --no-reboot - >>"$LOG_FILE" 2>&1
wget -c -q -t 0 -O - "$url" | xz -d | $SUDO rugpi-ctrl update install --stream --no-reboot -
;;

# It is a file
Expand All @@ -239,12 +233,12 @@ install() {
application/x-xz)
# Decode the file and stream it into rugpi (decompressing on the fly)
log "Executing: xz -d -T0 -c '$url' | $SUDO rugpi-ctrl update install --stream --no-reboot -"
xz --decompress --stdout -T0 "$url" | $SUDO rugpi-ctrl update install --stream --no-reboot - >>"$LOG_FILE" 2>&1
xz --decompress --stdout -T0 "$url" | $SUDO rugpi-ctrl update install --stream --no-reboot -
;;
*)
# Uncompressed file
log "Executing: rugpi-ctrl update install --no-reboot '$url'"
$SUDO rugpi-ctrl update install --no-reboot "$url" >>"$LOG_FILE" 2>&1
$SUDO rugpi-ctrl update install --no-reboot "$url"
;;
esac
;;
Expand Down Expand Up @@ -298,7 +292,7 @@ verify() {
fi

# Allow users to also call addition logic by adding their scripts to the /etc/health.d/ directory
if /usr/bin/healthcheck.sh >> "$LOG_FILE" 2>&1; then
if /usr/bin/healthcheck.sh; then
next_state "$ON_SUCCESS"
else
log "Health check failed on new partition"
Expand All @@ -309,7 +303,7 @@ verify() {
commit() {
log "Executing: rugpi-ctrl system commit"
set +e
$SUDO rugpi-ctrl system commit >> "$LOG_FILE" 2>&1
$SUDO rugpi-ctrl system commit
EXIT_CODE=$?
set -e

Expand Down
3 changes: 3 additions & 0 deletions recipes/thin-edge.io/files/tedge-config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
[[persist]]
directory = "/etc/tedge"

[[persist]]
directory = "/var/log/tedge"

[[persist]]
directory = "/etc/mosquitto"
10 changes: 9 additions & 1 deletion run-bakery
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

set -euo pipefail
set -e

DOCKER=${DOCKER:-docker}
RUGPI_IMAGE=${RUGPI_IMAGE:-ghcr.io/silitics/rugpi-bakery:latest}
Expand All @@ -11,3 +11,11 @@ $DOCKER run --rm --privileged \
--pull always \
"$RUGPI_IMAGE" \
"$@"

if [ -n "$CI" ]; then
# Fix ownership issues on CI runner as the docker output produces files
# not owned by the calling user. This causes downstream issues with tools
# such as xz which tries to change the group ownership of the compressed
# file.
sudo chown "$(whoami):$(whoami)" -R build ||:
fi

0 comments on commit 859d91e

Please sign in to comment.