AdamUK
Enthusiast
Enthusiast

PowerCli script with Get-View to report on VMs and specifications

Jump to solution

I have obtained the script below from the Web and I have amended it for my purpose:

$report = @()

foreach ($dc in Get-Datacenter) {

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

      $vms = Get-view -ViewType VirtualMachine

      foreach ($vm in $vms){

        $info = "" | select Datacenter, Name, ToolsStatus, NumCpu, MemoryMB, guestos, @{N='IPAddr';E={[string]::Join(',',$vm.Guest.net.IPAddress)}} | sort Name

        $info.datacenter = $dc.name

        $info.Name = $vm.name

        $info.toolsstatus = $vm.guest.toolsstatus

        $info.NumCpu = $vm.Summary.config.NumCpu

        $info.MemoryMB = $vm.Summary.config.memorySizeMB

        $info.guestos = $vm.guest.guestfullname

        $report += $info

      }

    }

}

$report | export-csv "\Report.csv" -NoTypeInformation

I would now like to amend the script to add the Datastore that each VM is stored on but I cannot seem to pipe that information into the script.  I have found another script which gets the datastore name but I cannot figure out how to configure the script above to include it:

Get-View -ViewType "VirtualMachine" -Property "Name", "Config.DatastoreUrl" | Select-Object -Property Name, @{N="DataStore";E={$_.Config.DatastoreUrl | %{$_.Name}}}

Please could you help?

1 Solution

Accepted Solutions
LucD
Leadership
Leadership

You could get that information directly from the VirtualMachine object, no need to do a Get-HardDisk.

Something like this

$report = @()

foreach ($dc in Get-Datacenter) {

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

      $vms = Get-view -ViewType VirtualMachine -SearchRoot $cluster.ExtensionData.MoRef

      foreach ($vm in $vms){

        $info = "" | select Datacenter, Name, ToolsStatus, NumCpu, MemoryMB, guestos, IPAddress, Datastore, DatastoreUsedGB

        $info.IPAddress = ($vm.Guest.net.IPAddress | where{$_} | Sort-Object -Unique) -join '|'

        $info.Datastore = (Get-View -Id $vm.Datastore -Property Name).Name -join '|'

        $info.DatastoreUsedGB = [math]::Round(($vm.Storage.PerDatastoreUsage.Committed | Measure-Object -Sum).Sum/1GB,1)

        $info.datacenter = $dc.name

        $info.Name = $vm.name

        $info.toolsstatus = $vm.guest.toolsstatus

        $info.NumCpu = $vm.Summary.config.NumCpu

        $info.MemoryMB = $vm.Summary.config.memorySizeMB

        $info.guestos = $vm.guest.guestfullname

        $report += $info

      }

    }

}

$report | export-csv "\Report.csv" -NoTypeInformation


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

View solution in original post

18 Replies
LucD
Leadership
Leadership

Try something like this.

$report = @()

foreach ($dc in Get-Datacenter) {

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

      $vms = Get-view -ViewType VirtualMachine

      foreach ($vm in $vms){

        $info = "" | select Datacenter, Name, ToolsStatus, NumCpu, MemoryMB, guestos, IPAddress, Datastore

        $info.IPAddress = ($vm.Guest.net.IPAddress | where{$_} | Sort-Object -Unique) -join '|'

        $info.Datastore = (Get-View -Id $vm.Datastore -Property Name).Name -join '|'

        $info.datacenter = $dc.name

        $info.Name = $vm.name

        $info.toolsstatus = $vm.guest.toolsstatus

        $info.NumCpu = $vm.Summary.config.NumCpu

        $info.MemoryMB = $vm.Summary.config.memorySizeMB

        $info.guestos = $vm.guest.guestfullname

        $report += $info

      }

    }

}

$report | export-csv "\Report.csv" -NoTypeInformation


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

AdamUK
Enthusiast
Enthusiast

Thanks, that works like a charm.  Is there any way I can now sort by Datacenter, then Name?  So the Datacenter values are sorted alphabetically and so are the VM Names under that Datacenter?

0 Kudos
LucD
Leadership
Leadership

Sure, replace the last line with

$report | Sort-Object -Property Datacenter,Name |

