VMware Cloud Community
Grimdari
Contributor
Contributor
Jump to solution

Problem combining Get-VM and Get-View

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.

Reply
0 Kudos
1 Solution

Accepted Solutions
mattboren
Expert
Expert
Jump to solution

Hello, -

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?

View solution in original post

Reply
0 Kudos
5 Replies
mattboren
Expert
Expert
Jump to solution

Hello, -

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?

Reply
0 Kudos
Grimdari
Contributor
Contributor
Jump to solution

I am trying these now.  Will report back the results.

Reply
0 Kudos
Grimdari
Contributor
Contributor
Jump to solution

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.

Reply
0 Kudos
mattboren
Expert
Expert
Jump to solution

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.

Grimdari
Contributor
Contributor
Jump to solution

Thank you again!  You are awesome!

Reply
0 Kudos