Hey guys!
I know there are plenty of one- and two-liners out there giving you detailed information on how to create snapshot reports. I know, I have been using these myself but now my question is a more technical one.
Why?
Because I'd like to get a list of VMs including their snapshot info but also some more VM details like the parent vCenter and the ESXi host the VM resides on etc..
Example:
Get-VM | select Name,VMHost
This statement produces the VM names and the ESXi host names. OK.
But if I go into depths to chain up objects like so:
Get-VM | Get-Snapshot | Select-Object VM,@{N='VMHost';E={$_.VMHost}}
the statement only produces the VM names but VMHost fields remain empty.
I'm pretty sure that's because the $_. thingy points to the last object in the chain which is the snapshot detail and that does not include a parent host name field.
But being halfway sure about that doesn't solve the mystery of how do I reference an element in a prior part of this chain?
My report is supposed to list
At least the three highlighted fields are somewhere to be found within the $vm object itself and therefore are on a different hierarchy level.
Does anyone know how I can solve this?
Thanks in advance, hopefully this is interesting also to other readers. *sigh* why don't I understand programming?!
BR
NC
You may want to put the one-liners aside and include loops to keep things readable and easily customizable.
Something like that ?
foreach ($vm in (get-vm)) {
foreach ($snap in ($vm | get-snapshot)) {
[pscustomobject]@{
VM = $VM.Name
vCenter = $VM.Uid.Split(":")[0].Split("@")[1]
VMHost = $VM.VMHost
PowerState = $VM.powerstate
OSVersion = $vm.guest.OSFullName
Snapshot = $snap.name
AgeDays = ((get-date)-$snap.created).days
SizeMB = [math]::round($snap.sizeMB,1)
}
}
}
You could even turn it into a function if you're going to use it now and again.
You may want to put the one-liners aside and include loops to keep things readable and easily customizable.
Something like that ?
foreach ($vm in (get-vm)) {
foreach ($snap in ($vm | get-snapshot)) {
[pscustomobject]@{
VM = $VM.Name
vCenter = $VM.Uid.Split(":")[0].Split("@")[1]
VMHost = $VM.VMHost
PowerState = $VM.powerstate
OSVersion = $vm.guest.OSFullName
Snapshot = $snap.name
AgeDays = ((get-date)-$snap.created).days
SizeMB = [math]::round($snap.sizeMB,1)
}
}
}
You could even turn it into a function if you're going to use it now and again.
Hey vXav,
that works exceptionally well, thank you very much!
I should probably get acquainted with the concepts of putting together a collection of properties myself. I have amended your script lightly to be able to create a list I can send via email or output directly when in ISE for example:
$SnapshotListe = @()
foreach ($vm in (get-vm)) {
foreach ($snap in ($vm | get-snapshot)) {
$obj = [pscustomobject]@{
VM = $VM.Name
vCenter = $VM.Uid.Split(":")[0].Split("@")[1]
VMHost = $VM.VMHost
PowerState = $VM.powerstate
OSVersion = $vm.guest.OSFullName
Snapshot = $snap.name
AgeDays = ((get-date)-$snap.created).days
SizeGB = [math]::round($snap.sizeGB,2)
}
$SnapshotListe += $obj
Clear-Variable obj
}
}
$SnapshotListe | Out-GridView
Again thank you for your kind & quick help. 👍
Totally okay with putting aside one-liners, yet I'd still be interested if what I originally tried to do is possible at all.
BR
NC
Yes, you can, with the help of the PipelineVariable.
Get-VM -PipelineVariable vm |
Get-Snapshot |
Select-Object @{N='VM';E={$vm.Name}},
@{N='vCenter';E={([uri]$vm.ExtensionData.Client.ServiceUrl).Host}},
@{N='VMHost';E={$vm.VMHost.Name}},
@{N='PowerState';E={$vm.PowerState}},
@{N='OSVersion';E={$vm.guest.OSFullName}},
@{N='Snapshot';E={$_.Name}},
@{N='AgeDays';E={(New-TimeSpan -Start $_.Created -End (Get-Date)).TotalDays}},
@{N='SizeMB';E={[math]::Round($_.sizeMB,1)}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
To be clear there's nothing wrong with one liners, it's just that it gets pretty messy as you add more and more properties. Especially when you add some math, split and stuff like that.
Edit thanks to LucD's comment: You can also just pipe the foreach into ogv like that:
foreach ($vm in (get-vm)) {
BLAH
} | out-gridview
Now if the goal is to send it via email you can try something like that:
$bodyhtml = foreach ($vm in (get-vm)) {
BLAH
}
Send-MailMessage -SmtpServer smtp.blah.blah -Subject "snapshots" -Body ($bodyhtml | ConvertTo-Html | Out-String) -BodyAsHtml -From from@blah.blah -To to@blah.blah
Just a small note, the foreach does not put anything in the pipeline.
So that pipe to Out-Gridview will not work I'm afraid.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference