I have been working on a script for some time now and am very close to getting it working the way I want. The script below is what I have so far and works the way I want.
$(foreach ($cluster in get-cluster) { get-view -viewtype VirtualMachine -SearchRoot $cluster.id | select @{N="VM name";E={$_.Name} },@{N="PowerState";E={$_.Summary.Runtime.PowerState}} ,@{N="Guest OS";E={$_.Config.GuestFullName} } , @{N="Cluster";E={$cluster.name} },@{N="Notes";E={$_.Summary.Config.Annotation} } })
However, I cannot seem to pull our custom annotations using Get-View but can with Get-VM. The script below works.
Get-VM | Select Name, @{N="Org1.Environment";E={(Get-Annotation -Entity $_ -CustomAttribute "Org1.Environment").Value}}
How do I combine the two? Any help would be greatly appreciated.
Hello, Grimdari-
You are pretty close there. A couple of ways that you could do this, the first using the Get-Annotation code that you basically already had:
foreach ($cluster in Get-Cluster) {
Get-View -ViewType VirtualMachine -SearchRoot $cluster.id | Select @{n="VM name"; e={$_.Name}},
@{n="PowerState"; e={$_.Summary.Runtime.PowerState}},
@{n="Guest OS"; e={$_.Config.GuestFullName}},
@{n="Cluster"; e={$cluster.name}},
@{n="Notes"; e={$_.Summary.Config.Annotation}},
## using the Get-VIObjectByVIView cmdlet; slower
@{n="Org1.Environment"; e={(Get-Annotation -Entity (Get-VIObjectByVIView $_) -CustomAttribute "Org1.Environment").Value}}
} ## end foreach
And, the second, sticking with the info that you already retrieved in the Get-View call:
## selected properties to retrieve in Get-View call
$arrViewPropertiesToGet = "Name","Summary.Runtime.PowerState","Config.GuestFullName","Summary.Config.Annotation","CustomValue","AvailableField"
foreach ($cluster in Get-Cluster) {
Get-View -ViewType VirtualMachine -Property $arrViewPropertiesToGet -SearchRoot $cluster.id | Select @{n="VM name"; e={$_.Name}},
@{n="PowerState"; e={$_.Summary.Runtime.PowerState}},
@{n="Guest OS"; e={$_.Config.GuestFullName}},
@{n="Cluster"; e={$cluster.name}},
@{n="Notes"; e={$_.Summary.Config.Annotation}},
## just using the data already retrieved; far faster
@{n="Org1.Environment"; e={$viewThisVM = $_; ($viewThisVM.CustomValue | ?{$_.Key -eq ($viewThisVM.AvailableField | ?{$_.Name -eq "Org1.Environment"}).Key}).Value}}
} ## end foreach
The second way is far faster, though it might be a bit less obvious how it is arriving with the results. It is getting the CustomValue value where the CustomValue key matches the AvailableField key for the AvailableField with the name of the attribute that you desire. Anyway, how do those do for you?
Hello, Grimdari-
You are pretty close there. A couple of ways that you could do this, the first using the Get-Annotation code that you basically already had:
foreach ($cluster in Get-Cluster) {
Get-View -ViewType VirtualMachine -SearchRoot $cluster.id | Select @{n="VM name"; e={$_.Name}},
@{n="PowerState"; e={$_.Summary.Runtime.PowerState}},
@{n="Guest OS"; e={$_.Config.GuestFullName}},
@{n="Cluster"; e={$cluster.name}},
@{n="Notes"; e={$_.Summary.Config.Annotation}},
## using the Get-VIObjectByVIView cmdlet; slower
@{n="Org1.Environment"; e={(Get-Annotation -Entity (Get-VIObjectByVIView $_) -CustomAttribute "Org1.Environment").Value}}
} ## end foreach
And, the second, sticking with the info that you already retrieved in the Get-View call:
## selected properties to retrieve in Get-View call
$arrViewPropertiesToGet = "Name","Summary.Runtime.PowerState","Config.GuestFullName","Summary.Config.Annotation","CustomValue","AvailableField"
foreach ($cluster in Get-Cluster) {
Get-View -ViewType VirtualMachine -Property $arrViewPropertiesToGet -SearchRoot $cluster.id | Select @{n="VM name"; e={$_.Name}},
@{n="PowerState"; e={$_.Summary.Runtime.PowerState}},
@{n="Guest OS"; e={$_.Config.GuestFullName}},
@{n="Cluster"; e={$cluster.name}},
@{n="Notes"; e={$_.Summary.Config.Annotation}},
## just using the data already retrieved; far faster
@{n="Org1.Environment"; e={$viewThisVM = $_; ($viewThisVM.CustomValue | ?{$_.Key -eq ($viewThisVM.AvailableField | ?{$_.Name -eq "Org1.Environment"}).Key}).Value}}
} ## end foreach
The second way is far faster, though it might be a bit less obvious how it is arriving with the results. It is getting the CustomValue value where the CustomValue key matches the AvailableField key for the AvailableField with the name of the attribute that you desire. Anyway, how do those do for you?
I am trying these now. Will report back the results.
Worked flawlessly with both scripts! You are very correct that the second script runs faster.
I knew I was close all this time. Thank you very much!
P.S. How would the output from either script be redirected to a csv? Doing a "| export-cvs etc" returns an error of EmptyPipeElement.
Hello,
You can use the call operator to run the foreach portion, and then, with its results in the pipeline, pipe to Export-Csv, like:
&{
## do all the things, here (put the code to run here)
} | Export-Csv -UseCulture -NoTypeInformation c:\temp\myVMInfo.csv
Or, PowerShell v4 has changed this behavior, so you need not use the call operator to continue the pipeline when using the previous examples in a PowerShell v4 session. Either way, enjoy.
Thank you again! You are awesome!
