VMware PowerCLI – Deploy and setup multiple servers

Release date: December 22nd 2022

Welcome to my VMware PowerCLI section. I recently experienced a total crash in my lab and had to redeploy everything. Although it was sad to loose everything, I thought this was a good opportunity to automate as much as possible. The script below depends on a working AD and vCenter, and uses a vSphere Template and a Customization Profile which joins the servers to the domain.

The script below uses a csv file with the following data:

  • vmName (Name of the virtual machine)
  • ServerName (Netbios name of the server)
  • vCPU
  • vRAM
  • vNetwork
  • IP
  • Subnet
  • Gateway
  • Cluster
  • VMFolder
  • Specs (Customization Profile)
  • Template
  • Notes
  • OSType
  • Dns1
  • Dns2

I also use VICredentialStoreItem xml-file to connect to my vCenter Server.

# Define Environment
$viserver = "fqdn-vcenter"
$viuser = Get-VICredentialStoreItem -File "<path to vcenter credentials>.xml" -host $viserver

# Initialize Environment
Import-Module VMware.VimAutomation.Core
Set-PowerCLIConfiguration -Scope User -ParticipateInCeip $false -Confirm:$false
Set-PowerCLIConfiguration -InvalidCertificateAction ignore -Confirm:$false
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false

# Connect vCenter
Connect-viserver -Server $viserver -User $viuser.user -Password $viuser.password
$VMCluster = Get-Cluster -name "Cluster"
$VMCluster | Get-VMHost
$VMHost1 = $VMCluster | Get-VMHost -Name "fqdn ESXi server"
$VMHost1_Datastore = Get-Datastore -Name "ESXi Datastore Name"
$DiskFormat = 'thin' # Options: Thin / Thick / EagerZeroedThick 

# Import csv
$csvFile = "<path to csv-file>.csv"
$DeployVMs = Import-Csv $csvFile

# Deploy VM's
$a = @()

foreach($vm in $DeployVMs){

    Write-host "Deploying VM " -ForegroundColor Green -NoNewline; Write-Host $vm.vmName -ForegroundColor Yellow

    get-OScustomizationspec $vm.specs -server $viserver | get-OScustomizationNicMapping | set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $vm.IP -SubnetMask $vm.subnet -DefaultGateway $vm.gateway -Dns $vm.Dns1, $vm.Dns2

    get-OScustomizationspec $vm.specs -server $viserver | Set-OSCustomizationSpec -NamingScheme fixed -NamingPrefix $vm.serverName

    $vms = New-VM -Name $vm.vmName -VMhost $VMHost1 -Template $vm.Template -OSCustomizationSpec $vm.specs -confirm:$false -Datastore $VMHost1_Datastore -Location $vm.VMFolder -verbose -RunAsync

    $vms | Add-Member -type NoteProperty -name VMName -value $vm.vmName -Force

    $a += $vms
    foreach($task in $a){
        $result = get-task -id $task.id
        $result = get-task -id $task.id
        start-sleep -Seconds 10
        until ($result.State -eq 'Success'){
        if($result.State -eq 'Success' -and ((Get-VM -Id $result.Result).PowerState) -eq 'PoweredOff'  ){
        Get-VM -Id $result.Result | start-vm 

I use this script to deploy all my member server with the correct ip-addresse set. The servers will be domain joined based on the Customization Profile and put in the Computers OU. To proceed I created a script which will automatically move the computer accounts to the correct OU and receive the correct GPO settings, posted here: Microsoft Powershell – Move Computer Accounts to Organizational Units

A BIG thanks to jrodsguitar who have developed a lot of the code in the script above!!

Disclaimer: Every tips/tricks/posting I have published here, is tried and tested in different it-solutions. It is not guaranteed to work everywhere, but is meant as a tip for other users out there. Remember, Google is your friend and don’t be afraid to steal with pride! Feel free to comment below as needed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: