Hi
I want to do a check on a nested env, for if there are more than 1 host - move VM to another random
if there are only 1 host on a nested env, just shut them off so later can set the host to maintenance mode.
I got only the part of the moving, need help to check if there are more than 1 host exists on the env
if($vms){
foreach ($vm in $vms) {
if($vm.PowerState -ne "PoweredOn"){
$randhosts = Get-VMHost -Location $clusterName | Get-Random
Move-VM -VM $vm -Destination $randhosts -Datastore $ds
}
}
}
I'm looking to add to that part, the check "if there are only 1 Host = Shut down VMs. if there are more than 1 Host, do that script above"
Thanks in advance for the help!
Something like this?
if ($vms) {
foreach ($vm in $vms) {
$esx = Get-VMHost -Location $clusterName
if ($esx.Count -eq 1) {
Shutdown-VMGuest -VM $vm -Confirm:$false
} else {
if ($vm.PowerState -eq "PoweredOn") {
$randhosts = Get-Random -InputObject $esx -Count 1
Move-VM -VM $vm -Destination $randhosts -Datastore $ds
}
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Something like this?
if ($vms) {
foreach ($vm in $vms) {
$esx = Get-VMHost -Location $clusterName
if ($esx.Count -eq 1) {
Shutdown-VMGuest -VM $vm -Confirm:$false
} else {
if ($vm.PowerState -eq "PoweredOn") {
$randhosts = Get-Random -InputObject $esx -Count 1
Move-VM -VM $vm -Destination $randhosts -Datastore $ds
}
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
yes sir thats it! forgot about simple count
another unrelated to the post question. but its relevant to the same automation I'm creating
so let me know if you need me to open a new post for that instead of posting in here...
anyway my next question is this (perhaps will be a bit complex one) :
so after the esxi upgrade is done, and im rebooting the nested host
whats the best way to - wait until the host is connected back on (from 'Not Responding' ) exit it from 'Maintenance' mode
and assign a license to the host
what I do is this:
$hostUpgrade = $hosts | Install-VMHostPatch -HostPath $dsPath
if($hostUpgrade -ne $null){
if($version -like "8.0*"){
$hosts | Set-VMHost -LicenseKey $license8
}
else {
$hosts | Set-VMHost -LicenseKey $license7
}
if($hosts.state -ne "Connected") {
do {
$hosts | Set-VMHost -State Connected -Confirm:$false
}
while($hosts.state -eq "Connected")
}
[System.Windows.MessageBox]::Show("The Host Successfully Upgraded!")
}
should I change if ($hostUpgrade -ne $null) to -ne $error perhaps?
and is that the correct way to do "wait until the host is back on" ?
because when I just go with 'while' its keep "Set VM Host" even when its already connected and not in maintenance mode.
Thanks in advance for the help
The Install-VMHostPatch cmdlet can result in 2 outcomes afaik.
If all went well, a VMHostPatchResult object is returned.
In that case your -ne $null would be ok.
I personally would check if there actually was an Install-VMHostPatch object returned.
if($hostUpgrade -is [VMware.VimAutomation.ViCore.Types.V1.Host.VMHostPatchResult]){
If things go wrong, I would force the cmdlet to end with an Exception.
The best way to handle those would be with a Try-Catch construct.
Something along these lines perhaps
$hosts | ForEach-Object {
try {
$hostUpgrade = Install-VMHostPatch -VMHost $_ -HostPath $dsPath -ErrorAction Stop
if ($hostUpgrade -is [VMware.VimAutomation.ViCore.Types.V1.Host.VMHostPatchResult]) {
# Your other post-patch commands
}
} catch {
Write-Host "Error: $_"
}
}
To check if the ESXi node needs a reconnection you can use the NeedsReconnect property in the VMHostPatchResult object.
If that property equals $true, you will need to do the reconcect.
If not, proceed.
Then leave the Maintenance mode, but I would always first check if the ESXi node is "Connected".
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
just tried this
if($hostUpgrade -is [VMware.VimAutomation.ViCore.Types.V1.Host.VMHostPatchResult]){
and it did not work. none of the commands inside
the
if($hostUpgrade -ne $null){
is working fine, I just trying to do the best of this part:
if($version -like "8.0*"){
$hosts | Set-VMHost -LicenseKey $license8
}
else {
$hosts | Set-VMHost -LicenseKey $license7
}
if($hosts.state -ne "Connected") {
do {
$hosts | Set-VMHost -State Connected -Confirm:$false
}
while($hosts.state -eq "Connected")
}
[System.Windows.MessageBox]::Show("The Host Successfully Upgraded!")
will that be the correct or best way to do the following as the script indicates:
If the selected version to upgrade is to 8 = assign the license8 to the host, otherwise assign license7
and second part, after the upgrade done, the *Nested* host required reboot so While its rebooting, as in 'Not Responding' wait for it and dont exit script, and then when its on and back in 'Maintenance' mode exit the maintenance mode and connect the host back.
and then finish the upgrade script
Did you check what is in $hostUpgrade?
Is it a single object?
And what is the type
$hostUpgrade.Count
$hostUpgrade.GetType()
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
the count print back '209'
and the get type prints back lot of info, which one am looking for?
the name is Object[]
the MemberType is TypeInfo
and there are alot more info
That is what I suspected, the result is from multiple ESXi nodes.
That is why a had a loop over $hosts in the snippet I posted earlier.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I see. I can stay with -ne $null its fine for me since its getting the results
Edit: actually I am selecting each time only 1 esx, why does it still get multiple esx nodes?
I only struggle a bit with the other part I posted, the waiting for host to connect etc
if you could help me with that please?
Since $hostUpdate is an array with 2309 (?) elements, your comparison with $null will not really work.
You will not detect that perhaps one or more patches failed.
See the PossibleIncorrectComparisonWithNull article for some background.
On the ESXi node connected issue, does $hosts contain more than 1 ESXi node?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
the $hostUpdate is an array with 209 elements looks like yes. atleast for the .count
I'm selecting every time only 1 ESXi host like this -
$HostIP = "ip"
$hosts = Get-VMHost | ?{$_.Name -like $HostIP}
so it will only get one esxi, which ever one I input
I just named the variable $hosts (plural) for my convenient. it might as well be just $host or $esxi or what ever singular variable name will be more convenient
On the patching concept.
When you do an Install-VMHostPatch, the returned object(s) each contain 2 properties: NeedsReconnect and NeedRestart.
Depending on the values in those properties, your script needs to take action.
I would do something along these lines (but I haven't tested that code).
try {
$hostUpgrade = Install-VMHostPatch -VMHost $hosts -HostPath $dsPath -ErrorAction Stop
if ($hostUpgrade -ne $null) {
# Make sure is ESXi node connected (state is Connected or Maintenance)
if($hostUpgrade.NeedsReconnect -contains $true){
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
while($esx.State -notin "Connected","Maintenance"){
Start-Sleep -Seconds 5
$esx = Get-VMHost -VMHost $esx
}
}
# If needed restart the ESXi node
if ($hostUpgrade.NeedsRestart -contains $true){
Restart-VMHost -VMHost $hosts -Confirm:$false
}
# Wait till ESXi node is rebooting
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
while($esx.State -ne "NotResponding"){
Start-Sleep -Seconds 5
$esx = Get-VMHost -VMHost $esx
}
# Now wait till ESXi node is back online
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
while($esx.State -notin "Connected","Maintenance"){
Start-Sleep -Seconds 5
$esx = Get-VMHost -VMHost $esx
}
# Leave maintenance mode (if required)
if($esx.Stat -eq "Maintenance"){
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
}
}
} catch {
Write-Host "Error: $_"
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
the catch got error
Error: A parameter cannot be found that matches parameter name 'VMHost'.
maybe instead $esx.State and $esx = Set-VMHost should change to the original $hosts ?
like so:
if ($hostUpgrade -ne $null) {
if($hostUpgrade.NeedsReconnect -contains $true){
$hosts | Set-VMHost -State Connected -Confirm:$false
while($hosts.State -notin "Connected","Maintenance"){
Start-Sleep -Seconds 5
$hosts = Get-VMHost -VMHost $hosts
}
}
if ($hostUpgrade.NeedsRestart -contains $true){
$hosts | Restart-VMHost -Confirm:$false
}
$hosts | Set-VMHost -State Connected -Confirm:$false
while($hosts.State -ne "NotResponding"){
Start-Sleep -Seconds 5
$hosts = Get-VMHost -VMHost $hosts
}
$hosts | Set-VMHost -State Connected -Confirm:$false
while($hosts.State -notin "Connected","Maintenance"){
Start-Sleep -Seconds 5
$hosts = Get-VMHost -VMHost $hosts
}
if($hosts.Stat -eq "Maintenance"){
$hosts | Set-VMHost -State Connected -Confirm:$false
}
}
In which line?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
since its try and catch with write-host it doesn't say the error line
but looks like its on every line in 'while' $esx= Get-VMHost -VMHost $hosts
i tried to change all to $esx and to $hosts. still same error
My bad, I just noticed that I used
Get-VMHost -VMHost $esx
that should of course be
Get-VMHost -Name $esx.Name
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
now its just stuck and not doing anything (after the install patch)
its just exit maintenance mode and thats it.
the ESXi host showing (Reboot Required)
but the script does nothing with it
maybe the statement is wrong should be -is instead of -contains ?
this is what I have now:
if($hostUpgrade -ne $null){
# Make sure is ESXi node connected (state is Connected or Maintenance)
if($hostUpgrade.NeedsReconnect -contains $true){
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
while($esx.State -notin "Connected","Maintenance"){
Start-Sleep -Seconds 5
$esx = Get-VMHost -Name $esx.Name
}
}
# If needed restart the ESXi node
if ($hostUpgrade.NeedsRestart -contains $true){
Restart-VMHost -VMHost $hosts -Confirm:$false
}
# Wait till ESXi node is rebooting
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
while($esx.State -ne "NotResponding"){
Start-Sleep -Seconds 5
$esx = Get-VMHost -Name $esx.Name
}
# Now wait till ESXi node is back online
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
while($esx.State -notin "Connected","Maintenance"){
Start-Sleep -Seconds 5
$esx = Get-VMHost -Name $esx.Name
}
# Leave maintenance mode (if required)
if($esx.Stat -eq "Maintenance"){
$esx = Set-VMHost -VMHost $hosts -State Connected -Confirm:$false
}
}
Maybe I'm missing something?
I assume that $hostUpgrade is an array with an entry for each patch,
I want to test if there is at least one element in that array that says True, hence the -contains
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
ok so the state of the script now is that it stuck and do nothing after the install patch is done
exit maintenance mode and stuck doing nothing forward.
no errors no break
Now would be a good time to use a debugger like the one in Visual Studio Code, and run the script line by line to see what goes wrong where.
At this point, I have no idea why it happens without actually running the code in your environment I'm afraid.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference