Hello Luc,
Good morning,
few days back i discussed with you regarding powercli script to upgrade esxi hosts.
below is the code with few modification like
1:including both upgrade and patch baseline in single command .
2:assigning license key .
i was hoping below code will loop on each esxi host of cluster as we are using foreach but it did not happen and stuck at following
also the upgrading host bar does not progress as we thought as per code below.
#code
$vcenter=read-host "vcenter name"
$cred=Get-Credential
$std_version=Read-Host "what version you want to upgrade to"
$std_build=read-host "what build you want to update to"
$license=read-host "specify license key"
connect-viserver -server $vcenter -Credential $cred
#$baseline_cisco= get-baseline -Name 'Cisco Custom ESXi 6.5 Upgrade'
import-module vmware.vumautomation
$baseline_dell=get-baseline -name "ESXi6.5Upgrade-Dell"
$baseline_dell_patch=Get-PatchBaseline -Name "ESXI 6.5 20180604001_19thAug2018"
#above can be different baseline also depending on the model.
$cluster=read-host "cluster name"
set-cluster -Cluster $cluster -DrsAutomationLevel FullyAutomated
Set-Cluster -Cluster $cluster -HAAdmissionControlEnabled $false
$hosts_cluster=get-vmhost -location $cluster
$count=$hosts_cluster.count
$count
# start vmotion test is done using vmotion_test_function
foreach ($esx in $hosts_cluster)
{
$esxi=get-vmhost -name $esx
write-host "currently working on "$esxi.name -ForegroundColor Green
if ($esxi.version -ne $std_version -and $esxi.build -ne $std_build)
{
write-host $esxi.name "needs to be upgraded to " $std_version "and" $std_build -BackgroundColor Yellow
write-host "putting host" $esxi.name "in mainteneace mode"
$maint = Set-VMHost -VMHost $esxi -State Maintenance -RunAsync
Do
{
Write-Host -NoNewline '.'
sleep 1
$esxi = Get-VMHost -Name $esxi.name
} until ($esxi.State -eq "maintenance" -and $maint.PercentComplete -eq 100)
Write-Host "`rDone"
Write-Output "Task '$($maint.Description)/$($maint.Id)' for $($maint.Result.Name) ended with status $($maint.State)"
}
else
{
write-host $esxi "is on standard version and build"
}
if($esxi.Manufacturer -match "Dell Inc.")
{
Attach-Baseline -Entity $esxi -Baseline $baseline_dell,$baseline_dell_patch
$update_esxi=Update-Entity -Baseline $baseline_dell,$baseline_dell_patch -Entity $esxi -runasync
while('Running','Queued' -contains $update_esxi.State){
Write-Progress -Activity 'upgrading host ' -PercentComplete $update_esxi.PercentComplete
sleep 2
}
Write-Output "Task '$($update_esxi.Description)/$($update_esxi.Id)' for $($update_esxi.Result.Name) ended with status $($update_esxi.State)"
#assigning license to upgraded host
set-vmhost -vmhost $esxi -LicenseKey $license
#taking host out of maintenance mode.
Set-VMHost -VMHost $esxi -State Connected
Start-Sleep -Seconds 240
}}
is it possible for you take a look one more time on above code.
That is because a svMotion is not producing a CST (client-side task) object, but a SST (server-side task) object.
With a SST the progress is under the Info property, and is not updated automatically.
You will need to refresh that property explicitly.
For example:
$vmName = 'MyVM'
$dsName = 'MyDS'
$sst = Get-VM -Name $vmName | Move-VM -Datastore $dsName -RunAsync
Write-Progress -Activity 'svMotion' -PercentComplete 0
while('success','error' -notcontains $sst.ExtensionData.Info.State){
Write-Progress -Activity 'svMotion' -PercentComplete $sst.ExtensionData.Info.Progress
$sst.ExtensionData.UpdateViewData('Info')
}
Write-Progress -Activity 'svMotion' -Completed
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You forgot the Completed call to Write-Progress.
I also replaced the sleep line with a loop.
$vcenter=Read-Host "vcenter name"
$cred=Get-Credential
$std_version=Read-Host "what version you want to upgrade to"
$std_build=Read-Host "what build you want to update to"
$license=Read-Host "specify license key"
Connect-VIServer -server $vcenter -Credential $cred
#$baseline_cisco= Get-Baseline -Name 'Cisco Custom ESXi 6.5 Upgrade'
Import-Module vmware.vumautomation
$baseline_dell=Get-Baseline -name "ESXi6.5Upgrade-Dell"
$baseline_dell_patch=Get-PatchBaseline -Name "ESXI 6.5 20180604001_19thAug2018"
#above can be different baseline also depending on the model.
$cluster=Read-Host "cluster name"
Set-Cluster -Cluster $cluster -DrsAutomationLevel FullyAutomated
Set-Cluster -Cluster $cluster -HAAdmissionControlEnabled $false
$hosts_cluster=Get-VMHost -location $cluster
$count=$hosts_cluster.count
$count
# start vmotion test is done using vmotion_test_function
foreach ($esx in $hosts_cluster)
{
$esxi=Get-VMHost -name $esx
write-host "currently working on "$esxi.name -ForegroundColor Green
if ($esxi.version -ne $std_version -and $esxi.build -ne $std_build)
{
Write-Host $esxi.name "needs to be upgraded to " $std_version "and" $std_build -BackgroundColor Yellow
Write-Host "putting host" $esxi.name "in mainteneace mode"
$maint = Set-VMHost -VMHost $esxi -State Maintenance -RunAsync
Do
{
Write-Host -NoNewline '.'
sleep 1
$esxi = Get-VMHost -Name $esxi.name
} until ($esxi.State -eq "maintenance" -and $maint.PercentComplete -eq 100)
Write-Host "`rDone"
Write-Output "Task '$($maint.Description)/$($maint.Id)' for $($maint.Result.Name) ended with status $($maint.State)"
}
else
{
Write-Host $esxi "is on standard version and build"
}
if($esxi.Manufacturer -match "Dell Inc.")
{
Attach-Baseline -Entity $esxi -Baseline $baseline_dell,$baseline_dell_patch
$update_esxi=Update-Entity -Baseline $baseline_dell,$baseline_dell_patch -Entity $esxi -runasync
while('Running','Queued' -contains $update_esxi.State){
Write-Progress -Activity 'upgrading host ' -PercentComplete $update_esxi.PercentComplete
sleep 2
}
Write-Output "Task '$($update_esxi.Description)/$($update_esxi.Id)' for $($update_esxi.Result.Name) ended with status $($update_esxi.State)"
Write-Progress -Activity 'upgrading host ' -Completed
#assigning license to upgraded host
Set-VMHost -VMHost $esxi -LicenseKey $license
#taking host out of maintenance mode.
Set-VMHost -VMHost $esxi -State Connected
Write-Host "putting host" $esxi.name "in connected mode"
$connect = Set-VMHost -VMHost $esxi -State Connected -RunAsync
Do
{
Write-Host -NoNewline '.'
sleep 1
$esxi = Get-VMHost -Name $esxi.name
} until ($esxi.State -eq "connected" -and $connect.PercentComplete -eq 100)
Write-Host "`rDone"
Write-Output "Task '$($connect.Description)/$($connect.Id)' for $($connect.Result.Name) ended with status $($connect.State)"
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc,
I am going to check this
however checking the following piece of code again
$update_esxi=Update-Entity -Baseline $baseline_dell,$baseline_dell_patch -Entity $esxi -runasync
while('Running','Queued' -contains $update_esxi.State){
Write-Progress -Activity 'upgrading host ' -PercentComplete $update_esxi.PercentComplete
sleep 2
}
Write-Output "Task '$($update_esxi.Description)/$($update_esxi.Id)' for $($update_esxi.Result.Name) ended with status $($update_esxi.State)"
Write-Progress -Activity 'upgrading host ' -Completed
i thought only following line is sufficient as this is how we define the progress in maintenance mode also (but with do...untill loop)
Write-Output "Task '$($update_esxi.Description)/$($update_esxi.Id)' for $($update_esxi.Result.Name) ended with status $($update_esxi.State)"
also i am thinking if "wait-event "(or any other powershell eqivalent command) has some inbuilt logic to avoid above piece of code
The line with the Completed switch makes sure the Write-Progress bar is removed.
Otherwise the bar will stay on screen at 100%.
There is no such "wait-event" cmdlet for Async tasks afaik.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc.
i am going to check this again however the bar stays @ zero percent (as shown in screen shot )only though i can see host being upgraded in web client.
Hi Luc,
i tried to test this with storage vmotion .
and used following code .but progress bar never refreshes (it stays as mentioned below in screenshot) nor it gave completed even after putting Write-Progress -Activity 'storage vmotion' -Completed
$vm=get-vm "some_vm"
$svmotion_vm=Move-VM -VM $vm -Datastore "some_datastore" -RunAsync
while('Running','Queued' -contains $svmotion_vm.State){
Write-Progress -Activity 'storage vmotion ' -PercentComplete $svmotion_vm.PercentComplete
sleep 2
}
Write-Output "Task '$($svmotion_vm.Description)/$($svmotion_vm.Id)' for $($svmotion_vm.Result.Name) ended with status $($svmotion_vm.State)"
Write-Progress -Activity 'storage vmotion' -Completed
also type is below .
That is because a svMotion is not producing a CST (client-side task) object, but a SST (server-side task) object.
With a SST the progress is under the Info property, and is not updated automatically.
You will need to refresh that property explicitly.
For example:
$vmName = 'MyVM'
$dsName = 'MyDS'
$sst = Get-VM -Name $vmName | Move-VM -Datastore $dsName -RunAsync
Write-Progress -Activity 'svMotion' -PercentComplete 0
while('success','error' -notcontains $sst.ExtensionData.Info.State){
Write-Progress -Activity 'svMotion' -PercentComplete $sst.ExtensionData.Info.Progress
$sst.ExtensionData.UpdateViewData('Info')
}
Write-Progress -Activity 'svMotion' -Completed
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks I am checking this .could you explain more about cst and sst or any page about them.
There is no real info on CST and SST available right now.
The only source I know of is the VMworld session VIN1992BE Kyle and myself did.
In short, some PowerCLI cmdlets determine that a background task can be a CST.
This decision is made on the basis of the number of calls to vSphere a cmdlet makes under the cover.
If only one call, a CST is used instead of a SST.
The reason, a CST is quicker than a SST.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks iam going to check this.
could you comment on following .
the whole idea of putting -runasync switch is to put that task in background .
putting while loop after that(depending on client side and server side task)t is to check progress and make sure task completed so that script can move to next task .
however if i dont put -runasync (and while loop) then that task will complete first and then move to next task (referring to upgrade script of putting host into maint mode and then upgrading host)
and using inherent progress of commands we can check the progress of individual task.and this is what we desired at very beginning.
What I normally do, I start a number of background task, and collect the Task objects (beit CST or SST) in an array.
Then I loop over the array of Task objects, and wait till they are done.
This way you will multiple background tasks running in parallel.
Another option is to go for a maximum number of background tasks.
When that number is reached, the script waits till at least one of those tasks is completed, before starting a new background task.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thnaks iam checking this.