Export-Csv "\Report.csv" -NoTypeInformation


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

AdamUK
Enthusiast
Enthusiast

Almost there, but the script seems to duplicate all of the VMs against all of the Datacenters.  So for example:

Datacenter1 contains VM-A & VM-B

Datacenter2 contains VM-C & VM-D

Datacenter3 contains VM-E & VM-F

Datacenter4 contains VM-G * VM-H

The generated report lists all 8 VMs against all 4 Datacenters so completes with 32 VMs across 4 Datacenters instead of 8.  Is there any changes I can make so that only the required VMs get listed against the Datacenter they are in?

0 Kudos
LucD
Leadership
Leadership

That is what you script is doing, you're getting all the VMs for each iteration through data/cluster.

To limit it to only to the VMs in a cluster, use the SearchRoot parameter.

Replace the line with

$vms = Get-view -ViewType VirtualMachine -SearchRoot $cluster.ExtensionData.MoRef


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

AdamUK
Enthusiast
Enthusiast

Thanks very much for your help.  Last one is that I am trying to get the Datastore diskspace used by VM so I have tried adding the line below but I guess it it not formatted correctly because when I try to re-format the command it either does not work or it causes script errors?

$info.DatastoreUsed = (Get-HardDisk -VM $vm.name -Property Name | Select-Object CapacityGB).Name -join '|'

LucD
Leadership
Leadership

You could get that information directly from the VirtualMachine object, no need to do a Get-HardDisk.

Something like this

$report = @()

foreach ($dc in Get-Datacenter) {

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

      $vms = Get-view -ViewType VirtualMachine -SearchRoot $cluster.ExtensionData.MoRef

      foreach ($vm in $vms){

        $info = "" | select Datacenter, Name, ToolsStatus, NumCpu, MemoryMB, guestos, IPAddress, Datastore, DatastoreUsedGB

        $info.IPAddress = ($vm.Guest.net.IPAddress | where{$_} | Sort-Object -Unique) -join '|'

        $info.Datastore = (Get-View -Id $vm.Datastore -Property Name).Name -join '|'

        $info.DatastoreUsedGB = [math]::Round(($vm.Storage.PerDatastoreUsage.Committed | Measure-Object -Sum).Sum/1GB,1)

        $info.datacenter = $dc.name

        $info.Name = $vm.name

        $info.toolsstatus = $vm.guest.toolsstatus

        $info.NumCpu = $vm.Summary.config.NumCpu

        $info.MemoryMB = $vm.Summary.config.memorySizeMB

        $info.guestos = $vm.guest.guestfullname

        $report += $info

      }

    }

}

$report | export-csv "\Report.csv" -NoTypeInformation


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

View solution in original post

AdamUK
Enthusiast
Enthusiast

Thanks, exactly what I was looking for.  The only change I have made is to convert the MemoryMb to MemoryGB and to change the line below as follows:

$info.MemoryGB = $vm.Summary.config.memorySizeMB / 1024

Thanks very much for your help

0 Kudos
AdamUK
Enthusiast
Enthusiast

Apologies for the additional ask, but is there a way I can calculate the total number of VMs per Datacenter/Cluster?  I have amended the script so it reports the total number of VMs in the vCenter instance by adding $total_vms = (Get-VM).count and I also found the command below:

get-cluster | select @{n="cluster";e={$_.name}}, @{n="hosts";e={($_ | get-vmhost).count}}, @{n="vms";e={($_ | get-vm).count}} | sort cluster | ft -auto

which works if I run it manually but if I try to integrate it into the script by assigning it to a variable, the output is as follows:

Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

I basically want it to output the results at the beginning of the output file

0 Kudos
LucD
Leadership
Leadership

The Export-Csv cmdlet looks at the 1st row if data to determine which columns will appear in the CSV.

So if you rows are not the same, the CSV file only contain part of the data.

You could repeat the information on each row, thus making sure each row has the same columns.

$report = @()

