diff mbox series

[v2,3/6] base-files: fwtool: implement compatibility check for images

Message ID 20200714142825.16889-4-freifunk@adrianschmutzler.de
State Accepted
Delegated to: Adrian Schmutzler
Headers show
Series sysupgrade: introduce compatibility version for devices | expand

Commit Message

Adrian Schmutzler July 14, 2020, 2:28 p.m. UTC
We regularly encounter the situation that devices are subject to
changes that will make them incompatible to previous versions.
Removing SUPPORTED_DEVICES will not really be helpful in most of these
cases, as this only helps after a rename.

To solve this situation, this patchset introduces a compatibility
version for devices. In this patch, the actual checks are implemented
into fwtool_check_image():

If an incompatible change is introduced, one can increase either
the minor version (1.0->1.1) or the major version (1.0->2.0).

Minor version increment:
This will still allow sysupgrade, but require to reset config
(-n or SAVE_CONFIG=0). If sysupgrade is called without -n, a
corresponding message will be printed. If sysupgrade is called
with -n, it will just pass, with supported devices being checked
as usual. (Which will allow us to add back SUPPORTED_DEVICES for
many cases.)

Major version increment:
This is meant for potential (rare) cases where sysupgrade is
not possible at all, because it would break the device.
In this case, a warning will be printed, and -n won't help.

If image check fails because of one of the versions parts not
matching, the content of DEVICE_COMPAT_MESSAGE is printed in
addition to the generic message (if set).

For both cases, upgrade can still be forced with -F as usual.

Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>

---

Changes in v2:
- Move compat check AFTER supported_devices check
- Improve error messages
---
 .../base-files/files/lib/upgrade/fwtool.sh    | 24 ++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

Comments

Paul Spooren July 16, 2020, 4:04 a.m. UTC | #1
On 14.07.20 04:28, Adrian Schmutzler wrote:
> We regularly encounter the situation that devices are subject to
> changes that will make them incompatible to previous versions.
> Removing SUPPORTED_DEVICES will not really be helpful in most of these
> cases, as this only helps after a rename.
>
> To solve this situation, this patchset introduces a compatibility
> version for devices. In this patch, the actual checks are implemented
> into fwtool_check_image():
>
> If an incompatible change is introduced, one can increase either
> the minor version (1.0->1.1) or the major version (1.0->2.0).
>
> Minor version increment:
> This will still allow sysupgrade, but require to reset config
> (-n or SAVE_CONFIG=0). If sysupgrade is called without -n, a
> corresponding message will be printed. If sysupgrade is called
> with -n, it will just pass, with supported devices being checked
> as usual. (Which will allow us to add back SUPPORTED_DEVICES for
> many cases.)
>
> Major version increment:
> This is meant for potential (rare) cases where sysupgrade is
> not possible at all, because it would break the device.
> In this case, a warning will be printed, and -n won't help.
What are those rare cases? I just can't think of anything where not even 
a clean sysupgrade would be possible. Would it mean to go back to stock 
firmware and then upgrade a 2.x version? If there isn't a scenario maybe 
a single integer is easier to handle than a pseudo float.
> If image check fails because of one of the versions parts not
> matching, the content of DEVICE_COMPAT_MESSAGE is printed in
> addition to the generic message (if set).
>
> For both cases, upgrade can still be forced with -F as usual.
>
> Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
>
> ---
>
> Changes in v2:
> - Move compat check AFTER supported_devices check
> - Improve error messages
> ---
>   .../base-files/files/lib/upgrade/fwtool.sh    | 24 ++++++++++++++++++-
>   1 file changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/package/base-files/files/lib/upgrade/fwtool.sh b/package/base-files/files/lib/upgrade/fwtool.sh
> index a0b3fb0a04..1807aecd6d 100644
> --- a/package/base-files/files/lib/upgrade/fwtool.sh
> +++ b/package/base-files/files/lib/upgrade/fwtool.sh
> @@ -44,13 +44,35 @@ fwtool_check_image() {
>   	}
>   
>   	device="$(cat /tmp/sysinfo/board_name)"
> +	devicecompat="$(uci -q get system.@system[0].compat_version)"
> +	[ -n "$devicecompat" ] || devicecompat="1.0"
> +
> +	json_get_var imagecompat compat_version
> +	json_get_var compatmessage compat_message
> +	[ -n "$imagecompat" ] || imagecompat="1.0"
>   
>   	json_select supported_devices || return 1
>   
>   	json_get_keys dev_keys
>   	for k in $dev_keys; do
>   		json_get_var dev "$k"
> -		[ "$dev" = "$device" ] && return 0
> +		if [ "$dev" = "$device" ]; then
> +			# major compat version -> no sysupgrade
> +			if [ "${devicecompat%.*}" != "${imagecompat%.*}" ]; then
> +				echo "The device is supported, but this image is incompatible for sysupgrade based on the image version ($devicecompat->$imagecompat)."
> +				[ -n "$compatmessage" ] && echo "$compatmessage"
> +				return 1
> +			fi
> +
> +			# minor compat version -> sysupgrade with -n required
> +			if [ "${devicecompat#.*}" != "${imagecompat#.*}" ] && [ "$SAVE_CONFIG" = "1" ]; then
> +				echo "The device is supported, but the config is incompatible to the new image ($devicecompat->$imagecompat). Please upgrade with -n."
I'd write "Please upgrade with -n to reset the device configuration"
> +				[ -n "$compatmessage" ] && echo "$compatmessage"
> +				return 1
> +			fi
> +
> +			return 0
> +		fi
>   	done
>   
>   	echo "Device $device not supported by this image"
Bjørn Mork July 16, 2020, 8:10 a.m. UTC | #2
Paul Spooren <mail@aparcar.org> writes:

