ℹ️ À savoir · En bref
Trois étages, trois outils : installation des hôtes par PXE avec un fichier de réponses, configuration du pool avec Ansible, ressources (stockage, disques, VM) avec Terraform et le provider officiel xenserver/xenserver.
Pour la partie Citrix, on enchaîne avec le provider citrix/citrix (connexion d'hébergement, catalogue MCS, voir TF-04) : toute la chaîne devient du code versionné.
Objectifs de la fiche
- Installer des hôtes XenServer sans intervention.
- Configurer pool, réseau et stockage avec Ansible.
- Créer disques et VM avec Terraform.
- Raccorder le pool à Citrix DaaS en code.
La chaîne complète

| Étage | Outil | Ce qu'il gère |
|---|---|---|
| Installation | PXE + fichier de réponses XML | Disque système, réseau de gestion, mot de passe, fuseau |
| Configuration hôtes / pool | Ansible (xe via SSH) | Jonction au pool, NTP, bonds, VLAN, SR partagés, mises à jour, certificats |
| Ressources | Terraform xenserver/xenserver | SR, VDI, VM (image maître, serveurs d'infrastructure) |
| VM invitées | Ansible community.general.xenserver_guest | Alternative à Terraform pour créer ou modifier des VM |
| Citrix | Terraform citrix/citrix | Connexion d'hébergement XenServer, catalogues MCS, groupes |
1. Installer sans intervention
fichier de réponses (exemple)
<?xml version="1.0"?>
<installation srtype="ext"> <!-- SR local en EXT (provisionnement fin) -->
<primary-disk>nvme0n1</primary-disk>
<keymap>fr</keymap>
<root-password type="hash">$6$…</root-password> <!-- jamais en clair -->
<source type="url">http://repo.corp.local/xenserver9/</source>
<admin-interface hwaddr="aa:bb:cc:00:11:22" proto="static">
<ipaddr>10.10.0.11</ipaddr><subnet>255.255.255.0</subnet><gateway>10.10.0.1</gateway>
</admin-interface>
<name-server>10.0.0.10</name-server>
<hostname>xs01</hostname>
<timezone>Europe/Paris</timezone>
</installation>
⚠️ Piège
Sur XenServer 9, les noms d'interfaces ne sont plus forcés en eth0, eth1 : désigne l'interface de gestion par son adresse MAC (hwaddr) plutôt que par son nom, et fais de même dans tes playbooks.
2. Configurer le pool avec Ansible
playbook (extrait)
# inventory : [xenserver] xs01 xs02 xs03 (connexion SSH root, clé + Ansible Vault)
- name: Rejoindre le pool (hôtes membres)
ansible.builtin.command: >
xe pool-join master-address={{ xs_coordinator }}
master-username=root master-password={{ vault_xs_root_password }}
when: inventory_hostname != groups['xenserver'][0]
no_log: true
register: join
changed_when: join.rc == 0
failed_when: join.rc != 0 and 'already' not in join.stderr
- name: Le SR NFS existe-t-il ?
ansible.builtin.command: xe sr-list name-label=SR-NFS-VDA --minimal
register: sr
changed_when: false
run_once: true
- name: Créer le SR NFS partagé (une seule fois)
ansible.builtin.command: >
xe sr-create type=nfs shared=true content-type=user name-label=SR-NFS-VDA
device-config:server=nas01.corp.local device-config:serverpath=/xs/vda
run_once: true
when: sr.stdout | length == 0
💡 Astuce
Les commandes xe ne sont pas idempotentes : teste d'abord l'état (xe sr-list name-label=… --minimal) et conditionne la création, ou encapsule la logique dans un rôle maison (ANS-02).
Mots de passe root et secrets dans Ansible Vault ou ton coffre ; no_log: true sur toutes les tâches qui les utilisent.
VM avec Ansible
- name: Créer une VM depuis un modèle (module XenAPI, pip install XenAPI)
community.general.xenserver_guest:
hostname: "{{ xs_coordinator }}"
username: root
password: "{{ vault_xs_root_password }}"
name: SRV-ANSIBLE-01
template: "Windows Server 2025 (64-bit)"
state: poweredon
hardware: { num_cpus: 4, memory_mb: 8192 }
disks: [{ size_gb: 80, sr: SR-NFS-VDA }]
networks: [{ name: "VLAN-120-Serveurs" }]
wait_for_ip_address: true
delegate_to: localhost
3. Provisionner avec Terraform
Le provider officiel xenserver/xenserver (version 0.x, mis à jour indépendamment de XenServer) gère notamment les SR, les disques (VDI) et les VM ; il interroge aussi réseaux et hôtes. Il demande Terraform 1.8 ou plus récent.
main.tf (exemple)
terraform {
required_providers {
xenserver = { source = "xenserver/xenserver" }
}
}
provider "xenserver" {
host = "https://xs01.corp.local"
username = "root"
password = var.xs_password # variable sensible, jamais dans le code
ca_cert_path = "certs/pool-ca.pem" # vérification TLS active par défaut (0.3.0+)
}
data "xenserver_sr" "nfs" { name_label = "SR-NFS-VDA" }
data "xenserver_network" "srv" { name_label = "VLAN-120-Serveurs" }
resource "xenserver_vdi" "master_disk" {
name_label = "W25-MASTER-disk"
sr_uuid = data.xenserver_sr.nfs.data_items[0].uuid
virtual_size = 80 * 1024 * 1024 * 1024
}
resource "xenserver_vm" "master" {
name_label = "W25-MASTER"
template_name = "Windows Server 2025 (64-bit)"
static_mem_max = 8 * 1024 * 1024 * 1024
vcpus = 4
boot_mode = "uefi_security" # UEFI + Secure Boot
hard_drive = [{ vdi_uuid = xenserver_vdi.master_disk.id, bootable = true, mode = "RW" }]
network_interface = [{ network_uuid = data.xenserver_network.srv.data_items[0].uuid, device = "0" }]
}
⚠️ Piège
Le provider est jeune : les noms d'attributs peuvent évoluer d'une version 0.x à l'autre. Fige la version (version = "~> 0.3"), lis le changelog avant chaque montée et vérifie le schéma dans le Terraform Registry.
4. Raccorder à Citrix DaaS
provider citrix/citrix
resource "citrix_xenserver_hypervisor" "xs_lille" {
name = "XS9-Lille"
zone = citrix_zone.lille.id
addresses = ["https://xs01.corp.local"]
username = "svc-citrix-xs"
password = var.xs_citrix_password
password_format = "PlainText"
ssl_thumbprints = [var.xs_thumbprint] # empreinte du certificat du pool
}
# Puis : citrix_xenserver_hypervisor_resource_pool (réseau, SR) et citrix_machine_catalog (TF-04)
- Utilise un compte dédié (rôle XenServer minimal adapté à MCS) plutôt que root pour Citrix.
- Si le certificat du pool change (renouvellement), mets à jour l'empreinte, sinon MCS et l'alimentation échouent.
Pièges classiques
| Symptôme | Cause probable | Parade |
|---|---|---|
| Échec TLS du provider ou de Citrix | Certificat auto-signé non approuvé | CA du pool dans ca_cert_path, empreinte côté Citrix ; insecure seulement en labo |
| Playbook qui recrée tout | Commandes xe non idempotentes | Tester l'état avant, changed_when, rôles |
| Interface introuvable sur XS9 | Script basé sur eth0 / eth1 | Sélection par adresse MAC (xe pif-list MAC=…) |
| Plan Terraform qui change sans raison | Attribut modifié par XenCenter ou nouvelle version du provider | Pas de modification manuelle, version du provider figée |
| Secret dans le state | Mot de passe passé en variable classique | Backend chiffré à accès restreint, variables sensibles (TF-03) |
🔷 En contexte Citrix
Avec ta Citrix Platform License, un pool XenServer 9 de recette entièrement décrit en code (Ansible + Terraform + provider Citrix) permet de tester MCS et l'image maître Windows Server 2025 sans toucher à la production.
Stocke le code dans le même dépôt que l'image maître (ANS-03) et les catalogues (TF-04) : un seul pipeline (TF-03, ANS-04) pour tout l'environnement Citrix.
À retenir
- PXE + fichier de réponses pour les hôtes ; interface choisie par adresse MAC sur XS9.
- Ansible pour le pool (xe via SSH) et éventuellement les VM (xenserver_guest).
- Terraform xenserver/xenserver pour SR, VDI, VM ; version figée.
- Provider citrix/citrix pour la connexion d'hébergement et les catalogues.
- Secrets dans Vault / variables sensibles ; TLS vérifié.
Auto-évaluation
Q1. Pourquoi désigner l'interface de gestion par son adresse MAC dans le fichier de réponses XenServer 9 ?
→ Parce que XenServer 9 ne force plus les noms eth0/eth1 : le nom peut changer, l'adresse MAC non.
Q2. Comment rendre idempotente la création d'un SR avec Ansible ?
→ Vérifier son existence (xe sr-list name-label=… --minimal) et ne lancer xe sr-create que s'il n'existe pas, idéalement dans un rôle.
Q3. Quelles ressources du provider Terraform officiel utilises-tu pour créer une VM avec un disque ?
→ xenserver_vdi pour le disque (sur un SR trouvé via la data source xenserver_sr) et xenserver_vm, avec la data source xenserver_network pour la carte réseau.
Q4. Que se passe-t-il côté Citrix si le certificat du pool XenServer est renouvelé ?
→ L'empreinte enregistrée dans la connexion d'hébergement ne correspond plus : MCS et l'alimentation échouent tant qu'elle n'est pas mise à jour.