Deploy multiple VM’s using PowerShell

Introduction  This is just a quick post detailing how to deploy multiple VMware VM’s with ease using PowerShell. It is quick to deploy 1 VM using Templates and OS Customizations in the vSphere Web Client. However, if you have multiple VM’s to deploy this can be tedious. If this sounds like something that could help you please read on…

Outline – Basically I have written a PowerShell script that requires you to input the VM information into a CSV file that gets imported by the script. The script will use the information provided by the CSV to set the various configs for your VM and then proceed to create the VM’s.

CSV – Below is an example of the CSV file that gets imported by the PowerShell script:

vmware2
Example CSV

Script – The PowerShell script is called New-VMFromTemplate.ps1 and can be seen below:

#####################################################################################
#### Script:      New-VMFromTemplate.ps1                                         ####
#### Author:      Callan Halls-Palmer                                            ####
#### Version:     1.0                                                            ####
#### Description: This script will change deploy a VM from a template,           ####
####              start the VM once built and move the AD object.                ####
#####################################################################################
# Import credentials AsSecureString #
$String = "76492d1116743f0423413b16050a5345MgB8AHUAUABpACsAUQB4AG8AQwAxADcAZAA3AEsATQBkAFYAdQBKAEgAbAA2AGcAPQA9AHwAZQA3ADMAMQA5ADEANAAyADcAZgBjAGEAYwA4AGUAOAAwAGYAMQA0ADIAMwBjADQAOA
A3AGYANQA3AGQAMwA0AGQANABhADgAMAA1AGMAYwA3ADUAMQA5ADAAMwA1ADIAMwBlADAAYwA5ADMAMQBiADcANAAzAGEAMwA3ADQANQA4AGIANABlAGIAYQAzAGIAZAA0ADMAMwA3AGIAOAAzAGMAMgAzADMAMAAzAGIAMwA0
AGUAOAAxADUAMAAwADUA"
$key = (2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43,6,6,6,6,6,6,31,33,60,23)
$SecureString = $String | ConvertTo-SecureString -Key $key
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList DELTA\callanhp,$SecureString
# Load PowerCli #
Set-Location "C:\Program Files (x86)\vmware\Infrastructure\PowerCLI\Scripts"
.\Initialize-PowerCLIEnvironment.ps1
# Connect to DEL-vCenter-01 #
Connect-ViServer vCenter01.contoso.com -Credential $Cred
# Set Variables #
$Date = Get-Date -Format dd-MM-yyyy
$VMs = Import-CSV "C:\Users\938077\OneDrive - Clifford Chance LLP\Desktop\Scripts\Kaplan Financial\VMware\xlsx\New-VMFromTemplate.csv"
# Create new VM with static IP #
ForEach ($VM in $VMs){
    $OSSpec = Get-OSCustomizationSpec -Name $vm.customization
    $OSSpecClone = New-OSCustomizationSpec -OSCustomizationSpec $OSSpec -Type NonPersistent
    $Template = Get-Template $vm.template
    $VMHost = Get-VMHost | Select Name,@{N="NumVM";E={($_ | Get-VM).Count}} | Sort-Object NumVM -Descending | Select-Object -Last 1
    $Datastore = Get-Datastore | Where-Object {$_.Name -eq "NFS_Dev_#1_FAS8020" -or $_.Name -eq "NFS_Dev_#3_FAS8020"} | Sort-Object FreeSpaceMB -Descending | Select-Object -First 1
    $nicMapping = Get-OSCustomizationNicMapping -OSCustomizationSpec $OSSpecClone
    $nicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $VM.IP -SubnetMask $VM.SubnetMask -Dns "8.8.8.8,6.6.6.6" -DefaultGateway $VM.DefaultGateway
    New-VM -Name $vm.name -OSCustomizationSpec $OSSpecClone -Template $Template -VMHost $VMHost.Name -Datastore $Datastore.Name -RunAsync
    Start-Sleep -Seconds 60
    $VMName = $VM.Name
    While(Get-Task | Where-Object {$_.Name -eq "CloneVM_Task" -and $_.State -eq "Running"}){
        Write-Host -ForegroundColor Green "Waiting for $VMName to be created"
    }
    Start-VM $VMName
}
# Remove OSSpecClone #
$OSSpecClone_TBD = Get-OSCustomizationSpec -Type NonPersistent
$OSSpecClone_TBD | Remove-OSCustomizationSpec -Confirm:$false
# Disconnect from vCenter01 #
Disconnect-VIServer -Confirm:$False
# Import Active Directory Module #
Import-Module ActiveDirectory
# Wait for Active Directory Objects to appear in Active Directory #
While((Get-ADComputer -Filter {Name -like "*$VMName*"} -SearchBase "OU=_Workstations,DC=contoso,DC=com") -eq $null){
    Write-Host "AD Objects aren't available."
}
# Put newly built DEV-VM's into a variable #
$NewComps = Get-ADComputer -Filter {Name -like "*$VMName*"} -SearchBase "OU=_Workstations,DC=contoso,DC=com" -Credential $Cred
# Move the AD Objects to the Development OU #
$NewComps | Move-ADObject -TargetPath "OU=Development,OU=KUK - Servers,OU=Hardware ***,DC=contoso,DC=com" -Credential $Cred
# Configure Email #
$VMNames = $VMs.Name | Format-List | Out-String
 $body ="