foreach ($dc in Get-Datacenter) {

    $dcVm = Get-View -ViewType VirtualMachine -Property Name -SearchRoot $dc.ExtensionData.MoRef

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

      $vms = Get-view -ViewType VirtualMachine -SearchRoot $cluster.ExtensionData.MoRef

      foreach ($vm in $vms){

        $info = "" | select Datacenter, Name, ToolsStatus, NumCpu, MemoryMB, guestos, IPAddress,

            Datastore, DatastoreUsedGB,NrVMperDC,NrVMperCluster

        $info.IPAddress = ($vm.Guest.net.IPAddress | where{$_} | Sort-Object -Unique) -join '|'

        $info.Datastore = (Get-View -Id $vm.Datastore -Property Name).Name -join '|'

        $info.DatastoreUsedGB = [math]::Round(($vm.Storage.PerDatastoreUsage.Committed | Measure-Object -Sum).Sum/1GB,1)

        $info.datacenter = $dc.name

        $info.Name = $vm.name

        $info.toolsstatus = $vm.guest.toolsstatus

        $info.NumCpu = $vm.Summary.config.NumCpu

        $info.MemoryMB = $vm.Summary.config.memorySizeMB

        $info.guestos = $vm.guest.guestfullname

        $info.NrVMperDC = $dcVm.Count

        $info.NrVmperCluster = $vms.Count

        $report += $info

      }

    }

}

$report | export-csv "\Report.csv" -NoTypeInformation


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

0 Kudos
AdamUK
Enthusiast
Enthusiast

That appears to display the figures in the table against each VM rather than separately.  What I was looking for was something like the following although the ClusterHosts and ClusterVMs fields do not display the details correctly (the ClusterName is reported correctly for all cluster instances).  The html configuration is something I am working on for display purposes so I have defined $html (and $export_html & $Dateformat) separately

$total_vms = (Get-VM).count

$reportcluster = @()

foreach ($dc in Get-Datacenter) {

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

$infocluster = "" | select ClusterName, ClusterHosts, ClusterVMs

$infocluster.ClusterName = $cluster

$infocluster.ClusterHosts = (get-cluster | select @{n="hosts";e={($_ | get-vmhost).count}}) -join '|'

$infocluster.ClusterVMs =  (get-cluster | select @{n="vms";e={($_ | get-vm).count}}) -join '|'

$reportcluster += $infocluster

      }

}

$reportcluster | Sort-Object -Property ClusterName | ConvertTo-Html -Head $html -Body "<h1> Report run on: $Dateformat</h1><h2>Total number of VMs across all Data Centres/Clusters: $total_vms</h2>" | Out-File $export_html

0 Kudos
LucD
Leadership
Leadership

Try like this

$total_vms = (Get-VM).count

$reportcluster = @()

foreach ($dc in Get-Datacenter) {

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

        $infocluster = "" | select ClusterName, ClusterHosts, ClusterVMs

        $infocluster.ClusterName = $cluster

        $infocluster.ClusterHosts = (Get-VMHost -Location $_).count

        $infocluster.ClusterVMs = (Get-VM -Location $_).Count

        $reportcluster += $infocluster

    }

}

$reportcluster | Sort-Object -Property ClusterName |

ConvertTo-Html -Head $html -Body "<h1> Report run on: $Dateformat</h1><h2>Total number of VMs across all Data Centres/Clusters: $total_vms</h2>" |

Out-File $export_html


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

0 Kudos
cnuvaasan
Contributor
Contributor
how to get the same report for signle vm
0 Kudos
LucD
Leadership
Leadership

Which of the many scripts in this thread are you referring to?


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

0 Kudos
cnuvaasan
Contributor
Contributor

$report = @()

foreach ($dc in Get-Datacenter) {

    $dcVm = Get-View -ViewType VirtualMachine -Property Name -SearchRoot $dc.ExtensionData.MoRef

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

      $vms = Get-view -ViewType VirtualMachine -SearchRoot $cluster.ExtensionData.MoRef

      foreach ($vm in $vms){

        $info = "" | select Datacenter, Name, ToolsStatus, NumCpu, MemoryMB, guestos, IPAddress,

            Datastore, DatastoreUsedGB,NrVMperDC,NrVMperCluster

        $info.IPAddress = ($vm.Guest.net.IPAddress | where{$_} | Sort-Object -Unique) -join '|'

        $info.Datastore = (Get-View -Id $vm.Datastore -Property Name).Name -join '|'

        $info.DatastoreUsedGB = [math]::Round(($vm.Storage.PerDatastoreUsage.Committed | Measure-Object -Sum).Sum/1GB,1)

        $info.datacenter = $dc.name

        $info.Name = $vm.name

        $info.toolsstatus = $vm.guest.toolsstatus

        $info.NumCpu = $vm.Summary.config.NumCpu

        $info.MemoryMB = $vm.Summary.config.memorySizeMB

        $info.guestos = $vm.guest.guestfullname

        $info.NrVMperDC = $dcVm.Count

        $info.NrVmperCluster = $vms.Count

        $report += $info

      }

    }

}

