VMware Cloud Community
golddiggie
Champion
Champion
Jump to solution

Need to gather information about VMs in specific datacenters in environment

I need to pull up a bunch of information for the VMs living in specific datacenters within a vCenter (5.1, ugh) environment right now. There are three datacenters with clusters within each (plus some hosts not in clusters, but still within the datacenter items). With about 4000 VMs total, I really need a solid way to pull the information from just one datacenter, or even from a single cluster/host within each set. The first target is the smallest, with only 18 hosts and 111 VMs listed in the summary of the DC.

I've found some scripts to pull the information (or a good chunk of it) but I really need it to be more specific (instead of shotgunning to everything).

Information I really need to pull:

VM name (obviously)

vNIC with portgroup connected to, plus how many of them (if more than one at least) along with the adapter type selected (e1000, etc.)

VMDK information including how many and which datastore it's on as well as what the type of datastore it is (VMFS, NAS, etc.).

Snapshot if present (I'd also prefer to have the total snapshot size if easy, but I can always gather that later).

Affinity rule(s) applied against the VM(s). If this can include which rule is applied, that would be great.

IMO, easy stuff to add would be the OS inside the VM, IP address, and power state. I'd also like to have the location information for the VM. Such as which datacenter, cluster and host. Or at least have that available and either enabled or disabled easily (add/remove # in front of the lines).

I've been asked to get all of this for the first target before end of the week. I'd like to have it sometime before EOD tomorrow. One of the scripts I found earlier today is still runnning.

Get-VM | Select-Object Name, Powerstate, NumCPU, MemoryGB, @{N="Noofdisk"; E={($_ | Get-HardDisk).count}}, HardDisks, @{N="Datastore"; E={($_ | Get-Datastore).Name}}, @{N="DiskState"; E={($_ | Get-HardDisk).storageformat}}, ProvisionedSpaceGB,  @{N="Snapshot"; E={($_ | Get-snapshot).count}}, VMHost,   @{N="OS"; E={$_.ExtensionData.summary.config.guestfullname}} | Export-Csv -NoTypeInformation -UseCulture -Path "C:\powercli_reports\Inventory4Result.csv$(Get-Date -f MM-dd-yyyy-H-mm-ss).csv"

The above script just finished and pulled up all the info listed in it (good sign). Can I simply add "NetworkAdapter," to the list to get the adapter type for each VM?? I'd still like to narrow down the target to just the DC/cluster I need to focus on (at each run time). Even if it means altering the script to be target specific. I'm also going to still need the rest of the info I listed above added to this. With each run taking over an hour (around 1-1/4 to 1-1/2 hours) it would be better. Especially when I can target a smaller group and get the results faster.

Hopefully someone will answer up soon (like LucD). Smiley Wink

update: added the "Get-Datacenter ="<datacenter>" | " at the start to narrow it down. I can change it to a cluster later when I start hitting the one with over 3000 VMs in it (so it takes less time).

Still trying to figure out how to get the Network Adapter Type added to the list. I've tried added "@{N="NetworkAdapter"; E={($_ | Get-NetworkAdapter)}}" but it's not giving me the desired result...

Update2: changed the NIC line to "@{N="NetworkAdapter"; E={($_ | Get-NetworkAdapter).type}}" and that pulls the info needed for that section... Need to figure out how to add a NIC count line to this too (hope what I'm thinking will work, but will see).

Update3: I've managed to get almost everything needed. Except for a way to get the DRS affinity rule for any VMs they are applied against. Since this is going against a DC, is that just not possible? I'll consider pushing the script against a cluster tomorrow.

Message was edited by: golddiggie

Tags (1)
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

You could do like this.

Also note that the script now creates columns for 4 harddisks and 4 vNics.

The reason for that is that the Export-Csv works better with objects that are of the same length, i.e. the same properties.

If you have VMs with more than 4 harddisks or vNics, you can adjust the numbers.

$dcName = 'MyDC'

$maxNic = 4

$maxHD = 4


$report = foreach($dc in Get-Datacenter -Name $dcName){

   foreach($cluster in Get-CLuster -Location $dc){

   foreach($vm in Get-VM -Location $cluster){

   $hd = Get-HardDisk -VM $vm

   $nic = Get-NetworkAdapter -VM $vm

   $drsRule = Get-DrsRule -Cluster $cluster -VM $vm

   $snap = Get-Snapshot -VM $vm

   $obj = [ordered]@{

   Datacenter = $dc.Name

   Cluster = $cluster.Name

   VMHost = $vm.VMHost.Name

   VM = $vm.Name

   DrsRule = $drsRule.Name -join'|'

   HDNumber = $hd.Count

   vNicNumber = $nic.Count

   SnapNumber = $snap.Count

   SnapSize = [math]::Round(($snap | Measure-Object -Property SizeGB -Sum).Sum,1)

   }

   1..$MaxNic | %{

   if($_ -le $nic.Count){

   $obj.Add("NIC$($_)PG",$nic[$_ -1].NetworkName)

   $obj.Add("NIC$($_)Type",$nic[$_ -1].Type)

   }

   else{

   $obj.Add("NIC$($_)PG",'')

   $obj.Add("NIC$($_)Type",'')

   }

   }

   1..$MaxHD | %{

   if($_ -le $hd.Count){

   $ds = Get-Datastore -RelatedObject $hd[$_ -1]

   $obj.Add("VMDK$($_)DS",$ds.Name)

   $obj.Add("VMDK$($_)DSType",$ds.Type)

   }

   else{

   $obj.Add("VMDK$($_)DS",'')

   $obj.Add("VMDK$($_)DSType",'')

   }

   }

   New-Object PSObject -Property $obj

   }

   }

}


$report | Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture


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

View solution in original post

80 Replies
LucD
Leadership
Leadership
Jump to solution

Try something like this.

$maxNic = 4

$maxHD = 4


foreach($dc in Get-Datacenter){

   foreach($cluster in Get-CLuster -Location $dc){

   foreach($vm in Get-VM -Location $cluster){

   $hd = Get-HardDisk -VM $vm

   $nic = Get-NetworkAdapter -VM $vm

   $drsRule = Get-DrsRule -Cluster $cluster -VM $vm

   $snap = Get-Snapshot -VM $vm


   $obj = [ordered]@{

   Datacenter = $dc.Name

   Cluster = $cluster.Name

   VMHost = $vm.VMHost.Name

   VM = $vm.Name

   DrsRule = $drsRule.Name -join'|'

   HDNumber = $hd.Count

   vNicNumber = $nic.Count

   SnapNumber = $snap.Count

   SnapSize = [math]::Round(($snap | Measure-Object -Property SizeGB -Sum).Sum,1)

   }

   1..$MaxNic | %{

   if($_ -le $nic.Count){

   $obj.Add("NIC$($_)PG",$nic[$_ -1].NetworkName)

   $obj.Add("NIC$($_)Type",$nic[$_ -1].Type)

   }

   else{

   $obj.Add("NIC$($_)PG",'')

   $obj.Add("NIC$($_)Type",'')

   }

   }

   1..$MaxHD | %{

   if($_ -le $hd.Count){

   $ds = Get-Datastore -RelatedObject $hd[$_ -1]

   $obj.Add("VMDK$($_)DS",$ds.Name)

   $obj.Add("VMDK$($_)DSType",$ds.Type)

   }

   else{

   $obj.Add("VMDK$($_)DS",'')

   $obj.Add("VMDK$($_)DSType",'')

   }

   }

   New-Object PSObject -Property $obj

   }

   }

}


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

0 Kudos
golddiggie
Champion
Champion
Jump to solution

I'll give that a shot in the morning... Looks like I'll need to add the line to export to CSV file to it (unless you can before I give it a shot tomorrow Smiley Wink).

Where would I specify the DC that this needs to run against? That way it won't go to all three DC's with upwards of 4000 VMs living there.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You could do like this.

Also note that the script now creates columns for 4 harddisks and 4 vNics.

The reason for that is that the Export-Csv works better with objects that are of the same length, i.e. the same properties.

If you have VMs with more than 4 harddisks or vNics, you can adjust the numbers.

$dcName = 'MyDC'

$maxNic = 4

$maxHD = 4


$report = foreach($dc in Get-Datacenter -Name $dcName){

   foreach($cluster in Get-CLuster -Location $dc){

   foreach($vm in Get-VM -Location $cluster){

   $hd = Get-HardDisk -VM $vm

   $nic = Get-NetworkAdapter -VM $vm

   $drsRule = Get-DrsRule -Cluster $cluster -VM $vm

   $snap = Get-Snapshot -VM $vm

   $obj = [ordered]@{

   Datacenter = $dc.Name

   Cluster = $cluster.Name

   VMHost = $vm.VMHost.Name

   VM = $vm.Name

   DrsRule = $drsRule.Name -join'|'

   HDNumber = $hd.Count

   vNicNumber = $nic.Count

   SnapNumber = $snap.Count

   SnapSize = [math]::Round(($snap | Measure-Object -Property SizeGB -Sum).Sum,1)

   }

   1..$MaxNic | %{

   if($_ -le $nic.Count){

   $obj.Add("NIC$($_)PG",$nic[$_ -1].NetworkName)

   $obj.Add("NIC$($_)Type",$nic[$_ -1].Type)

   }

   else{

   $obj.Add("NIC$($_)PG",'')

   $obj.Add("NIC$($_)Type",'')

   }

   }

   1..$MaxHD | %{

   if($_ -le $hd.Count){

   $ds = Get-Datastore -RelatedObject $hd[$_ -1]

   $obj.Add("VMDK$($_)DS",$ds.Name)

   $obj.Add("VMDK$($_)DSType",$ds.Type)

   }

   else{

   $obj.Add("VMDK$($_)DS",'')

   $obj.Add("VMDK$($_)DSType",'')

   }

   }

   New-Object PSObject -Property $obj

   }

   }

}


$report | Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture


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

golddiggie
Champion
Champion
Jump to solution

Great, thanks... I'm going to give it a shot in a few minutes.

0 Kudos
golddiggie
Champion
Champion
Jump to solution

I'm getting error messages. Not sure if it matters, but I'm using the latest PowerCLI release (10.1.1) for this. Even though the vCenter (and such) is on 5.1...

Errors:

Get-Datastore : Cannot validate argument on parameter 'RelatedObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\Users\XXXXXXXXXXX\Desktop\powercli_scripts\InventoryReportDC01.ps1:71 char:39

+    $ds = Get-Datastore -RelatedObject $hd[$_ -1]

+                                       ~~~~~~~~~~

+ CategoryInfo          : InvalidData: (:) [Get-Datastore], ParameterBindingValidationException

+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetDatastore

Get-Datastore : Cannot validate argument on parameter 'RelatedObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\Users\XXXXXXXXXXXXXX\Desktop\powercli_scripts\InventoryReportDC01.ps1:71 char:39

+    $ds = Get-Datastore -RelatedObject $hd[$_ -1]

+                                       ~~~~~~~~~~

+ CategoryInfo          : InvalidData: (:) [Get-Datastore], ParameterBindingValidationException

+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetDatastore

Get-Datastore : Cannot validate argument on parameter 'RelatedObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\Users\v-agoldberg\Desktop\powercli_scripts\InventoryReportDC01.ps1:71 char:39

+    $ds = Get-Datastore -RelatedObject $hd[$_ -1]

+                                       ~~~~~~~~~~

+ CategoryInfo          : InvalidData: (:) [Get-Datastore], ParameterBindingValidationException

+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetDatastore

I stopped the run once these started to come up... Ideas???

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Which PowerCLI version are you using?

Do a Get-PowerCLIVersion


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

0 Kudos
golddiggie
Champion
Champion
Jump to solution

VMware PowerCLI 10.1.0 build 8346946

Get-Module (since 'Get-PowerCLIVersion' is deprecated Smiley Wink)

ModuleType Version    Name                                ExportedCommands

---------- -------    ----                                ----------------

Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Content, Clear-Content, Clear-Item, Clear-ItemProperty...}

Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}

