Skip to content

updater: dom0 non-iteractive updater#191

Open
piotrbartman wants to merge 13 commits intoQubesOS:mainfrom
piotrbartman:vmupdater/dom0
Open

updater: dom0 non-iteractive updater#191
piotrbartman wants to merge 13 commits intoQubesOS:mainfrom
piotrbartman:vmupdater/dom0

Conversation

@piotrbartman
Copy link
Member

  • qubes-vm-update uses qubes-dom0-update --just-print-progress for non-interactive update, only small subset of action are supported.
  • introduce agent_type: for local (dom0), remote (template vms etc.) and proxy (update vm) actions.
  • progress reporting for dom0 update (dnf4, dnf5)

requires: QubesOS/qubes-core-agent-linux/pull/576

@codecov-commenter
Copy link

codecov-commenter commented May 30, 2025

Codecov Report

❌ Patch coverage is 58.30904% with 143 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.33%. Comparing base (d7df71c) to head (4824edd).

Files with missing lines Patch % Lines
vmupdate/update_manager.py 27.45% 74 Missing ⚠️
vmupdate/qube_connection.py 4.65% 41 Missing ⚠️
vmupdate/vmupdate.py 81.69% 13 Missing ⚠️
vmupdate/agent/source/common/process_result.py 0.00% 6 Missing ⚠️
vmupdate/agent/source/status.py 42.85% 4 Missing ⚠️
vmupdate/agent/source/log_config.py 60.00% 2 Missing ⚠️
vmupdate/tests/test_vmupdate.py 97.80% 2 Missing ⚠️
vmupdate/tests/conftest.py 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #191      +/-   ##
==========================================
- Coverage   72.63%   69.33%   -3.31%     
==========================================
  Files          10       10              
  Lines        1162     1275     +113     
==========================================
+ Hits          844      884      +40     
- Misses        318      391      +73     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@marmarek marmarek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is based on initial reading the code, I haven't tested it yet.

super().__init__(log_handler, log_level, agent_type)

if self.type == AgentType.UPDATE_VM:
dnfconf = "/var/lib/qubes/dom0-updates/etc/dnf/dnf.conf"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use self.UPDATE_VM_INSTALLROOT like in the other places?


self.base = dnf.Base(conf)
if self.type == AgentType.UPDATE_VM:
self.base._allow_erasing = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the dnf source, the only place where it's used in practice is an argument to base.resolve(). So, you can use it there (in upgrade_internal) instead of setting a private attribute.

QVMRUN_OPTS=(--quiet --filter-escape-chars --nogui --pass-io)

if [ "$PROGRESS_REPORTING" == "1" ]; then
CMD="/usr/lib/qubes/qubes-download-dom0-updates-init.sh"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to handle the case of old template too. It's okay to refuse this mode in such a case, but it needs a proper error message instead of a file not found error. Something like "Progress reporting requires updatevm based on a template with Qubes 4.3 packages", or something like this (maybe include template name and/or name of the updatevm?)
Whether it is new enough, you can check either by handling exit code 127 (file not found), or (better) by announcing some supported feature in the core-agent-linux PR and checking it here.

from .exit_codes import EXIT


class AgentType(enum.Enum):
Copy link

@3nprob 3nprob Jun 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Is there some more specific and descriptive name than AgentType/self.type/agent_type? It's very overloadable... In particular self.type can become problematic.

How about for example AgentDomain/self.domain/agent_domain?

@marmarek
Copy link
Member

The test is still running at https://openqa.qubes-os.org/tests/144378, but I see already some exception (this is updating just templates for now):
image
(sorry for the picture, logs will be uploaded when the job completes)

@qubesos-bot
Copy link

qubesos-bot commented Jun 23, 2025

OpenQA test summary

Complete test suite and dependencies: https://openqa.qubes-os.org/tests/overview?distri=qubesos&version=4.3&build=2025121602-4.3&flavor=pull-requests

Test run included the following:

New failures, excluding unstable

Compared to: https://openqa.qubes-os.org/tests/overview?distri=qubesos&version=4.3&build=2025111104-4.3&flavor=update

  • system_tests_network_updates
    • TC_00_Dom0Upgrade_whonix-gateway-18: test_000_update (error)
      subprocess.CalledProcessError: Command 'timeout=120; while ! tor-ci...

Failed tests

1 failures
  • system_tests_network_updates
    • TC_00_Dom0Upgrade_whonix-gateway-18: test_000_update (error)
      subprocess.CalledProcessError: Command 'timeout=120; while ! tor-ci...

