Here is what I am trying to do: I have a vSphere setup with multiple clusters, underneath those clusters there are a few hosts.
I am trying to write a script that walks through the clusters and inside each cluster, puts the host into maintenance mode, moves it outside the cluster, start/stop a VM, add memory to it, then moves the host back into the cluster it was moved out of.
Here is what I have so far. The inner loop works, but the outer one is just making everything run twice and adding the cluster name as $cluster
in the inner loop.
Any ideas? I just want the inner loop to run for all the hosts in each cluster.
I added -WhatIf
for testing, you can ignore those.
Connect-VIServer vcenter01
$clusters = Get-Cluster
$esxhosts = Get-Cluster $clusters | Get-VMHost
$Datacenter = "Datacenter01"
$sleep = 1
& {
foreach ($cluster in $clusters) {
foreach ($esxhost in $esxhosts) {
Set-VMHost $esxhost -State Maintenance -WhatIf
Move-VMhost $esxhost -Destination $Datacenter -WhatIf
Set-VMHost $esxhost -State Connected -WhatIf
Sleep $sleep
Stop-VMGuest -Vm Z-VRA-$esxhost -Confirm:$false -WhatIf
Sleep $sleep
Set-VM -Vm Z-VRA-$esxhost -MemoryGB 6 -Confirm:$false -WhatIf
Start-VM -Vm Z-VRA-$esxhost -WhatIf
Sleep $sleep
Move-VMhost $esxhost -Destination $cluster -WhatIf
}
}
}
Disconnect-VIServer vcenter01
Here is what a working copy looks like (Thanks @Ansgar Wiechers):
I added in some code to start/stop HA admission control on each cluster as it works through it. That will stop issues with VM's vacating during maintenance mode if you are low on resorces.
Connect-VIServer vcenter01
$Datacenter = "Datacenter01"
$sleep = 1
Get-Cluster | ForEach-Object {
$cluster = $_
Set-Cluster -HAAdmissionControlEnabled $false -Cluster $cluster -Confirm:$false -Whatif
$cluster | Get-VMHost | ForEach-Object {
Set-VMHost $_ -State Maintenance -WhatIf
Move-VMhost $_ -Destination $Datacenter -WhatIf
Set-VMHost $_ -State Connected -WhatIf
Sleep $sleep
Stop-VMGuest -Vm Z-VRA-$_ -Confirm:$false -WhatIf
Sleep $sleep
Set-VM -Vm Z-VRA-$_ -MemoryGB 6 -Confirm:$false -WhatIf
Start-VM -Vm Z-VRA-$_ -WhatIf
Sleep $sleep
Move-VMhost $_ -Destination $cluster -WhatIf
}
Set-Cluster -HAAdmissionControlEnabled $true -Cluster $cluster Confirm:$false -Whatif
}
Disconnect-VIServer vcenter01
This statement gives you all clusters:
$clusters = Get-Cluster
This statement gives you all hypervisors of all clusters:
$esxhosts = Get-Cluster $clusters | Get-VMHost
Because your inner loop already iterates over all hypervisers of all clusters, iterating over the clusters in an outer loop repeats that operation for each cluster. For two clusters you get the result twice, for three clusters you'd get the result three times, and so on.
Since the final operation in the inner loop is not cluster-agnostic, your code might actually break something if you removed the chicken switch. You need to enumerate the hypervisors per cluster. I don't have access to a vSphere system, but I suppose something like this should do what you want:
Get-Cluster | ForEach-Object {
$cluster = $_
$cluster | Get-VMHost | ForEach-Object {
Set-VMHost $_ -State Maintenance -WhatIf
...
Move-VMhost $_ -Destination $cluster -WhatIf
}
}
Side note: the & { ... }
around your loops is pointless. Just drop it.