From d31ca9eab98917bf4f98d6a9234d73239691719e Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Wed, 2 Sep 2026 04:13:48 -0400 Subject: [PATCH] [UPD] qemu manage : nom de VM sans la version d'une publication continue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Une distribution en publication continue n'a qu'une version, latest : le segment ne distingue aucune VM d'une autre et sort du nom. Une version nommée qui coexiste avec d'autres au catalogue y reste, tumbleweed comme les numérotées. Le nom se relit dans l'autre sens pour retrouver (distro, version) et filtrer les outils par distribution : une VM déjà déployée sous l'ancien nom n'y est plus résolue, la renommer suffit. Vérifié : catalogue rejoué sans collision, aller-retour du nom, 6 tests. --- EN --- A rolling-release distribution has a single version, latest: the segment tells no VM apart from another and leaves the name. A named version that coexists with others in the catalogue stays, tumbleweed as much as the numbered ones. The name is read back the other way to recover (distro, version) and filter tools by distribution: a VM already deployed under the old name no longer resolves there, renaming it is enough. Checked: catalogue replayed without collision, name round trip, 6 tests. Assisted-by: Claude Opus 5 --- script/todo/qemu_manage.py | 12 ++++- test/test_qemu_vm_name.py | 99 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 test/test_qemu_vm_name.py diff --git a/script/todo/qemu_manage.py b/script/todo/qemu_manage.py index 56d47be..53d95a7 100644 --- a/script/todo/qemu_manage.py +++ b/script/todo/qemu_manage.py @@ -2323,8 +2323,16 @@ class QemuManageMixin: """Nom de VM stable pour le parc, ex. erplibre-ubuntu-2404. Ajoute un suffixe d'architecture quand elle diffère de la native de l'hôte (ex. erplibre-ubuntu-2604-s390x sur un hôte amd64) pour éviter les collisions - de noms entre archis et rendre l'archi visible.""" - base = f"erplibre-{distro}-{version.replace('.', '')}" + de noms entre archis et rendre l'archi visible. + + La version « latest » ne figure pas dans le nom : une distribution en + publication continue n'en a qu'une, si bien que le segment ne + distingue aucune VM d'une autre. Une version nommée qui coexiste avec + d'autres au catalogue reste dans le nom, tumbleweed comprise.""" + if version == "latest": + base = f"erplibre-{distro}" + else: + base = f"erplibre-{distro}-{version.replace('.', '')}" if arch and arch != cls._native_arch(): base += f"-{arch}" return base diff --git a/test/test_qemu_vm_name.py b/test/test_qemu_vm_name.py new file mode 100644 index 0000000..5d53468 --- /dev/null +++ b/test/test_qemu_vm_name.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +# © 2021-2026 TechnoLibre (http://www.technolibre.ca) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +"""Le nom de VM du parc : que porte-t-il, et que retrouve-t-on dedans ? + +Le nom se lit dans les deux sens. `_qemu_infra_name` le fabrique à partir de +(distro, version, archi) ; `_qemu_vm_meta` remonte de ce nom à la version en +rejouant le catalogue. Les deux doivent rester en miroir : une règle ajoutée +d'un seul côté rend une VM introuvable dans son propre parc. + +Une distribution en publication continue n'a qu'une version, « latest », qui +ne distingue donc rien — elle sort du nom. Une version nommée qui coexiste +avec d'autres au catalogue, tumbleweed, reste. +""" + +import unittest +from unittest.mock import patch + +from script.todo.todo import TODO + + +class TestInfraName(unittest.TestCase): + """Ce que le nom porte selon la distribution et l'architecture.""" + + def setUp(self): + patcher = patch.object( + TODO, "_native_arch", staticmethod(lambda: "amd64") + ) + patcher.start() + self.addCleanup(patcher.stop) + + def test_rolling_release_drops_the_version(self): + self.assertEqual( + TODO._qemu_infra_name("arch", "latest", "amd64"), "erplibre-arch" + ) + + def test_rolling_release_keeps_the_foreign_arch(self): + self.assertEqual( + TODO._qemu_infra_name("arch", "latest", "arm64"), + "erplibre-arch-arm64", + ) + + def test_named_version_stays(self): + """tumbleweed coexiste avec Leap au catalogue : le nom doit trancher.""" + self.assertEqual( + TODO._qemu_infra_name("opensuse", "tumbleweed", "amd64"), + "erplibre-opensuse-tumbleweed", + ) + + def test_numbered_version_loses_only_its_dots(self): + self.assertEqual( + TODO._qemu_infra_name("ubuntu", "24.04", "amd64"), + "erplibre-ubuntu-2404", + ) + + def test_every_catalogue_entry_yields_a_distinct_name(self): + """Deux entrées du catalogue ne peuvent pas porter le même nom.""" + import importlib.util + from pathlib import Path + + path = ( + Path(__file__).resolve().parent.parent + / "script" + / "qemu" + / "deploy_qemu.py" + ) + spec = importlib.util.spec_from_file_location("deploy_qemu", path) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + + noms = [ + TODO._qemu_infra_name(distro, version, "amd64") + for distro, (versions, _default) in mod.DISTROS.items() + for version in versions + ] + self.assertEqual(len(noms), len(set(noms)), sorted(noms)) + + +class TestNameRoundTrip(unittest.TestCase): + """_qemu_vm_meta retrouve la version que _qemu_infra_name a effacée.""" + + def test_rolling_release_resolves_back_to_latest(self): + todo = TODO() + with patch.object( + TODO, "_qemu_vm_arch", lambda self, name: "amd64" + ), patch.object(TODO, "_native_arch", staticmethod(lambda: "amd64")): + + class Catalogue: + DISTROS = {"arch": (["latest"], "latest")} + + self.assertEqual( + todo._qemu_vm_meta("erplibre-arch", Catalogue()), + ("arch", "latest", "amd64"), + ) + + +if __name__ == "__main__": + unittest.main()