Recently I had to grab some general info on a group of VMs in a particular folder within vSphere. Typical stuff like, Guest OS, # vCPUs, RAM, Disk, etc. I looked around my scripts folder as I was sure I had written a small script to accomplish this task previously but came up empty. No problem, I’ll just whip something up I thought. Then my mind starts racing, will the script output to csv? html? Excel? Word? I could include all options (and code) and let the user choose? What parameters will I need and how will I validate them? This script was getting cumbersome already and I hadn’t even thought about the simple info I needed to query. Then it dawned on me…all I needed was the data. I decided to strip the function down to simply gathering the information I needed. If I wrote a proper advanced function, then I could just return the gathered objects down the pipeline and from there format the output as needed.
Simply put, an advanced function acts very much like a standard cmdlet.
This allows me to create simple one-liners that will a) select the VMs I’d like to query and b) format the output however I would like. Unlike having to create a new full script each time you want to accomplish a task, an advanced function is flexible, versatile and possibly most importantly – easily reusable. This makes them ideal for inclusion into modules that load any time you fire up PowerShell.
Below is the code for the (simple) advanced function I created – Get-VMInfo. As you can see the code is pretty simple though it makes for a great example. You feed it a list of VMs via the pipeline and it returns the info you requested via custom objects. Let’s see how we could utilize the function assuming we are connected to vCenter and have PowerCLI loaded.
Gather a list of all VMs and pipe to Get-VMInfo
Get-VM | Get-VMInfo
Gather a list of VMs in a particular cluster and pipe to Get-VMInfo
Get-Cluster MyCluster | Get-VM | Get-VMInfo
Gather a list of VMs in a particular vSphere folder and pipe to Get-VMInfo
Get-Folder Servers | Get-VM | Get-VMInfo
Now lets do something more with the output.
Gather a list of all VMs, pipe to Get-VMInfo then pipe to Export-Csv
Get-VM | Get-VMInfo | Export-Csv -NoTypeInformation -Path E:\VMInfo.csv
Gather a list of all VMs, pipe to Get-VMInfo, pipe to ConvertTo-HTML then pipe to Out-File
Get-VM | Get-VMInfo | ConvertTo-HTML | Out-File E:\VMInfo.html
As you can see, by using an advanced function I actually have more options available to me then if I had hard coded all these options into one mega script. It also saved me a lot of time.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Function Get-VMInfo { | |
<# | |
.SYNOPSIS | |
Gather general information about a group of VMs. | |
.DESCRIPTION | |
This function returns general information gathered from a set of one or more VMs. | |
Data returned – Folder, Name, PowerState, FullName, GuestOS, IP, NumCPU, MemoryGB, DiskGB, DiskUsedGB, DiskFreeGB, Notes | |
.PARAMETER VMs | |
VM object (Get-VM) | |
.EXAMPLE | |
Get-VM | Get-VMInfo | |
Returns info for all VMs | |
.EXAMPLE | |
Get-Folder Servers | Get-VM | Get-VMInfo | |
Returns info for all VMs located within the Servers folder | |
.NOTES | |
Author: Shawn Masterson | |
Created: Aug 2014 | |
Version: 1.0 | |
#> | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory=$True, | |
ValueFromPipeline=$True)] | |
[array]$VMs | |
) | |
Begin { | |
$output = @() | |
} | |
Process { | |
Foreach ($VM in $VMs) { | |
Write-Verbose "Processing $VM" | |
$tempvm = @{} | |
$tempvm.Folder = $VM.Folder | |
$tempvm.Name = $VM.Name | |
$tempvm.PowerState = $VM.PowerState | |
$tempvm.NumCPU = $VM.NumCPU | |
[int]$tempvm.MemoryGB = $VM.MemoryGB | |
$tempvm.DiskGB = [Math]::Round((($vm.HardDisks | Measure-Object -Property CapacityKB -Sum).Sum * 1KB / 1GB),2) | |
$tempvm.DiskFreeGB = If (![Math]::Round((($vm.Guest.Disks | Measure-Object -Property FreeSpace -Sum).Sum / 1GB),2)) ` | |
{"Tools Not Running\Unknown"} Else {[Math]::Round((($vm.Guest.Disks | Measure-Object -Property FreeSpace -Sum).Sum / 1GB),2)} | |
$tempvm.DiskUsedGB = If ($tempvm.DiskFreeGB -eq "Tools Not Running\Unknown") ` | |
{"Tools Not Running\Unknown"} Else {$tempvm.DiskGB – $tempvm.DiskFreeGB} | |
$tempvm.Notes = $VM.Notes | |
$tempvm.GuestOS = If (!$VM.Guest.OSFullName) {"Tools Not Running\Unknown"} Else {$VM.Guest.OSFullName} | |
$tempvm.IP = If (!$VM.Guest.IPAddress[0]) {"Tools Not Running\Unknown"} Else {$VM.Guest.IPAddress[0]} | |
$tempvm.FullName = If (!$VM.Guest.hostname) {"Tools Not Running\Unknown"} Else {$VM.Guest.hostname} | |
$temp = New-Object –TypeName PSObject –Prop $tempvm | |
$output += $temp | |
} | |
} | |
End { | |
$output | Select Folder, Name, PowerState, FullName, GuestOS, IP, NumCPU, MemoryGB, DiskGB, DiskUsedGB, DiskFreeGB, Notes | Sort Folder, Name | |
} | |
} |