VMware Cloud Community
jvm2016
Hot Shot
Hot Shot
Jump to solution

host_upgrade_patch_esxi_powercli

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.

pastedImage_0.png

#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.

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

View solution in original post

Reply
0 Kudos
12 Replies
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

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.

Reply
0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

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

pastedImage_0.png

also type is below .

pastedImage_2.png

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

Thanks  I am checking this .could you explain more about cst and sst or any page about them.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

Thanks iam going to check this.

Reply
0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

Thnaks iam checking this.

Reply
0 Kudos