Owut: OpenWrt Upgrade Tool

Yeah, the first point is why I've been following the 24.10-SNAPSHOT vs. a tagged RC on the 24.10 branch... it means I can get granular updates when I have a few minutes to update the router, and makes it easy to keep up with new features / bug fixes (or help ID new bugs) as things change.

But my comment about being able to upgrade to 24.10-SNAPSHOT was only to point out that it seems there's something specific in the RC5 builds/agents vs. it being a generic trait of the 24.10 source tree / state.

1 Like

I thought I'd try owut

Currently on 24.10.0-rc5 built using Dynalink DL-WRX36 sysupgrade image + manually adding all packages (due to issues with firmware-selector site displaying init when trying the same there).

Successfully built an image using:
owut download -V 24.10-snapshot

Now tried:
owut download -V 24.10.0-rc5 or
owut download -V 24.10.0-rc5 --force and getting errors...?

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/rq/worker.py", line 1633, in perform_job
    return_value = job.perform()
                   ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rq/job.py", line 1331, in perform
    self._result = self._execute()
                   ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rq/job.py", line 1365, in _execute
    result = self.func(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/asu/build.py", line 155, in build
    container = podman.containers.create(
                ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/podman/domain/containers_create.py", line 354, in create
    response.raise_for_status(not_found=ImageNotFound)
  File "/usr/local/lib/python3.12/site-packages/podman/api/client.py", line 74, in raise_for_status
    raise not_found(cause, response=self._response, explanation=message)
podman.errors.exceptions.ImageNotFound: 404 Client Error: Not Found (no such image: ghcr.io/openwrt/imagebuilder:qualcommax-ipq807x-v24.10.0-rc5: image not known)

ERROR: Build failed with status 500```

It looks like we hit the wall with the master snapshots - one of the ABI-versioned packages was updated. Has there been any progress with fixing the underlying packaging tools?

You are seeing this upstream issue with the docker/podman containers, which I believe has been fixed by aparcar a couple hours ago. Give it a try again, let us know if it works.

Yeah, this first one is pretty easy to deal with, just remove the package:

$ owut download --remove libubus20241020

This works because libubus is not a top-level package (it's only there because something depends on it), and since nothing in the new package list depends on the 20241020-named version, owut thinks "fine, it's no longer needed, so carry on". When you go to build, all the packages that actually depend on libubus will pull in the new version libubus20250102 as a new package, so everything falls into place.

Since there's no way to automate this into owut, we'll have to do a manual intervention until the ABI data appears in the package/index files, bringing us to...

It's still in the pipe, @Ansuel created a new issue to track it a couple days ago: https://gitlab.alpinelinux.org/alpine/apk-tools/-/issues/11066

Oh, and since I'm speaking of --remove, I just added a new feature yesterday: both it and the --add option will now accept an argument delimited by whitespace, in addition to commas. I did this because I had wanted to test removing a bunch of packages that were listed in a file and didn't want to jump through hoops editing the file's contents.

$ cat files-to-remove
adblock
dnsmasq
... 50 other package names ...
zerotier

$ owut download --remove "$(cat files-to-remove)"
...

You can probably think of ways to combine the owut list output and the --add option to re-create a package collection from one device to another.

2 Likes

If anyone does this, take notes and add an example to the wiki with any considerations or issues you had to overcome. https://openwrt.org/docs/guide-user/installation/sysupgrade.owut#adding_and_removing_packages

1 Like

:hammer: Not getting this error anymore!

Also if a previous identical image resides on the server:
:hammer: Working!...

owut download -V 24.10.0-rc5
owut download -V 24.10-SNAPSHOT

I'm not sure if it's intended?
Adding init-script, then adding --force, 2x errors occur if the image on the server contains an identical init-script...

owut download -V 24.10.0-rc5    -I /tmp/99-asu-defaults
owut download -V 24.10.0-rc5    -I /tmp/99-asu-defaults --force
owut download -V 24.10-SNAPSHOT -I /tmp/99-asu-defaults
owut download -V 24.10-SNAPSHOT -I /tmp/99-asu-defaults --force
Request:
  Version 24.10-SNAPSHOT r28308-c06d4df974 (kernel 6.6.69)
  Included init script '/tmp/99-asu-defaults' (1938 bytes) in build request
Request hash:
  23481b46d8c71ee25c6082320f79f19afb2f8e58054de79827fb7971458b4fca
--
Status:   queued - 0 ahead of you
Progress:   0s total =   0s in queue +   0s in build
--
Status:   init
Progress:   3s total =   0s in queue +   3s in build

Build failed in   3s total =   0s in queue +   3s to build:
ASU server error =
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/rq/worker.py", line 1633, in perform_job
    return_value = job.perform()
                   ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rq/job.py", line 1331, in perform
    self._result = self._execute()
                   ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rq/job.py", line 1365, in _execute
    result = self.func(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/asu/build.py", line 142, in build
    defaults_file.parent.mkdir(parents=True)
  File "/usr/local/lib/python3.12/pathlib.py", line 1311, in mkdir
    os.mkdir(self, mode)
FileExistsError: [Errno 17] File exists: '/home/openwrt/public/store/23481b46d8c71ee25c6082320f79f19afb2f8e58054de79827fb7971458b4fca/files/etc/uci-defaults'

ERROR: Build failed with status 500
The above errors are often due to the upgrade server lagging behind the
build server, first suggestion is to wait a while and try again.

It could me my interpretation of how I issued the command line with init-script?

1 Like

Nope, you are doing everything correctly, that's a bug in the ASU server. I'm embarrassed to say that I found that 3-4 months ago, but forgot to submit the fix. Will do so right now...

EDIT: Proof that I did it, https://github.com/openwrt/asu/pull/1150 :grin:

1 Like

I reported a new issue based on a test device upgrade.

1 Like

Anyone here have an OpenWrt One? If so, could you post the output of the following? I'm curious about the block devices when you have both nand and nor storage on the same device (relates to some work I'm doing on --rootfs-size).

$ ls -la /sys/class/block/

I have an OpenWrt One, here is the output:

ls -la /sys/class/block/
root@router:~# ls -la /sys/class/block/
drwxr-xr-x    2 root     root             0 Jan  1  1970 .
drwxr-xr-x   43 root     root             0 Jan  1  1970 ..
lrwxrwxrwx    1 root     root             0 Jan  1  1970 fit0 -> ../../devices/platform/fitblk/fit0/block/fit0
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop0 -> ../../devices/virtual/block/loop0
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop1 -> ../../devices/virtual/block/loop1
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop2 -> ../../devices/virtual/block/loop2
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop3 -> ../../devices/virtual/block/loop3
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop4 -> ../../devices/virtual/block/loop4
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop5 -> ../../devices/virtual/block/loop5
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop6 -> ../../devices/virtual/block/loop6
lrwxrwxrwx    1 root     root             0 Jan  1  1970 loop7 -> ../../devices/virtual/block/loop7
lrwxrwxrwx    1 root     root             0 Jan  1  1970 mtdblock0 -> ../../devices/platform/soc/11009000.spi/spi_master/spi0/spi0.0/mtd/mtd0/mtdblock0
lrwxrwxrwx    1 root     root             0 Jan  1  1970 mtdblock1 -> ../../devices/platform/soc/11009000.spi/spi_master/spi0/spi0.0/mtd/mtd1/mtdblock1
lrwxrwxrwx    1 root     root             0 Jan  1  1970 mtdblock2 -> ../../devices/platform/soc/11009000.spi/spi_master/spi0/spi0.0/mtd/mtd2/mtdblock2
lrwxrwxrwx    1 root     root             0 Jan  1  1970 mtdblock3 -> ../../devices/platform/soc/11009000.spi/spi_master/spi0/spi0.0/mtd/mtd3/mtdblock3
lrwxrwxrwx    1 root     root             0 Jan  1  1970 mtdblock4 -> ../../devices/platform/soc/1100a000.spi/spi_master/spi1/spi1.1/mtd/mtd4/mtdblock4
lrwxrwxrwx    1 root     root             0 Jan  1  1970 mtdblock5 -> ../../devices/platform/soc/1100a000.spi/spi_master/spi1/spi1.1/mtd/mtd5/mtdblock5
lrwxrwxrwx    1 root     root             0 Jan  1  1970 ubiblock0_4 -> ../../devices/platform/soc/1100a000.spi/spi_master/spi1/spi1.1/mtd/mtd5/ubi0/ubi0_4/ubiblock0_4

Also attach the board info in case needed.

ubus call system board
root@router:~# ubus call system board
{
        "kernel": "6.6.70",
        "hostname": "***",
        "system": "ARMv8 Processor rev 4",
        "model": "OpenWrt One",
        "board_name": "openwrt,one",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "SNAPSHOT",
                "revision": "r28552-17b0d1379a",
                "target": "mediatek/filogic",
                "description": "OpenWrt SNAPSHOT r28552-17b0d1379a",
                "builddate": "1736517229"
        }
}

1 Like

Thanks! That's helpful, I hadn't seen a fit block in the wild before.

@efahl Quick question ...

Do you know with the upcoming 24.10.x release version, what will the sysupgrade.bin naming convention look like :question:

e.g... with the release candidate snapshot, and in the owut generated firmware-manifest.json file... there's the openwrt-*.bin name field:

    {
      "filesystem": "squashfs",
      "name": "openwrt-24.10-snapshot-r28327-e620694876-8a1efdc71422-qualcommax-ipq807x-dynalink_dl-wrx36-squashfs-sysupgrade.bin",
      "sha256": "4f83855dc23a11e39a2cbc356c93068caaa62db84dd64660a615dbbc47fcc5a6",
      "sha256_unsigned": "e3d951ee947a8c866c4ad5d00ce58f6d99a63f7a5915a787d68bf472e631050a",
      "type": "sysupgrade"
    }

I'm writing a script that'll convert the default owut generated firmware.* files to an openwrt-24*.firwmare.* format, to archive builds by the generated name found in the firmware-manifest.json.

I noticed a difference between the:
development snapshot & release candidate snapshot names, and I'm guessing there'll be a different format for the release versions?

The naming of location and images has been stable for many years, I haven't seen it change in forever.

On the downloads site, the locations are always:

https://downloads.openwrt.org/snapshots/targets/<target>/<subtarget>/
https://downloads.openwrt.org/releases/<version>/targets/<target>/<subtarget>/

Where <version> on the release branches is something like 23.05.5, 24.10-SNAPSHOT or 22.03.0-rc4. (Note that unlike most web addresses, the version names are case sensitive, so 24.10-snapshot will not work, you'll get a 404.)

For the image names themselves, the naming convention is consistent across releases and between the release and snapshots:

openwrt[-<version>][-<rev_code>][-<extra>]-<target>-<subtarget>-<profile>-<rootfs-type>-<image-type>.<appropriate-extension>
  • <version> is as above, but optional and only present for release -snapshots;
  • <rev-code> is the optional release code followed by the commit hash on the git repo, again only on release -snapshots;
  • <extra> is not present on images from the downloads site, but is used by the ASU server as a build-specific tag for each image it creates;
  • <target> and <subtarget> as usual;
  • <profile> is the device specifier, any commas turned into underscore (ubus call system board see board_name);
  • <rootfs-type> usually squashfs, but whatever's appropriate;
  • <image-type> usually sysupgrade, but combined or combined-efi for (usually) SBCs;
  • <extension> as appropriate, .ubi or .bin or .tgz or .fit or ...

Let's compare the image name you posted above with the image from downloads with the same specs:

openwrt-24.10-snapshot-r28327-e620694876-8a1efdc71422-qualcommax-ipq807x-dynalink_dl-wrx36-squashfs-sysupgrade.bin
openwrt-24.10-snapshot-r28337-7d597f8709-qualcommax-ipq807x-dynalink_dl-wrx36-squashfs-sysupgrade.bin

The differences I see are in the <rev-code>, where downloads is newer and thus the revision is bumped and the repo hash is different.

r28327-e620694876
r28337-7d597f8709

Yours also includes that build-specific hash in the middle, that's this part.

-8a1efdc71422

More than you wanted to know, right? :grin:

2 Likes

Yeah more / less! :smile:

Thank you for the detailed analysis, I had an expectation that you'd be so precise!

So the final 24.10.x release would be:
openwrt-24.10.x-8a1efdc71422-qualcommax-ipq807x-dynalink_dl-wrx36-squashfs-sysupgrade.bin

Right, from the firmware selector, but you don't know what that hash in the middle is until you know the full package selection and run it through https://github.com/openwrt/asu/blob/main/asu/util.py#L147 (which is what gives each ASU image its unique name). If you go to downloads, it's the same but minus the -8a...22.

You can see where the image name gets that part starting at https://github.com/openwrt/asu/blob/main/asu/build.py#L243, then down at line 251 it's passed to the image builder as EXTRA_IMAGE_NAME.

The various ASU clients don't even bother constructing the name, they look into the manifest.json at the images array (your json snippet a couple posts up) and search for the entry with the applicable filesystem and type, then grab the name entry directly.

That array is mirrored in the various profiles.json files for each of the targets, so you can get a good feel by just surfing all over downloads and look at those, checking out the images section of each profile. This one is pretty representative: https://downloads.openwrt.org/releases/23.05.5/targets/octeon/generic/profiles.json

Ahh... I should have explained that the sysupgrade.bin file was an example only:man_facepalming:
I did recognised the <extra> hash as changing a component, not static.

If using the owut package to generated images, it will generate the*.bin file in the manner your described in your last post?

e.g. this is what the forthcoming 24.10.x release image would look like?

openwrt-24.10.x-[generated]-qualcommax-ipq807x-dynalink_dl-wrx36-squashfs-sysupgrade.bin

Yup, you got it (or more precisely, ASU server will generate it, then owut downloads it to /tmp/firmware.bin).

Play around with this and see if it gets you anywhere:

$ jsonfilter -i /tmp/firmware-manifest.json -e '$.images[@.filesystem="squashfs" && @.type="sysupgrade"].name'

$ is the root anchor;
@ is the "here" anchor, so same as $.images[this-image] in this expression.

1 Like

the opkg manager name has changed and the image is not built if there are old language packs related to the old manager name.
However, the manager is automatically changed during the build, but the language packs are not.
Even after deleting the old language packs and running the build, it is built, although without errors, but without new language packs.
Is the problem in dependencies?
Since with other packages that have language packs for LUCI, they are pulled in automatically.