Script     1.2        PSReadLine                          {Get-PSReadlineKeyHandler, Get-PSReadlineOption, Remove-PSReadlineKeyHandler, Set-PSReadlineKeyHandler...}

Script     6.7.0.8... VMware.Vim

Script     10.1.0.... VMware.VimAutomation.Cis.Core       {Connect-CisServer, Disconnect-CisServer, Get-CisService}

Script     10.1.0.... VMware.VimAutomation.Common

Script     10.1.0.... VMware.VimAutomation.Core           {Add-PassthroughDevice, Add-VirtualSwitchPhysicalNetworkAdapter, Add-VMHost, Add-VMHostNtpServer...}

Script     10.1.0.... VMware.VimAutomation.Sdk            {Get-InstallPath, Get-PSVersion}

0 Kudos
LucD
Leadership
Leadership
Jump to solution

There was a typo, I put $nic.Count where it should say $hd.Count.

The code above is corrected, give it another try.


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

0 Kudos
golddiggie
Champion
Champion
Jump to solution

I updated the file here (since it was just one line Smiley Wink) and it's running now... Will see what it looks like when done and report back...

I might need to change the drive count, depending on what I see for the other VMs in the inventory. I recall seeing one (yesterday) with five HDs listed.

I'm probably going to want to have the option to narrow it down to clusters within the larger DC. Provided they want the information pulled for those VMs too.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

