I have a PowerShell script which is used to return information for each Host on a user specified cluster. The user provides the vCenter and cluster in as parameters and the script works as expected.
I am trying to modify this script so the user only needs to pass in the vCenter as a parameter and it would return information for all hosts on all clusters.
Here is the original script I have which works:
Param(
$vc,
$ClusterName
)
Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer $vc
$VMHosts = Get-Cluster $ClusterName | Get-VMHost | ? { $_.ConnectionState -eq "Connected" } | Sort-Object -Property Name
foreach ($VMHost in $VMHosts) {
Get-VMHostStorage -RescanAllHba -VMHost $VMHost | Out-Null
$esx = Get-VMHost $VMHost
foreach($hba in (Get-VMHostHba -VMHost $esx -Type "FibreChannel")){
$target = ((Get-View $hba.VMhost).Config.StorageDevice.ScsiTopology.Adapter | where {$_.Adapter -eq $hba.Key}).Target
$luns = Get-ScsiLun -Hba $hba -LunType "disk"
$nrPaths = ($target | %{$_.Lun.Count} | Measure-Object -Sum).Sum
$deadPaths = $luns | Get-ScsiLunPath | Group-Object -Property state | ? { $_.Name -eq "Dead"}
$hbaDevice = $hba.Device
$targetCount = $target.Count
$lunsCount = $luns.Count
$deadPathCount = $deadPaths.Count
"vmhost=$VMHost;hba=$hbaDevice;targets=$targetCount;devices=$lunsCount;paths=$nrPaths;deadpaths=$deadPathsCount|"
}
}
Disconnect-VIServer -Confirm:$False
And here is my modified version:
Param(
$vc
)
Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer $vc
$clusters = Get-Cluster
foreach ($cluster in $clusters) {
$clusterName = $cluster.name
$VMHosts = Get-Cluster $clusterName | Get-VMHost | ? { $_.ConnectionState -eq "Connected" } | Sort-Object -Property Name
foreach ($VMHost in $VMHosts) {
Get-VMHostStorage -RescanAllHba -VMHost $VMHost | Out-Null
$esx = Get-VMHost $VMHost
foreach($hba in (Get-VMHostHba -VMHost $esx -Type "FibreChannel")){
$target = ((Get-View $hba.VMhost).Config.StorageDevice.ScsiTopology.Adapter | where {$_.Adapter -eq $hba.Key}).Target
$luns = Get-ScsiLun -Hba $hba -LunType "disk"
$nrPaths = ($target | %{$_.Lun.Count} | Measure-Object -Sum).Sum
$deadPaths = $luns | Get-ScsiLunPath | Group-Object -Property state | ? { $_.Name -eq "Dead"}
$hbaDevice = $hba.Device
$targetCount = $target.Count
$lunsCount = $luns.Count
$deadPathCount = $deadPaths.Count
"vmhost=$VMHost;hba=$hbaDevice;targets=$targetCount;devices=$lunsCount;paths=$nrPaths;deadpaths=$deadPathsCount|"
}
}
}
Disconnect-VIServer -Confirm:$False
The error that I am getting is:
Could not execute powershell command.
At \\xx\xxx\xxxx\scripts\vmwarePathCheckAllClusters.ps1:35 char:26
+ Get-VMHostStorage <<<< -RescanAllHba -VMHost $VMHost | Out-Null
It seems that $VMHost
is being return as null, but I can't work out why!
This is my first time using PowerCLI CommandLets and I am very new to PowerShell as well. I'm sure that this is something very simple and would appreciate any help. If you require anymore information I'll be more than happy to provide. BUMP!
EDIT: Here is the additional error info:
+ Get-VMHostStorage <<<< -RescanAllHba -VMHost $VMHost | Out-Null ---> VMware.VimAutomation.Sdk.Types.V1.ErrorHandling.VimException.VimException: 9/24/2014 5:58:57 AM Get-VMHostStorage Value cannot be found for the mandatory parameter VMHost ---> System.Management.Automation.ParameterBindingException: Value cannot be found for the mandatory parameter VMHost
Have you tested running Get-VMHostStorage
without -RescanAllHBA
? Why do you think $VMHost
is being returned as null? Maybe it finds the host, but nothing to rescan? Just a guess.
Not sure this could cause your problem, but you don't need to run Get-Cluster
twice. Rather,
$VMHosts = $cluster | Get-VMHost | ? <etc>
edit - For a given run of the script, how many times does the full error text appear? How many vmhosts were found in that run? Do you have a cluster without hosts? A host without storage? You could set $vmhost = $null
or $cluster = $null
if a value from one loop iteration seems to be corrupting the next iteration. (Sorry, there's gotta be a better way to phrase that... hopefully you catch my drift.) You could always put the offending line of code in a [try]
block and handle the error with catch.
edit again - apparently this fixed it for the host in maintenance mode: if (!$VMHost) {continue}