Guide technique ANYSYS · vérifié le 26 octobre 2026
VMware vers Hyper-V : plan de migration et PowerShell

Le déroulé complet que nous appliquons pour migrer des VM vSphere vers Hyper-V sur Windows Server 2022 ou 2025 : choix de l’outil, préparation de la cible et des invités, bascule, corrections post-migration et retour arrière, avec les commandes PowerShell correspondantes.
01 / Périmètre
Périmètre et prérequis
Source : vCenter 6.x, 7.x ou 8.x. Cible : Hyper-V sur Windows Server 2022 ou 2025, en hôte seul ou en cluster de basculement (stockage S2D ou SAN). Pour Azure Local, Microsoft oriente vers Azure Migrate et non vers les outils décrits ici.
Ce guide suppose l’inventaire réalisé et les blocages traités : voir Sortir de VMware : inventaire, blocages et plan de vagues.
02 / Outils
Choisir l’outil de conversion
| WAC VM Conversion | SCVMM (New-SCV2V) | Veeam Instant Recovery | |
|---|---|---|---|
| Statut | Extension gratuite en préversion, régie par les conditions de licence des extensions en préversion de Windows Admin Center | Produit supporté ; VMM 2022 UR2 ou plus récent recommandé (conversion jusqu’à quatre fois plus rapide) | Fonction de Veeam Backup & Replication |
| Principe | Copie initiale à chaud, puis delta par CBT ; à la bascule, arrêt de la source et dernier delta | Conversion à froid : la VM source doit être éteinte | La VM démarre sur Hyper-V depuis la sauvegarde VMware, puis ses disques sont migrés vers le stockage de production |
| Interruption | Courte (dernier delta) | Durée de la copie complète | Courte au démarrage, performances réduites jusqu’à la fin de la migration des disques |
| Limites documentées | vCenter 6.x à 8.x ; lots de 10 VM ; pas de vSAN ; pas d’Azure Local ; mémoire configurée en statique ; VMware Tools non désinstallés automatiquement ; BIOS GUID différent de la source | Pas de vSAN ; pas de disques IDE ; VMware Tools désinstallés avant ; 10 conversions parallèles par couple source/destination recommandées | Nécessite des sauvegardes Veeam des VM VMware et la licence correspondante |
| Quand l’utiliser | Petits et moyens parcs, fenêtres courtes, sans SCVMM | Environnements déjà gérés par SCVMM, VM tolérant une copie à froid | Parc déjà sauvegardé par Veeam, besoin de redémarrage rapide |
Prérequis de l’extension WAC
- Passerelle Windows Admin Center version 2410 (build 2.4.12.10) ou plus récente.
- PowerCLI installé sur la passerelle.
- VMware VDDK 8.0.3 exactement, extrait dans
C:\Program Files\WindowsAdminCenter\Service\VDDK. Microsoft indique qu’aucune autre version n’est supportée. - Redistribuables Visual C++ 2013 et 2015.
- Rôle Hyper-V sur la cible, compte membre des administrateurs locaux ou du groupe Administrateurs Hyper-V.
- Pour Linux : pilotes Hyper-V installés avant la migration (Microsoft renvoie aux Linux Integration Services ; sur les distributions récentes, les pilotes sont dans le noyau et doivent être présents dans l’initramfs, voir plus bas).
03 / Cible
Préparer les hôtes Hyper-V
Sur chaque nœud : rôle Hyper-V, clustering si nécessaire, un commutateur virtuel avec association intégrée (SET) pour les VM. Les noms de cartes réseau sont ceux renvoyés par Get-NetAdapter.
# Sur chaque noeud (redémarrage requis)
Install-WindowsFeature -Name Hyper-V, Failover-Clustering -IncludeManagementTools -Restart
# Commutateur SET dédié aux VM (deux cartes physiques)
New-VMSwitch -Name 'SET-VM' -NetAdapterName 'NIC1', 'NIC2' -EnableEmbeddedTeaming $true -AllowManagementOS $false
# Validation avant création du cluster (à exécuter avant toute mise en production)
Test-Cluster -Node 'HV01', 'HV02'
New-Cluster -Name 'HVCL01' -Node 'HV01', 'HV02' -StaticAddress '10.0.10.50'- Réseau : reproduire les VLAN des groupes de ports vSphere (le mapping se fait ensuite VM par VM).
- Stockage : volumes partagés de cluster (CSV) dimensionnés avec la marge nécessaire à la conversion de disques dynamiques en disques fixes, si vous le prévoyez.
- Processeurs : si les nœuds n’ont pas exactement la même génération de CPU, la compatibilité processeur devra être activée sur les VM pour permettre la migration à chaud.
- Sauvegarde : le travail de sauvegarde Hyper-V doit exister avant la première bascule, pas après.
04 / Invités
Préparer les VM sources
Windows
- 01
Prendre un relevé de référence avec
Get-MigrationBaseline.ps1(voir le guide de recette). - 02
Passer la stratégie SAN en
OnlineAllpour que les disques de données ne reviennent pas hors ligne après la conversion. SCVMM documente ce comportement ; il concerne en pratique toute conversion. - 03
Si BitLocker est actif, sauvegarder les mots de passe de récupération : un vTPM ne se transporte pas d’un hyperviseur à l’autre.
- 04
Désinstaller les VMware Tools dans la fenêtre de bascule (voir ci-dessous).
# Dans l'invité, en administrateur
Set-StorageSetting -NewDiskPolicy OnlineAll
Get-StorageSetting | Select-Object NewDiskPolicy
# BitLocker : afficher les protecteurs de récupération à mettre en lieu sûr
Get-BitLockerVolume | ForEach-Object {
$mountPoint = $_.MountPoint
$_.KeyProtector | Where-Object KeyProtectorType -eq 'RecoveryPassword' |
Select-Object @{ n = 'Volume'; e = { $mountPoint } }, KeyProtectorId, RecoveryPassword
}VMware Tools : quand et comment
Broadcom indique que les VMware Tools doivent être désinstallés avant la migration : sur un autre hyperviseur, le programme de désinstallation échoue (erreur MSI 1603, contrôle VM_CheckRequirements). SCVMM l’exige également, et l’extension WAC ne les désinstalle pas automatiquement.
# Dans l'invité : désinstallation silencieuse des VMware Tools (installation MSI)
$tools = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' |
Where-Object DisplayName -eq 'VMware Tools'
if ($tools) {
Start-Process -FilePath msiexec.exe -ArgumentList "/x $($tools.PSChildName) /qn /norestart" -Wait
}Linux
Les pilotes hv_vmbus, hv_storvsc et hv_netvsc doivent être dans l’initramfs avant la conversion, sinon la VM ne trouve pas son disque au démarrage. Les distributions de la famille RHEL génèrent souvent un initramfs « hostonly » qui ne contient que les pilotes du matériel VMware. Le script suivant vérifie, et ajoute sur demande, les pilotes manquants (dracut ou initramfs-tools).
#!/bin/sh
# prepare-linux-initramfs.sh
#
# Checks (default) or adds (--apply) the storage and network drivers a Linux guest
# needs in its initramfs to boot on the target hypervisor, BEFORE the conversion.
# hyperv : hv_vmbus hv_storvsc hv_netvsc
# virtio : virtio_pci virtio_blk virtio_scsi virtio_net (Nutanix AHV, Proxmox VE, KVM)
#
# Supports dracut (RHEL, Rocky, Alma, SUSE, Fedora) and initramfs-tools (Debian, Ubuntu).
# Drivers built into the kernel (=y) need nothing and are reported as such.
#
# Usage: sudo sh prepare-linux-initramfs.sh hyperv # check only
# sudo sh prepare-linux-initramfs.sh virtio --apply # add missing drivers, rebuild
#
# Take a snapshot or a backup first. Rebuilding the initramfs of the running kernel is a
# boot-critical change: keep the previous kernel entry available in the boot menu.
# Source: ANYSYS ICT, https://www.anysys.be/articles/
set -eu
TARGET="${1:-}"
MODE="${2:-check}"
KVER="${KVER:-$(uname -r)}"
case "$TARGET" in
hyperv) MODULES="hv_vmbus hv_storvsc hv_netvsc" ;;
virtio) MODULES="virtio_pci virtio_blk virtio_scsi virtio_net" ;;
*) echo "usage: $0 hyperv|virtio [--apply]" >&2; exit 2 ;;
esac
if command -v dracut >/dev/null 2>&1 && [ ! -d /etc/initramfs-tools ]; then
TOOL=dracut
elif [ -d /etc/initramfs-tools ]; then
TOOL=initramfs-tools
else
echo "Neither dracut nor initramfs-tools found: prepare this guest manually." >&2
exit 3
fi
BUILTIN="/lib/modules/$KVER/modules.builtin"
# RHEL family names the image initramfs-<kver>.img, Debian family initrd.img-<kver>.
if [ -f "/boot/initramfs-$KVER.img" ]; then
IMG="/boot/initramfs-$KVER.img"
else
IMG="/boot/initrd.img-$KVER"
fi
list_initramfs() {
if [ "$TOOL" = dracut ]; then
lsinitrd "$IMG" 2>/dev/null
else
lsinitramfs "$IMG" 2>/dev/null
fi
}
CONTENT="$(list_initramfs || true)"
MISSING=""
for m in $MODULES; do
if [ -f "$BUILTIN" ] && grep -q "/$m.ko" "$BUILTIN"; then
echo "builtin $m"
elif printf '%s\n' "$CONTENT" | grep -q "/$m.ko"; then
echo "present $m"
else
echo "MISSING $m"
MISSING="$MISSING $m"
fi
done
echo "kernel=$KVER tool=$TOOL image=$IMG target=$TARGET"
if [ -z "$MISSING" ]; then
echo "Nothing to do."
exit 0
fi
if [ "$MODE" != "--apply" ]; then
echo "Run again with --apply to add:$MISSING"
exit 1
fi
if [ "$TOOL" = dracut ]; then
CONF="/etc/dracut.conf.d/90-migration-$TARGET.conf"
echo "add_drivers+=\"$MISSING \"" > "$CONF"
echo "wrote $CONF"
dracut -f "$IMG" "$KVER"
else
for m in $MISSING; do
grep -qx "$m" /etc/initramfs-tools/modules || echo "$m" >> /etc/initramfs-tools/modules
done
echo "updated /etc/initramfs-tools/modules"
update-initramfs -u -k "$KVER"
fi
echo "Rebuilt. Verify with: $0 $TARGET"sudo sh prepare-linux-initramfs.sh hyperv # contrôle seul, code retour 1 si un pilote manque
sudo sh prepare-linux-initramfs.sh hyperv --apply # ajoute et reconstruit l'initramfs du noyau courant- Le nom de l’interface réseau change (par exemple ens192 vers eth0) : une configuration NetworkManager ou netplan liée au nom de l’interface ne s’appliquera plus. Liez-la à l’adresse MAC ou préparez le fichier cible.
- VM Linux en génération 2 avec Secure Boot : le modèle
MicrosoftUEFICertificateAuthorityest requis (voir corrections côté hôte).
05 / Bascule
Déroulé de bascule
| Moment | Action | Validation |
|---|---|---|
| J-7 | Synchronisation initiale (WAC) ou test de conversion d’une copie (SCVMM). Relevé de référence dans l’invité. | Synchronisation terminée sans erreur de Change ID |
| J-1 | Sauvegarde complète et test de restauration. Gel des changements applicatifs. Communication aux utilisateurs. | Point de restauration identifié |
| H-0 | Arrêt des services applicatifs, désinstallation des VMware Tools, lancement de la migration (dernier delta) ou arrêt et conversion. | Source éteinte |
| H+0 | Neutraliser la source : cartes réseau non connectées au démarrage, VM renommée. | Source impossible à redémarrer par erreur sur le réseau |
| H+1 | Démarrage sur Hyper-V, corrections invité, relevé après migration et comparaison. | Compare-MigrationBaseline.ps1 sans échec |
| H+2 | Tests applicatifs par le métier. Décision go / no-go avant l’heure limite de retour arrière. | Validation écrite du responsable applicatif |
Pour SCVMM, la conversion se pilote aussi en PowerShell. Exemple minimal à adapter, d’après l’exemple 1 de la documentation New-SCV2V :
# Module VirtualMachineManager, sur un poste disposant de la console VMM
# L'hôte ESXi doit être géré par VMM ; la VM source doit être éteinte
$esxHost = Get-SCVMHost -ComputerName 'esxi01.contoso.local'
$vmHost = Get-SCVMHost -ComputerName 'HV01.contoso.local'
$vm = Get-SCVirtualMachine -VMHost $esxHost -Name 'APP01'
New-SCV2V -VM $vm -VMHost $vmHost -Name 'APP01' -Path 'C:\ClusterStorage\Volume1' -RunAsynchronously06 / Hôte
Corrections côté hôte
Le rapport suivant liste, pour chaque VM, ce qui demande en général une correction après conversion. Il ne modifie rien.
<#
.SYNOPSIS
Read-only health report of virtual machines on a Hyper-V host after a migration.
.DESCRIPTION
One row per VM with what typically needs fixing after a VMware conversion:
generation, configuration version, static vs dynamic memory, processor compatibility
for live migration, Secure Boot template, disk format (dynamic/fixed) and location,
switch / VLAN, MAC mode, integration services turned off, leftover checkpoints,
cluster role and heartbeat. Nothing is changed.
.PARAMETER VMName
One or more VM names. Defaults to every VM on the host.
.EXAMPLE
.\Get-HyperVMigrationReport.ps1 | Out-GridView
.EXAMPLE
.\Get-HyperVMigrationReport.ps1 -VMName APP01,SQL01 | Export-Csv .\hyperv-report.csv -NoTypeInformation -Delimiter ';'
.NOTES
Windows Server 2016 or later with the Hyper-V PowerShell module. Run on the host.
Integration service names are localized: the script reports them as returned.
Source: ANYSYS ICT, https://www.anysys.be/articles/
#>
[CmdletBinding()]
param(
[string[]]$VMName = '*'
)
$ErrorActionPreference = 'Stop'
foreach ($vm in Get-VM -Name $VMName) {
$fw = if ($vm.Generation -eq 2) { Get-VMFirmware -VM $vm } else { $null }
$cpu = Get-VMProcessor -VM $vm
$mem = Get-VMMemory -VM $vm
$nics = @(Get-VMNetworkAdapter -VM $vm)
$hdds = @(Get-VMHardDiskDrive -VM $vm)
$vhds = @($hdds | Where-Object Path | ForEach-Object { Get-VHD -Path $_.Path -ErrorAction SilentlyContinue })
$snaps = @(Get-VMSnapshot -VM $vm)
$isOff = @(Get-VMIntegrationService -VM $vm | Where-Object { -not $_.Enabled } | ForEach-Object Name)
[pscustomobject]@{
Name = $vm.Name
State = $vm.State
Heartbeat = $vm.Heartbeat
Generation = $vm.Generation
ConfigVersion = $vm.Version
Clustered = $vm.IsClustered
vCPU = $cpu.Count
CpuCompatibility = $cpu.CompatibilityForMigrationEnabled
DynamicMemory = $mem.DynamicMemoryEnabled
StartupMemoryGB = [math]::Round($mem.Startup / 1GB, 1)
SecureBoot = if ($fw) { $fw.SecureBoot } else { 'n/a (Gen1)' }
SecureBootTemplate = if ($fw) { $fw.SecureBootTemplate } else { '' }
Disks = $hdds.Count
VhdTypes = ($vhds.VhdType | Sort-Object -Unique) -join ','
VhdPaths = ($hdds.Path) -join ' | '
Switches = ($nics.SwitchName | Sort-Object -Unique) -join ','
Vlans = ($nics | ForEach-Object { $v = Get-VMNetworkAdapterVlan -VMNetworkAdapter $_; '{0}:{1}' -f $v.OperationMode, $v.AccessVlanId }) -join ','
DynamicMac = ($nics.DynamicMacAddressEnabled | Sort-Object -Unique) -join ','
MacAddresses = ($nics.MacAddress) -join ','
GuestIPs = (@($nics.IPAddresses) -join ',')
IntegrationOff = $isOff -join ','
Checkpoints = $snaps.Count
}
}Corrections usuelles. La plupart exigent la VM éteinte :
Stop-VM -Name 'APP01'
# WAC crée la mémoire en statique : réactiver la mémoire dynamique si la charge le permet
Set-VMMemory -VMName 'APP01' -DynamicMemoryEnabled $true -MinimumBytes 2GB -StartupBytes 4GB -MaximumBytes 8GB
# Migration à chaud entre noeuds de générations CPU différentes
Set-VMProcessor -VMName 'APP01' -CompatibilityForMigrationEnabled $true
# VLAN du port de la VM
Set-VMNetworkAdapterVlan -VMName 'APP01' -Access -VlanId 20
# Linux en génération 2 avec Secure Boot
Set-VMFirmware -VMName 'LNX01' -SecureBootTemplate MicrosoftUEFICertificateAuthority
# Disque dynamique vers fixe (espace disque complet requis sur la destination)
Convert-VHD -Path 'C:\ClusterStorage\Volume1\APP01\APP01.vhdx' -DestinationPath 'C:\ClusterStorage\Volume1\APP01\APP01-fixed.vhdx' -VHDType Fixed
Start-VM -Name 'APP01'En cluster, la VM doit résider sur un volume partagé avant d’être rendue hautement disponible :
Move-VMStorage -VMName 'APP01' -DestinationStoragePath 'C:\ClusterStorage\Volume1\APP01'
Add-ClusterVirtualMachineRole -VMName 'APP01'
# Une fois la validation métier signée : supprimer les points de contrôle de travail
Get-VMSnapshot -VMName 'APP01' | Remove-VMSnapshot07 / Invité
Corrections dans l’invité
Trois problèmes reviennent sur presque toutes les VM Windows converties :
- Carte réseau fantôme : l’ancienne carte VMXNET3 reste enregistrée avec son adresse IP statique ; Windows refuse alors d’attribuer la même adresse à la nouvelle carte.
- Disques hors ligne : si la stratégie SAN n’a pas été modifiée avant, les disques de données sont hors ligne.
- Restes des VMware Tools : services et pilotes si la désinstallation n’a pas été faite avant.
# Cartes réseau non présentes (fantômes)
Get-PnpDevice -Class Net | Where-Object Status -eq 'Unknown' | Format-Table FriendlyName, InstanceId -AutoSize
# Suppression (pnputil /remove-device : Windows Server 2022 et versions ultérieures)
pnputil /remove-device "<InstanceId>"
# Disques hors ligne ou en lecture seule
Get-Disk | Where-Object IsOffline | Set-Disk -IsOffline $false
Get-Disk | Where-Object IsReadOnly | Set-Disk -IsReadOnly $falseSur Windows Server 2019 et versions antérieures, la carte fantôme se supprime depuis le Gestionnaire de périphériques (affichage des périphériques cachés). Pour des VMware Tools restés installés, Broadcom recommande d’abord l’utilitaire Microsoft de résolution des problèmes d’installation et de désinstallation, puis en dernier recours le nettoyage manuel de la KB 315629. Ce nettoyage modifie le registre, n’est pas officiellement supporté et ne s’applique qu’après une sauvegarde complète de la VM.
Terminez par la comparaison avec le relevé de référence : recette post-migration Windows.
08 / Retour arrière
Retour arrière
Le retour arrière est simple tant que la source n’a pas été modifiée et que les utilisateurs n’ont pas écrit de données sur la cible. Au-delà, il faut reprendre ces données : c’est pourquoi l’heure limite de décision est fixée dans le plan de vague.
# Sur l'hôte Hyper-V : arrêter la VM migrée et l'isoler du réseau
Stop-VM -Name 'APP01' -Force
Disconnect-VMNetworkAdapter -VMName 'APP01'# Session PowerCLI distincte (Get-VM, Set-VM et Start-VM existent aussi dans le module Hyper-V)
$vm = Get-VM -Name 'APP01-MIGRATED-*'
Set-VM -VM $vm -Name 'APP01' -Confirm:$false
Get-NetworkAdapter -VM $vm | Set-NetworkAdapter -StartConnected:$true -Confirm:$false
Start-VM -VM $vmSi les VMware Tools ont été désinstallés, réinstallez-les depuis la console vSphere pour retrouver le pilote VMXNET3. Ce cas doit avoir été répété sur la VM pilote : c’est la seule manière de connaître la durée réelle d’un retour arrière.
09 / Références
Sources
- Microsoft : VM Conversion extension, vue d’ensemble
- Microsoft : migrer avec l’extension VM Conversion (prérequis)
- Microsoft : FAQ de l’extension VM Conversion
- Microsoft : dépannage de l’extension VM Conversion
- Microsoft : convertir une VM VMware dans VMM
- Microsoft : New-SCV2V
- Veeam : Instant Recovery to Microsoft Hyper-V
- Broadcom KB 414772 : VMware Tools sur un hyperviseur tiers