firmware: abort on what appear to be partial updates due to obscure file errors

This relates to update logs like these when pkg does not proceed to install
at least all the packages that it should (see "67/73"):

    [...]
    [65/73] Upgrading easy-rsa from 3.2.2,1 to 3.2.3,1...
    [65/73] Extracting easy-rsa-3.2.3,1: .......... done
    [66/73] Upgrading jq from 1.7.1 to 1.8.0...
    [66/73] Extracting jq-1.8.0: .......... done
    [67/73] Upgrading py311-httpx from 0.28.1 to 0.28.1_1...
    [67/73] Extracting py311-httpx-0.28.1_1: ..
    pkg-static: Fail to set time on /usr/local/lib/python3.11/site-packages/httpx/__pycache__/.pkgtemp._exceptions.cpython-311.opt-1.pyc.XQqetoRDyijl:No such file or directory
    [67/73] Extracting py311-httpx-0.28.1_1... done
    Starting web GUI...done.
    Fetching base-25.1.11-amd64.txz: ........ done
    Fetching kernel-25.1.11-amd64.txz: .... done
    !!!!!!!!!!!! ATTENTION !!!!!!!!!!!!!!!
    ! A critical upgrade is in progress. !
    ! Please do not turn off the system. !
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    [...]

Historically we never aborted updates and I don't remember a time when this
was as bad as it is now.  Since opnsense-update already calls an explicit
"exit 1" in this case we can catch the error and proceed to inform the user,
try the temporary pkg file cleanup and then prompt the user to restart.

This prevents any further action like installing a new kernel and booting into
the partially updated situation which may be fatal for various reasons.

I'm unsure about the web GUI restart hook. It could be dangerous to restart,
it could be dangerous not to restart.  Since the historic behaviour is to
always do it keep this approach.

Related to: https://github.com/opnsense/ports/issues/234
This commit is contained in:
Franco Fichtner 2025-08-06 09:07:50 +02:00
parent 1d1ff5c007
commit ea75da8a35

View file

@ -1,6 +1,6 @@
#!/bin/sh
# Copyright (C) 2015-2023 Franco Fichtner <franco@opnsense.org>
# Copyright (C) 2015-2025 Franco Fichtner <franco@opnsense.org>
# Copyright (C) 2014 Deciso B.V.
# All rights reserved.
#
@ -46,13 +46,24 @@ fi
# read reboot flag and record current package name and version state
ALWAYS_REBOOT=$(/usr/local/sbin/pluginctl -g system.firmware.reboot)
PKGS_HASH=$(${PKG} query %n-%v 2> /dev/null | sha256)
UPDATE_FAILED=
# upgrade all packages if possible
output_cmd opnsense-update ${FORCE} -pt "opnsense${SUFFIX}"
# update all packages if possible
if ! output_cmd opnsense-update ${FORCE} -pt "opnsense${SUFFIX}"; then
UPDATE_FAILED=1
fi
# restart the web server
output_cmd /usr/local/etc/rc.restart_webgui
# if the uodate failed then abort and and try to recover
if [ -n "${UPDATE_FAILED}" ]; then
output_txt "Partial update failure detected: attempting automatic cleanup."
output_cmd opnsense-update -Fs
output_txt "No further actions will be taken. Please restart the update now."
output_done
fi
# run plugin resolver if requested
if [ "${CMD}" = "sync" ]; then
/usr/local/opnsense/scripts/firmware/sync.subr.sh