From 83a68fab36e82924ea183a9a2e8385b44d9feb28 Mon Sep 17 00:00:00 2001 From: Ali Mirjamali Date: Mon, 16 Sep 2024 00:23:37 +0330 Subject: [PATCH] Support DNF5 UpdateVM for qvm-template Related: https://github.com/QubesOS/qubes-issues/issues/9244 --- qubesadmin/tests/tools/qvm_template.py | 37 ++++++++++++++++++++++++++ qubesadmin/tools/qvm_template.py | 12 +++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/qubesadmin/tests/tools/qvm_template.py b/qubesadmin/tests/tools/qvm_template.py index e6ee7f77..2b083abc 100644 --- a/qubesadmin/tests/tools/qvm_template.py +++ b/qubesadmin/tests/tools/qvm_template.py @@ -1425,6 +1425,43 @@ def test_120_qrexec_repoquery_success(self, mock_payload): ]) self.assertAllCalled() + @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload') + def test_120_b_qrexec_repoquery_success_dnf5(self, mock_payload): + args = argparse.Namespace(updatevm='test-vm') + mock_payload.return_value = 'str1\nstr2' + self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \ + b'0\x00test-vm class=TemplateVM state=Halted\n' + self.app.expected_service_calls[ + ('test-vm', 'qubes.TemplateSearch')] = \ +b'''qubes-template-debian-12-minimal|0|4.3.0|202405272135|qubes-templates-itl|228848654|1716847042|GPLv3+|http://www.qubes-os.org|Qubes OS template for debian-12-minimal|Qubes OS template for debian-12-minimal.|''' + # The above is actual data from Fedora 41 based UdpateVM (Sep-2024) + res = qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app, + 'qubes-template-debian-12-minimal') + self.assertEqual(res, [ + qubesadmin.tools.qvm_template.Template( + 'debian-12-minimal', + '0', + '4.3.0', + '202405272135', + 'qubes-templates-itl', + 228848654, + datetime.datetime(2024, 5, 27, 21, 57, 22), + 'GPLv3+', + 'http://www.qubes-os.org', + 'Qubes OS template for debian-12-minimal', + 'Qubes OS template for debian-12-minimal.' + ) + ]) + self.assertEqual(self.app.service_calls, [ + ('test-vm', 'qubes.TemplateSearch', + {'filter_esc': True, 'stdout': subprocess.PIPE}), + ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2') + ]) + self.assertEqual(mock_payload.mock_calls, [ + mock.call(args, self.app, 'qubes-template-debian-12-minimal', False) + ]) + self.assertAllCalled() + @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload') def test_121_qrexec_repoquery_refresh_success(self, mock_payload): args = argparse.Namespace(updatevm='test-vm') diff --git a/qubesadmin/tools/qvm_template.py b/qubesadmin/tools/qvm_template.py index bdd44764..2d96f75c 100644 --- a/qubesadmin/tools/qvm_template.py +++ b/qubesadmin/tools/qvm_template.py @@ -550,6 +550,9 @@ def qrexec_repoquery( # This is because if .strip() is used, the .split() will not work. if line == '': continue + # This is specific to DNF5: + if line.endswith('|'): + line = line[:-1] entry = line.split('|') try: # If there is an incorrect number of entries, raise an error @@ -573,9 +576,14 @@ def qrexec_repoquery( raise ValueError dlsize = int(dlsize) # First verify that the date does not look weird, then parse it - if not re.fullmatch(date_re, buildtime): + if re.fullmatch(date_re, buildtime): + buildtime = datetime.datetime.strptime(buildtime, \ + '%Y-%m-%d %H:%M') + elif buildtime.isnumeric(): + # DNF5 provides seconds since epoch + buildtime = datetime.datetime.fromtimestamp(int(buildtime)) + else: raise ValueError - buildtime = datetime.datetime.strptime(buildtime, '%Y-%m-%d %H:%M') # XXX: Perhaps whitelist licenses directly? if not re.fullmatch(licence_re, licence): raise ValueError