VMware Cloud Community
mgteamcds
Contributor
Contributor
Jump to solution

List and count VM info by Folder

I was asked to find a way to gather information of our environment based on our folder structure. We will be working on chargeback models soon, but we would like to get an idea of what we have in our environment per folder (customer) before we start. For each folder we are looking for a count of VMs, total NumCPU, total MemoryMB, and total ProvisionedSpaceGB. I've only recently started using PowerCLI and Powershell, so I can pull folderpath and VM information, but have not been able to figure out how to create the mathematical functions in the script to total up what we have per folder. Any suggestions or help pointing in the right direction would be greatly appreciated.

0 Kudos
1 Solution

Accepted Solutions
RvdNieuwendijk
Leadership
Leadership
Jump to solution

The following PowerCLI script gives you the desired information for each folder that contains vm's.

Get-VM |
Group-Object -Property Folder |
ForEach-Object {
  if ($_) {
    New-Object -TypeName PSObject -Property @{
      Folder = $_.Name
      NumVMs = $_.Group.Count
      TotalNumCPU = ($_.Group | Measure-Object -Property NumCPU -Sum).Sum
      TotalMemoryMB = ($_.Group | Measure-Object -Property MemoryMB -Sum).Sum
      TotalProvisionedSpaceGB = ($_.Group | Measure-Object -Property ProvisionedSpaceGB -Sum).Sum
    }
  }
}

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition

View solution in original post

0 Kudos
8 Replies
RvdNieuwendijk
Leadership
Leadership
Jump to solution

The following PowerCLI script gives you the desired information for each folder that contains vm's.

Get-VM |
Group-Object -Property Folder |
ForEach-Object {
  if ($_) {
    New-Object -TypeName PSObject -Property @{
      Folder = $_.Name
      NumVMs = $_.Group.Count
      TotalNumCPU = ($_.Group | Measure-Object -Property NumCPU -Sum).Sum
      TotalMemoryMB = ($_.Group | Measure-Object -Property MemoryMB -Sum).Sum
      TotalProvisionedSpaceGB = ($_.Group | Measure-Object -Property ProvisionedSpaceGB -Sum).Sum
    }
  }
}

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
0 Kudos
RParker
Immortal
Immortal
Jump to solution

I highly encourage you to use RVtools (http://www.robware.net/)

It will not give exactly what you want, but you CAN export the results (for ALL VM) in a XLS / CSV format sheet.

Use that list and open in excel (or your favorite spreadsheet cloud program) and those will let you filter by folder.. RVtools will give you ALL details, you can then sort, filter, and group by the output.

The tool is completely FREE

0 Kudos
mgteamcds
Contributor
Contributor
Jump to solution

Rvdn, thank you so much! That definitely put me in the right direction and was much simpler than what I was doing with my script.

0 Kudos
mgteamcds
Contributor
Contributor
Jump to solution

Ran into a couple issues trying to alter this script to add a couple more items that management decided they want to include. I noticed that I could not tell which was a subfolder and which folders were the parent folder, etc. I was able to fix that using part of a script from LucD to create a new-viproperty for BlueFolderPath and that worked great after incorporating it into the script. I also found how to convert the MB to GB and round the results. The issue I'm having now is I need to find a way to split the TotalProvisionedSpaceGB into two parts based of the type of datastore (FiberChannel and Non-FiberChannel). Our FiberChannel datastores all contain the text "_FC_" in the name to differentiate those from the Non-FiberChannel datastores, I'm just not sure how to include those. Thoughts or maybe an alternative way to go about getting the info into the script? Here is the script I have so far:

New-VIProperty -Name 'BlueFolderPath' -ObjectType 'VirtualMachine' -Value {
    param($vm)

    function Get-ParentName{
        param($object)

        if($object.Folder){
            $blue = Get-ParentName $object.Folder
            $name = $object.Folder.Name
        }
        elseif($object.Parent -and $object.Parent.GetType().Name -like "Folder*"){
            $blue = Get-ParentName $object.Parent
            $name = $object.Parent.Name
        }
        elseif($object.ParentFolder){
            $blue = Get-ParentName $object.ParentFolder
            $name = $object.ParentFolder.Name
        }
        if("vm","Datacenters" -notcontains $name){
            $blue + "/" + $name        }
        else{
            $blue        }
    }

   

     (Get-ParentName $vm).Remove(0,1)
} -Force | Out-Null

$VMInfo =
Get-VM |
Group-Object -Property BlueFolderPath |
ForEach-Object {
  if ($_) {
    New-Object -TypeName PSObject -Property @{
      Folder = $_.Name
      NumVMs = $_.Group.Count
      TotalNumCPU = ($_.Group | Measure-Object -Property NumCPU -Sum).Sum
      TotalMemoryGB = [math]::round((($_.Group | Measure-Object -Property MemoryMB -Sum).Sum) / 1024,2)
      TotalProvisionedSpaceGB = [math]::round((($_.Group | Measure-Object -Property ProvisionedSpaceGB -Sum).Sum),0)

    }
  }
}

$VMInfo | Export-csv -NoTypeInformation "D:\VMinfo.csv"

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Glad the New-VIProperty was of use.

Btw PowerShell has builtin constant for those common values, you can use 1KB instead of 1024 in your calculation.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
mgteamcds
Contributor
Contributor
Jump to solution

Good to know! Thanks.

I've still been working on the script off and on during the holidays. I was finally able to figure out how to gather specific disk space by datastore. Where I'm getting stuck is that rather than grouping by BlueFolderPath, how would I go about grouping by top-level blue folder? Is that possible with another new-viproperty or is there another way to group these by top-level folder?

The only other way I could find was by using another of Roberts' scripts here: http://communities.vmware.com/message/1779950 which works great to get VM info by top-level folder. This is extremely close to what I'm trying to do, however, I could not figure out to make it only use specific clusters.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

If you only want to group on the top level folder, you could use the 1st qualifier in the BlueFolderPath property.

Something like this

Group-Object -Property {BlueFolderPath.Split('/')[0]}....


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

mgteamcds
Contributor
Contributor
Jump to solution

Thanks! For some reason, this didn't seem to work properly. It was changing the way the script was reading the BlueFolderPath property and was trying to change it to a cmdlet or something. After playing around with the New-VIProperty a bit, I added the split there instead, on this line:

(Get-ParentName $vm).Remove(0,1).split('/')[1]

This returned only the top level folder using the BlueFolderPath -property. Thanks again for the help.

0 Kudos