VMware vSphere Infrastructure build completed, tested and ready for workloads. What’s next? Right, it’s time to create bunch of Windows and Linux VMs for customers! Fastest way to do so – prepare VMware PowerCLI / PowerShell script.
In my case as part of the project I had to build 200+ VMs. Of course we can use Templates in vSphere and Guest OS customization during new VM deployment from Template, still this is boring task… Let’s automate it and create all of them with single PowerCLI / PowerShell script using CSV file as input for VM names and the rest VM specific parameters.
VM list file contains all necessary custom parameters specific for each VM like:
- VM name
- Name of the template which used to clone to VM
- Specification name to customize common VM configurations for given OS type
- Name of the Cluster in vSphere where to put new VM
- Name of the Folder in vSphere where to put new VM
- Datastore name for VM
- Storage policy (in my case we have stretched vSAN configuration and several vSAN policies for different VM types)
- Amount of vCPU
- Amount of RAM
- System disk size
- IP address for VM
- Subnet Mask
- Default Gateway IP
- DNS IP address
- vSphere Port Group name (or NSX Segment name)
Here is example of such CSV file (vm-list.csv):
vmName,templateName,specName,clusterName,vmFolderName,datastoreName,storagepolicyName,numCpu,memSizeGB,systemDiskSizeGB,ipAddr,ipMask,ipGateway,ipDns,portgroupName testwin01,win2019dc-withagents-template,Windows2019-without-domain,Cluster,TST,vsanDatastore,vSAN-Stretched,8,16,200,10.100.1.11,255.255.255.0,10.100.1.1,10.100.1.2,nsx-segment-10.100.1.0 testwin02,win2019dc-withagents-template,Windows2019-without-domain,Cluster,TST,vsanDatastore,vSAN-Stretched,8,16,200,10.100.1.12,255.255.255.0,10.100.1.1,10.100.1.2,nsx-segment-10.100.1.0 testlnx03,redhat92-withagents-template2,Linux-RedHat-9.2-Customization,Cluster,TST,vsanDatastore,vSAN-Stretched,4,8,200,10.100.1.13,255.255.255.0,10.100.1.1,10.100.1.2,nsx-segment-10.100.1.0 testlnx04,redhat92-withagents-template2,Linux-RedHat-9.2-Customization,Cluster,TST,vsanDatastore,vSAN-Stretched,4,8,200,10.100.1.14,255.255.255.0,10.100.1.1,10.100.1.2,nsx-segment-10.100.1.0
VM Customization specification example for Windows and Linux:
Storage policies example:
Once all pre-requisites are done you can run the script. If you run it without parameters, you get the help
Let’s run it once again with csv file as parameter
Ensure CSV file imported correctly and all parameters fit to your needs and press “Enter”
Authenticate to vCenter with account which has admin permissions to vSphere. Make a tea or coffee or even go to lunch (of you have tens or hundreds of VMs to deploy) and relax while script works instead of you.
Once completed you will see your VMs created according to specification, Powered On, connected to the network and IP configuration applied.
Similar result for Linux VMs:
Here is the script. Fill free to update it to your needs if you want.
###################################################################### ##### Deploy VMs from VM_Template with guest OS customization ##### ##### (c) Yevgeniy Steblyanko ##### ###################################################################### $vCenterName = "vc01.lab.local" # vCenter FQDN or IP $param = $args[0] if ($param) { # if parameter has file name defined, continue Write-Host "Importing file: " $param $vmParametersTable = Import-Csv -Path $param -Delimiter "," $vmParametersTable | Format-Table * | Out-String -Width 500 Read-Host "Press ENTER to continue..." $vc = Connect-VIServer -Server $vCenterName if ($vc) { Foreach ($vmParameters in $vmParametersTable) { Write-Host -foregroundcolor "Green" "`nDeploying VM: " $vmParameters.vmName $template = Get-template -Name $vmParameters.templateName $spec = Get-OSCustomizationSpec -Name $vmParameters.specName $cluster = get-cluster $vmParameters.clusterName $datastore = Get-Datastore $vmParameters.datastoreName $storagePolicy = Get-SpbmStoragePolicy $vmParameters.storagepolicyName $tempCustSpecName = "TempCustomSpec-to-be-deleted-after-vm-deployment-" + $vmParameters.vmName + $(Get-Date -Format yyyy-MM-dd-HH-mm-ss) Get-OSCustomizationSpec -Name $vmParameters.specName | New-OSCustomizationSpec -Name $tempCustSpecName if ($vmParameters.specName -Match "linux") { $specTemp = Get-OSCustomizationSpec -Name $tempCustSpecName | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $vmParameters.ipAddr -SubnetMask $vmParameters.ipMask -DefaultGateway $vmParameters.ipGateway Write-Host "`nDNS is not applied on Linux, make it manually" } elseif ($vmParameters.specName -Match "windows") { $specTemp = Get-OSCustomizationSpec -Name $tempCustSpecName | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $vmParameters.ipAddr -SubnetMask $vmParameters.ipMask -DefaultGateway $vmParameters.ipGateway -Dns $vmParameters.ipDns } else { Write-Host -foregroundcolor "Red" "`nOS type not recognized from OS Customization string" } if ($specTemp) { $spec = Get-OSCustomizationSpec -Name $specTemp.spec $vm = New-Vm -Name $vmParameters.vmName -Template $template -OSCustomizationSpec $spec -ResourcePool $cluster -Location $vmParameters.vmFolderName -Datastore $datastore # if VM created successfully, update vCPU, RAM, Storage size if ($vm) { $vm | Set-Vm -MemoryGB $vmParameters.memSizeGB -NumCpu $vmParameters.numCpu -Confirm:$false $vm | Set-Vm -StoragePolicy $storagepolicy -Confirm:$false $portgroup = Get-VDPortgroup -Name $vmParameters.portgroupName $vm | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $portgroup -Confirm:$false $vm | Get-HardDisk | Set-HardDisk -CapacityGB $vmParameters.systemDiskSizeGB -Confirm:$false $spec | Remove-OSCustomizationSpec -Confirm:$false Write-Host -foregroundcolor "Green" "`nVM deployed: " $vmParameters.vmName Start-VM -VM $vm -RunAsync } else { Write-Host -foregroundcolor "Red" "`nVM create error" } } } Disconnect-VIServer -Server $vCenterName -Confirm:$False } else { Write-Host -foregroundcolor "Red" "`nvCenter connect error" } } else { # if parameter not defined, show error and stop Write-Host -foregroundcolor "Red" "`nMissing parameter" Write-Host "define <file>.csv as parameter, example:" Write-Host "bulk-vms-creation-from-template.ps1 vm-list.csv" }
Script was tested and used for Windows 2019 and RedHat Linux 9.2 creation.
Yevgeniy Steblyanko
Latest posts by Yevgeniy Steblyanko (see all)
- Automate bulk Windows and Linux VMs creation from template with Guest OS customization - July 18, 2024
- VMware NSX VPN tunnels statistics collection with PowerShell - February 29, 2024
- vSphere & NSX: Active Directory over LDAPs authentication - February 3, 2022
Hi Yevgeniy Steblyanko,
I try the script and follow the step to create VM Customization Specifications, but I found the Linux RedHat 9 do not have hostname, IP address, subnet mask and gateway, I also use ESXi 8 and Redhat 9.3 to test
Is there something wrong?
Thank You
Hi Mic,
Please check if you have following linux components installed: perl and dbus-tools.
In case both installed then show output on the step like this:
https://i0.wp.com/thevirtualist.org/wp-content/uploads/2024/07/image-4.png?w=1643&ssl=1
Best regards,
Yevgeniy