Fixed failures

Compared to: https://openqa.qubes-os.org/tests/158999#dependencies
Nothing fixed

Unstable tests

Details

Performance Tests

Performance degradation:

No issues

Remaining performance tests:

No remaining performance tests

@marmarek
Copy link
Member

I tried to play with it and I have some questions/remarks:

  1. How can I make qubes-dom0-update --targets=dom0 display the progress bar instead of full output?
  2. When targeting dom0, it asks me to run qubes-vm-update as root. This usually leads to permission issues with log files, so we've been careful to always call it as normal user. Maybe qubes-vm-update should use sudo internally for updating dom0, instead of calling the whole qubes-vm-update as root from GUI?
  3. Updating dom0 via GUI didn't worked for me (but via qubes-vm-update CLI worked). Fetching updates went fine, but then it took significantly too little time to apply updates (didn't actually install them) and the details section says:
...
Fetching lksctp-tools-0:1.0.20-1.fc41.x86_64 [99.44 KB]
Fetching lua-0:5.4.8-1.fc41.x86_64 [204.02 KB]
Fetching lua-libs-0:5.4.8-1.fc41.x86_64 [134.70 KB]
Fetching tzdata-java-0:2025b-1.fc41.noarch [47.40 KB]


No match for argument: *


                 1:24.8.7.2-2.fc41   qubes-dom0-cached
    1:21.0.7.0.6-2.fc41 qubes-dom0-cached
                      0.1.8-1.fc41        qubes-dom0-cached
                  0.1.12-1.fc41       qubes-dom0-cached
                 1:24.8.7.2-2.fc41   qubes-dom0-cached
            1:24.8.7.2-2.fc41   qubes-dom0-cached
            1:24.8.7.2-2.fc41   qubes-dom0-cached
            1:24.8.7.2-2.fc41   qubes-dom0-cached
            1:24.8.7.2-2.fc41   qubes-dom0-cached
            1:24.8.7.2-2.fc41   qubes-dom0-cached
      1:24.8.7.2-2.fc41   qubes-dom0-cached
   1:24.8.7.2-2.fc41   qubes-dom0-cached
            1:24.8.7.2-2.fc41   qubes-dom0-cached
         1:24.8.7.2-2.fc41   qubes-dom0-cached
         1:24.8.7.2-2.fc41   qubes-dom0-cached
     1:24.8.7.2-2.fc41   qubes-dom0-cached
            1:24.8.7.2-2.fc41   qubes-dom0-cached
        1:24.8.7.2-2.fc41   qubes-dom0-cached
1:24.8.7.2-2.fc41   qubes-dom0-cached
       1:24.8.7.2-2.fc41   qubes-dom0-cached
           1:24.8.7.2-2.fc41   qubes-dom0-cached
             1:24.8.7.2-2.fc41   qubes-dom0-cached
      1:24.8.7.2-2.fc41   qubes-dom0-cached
          1:24.8.7.2-2.fc41   qubes-dom0-cached
             1:24.8.7.2-2.fc41   qubes-dom0-cached
                    0.1.8-1.fc41        qubes-dom0-cached
                1.0.20-1.fc41       qubes-dom0-cached
                         5.4.8-1.fc41        qubes-dom0-cached
                    5.4.8-1.fc41        qubes-dom0-cached
                 2025b-1.fc41        qubes-dom0-cached

PS my approach to get some updates pending is this: qubes-dom0-update --disablerepo=updates libreoffice, and on latter attempts add --action=downgrade.

@marmarek
Copy link
Member

openQArun PR_LABEL=openqa-group-1 TEST=system_tests_network,system_tests_network_updates,system_tests_gui_tools MACHINE=64bit

1 similar comment
@marmarek
Copy link
Member

openQArun PR_LABEL=openqa-group-1 TEST=system_tests_network,system_tests_network_updates,system_tests_gui_tools MACHINE=64bit

@marmarek
Copy link
Member

Is it intentional change? It should fail (trying to update without network access), but it used to fail with different error code.

@piotrbartman
Copy link
Member Author

In dnf5, building the repo sack is more automated. When loading repositories, libdnf5 decides internally whether to refresh the data or if the cache is fresh enough (like dnf cli). This gives us less control over the metadata refresh step, even though it is required to build the repo sack object.

Currently, refresh in our wrapper of dnf5 simply invalidate cache ensures that the cache is updated with fresh data. However, skipping this step does not guarantee that a metadata refresh attempt won't happen anyway (since libdnf5 manages it).
We could force this behavior by modifying the config options to disable cache refreshing, but the question is whether we want or need to do that.

