QubesOS / qubes-issues

The Qubes OS Project issue tracker
https://www.qubes-os.org/doc/issue-tracking/
544 stars 48 forks source link

`qubes-vm-update`: `KeyError` in template handling #9449

Open cfm opened 2 months ago

cfm commented 2 months ago

Qubes OS release

R4.2.2

Brief summary

Running qubes-vm-update --templates can fail with a KeyError on some templates: in my testing, both a stock template and a clone I've created.

Steps to reproduce

[user@dom0 ~]$ sudo qubes-vm-update --no-progress --show-output --standalones --templates --apply-to-all

Expected behavior

No unhandled errors.

Actual behavior

The first run fails on a template cloned from debian-12-xfce, with VM-level errors that I believe are not relevant here:

[...]
cfm-d12:out: Refreshing package info
cfm-d12:out: Hit:1 https://updates.signal.org/desktop/apt xenial InRelease
cfm-d12:out: Hit:2 https://deb.debian.org/debian bookworm InRelease
cfm-d12:out: Hit:3 https://deb.debian.org/debian-security bookworm-security InRelease
cfm-d12:out: Hit:4 https://downloads.1password.com/linux/debian/amd64 stable InRelease
cfm-d12:out: Hit:5 https://apt.releases.hashicorp.com bookworm InRelease
cfm-d12:out: Hit:6 https://deb.qubes-os.org/r4.2/vm bookworm InRelease
cfm-d12:out: Hit:7 https://wire-app.wire.com/linux/debian stable InRelease
cfm-d12:out: Reading package lists...
cfm-d12:out: Reading package lists...
cfm-d12:out: Building dependency tree...
cfm-d12:out: Reading state information...
cfm-d12:out: Calculating upgrade...
cfm-d12:out: The following package was automatically installed and is no longer required:
cfm-d12:out:   linux-image-6.1.0-21-amd64
cfm-d12:out: Use 'apt autoremove' to remove it.
cfm-d12:out: 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
cfm-d12:out: 1 not fully installed or removed.
cfm-d12:out: After this operation, 0 B of additional disk space will be used.
cfm-d12:out: Setting up 1password (8.10.44) ...
cfm-d12:out: Installing the debian auto-update channel
cfm-d12:out: curl: (6) Could not resolve host: downloads.1password.com
cfm-d12:out: gpg: no valid OpenPGP data found.
cfm-d12:out: dpkg: error processing package 1password (--configure):
cfm-d12:out:  installed 1password package post-installation script subprocess returned error exit status 2
cfm-d12:out: Errors were encountered while processing:
cfm-d12:out:  1password
cfm-d12:out: Installed packages:
cfm-d12:out: None
cfm-d12:out: Updated packages:
cfm-d12:out: None
cfm-d12:out: Removed packages:
cfm-d12:out: None
cfm-d12:out:
cfm-d12:out:
cfm-d12:err: Refreshing package info
cfm-d12:err: Hit:1 https://updates.signal.org/desktop/apt xenial InRelease
cfm-d12:err: Hit:2 https://deb.debian.org/debian bookworm InRelease
cfm-d12:err: Hit:3 https://deb.debian.org/debian-security bookworm-security InRelease
cfm-d12:err: Hit:4 https://downloads.1password.com/linux/debian/amd64 stable InRelease
cfm-d12:err: Hit:5 https://apt.releases.hashicorp.com bookworm InRelease
cfm-d12:err: Hit:6 https://deb.qubes-os.org/r4.2/vm bookworm InRelease
cfm-d12:err: Hit:7 https://wire-app.wire.com/linux/debian stable InRelease
cfm-d12:err: Reading package lists...
cfm-d12:err: Reading package lists...
cfm-d12:err: Building dependency tree...
cfm-d12:err: Reading state information...
cfm-d12:err: Calculating upgrade...
cfm-d12:err: The following package was automatically installed and is no longer required:
cfm-d12:err:   linux-image-6.1.0-21-amd64
cfm-d12:err: Use 'apt autoremove' to remove it.
cfm-d12:err: 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
cfm-d12:err: 1 not fully installed or removed.
cfm-d12:err: After this operation, 0 B of additional disk space will be used.
cfm-d12:err: Setting up 1password (8.10.44) ...
cfm-d12:err: Installing the debian auto-update channel
cfm-d12:err: curl: (6) Could not resolve host: downloads.1password.com
cfm-d12:err: gpg: no valid OpenPGP data found.
cfm-d12:err: dpkg: error processing package 1password (--configure):
cfm-d12:err:  installed 1password package post-installation script subprocess returned error exit status 2
cfm-d12:err: Errors were encountered while processing:
cfm-d12:err:  1password
cfm-d12:err: Installed packages:
cfm-d12:err: None
cfm-d12:err: Updated packages:
cfm-d12:err: None
cfm-d12:err: Removed packages:
cfm-d12:err: None
cfm-d12:err:
cfm-d12:err:
[...]
Traceback (most recent call last):
  File "/usr/bin/qubes-vm-update", line 33, in <module>
    sys.exit(load_entry_point('qubes-vmupdate==4.2.28', 'console_scripts', 'qubes-vm-update')())
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vmupdate/vmupdate.py", line 76, in main
    ret_code_restart = apply_updates_to_appvm(
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vmupdate/vmupdate.py", line 325, in apply_updates_to_appvm
    updated_tmpls = [
            ^
  File "/usr/lib/python3.11/site-packages/vmupdate/vmupdate.py", line 327, in <listcomp>
    if bool(template_statuses[vm.name]) and vm.klass == 'TemplateVM'
        ~~~~~~~~~~~~~~~~~^^^^^^^^^
KeyError: 'cfm-d12'

The second run fails on stock fedora-40-xfce, without VM-level errors:

[...]
fedora-40-xfce:out: Refreshing package info
fedora-40-xfce:out: Last metadata expiration check: 0:00:02 ago on Wed Sep 11 12:04:53 2024.
fedora-40-xfce:out: Dependencies resolved.
fedora-40-xfce:out: Nothing to do.
fedora-40-xfce:out: Complete!
fedora-40-xfce:out: Installed packages:
fedora-40-xfce:out: None
fedora-40-xfce:out: Updated packages:
fedora-40-xfce:out: None
fedora-40-xfce:out: Removed packages:
fedora-40-xfce:out: None
fedora-40-xfce:out:
fedora-40-xfce:out:
fedora-40-xfce:err: Refreshing package info
fedora-40-xfce:err: Last metadata expiration check: 0:00:02 ago on Wed Sep 11 12:04:53 2024.
fedora-40-xfce:err: Dependencies resolved.
fedora-40-xfce:err: Nothing to do.
fedora-40-xfce:err: Complete!
fedora-40-xfce:err: Installed packages:
fedora-40-xfce:err: None
fedora-40-xfce:err: Updated packages:
fedora-40-xfce:err: None
fedora-40-xfce:err: Removed packages:
fedora-40-xfce:err: None
fedora-40-xfce:err:
fedora-40-xfce:err:
[...]
Traceback (most recent call last):
  File "/usr/bin/qubes-vm-update", line 33, in <module>
    sys.exit(load_entry_point('qubes-vmupdate==4.2.28', 'console_scripts', 'qubes-vm-update')())
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vmupdate/vmupdate.py", line 76, in main
    ret_code_restart = apply_updates_to_appvm(
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/vmupdate/vmupdate.py", line 325, in apply_updates_to_appvm
    updated_tmpls = [
            ^
  File "/usr/lib/python3.11/site-packages/vmupdate/vmupdate.py", line 327, in <listcomp>
    if bool(template_statuses[vm.name]) and vm.klass == 'TemplateVM'
        ~~~~~~~~~~~~~~~~~^^^^^^^^^
KeyError: 'fedora-40-xfce'
cfm commented 2 months ago

It looks like apply_updates_to_appvm() tries to check the status of vm even when it's not updateable. Naïvely, this patch eliminates the KeyError, though I'll have to wait for a template to have pending updates again to test this in that case:

Edit: This does not do the trick after all.

--- a/vmupdate/vmupdate.py
+++ b/vmupdate/vmupdate.py
@@ -324,7 +324,7 @@ def apply_updates_to_appvm(

     updated_tmpls = [
         vm for vm in vm_updated
-        if bool(template_statuses[vm.name]) and vm.klass == 'TemplateVM'
+        if getattr(vm, "updateable", False) and vm.klass == "TemplateVM" and bool(template_statuses[vm.name])
     ]
     to_restart, to_shutdown = get_derived_vm_to_apply(
         updated_tmpls, derived_statuses)