Most painless way to mass migrate Windows VMs from Vmware to proxmox?

wallythewalnut

New Member
Mar 12, 2025
4
0
1
So, preface:
We're a manufacturing company with about ~400 Windows VMs, spread across about 10 different site and locations. We're experimenting with Proxmox, and I like what I see. I'm primarily a linux guy, but I can work my way around windows. I have several guys around me who are wizards with windows, but none of them have had much luck.

The issue:

I can migrate a single VM from Vmware to proxmox, no problem. The issue is with the SCSI adapter - The whole "Add a disk, change to sata, boot up, install drivers, activate SCSI disk, shut down, swap to SCSI, boot up" works in a small scale, but that's a LOT of manual work for the large scale. I've got the drivers installed beforehand with no issue, windows just isn't picking them up(unless you do the aforementioned "boot as sata" trick.) All my digging has just found lots of ways to fix this, after the migration, manually. Is there a way to pre-prep the windows environment so that on the first boot, with no manual intervention, it'll swap over to the correct SCSI driver?
 
Sure do - we got the drivers installed ahead of the migration. The problem is that Windows, annoyingly, doesn't seem to want to use them until it boots up successfully, and a SCSI drive is enabled. Fortunately, almost all of our windows VMs have secondary drives for applications and such, so we don't have to worry about creating a new drives for all the VMs.
I've got the process down to this:

Boot with boot drive as SATA, secondary as SCSI
Enable the secondary drive.
Shut down VM
Detach boot drive, re-attach as SCSI
Boot up

It works fine after that. It's just annoying to have to do that for 400 VMs :)
 
I would have believed it should just work...

oh well- this is probably a job for terraform. Since you are predeploying the vm-tools and virtio-net drivers, you can obtain the vm's new address from the proxmox api, feed that to terraform to complete the rest of the operation. Not worth doing for 10 machines but for 400- sure.
 
Windows has to slipstream the drivers into the boot process. You can do that with dism /image:{drive_letter}: /add-driver /driver:{path_to_driver_inf} - this could be done either in a rescue disk (I’ve made one that can run any PowerShell script and then reboots) if you need to rescue from a broken VMware environment or before migration.

Also uninstall the VMware tools before you cancel your VMware contract (but not the drivers), I’ve seen some instances where especially the older VMware tools cannot be uninstalled without being on a VMware host and the uninstaller are now conveniently behind the paywall (it’s not impossible to remove, but a PITA).

The other way of doing it is setting it up with the emulated SATA, install the virtio drivers, attach a dummy (32G) VirtIO disk (you can do this live), the disk will now be recognized and loaded into the boot, stop the machine, remove the dummy disk and swap over the main disk as a VirtIO system and reboot. All this can be scripted too.
 
  • Like
Reactions: david_tao
I would have believed it should just work...

oh well- this is probably a job for terraform. Since you are predeploying the vm-tools and virtio-net drivers, you can obtain the vm's new address from the proxmox api, feed that to terraform to complete the rest of the operation. Not worth doing for 10 machines but for 400- sure.
Ooh, interesting idea. I'll try that - thank you!
 
Just to be clear - the issue isn't so much Migrating from vmware to proxmox(we got that down solid), but rather, Migrating from vmware to proxmox, WITHOUT having to do a whole bunch of manual shenanigans(I think that's the technical term) on the VM afterwards and just get windows to recognize the goddang SCSI drivers beforehand. We're currently exploring the terraform option, though we may end up just biting the bullet and doing them all manually depending on the timing.
 
injection of storage driver into Windows seems can be only done offline ( with dism /image:c:\ /add-driver /driver:...)
a WinPE iso or another temporary Windows VM disk, can be made to do injection automatically.
 
I am facing the same challenge. The migration process from VMware to Proxmox is easy, with "Prepare for the VirtIO" option selected, that uses Sata disks instead of SCSI disks. I could not find an option of injecting the SCSI driver into Pre Boot environment while VM is running(in VMware). The only option to do this step is to use DISM but boot disk has to be offline, or use the approach as mentioned before. It works, but it is somehow inconvenient and it will be a pain if we decide to migrate 500VMs+.
 
Making a Windows VM "injector" (vmid=911 for example),
then Linux script with a loop , from PVE shell :
qm set 911 -scsi2 [migrated boot vdisk] ( hotplug attach works with scsi )
qm guest exec 911 C:\\Windows\\system32\\dism.exe /image:LetterOfDiskAttached: /Add-Driver /Driver:C:\\VirtioDrivers\\SCSI
qm set 911 -delete scsi2
Need to be completed / refined
 
Last edited:
  • Like
Reactions: fba and david_tao
@robertlukan: Are you using the DISM built-in to Windows or the one from the Windows ADK, because there are differences, I know back in the day dism from ADK used to be able to do live insertions, but with Secure Boot stuff they may have removed that loophole.

As many including myself have suggested
- there are fully-automated WinPE CDs/PXE environments, PXE boot for the first time, fix the damn thing with dism offline mode
- boot with the SATA drivers (provided VMware hasn't deleted them, they do in some cases), then attach ANY VirtIO drive (provided you provision the Red Hat drivers through SCCM or so) and remove the VirtIO drive.
- you can do a comparison of the file structure before and after, see what magic Microsoft does to consider it to be in the boot drivers (registry or file location). The drivers must go somewhere, that location is accessible from outside the VM, so whatever dism does, must be possible to do with other tools.
 
Last edited:
@_gabriel
Thanks, was looking for while already for a method like this.

For a test I did it from within windows' rescue mode. Just needed to load the driver via drvload and assign a letter via diskpart and it worked like a charme.
 
Last edited: