I’ve gotten some great feedback from my original PowerShell/PowerCLI script to deploy multiple VMs asynchronously via a CSV file found here. I decided a minor update was needed to employ these new ideas along with a few I had myself.
One of those ideas was to require the usage of the new PowerCLI 5.5 R2 features which allows the script to run without the need for a 32bit PowerShell console.
Changes include:
- Cleaned up code / Minor bug fixes
- Added CSV field descriptions to notes section
- Removed requirement for 32bit PowerShell
- Added requirement for PowerCLI 5.5 R2 or later
- Added Boot parameter to determine whether or not to power on new VMs
- Added OS Customization Spec to CSV (previously was hard coded in user variables)
- Fixed logic for vSS vs vDS – Added parameter to CSV
- Added ability to use DHCP instead of just static IPs
- Renamed a few CSV fields to better describe parameter
- Added progress bar to indicate status
I also thought it would be a good idea to describe how to setup and run the script as there are a few components that need to be in place for everything to run smoothly. If you happen to have run v1 of the script, you’ll need to create a new DeployVM.csv as some fields have been added and others changed.
In order to run the script, three components need to be setup prior.
1) OS Customization Spec
I won’t go into great detail about what a OS Customization Spec is but I did want to point out a few helpful items. Essentially, we need to create a Custom Spec that we will then use as a template of sorts. I like to have one set aside specifically for the script to use.
For both Windows and Linux you’ll want to set the Computer Name as shown here:
Also, set the Network as shown:
You can then setup the remaining details as it fits your needs.
A note on Linux – you’ll need to set the DNS servers in the Custom Spec as they are not able to be modified via the Set-OSCustomizationNicMapping cmdlet.
Lastly, ensure that your OS is supported via OS Customization Spec as all are not (even if they are supported as a guest OS in VMware – for example Windows 2000 and CentOS are two examples that are not supported)
2) VM Template
This one is pretty self-explanatory – you’ll need a template to clone for your new VM.
3) DeployVM.csv
This is where the script receives all the information that you provide to build the new VMs. As the field descriptions have been added to the script, I won’t go over all of them here.
It’s worth noting that the script can create a blank CSV for you by issuing the following command:
.\DeployVM.ps1 -createcsv
This will create the DeployVM.csv file in the same directory as the script.
Running the script
Once you have tested the script and have everything in place, it’s easy to reuse over again as you’ll just need to update the DeployVM.csv with a few parameters. For ease of use you can get to a point where a single one-liner will fire off the script like so:
.\DeployVM.ps1 -csvfile E:\DeployVM\DeployVM.csv -vcenter vcname -auto
Logging
The last point to mention is that a directory is created to store a log of the actions as well as a folder to store a copy of the DeployVM.csv so you can keep track of who has done what and when. These folders are created in the same directory in which the script is run.
Enjoy!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Deploy Multiple VMs to vCenter | |
.DESCRIPTION | |
VMs are deployed asynchronously based on a pre-configured csv file (DeployVM.csv) | |
.PARAMETER csvfile | |
Path to DeployVM.csv file with new VM info | |
.PARAMETER vCenter | |
vCenter Server FQDN or IP | |
.PARAMETER auto | |
Will allow script to run with no review or confirmation | |
.PARAMETER createcsv | |
Generates a blank csv file – DeployVM.csv | |
.EXAMPLE | |
.\DeployVM.ps1 | |
Runs DeployVM | |
.EXAMPLE | |
.\DeployVM.ps1 -vcenter my.vcenter.address | |
Runs DeployVM specifying vCenter address | |
.EXAMPLE | |
.\DeployVM.ps1 -csvfile "E:\Scripts\Deploy\DeployVM.csv" -vcenter my.vcenter.address -auto | |
Runs DeployVM specifying path to csv file, vCenter address and no confirmation | |
.EXAMPLE | |
.\DeployVM.ps1 -createcsv | |
Creates a new/blank DeployVM.csv file in same directory as script | |
.NOTES | |
Author: Shawn Masterson | |
Created: May 2014 | |
Version: 1.2.1 | |
REQUIREMENTS | |
PowerShell v3 or greater | |
vCenter (tested on 5.1/5.5) | |
PowerCLI 5.5 R2 or later | |
CSV File – VM info with the following headers | |
Name, Boot, OSType, Template, CustSpec, Folder, ResourcePool, CPU, RAM, Disk2, Disk3, Disk4, Datastore, DiskStorageFormat, NetType, Network, DHCP, IPAddress, SubnetMask, Gateway, pDNS, sDNS, Notes | |
Must be named DeployVM.csv | |
Can be created with -createcsv switch | |
CSV Field Definitions | |
Name – Name of new VM | |
Boot – Determines whether or not to boot the VM – Must be 'true' or 'false' | |
OSType – Must be 'Windows' or 'Linux' | |
Template – Name of existing template to clone | |
CustSpec – Name of existing OS Customiation Spec to use | |
Folder – Folder in which to place VM in vCenter (optional) | |
ResourcePool – VM placement – can be a reasource pool, host or a cluster | |
CPU – Number of vCPU | |
RAM – Amount of RAM | |
Disk2 – Size of additional disk to add (GB)(optional) | |
Disk3 – Size of additional disk to add (GB)(optional) | |
Disk4 – Size of additional disk to add (GB)(optional) | |
Datastore – Datastore placement – Can be a datastore or datastore cluster | |
DiskStorageFormat – Disk storage format – Must be 'Thin', 'Thick' or 'EagerZeroedThick' | |
NetType – vSwitch type – Must be 'vSS' or 'vDS' | |
Network – Network/Port Group to connect NIC | |
DHCP – Use DHCP – Must be 'true' or 'false' | |
IPAddress – IP Address for NIC | |
SubnetMask – Subnet Mask for NIC | |
Gateway – Gateway for NIC | |
pDNS – Primary DNS (Windows Only) | |
sDNS – Secondary NIC (Windows Only) | |
Notes – Description applied to the vCenter Notes field on VM | |
CREDITS | |
Handling New-VM Async – LucD – @LucD22 | |
http://www.lucd.info/2010/02/21/about-async-tasks-the-get-task-cmdlet-and-a-hash-table/ | |
USE AT YOUR OWN RISK! | |
.LINK | |
http://blog.smasterson.com/2014/05/21/deploying-multiple-vms-via-powercli-updated-v1-2/ | |
#> | |
#requires –Version 3 | |
#——————————————————————– | |
# Parameters | |
param ( | |
[parameter(Mandatory=$false)] | |
[string]$csvfile, | |
[parameter(Mandatory=$false)] | |
[string]$vcenter, | |
[parameter(Mandatory=$false)] | |
[switch]$auto, | |
[parameter(Mandatory=$false)] | |
[switch]$createcsv | |
) | |
#——————————————————————– | |
# User Defined Variables | |
#——————————————————————– | |
# Static Variables | |
$scriptName = "DeployVM" | |
$scriptVer = "1.2.1" | |
$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent | |
$starttime = Get-Date -uformat "%m-%d-%Y %I:%M:%S" | |
$logDir = $scriptDir + "\Logs\" | |
$logfile = $logDir + $scriptName + "_" + (Get-Date -uformat %m-%d-%Y_%I-%M-%S) + "_" + $env:username + ".txt" | |
$deployedDir = $scriptDir + "\Deployed\" | |
$deployedFile = $deployedDir + "DeployVM_" + (Get-Date -uformat %m-%d-%Y_%I-%M-%S) + "_" + $env:username + ".csv" | |
$exportpath = $scriptDir + "\DeployVM.csv" | |
$headers = "" | Select-Object Name, Boot, OSType, Template, CustSpec, Folder, ResourcePool, CPU, RAM, Disk2, Disk3, Disk4, Datastore, DiskStorageFormat, NetType, Network, DHCP, IPAddress, SubnetMask, Gateway, pDNS, sDNS, Notes | |
$taskTab = @{} | |
#——————————————————————– | |
# Load Snap-ins | |
# Add VMware snap-in if required | |
If ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null) {add-pssnapin VMware.VimAutomation.Core} | |
#——————————————————————– | |
# Functions | |
Function Out-Log { | |
Param( | |
[Parameter(Mandatory=$true)][string]$LineValue, | |
[Parameter(Mandatory=$false)][string]$fcolor = "White" | |
) | |
Add-Content -Path $logfile -Value $LineValue | |
Write-Host $LineValue -ForegroundColor $fcolor | |
} | |
Function Read-OpenFileDialog([string]$WindowTitle, [string]$InitialDirectory, [string]$Filter = "All files (*.*)|*.*", [switch]$AllowMultiSelect) | |
{ | |
Add-Type -AssemblyName System.Windows.Forms | |
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog | |
$openFileDialog.Title = $WindowTitle | |
if (![string]::IsNullOrWhiteSpace($InitialDirectory)) { $openFileDialog.InitialDirectory = $InitialDirectory } | |
$openFileDialog.Filter = $Filter | |
if ($AllowMultiSelect) { $openFileDialog.MultiSelect = $true } | |
$openFileDialog.ShowHelp = $true # Without this line the ShowDialog() function may hang depending on system configuration and running from console vs. ISE. | |
$openFileDialog.ShowDialog() > $null | |
if ($AllowMultiSelect) { return $openFileDialog.Filenames } else { return $openFileDialog.Filename } | |
} | |
#——————————————————————– | |
# Main Procedures | |
# Start Logging | |
Clear-Host | |
If (!(Test-Path $logDir)) {New-Item -ItemType directory -Path $logDir | Out-Null} | |
Out-Log "**************************************************************************************" | |
Out-Log "$scriptName`tVer:$scriptVer`t`t`t`tStart Time:`t$starttime" | |
Out-Log "**************************************************************************************`n" | |
# If requested, create DeployVM.csv and exit | |
If ($createcsv) { | |
If (Test-Path $exportpath) { | |
Out-Log "`n$exportpath Already Exists!`n" "Red" | |
Exit | |
} Else { | |
Out-Log "`nCreating $exportpath`n" "Yellow" | |
$headers | Export-Csv $exportpath -NoTypeInformation | |
Out-Log "Done!`n" | |
Exit | |
} | |
} | |
# Ensure PowerCLI is at least version 5.5 R2 (Build 1649237) | |
If ((Get-PowerCLIVersion).Build -lt 1649237) { | |
Out-Log "Error: DeployVM script requires PowerCLI version 5.5 R2 (Build 1649237) or later" "Red" | |
Out-Log "PowerCLI Version Detected: $((Get-PowerCLIVersion).UserFriendlyVersion)" "Red" | |
Out-Log "Exiting…`n`n" "Red" | |
Exit | |
} | |
# Test to ensure csv file is available | |
If ($csvfile -eq "" -or !(Test-Path $csvfile) -or !$csvfile.EndsWith("DeployVM.csv")) { | |
Out-Log "Path to DeployVM.csv not specified…prompting`n" "Yellow" | |
$csvfile = Read-OpenFileDialog "Locate DeployVM.csv" "C:\" "DeployVM.csv|DeployVM.csv" | |
} | |
If ($csvfile -eq "" -or !(Test-Path $csvfile) -or !$csvfile.EndsWith("DeployVM.csv")) { | |
Out-Log "`nStill can't find it…I give up" "Red" | |
Out-Log "Exiting…" "Red" | |
Exit | |
} | |
Out-Log "Using $csvfile`n" "Yellow" | |
# Make copy of DeployVM.csv | |
If (!(Test-Path $deployedDir)) {New-Item -ItemType directory -Path $deployedDir | Out-Null} | |
Copy-Item $csvfile -Destination $deployedFile | Out-Null | |
# Import VMs from csv | |
$newVMs = Import-Csv $csvfile | |
$newVMs = $newVMs | Where {$_.Name -ne ""} | |
[INT]$totalVMs = @($newVMs).count | |
Out-Log "New VMs to create: $totalVMs" "Yellow" | |
# Check to ensure csv is populated | |
If ($totalVMs -lt 1) { | |
Out-Log "`nError: No entries found in DeployVM.csv" "Red" | |
Out-Log "Exiting…`n" "Red" | |
Exit | |
} | |
# Show input and ask for confirmation, unless -auto was used | |
If (!$auto) { | |
$newVMs | Out-GridView -Title "VMs to be Created" | |
$continue = Read-Host "`nContinue (y/n)?" | |
If ($continue -notmatch "y") { | |
Out-Log "Exiting…" "Red" | |
Exit | |
} | |
} | |
# Connect to vCenter server | |
If ($vcenter -eq "") {$vcenter = Read-Host "`nEnter vCenter server FQDN or IP"} | |
Try { | |
Out-Log "`nConnecting to vCenter – $vcenter`n`n" "Yellow" | |
Connect-VIServer $vcenter -EA Stop | Out-Null | |
} Catch { | |
Out-Log "`r`n`r`nUnable to connect to $vcenter" "Red" | |
Out-Log "Exiting…`r`n`r`n" "Red" | |
Exit | |
} | |
# Start provisioning VMs | |
$v = 0 | |
Out-Log "Deploying VMs`n" "Yellow" | |
Foreach ($VM in $newVMs) { | |
$Error.Clear() | |
$vmName = $VM.Name | |
$v++ | |
$vmStatus = "[{0} of {1}] {2}" -f $v, $totalVMs, $vmName | |
Write-Progress -Activity "Deploying VMs" -Status $vmStatus -PercentComplete (100*($v/$totalVMs)) | |
# Create custom OS Custumization spec | |
If ($vm.DHCP -match "true") { | |
$spec = Get-OSCustomizationSpec -Name $VM.CustSpec | |
$tempSpec = $spec | New-OSCustomizationSpec -Name temp$vmName | |
$tempSpec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping ` | |
-IpMode UseDhcp | Out-Null | |
} Else { | |
If ($VM.OSType -eq "Windows") { | |
$spec = Get-OSCustomizationSpec -Name $VM.CustSpec | |
$tempSpec = $spec | New-OSCustomizationSpec -Name temp$vmName | |
$tempSpec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping ` | |
-IpMode UseStaticIP -IpAddress $VM.IPAddress -SubnetMask $VM.SubnetMask ` | |
-Dns $VM.pDNS,$VM.sDNS -DefaultGateway $VM.Gateway | Out-Null | |
} ElseIF ($VM.OSType -eq "Linux") { | |
$spec = Get-OSCustomizationSpec -Name $VM.CustSpec | |
$tempSpec = $spec | New-OSCustomizationSpec -Name temp$vmName | |
$tempSpec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping ` | |
-IpMode UseStaticIP -IpAddress $VM.IPAddress -SubnetMask $VM.SubnetMask ` | |
-DefaultGateway $VM.Gateway | Out-Null | |
} | |
} | |
# Create VM | |
Out-Log "Deploying $vmName" | |
$taskTab[(New-VM -Name $VM.Name -ResourcePool $VM.ResourcePool -Location $VM.Folder -Datastore $VM.Datastore -DiskStorageFormat $VM.DiskStorageFormat ` | |
-Notes $VM.Notes -Template $VM.Template -OSCustomizationSpec temp$vmName -RunAsync -EA SilentlyContinue).Id] = $VM.Name | |
# Remove temp OS Custumization spec | |
Remove-OSCustomizationSpec -OSCustomizationSpec temp$vmName -Confirm:$false | |
# Log errors | |
If ($Error.Count -ne 0) { | |
If ($Error.Count -eq 1 -and $Error.Exception -match "'Location' expects a single value") { | |
$vmLocation = $VM.Folder | |
Out-Log "Unable to place $vmName in desired location, multiple $vmLocation folders exist, check root folder" "Red" | |
} Else { | |
Out-Log "`n$vmName failed to deploy!" "Red" | |
Foreach ($err in $Error) { | |
Out-Log "$err" "Red" | |
} | |
$failDeploy += @($vmName) | |
} | |
} | |
} | |
Out-Log "`n`nAll Deployment Tasks Created" "Yellow" | |
Out-Log "`n`nMonitoring Task Processing" "Yellow" | |
# When finsihed deploying, reconfigure new VMs | |
$totalTasks = $taskTab.Count | |
$runningTasks = $totalTasks | |
while($runningTasks -gt 0){ | |
$vmStatus = "[{0} of {1}] {2}" -f $runningTasks, $totalTasks, "Tasks Remaining" | |
Write-Progress -Activity "Monitoring Task Processing" -Status $vmStatus -PercentComplete (100*($totalTasks-$runningTasks)/$totalTasks) | |
Get-Task | % { | |
if($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success"){ | |
#Deployment completed | |
$Error.Clear() | |
$vmName = $taskTab[$_.Id] | |
Out-Log "`n`nReconfiguring $vmName" "Yellow" | |
$VM = Get-VM $vmName | |
$VMconfig = $newVMs | Where {$_.Name -eq $vmName} | |
# Set CPU and RAM | |
Out-Log "Setting vCPU(s) and RAM on $vmName" "Yellow" | |
$VM | Set-VM -NumCpu $VMconfig.CPU -MemoryGB $VMconfig.RAM -Confirm:$false | Out-Null | |
# Set port group on virtual adapter | |
Out-Log "Setting Port Group on $vmName" "Yellow" | |
If ($VMconfig.NetType -match "vSS") { | |
$network = @{ | |
'NetworkName' = $VMconfig.network | |
'Confirm' = $false | |
} | |
} Else { | |
$network = @{ | |
'Portgroup' = $VMconfig.network | |
'Confirm' = $false | |
} | |
} | |
$VM | Get-NetworkAdapter | Set-NetworkAdapter @network | Out-Null | |
# Add additional disks if needed | |
If ($VMConfig.Disk2 -gt 1) { | |
Out-Log "Adding additional disk on $vmName – don't forget to format within the OS" "Yellow" | |
$VM | New-HardDisk -CapacityGB $VMConfig.Disk2 -StorageFormat $VMConfig.DiskStorageFormat -Persistence persistent | Out-Null | |
} | |
If ($VMConfig.Disk3 -gt 1) { | |
Out-Log "Adding additional disk on $vmName – don't forget to format within the OS" "Yellow" | |
$VM | New-HardDisk -CapacityGB $VMConfig.Disk3 -StorageFormat $VMConfig.DiskStorageFormat -Persistence persistent | Out-Null | |
} | |
If ($VMConfig.Disk4 -gt 1) { | |
Out-Log "Adding additional disk on $vmName – don't forget to format within the OS" "Yellow" | |
$VM | New-HardDisk -CapacityGB $VMConfig.Disk4 -StorageFormat $VMConfig.DiskStorageFormat -Persistence persistent | Out-Null | |
} | |
# Boot VM | |
If ($VMconfig.Boot -match "true") { | |
Out-Log "Booting $vmName" "Yellow" | |
$VM | Start-VM -EA SilentlyContinue | Out-Null | |
} | |
$taskTab.Remove($_.Id) | |
$runningTasks– | |
If ($Error.Count -ne 0) { | |
Out-Log "$vmName completed with errors" "Red" | |
Foreach ($err in $Error) { | |
Out-Log "$Err" "Red" | |
} | |
$failReconfig += @($vmName) | |
} Else { | |
Out-Log "$vmName is Complete" "Green" | |
$successVMs += @($vmName) | |
} | |
} | |
elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error"){ | |
# Deployment failed | |
$failed = $taskTab[$_.Id] | |
Out-Log "`n$failed failed to deploy!`n" "Red" | |
$taskTab.Remove($_.Id) | |
$runningTasks– | |
$failDeploy += @($failed) | |
} | |
} | |
Start-Sleep -Seconds 10 | |
} | |
#——————————————————————– | |
# Close Connections | |
Disconnect-VIServer -Server $vcenter -Force -Confirm:$false | |
#——————————————————————– | |
# Outputs | |
Out-Log "`n**************************************************************************************" | |
Out-Log "Processing Complete" "Yellow" | |
If ($successVMs -ne $null) { | |
Out-Log "`nThe following VMs were successfully created:" "Yellow" | |
Foreach ($success in $successVMs) {Out-Log "$success" "Green"} | |
} | |
If ($failReconfig -ne $null) { | |
Out-Log "`nThe following VMs failed to reconfigure properly:" "Yellow" | |
Foreach ($reconfig in $failReconfig) {Out-Log "$reconfig" "Red"} | |
} | |
If ($failDeploy -ne $null) { | |
Out-Log "`nThe following VMs failed to deploy:" "Yellow" | |
Foreach ($deploy in $failDeploy) {Out-Log "$deploy" "Red"} | |
} | |
$finishtime = Get-Date -uformat "%m-%d-%Y %I:%M:%S" | |
Out-Log "`n`n" | |
Out-Log "**************************************************************************************" | |
Out-Log "$scriptName`t`t`t`t`tFinish Time:`t$finishtime" | |
Out-Log "**************************************************************************************" |
I get “Attempted to divide by zero” at line 240 and “Index operation failed; the array index evaluated to null” at line 265. Any ideas?
Can you email me the log and csv so I can take a look? It appears like there is some missing info. smasterson [at] gmail
Thanks
Actually I found my issues. For some reason the $newVMs.count was not registering, but by adding @($newVMs).count it picked up the value. Also, for the array index being null…that was my bad. I had the Foreach closing bracket misplaced. Thanks for your quick response and willing to assist. I appreciate that greatly!!
Hi, I get he following error:
Deploying VMs
Attempted to divide by zero.
At C:\temp\DeployVM.ps1:217 char:1
+ Write-Progress -Activity “Deploying VMs” -Status $vmStatus -PercentComplete (100 …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Deploying win2k8_02
win2k8_02 failed to deploy!
Attempted to divide by zero.
Hash,
It seems to not be validating the number of VMs to create properly. Please confirm you are using version 1.2. Can you send me a copy of the log as well as the csv and I’ll take a closer look? smasterson [at] gmail
–shawn
Hi Shawn, thank you for your reply.
Interestingly I have tried with two VM’s in the CSV file and the script works perfectly. I seem to be getting the error if there is only one VM in CSV file which is how I have been testing. As I will be deploying more then one VM I am happy not to chase further but can still send you a copy of the log and CSV if you are interested.
This script is exactly what I am looking for, but also have a requirement to deploy with two NIC’s with different ip address details on separate VLAN’s. Is it possible to add the capability of multiple NIC’s like you have done with the additional disks for example NIC1 NIC2.
Thank you again for an outstanding solution.
Hi Hash
Thanks for the comments. A dual nic setup could be done but would require a bit of logic within the script as the NIC is configured via the Guest Customization Spec. If your adventurous, check out this link where it talks about New-OSCustomizationNicMapping
http://pubs.vmware.com/vsphere-51/index.jsp?topic=%2Fcom.vmware.powercli.ug.doc%2FGUID-F0ADEF4B-E45F-4718-84E7-EE1786ABE403.html
Hi, I have found a solution to this issue.
The problem is that the Import-Csv cmdlets doesn’t seem to return an array when the .csv file contains only one row
To force PowerShell to consider $newVMs (which contains the .csv file import) as an array and thus be able to use the .count method, you shall use this syntaxe : @($newVMs).count instead of just $newVMs.count
Hi,
i am trying to install vm by using this script. vm is installing and the hardware changes are working perfectly but the ip address which we assign in script is not working .please advice .
Hi venkatesh
There are a couple of possibilities here. If DHCP is set to true in the csv, it will skip the IP assignment. The guest OS must be supported and VMware tools must be installed.
You could try to deploy manually via the spec and see if any errors are thrown in vCenter.
Hope this helps
Hi ,
We set DHCP as false only . i am debugging code by putting out_log option it showing like it taking static ip which i have given in csv file . but when the vm up again it is taking DHCP only it is not taking ip which i have given .and vmware tools are installed .
Hi When i checked temp logs i found below
please check
[2014-10-26T00:22:07 INFO] GuestCustUtil invoked.
[2014-10-26T00:22:07 INFO] Params: customize -sealparam “/quiet /generalize /oobe /reboot” -nics 4000 -schedulenativeunobfusc
[2014-10-26T00:22:07 DEBUG] Customization in progress set to 1 at 2014-Oct-26 00:22:07
[2014-10-26T00:22:07 DEBUG] Rpci: Sending request=’deployPkg.update.state 4 0 C:\Windows\TEMP\vmware-imc\guestcust.log’
[2014-10-26T00:22:07 DEBUG] Rpci: Sent request=’deployPkg.update.state 4 0 C:\Windows\TEMP\vmware-imc\guestcust.log’, reply=”, len=0, status=1
[2014-10-26T00:22:07 DEBUG] Successfully opened key SYSTEM\CurrentControlSet\Control\Session Manager\
[2014-10-26T00:22:07 DEBUG] Size of reg_multi_sz 21.
[2014-10-26T00:22:07 DEBUG] Read multi_sz value from registry autocheck autochk *, size 21.
[2014-10-26T00:22:07 DEBUG] string value from registry autocheck autochk *.
[2014-10-26T00:22:07 DEBUG] Returning 1 elements
[2014-10-26T00:22:07 DEBUG] Got BootExecute from session mgr.
[2014-10-26T00:22:07 DEBUG] Native App sysprepDecrypter.exe, arguments ”
[2014-10-26T00:22:07 DEBUG] Copied file sysprepDecrypter.exe to C:\Windows\system32\sysprepDecrypter.exe
[2014-10-26T00:22:07 DEBUG] Updated boot execute value.
[2014-10-26T00:22:07 DEBUG] Successfully created/opened key SOFTWARE\VMware, Inc.\Guest Customization\
[2014-10-26T00:22:07 DEBUG] New boot execute:
[2014-10-26T00:22:07 DEBUG] autocheck autochk *
[2014-10-26T00:22:07 DEBUG] sysprepDecrypter.exe
[2014-10-26T00:22:07 DEBUG] System Drive: C:
[2014-10-26T00:22:07 DEBUG] Moving directory ‘sysprep’ to ‘C:’
[2014-10-26T00:22:07 DEBUG] select * from win32_networkadapter where Manufacturer != ‘Microsoft’ and ServiceName != ‘VMnetAdapter’ and manufacturer is not null and MACAddress is not null
[2014-10-26T00:22:07 DEBUG] Found 1 objects. Pointer 1696468. return code 0(0x0)
[2014-10-26T00:22:07 DEBUG] Found 0 objects. Pointer 0. return code 1(0x1)
[2014-10-26T00:22:07 DEBUG] Returning value 00:50:56:9B:0F:67 for system property
[2014-10-26T00:22:07 DEBUG] Setting dhcp for nic # 0
[2014-10-26T00:22:07 DEBUG] Returning value \\TESTPC-PC\ROOT\CIMV2:Win32_NetworkAdapter.DeviceID=”7″ for system property
[2014-10-26T00:22:07 DEBUG] ASSOCIATORS OF {\\TESTPC-PC\ROOT\CIMV2:Win32_NetworkAdapter.DeviceID=”7″} where ResultClass = Win32_NetworkAdapterConfiguration
[2014-10-26T00:22:08 DEBUG] Found 1 objects. Pointer 169ae20. return code 0(0x0)
[2014-10-26T00:22:08 DEBUG] Found 0 objects. Pointer 0. return code 1(0x1)
[2014-10-26T00:22:08 DEBUG] Clearing gateway ip addresses.
[2014-10-26T00:22:08 DEBUG] Enabling DHCP on the computer
[2014-10-26T00:22:08 DEBUG] Returning value \\TESTPC-PC\ROOT\CIMV2:Win32_NetworkAdapterConfiguration.Index=7 for system property
[2014-10-26T00:22:08 DEBUG] Setting DNS Server to ip
[2014-10-26T00:22:08 DEBUG] Executing command C:\windows\system32\sysprep\sysprep.exe /quiet /generalize /oobe /reboot /unattend:C:\sysprep\sysprep.xml
[2014-10-26T00:22:08 DEBUG] Successfully executed command C:\windows\system32\sysprep\sysprep.exe /quiet /generalize /oobe /reboot /unattend:C:\sysprep\sysprep.xml
[2014-10-26T00:22:08 DEBUG] Trying to connect network interfaces, attempt 1
[2014-10-26T00:22:08 DEBUG] Rpci: Sending request=’deployPkg.update.state 4 103 C:\Windows\TEMP\vmware-imc\guestcust.log@4000′
[2014-10-26T00:22:08 DEBUG] Rpci: Sent request=’deployPkg.update.state 4 103 C:\Windows\TEMP\vmware-imc\guestcust.log@4000′, reply=’queryNicsSupported’, len=18, status=1
[2014-10-26T00:22:08 DEBUG] Got VMX response ‘queryNicsSupported’
[2014-10-26T00:22:08 DEBUG] Rpci: Sending request=’deployPkg.update.state 4 104 C:\Windows\TEMP\vmware-imc\guestcust.log@4000′
[2014-10-26T00:22:08 DEBUG] Rpci: Sent request=’deployPkg.update.state 4 104 C:\Windows\TEMP\vmware-imc\guestcust.log@4000′, reply=’disconnected’, len=12, status=1
[2014-10-26T00:22:08 DEBUG] Got VMX response ‘disconnected’
[2014-10-26T00:22:09 DEBUG] Rpci: Sending request=’deployPkg.update.state 4 104 C:\Windows\TEMP\vmware-imc\guestcust.log@4000′
[2014-10-26T00:22:09 DEBUG] Rpci: Sent request=’deployPkg.update.state 4 104 C:\Windows\TEMP\vmware-imc\guestcust.log@4000′, reply=’connected’, len=9, status=1
[2014-10-26T00:22:09 DEBUG] Got VMX response ‘connected’
[2014-10-26T00:22:09 INFO] The network interfaces are connected on 1 second
[2014-10-26T00:22:09 INFO] GuestCustUtil exiting.
Hi,
I’m getting the following error:
Required property datastore is missing from data object of type VirtualMachineRelocateSpecDiskLocator
while parsing serialized DataObject of type vim.vm.RelocateSpec.DiskLocator
at line 1, column 1068
while parsing property “disk” of static type ArrayOfVirtualMachineRelocateSpecDiskLocator
while parsing serialized DataObject of type vim.vm.RelocateSpec
at line 1, column 1014
while parsing property “location” of static type VirtualMachineRelocateSpec
while parsing serialized DataObject of type vim.vm.CloneSpec
at line 1, column 1003
while parsing property “cloneSpec” of static type VirtualMachineCloneSpec
while parsing serialized DataObject of type vim.storageDrs.StoragePlacementSpec
at line 1, column 324
while parsing call information for method RecommendDatastores
at line 1, column 218
while parsing SOAP body
at line 1, column 207
while parsing SOAP envelope
at line 1, column 38
while parsing HTTP request for method recommendDatastores
on object of type vim.StorageResourceManager
at line 1, column 0
For every vm,
my versions are:
VMware vSphere PowerCLI 5.5 Release 2 Patch 1 build 1931983
and vcenter 5.5 update 2
Hi,
I found the error https://communities.vmware.com/thread/473720
I’m launching your script against a datastorage cluster (SDRS) and then it doesn’t apply the parameter of DiskStorageFormat. If we use this parameter we can only work against datastorage and not SDRS.
So only 2 options or decide which datastorage to use estimating the space that would use, or remove the parameter DiskStorageFormat.
To be honest I don’t like neither of them but doesnt look like any other solution available.
Correct, it is a bug in PowerCLI 🙁
For me, I have removed the DiskStorageFormat switch in the New-VM call so I can still use Datastore Clusters. It seems to use thin by default which is what I would want anyhow.
It was supposedly fixed in PowerCLI 5.8 according to the release notes but I still get the same error.
I would like to introduce some changes on your script in order to use New-OSCustomizationSpec per vm and -nonpersistent parameters, and a switch for SDRS or datastore directly. I will upgrade it to version 1.3 and keep your credits if you dont mind.
I’ll publish it in my blog if you agrees
Absolutely, feel free to customize to your own liking!
Note – you can currently specify a Datastore Cluster or a single Datastore – no changes needed.
Ok I have your 1.3 script ready, the improves are :
1. Add creation onthefly for customization Spec for linux systems
2. Ability to create machines names and guest hostname using different names
3. Added a value to find out the kind of disk because powercli bug for SDRS reported at https://communities.vmware.com/message/2442684#2442684
4. Remove the dependency for an already created OScustomization Spec
For 1.4 I would like to:
1. The ability to deploy system with more than 1 IP coming from a template with just one network adapter. So you need to create the adapter and populate it.
2. The ability to deploy VMs in bunches. I mean if a cluster has 4 nodes create maximum of vms at time and wait until they finish.
Here is the version 1.3 http://www.vidanez.com/2014/11/02/crear-multiples-linux-vms-de-un-fichero-csv-usando-powercli-deploying-multiple-linux-vms-using-powercli/
I hope you like it
Looks great – glad you were able to customize for your needs – it’s one of the best parts of sharing code!
Pingback: Crear múltiples Linux VMs de un fichero CSV usando PowerCli. Deploying multiple Linux VMs using PowerCli – VIDANEZ SITE
hi i am getting below exception
index operation failed :the array index evaluated to null . at c:\deplyvm.ps1:184 char 5
please advice.
Hello Shawn,
Can you help me with the statement in the script to have the VMs created with the gues OS name in the LowerCase & VM Name in vCenter in the UpperCase.
Regards,
Ankur Dahiya
Hi Ankur,
Please have a look at the script 1.3.1 version, its the same as Shawn version but with a few extra fields. In that version of the script is amended the lower and capital situation that you are facing.
http://www.vidanez.com/2014/11/02/crear-multiples-linux-vms-de-un-fichero-csv-usando-powercli-deploying-multiple-linux-vms-using-powercli/
Also I sharing it at https://github.com/Vidanez/DeployVMs
Hi Ankur
Unfortunately, the same variable is used for both names (via the OS Customization Spec), so the change will need to occur after VM creation.
What you could try is this:
1) Use lowercase name for VM creation (in csv) – this will create a VM with both Guest OS and vSphere name in lowercase.
2) Apply change to vSphere name after creation (in portion of script that is going to set vCPU/Disk/etc)
(I haven’t fully tested this, please proceed with caution!)
Try inserting this command after line 299 (line 299 should read “$VM = Get-VM $vmName”)
Set-VM -VM $VM -Name ($VM.Name).ToUpper() -Confirm:$false
That should do the trick.
–shawn
So I am running into build issues. Here’s my log:
**************************************************************************************
DeployVM Ver:1.2 Start Time: 03-18-2015 08:47:14
**************************************************************************************
Using .\DeployVM.csv
New VMs to create: 4
Connecting to vCenter – crifvc.myappro.com
Deploying VMs
Deploying LC-T-APP-WF01
LC-T-APP-WF01 failed to deploy!
3/18/2015 8:47:43 AM Remove-OSCustomizationSpec Value cannot be found for the mandatory parameter OSCustomizationSpec
3/18/2015 8:47:43 AM Remove-OSCustomizationSpec Could not find OSCustomizationSpec with name ‘tempLC-T-APP-WF01’.
Index operation failed; the array index evaluated to null.
3/18/2015 8:47:39 AM New-VM OSCustomizationSpec parameter: Could not find any of the objects specified by name.
3/18/2015 8:47:39 AM New-VM Could not find OSCustomizationSpec with name ‘tempLC-T-APP-WF01’.
Deploying LC-T-APP-ENCOR1
LC-T-APP-ENCOR1 failed to deploy!
3/18/2015 8:47:56 AM Remove-OSCustomizationSpec Value cannot be found for the mandatory parameter OSCustomizationSpec
3/18/2015 8:47:56 AM Remove-OSCustomizationSpec Could not find OSCustomizationSpec with name ‘tempLC-T-APP-ENCOR1’.
Index operation failed; the array index evaluated to null.
3/18/2015 8:47:51 AM New-VM OSCustomizationSpec parameter: Could not find any of the objects specified by name.
3/18/2015 8:47:51 AM New-VM Could not find OSCustomizationSpec with name ‘tempLC-T-APP-ENCOR1’.
Deploying LC-T-APP-UBT01
LC-T-APP-UBT01 failed to deploy!
3/18/2015 8:48:08 AM Remove-OSCustomizationSpec Value cannot be found for the mandatory parameter OSCustomizationSpec
3/18/2015 8:48:08 AM Remove-OSCustomizationSpec Could not find OSCustomizationSpec with name ‘tempLC-T-APP-UBT01’.
Index operation failed; the array index evaluated to null.
3/18/2015 8:48:04 AM New-VM OSCustomizationSpec parameter: Could not find any of the objects specified by name.
3/18/2015 8:48:04 AM New-VM Could not find OSCustomizationSpec with name ‘tempLC-T-APP-UBT01’.
Deploying LC-T-APP-TMK01
LC-T-APP-TMK01 failed to deploy!
3/18/2015 8:48:20 AM Remove-OSCustomizationSpec Value cannot be found for the mandatory parameter OSCustomizationSpec
3/18/2015 8:48:20 AM Remove-OSCustomizationSpec Could not find OSCustomizationSpec with name ‘tempLC-T-APP-TMK01’.
Index operation failed; the array index evaluated to null.
3/18/2015 8:48:16 AM New-VM OSCustomizationSpec parameter: Could not find any of the objects specified by name.
3/18/2015 8:48:16 AM New-VM Could not find OSCustomizationSpec with name ‘tempLC-T-APP-TMK01’.
All Deployment Tasks Created
Monitoring Task Processing
**************************************************************************************
Processing Complete
The following VMs failed to deploy:
LC-T-APP-WF01
LC-T-APP-ENCOR1
LC-T-APP-UBT01
LC-T-APP-TMK01
**************************************************************************************
DeployVM Finish Time: 03-18-2015 08:48:21
**************************************************************************************
Here’s the Output
Deploying LC-T-APP-WF01
Index operation failed; the array index evaluated to null.
At C:\VS_Projects\PowerShell\PowerCLI\vCenter and vSphere\Deploy_Automations\DeploymentScript03\DepScript03_V01.ps1:265 char:5
+ $taskTab[(New-VM -Name $VM.Name -ResourcePool $VM.ResourcePool -Location $VM …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
Remove-OSCustomizationSpec : 3/18/2015 8:57:18 AM Remove-OSCustomizationSpec Could not find OSCustomizationSpec with name
‘tempLC-T-APP-WF01’.
At C:\VS_Projects\PowerShell\PowerCLI\vCenter and vSphere\Deploy_Automations\DeploymentScript03\DepScript03_V01.ps1:268 char:5
+ Remove-OSCustomizationSpec -OSCustomizationSpec temp$vmName -Confirm:$false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (tempLC-T-APP-WF01:String) [Remove-OSCustomizationSpec], VimException
+ FullyQualifiedErrorId : Core_ObnSelector_SelectObjectByNameCore_ObjectNotFound,VMware.VimAutomation.ViCore.Cmdlets.Commands.Rem
oveOSCustomizationSpec
Remove-OSCustomizationSpec : 3/18/2015 8:57:18 AM Remove-OSCustomizationSpec Value cannot be found for the mandatory
parameter OSCustomizationSpec
At C:\VS_Projects\PowerShell\PowerCLI\vCenter and vSphere\Deploy_Automations\DeploymentScript03\DepScript03_V01.ps1:268 char:5
+ Remove-OSCustomizationSpec -OSCustomizationSpec temp$vmName -Confirm:$false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-OSCustomizationSpec], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.RemoveOSCustomizationSpec
LC-T-APP-WF01 failed to deploy!
3/18/2015 8:57:18 AM Remove-OSCustomizationSpec Value cannot be found for the mandatory parameter OSCustomizationSpec
3/18/2015 8:57:18 AM Remove-OSCustomizationSpec Could not find OSCustomizationSpec with name ‘tempLC-T-APP-WF01’.
Index operation failed; the array index evaluated to null.
3/18/2015 8:57:14 AM New-VM OSCustomizationSpec parameter: Could not find any of the objects specified by name.
3/18/2015 8:57:14 AM New-VM Could not find OSCustomizationSpec with name ‘tempLC-T-APP-WF01’.
Hi Matt
It appears as though the name you are passing for the OS Customization Spec does not exist – can you confirm you have setup one up named ‘tempLC-T-APP-WF01’?
So, the CSV is setup this way:
Name Boot OSType Template CustSpec Folder ResourcePool CPU RAM Disk2 Disk3 Disk4 Datastore DiskStorageFormat NetType Network DHCP IPAddress SubnetMask Gateway pDNS sDNS
LC-T-APP-WF01 LC-T-APP-TMPL LCC_ApproDev_Testing LCC_TEST LCC_APP_TEST VMAX_LCC_TEST_APP01_04DA Thin VLAN627 10.110.47.118 255.255.255.128 10.110.47.1 10.15.1.3 10.15.1.6
LC-T-APP-ENCOR1 LC-T-APP-TMPL LCC_ApproDev_Testing LCC_TEST LCC_APP_TEST VMAX_LCC_TEST_APP02_04E2 Thin VLAN627 10.110.47.109 255.255.255.128 10.110.47.1 10.15.1.3 10.15.1.6
LC-T-APP-UBT01 LC-T-APP-TMPL LCC_ApproDev_Testing LCC_TEST LCC_APP_TEST VMAX_LCC_TEST_APP03_04EA Thin VLAN627 10.110.47.113 255.255.255.128 10.110.47.1 10.15.1.3 10.15.1.6
LC-T-APP-TMK01 LC-T-APP-TMPL LCC_ApproDev_Testing LCC_TEST LCC_APP_TEST VMAX_LCC_TEST_APP04_04F2 Thin VLAN627 10.110.47.111 255.255.255.128 10.110.47.1 10.15.1.3 10.15.1.6
I do not know why it’s referencing temp but I did notice in your script it has this in it:
temp$vmName
at the OSCustSpec area. So I am perplexed.
You are correct – what is happening here is that the code is taking your existing spec (the one you identified in the csv) and creating a new (temp) spec. It then makes changes to this temp spec and applies them to the template when it is rolled out.
If you look at your specs – do you see any that start with temp? It seems as though it is either not getting created at all or with the wrong name.
We have no custspecs named Temp.
My CSV file looks like this:
Name,Boot,OSType,Template,CustSpec,Folder,ResourcePool,CPU,RAM,Disk2,Disk3,Disk4,Datastore,DiskStorageFormat,NetType,Network,DHCP,IPAddress,SubnetMask,Gateway,pDNS,sDNS,Notes
LC-T-APP-WF01,,,LC-T-APP-TMPL,TestLCC,LCC_TEST,LCC_APP_TEST,,,,,,VMAX_LCC_TEST_APP01_04DA,Thin,,VLAN627,,10.110.47.118,255.255.255.128,10.110.47.1,10.15.1.3,10.15.1.6,Woodforest LCC Test Server
LC-T-APP-ENCOR1,,,LC-T-APP-TMPL,TestLCC,LCC_TEST,LCC_APP_TEST,,,,,,VMAX_LCC_TEST_APP02_04E2,Thin,,VLAN627,,10.110.47.109,255.255.255.128,10.110.47.1,10.15.1.3,10.15.1.6,Encore LCC Test Server
LC-T-APP-UBT01,,,LC-T-APP-TMPL,TestLCC,LCC_TEST,LCC_APP_TEST,,,,,,VMAX_LCC_TEST_APP03_04EA,Thin,,VLAN627,,10.110.47.113,255.255.255.128,10.110.47.1,10.15.1.3,10.15.1.6,UB&T LCC Test Server
LC-T-APP-TMK01,,,LC-T-APP-TMPL,TestLCC,LCC_TEST,LCC_APP_TEST,,,,,,VMAX_LCC_TEST_APP04_04F2,Thin,,VLAN627,,10.110.47.111,255.255.255.128,10.110.47.1,10.15.1.3,10.15.1.6,TMK LCC Test Server
I created another customization spec and labeled it “TestLCC” Still didn’t work (Same Errors)
I guess it’s not creating the temp spec in the script?
Unfortunately, I can’t test at the moment – can you try changing the VM name to something simple like ‘testvm’.
Just want to make sure it is not the VM name that is throwing it off.
Another thing to try would be to test the create spec part of the code with something like this:
$vmName = “testVMname”
$currentSpec = “Nameofexistingspec”
$spec = Get-OSCustomizationSpec -Name $currentSpec
$tempSpec = $spec | New-OSCustomizationSpec -Name temp$vmName
Running the above – any errors? Is a new spec created?
The four variables, are you saying to place them at the beginning of the code? Where should they go?
Still getting that error when I swap names:
Deploying testvm1
Index operation failed; the array index evaluated to null.
At C:\VS_Projects\PowerShell\PowerCLI\vCenter and
vSphere\Deploy_Automations\DeploymentScript03\DepScript03.ps1:265 char:2
+ $taskTab[(New-VM -Name $VM.Name -ResourcePool $VM.ResourcePool -Location
$VM.Fo …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
Remove-OSCustomizationSpec : 3/18/2015 10:52:15 AM
Remove-OSCustomizationSpec Could not find OSCustomizationSpec with name
‘temptestvm1’.
At C:\VS_Projects\PowerShell\PowerCLI\vCenter and
vSphere\Deploy_Automations\DeploymentScript03\DepScript03.ps1:268 char:2
+ Remove-OSCustomizationSpec -OSCustomizationSpec temp$vmName
-Confirm:$false
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (temptestvm1:String) [Remove-OSC
ustomizationSpec], VimException
+ FullyQualifiedErrorId : Core_ObnSelector_SelectObjectByNameCore_ObjectNo
tFound,VMware.VimAutomation.ViCore.Cmdlets.Commands.RemoveOSCustomizationS
pec
Remove-OSCustomizationSpec : 3/18/2015 10:52:15 AM
Remove-OSCustomizationSpec Value cannot be found for the mandatory
parameter OSCustomizationSpec
At C:\VS_Projects\PowerShell\PowerCLI\vCenter and
vSphere\Deploy_Automations\DeploymentScript03\DepScript03.ps1:268 char:2
+ Remove-OSCustomizationSpec -OSCustomizationSpec temp$vmName
-Confirm:$false
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-OSCustomizationSpec],
VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomatio
n.ViCore.Cmdlets.Commands.RemoveOSCustomizationSpec
testvm1 failed to deploy!
3/18/2015 10:52:15 AM Remove-OSCustomizationSpec Value cannot be found for the
mandatory parameter OSCustomizationSpec
3/18/2015 10:52:15 AM Remove-OSCustomizationSpec Could not find OSCustomization
Spec with name ‘temptestvm1’.
Index operation failed; the array index evaluated to null.
3/18/2015 10:52:11 AM New-VM OSCustomizationSpec parameter: Could not find any
of the objects specified by name.
3/18/2015 10:52:11 AM New-VM Could not find OSCustomizationSpec with name ‘temp
testvm1’.
You should be able to just run the four lines of code (with PowerCLI loaded and connected to VI server).
You can leave the $vmName variable (or change for testing).
You should just need to change the $currentSpec variable to the spec name you are trying to use.
Leave the last two lines alone. The third line grabs the existing spec while the fourth line should make a copy of it.
Ok looks like just running those four lines creates the CustomSpec, so now what lol?
Hmmm Ok
Did you try using the same spec and VM name that you are using in the csv?
Odd how it is created here but not via the full script.
I did and it created it.
Not sure why it doesn’t want to create it in the script. Let me know if you want to email (m.dartez@criflending.com) so I can throw some screenshots your way.
I’m a bit stumped as well…
Feel free to send more info my way (smasterson at gmail)
Hi! I am trying to use your script, and it goes as far as deploying the VM but fails on Customization. The error in Status on my vi-client “Cannot complete customization”. Any pointers or tips? I can use the same customization when deploying VM’s manually and it works fine so the customization looks fine. Am I missing anything? My template has already got networking config in place.
Thanks in advance and will wait for your reply.
Hello
What errors are you seeing in the PowerShell console? Log file?
Hello,
Thank you for your response, I am getting the following in the PS console.
New VMs to create: 1
Connecting to vCenter – vcenter
Deploying VMs
Deploying TESTVM
All Deployment Tasks Created
Monitoring Task Processing
TESTVM failed to deploy!
**************************************************************************************
Processing Complete
The following VMs failed to deploy:
TESTVM
**************************************************************************************
DeployVM Finish Time: 04-17-2015 03:33:48
**************************************************************************************
the log files below:
**************************************************************************************
DeployVM Ver:1.2.1 Start Time: 04-17-2015 03:30:46
**************************************************************************************
Using DeployVM.csv
New VMs to create: 1
Connecting to vCenter – vcenter
Deploying VMs
Deploying TESTVM
All Deployment Tasks Created
Monitoring Task Processing
TESTVM failed to deploy!
**************************************************************************************
Processing Complete
The following VMs failed to deploy:
TESTVM
**************************************************************************************
DeployVM Finish Time: 04-17-2015 03:33:48
**************************************************************************************
Thanks in advance.
Regards,
Rehman
Hmm..it seems we are still not seeing the actual error.
Can you please swap out the following code on line 266:
-EA SilentlyContinue
change to
-EA Stop
Run again and let me know if you see a more detailed error
Hi,
Have run the script after making the change and it’s failing without any additional errors.
Odd…did the script finish or stop when the error occurred?
Hi!
It ran and finished exactly as the previous errors it didn’t stop
Thank you so much for assisting in this
Not sure what’s going on here…it seems the actual error is being suppressed some how.
Try adding this line after line 275
Write-Host $Error
Are you running the script from console or ISE?
Odd that we are not seeing the actual PS error here. Without it, it is very difficult to troubleshoot.
Hi Shawn,
First, great script. saved me lots of time develop it myself 🙂
i have changed few things for my requirements (added dynamic selection for esx host based on free memory, added few other fields and logic’s because i’m working with 2 vc servers).
now, i have strange problem.
i deploy 3 machines for debugging purpose . the first should be fine, the seconds should fail on configure and the third fail completely.
when the script finish i have the following result:
Processing Complete
The following VMs were successfully created:
meme1-vvw
The following VMs failed to reconfigure properly:
meme2-vvw
The following VMs failed to deploy:
meme3-vvw
meme1-vvw
as you can see the first vm (meme1) is successful and failed at the same time. it looks line the line :”if($taskTab.ContainsKey($_.Id) -and $_.State -eq “Success”)” is true and also the line “elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq “Error”)” is true.
the only thing i changed in the tasktab is the id name. instead of using the vmname i add id_vmname (id is a filed from the csv).
complete log:
**************************************************************************************
DeployVM Ver:1.2 Start Time: 04-19-2015 11:30:15
**************************************************************************************
Using D:\Automation\DeployVM\DeployVMs.csv
Line 210: New VMs to create: 3
Line 236: Deploying VMs
Line 266: Connecting xxx…
Name Port User
—- —- —-
vcprod01.pelephone.co.il 443 PELE\VCUser
Getting host…
host @{Name=xxx; [math]::round($_.MemoryUsageGB)=102}
Line 300: Current customization: Name=tempmeme1-vvw
free : 19.08
Line 314: Deploying meme1-vvw
Line 266: Connecting xxx…
vcprod01.pelephone.co.il 443 PELE\VCUser
Getting host…
host @{Name=xxx; [math]::round($_.MemoryUsageGB)=102}
Line 300: Current customization: Name=tempmeme2-vvw
free : 19.08
Line 314: Deploying meme2-vvw
Line 266: Connecting xxx…
vcprod01.pelephone.co.il 443 PELE\VCUser
Getting host…
host @{Name=xxx; [math]::round($_.MemoryUsageGB)=102}
Line 300: Current customization: Name=tempmeme3-vvw
free : 18.99
Line 314: Deploying meme3-vvw
Line 325: meme3-vvw failed to deploy!
Line 326: 4/19/2015 11:30:45 AM New-VM Could not find Folder with name ‘new ser3vers’. .Exception
Line 328: 4/19/2015 11:30:45 AM New-VM Could not find Folder with name ‘new ser3vers’.
Line 335: All Deployment Tasks Created
Line 336: Monitoring Task Processing
Line 354: Reconfiguring meme1-vvw
Line 359: Setting vCPU(s) and RAM on meme1-vvw
Line 370: Setting Port Group on meme1-vvw
WARNING: PowerCLI scripts should not use the ‘Client’ property. The property will be removed in a future release.
MacAddress : 00:50:56:83:14:ec
WakeOnLanEnabled : True
NetworkName : dvP_10.57.9.0
Type : Vmxnet3
ParentId : VirtualMachine-vm-657391
Parent : meme1-vvw
Uid : /VIServer=pele\vcuser@vcprod01.pelephone.co.il:443/VirtualMachine=VirtualMachine-vm-657391/NetworkAd
apter=4000/
ConnectionState : NotConnected, GuestControl, NoStartConnected
ExtensionData : VMware.Vim.VirtualVmxnet3
Id : VirtualMachine-vm-657391/4000
Name : Network adapter 1
Client : VMware.VimAutomation.ViCore.Impl.V1.VimClient
Line 403: Booting meme1-vvw
Line 417: meme1-vvw is Complete
Line 425: meme1-vvw failed to deploy!
Line 354: Reconfiguring meme2-vvw
Line 359: Setting vCPU(s) and RAM on meme2-vvw
Line 370: Setting Port Group on meme2-vvw
Set-NetworkAdapter : Cannot validate argument on parameter ‘Portgroup’. The argument is null. Supply a non-null
argument and try the command again.
At D:\Automation\DeployVM\DeployVM.ps1:385 char:61
+ $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $MyVDPortgroup -Conf …
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Set-NetworkAdapter], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.VirtualDev
ice.SetNetworkAdapter
Line 403: Booting meme2-vvw
Line 409: meme2-vvw completed with errors
Line 411: Cannot validate argument on parameter ‘Portgroup’. The argument is null. Supply a non-null argument and try th
e command again.
2
1
1
**************************************************************************************
Processing Complete
The following VMs were successfully created:
meme1-vvw
The following VMs failed to reconfigure properly:
meme2-vvw
The following VMs failed to deploy:
meme3-vvw
meme1-vvw
**************************************************************************************
DeployVM Finish Time: 04-19-2015 11:31:36
**************************************************************************************
Success:
meme1-vvw
@FailConfig:
meme2-vvw
@FailDeploy:
meme3-vvw
meme1-vvw
Thanks
Mor
Hi!
I have added the Write-Host$Error but still no joy. I was running this from PowerGUI on Friday and today have executed this from PowerCli console but the errors are exactly the same as I had posted earlier. Below is the version detail I am running .
C:\ Get-PSVersion
Major Minor Build Revision
—– —– —– ——–
4 0 -1 -1
PowerCLI C:\ Get-PowerCLIVersion
PowerCLI Version
—————-
VMware vSphere PowerCLI 6.0 Release 1 build 2548067
—————
Component Versions
—————
VMWare AutoDeploy PowerCLI Component 6.0 build 2358282
VMWare ImageBuilder PowerCLI Component 6.0 build 2358282
VMware License PowerCLI Component 6.0 build 2315846
VMware vSphere PowerCLI Component 6.0 build 2548068
VMware Cloud Infrastructure Suite PowerCLI Component 6.0 build 2548068
VMware VDS PowerCLI Component 6.0 build 2548068
VMware vCloud Director PowerCLI Component 6.0 build 2512755
VMware HA PowerCLI Component 6.0 build 2510422
VMware vCloud Air PowerCLI Component 6.0 build 2512755
VMware PowerCLI Component for Storage Management 6.0 build 2522368
Shawn,
Thank you for sharing this multiple VM deployment tool. It worked perfectly right out of the gate. I have modified it a bit for use with rolling out large numbers of IO Analyzer worker VMs with more granular configurations. On the worker IO Analyzer VMs, VMware recommends placing the primary OS disk on a storage system other than that which you intend to test so as to avoid having untracked OS operations impact a target storage system’s maximum capabilities and skewing the results. As originally written, your DeployVM script placed any of the optional additional disks on the same datastore as the primary/OS. Since you already had the optional disks 2/3/4 coded in the script, I added fields and variables to the csvfile, createcsv, and post-build reconfiguration section of the script respectively, as well as updated the comments at the top. I have tested placing all three additional disks on three unique datastores successfully with various arrangements, skips, etc. CSV file must have DiskStorageFormat value for each additional disk 2/3/4, or will error. A similar vnic mod would likely address the need for additional vnics as one commenter previously requested. Your script was a great help, so in turn I am sharing the modified version (below).
Thanks again.
-Matthew Lieblong
———-beginning of script—————–
#requires –Version 3
#——————————————————————–
# Parameters
param (
[parameter(Mandatory=$false)]
[string]$csvfile,
[parameter(Mandatory=$false)]
[string]$vcenter,
[parameter(Mandatory=$false)]
[switch]$auto,
[parameter(Mandatory=$false)]
[switch]$createcsv
)
#——————————————————————–
# User Defined Variables
#——————————————————————–
# Static Variables
$scriptName = “DeployVM”
$scriptVer = “1.2”
$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$starttime = Get-Date -uformat “%m-%d-%Y %I:%M:%S”
$logDir = $scriptDir + “\Logs\”
$logfile = $logDir + $scriptName + “_” + (Get-Date -uformat %m-%d-%Y_%I-%M-%S) + “_” + $env:username + “.txt”
$deployedDir = $scriptDir + “\Deployed\”
$deployedFile = $deployedDir + “DeployVM_” + (Get-Date -uformat %m-%d-%Y_%I-%M-%S) + “_” + $env:username + “.csv”
$exportpath = $scriptDir + “\DeployVM.csv”
$headers = “” | Select-Object Name, Boot, OSType, Template, CustSpec, Folder, ResourcePool, CPU, RAM, Disk2, Disk3, Disk4, Datastore, Datastore2, Datastore3, Datastore4, DiskStorageFormat, DiskStorageFormat2, DiskStorageFormat3, DiskStorageFormat4, NetType, Network, DHCP, IPAddress, SubnetMask, Gateway, pDNS, sDNS, Notes
$taskTab = @{}
#——————————————————————–
# Load Snap-ins
# Add VMware snap-in if required
If ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null) {add-pssnapin VMware.VimAutomation.Core}
#——————————————————————–
# Functions
Function Out-Log {
Param(
[Parameter(Mandatory=$true)][string]$LineValue,
[Parameter(Mandatory=$false)][string]$fcolor = “White”
)
Add-Content -Path $logfile -Value $LineValue
Write-Host $LineValue -ForegroundColor $fcolor
}
Function Read-OpenFileDialog([string]$WindowTitle, [string]$InitialDirectory, [string]$Filter = “All files (*.*)|*.*”, [switch]$AllowMultiSelect)
{
Add-Type -AssemblyName System.Windows.Forms
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Title = $WindowTitle
if (![string]::IsNullOrWhiteSpace($InitialDirectory)) { $openFileDialog.InitialDirectory = $InitialDirectory }
$openFileDialog.Filter = $Filter
if ($AllowMultiSelect) { $openFileDialog.MultiSelect = $true }
$openFileDialog.ShowHelp = $true # Without this line the ShowDialog() function may hang depending on system configuration and running from console vs. ISE.
$openFileDialog.ShowDialog() > $null
if ($AllowMultiSelect) { return $openFileDialog.Filenames } else { return $openFileDialog.Filename }
}
#——————————————————————–
# Main Procedures
# Start Logging
Clear-Host
If (!(Test-Path $logDir)) {New-Item -ItemType directory -Path $logDir | Out-Null}
Out-Log “**************************************************************************************”
Out-Log “$scriptName`tVer:$scriptVer`t`t`t`tStart Time:`t$starttime”
Out-Log “**************************************************************************************`n”
# If requested, create DeployVM.csv and exit
If ($createcsv) {
If (Test-Path $exportpath) {
Out-Log “`n$exportpath Already Exists!`n” “Red”
Exit
} Else {
Out-Log “`nCreating $exportpath`n” “Yellow”
$headers | Export-Csv $exportpath -NoTypeInformation
Out-Log “Done!`n”
Exit
}
}
# Ensure PowerCLI is at least version 5.5 R2 (Build 1649237)
If ((Get-PowerCLIVersion).Build -lt 1649237) {
Out-Log “Error: DeployVM script requires PowerCLI version 5.5 R2 (Build 1649237) or later” “Red”
Out-Log “PowerCLI Version Detected: $((Get-PowerCLIVersion).UserFriendlyVersion)” “Red”
Out-Log “Exiting…`n`n” “Red”
Exit
}
# Test to ensure csv file is available
If ($csvfile -eq “” -or !(Test-Path $csvfile) -or !$csvfile.EndsWith(“DeployVM.csv”)) {
Out-Log “Path to DeployVM.csv not specified…prompting`n” “Yellow”
$csvfile = Read-OpenFileDialog “Locate DeployVM.csv” “C:\” “DeployVM.csv|DeployVM.csv”
}
If ($csvfile -eq “” -or !(Test-Path $csvfile) -or !$csvfile.EndsWith(“DeployVM.csv”)) {
Out-Log “`nStill can’t find it…I give up” “Red”
Out-Log “Exiting…” “Red”
Exit
}
Out-Log “Using $csvfile`n” “Yellow”
# Make copy of DeployVM.csv
If (!(Test-Path $deployedDir)) {New-Item -ItemType directory -Path $deployedDir | Out-Null}
Copy-Item $csvfile -Destination $deployedFile | Out-Null
# Import VMs from csv
$newVMs = Import-Csv $csvfile
$newVMs = $newVMs | Where {$_.Name -ne “”}
[INT]$totalVMs = @($newVMs).count
Out-Log “New VMs to create: $totalVMs” “Yellow”
# Check to ensure csv is populated
If ($totalVMs -lt 1) {
Out-Log “`nError: No entries found in DeployVM.csv” “Red”
Out-Log “Exiting…`n” “Red”
Exit
}
# Show input and ask for confirmation, unless -auto was used
If (!$auto) {
$newVMs | Out-GridView -Title “VMs to be Created”
$continue = Read-Host “`nContinue (y/n)?”
If ($continue -notmatch “y”) {
Out-Log “Exiting…” “Red”
Exit
}
}
# Connect to vCenter server
If ($vcenter -eq “”) {$vcenter = Read-Host “`nEnter vCenter server FQDN or IP”}
Try {
Out-Log “`nConnecting to vCenter – $vcenter`n`n” “Yellow”
Connect-VIServer $vcenter -EA Stop | Out-Null
} Catch {
Out-Log “`r`n`r`nUnable to connect to $vcenter” “Red”
Out-Log “Exiting…`r`n`r`n” “Red”
Exit
}
# Start provisioning VMs
$v = 0
Out-Log “Deploying VMs`n” “Yellow”
Foreach ($VM in $newVMs) {
$Error.Clear()
$vmName = $VM.Name
$v++
$vmStatus = “[{0} of {1}] {2}” -f $v, $newVMs.count, $vmName
Write-Progress -Activity “Deploying VMs” -Status $vmStatus -PercentComplete (100*$v/($newVMs.count))
# Create custom OS Custumization spec
If ($vm.DHCP -match “true”) {
$spec = Get-OSCustomizationSpec -Name $VM.CustSpec
$tempSpec = $spec | New-OSCustomizationSpec -Name temp$vmName
$tempSpec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping `
-IpMode UseDhcp | Out-Null
} Else {
If ($VM.OSType -eq “Windows”) {
$spec = Get-OSCustomizationSpec -Name $VM.CustSpec
$tempSpec = $spec | New-OSCustomizationSpec -Name temp$vmName
$tempSpec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping `
-IpMode UseStaticIP -IpAddress $VM.IPAddress -SubnetMask $VM.SubnetMask `
-Dns $VM.pDNS,$VM.sDNS -DefaultGateway $VM.Gateway | Out-Null
} ElseIF ($VM.OSType -eq “Linux”) {
$spec = Get-OSCustomizationSpec -Name $VM.CustSpec
$tempSpec = $spec | New-OSCustomizationSpec -Name temp$vmName
$tempSpec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping `
-IpMode UseStaticIP -IpAddress $VM.IPAddress -SubnetMask $VM.SubnetMask `
-DefaultGateway $VM.Gateway | Out-Null
}
}
# Create VM
Out-Log “Deploying $vmName”
$taskTab[(New-VM -Name $VM.Name -ResourcePool $VM.ResourcePool -Location $VM.Folder -Datastore $VM.Datastore -DiskStorageFormat $VM.DiskStorageFormat`
-Notes $VM.Notes -Template $VM.Template-OSCustomizationSpec temp$vmName -RunAsync -EA SilentlyContinue).Id] = $VM.Name
# Remove temp OS Customization spec
Remove-OSCustomizationSpec -OSCustomizationSpec temp$vmName -Confirm:$false
# Log errors
If ($Error.Count -ne 0) {
If ($Error.Count -eq 1 -and $Error.Exception -match “‘Location’ expects a single value”) {
$vmLocation = $VM.Folder
Out-Log “Unable to place $vmName in desired location, multiple $vmLocation folders exist, check root folder” “Red”
} Else {
Out-Log “`n$vmName failed to deploy!” “Red”
Foreach ($err in $Error) {
Out-Log “$err” “Red”
}
$failDeploy += @($vmName)
}
}
}
Out-Log “`n`nAll Deployment Tasks Created” “Yellow”
Out-Log “`n`nMonitoring Task Processing” “Yellow”
# When finsihed deploying, reconfigure new VMs
$totalTasks = $taskTab.Count
$runningTasks = $totalTasks
while($runningTasks -gt 0){
$vmStatus = “[{0} of {1}] {2}” -f $runningTasks, $totalTasks, “Tasks Remaining”
Write-Progress -Activity “Monitoring Task Processing” -Status $vmStatus -PercentComplete (100*($totalTasks-$runningTasks)/$totalTasks)
Get-Task | % {
if($taskTab.ContainsKey($_.Id) -and $_.State -eq “Success”){
#Deployment completed
$Error.Clear()
$vmName = $taskTab[$_.Id]
Out-Log “`n`nReconfiguring $vmName” “Yellow”
$VM = Get-VM $vmName
$VMconfig = $newVMs | Where {$_.Name -eq $vmName}
# Set CPU and RAM
Out-Log “Setting vCPU(s) and RAM on $vmName” “Yellow”
$VM | Set-VM -NumCpu $VMconfig.CPU -MemoryGB $VMconfig.RAM -Confirm:$false | Out-Null
# Set port group on virtual adapter
Out-Log “Setting Port Group on $vmName” “Yellow”
If ($VMconfig.NetType -match “vSS”) {
$network = @{
‘NetworkName’ = $VMconfig.network
‘Confirm’ = $false
}
} Else {
$network = @{
‘Portgroup’ = $VMconfig.network
‘Confirm’ = $false
}
}
$VM | Get-NetworkAdapter | Set-NetworkAdapter @network | Out-Null
# Add additional disks if needed
If ($VMConfig.Disk2 -gt 1) {
Out-Log “Adding additional disk 2 on $vmName – don’t forget to format within the OS” “Yellow”
$VM | New-HardDisk -CapacityGB $VMConfig.Disk2 -Datastore $VMconfig.Datastore2 -StorageFormat $VMconfig.DiskStorageFormat2 -Persistence persistent | Out-Null
}
If ($VMConfig.Disk3 -gt 1) {
Out-Log “Adding additional disk 3 on $vmName – don’t forget to format within the OS” “Yellow”
$VM | New-HardDisk -CapacityGB $VMConfig.Disk3 -Datastore $VMconfig.Datastore3 -StorageFormat $VMConfig.DiskStorageFormat3 -Persistence persistent | Out-Null
}
If ($VMConfig.Disk4 -gt 1) {
Out-Log “Adding additional disk 4 on $vmName – don’t forget to format within the OS” “Yellow”
$VM | New-HardDisk -CapacityGB $VMConfig.Disk4 -Datastore $VMconfig.Datastore4 -StorageFormat $VMConfig.DiskStorageFormat4 -Persistence persistent | Out-Null
}
# Boot VM
If ($VMconfig.Boot -match “true”) {
Out-Log “Booting $vmName” “Yellow”
$VM | Start-VM -EA SilentlyContinue | Out-Null
}
$taskTab.Remove($_.Id)
$runningTasks–
If ($Error.Count -ne 0) {
Out-Log “$vmName completed with errors” “Red”
Foreach ($err in $Error) {
Out-Log “$Err” “Red”
}
$failReconfig += @($vmName)
} Else {
Out-Log “$vmName is Complete” “Green”
$successVMs += @($vmName)
}
}
elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq “Error”){
# Deployment failed
$failed = $taskTab[$_.Id]
Out-Log “`n$failed failed to deploy!`n” “Red”
$taskTab.Remove($_.Id)
$runningTasks–
$failDeploy += @($failed)
}
}
Start-Sleep -Seconds 10
}
#——————————————————————–
# Close Connections
Disconnect-VIServer -Server $vcenter -Force -Confirm:$false
#——————————————————————–
# Outputs
Out-Log “`n**************************************************************************************”
Out-Log “Processing Complete” “Yellow”
If ($successVMs -ne $null) {
Out-Log “`nThe following VMs were successfully created:” “Yellow”
Foreach ($success in $successVMs) {Out-Log “$success” “Green”}
}
If ($failReconfig -ne $null) {
Out-Log “`nThe following VMs failed to reconfigure properly:” “Yellow”
Foreach ($reconfig in $failReconfig) {Out-Log “$reconfig” “Red”}
}
If ($failDeploy -ne $null) {
Out-Log “`nThe following VMs failed to deploy:” “Yellow”
Foreach ($deploy in $failDeploy) {Out-Log “$deploy” “Red”}
}
$finishtime = Get-Date -uformat “%m-%d-%Y %I:%M:%S”
Out-Log “`n`n”
Out-Log “**************************************************************************************”
Out-Log “$scriptName`t`t`t`t`tFinish Time:`t$finishtime”
Out-Log “**************************************************************************************”
———–end of script—————–
Hello Rehman,
I also created a new version and I sahred it here http://www.vidanez.com/2014/11/02/crear-multiples-linux-vms-de-un-fichero-csv-usando-powercli-deploying-multiple-linux-vms-using-powercli/ Also I sharing it at https://github.com/Vidanez/DeployVMs
If you want we could merge your version with my version using github. We could create the version 1.4 have a look.
Regards,
JJ
Hello, I’ve been using the script for a few weeks now, saved a lot of time and effort on new builds of environments, so firstly thanks!
When running the script to deploy, say, 20 VM’s, What i see happening is that first 4 or 5 machines are started, then shortly afterwards all other machines are then started for deployment. What rules/process govern the number of machines that are deployed at once? ie, if i want the system to build 5 systems at a time out of a batch?
Regards
Adrian
Hi There
Currently there are no throttling rules within the script (though there probably should be).
You might want to check the vCenter tasks to see if any are queuing
Great script, saves me tons of time! Is there a way to select additional datastores for Disk2,Disk3 type deployments.
Looks like this is a very nice script, however, having issues with it and it fails. Running on vCenter 6 and PowerCLI 6.0 R2 Below is error:
testvm failed to deploy!
Index operation failed; the array index evaluated to null.
4/13/2016 10:41:32 AM New-VM VIContainer parameter: Could not find any of the objects specified by name.
Any ideas on why? I cant seem to figure it out
Hi Mike
I haven’t had a chance to use on v6 yet – may or may not be the issue here.
It looks as though it does not like the item specified in the csv under ResourcePool. This should contain the name of a Resource Pool, Host or Cluster.
Hi,
i’m facing some problems and i hope you can help.
i’m using 3 different vcenter servers (selected by params in the csv).
2 are ok but the third recently failing with vm exist. the thing is that the vm doesn’t exist until the new-vm command, and then in the vc it looks like there are two attempts to clone the vm, 2 seconds apart (the first start the clone and 2 secs later there is a failure that the vm exist).
i can’t find any thing that will explain this behavior, not in the script and not in the vc logs.
any thoughts/ideas?
thanks
mor
Hi Mor
It looks as though per the VMware forums that you got this solved?
Hope all is well!
i used this script and its working. But when i mention cluster names for Host and datastore its not wworking. i have to give specific host and lun which is again making issue on resource usages
This shouldn’t be an issue as clusters and datastore clusters should both be supported.
What version of vSphere/PowerCLI/PowerShell are you running?
Hi I am having issue with this script can someone help please.
I have ESX clusters CL01 and CL02; both clusters have resource pool called “Infrastructure”.
In my csv under Folder option I have CL02 and under resourcepool option I have “Infrastructure” but script fails with following errors:
Deploying vm1-jaw
Index operation failed; the array index evaluated to null.
At C:\Users\jabbasi\Documents\DeployVM-ShawnM\DeployVMs.ps1:265 char:5
+ $taskTab[(New-VM -Name $VM.Name -ResourcePool $VM.ResourcePool -Location $VM …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
vm1-jaw failed to deploy!
Index operation failed; the array index evaluated to null.
6/2/2016 9:54:00 AM New-VM VIContainer parameter: Could not find any of the objects specified by name.
6/2/2016 9:54:00 AM New-VM The specified parameter ‘ResourcePool’ expects a single value, but your name criteria ‘Infrastructure’ corresponds to multiple values.
Deploying vm2-jaw
Index operation failed; the array index evaluated to null.
At C:\Users\jabbasi\Documents\DeployVM-ShawnM\DeployVMs.ps1:265 char:5
+ $taskTab[(New-VM -Name $VM.Name -ResourcePool $VM.ResourcePool -Location $VM …
Hello
It looks like I can see two issues
1) Do you have a blue folder called CL02? You mention you have a cluster called CL02 – this is not a blue folder
2) It appears you have multiple resources called Infrastructure – this is going to error as it doesn’t know which Infrastructure to place the VM in
HTH
Hi Shawn
Clusters are not really shown like a folder; hierarchy I have is
DC (which is building) > CL01 (which is ICON with 3 Computers) > ResourcePool (infrastructure) that is a blue Circle
DC (which is building) > CL02 (which is ICON with 3 Computers) > > ResourcePool (infrastructure) that is a blue Circle
Hi Shawn
Clusters are not really shown like a folder; hierarchy I have is
DC (which is building) > CL01 (which is ICON with 3 Computers) > ResourcePool (infrastructure) that is a blue Circle
DC (which is building) > CL02 (which is ICON with 3 Computers) > > ResourcePool (infrastructure) that is a blue Circle
It sounds as though you are looking at the ‘Hosts and Clusters’ view. Using your description I would say CL01 and CL02 are Hosts.
Try switching to the ‘VMs and Templates’ view – this is where you will find blue folders (if there are any)
Hello Shawn Masterso,
I have created the version 1.6 of the script and its available at https://github.com/Vidanez/DeployVMs/blob/master/DeployVM.ps1
NOTES
Author: Shawn Masterson
Created: May 2014
Version: 1.2
Author: JJ Vidanez
Created: Nov 2014
Version: 1.3
Add creation onthefly for customization Spec for linux systems
Ability to create machines names and guest hostname using different names
Added a value to find out the kind of disk because powercli bug for SDRS reported at https://communities.vmware.com/message/2442684#2442684
Remove the dependency for an already created OScustomization Spec
Author: JJ Vidanez
Created: Jul 2015
Version: 1.4
Adding domain credential request for Windows systems
Author : Simon Davies – Everything-Virtual.com
Created : May 2016
Version: 1.5
Adding AD Computer Account Creation in specified OU’s for VM’s at start of deployment – Yes even Linux as that was a requirement
It’s possible to restrict this to just Windows VM’s by removing the comment at line #261
Author: JJ Vidanez & Robert Rowan
Created: Jun 2016
Version: 1.6
Fixed issue to deploy just one VM
Adding banner for each credential to show the domain where credentials are set
If OU parameter is defined at the OU create the object on AD where the machine is register Linux and Windows
Hey Shawn, great script, I owe you a beer! Quick question, do you know of a way to run some Linux commands at VM creation time in a similar fashion to AWS’ user data or a kickstart file’s %post section?
Try looking at Invoke-VMScript
https://www.vmware.com/support/developer/PowerCLI/PowerCLI55/html/Invoke-VMScript.html
Awesome, thanks, I will check that out.
Newest version 1.6 doesn’t like any vCenter i input “unable to connect to vCenter”. Also our “Administrator” account PW starts with a bang “!” and it seems the script errors out when inputting the exclamation…Still using version 1.4 and it works just fine…
Hi Adam
Might need some clarification here as the script has only v1.0 (original) and v1.2.1 (latest).
All versions of the script simply connect to a vcenter using the account running the command via this simple line:
Connect-VIServer $vcenter -EA Stop
(Where $vcenter is the server name/IP given when prompt)
Ahhh i see what i did…i followed the link in this post to the “new” modified version that someone else has contributed to…
https://github.com/Vidanez/DeployVMs/blob/master/DeployVM.ps1
I’m running the script and it is deploying the VMs OK but when it comes to re-configure them it fails saying “Get-VM VM with name’XXXXXXX’ was not found using the specified filter(s).”
I’m not sure if this is because the name of the VM as seen in vSphere (in the csv file the NameVM field) and the the actual servername (in the csv file the Name field) are different (long story relating to different departments requirements).
The NameVM field = test01vm
The Name field = TestWin01VM.
Output error:
Reconfiguring TestWin01VM
Get-VM : 10/13/2016 3:10:34 PM Get-VM VM with name ‘TestWin01VM’ was not found using the
specified filter(s).
At C:\vmdeploy\csvdeploy_1_2.ps1:357 char:13
+ $VM = Get-VM $vmName
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
+ FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Co
mmands.GetVM
Setting vCPU(s) and RAM on TestWin01VM
Setting Port Group on TestWin01VM
Adding additional disk on TestWin01VM – don’t forget to format within the OS
Booting TestWin01VM
TestWin01VM completed with errors
10/13/2016 3:10:34 PM Get-VM VM with name ‘TestWin01VM’ was not found using the specified filter(s).
It appears as though you have customized the script as currently it does not have the ability to account for the VM name being different from the OS name
Thanks to spotting the.
I somehow got a copy that was saying it was version 1.3.
using 1.2 the above error disappears.Now I have another issue.
It is unable to set the portgroup.
I get the following error:
Set-NetworkAdapter : 10/14/2016 8:40:57 AM Set-NetworkAdapter The specified parameter ‘Portgroup’ expects a
single value, but your name criteria ‘10.105.19_Corp_Test’ corresponds to multiple values.
At C:\vmdeploy\csvdeploy.ps1:319 char:31
+ $VM | Get-NetworkAdapter | Set-NetworkAdapter @network | Out-Nu …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidResult: (System.Collecti…dObjectInterop]:List`1) [Set-NetworkAdapter], VimExcep
tion
+ FullyQualifiedErrorId : Core_ObnSelector_SelectObjectByNameCore_MoreResultsThanExpected,VMware.VimAutomation.ViC
ore.Cmdlets.Commands.VirtualDevice.SetNetworkAdapter
Set-NetworkAdapter : 10/14/2016 8:40:57 AM Set-NetworkAdapter Value cannot be found for the mandatory
parameter Portgroup
At C:\vmdeploy\csvdeploy.ps1:319 char:31
+ $VM | Get-NetworkAdapter | Set-NetworkAdapter @network | Out-Nu …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-NetworkAdapter], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.VirtualDevice.
SetNetworkAdapter
Any suggestions?
This could be a couple of things
1) Do you have multiple objects by the same name, even different types of objects?(10.105.19_Corp_Test)
2) Do you have multiple connections open? (Can check with $defaultVIServers)
3) You could try using Get-VirtualPortGroup (or Get-VDPortGroup if using vDS) to see what is returned for the name (ex: Get-VirtualPortGroup -Name “10.105.19_Corp_Test”)
When I run Get-VirtualPortGroup -Name “10.105.19_Corp_Test” I get the following:
PowerCLI C:\> Get-virtualPortGroup -Name “10.105.19_Corp_test”
Name Key VLanId PortBinding NumPorts
—- — ———- ————— ————–
10.105.19_Corp_Test key-vim.host.PortGroup-10.1… 19
10.105.19_Corp_Test key-vim.host.PortGroup-10.1… 19
10.105.19_Corp_Test key-vim.host.PortGroup-10.1… 19
The cluster I’m using has 3 hosts and each host has the same PortGroups configured on them.
This is the standard way our clusteres are configured.
I need it to be able to build the VM on any of the hosts and use the same PortGroup whichever host it uses.
Not sure what is going on here. I just ran a fresh test and had no issues on vSphere 5.5/PowerCLI 5.5.
At this point even though the script ended with error, the VM should actually be created, so we can do some tests. Try the following and see what you get:
$vmName = “NameOfCreatedVM”
$networkName = “10.105.19_Corp_Test”
$VM = Get-VM $vmName
$VM | Get-NetworkAdapter | Set-NetworkAdapter -NetworkName $networkName
That is pretty much the standard was to assign a network name to a VM adapter. Beyond that, I am not sure…maybe try this link for more info:
https://communities.vmware.com/thread/307621?start=0&tstart=0
Wonderful Script, i have one question for non applicable fields what i need to mention in csv. for example, we don’t user resource pool,SDRS & other things. Please advise.
Optional fields are marked as such in the Notes (optional).
Without DRS/sDRS you’ll need to specify a particular Host or Datastore for the VM as opposed to a Cluster or Datastore Cluster.
I love your script but am having some issues. Well only one issue now, I have worked through the other issues I had. Now it all comes down to the NIC. As soon as I deploy a VM I get a bunch of errors about setting the NIC customization.
Set-OSCustomizationNicMapping : 4/21/2017 1:37:27 PM Set-OSCustomizationNicMapping
Required property ip is missing from data object of type CustomizationIPSettings
while parsing serialized DataObject of type vim.vm.customization.IPSettings
at line 1, column 2058
while parsing property “adapter” of static type CustomizationIPSettings
while parsing serialized DataObject of type vim.vm.customization.AdapterMapping
at line 1, column 2043
while parsing property “nicSettingMap” of static type ArrayOfCustomizationAdapterMapping
while parsing serialized DataObject of type vim.vm.customization.Specification
at line 1, column 586
while parsing property “spec” of static type CustomizationSpec
while parsing serialized DataObject of type vim.CustomizationSpecItem
at line 1, column 335
while parsing call information for method OverwriteCustomizationSpec
at line 1, column 218
while parsing SOAP body
at line 1, column 207
while parsing SOAP envelope
at line 1, column 38
while parsing HTTP request for method overwrite
on object of type vim.CustomizationSpecManager
at line 1, column 0
At C:\Users\99gwilliams\Desktop\EBI VM Deploy\DeployVM.ps1:244 char:53
+ … pec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-OSCustomizationNicMapping], InvalidRequest
+ FullyQualifiedErrorId : Client20_VMGuestServiceImpl_ModifyServersideSpec_ViError,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetOSCustomizationNicMapping
I have DHCP set to true in the CSV, I have also tried setting it to true but still putting IP information in. I need it to set the DNS, but use DHCP for everything else. In my Customization I previously had it set up to use DHCP but set DNS, per your recommendation at the top I told it to use typical settings instead.
The VM continues to deploy but once completed the NIC is not set to CONNECTED or CONNECT AT POWER ON. I need the NIC connected in order to finish out the customization that joins it to the domain.
Any help would be greatly appreciated.
Here is the CSV file.
Name,Boot,OSType,Template,CustSpec,Folder,ResourcePool,CPU,RAM,Disk2,Disk3,Disk4,Datastore,DiskStorageFormat,NetType,Network,DHCP,IPAddress,SubnetMask,Gateway,pDNS,sDNS,Notes
IND01-GlynnTest,FALSE,Windows,EBI-Template-DomainJoin,EBI-Virtual-Desktops,EBI Remote Desktops,NYC_Nehelem,2,6,,,,vnx_cluster,thin,vDS,VLAN62,TRUE,,,,8.8.8.8,4.4.4.4,
Getting this error…
Set-OSCustomizationNicMapping : 06/11/2017 16:58:27 Set-OSCustomizationNicMapping When the IpMode parameter is set to UseStaticIp, you must specify the IPAddress, Subnetmask,
Dns(on Windows specs only), and DefaultGateway parameters.
At \\Petpsinfra01\d$\Scripts\PowerCLI Scripts\Test Scripts\Multi-VM Deployment.ps1:246 char:54
+ … pec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-OSCustomizationNicMapping], ViError
+ FullyQualifiedErrorId : Core_NicMappingCmdletBase_ValidateParameters_RequiredParametersSaticIp,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetOSCustomizationNicMapping
Deploying Kirk VM Test
Index operation failed; the array index evaluated to null.
At \\Petpsinfra01\d$\Scripts\PowerCLI Scripts\Test Scripts\Multi-VM Deployment.ps1:254 char:5
+ $taskTab[(New-VM -Name $VM.Name -ResourcePool $VM.ResourcePool -L …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
Hi Kirk
Does your csv contain all required info?
From your error msg – When the IpMode parameter is set to UseStaticIp, you must specify the IPAddress, Subnetmask,
Dns(on Windows specs only), and DefaultGateway parameters.
Ok thanks Ill give that a try!
Thank you for this script – it has helped out immensely.
I’ve recently upgraded vCenter to 6.5 and along with it – the powercli version as well.
Now when I run the script, I receive the following error:
Set-NetworkAdapter : 12/19/2017 10:13:22 AM Set-NetworkAdapter Value cannot be null.
Parameter name: collection
+ … pter -Name “Network Adapter 1” | Set-NetworkAdapter @network1 | Out-N …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-NetworkAdapter], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.VirtualDevice.
SetNetworkAdapter
This was never the case on 5.5 – any input / guidance on this would be appreciated.
Try to check manually the command for the network creation, you will find that is not valid anymore in 6.5. There is a new command now the same that is use to be only valid for VDS
Hi, under powercli v6.0 and vcenter 6.5 we’ve found the script deploys the VMs with 8 cores per socket
looks like powerCLI v6.5 adds the -CoresPerSocket option
So I’ll need to update my PowerCLI to 6.5 to test this modification to the script.
How was a request for say 8 vCPU handled before 6.5? (2sockets x 4 cores / socket)?
What kind of logic have folks maybe added to handle the vCPU -> sockets x cores/socket translation in the script?
thanks!
Hi,
i addressed this issue with this code after new vm task successed:
# Set CPU and RAM
Out-Log “Line 365: Setting vCPU(s)=$VMconfig.CPU and RAM=$VMconfig.RAM on $vmName” “Yellow”
$VM | Set-VM -NumCpu $VMconfig.CPU -MemoryGB $VMconfig.RAM -Confirm:$false | Out-Null
if ($cpu -gt 4) {
#$NmbrCPU = 4
$NmbrCore = $cpu/2
Out-Log “Line 370: NumCoresPerSocket = $NmbrCore numCPUs = $VMconfig.CPU” “Yellow”
$specpu = New-Object -Type VMware.Vim.VirtualMachineConfigSpec -Property @{“NumCoresPerSocket” = $NmbrCore;”numCPUs” = $VMconfig.CPU}
(Get-VM -Name $vmName -Location $cluster -Server $vcserver).ExtensionData.ReconfigVM_Task($specpu)
}
I am trying to set this script to install multiple VM’s from the command line, and I am having the following issue.
Enter vCenter server FQDN or IP: vcenter.vsphere.local
Connecting to vCenter – vcenter.vsphere.local
Unable to connect to vcenter.vsphere.local
Exiting…
What I have tried to troubleshoot the problem:
I have tried to connect directly to the vcenter using connect-viserver from the Powershell window.
PS C:\Deploy> Connect-VIServer vcenter.vsphere.local
Name Port User
—- —- —-
vcenter.vsphere.local 443 VSPHERE.LOCAL\Administrator
PS C:\Deploy>
I tried using the IP address of the VCenter server
PS C:\Deploy> Connect-VIServer 10.0.0.100
Name Port User
—- —- —-
10.0.0.100 443 VSPHERE.LOCAL\Administrator
PS C:\Deploy>
My PowerCLI is good.
PS C:\Deploy> Get-PowerCLIVersion
PowerCLI Version
—————-
VMware PowerCLI 10.0.0 build 7895300
—————
Component Versions
—————
VMware Cis Core PowerCLI Component PowerCLI Component 10.0 build 7893915
VMware VimAutomation VICore Commands PowerCLI Component PowerCLI Component 10.0 build 7893909
PowerCLI Version
—————-
VMware PowerCLI 10.0.0 build 7895300
—————
Component Versions
—————
VMware Cis Core PowerCLI Component PowerCLI Component 10.0 build 7893915
VMware VimAutomation VICore Commands PowerCLI Component PowerCLI Component 10.0 build 7893909
I think my Powershell is good. I can ping both front ways and backwards.
PS C:\Deploy> $PSVersionTable.PSVersion
Major Minor Build Revision
—– —– —– ——–
5 1 16299 251
PS C:\Deploy> ping vcenter.vsphere.local
Pinging vcenter.vsphere.local [10.0.0.100] with 32 bytes of data:
Reply from 10.0.0.100: bytes=32 time=1ms TTL=64
Reply from 10.0.0.100: bytes=32 time=1ms TTL=64
Reply from 10.0.0.100: bytes=32 time=3ms TTL=64
Reply from 10.0.0.100: bytes=32 time=2ms TTL=64
Ping statistics for 10.0.0.100:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 1ms, Maximum = 3ms, Average = 1ms
PS C:\Deploy>
PS C:\Deploy> ping 10.0.0.100
Pinging 10.0.0.100 with 32 bytes of data:
Reply from 10.0.0.100: bytes=32 time=1ms TTL=64
Reply from 10.0.0.100: bytes=32 time=1ms TTL=64
Reply from 10.0.0.100: bytes=32 time=2ms TTL=64
Reply from 10.0.0.100: bytes=32 time=2ms TTL=64
Ping statistics for 10.0.0.100:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 1ms, Maximum = 2ms, Average = 1ms
PS C:\Deploy>
It just does not look like it is even trying to connect to the VCenter. It just goes boom, and then boom it fails.
I would appreciate any help that could be provided.
Try changing
Connect-VIServer $vcenter -EA Stop | Out-Null
To
Connect-VIServer $vcenter -EA Stop
This should force the error to be shown and help determine what the issue is.
Dear Author,
This is the excellent script for deploy VM in VMware and it does the job nicely.
How do we use the same script when we need to deploy VM from a content library instead of Template?
I just ran into this same issue, doing some research on the matter now. I’ve been using PowerCLI for scripting new VMs (from Template) with OSCustomizationSpec just fine, but that tag is no longer available when using -ContentLibraryItem flag.
I just found this article on Reddit, going to experiment here. Perhaps just running this set-vm command for the OSCustomizationSpec configuration after the VM is built (from content library) but before it’s turned on the first time.
https://www.reddit.com/r/vmware/comments/91jli8/content_library_template_deployment_via_powercli/
Hi all,
does anyone got a version running with 2 nic‘s to deploy.