To Administrator,
The following VM's have been deployed:

$VMNames
    
PLEASE DO NOT REPLY TO THIS EMAIL.
   
Regards,
KUK Helpdesk
UK Tel: ###############
# Send E-Mail to Administrators confirming the VM's that have been built #
Send-MailMessage -From vCenterAlerts@contoso.com -To Administrators@contoso.com -Subject "VM's deployed on $Date" -Body $body -SmtpServer 0.0.0.0
# END #

Summary of actions completed by the script:

  1. My Credentials are imported into a Secure String and put into a Variable so that they can be used to automatically sign in to vCenter.
  2. Next, the PowerCLI environment is initialized and then we log in to vCenter using the Credentials that were created in the previous step.
  3. We set the $Date Variable and we also import the CSV file into the $VMs Variable.
  4. Next, we do a “ForEach” loop through the list of VM’s completeing the following:
    • Put the OS Customization from the CSV into the $OSSpec Variable.
    • Clone the OS Customization from the previous step making it nonpersistent.
    • Put the Template from the CSV into the $Template Variable.
    • Set the $VMHost Variable based  on the destination Host with the least number of VM’s.
    • Put the Datastore with the most free space into the $Datastore Variable.
    • Add the custom network settings using the cloned OS Customization from earlier.
    • Create the VM with all of the settings defined in the previous steps.
  5. We then sleep for 60 seconds, allowing enough time to pass so that the “Task” has been registered in vCenter.
  6. We then do a “While” loop until the VM has been created. The script will automatically start the VM once it has finished deploying.
  7. Next, the script deletes any non persistent OS Customizations to clean up.
  8. Disconnect from the vCenter server.
  9. The Script will now send out an automated email detailing the names of the VM’s that have been deployed by the script.

This script is useful if you have a long list of VM’s to deploy. It means you can input the information quickly into the CSV and let PowerShell take care of the excessive clicking! I will write about an alternative PowerShell script which allows you to create VM’s with interactive prompts instead of the referenced CSV file.

Hope this helps!

Thanks for reading and take care.

Callan Halls-Palmer

One thought on “Deploy multiple VM’s using PowerShell

  1. Have this cup of Tea ohhh Sensei, and accept us as your student. Take us with you Morpheus out of The Matrix in the Nabucodonosor…adn we will give you our stimulus checks, do your taxes and vote for your favorite political party.

    Like

Leave a comment