Introduction#
La sauvegarde régulière des configurations réseau est une bonne pratique essentielle. Perdre la configuration d’un switch peut entraîner des heures de reconfiguration manuelle.
Cet article décrit une architecture Ansible fiable pour :
- déployer une VM Windows depuis un template VMware
- récupérer automatiquement son IP DHCP
- établir la connexion WinRM
- basculer vers une IP statique
- reconstruire l’inventaire
- poursuivre la configuration système
Explication rapide du workflow#
- Déploiement de la VM
- Récupération IP DHCP via VMware Tools
- Connexion WinRM initiale
- Bascule IP statique
- Reconstruction inventaire
- Reconnexion WinRM
- Configuration finale
Prérequis#
1
2
3
4
5
|
python3.11 -m venv venv
source venv/bin/activate
pip install ansible pyvmomi pywinrm requests-ntlm
ansible-galaxy collection install community.vmware
ansible-galaxy collection install ansible.windows
|
Architecture du projet#
Arborescence recommandée :
ansible_vmware_winserver2/
├── group_vars/
│ └── vault.yml
├── roles/
│ ├── deploy_vm_windows/
│ │ └── tasks/
│ │ ├── main.yml
│ │ └── deploy_one_vm.yml
│ ├── configure_network/
│ │ └── tasks/
│ │ └── main.yml
│ └── baseline_windows/
│ └── tasks/
│ └── main.yml
├── vars/
│ └── vms.yml
└── site.yml
Fichiers à modifier#
vars/vms.yml#
1
2
3
4
5
6
7
8
9
10
11
|
vms:
- name: SRV-TEST-2025
template: TEMPLATE-WIN2022
datacenter: DC01
datastore: DATASTORE01
network: VLAN_SERVERS
ip: 192.168.1.10
gateway: 192.168.1.1
dns:
- 192.168.1.254
- 8.8.8.8
|
group_vars/vault.yml#
1
2
3
4
|
vcenter_hostname: vcenter.domain.local
vcenter_username: [email protected]
vcenter_password: changeme
windows_admin_password: changeme
|
roles/configure_network/tasks/main.yml#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
- name: Configure static IP
ansible.windows.win_shell: |
$iface = Get-NetIPConfiguration |
Where-Object { $_.IPv4DefaultGateway -ne $null } |
Select-Object -First 1
$ifIndex = $iface.InterfaceIndex
Set-NetIPInterface -InterfaceIndex $ifIndex -Dhcp Disabled
Get-NetIPAddress -InterfaceIndex $ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Remove-NetIPAddress -Confirm:$false
New-NetIPAddress `
-InterfaceIndex $ifIndex `
-IPAddress "{{ vm_ip }}" `
-PrefixLength 23 `
-DefaultGateway "{{ vm_gateway }}"
Set-DnsClientServerAddress `
-InterfaceIndex $ifIndex `
-ServerAddresses {{ vm_dns }}
Set-NetConnectionProfile -InterfaceIndex $ifIndex -NetworkCategory Private
Enable-PSRemoting -Force
ignore_errors: true
|
site.yml#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# PHASE 0 : Déploiement
- name: Deploy Windows VMs on VMware
hosts: localhost
gather_facts: no
vars_files:
- vars/vms.yml
- group_vars/vault.yml
roles:
- deploy_vm_windows
# PHASE 0.5 : Récupération IP DHCP + inventaire dynamique
- name: Get DHCP IP and build inventory
hosts: localhost
gather_facts: no
vars_files:
- vars/vms.yml
- group_vars/vault.yml
tasks:
- name: Wait for VMware Tools + retrieve IP
community.vmware.vmware_guest_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: false
name: "{{ item.name }}"
datacenter: "{{ item.datacenter }}"
loop: "{{ vms }}"
loop_control:
loop_var: item
register: vm_info
until: >
vm_info.instance is defined and
vm_info.instance.ipv4 is defined and
vm_info.instance.ipv4 != ''
retries: 30
delay: 15
- name: Pause for Windows stabilization
ansible.builtin.pause:
seconds: 30
- name: Build dynamic inventory (DHCP IP)
ansible.builtin.add_host:
name: "{{ item.item.name }}"
groups: windows_vms
ansible_host: "{{ item.instance.ipv4 }}"
ansible_user: Administrator
ansible_password: "{{ windows_admin_password }}"
ansible_connection: winrm
ansible_port: 5985
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
vm_ip: "{{ item.item.ip }}"
vm_gateway: "{{ item.item.gateway }}"
vm_dns: "{{ item.item.dns | join(',') }}"
loop: "{{ vm_info.results }}"
# PHASE 1 : WinRM DHCP
- name: Wait for WinRM (DHCP IP)
hosts: windows_vms
gather_facts: no
tasks:
- name: Wait for WinRM ready
ansible.windows.win_ping:
register: result
until: result is success
retries: 40
delay: 10
# PHASE 2 : Changement IP
- name: Configure network (switch to static IP)
hosts: windows_vms
gather_facts: no
roles:
- configure_network
# PHASE 3 : Rebuild inventory
- name: Rebuild inventory with static IP
hosts: localhost
gather_facts: no
vars_files:
- vars/vms.yml
- group_vars/vault.yml
tasks:
- name: Update hosts with static IP
ansible.builtin.add_host:
name: "{{ item.name }}"
groups: windows_vms
ansible_host: "{{ item.ip }}"
ansible_user: Administrator
ansible_password: "{{ windows_admin_password }}"
ansible_connection: winrm
ansible_port: 5985
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
loop: "{{ vms }}"
# PHASE 4 : WinRM statique
- name: Wait for WinRM (static IP)
hosts: windows_vms
gather_facts: no
tasks:
- name: Wait for WinRM after IP change
ansible.windows.win_ping:
register: result
until: result is success
retries: 40
delay: 10
# PHASE 5 : Configuration finale
- name: Configure Windows (post network)
hosts: windows_vms
gather_facts: no
roles:
- baseline_windows
|