We could even automate those numbers, by looking at all the VMs and determining the highest number of vNics and HDs


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

0 Kudos
golddiggie
Champion
Champion
Jump to solution

One of the things that [IMO] isn't all that good about the DC (and cluster) names here, is they include spaces in the names. Not underscores, or such, but actual spaces. Means I have to contain the names in quotes in order for things to work right. I've made a point to use underscores instead of spaces in names for years. It just makes things so much easier when you're using scripts. Or going into a setup via command line when you need to (like when you have support on the horn Smiley Wink).

This run is taking a while longer than the one from yesterday... I just hope it's only pulling from the one DC and not going into the others too.

0 Kudos
golddiggie
Champion
Champion
Jump to solution

I'll have to see if I can find a max HD and NIC number for the entire environment... Well, without pulling a report that takes over an hour that is. Smiley Wink

Your scripts are one of the BIG reasons to be a member here, IMO...

0 Kudos
golddiggie
Champion
Champion
Jump to solution

BTW, do you happen to have any recommendations for books to help with creating PowerCLI scripts in v10.x?? I have a couple I bought a couple/few years back (published in the 2015/6 time frame) but would like to have something a bit newer in my library.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You better restart, I found another typo in the Get-Cluster line, it said $datacenter instead of $dc.

Code is corrected.


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

