Report for all vms regarding uuid,network card, macaddress, ipaddress, network card type e1000/vmxnet in a csv ;)

i wanted to see all vms, with their current ips, macaddresses, names, networkcard types.
This report should also have all network cards in separate columns in csv. So i needed to dynamically adjust number of those ‘columns’.
Below script will output only ipv4 addresses without ipv6.

$reportedvms=New-Object System.Collections.ArrayList
$vms=get-view -viewtype virtualmachine  |Sort-Object -Property {  $_.Config.Hardware.Device |  where {$_ -is [VMware.Vim.VirtualEthernetCard]} |  Measure-Object | select -ExpandProperty Count} -Descending 

foreach($vm in $vms){
  $reportedvm = New-Object PSObject
  Add-Member -Inputobject $reportedvm -MemberType noteProperty -name Guest -value $vm.Name
  Add-Member -InputObject $reportedvm -MemberType noteProperty -name UUID -value $($vm.Config.Uuid)
$networkcards=$ | ?{$_.DeviceConfigId -ne -1}
foreach($ntwkcard in $networkcards){
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.Network" -Value $ntwkcard.Network
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.MacAddress" -Value $ntwkcard.Macaddress  
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.IpAddress" -Value $($ntwkcard.IpAddress|?{$_ -like "*.*"})
Add-Member -InputObject $reportedvm -MemberType NoteProperty -Name "networkcard${i}.Device" -Value $(($vm.config.hardware.device|?{$_.key -eq $($ntwkcard.DeviceConfigId)}).gettype().name)

$reportedvms|Export-Csv c:\myreport.csv

Ok, and what if somebody doesn’t want those multiple columns, but wants to have only 1 column that will describe all network cards for particular vm ?

$vms=get-view -viewtype virtualmachine
foreach($vm in $vms){
$networkcards=$ | ?{$_.DeviceConfigId -ne -1}
""|select  @{n="VM name";e={$}},@{n="uuid";e={$vm.config.uuid}},@{n="net  info";e={[string]::join(',',  $($networkcards|%{$devid=$_.DeviceConfigId;[string]::join(',',$(($vm.config.hardware.device|?{$_.key  -eq $devid}).gettype().name,$,($_.ipaddress -join ';'),$_.Macaddress))})  )}}
)|export-csv c:\myreport.csv

I know 😉 a lot of joining.
@Update: Luc has noticed my error there that i was not sorting $vms array. We have to sort it by the vm with most network cards so that export-csv will work properly.
@Update: Thanks Steve for the feedback. I have updated the code in both examples.
27/02/2014@Update : Fixed issue with reporting multiple ip addresses in second example.

Quicky#1 Get csv report on virtual machine partitions in cluster/multiple clusters

I was asked today how to do that kind of report. It’s really handy to have one of those, and i was surprised that i haven’t wrote about that so far on my blog. So here it is 😉

$(foreach ( $cluster in 'xyz1','yxx2' ) { get-view -SearchRoot (get-cluster $cluster).id -viewtype VirtualMachine -Filter @{"Summary.Runtime.PowerState"="poweredOn";"Config.Template"="False"}  | % {$esxhost=(get-view ($_.Summary.Runtime.Host)).name;$vmname=$_.Name;$_.Guest.Disk | select @{N="VMName";E={$vmname}},DiskPath,@{N="CapacityGB"; E={[Math]::Round($_.Capacity/1GB,2)} },@{N="FeeSpaceGB";E={[Math]::Round($_.FreeSpace/1GB,2)}},@{N="Cluster";E={$cluster} },@{N="Host";E={$esxhost} } }  })  | Export-Csv "c:\ReportVMsDiskUsage.csv" -NoTypeInformation

Yes, i know 😉
So what it does. It will output a csv file in my example to c:\ReportVMsDiskUsage.csv”. Contents are : Name of VM, disk letter/path, Capacity in Gb, FreeSpace in GB, Cluster name on which vm resides, Host name on which vm resides.
This one liner looks bit complicated but once disassembled it’s very easy to understand what i am doing.
I am using the sub-expression $ ( ) | Export-csv … . I did that because i want the whole output in my csv file. Without first getting the whole output it’s very hard i suppose to use the export-csv to put it to 1 file. If you want this to run against 1 cluster or more clusters, just adjust the strings in the foreach($cluster in ….) .
It can be very easy to adjust this one liner to ignore cluster, do the report on the highest level. I am using switch -SearchRoot from get-view and giving him the location of get-cluster X. If you do not want to narrow down the results, just don’t use the -SearchRoot, and it will give you output for all vms that are:
-Filter @{“Summary.Runtime.PowerState”=”poweredOn”;”Config.Template”=”False”}
Powered On, and are not tempaltes.
Before sending the output ” $_.Guest.Disk | ….” further , i also grab all other needed properites, like vmname,esxhost.
It also useful to check the output first before sending it to export-csv. So let’s take a look by running :

foreach ( $cluster in 'xyz1','yxx2' ) { get-view -SearchRoot (get-cluster $cluster).id -viewtype VirtualMachine -Filter @{"Summary.Runtime.PowerState"="poweredOn";"Config.Template"="False"}  | % {$esxhost=(get-view ($_.Summary.Runtime.Host)).name;$vmname=$_.Name;$_.Guest.Disk | select @{N="VMName";E={$vmname}},DiskPath,@{N="CapacityGB"; E={[Math]::Round($_.Capacity/1GB,2)} },@{N="FeeSpaceGB";E={[Math]::Round($_.FreeSpace/1GB,2)}},@{N="Cluster";E={$cluster} },@{N="Host";E={$esxhost} } }  }

You will see report on each vm . from each cluster. Then we need to get the WHOLE output as one and send it to export-csv, and this is why i used
sub-expression $() | export-csv… to grab first the whole output. I got loops for each cluster so , i cant export the loop to export-csv, as the file will be overwritten as the end by the last loop output. You could ommit the export-csv and the sub-expression here by sending the output straight to file using ” >> file.csv ” , but in this case you would have to prepare some [string]$line, which will have commas in it so it would look like a csv file.
If you find any bug in my scripts or you know more efficient way to do things describes in my posts, please do comment and share your experience.