From 05a5edfce594e24db53fff700087373d2775b29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Thu, 28 May 2026 10:04:51 +0200 Subject: [PATCH 1/5] ci: switch ansible-deploy needs from vm-fc42 to vm-fc43 Also retarget the mgmtvm qrexec policy at the default management dispvm template instead of a hardcoded fedora-42-xfce, otherwise admin.vm.List from mgmtvm omits the new fedora-43-xfce template and clone tests against qubes.default_template.name fail with "Cannot clone the 'fedora-43-xfce' because it doesn't exist". --- .gitlab-ci.yml | 2 +- ci/install_mgmtvm.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fdf28f5..b3ec1f0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,7 +33,7 @@ lint: needs: - r4.3:build:host-fc41 - - r4.3:build:vm-fc42 + - r4.3:build:vm-fc43 r4.3:mgmt-host: extends: .qubes-ansible-tests diff --git a/ci/install_mgmtvm.sh b/ci/install_mgmtvm.sh index afe3124..19cd6e7 100755 --- a/ci/install_mgmtvm.sh +++ b/ci/install_mgmtvm.sh @@ -42,7 +42,7 @@ mgmtvm mgmtvm allow target=dom0 mgmtvm sys-net allow target=dom0 mgmtvm sys-firewall allow target=dom0 mgmtvm sys-usb allow target=dom0 -mgmtvm fedora-42-xfce allow target=dom0 +mgmtvm ${default_mgmt_dispvm_template} allow target=dom0 mgmtvm debian-13-xfce allow target=dom0 EOF @@ -50,7 +50,7 @@ cat << EOF >> /etc/qubes/policy.d/include/admin-local-ro mgmtvm sys-net allow target=dom0 mgmtvm sys-firewall allow target=dom0 mgmtvm sys-usb allow target=dom0 -mgmtvm fedora-42-xfce allow target=dom0 +mgmtvm ${default_mgmt_dispvm_template} allow target=dom0 mgmtvm debian-13-xfce allow target=dom0 EOF @@ -66,7 +66,7 @@ admin.vm.Create.TemplateVM * mgmtvm dom0 allow # You may want to allow the ManagementVM to clone some templates to create StandaloneVMs or new TemplateVMs admin.vm.volume.CloneFrom * mgmtvm debian-13-xfce allow target=dom0 -admin.vm.volume.CloneFrom * mgmtvm fedora-42-xfce allow target=dom0 +admin.vm.volume.CloneFrom * mgmtvm ${default_mgmt_dispvm_template} allow target=dom0 # And to remove created ones admin.vm.Remove * mgmtvm @tag:created-by-mgmtvm allow target=dom0 From cf463e72eecf006da32b6a41c9fc6335241937eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Fri, 29 May 2026 09:46:43 +0200 Subject: [PATCH 2/5] ci: use docker-style VM_IMAGE ref for r4.3:mgmt-host --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b3ec1f0..3059464 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,7 +29,7 @@ lint: - ci/codecov-wrapper -F unittests variables: - VM_IMAGE: qubes_4.3_64bit_stable.qcow2 + VM_IMAGE: "qubesos:4.3" needs: - r4.3:build:host-fc41 From 2ba1dd47bdc207d9ccf51c4afdf2d16bbc1cb4bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Wed, 27 May 2026 15:47:09 +0200 Subject: [PATCH 3/5] qubes_proxy: dedupe roles in _add_roles play.get_roles() returns one entry per role usage, so the same role listed twice with different when: makes shutil.copytree fail on the second copy with FileExistsError. --- .../qubesos/security/plugins/strategy/qubes_proxy.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py b/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py index 34dc660..3751473 100644 --- a/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py +++ b/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py @@ -307,8 +307,14 @@ def _add_roles(self, play): dest_roles_path = self.temp_dir / "roles" dest_roles_path.mkdir() + # A play may list the same role multiple times with different + # `when:` conditions; only copy each role directory once. + seen = set() for role in play.get_roles(): role_path = Path(role.get_role_path()) + if role_path.name in seen: + continue + seen.add(role_path.name) shutil.copytree(role_path, dest_roles_path / role_path.name) def _add_rpc_policies(self, dispvm_name): From cdf2da95e16da2f118d13e5f4b0c2eb568c4de2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Tue, 2 Jun 2026 09:56:56 +0200 Subject: [PATCH 4/5] qubes_proxy: make ansible Role._hash picklable --- .../qubesos/security/plugins/strategy/qubes_proxy.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py b/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py index 3751473..810b513 100644 --- a/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py +++ b/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py @@ -22,9 +22,15 @@ import tarfile import tempfile import traceback +import types +from multiprocessing.reduction import ForkingPickler from pathlib import Path +# Ansible stores Role._hash as MappingProxyType. multiprocessing.Pool +# pickles task args through ForkingPickler and mappingproxy isn't picklable. +ForkingPickler.register(types.MappingProxyType, lambda mp: (dict, (dict(mp),))) + import qubesadmin import qubesadmin.events.utils import qubesadmin.exc @@ -392,7 +398,7 @@ def _remove_rpc_policies(self, dispvm_name): ) def _start_mgmt_disp_vm(self): - self.vvv("Lookup for dispvm_mgmt") + self.vvv(f"Lookup for dispvm_mgmt {self.dispvm_mgmt_name}") dispvm = self.app.domains.get(self.dispvm_mgmt_name) self.vvv(f"Found dispvm: {dispvm}") if dispvm is None: From adcdbcbbbd3d6b5ccc7d0954df6c6327343c88a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Pierret=20=28fepitre=29?= Date: Tue, 2 Jun 2026 14:34:47 +0200 Subject: [PATCH 5/5] qubes_proxy: pin multiprocessing.Pool to fork context --- .../qubesos/security/plugins/strategy/qubes_proxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py b/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py index 810b513..b6ed90e 100644 --- a/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py +++ b/ansible_collections/qubesos/security/plugins/strategy/qubes_proxy.py @@ -545,7 +545,7 @@ def proxy_run(self, iterator, play_context): display.vvv( f" Running play {play} " f"with {self._tqm._forks} forks" ) - pool = multiprocessing.Pool(self._tqm._forks) + pool = multiprocessing.get_context("fork").Pool(self._tqm._forks) self.qubes_results = {} for host in self._inventory.get_hosts(play.hosts):