VMware to Proxmox VE migration via Ansible and Ascender
Moving virtual machines off VMware usually means plenty of trial and error. In this demo, Greg Sowell shows an Ascender workflow that pulls two Rocky Linux 9 guests out of vCenter and lands them running on Proxmox VE with no manual steps, then spends the rest of the video explaining how the playbooks work and where they broke along the way.
The workflow chains two playbooks. A pre-configure step runs dracut on each guest to add the virtio SCSI and virtio PCI drivers to the initramfs, since a VM imported with the VMware paravirtual controller never sees its disks, and then shuts the machine down. The migration playbook adds the Proxmox host to the in-memory inventory, exports each VM with VMware's ovftool into a temporary folder, and imports it with qm using a fresh ID from pvesh get /cluster/nextid. Because parallel forks would all receive the same ID, the import task runs once and loops over play_hosts sequentially.
Greg also covers the post-import fixes that took longest to find: setting the CPU type to x86-64-v2, switching the BIOS from SeaBIOS to OVMF with an EFI disk, and adding a network interface, all of which require update_unsafe true in the proxmox_kvm module. The two-VM migration finishes in about five and a half minutes, and he closes with ideas such as exporting to an NFS share and preserving static IPs.
Key takeaways
- A two-step Ascender workflow first preps each Rocky Linux guest with dracut and shuts it down, then exports and imports it into Proxmox.
- Adding virtio_scsi and virtio_pci to the initramfs is required; VMs imported with the VMware paravirtual controller never detect their disks.
- VMware's ovftool exports each VM by its friendly config.name from a datacenter/vm path into a temporary directory on the Proxmox host.
- Because parallel forks would all get the same pvesh nextid value, the qm import task uses run_once and loops over play_hosts one at a time.
- Imported VMs needed CPU type x86-64-v2, OVMF BIOS with an EFI disk and a network interface, which proxmox_kvm only allows with update_unsafe true.
- The complete migration of two VMs from VMware to Proxmox, including shutdown, export, import and boot, took about five and a half minutes.
Questions this video answers
Can I migrate VMs from VMware to Proxmox automatically with Ansible?
Yes. Greg's Ascender workflow prepares each Rocky Linux guest with dracut, shuts it down, exports it with VMware's ovftool, imports it into Proxmox with qm, fixes the hardware settings through the proxmox_kvm module and boots it. Two VMs migrated end to end in roughly five and a half minutes.
Why won't my VMware VM boot after importing it into Proxmox?
In the demo, VMs imported with the VMware paravirtual SCSI controller never saw their drives. The fix was to add the virtio_scsi and virtio_pci drivers to the initramfs with dracut before export, use VirtIO SCSI hardware on Proxmox, change the BIOS from SeaBIOS to OVMF, and create an EFI disk.
Why does the Proxmox import have to run one host at a time?
The playbook asks Proxmox for the next free VM ID with pvesh get /cluster/nextid. Ansible runs five forks by default, so every host would receive the same ID and the imports would collide. Using run_once with a loop over play_hosts processes them sequentially, which is slower but safe.
About this video
In this demo, Greg Sowell will demonstrate how to migrate VMs from VMware to Proxmox VE using automation! Greg explains the process and some of the hiccups he experienced along the way.
This video is part of the Ascender Pro playlist. Browse every CIQ video by product and topic.
Transcript
hey everybody I'm Greg Sowell and welcome to another ciq demo so I'm going to be showing you how to use automation to migrate your VMware VMS straight over to proxmox right it's going to pull them out of that and then stick them into the other without any intervention on your part so this is something I have been fighting with for a little while gone through a lot of uh different desp Spirit things online trying to piece all this together and I'm going to make the easy button for you so that you don't have to do all that so in my demo today I'm going
to be migrating a couple of Rocky Linux hosts oh surprise surprise why would I be doing Rocky but you should be able to migrate any other host now there are going to be some tweaks and tunes you're probably going to have to do for those other uh VMS those other os's but uh this should be a good starting point for you so I'm going to start with Ascender I'm going to fire the automation we'll kind of watch it move and then I will uh then break down all those little nuisances that uh took me a little while to figure out so start the start
here I'm in my template section so I have created a couple of playbooks that this is actually going to be pulling in right here they are the pre-configure and myig great VMS and I have put them together in a workflow so I'm going to go ahead and launch that workflow right here by clicking the little rocket ship as you can see it pops into the job section but the viewer for the uh workflow a workflow allows you to take individual automations and kind of string them together visually and so this one super simple I don't have any Air recovery in a real environment you actually
would so I could if this uh pre-prep stuff were to fail I could uh follow a red line and then do some Air recovery maybe try and repair or rerun or anything like that maybe send a notification in this instance I am just doing the prep work and so it's going to prepare those Linux operating systems first then it's going to move on to the migration section all right so it has completed that prep work now it's moving over to the actual migration section so let's pop into my VMware server I'm going to be migrating this Rocky 9 and Rocky 92 host right here you
View full transcriptHide full transcript
can see that they are currently offline that's because after it preps the system so essentially what it does is it uh connects into my Rocky n systems and it's issuing a d cut command which will set up the init Ram file system uh with the vert IO uh drivers uh so if you don't do that whenever you try and boot it up later it's not actually going to be able to detect the drives and you're going to have a bad time so it does all that and then it shuts them down and we'll walk through that a little bit more in the Playbook section but
for now shut them down and then it's going to do the ovf migration process you can see right down here it says export ovf template it's Compu competing you see both of these racing to uh finish and through the magic of editing you don't have to wait we'll come right back all right the two have just completed you can see down there so now I'm going to move over to my proxmox server and we should momentarily see them starting to pop in all right you already see one popping in 101 Greg Rocky 9-2 so after it runs the ovf tool it's going to pull from
VMware and it's going to put those in a temporary folder and then from there it's going to take those and then issue the uh qm command to import all those inside of proxmox you can see them kind of popping in one and two but there is some post-processing that is required after that um well actually otherwise it's just absolutely not going to work the post processing has to set up a few very specific things in Hardware after it does all of that it's going to then boot the systems up and so we should see that move through in just a moment all right they have
completed provisioning now it should be doing the update on the uh individual configuration so it has to do stuff like set the bios so for me in my proxmox it defaults to C bios we had to change it to uh what EFI and then we had to uh create the EFI drive then we had to uh Set uh the uh processor type and then we also had to what was the last thing oh yes uh set up a network interface and so it should be up and operating let see pop into the console here this was the first one it is still currently loading but
it should be completed just a moment there we are it is up root log into the box really quick let me ping the Google and there you have it it's up and on the network and it's accessible so as you can see that process went Fair really smoothly so if you want to go further down the rabbit hole stick with me here and we will take a look at some of the playbooks that actually made all of that happen all right so taking a look at my get repository here I'll go into the base you can see I really have three files one is going to do the pre-configure work so let's pop in
and see what it's doing and it's ultimately issuing two commands right so it's doing two tasks here it's the uh I don't know how you say this word Dr aut draut Dre cut whatever you want to say I don't know how to properly say it so I'm just going to make up something we'll call it Dr a cut you issue that command and essentially what you're doing is you're adding the vert iozzi and the vert IO PCI to the init uh RAM file system and it's going to be using the kernel name so it's really just going to create that based on the Kernel name
and it's going to assign it uh in the uh the boot folder so that way on boot it'll actually have those uh up and available to you so by default in mine I was using the uh what is it it is the let's take a look at it really quick I'm going to right click I'm going to say edit settings I'm going to take a look at the scuzzy controller it's the VMware par virtual now when I tried just importing those directly and setting it to the VMware par virtual it would never actually like properly boot it would never see the drives so I found
that using vert IO uh inside of proxmox here I'll go to the hardware section on that exact same host so doing the Verio scuzzy actually did make the drives available and uh the system could see them and also by default again I think I mentioned earlier uh the BIOS that comes in is the C bios and so uh we had to change all that but I'll show you that in just a second when we get there let's pop back into the Playbook so that's essentially what it's doing it's prepping the machine now if you are running a different flavor of Linux or maybe you have
some special drivers you need to put in there feel free to put those in right so this is really easily modifiable that's why I made it its own separate little Playbook so it's kind of easy to modify just the pre-prep system for you know whatever host you're connecting to and for this one I would probably put a check so I would Connect into the system see what flavor of os it is if it's Rocky 9 or rocky 8 I would go ahead and issue this command if it was something else I would call maybe a different task file right so it gives you options you could put it all in one you could have individual task files entirely up to you after it does issue that command and it's successful it will go ahead and just shut down the the machine I'm just using the community.
general. shutdown so it'll go ahead and turn it off and I do that because I'm using the ovf tool from VMware who is kind enough to supply that and I am going to be having a company blog post uh that will show you how to actually configure that really I didn't and I absolutely could have done it via automation just to connect into the proxmox go ahead and use the ovf tool like install it and do all that stuff but really you need to go straight to VMware to get the download and so I uh I didn't want to have an automated way to to
bypass any of that stuff I want you to actually go there grab the grab the files that you require and uh get them ready to go really it's essentially you're grabbing uh a tar file you extract it you make the uh ovf tool executable you're done it just runs after that you can also grab the bundle installer and install that if you want um but it's a super simple process again it'll be documented in the blog post so don't worry too much about that so after we do the prep work we actually go into the migrate VMS Playbook so that's what my workflow did first
did the prep work and then it does the migration section so in here I'm setting up and I explained all of this good stuff how this works right here with anchors references uh in the previous um previous one I did on VMware uh control and proxmox control and so essentially it allows you to make a reference to a set of variables and I'm going to be using these for the proxmox sections after that I've got several variables I'm setting up I like to again I like to put all my variables up at the top of the variable section even if I'm overwriting it just so
I can have it up and available and I see all the things and it's just it's more or less a documentation piece for me so it keeps it really simple I do like to try and variabe as many things that are going to change right just to keep it simple for everybody else that's coming along following behind me here but ovf tool the path so I am again just taking the archive extracting it and so I'm telling it this is exactly where the file is uh so that I use that when I run the obf tool command setting up some info on the VMware hosts
um setting what my data center is the VMware directory uh username password and so something I found interesting is whenever you you are and let me scroll down here so you can actually see it whenever you are going to be extracting VMS there's this special kind of hidden path that it's going to follow I know this looks a little bit crazy right here but essentially it's username colon password at the VMware host right here right and then colon the port you're going to be connecting to forward slash and then the name of the data center right so for me it's M&S it's in my test
cluster so it's Capital MNS slvm so if you're doing a VM that for slvm is always going to be in that path in the blog post I'm going to show you how you can actually just kind of browse uh these directories to find how everything follows you don't necessarily have to do that just remember it's uh data center slvm SL and then you just start following your directory structure so for me I had it in a uh folder named Greg SL CQ and that's where my stuff was so I went ahead and filled that out but I digress let's come back to the tasks uh
very first thing I'm going to do is I'm going to be running most of the stuff on the proxmox host itself now you could have these um operate differently so what I'm doing is I'm actually connecting into the proxmox host and I am pulling those into just a temporary folder on the proxmox host so that means I mean essentially that folder structure on there has to be big a lot of people don't really do that right on their host they don't have like a lot of extra storage just for the proxmox OS you you could in this instance and for me it kept this demo
really simple but what you could really be doing is um you could map say an NFS share on a server then you could run the ovf tool command that just puts them all in an NF share or NFS share somewhere and then on the proxmox server server whenever you're running the key uh the qm to like import these ovfs that you've created you're going to import them you're just pulling them from the NFS share uh and then you are sticking into whatever file system is required on there right so you don't necessarily have to store it all right there uh temporarily on your proxmox hos
I'm doing it in this example you could super easily just be running this stuff off to a a network share somewhere that you can then just re uh re access so keep that in mind so first thing I'm doing is I'm setting up uh my inventory so my inventory I'm dynamically pulling it from my V Center so my proxmox host isn't going to be in there uh so I'm injecting that so that it's in the inventory because if it's something in the inventory and you want to access it usually makes sense to go ahead and stick it in the inventory so the very first command
or a task I should say is using the add host module which will stick it in the uh just in memory in the inventory in memory so I've got my proxmox host in there after that I am creating a migration directory on the proxmox host temporary place to store the files then I'm checking in that folder right so this is doing it item potently if the folder already exists it's not going to create it if it doesn't exist it will go ahead and create it um and then it's going to check in there and make sure that I haven't already done the export on this
host if I have it's going to just stop and not do anything it's just essentially going to skip it later on so it's really just making a list of everything it's found in there next I'm hitting a block and the block I'm doing in a block because I'm putting one conditional that will everything under there will adhere to right so instead of putting a win condition on each one of these tasks which I could do instead I'm just putting them in a big block it's just a little bit more efficient to operate that way and it also kind of groups them together logically right so
you can kind of see them makes a little bit simpler so the very first command I'm running here is the ovf tool path uh rather ovf uh the ovf command and so it's using the tool path where it's actually located uh I walked through it just a second ago but it's going to be exporting that individual file and you can see right here are some Shenanigans so in my inventory let me show you in my Ascender I'll go into inventory I'll look for my VMware to proxmox migration I'll pop in here I'll take a look at the host section you can see that it took
um say Greg Rocky 9 underscore and then this unique ID right that way if you have multiple machines that have the same ID uh inside of VMware it actually pins uh this little unique ID on there so that you know they won't override you'll actually be able to specifically know which one well whenever I'm referencing everything I don't want to do it by that exact giant unique ID but if I take a look at this individual host under the variables that it pulls in I can see right config actually let me expand this it makes a little bit easier to find everything I can see
I've got config do name right here this variable greg- rocky9 so that that um that nice name that I'm accustomed to seeing it's right there and so in my playbook here I'm referencing host fars inventory name config do name so I'm really just pulling that nice name so whenever I do the export I'm exporting that nice name uh space period and that will pull the obf and all the files now I could also say the data portion of these drives are actually coming from an NFS here and I just want to reference those I can't just export with the no dis command and it won't
export any of the diss I can then import those into proxmox it will create them and then I can map those additional drives right I can attach those network drives over so I don't necessarily have to grab all the day to pull it like I don't have to pull all the drives and then push them somewhere else I can do the no disk and then map that as well right I don't have it shown here but it would just be a quick simple modification to this to add that additional functionality so it's going to go and it's going to grab those for all the various
hosts the next thing you see it do is it's going to call the import uh ovf task file now I had to do it this way specifically because I am let me open this in a new tab import ovf yml what I'm doing is I'm using a command in here it's this uh uh PES get cluster next ID if you run that command on the command line what it'll do is it'll tell you the next uh VI ID or unique ID that proxmox has if you take a look at proxmox you can see right here where it says um 101 is Greg 9-2 102 is
Greg uh Rocky n right so it's actually got a unique ID for each one of these hosts so that's really how you're going to have to reference it and whenever you create one you have to create it via that unique ID so they have this convenient command that will show you heyy here's the very next unique ID you can use the only problem is um when anible runs a task so say for example it runs this task right here if I just tried to commit like um run the unique ID it's going to by default start with five uh Five Forks right so it's going
to run five host simultaneously well they're all going to issue that command and they're all going to get back the exact same number because they're all processing simultaneously right so they'll all get back 101 for example when it tries to create them there's going to be an overlap uh on that unique ID so we can't do that so which means we have to process them one at a time so what I did is I said hey uh do a run run once and then Loop over play hosts and so in memory all the hosts that are available in this play come under the play hosts
uh variable so I can just kind of loop over them really easy like that so I say run once but Loop over all the hosts and call this task file every time you do it so one at a time they're going to run this so it does slow down processing a little bit right so instead of parallel processing a whole bunch of these at once it's going to do them sequentially but it means that I get to very conveniently use this next ID command so it will pull the next ID so it'll be 101 and then it runs the qm import command so you can
see right here it's running the qm import with that next ID that we just got it will say it's in the folder um config do name right and that's the nice name that we had from VMware so it creates a folder and then it puts the ovf of that exact same name inside that folder and then I am specifying the proxmox storage variable that I've uh assigned in the main Playbook right and that's just going to be what storage device in proxmox am I actually saving this stuff on so it's going to run through process all of that and then uh it will exit the
loop Loop go back in grab the next host and it'll just keep running through this task file until it's completed for all the hosts we have available to us well now that they're actually imported we have to do some modification so in here in the proxmox KVM module I'm essentially setting all of my settings I'm going to do an update so something I learned in here is that um for me it's going to Breck if I don't have the CPU set properly and I had to set it to x86 64 V2 and I added the AES just the regular V2 Sans AES works as well
uh the scuzzy hardware again I had to set it to ver iio uh sky for it to recognize the drives properly the BIOS I had to change it from the C bios to ovmf uh which you know is like the I think they call it ufi in there as well well for ufi to work you have to actually create a ufi disc you can see that down there I set up the network interface as well right here and then uh I set it to update and I tried running that and it failed and I tried all these various iterations maybe my network interface was wrong
or something like that couldn't get it to work and eventually I started reading through all the documentation and line by line and somewhere it happened to I think on the network interface or maybe on the update command itself on update true it actually told me that oh there's a whole chunk of things that it won't actually allow you to update on an existing machine uh for safety reasons because you could theoretically break the machine and lose data and one of those was network interface and another one was an EFI disc it wouldn't let you create those so I learned that if you do update unsafe
true it allows you to go ahead and create those and guess what everything magically started working after that so keep in mind that if you are doing this stuff there is a risk of data loss as you're moving it over um because you're technically you know allowing yourself to uh manipulate drives here so be careful uh on this when I have uh a upate unsafe true on it allows you to do some funky stuff but for us it was absolutely required and most of these commands actually worked just fine it was uh just a couple in there that didn't but essentially once you set those
things up it will be able to boot properly and then the very last task we do is start the VM and very simply we are just cranking through all the host and turning them on so really I think you could see that was pretty succinct there wasn't a whole lot in there I know it seems like a long time because I talked forever but that's just so that you would understand what's going on these various pieces if you actually look at the time of completion on that job we pulled data for 2 VMS uh we extracted their ovfs uh we then imported them let's go
to the job section so how long did it take that workflow to actually process uh about 6 minutes well five and a half or so it was able to migrate to hosts completely from VMware pull them out shut them down push them into prox Mox and crank them on right um so how would I modify this one would potentially be the option to do the no disk where you're just doing stuff from uh NFS shares um when you're pulling ovfs uh you could pull them into an NFS share so that you're not eating up storage on your or proxmox host that could be another option
there another one could be um connecting to the host and grab their Network info and check if they are statically configured IPS if they are just keep that in memory in a variable or you know you could extract those files I you could absolutely do that just pull the configuration file and then whenever you create the network interface again apply that configuration back on the server so that it um it does have the exact same static IP so and the span of I'm guessing if you were doing this on a single box it's probably going to run about three and a half to four minutes
maybe you could completely migrate with exact Network information you know Drive information all that stuff and have it crank back up on the other side so I digress this is the part where I say thank you for watching if you have any questions or comments I'd love to hear them I love suggestions on what you folks would love to see next um how you would tweak or tune the existing stuff you're seeing um just give us feedback I'm always curious on how I can do this stuff better or different um also if you are looking to do some migrations that's a big part of what
we do Professional Services here and so we love to come in build your Ascender cluster out you know have it highly available maybe help you write some playbooks maybe help you do migrations entirely and then we have leave behind of automation like however you want to do it we're here to assist so please reach out and if nothing else happy automating and thanks we'll see you next time bye
Built for scale. Chosen by the world’s best.
2.75M+
Rocky Linux instances
Being used world wide
90%
Of fortune 100 companies
Use CIQ supported technologies
250k
Avg. monthly downloads
Rocky Linux
9
Enterprise products
Spanning the kernel to the orchestrator
Have questions about your infrastructure?
Talk to a CIQ engineer about Rocky Linux, HPC, and AI infrastructure.