>> Major version increment:
>> This is meant for potential (rare) cases where sysupgrade is
>> not possible at all, because it would break the device.
>> In this case, a warning will be printed, and -n won't help.
>
> What are those rare cases? I just can't think of anything where not
> even a clean sysupgrade would be possible. Would it mean to go back to
> stock firmware and then upgrade a 2.x version? If there isn't a
> scenario maybe a single integer is easier to handle than a pseudo
> float.

Changing partition layout maybe?

I don't think it's necessary to specify the exact upgrade method for
every possible device/scenario.  The important part is to prevent
semi-bricking and issue a warning, which should make the user go look
for further upgrade instructions.


Bjørn
Adrian Schmutzler July 16, 2020, 9:34 a.m. UTC | #3
> -----Original Message-----
> From: openwrt-devel [mailto:openwrt-devel-bounces@lists.openwrt.org]
> On Behalf Of Bjørn Mork
> Sent: Donnerstag, 16. Juli 2020 10:10
> To: Paul Spooren <mail@aparcar.org>
> Cc: Adrian Schmutzler <freifunk@adrianschmutzler.de>; openwrt-
> devel@lists.openwrt.org
> Subject: Re: [PATCH v2 3/6] base-files: fwtool: implement compatibility check
> for images
> 
> Paul Spooren <mail@aparcar.org> writes:
> 
> >> Major version increment:
> >> This is meant for potential (rare) cases where sysupgrade is not
> >> possible at all, because it would break the device.
> >> In this case, a warning will be printed, and -n won't help.
> >
> > What are those rare cases? I just can't think of anything where not
> > even a clean sysupgrade would be possible. Would it mean to go back to
> > stock firmware and then upgrade a 2.x version? If there isn't a
> > scenario maybe a single integer is easier to handle than a pseudo
> > float.
> 
> Changing partition layout maybe?
> 
> I don't think it's necessary to specify the exact upgrade method for every
> possible device/scenario.  The important part is to prevent semi-bricking and
> issue a warning, which should make the user go look for further upgrade
> instructions.

Indeed, this is not really designed with a precise case in mind already.

The honor for the initial idea of having X.Y versions actually goes to Paweł Dembicki:
http://lists.infradead.org/pipermail/openwrt-devel/2020-June/029508.html
He even provided links for the major revision case there.

I picked it up thankfully, as this makes the concept more powerful and general without having a real downside.

An easy way of reflashing without sysupgrade for many devices could be e.g. TFTP, where you are able to just flash the factory.bin again without caring about really going back to vendor firmware.
Of course, what's actually recommended here depends on the situation and will be very specific to the devices affected, and one could even provide instructions via COMPAT_MESSAGE then (e.g. flash via TFTP).

After all, it may also be possible that we will never need this, but I still think it makes sense to put it in place when we are touching this now anyway.

Best

Adrian
diff mbox series

Patch

diff --git a/package/base-files/files/lib/upgrade/fwtool.sh b/package/base-files/files/lib/upgrade/fwtool.sh
index a0b3fb0a04..1807aecd6d 100644
--- a/package/base-files/files/lib/upgrade/fwtool.sh
+++ b/package/base-files/files/lib/upgrade/fwtool.sh
@@ -44,13 +44,35 @@  fwtool_check_image() {
 	}
 
 	device="$(cat /tmp/sysinfo/board_name)"
+	devicecompat="$(uci -q get system.@system[0].compat_version)"
+	[ -n "$devicecompat" ] || devicecompat="1.0"
+
+	json_get_var imagecompat compat_version
+	json_get_var compatmessage compat_message
+	[ -n "$imagecompat" ] || imagecompat="1.0"
 
 	json_select supported_devices || return 1
 
 	json_get_keys dev_keys
 	for k in $dev_keys; do
 		json_get_var dev "$k"
-		[ "$dev" = "$device" ] && return 0
+		if [ "$dev" = "$device" ]; then
+			# major compat version -> no sysupgrade
+			if [ "${devicecompat%.*}" != "${imagecompat%.*}" ]; then
+				echo "The device is supported, but this image is incompatible for sysupgrade based on the image version ($devicecompat->$imagecompat)."
+				[ -n "$compatmessage" ] && echo "$compatmessage"
+				return 1
+			fi
+
+			# minor compat version -> sysupgrade with -n required
+			if [ "${devicecompat#.*}" != "${imagecompat#.*}" ] && [ "$SAVE_CONFIG" = "1" ]; then
+				echo "The device is supported, but the config is incompatible to the new image ($devicecompat->$imagecompat). Please upgrade with -n."
+				[ -n "$compatmessage" ] && echo "$compatmessage"
+				return 1
+			fi
+
+			return 0
+		fi
 	done
 
 	echo "Device $device not supported by this image"