RN the first try of network connection happens during the update step, which explains the different error code.

IMO we should update the test to accept both error codes for all package managers (as is already done for Arch), rather than modifying libdnf5 to mimic apt. Thoughts?

@marmarek
Copy link
Member

Fair enough.

marmarek added a commit to marmarek/qubes-core-admin that referenced this pull request Dec 16, 2025
DNF5 gives less control over when metadata is refreshed. Accept both
error codes in the test.

More details at QubesOS/qubes-core-admin-linux#191 (comment)
@marmarek
Copy link
Member

openQArun PR_LABEL=openqa-group-1 TEST=system_tests_network,system_tests_network_updates,system_tests_gui_tools MACHINE=64bit

Copy link
Member

@marmarek marmarek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides two minor issues, error handling is broken:

dom0 (no updates):   0%|                                                                                                                                                                               | 0/100 [00:06<?, ?it/s]
( ' d o m 0 : e r r :   U s i n g   s y s - f i r e w a l l   a s   U p d a t e V M   f o r   D o m 0 ' , )
( ' d o m 0 : e r r :   D o w n l o a d i n g   u p d a t e s .   T h i s   m a y   t a k e   a   w h i l e . . . ' , )
( ' d o m 0 : e r r :   / b i n / b a s h :   l i n e   1 :   / u s r / l i b / q u b e s / q u b e s - d o w n l o a d - d o m 0 - u p d a t e s - i n i t . s h :   N o   s u c h   f i l e   o r   d i r e c t o r y ' , )
( ' d o m 0 : o u t :   [ 0 ; 3 1 m [ 0 m d o m 0 : o u t :   R e f r e s h i n g   p a c k a g e   i n f o ' , )
( ' d o m 0 : o u t :   s y s - f i r e w a l l : o u t :   ' , )
( ' d o m 0 : o u t :   s y s - f i r e w a l l : e r r :   ' , )
( ' d o m 0 : o u t :   d o m 0 : o u t :   N o t h i n g   t o   d o . ' , )
( ' d o m 0 : e r r :   d o m 0   d o n e   n o _ u p d a t e s ' , )
( < v m u p d a t e . a g e n t . s o u r c e . s t a t u s . F o r m a t e d L i n e   o b j e c t   a t   0 x 7 1 1 8 f 8 2 b 4 c 5 0 > , )
( < v m u p d a t e . a g e n t . s o u r c e . s t a t u s . F o r m a t e d L i n e   o b j e c t   a t   0 x 7 1 1 8 f 8 2 b 4 c 5 0 > , )

[user@dom0 ~]$ echo $?
0

failure of the script (here because it wasn't there, but applies to other cases too) should be reported as an error, not "no updates"

def print(self, *args):
if self.buffered:
self.buffer += ' '.join(args) + '\n'
self.buffer += " ".join(str(args)) + "\n"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't you mean something like map(str, args)?

CMD="script --quiet --return --command '${CMD//\'/\'\\\'\'}' /dev/null"
fi
if [ "$PROGRESS_REPORTING" == "1" ]; then
qvm-run "${QVMRUN_OPTS[@]}" -- "$UPDATEVM" "$CMD" < /dev/null | sed "s/``^/$(hostname):out: /"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
qvm-run "${QVMRUN_OPTS[@]}" -- "$UPDATEVM" "$CMD" < /dev/null | sed "s/``^/$(hostname):out: /"
qvm-run "${QVMRUN_OPTS[@]}" -- "$UPDATEVM" "$CMD" < /dev/null | sed "s/^/$(hostname):out: /"

?

marmarek added a commit to marmarek/qubes-core-admin that referenced this pull request Dec 22, 2025
DNF5 gives less control over when metadata is refreshed. Accept both
error codes in the test.

More details at QubesOS/qubes-core-admin-linux#191 (comment)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pacman plugin needs an updated __init__ arguments too

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, it needs more than that, AttributeError: 'PACMANCLI' object has no attribute 'PROGRESS_REPORTING'

introduce agent_type: for local (dom0), remote (template vms etc.) and proxy (update vm) actions.
`qubes-vm-update` uses `qubes-dom0-update --just-print-progress` for non-interactive update, only small subset of action are supported.
Comment on lines 84 to 86
--quiet)
exec > /dev/null
;;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks salt, see QubesOS/qubes-issues#10543 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the easiest way would be to rename this flag, --silent ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, --silent is not a valid dnf option, so should be safe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants