Home > PowerCLI, Powershell > Exporting all that useful VM information with PowerCLI

Exporting all that useful VM information with PowerCLI

August 16th, 2010

There are many occasions when you may need to produce a report showing some aspect of your VM environment.

Many companies have various types of inventory databases which grab information from various sources to provide tracking and reporting of the various IT assets.

An example of a database could be one which pulls information from the software inventory system, patch management system, anti-virus console showing latest file update, AD etc. which could show a dashboard view of the workstations and highlight where they are not in compliance to company standards.

As a virtual workstation environment grows there is plently of information from vCenter that would be very useful to gather.

Grouping VMs by VDI groups in vCenter folders so you know how many VMs x department has would be useful to have. For the dashboard view it may be usedful having the VM Tools status. It’s could also be useful knowing which VMs are in which cluster and datastore, what virtual CPU and RAM they have and how big their disks are which can be used for capacity planning, performance analysis and reporting on what is deployed where.

A daily PowerCLI report can then be run which pulls this all from vCenter and dumps a .CSV file which the workstation database sucks in and mashes together with the other feeds providing a single place to view everything related to workstations.

The script builds an always useful hash table which is very easy to add to and then exports the resulting report to CSV.

The Get-Member powershell command is the best way to find out what information is available for a particular object. There are two simple lines you can run which will output most of the objects you can report on, for this example it is Get-VM but you could use Get-Cluster etc.

Get-VM "AnyVM" | Get-Member
Get-VM "AnyVM"| Get-View | Get-Member

I’ve also used the great Get-FolderPath function from Maish which is excellent.

@"
===============================================================================
Title:         Export-VMInfo.ps1
Description:   Exports VM Information from vCenter into a .CSV file for importing into anything
Usage:         .\Export-VMInfo.ps1
Date:          04/03/2010
===============================================================================
"@

filter Get-FolderPath {
    $_ | Get-View | % {
        $row = "" | select Name, Path
        $row.Name = $_.Name

        $current = Get-View $_.Parent
#        $path = $_.Name # Uncomment out this line if you do want the VM Name to appear at the end of the path
        $path = ""
        do {
            $parent = $current
            if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
            $current = Get-View $current.Parent
        } while ($current.Parent -ne $null)
        $row.Path = $path
        $row
    }
}

$VCServerName = "vCenter.local"
$VC = Connect-VIServer $VCServerName
$VMFolder = "Workstations"
$ExportFilePath = "\\fileshare\dump\Export-VMInfo.csv"

$Report = @()
$VMs = Get-Folder $VMFolder | Get-VM

$Datastores = Get-Datastore | select Name, Id
$VMHosts = Get-VMHost | select Name, Parent

ForEach ($VM in $VMs) {
		$VMView = $VM | Get-View
		$VMInfo = {} | Select VMName,Powerstate,OS,Folder,IPAddress,ToolsStatus,Host,Cluster,Datastore,NumCPU,MemMb,DiskGb, DiskFree, DiskUsed
		$VMInfo.VMName = $vm.name
		$VMInfo.Powerstate = $vm.Powerstate
		$VMInfo.OS = $vm.Guest.OSFullName
		$VMInfo.Folder = ($vm | Get-Folderpath).Path
		$VMInfo.IPAddress = $vm.Guest.IPAddress[0]
		$VMInfo.ToolsStatus = $VMView.Guest.ToolsStatus
		$VMInfo.Host = $vm.host.name
		$VMInfo.Cluster = $vm.host.Parent.Name
		$VMInfo.Datastore = ($Datastores | where {$_.ID -match (($vmview.Datastore | Select -First 1) | Select Value).Value} | Select Name).Name
		$VMInfo.NumCPU = $vm.NumCPU
		$VMInfo.MemMb = [Math]::Round(($vm.MemoryMB),2)
		$VMInfo.DiskGb = [Math]::Round((($vm.HardDisks | Measure-Object -Property CapacityKB -Sum).Sum * 1KB / 1GB),2)
		$VMInfo.DiskFree = [Math]::Round((($vm.Guest.Disks | Measure-Object -Property FreeSpace -Sum).Sum / 1GB),2)
		$VMInfo.DiskUsed = $VMInfo.DiskGb - $VMInfo.DiskFree
		$Report += $VMInfo
}
$Report = $Report | Sort-Object VMName
IF ($Report -ne "") {
$report | Export-Csv $ExportFilePath -NoTypeInformation
}
$VC = Disconnect-VIServer -Confirm:$False
Categories: PowerCLI, Powershell Tags: , ,
  1. August 18th, 2010 at 18:40 | #1

    Thanks for the mention Julian

    But the get-folderpath credit should actually go to Luc Dekens – I can’t exactly remember where the source is on the community – but I am 100% he was the source for the script.

    • WoodITWork
      August 18th, 2010 at 19:34 | #2

      I’m sure a lot of scripting credit when passed up the chain lands at the foot of the master…Luc.
      Well, thanks Luc for devising it and Maish for implementing it!

  2. WoodITWork
    November 24th, 2010 at 15:55 | #3

    Updated with some more operational efficiencies and added calculated disk space info

  3. Guillermo
    May 20th, 2011 at 19:30 | #4

    Thank you. Nice report
    Can you add a line to get the notes in VMs?
    Regards

  4. Anton
    April 13th, 2012 at 22:34 | #5

    I have an issue with one part that I cannot figure out.
    I have PowerCLI 5.0 and vcenter 4.1 U2.

    I get an error
    Get-View : Cannot validate argument on parameter ‘VIObject’. The argument is null or empty. Supply an argument that is not null or empty and the
    n try the command again.
    exportvms.ps1:12 char:32 which is $current = Get-View $current.Parent

    Any help would be appreciated

  5. Samuel
    August 14th, 2012 at 15:15 | #6

    hello everyone, this scripts get the first hdd and datastore configured in vsphere. is there any way that we can get all the hdd and datastore through this script?

    waiting for reply.

  6. Sony Koithara
    March 13th, 2013 at 20:39 | #7

    here is another one liner that you can use…

    Get-VM | Select Name, NumCPU, MemoryMB, ProvisionedSpaceGB, UsedSpaceGB, @{N=”ESX Host”;E={Get-VMHost -VM $_}}, @{N=”Datastore”;E={Get-Datastore -VM $_}}, @{N=”Guest OS”;E={Get-VMGuest -VM $_}}

  7. Maurice84
    May 14th, 2013 at 13:26 | #8

    Hello everyone, I’m using PowerCLI 5.1 and I’m getting a HardDisk deprecation error with this script. Is it possible to update the script using the new cmdlet?

  8. Graham
    November 12th, 2013 at 09:11 | #9

    This will let you use the Custom Attributes of a VM, replace “Description” with your own custom attribute name:

    $VMInfo.Description = (Get-VM -Name $VM | Get-Annotation -CustomAttribute “Description”) -replace “Description:”

  9. Madhusudan
    July 17th, 2015 at 08:38 | #10

    Hi,

    I would like to know, how do I get the Folder details of VM and RDM disk in below oneliner

    Get-VM | Select Name, NumCPU, MemoryMB, ProvisionedSpaceGB, UsedSpaceGB, @{N=”ESX Host”;E={Get-VMHost -VM $_}}, @{N=”Datastore”;E={Get-Datastore -VM $_}}, @{N=”Guest OS”;E={Get-VMGuest -VM $_}}

  10. Amandeep
    July 30th, 2015 at 04:18 | #11

    Hi All,

    I would like to know how do i get details of all the VM in a cluster.
    The VMs have multiple NICs attached so would like VM information to show IP address on both the NICs

    kindly assist.

    Thanks

  11. kichan
    May 12th, 2016 at 10:13 | #12

    How do i change the script for Hyper-V (non-cluster) . Please guide me .

  12. jmachado81
    May 26th, 2016 at 16:33 | #13

    I have changed this line in the script because it does not display the full and correct OS level. For instance, VMware will only display 2012 guest OS and not 2012 R2. When run it by itself it seems to work great on remote systems, but when its run in the script against a vcenter the issue I’m running into is it appears to list things in that line as an array and if it can’t locate that VM’s info it doesn’t place a NULL in its place.

    # $VMInfo.OS = $vm.Guest.OSFullName
    $VMInfo.OS = (Get-CimInstance -ComputerName $VMs Win32_OperatingSystem | Select Caption)

    I was hoping you could have some guidance on how to successfully merge this into your script to get that much more detail.

  13. Bill
    May 17th, 2018 at 15:48 | #14

    @Suresh
    Try just Network:
    $vminfo.NetworkName= $vm.Network

    Before running in a script, try this:
    Get-VM SOME-VM-HERE | Get-View
    you will see a line for Network and see what the variable data is.

  1. No trackbacks yet.
Comments are closed.