Guide technique ANYSYS · vérifié le 26 octobre 2026
Sortir de VMware : inventaire, blocages et plan de vagues

Avant de choisir Hyper-V, Nutanix AHV ou Proxmox VE, il faut savoir ce que contient réellement le parc : disques indépendants, RDM, vTPM, snapshots oubliés, dépendances réseau. Ce guide fournit le script d’inventaire PowerCLI que nous utilisons, la matrice des blocages connus par outil de conversion et la méthode de découpage en vagues.
01 / Principe
Pourquoi l’inventaire vient avant l’outil
Les outils de conversion se valent sur les VM simples. Les projets dérapent sur les exceptions : une VM avec un disque en mode indépendant que l’outil refuse, un serveur applicatif dont la licence est liée à l’identifiant BIOS, un cluster à disques partagés qu’aucun convertisseur ne sait déplacer, un poste chiffré par BitLocker dont la clé était scellée dans un vTPM.
Ces cas se détectent à froid, en lecture seule, depuis vCenter. Le choix de l’outil (et parfois de la cible) découle de leur nombre et de leur nature. Un inventaire produit en début de projet sert ensuite de référence pour chaque vague.
- Ce qui est automatisable : configuration matérielle virtuelle, disques, réseau, état des VMware Tools, snapshots, chiffrement.
- Ce qui ne l’est pas : la criticité métier, les fenêtres d’intervention, les dépendances applicatives implicites, les contrats de support. Ces informations se collectent en entretien avec les responsables applicatifs.
02 / Inventaire
Le script d’inventaire PowerCLI
Le script ci-dessous produit un CSV (séparateur point-virgule, lisible directement dans Excel) avec une ligne par VM et une colonne Blockers qui résume les points à traiter. Il ne modifie rien : un compte vCenter en lecture seule suffit.
<#
.SYNOPSIS
Read-only inventory of a vCenter estate before a hypervisor migration.
.DESCRIPTION
Exports one row per VM with the attributes that decide how (and whether) a VM
can be converted: firmware, Secure Boot, vTPM, encryption, VMware Tools state,
CBT, snapshots, disk modes, RDMs, shared/multi-writer disks, SCSI bus sharing,
PCI passthrough, vSAN placement, networks and guest IPs.
A "Blockers" column lists the findings that need a decision before conversion.
The script only reads. It never changes a VM, a snapshot or a setting.
.PARAMETER Server
vCenter FQDN or IP.
.PARAMETER OutFile
CSV path. Defaults to .\vmware-inventory-<date>.csv
.EXAMPLE
.\Get-VMwareMigrationInventory.ps1 -Server vcenter.contoso.local
Prompts for credentials, then writes the CSV in the current folder.
.NOTES
Requires the PowerCLI core module VMware.VimAutomation.Core. PowerCLI 9 and later ship
as VCF.PowerCLI (Install-Module VCF.PowerCLI -Scope CurrentUser); older estates use
VMware.PowerCLI 13.x. Tested with VMware.VimAutomation.Core 13.5.1.
A read-only vCenter role is enough.
Source: ANYSYS ICT, https://www.anysys.be/articles/
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$Server,
[pscredential]$Credential = (Get-Credential -Message "vCenter (read-only account)"),
[string]$OutFile = (Join-Path (Get-Location) ("vmware-inventory-{0:yyyyMMdd-HHmm}.csv" -f (Get-Date)))
)
$ErrorActionPreference = 'Stop'
Import-Module VMware.VimAutomation.Core -ErrorAction Stop
# Do not touch the global PowerCLI configuration: the setting below only lives in this session.
Set-PowerCLIConfiguration -Scope Session -InvalidCertificateAction Warn -Confirm:$false | Out-Null
$vi = Connect-VIServer -Server $Server -Credential $Credential
try {
$rows = foreach ($vm in Get-VM -Server $vi | Sort-Object Name) {
$cfg = $vm.ExtensionData.Config
$devices = @($cfg.Hardware.Device | Where-Object { $null -ne $_ })
$disks = @(Get-HardDisk -VM $vm)
$nics = @(Get-NetworkAdapter -VM $vm)
$snaps = @(Get-Snapshot -VM $vm)
$scsi = @(Get-ScsiController -VM $vm)
$dsNames = @($disks | ForEach-Object { ($_.Filename -split '\]')[0].TrimStart('[') } | Sort-Object -Unique)
$dsTypes = @($dsNames | ForEach-Object { (Get-Datastore -Name $_ -Server $vi).Type } | Sort-Object -Unique)
$independent = @($disks | Where-Object { $_.Persistence -like 'Independent*' })
$rdmPhysical = @($disks | Where-Object { $_.DiskType -eq 'RawPhysical' })
$rdmVirtual = @($disks | Where-Object { $_.DiskType -eq 'RawVirtual' })
$multiWriter = @($disks | Where-Object { $_.ExtensionData.Backing.Sharing -eq 'sharingMultiWriter' })
$busSharing = @($scsi | Where-Object { $_.BusSharingMode -ne 'NoSharing' })
$ideKeys = @($devices | Where-Object { $_ -is [VMware.Vim.VirtualIDEController] } | ForEach-Object Key)
$ideDisks = @($disks | Where-Object { $ideKeys -contains $_.ExtensionData.ControllerKey })
$passthrough = @($devices | Where-Object { $_ -is [VMware.Vim.VirtualPCIPassthrough] })
$vtpm = @($devices | Where-Object { $_.GetType().Name -eq 'VirtualTPM' })
$encrypted = $null -ne $cfg.KeyId
$blockers = [System.Collections.Generic.List[string]]::new()
if ($snaps.Count) { $blockers.Add("snapshots($($snaps.Count))") }
if ($independent.Count) { $blockers.Add('independent-disk') }
if ($rdmPhysical.Count) { $blockers.Add('rdm-physical') }
if ($rdmVirtual.Count) { $blockers.Add('rdm-virtual') }
if ($multiWriter.Count) { $blockers.Add('multi-writer') }
if ($busSharing.Count) { $blockers.Add('scsi-bus-sharing') }
if ($ideDisks.Count) { $blockers.Add('ide-disk') }
if ($passthrough.Count) { $blockers.Add('pci-passthrough') }
if ($vtpm.Count) { $blockers.Add('vtpm') }
if ($encrypted) { $blockers.Add('vm-encryption') }
if ($dsTypes -contains 'vsan') { $blockers.Add('vsan') }
if (-not $cfg.ChangeTrackingEnabled) { $blockers.Add('cbt-off') }
if ($vm.ExtensionData.Guest.ToolsRunningStatus -ne 'guestToolsRunning') { $blockers.Add('tools-not-running') }
[pscustomobject]@{
Name = $vm.Name
PowerState = $vm.PowerState
GuestOS = $vm.ExtensionData.Guest.GuestFullName
ConfiguredOS = $cfg.GuestFullName
HardwareVersion = $vm.HardwareVersion
Firmware = $cfg.Firmware
SecureBoot = [bool]$cfg.BootOptions.EfiSecureBootEnabled
vTPM = [bool]$vtpm.Count
Encrypted = $encrypted
NumCpu = $vm.NumCpu
MemoryGB = $vm.MemoryGB
ProvisionedGB = [math]::Round($vm.ProvisionedSpaceGB, 1)
UsedGB = [math]::Round($vm.UsedSpaceGB, 1)
Disks = $disks.Count
DiskDetail = ($disks | ForEach-Object { '{0}:{1}GB:{2}:{3}' -f $_.Name, [math]::Round($_.CapacityGB, 1), $_.StorageFormat, $_.Persistence }) -join ' | '
ScsiTypes = ($scsi.Type | Sort-Object -Unique) -join ','
Datastores = $dsNames -join ','
DatastoreTypes = $dsTypes -join ','
Snapshots = $snaps.Count
CBT = [bool]$cfg.ChangeTrackingEnabled
ToolsStatus = $vm.ExtensionData.Guest.ToolsRunningStatus
ToolsVersion = $vm.ExtensionData.Guest.ToolsVersionStatus2
Networks = ($nics.NetworkName | Sort-Object -Unique) -join ','
NicTypes = ($nics.Type | Sort-Object -Unique) -join ','
MacAddresses = $nics.MacAddress -join ','
GuestIPs = (@($vm.Guest.IPAddress) -join ',')
Host = $vm.VMHost.Name
Folder = $vm.Folder.Name
Notes = ($vm.Notes -replace '\r?\n', ' ')
Blockers = $blockers -join ';'
}
}
$rows | Export-Csv -Path $OutFile -NoTypeInformation -Encoding UTF8 -Delimiter ';'
Write-Host ("{0} VMs exported to {1}" -f @($rows).Count, $OutFile)
Write-Host ("{0} VMs carry at least one blocker" -f @($rows | Where-Object Blockers).Count)
}
finally {
Disconnect-VIServer -Server $vi -Confirm:$false
}Prérequis : le module VMware.VimAutomation.Core. Depuis PowerCLI 9, l’ensemble est publié sous le nom VCF.PowerCLI ; les environnements plus anciens utilisent VMware.PowerCLI 13.x. Le paramétrage du certificat n’est appliqué qu’à la session et ne modifie pas votre configuration PowerCLI.
Install-Module VCF.PowerCLI -Scope CurrentUser
.\Get-VMwareMigrationInventory.ps1 -Server vcenter.contoso.local
# Filtrer ensuite les VM qui demandent une décision
Import-Csv .\vmware-inventory-*.csv -Delimiter ';' | Where-Object Blockers | Format-Table Name, Blockers -AutoSizeLire la colonne Blockers
| Code | Signification | Ce qu’il faut décider |
|---|---|---|
| snapshots(n) | Snapshots présents sur la VM | Consolider avant la synchronisation. Un snapshot ancien est aussi un risque d’espace disque pendant la réplication. |
| independent-disk | Disque en mode indépendant (persistant ou non) | Repasser en mode dépendant si possible, ou migrer ce disque autrement (copie de données). |
| rdm-physical / rdm-virtual | LUN présentée directement à la VM | Convertir en disque virtuel ou reprendre la LUN côté cible (iSCSI, passthrough). Rarement automatique. |
| multi-writer / scsi-bus-sharing | Disques partagés entre plusieurs VM (clusters, Oracle RAC) | Reconstruire le cluster sur la cible. Aucun convertisseur ne déplace un cluster à disques partagés en l’état. |
| ide-disk | Disque sur contrôleur IDE | SCVMM refuse ces VM ; ailleurs, vérifier le contrôleur de démarrage côté cible. |
| pci-passthrough | Périphérique PCI attribué à la VM | Prévoir l’équivalent matériel côté cible ou garder la VM hors périmètre. |
| vtpm | TPM virtuel présent | Récupérer les clés de récupération BitLocker avant de bouger : l’état du vTPM ne suit pas d’un hyperviseur à l’autre. |
| vm-encryption | VM chiffrée par vSphere | Retirer la stratégie de chiffrement avant conversion : les outils lisent des disques en clair. |
| vsan | Disques sur un datastore vSAN | Plusieurs outils refusent vSAN : déplacer les disques sur un autre datastore (Storage vMotion) avant conversion. |
| cbt-off | Changed Block Tracking désactivé | Les outils à réplication incrémentale en ont besoin : l’activer (cycle d’alimentation requis) ou accepter une copie à froid. |
| tools-not-running | VMware Tools absents ou arrêtés | Les préparations automatiques d’invité (adresse IP, pilotes) en dépendent. |
03 / Compatibilité
Matrice des blocages par outil
Ce tableau ne reprend que ce que les éditeurs documentent explicitement à la date de vérification. « Non documenté » signifie qu’il faut valider le cas sur une VM pilote, pas que cela fonctionne.
| Situation | WAC VM Conversion | SCVMM | Nutanix Move | Proxmox VE import |
|---|---|---|---|---|
| Statut de l’outil | Préversion (conditions des extensions en préversion) | Produit supporté (VMM 2022 UR2+, 2025) | Produit supporté | Produit supporté (PVE 8 et plus) |
| Copie à chaud | Oui (synchro initiale puis delta CBT) | Non : VM source éteinte | Oui (seeding puis incrémental) | Non, mais import « live » possible |
| Datastore vSAN | Non | Non | Non documenté | Non (déplacer les disques avant) |
| Disque indépendant | Non documenté | Non documenté | Non | Non documenté |
| Disques partagés, multi-writer | Non documenté | Non documenté | Non | Non documenté |
| Disque IDE | Non documenté | Non | Non documenté | Non documenté |
| vTPM | Non documenté | Non documenté | vTPM recréé, contenu perdu | État non migrable |
| VM chiffrée | Non documenté | Non documenté | Non documenté | Non (retirer le chiffrement) |
| VMware Tools | Non désinstallés automatiquement | À désinstaller avant | Requis et en cours d’exécution pour la préparation auto | À retirer avant |
| Volumétrie par lot | 10 VM | 10 en parallèle par couple source/cible | Plans de migration | Imports à sérialiser |
04 / Dépendances
Cartographier les dépendances
Une VM qui démarre correctement peut casser une application si l’ordre de bascule ignore ses dépendances : base de données, partage de fichiers, licence réseau, relais SMTP, flux vers une machine qui reste sur VMware pendant plusieurs semaines.
Sur les serveurs Windows, un relevé des connexions établies, répété sur un cycle métier complet (inclure une fin de mois), donne une base factuelle. C’est un échantillon : les flux rares (batch trimestriel, sauvegarde) doivent être confirmés avec les équipes.
# Relevé des connexions établies sur une liste de serveurs (WinRM requis)
$servers = Get-Content .\servers.txt
Invoke-Command -ComputerName $servers -ScriptBlock {
Get-NetTCPConnection -State Established |
Where-Object { $_.RemoteAddress -notmatch '^(127\.|::1)' } |
Select-Object LocalPort, RemoteAddress, RemotePort,
@{ n = 'Process'; e = { (Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName } }
} | Group-Object PSComputerName, RemoteAddress, RemotePort, Process -NoElement |
Sort-Object Count -Descending |
Export-Csv .\flows.csv -NoTypeInformation -Delimiter ';'Côté vSphere, notez aussi ce qui ne voyage pas avec la VM : règles d’affinité et d’anti-affinité DRS, pools de ressources, réservations, tags utilisés par les sauvegardes, alarmes. Chacun doit avoir son équivalent sur la cible, ou être abandonné en connaissance de cause.
05 / Planification
Découper en vagues
- 01
Vague 0, pilote : 5 à 10 VM représentatives (Windows et Linux, BIOS et UEFI, petites et volumineuses), non critiques mais réellement utilisées. Elle valide l’outil, la cible, le réseau et le déroulé.
- 02
Vagues d’infrastructure : serveurs à faibles dépendances (utilitaires, serveurs d’impression, frontaux).
- 03
Vagues applicatives : une application et toutes ses VM ensemble, dans l’ordre des dépendances.
- 04
Dernière vague : bases de données et applications critiques, une fois le déroulé rodé.
Pour chaque vague, écrivez avant la bascule : la fenêtre d’intervention, la personne qui valide côté métier, les tests applicatifs à exécuter, le critère de retour arrière et l’heure limite pour le décider. Ce dernier point est le plus souvent oublié : passé le moment où les utilisateurs écrivent des données sur la nouvelle plateforme, revenir en arrière implique de perdre ou de reprendre ces données.
06 / Continuité
Sauvegardes et retour arrière
- Avant : une sauvegarde réussie et un test de restauration de chaque VM de la vague. Une sauvegarde jamais restaurée n’est pas un plan de retour arrière.
- Pendant : la VM source est éteinte, renommée et ses cartes réseau déconnectées au démarrage, pour qu’un redémarrage accidentel ne crée pas de conflit d’adresse IP.
- Après : les travaux de sauvegarde sont recréés sur la cible ; la première sauvegarde est complète. Les chaînes de l’ancienne plateforme restent consultables pendant leur durée de rétention.
- Conservation : la VM source est gardée éteinte pendant une période définie (deux à quatre semaines est courant) et supprimée seulement après plusieurs sauvegardes réussies sur la cible.
# PowerCLI : neutraliser la VM source juste après la bascule
$vm = Get-VM -Name 'APP01'
Get-NetworkAdapter -VM $vm | Set-NetworkAdapter -StartConnected:$false -Confirm:$false
Set-VM -VM $vm -Name ('APP01-MIGRATED-{0:yyyyMMdd}' -f (Get-Date)) -Confirm:$falseLe guide recette post-migration fournit les scripts de relevé avant/après qui servent de critère objectif de validation.
07 / Contrats
Licences et support éditeur
- Windows Server : la licence se calcule par cœur physique des hôtes cibles. L’édition Standard couvre deux environnements virtuels par hôte entièrement licencié, Datacenter un nombre illimité. Un changement de matériel est l’occasion de refaire ce calcul.
- Logiciels liés au matériel : certaines licences se basent sur l’adresse MAC, l’UUID ou le numéro de série BIOS. Ces identifiants changent ou sont partiellement conservés selon l’outil. Exemple documenté : avec l’extension WAC, le BIOS GUID de la VM Hyper-V ne correspond pas à celui de la source tant qu’il n’est pas mis à jour manuellement (Microsoft fournit un script dans sa FAQ). À vérifier avec l’éditeur avant la vague concernée.
- Appliances virtuelles (pare-feu, équilibreurs, NAS virtuels) : la plupart sont livrées par l’éditeur dans un format par hyperviseur. On redéploie l’image prévue pour la cible et on restaure la configuration.
- Déclarations de support : vérifiez que l’éditeur de chaque application critique supporte la cible (version d’hyperviseur incluse).
08 / Cibles
Choisir la cible
| Cible | Points forts | Points d’attention | Guide |
|---|---|---|---|
| Hyper-V | Inclus dans Windows Server, compétences souvent présentes, intégration Active Directory et Veeam | Outil de conversion officiel en préversion ; cluster et stockage (S2D ou SAN) à concevoir | VMware vers Hyper-V |
| Nutanix AHV | Outil Move mature, plateforme hyperconvergée intégrée, réplication à chaud | Matériel et licences Nutanix, matrice de versions Move à respecter | VMware vers Nutanix AHV |
| Proxmox VE | Licence libre, assistant d’import ESXi intégré, coût d’entrée faible | Support par abonnement, pilotes VirtIO à préparer, compétences Linux requises | VMware vers Proxmox VE |
09 / Références
Sources
- Microsoft : VM Conversion extension, vue d’ensemble
- Microsoft : VM Conversion extension, FAQ et limites
- Microsoft : convertir une VM VMware avec SCVMM
- Nutanix : Move, fonctionnalités non supportées (ESXi)
- Nutanix Community : notes de version Move 6.3.3
- Proxmox : Migrate to Proxmox VE
- Broadcom KB 414772 : désinstallation des VMware Tools sur un autre hyperviseur