Dear one and all
Having messed around with Powercli for some time now I've started to slowly move into the realms of script writing using 'Advanced Functions'. One of the main reasons was I like the way functions act more like cmdlets and hence I thought I'd give it a shot and write one to help me update the 'virtual hardware' versions of my VMs to its latest (v10). Now I would like to point out that my script DOES WORK. However, once you look at it you will realise its REALLY SLOW. Thats the failure on my part as I've created a foreach loop which simply goes through each VM 'asynchronously'. (i.e. one after the other) and obviously doing this on hundreds of VMs can be quite time consuming!
. This is where I need some help. Could you supply me with some 'pointers' as to a way where I might be able to batch say '20' VMs at a time ??? . This would save loads of time on my part. and allow my function to run a lot more efficiently.
As always many thanks in advance
Munster
Function Update-VirtualHardware {
<#
.SYNOPSIS
This will update the Virtual Hardware to v10 for Virtual machines
.DESCRIPTION
This function shuts down the VM, Updates its virtual hardware and finally Powers the
VM back on
.PARAMETER VMName
A VM object is required
.INPUTS
Input Object Type = [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]
.EXAMPLE
Update-VirtualHardware -VMname (get-VM -VM VM1)
#>
[CmdletBinding()]
PARAM
(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
HelpMessage = "Please enter a VM Object",
Position=0)]
[ValidateNotNullOrEmpty()]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl[]]$VMName,
[Parameter()]
[string]$ErrorLogFilePath = "C:\Errors.txt",
[Parameter()]
[switch]$LogErrors
)
BEGIN {
Write-Verbose "Error log will be $ErrorLogFilePath"
Del $ErrorLogFilePath -ErrorAction SilentlyContinue
}
PROCESS {
Foreach ($VM in $VMName){
if (($VM.PowerState -eq "PoweredOn") -and ($VM._VMToolsRunningStatus -eq "guestToolsRunning") -and ($VM.Version -ne "v10")) {
Write-Verbose "Shutting Down $VM"
$vm | Shutdown-VMGuest -Confirm:$false | Out-Null
#Wait for Shutdown to complete
do {
#Wait 5 seconds
Start-Sleep -s 5
#Check the power status
$vm = Get-VM -Name $vm
$status = $vm.PowerState
}until($status -eq "PoweredOff")
Try{
# UPGRADING THE VM
Write-Verbose "UPGRADING $VM"
Set-VM -VM $VM -Version v10 -confirm:$false -ErrorAction Stop | Out-Null
# POWERING ON THE VM
Write-Verbose "POWERING ON $VM"
$vm | Start-VM -Confirm:$false | Out-Null
}
Catch{
Write-Warning "$VM Failed to upgrade - logging ComputerName to $ErrorLogFilePath"
$VM.name | Out-File $ErrorLogFilePath -Append # append to the Errors logfile
}
}
elseif (($VM._VMToolsRunningStatus -ne "guestToolsRunning") -or ($VM.Version -eq "v10")) {
Write-Verbose "$vm VM Tools are NOT running or it is already at v10"
$VM.name | Out-File $ErrorLogFilePath -Append # append to the Errors logfile
}
}
}
END { }
}
One option would be to fire off the actions with a Start-Job, that way they will run in the background.
An other option is to use a Workflow which also allows parallelism.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