0 Kudos
LucD
Leadership
Leadership
Jump to solution

This version calculates the max HD and vNic

$dcName = 'MyDC'

$report = foreach($dc in Get-Datacenter -Name $dcName){

   foreach($cluster in Get-CLuster -Location $dc){

       $vms = Get-VM -Location $cluster

       $maxHD = ($vms.ExtensionData.Layout | %{$_.Disk.Count} | Measure-Object -Maximum).Maximum

       $maxNic = ($vms.ExtensionData | %{$_.Network.Count} | Measure-Object -Maximum).Maximum

       foreach($vm in $vms){

           $hd = Get-HardDisk -VM $vm

           $nic = Get-NetworkAdapter -VM $vm

           $drsRule = Get-DrsRule -Cluster $cluster -VM $vm

           $snap = Get-Snapshot -VM $vm

        

           $obj = [ordered]@{

               Datacenter = $dc.Name

               Cluster = $cluster.Name

               VMHost = $vm.VMHost.Name

               VM = $vm.Name

               DrsRule = $drsRule.Name -join'|'

               HDNumber = $hd.Count

               vNicNumber = $nic.Count

               SnapNumber = $snap.Count

               SnapSize = [math]::Round(($snap | Measure-Object -Property SizeGB -Sum).Sum,1)

           }

           1..$MaxNic | %{

               if($_ -le $nic.Count){

                   $obj.Add("NIC$($_)PG",$nic[$_ -1].NetworkName)

                   $obj.Add("NIC$($_)Type",$nic[$_ -1].Type)

               }

               else{

                   $obj.Add("NIC$($_)PG",'')

                   $obj.Add("NIC$($_)Type",'')

               }

           }

           1..$MaxHD | %{

               if($_ -le $hd.Count){

                   $ds = Get-Datastore -RelatedObject $hd[$_ -1]

                   $obj.Add("VMDK$($_)DS",$ds.Name)

                   $obj.Add("VMDK$($_)DSType",$ds.Type)

               }

               else{

                   $obj.Add("VMDK$($_)DS",'')

                   $obj.Add("VMDK$($_)DSType",'')

               }

           }

           New-Object PSObject -Property $obj

       }

   }

}

$report | Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture


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

0 Kudos
golddiggie
Champion
Champion
Jump to solution

Updated the code and ran it again... I left the first (with the DC name) line and the last where I had the CSV file destination and parameters (I like to add the date and time to the file name, so that I can keep them for historical reasons).

Assuming I can shuffle the order of the code sections and get the output to reorder the way I want, yes? Although I think it might be better to just leave it as it sits now... Since the VMs show up in the related cluster within the DC first. I could just sort the info after the file is created to make it easier for others to read (or they can do it if they don't like it).

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can shuffle around the properties in the $obj variable (that is an ordered object).
The code for the HD and vNic has to come after the $obj has been created.


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

0 Kudos
golddiggie
Champion
Champion
Jump to solution

Trying this one out now... I can already see adding more information pulls to this so that I can just run the one script and pull up even more info... Thinks like the VM IP address, since some are going to be changed in the near future, and they could get changed again a while longer...

For the ~100 VM count DC, the script is finishing pretty fast. Since the large target is about 3500 VMs that run is going to take a while. IF they want me to get all the same info that is.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

For bigger environments we could consider going to Get-View instead of Get-VM.

But that would make the code more complex, and in this case probably not bring a huge time gain.


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

0 Kudos