log0u7.hyperv: le deuxième inventaire dynamique, cette fois depuis l'hyperviseur
L’inventaire DNS
lit le réseau pour deviner où sont les hôtes. Son frère ne devine pas: log0u7.hyperv
(v1.0.0, publié sur Ansible Galaxy
, MIT) demande à l’hyperviseur. C’est un plugin d’inventaire Ansible (la collection log0u7.hyperv, plugin log0u7.hyperv.inventory) qui construit l’inventaire depuis les machines virtuelles tournant sur un ou plusieurs hôtes Hyper-V, interrogés par WinRM ou PSRP. Deuxième épisode de la série inventaires: même but (la vérité vit quelque part et Ansible doit la lire), chemin de lecture opposé.
Le plugin, en 182 lignes
plugins/inventory/inventory.py fait 182 lignes et la plupart des décisions de design sont les deux mots après la déclaration de classe: il hérite de BaseInventoryPlugin, Cacheable et Constructable, les mixins natifs d’Ansible. Pas de cache maison (le fragment inventory_cache plus n’importe quel plugin de cache marchent d’emblée), pas de grouping maison (compose, groups et keyed_groups du fragment constructed s’appliquent à l’inventaire comme à n’importe quel autre).
La vraie requête Hyper-V vit dans plugins/module_utils/hyperv.py (360 lignes): un bloc PowerShell embarqué, foreach ($vm in @(Get-VM)) qui parcourt les VMs et leurs adaptateurs réseau, sérialisé en retour vers Python. Le choix de transport (winrm par défaut, psrp en alternative) sélectionne pywinrm ou pypsrp sur le nœud de contrôle; les ports 5985/5986 font le reste.
Ce que chaque VM devient
Les hostvars portent les faits qui comptent pour l’automatisation: ansible_host (IPv4 primaire, la cible de connexion), hyperv_state (running, stopped…), hyperv_cpu_count, hyperv_memory_mb (arrondi en dessous depuis les octets), hyperv_network_adapters (liste de MAC), hyperv_notes (le champ description de la VM, nullable), hyperv_host et hyperv_custom_tags (tags VM définis par l’utilisateur, aplatis en dict).
Les groupes viennent en trois espèces, tous construits automatiquement: un par état (running…), un par hôte Hyper-V (hyperv_host_hv01), et, quand group_by_tags: true, un par clé de tag custom (tag_<key>). Les questions d’une flotte du type “quelles VMs tournent sur quel hyperviseur, lesquelles sont arrêtées, lesquelles portent le tag prod” deviennent des noms de groupes.
Les identifiants passent par lookup('env', 'ANSIBLE_USER') / ANSIBLE_PASSWORD: la source d’inventaire reste committable, le secret jamais. La doc livre un docs/security_guardrails.md à côté, la même discipline de mise en garde honnête que la collection DNS.
Ce qui diffère de l’inventaire DNS
Même série, donc les deltas sont la partie intéressante:
- Fraîcheur vs autorité. Le DNS répond “qu’est-ce que le réseau dit que la flotte est”; Hyper-V répond “qu’est-ce qui existe vraiment maintenant, allumé ou pas”. Les VMs arrêtées apparaissent avec
hyperv_state: stopped; le DNS ne peut pas voir une machine éteinte. - Coût de requête. Le DNS se parallélise trivialement avec des résolveurs par thread; Hyper-V, c’est une session PSRP par hôte, séquentielle par hôte mais parallèle entre hôtes. Le cache compte plus ici: un
cache_timeoutde 5 minutes transforme chaque run Ansible en un aller-retour WinRM par hôte. - Modèle de confiance. Les métadonnées DNS sont publiques par défaut (avec les garde-fous documentés); les identifiants Hyper-V sont privés par défaut et ne voyagent que par env lookups et 5986 chiffré.
- Distribution. La collection DNS livre un convertisseur de zone pour la migration; celle-ci n’en a besoin d’aucun: l’hyperviseur est la source d’inventaire, il n’y a rien à convertir.
L’hyperviseur sait aussi
- Les mixins
Cacheable/Constructablesont tout le contrat. Les hériter et le plugin se comporte comme un citoyen de première classe; les sauter et vous réimplémenterez le cache mal. - Interrogez ce qui possède la vérité. Pour des flottes de VMs, c’est l’hyperviseur, pas un protocole réseau qui a peut-être vu la machine booter.
- Les env lookups sont la convention des identifiants. Les sources d’inventaire Ansible se committent; le plugin doit rendre ça sûr par construction.
- Un plugin d’inventaire de 182 lignes suffit quand les mixins portent le travail de framework. Les 360 lignes de PowerShell dans
module_utilssont là où le domaine vit vraiment.
[edit: 2026] L’implémentation Ansible de tout ceci: le rôle hyperv .