$report | export-csv "\Report.csv"

the same script but i need to get a single vm  report

0 Kudos
LucD
Leadership
Leadership

Use the Filter parameter on the Get-View cmdlet.

$report = @()

$vmName = 'MyVM'


foreach ($dc in Get-Datacenter) {

    $dcVm = Get-View -ViewType VirtualMachine -Property Name -SearchRoot $dc.ExtensionData.MoRef

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

      $vms = Get-view -ViewType VirtualMachine -SearchRoot $cluster.ExtensionData.MoRef -Filter @{Name="^$vmName$"}

      foreach ($vm in $vms){

        $info = "" | select Datacenter, Name, ToolsStatus, NumCpu, MemoryMB, guestos, IPAddress,

            Datastore, DatastoreUsedGB,NrVMperDC,NrVMperCluster

        $info.IPAddress = ($vm.Guest.net.IPAddress | where{$_} | Sort-Object -Unique) -join '|'

        $info.Datastore = (Get-View -Id $vm.Datastore -Property Name).Name -join '|'

        $info.DatastoreUsedGB = [math]::Round(($vm.Storage.PerDatastoreUsage.Committed | Measure-Object -Sum).Sum/1GB,1)

        $info.datacenter = $dc.name

        $info.Name = $vm.name

        $info.toolsstatus = $vm.guest.toolsstatus

        $info.NumCpu = $vm.Summary.config.NumCpu

        $info.MemoryMB = $vm.Summary.config.memorySizeMB

        $info.guestos = $vm.guest.guestfullname

        $info.NrVMperDC = $dcVm.Count

        $info.NrVmperCluster = $vms.Count

        $report += $info

      }

    }

}

$report | export-csv "\Report.csv"


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

0 Kudos
GustavoDXC
Contributor
Contributor

It is possible to list each vm cluster on this report?

0 Kudos
LucD
Leadership
Leadership

Try something like this

$report = @()
$vmName = 'MyVM'

foreach ($dc in Get-Datacenter) {
    $dcVm = Get-View -ViewType VirtualMachine -Property Name -SearchRoot $dc.ExtensionData.MoRef
    foreach ($cluster in Get-Cluster -Location $dc){
      $vms = Get-view -ViewType VirtualMachine -SearchRoot $cluster.ExtensionData.MoRef -Filter @{Name="^$vmName$"}
      foreach ($vm in $vms){
        $info = "" | select Datacenter, Cluster, Name, ToolsStatus, NumCpu, MemoryMB, guestos, IPAddress,
            Datastore, DatastoreUsedGB,NrVMperDC,NrVMperCluster
        $info.Datacenter = $dc.Name
        $info.Cluster = $cluster.Name
        $info.IPAddress = ($vm.Guest.net.IPAddress | where{$_} | Sort-Object -Unique) -join '|'
        $info.Datastore = (Get-View -Id $vm.Datastore -Property Name).Name -join '|'
        $info.DatastoreUsedGB = [math]::Round(($vm.Storage.PerDatastoreUsage.Committed | Measure-Object -Sum).Sum/1GB,1)
        $info.datacenter = $dc.name
        $info.Name = $vm.name
        $info.toolsstatus = $vm.guest.toolsstatus
        $info.NumCpu = $vm.Summary.config.NumCpu
        $info.MemoryMB = $vm.Summary.config.memorySizeMB
        $info.guestos = $vm.guest.guestfullname
        $info.NrVMperDC = $dcVm.Count
        $info.NrVmperCluster = $vms.Count
        $report += $info
      }
    }
}

$report | export-csv "\Report.csv"


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

0 Kudos