VMware Cloud Community
crosen
Contributor
Contributor

Consolidated VM Collection Script

I have about six scripts currently that pull this data and then that many Perl scripts to parse and put all of the data into one CSV file.  Needless to say it is a bit of a mess.  If I can pull all of the data I need in one script it will eliminate a lot of parsing errors.  Thanks.

$vmware_uuid,$vm_name,$vcenter_server,$vm_ip,$vm_os,$rp,$ram,$cpu,$hd,$vmt_status,$powerstate,$datastore,$numsnaps,$sizesnaps,$utilization

UUID:

Get-VM | select @{N="VMname"; E={$_.Name}},
@{N="UUID"; E={($_ | Get-View).config.uuid}} | Export-Csv $filename1 -noTypeInformation

VM Name, OS, IP:

Get-VM | %{
  $guest = $_ | Get-VMGuest
  $vm  = "" | Select VMname, OSFullName, IPAddr1
  $vm.VMname = $_.Name
  $vm.OSFullName = $guest.OSFullname
     if ($vm.OSFullName -eq "Microsoft Windows Server 2003, Enterprise Edition (32-bit)" ) {
       $vm.OSFullName = "Microsoft Windows Server 2003 Enterprise Edition (32-bit)"}
     elseif ($vm.OSFullName -eq "Microsoft Windows Server 2003, Enterprise Edition (64-bit)" ) {
       $vm.OSFullName = "Microsoft Windows Server 2003 Enterprise Edition (64-bit)"}
     elseif ($vm.OSFullName -eq "Microsoft Windows Server 2003, Standard Edition (32-bit)" ) {
       $vm.OSFullName = "Microsoft Windows Server 2003 Standard Edition (32-bit)"}
     elseif ($vm.OSFullName -eq "Microsoft Windows Server 2003, Standard Edition (64-bit)" ) {
       $vm.OSFullName = "Microsoft Windows Server 2003 Standard Edition (64-bit)"}
  $vm.IPAddr1 = $guest.IPAddress[0]
  $vm
} | Export-Csv "$filename1" -noTypeInformation

Specs:

$VMs = Get-VM
$myCol = @()
ForEach ($VM in $VMs)
{
$myObj = "" | Select-Object VMName, DisksGB
$myObj.VMName = $VM.Name
$myObj.DisksGB = [Math]::Round((($VM.HardDisks | Measure-Object -Property CapacityKB -Sum).Sum * 1KB / 1GB),2)
$myCol += $myObj
#$myCol
}
$myCol | Export-Csv "$filename1" -NoTypeInformation

$Report = @()
get-vm | % {
  $vm = Get-View $_.ID
    $vms = "" | Select-Object VMName, VMState, TotalCPU, TotalMemory, ToolsStatus, resourcepool, Datastore
    $vms.VMName = $vm.Name
    $vms.VMState = $vm.summary.runtime.powerState
    $vms.TotalCPU = $vm.summary.config.numcpu
    $vms.TotalMemory = $vm.summary.config.memorysizemb
    $vms.ToolsStatus = $vm.guest.toolsstatus
    $resourcepool = Get-ResourcePool -VM $vms.VMName
    $vms.resourcepool = $resourcepool.Name
    $Report += $vms
    #$Report
}
$Report | Export-Csv "$filename2" -noTypeInformation

$report = @()
Get-VM | Get-View | % {
$row = "" | select Name, Datastore
$row.Name = $_.Name
$row.Datastore = (Get-View $_.Datastore[0]).Summary.Name
$report += $row
}
$report | Export-Csv "$filename3" -noTypeInformation

Snapshots:

$DiskInfoDef = @"
public struct DiskInfo {
public string VMname;
public string TotalSnapMB;
"@

# Original
#$vms = Get-View -ViewType VirtualMachine
# New
$vms = Get-View -ViewType VirtualMachine -Property "LayoutEx", "Snapshot", "Config.Hardware.Device", "Name"

$maxSnapshot = ($vms | %{$_.LayoutEx.Snapshot.Count} | Measure-Object -Maximum).Maximum
1..$maxSnapshot | %{
$DiskInfoDef += ("`n`tpublic string Snap" + $_ + "MB;")
}
$DiskInfoDef += "`n}"

Add-Type -Language CsharpVersion3 -TypeDefinition $DiskInfoDef

$snapHash = @{}

filter Get-SnapHash{
$snapHash[$_.Snapshot.Value] = $_.Name
if($_.ChildSnapshotList){
  $_.ChildSnapShotList | Get-SnapHash
}
}

$vms | %{
$vm = $_

if($vm.Snapshot){
  $vm.Snapshot.RootSnapshotList | Get-SnapHash
}

$_.Config.Hardware.Device | where {$_.DeviceInfo.Label -like "Hard disk *"} | %{
  $hd = $_
  $vm.LayoutEx.Disk | where {$_.Key -eq $hd.Key} | %{
   $diskFiles = $_.Chain | %{$_.FileKey} | %{$_}
  }

  $diskInfo = New-Object DiskInfo
  $diskInfo.VMname = $vm.Name
  $snapNr = 1
  if($vm.Snapshot){
   $totalSnapMB = 0
   $vm.LayoutEx.Snapshot | %{
    $_.Disk | where {$_.Key -eq $hd.Key} | %{
     $prevFiles = $_.Chain | %{$_.FileKey} | %{$_}
    }
    $vm.LayoutEx.Disk | where {$_.Key -eq $hd.Key} | %{
     foreach($chain in $_.Chain){
      if($prevFiles -notcontains $chain.FileKey[0] -and $prevFiles -notcontains $chain.FileKey[1]){
       break
      }
     }
    }
    $snapFiles = $chain.FileKey | %{$_}
    $snapSize = ""
    if($snapFiles){
     $snapAllocated = 0
     $vm.LayoutEx.File | where {$snapFiles -contains $_.Key} | %{
      $snapAllocated += $_.Size
     }
     $snapSize = ("{0:N1}" -f ($snapAllocated / 1MB))
    }
    $diskInfo.("Snap" + $snapNr + "MB") = $snapSize
    $totalSnapMB += ($snapAllocated / 1MB)
    $snapNr++
   }
   $totalSnapMB = ($totalSnapMB/1024)
   $diskInfo.TotalSnapMB = ("{0:N1}" -f $totalSnapMB)
  }
  $diskInfo
}
} | Export-Csv $filename1 -UseCulture -NoTypeInformation

0 Kudos
10 Replies
LucD
Leadership
Leadership

Besides the snapshot part, it is straightforward to collect all the properties in 1 loop.

It's a matter of collection all the required properties in 1 variable, I called it $row, and store it in an array, called $report, which you can then export to  a CSV file.

Something like this

$report = @()
foreach($vm in Get-VM){
    $guest = Get-VMGuest -VM $vm    $row = "" | Select VMName,UUID,OSFullName,IPAddr,DisksGB,VMState,
                    TotalCPU,TotalMemory,ToolsStatus,Resourcepool,Datastore
    $row.VMName = $vm.Name
    $row.UUID = $vm.ExtensionData.config.uuid
    $row.OSFullName = $vm.Guest.OSFullName
    $row.IPAddr = $guest.IPAddress[0]
    $row.DisksGB = [Math]::Round((($VM.HardDisks | Measure-Object -Property CapacityKB -Sum).Sum * 1KB / 1GB),2)
    $row.VMState = $vm.powerState
    $row.TotalCPU = $vm.numcpu
    $row.TotalMemory = $vm.memorymb
    $row.ToolsStatus = $vm.Extensiondata.Guest.toolsstatus
    $row.Resourcepool = (Get-ResourcePool -VM $vm).Name
    $row.Datastore = [string]::Join(',',(Get-Datastore -VM $vm | %{$_.Name}))
    $report += $row    
}
$report | Export-Csv "C:\MyReport.csv" -NoTypeInformation -UseCulture 

The snapshots is another story.

Since there can be x-number of snapshots on a VM, I created a script that uses a dynamic object to store the information.

That dynamic object is defined in C#.

If you want to incorporate the first part with the snapshot part, one would have to define the complete $row variable from the previous script in a C# declaration.


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

0 Kudos
crosen
Contributor
Contributor

$row.OSFullName = $vm.OSFullName is not pulling anything.

0 Kudos
LucD
Leadership
Leadership

That should have said $vm.Guest.OSFullName.

I updated the script


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

0 Kudos
crosen
Contributor
Contributor

OS working now!!!

I use a CPU utilization metric using Perl (http://communities.vmware.com/docs/DOC-1010)...can I get something like that using this script?  A 30 day average for CPU?

We also use the VMware notes section to contain a string of the creation date, expiration date, owner, and product.  I think I can pull it using this script, but don't know if I can separate the fields like I do in Perl?

foreach($vm in $VMs){
$myObj = "" | Select-Object Name, Notes
$myObj.Name = $VM.Name
$myObj.Notes = $VM.Description
      $myCol += $myObj
}

0 Kudos
crosen
Contributor
Contributor

Trying to add an if statement that does a comparison of a variable.  Have tried -contains, -like, and -match, but can't get this working...

if ($row.Resourcepool -match "010") {
  $row.VP = "VP 1"
} elsif ($row.Resourcepool -match "020") {
  $row.VP = "VP 2"
} elsif ($row.Resourcepool -match "030") {
  $row.VP = "VP 3"
} elsif ($row.Resourcepool -match "040") {
  $row.VP = "VP 4"
} elsif ($row.Resourcepool -match "050") {
  $row.VP = "VP 5"
} elsif ($row.Resourcepool -match "060") {
  $row.VP = "VP 6"
} elsif ($row.Resourcepool -match "070") {
  $row.VP = "VP 7"
} elsif ($row.Resourcepool -match "080") {
  $row.VP = "VP 8"
} elsif ($row.Resourcepool -match "090") {
  $row.VP = "VP 8"
} elsif ($row.Resourcepool -match "200") {
  $row.VP = "VP 9"
} else {
  $row.VP = "VP10"
}

Unexpected token 'VP"
    if ($row.Resourcepool -match "010") {
        $row.VP = "VP' in expression or statement.
At C:\MyDocs\work\Virtualization\VMWare\VMware_Healthcheck\Notes_Fields\TCOMDB_
Data\consolidated_data_collection.ps1:30 char:16
+     #$row.VP =  <<<< "VP"
    + CategoryInfo          : ParserError: (VP"
    if ($ro...        $row.VP = "VP:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

0 Kudos
LucD
Leadership
Leadership

Did you add the VP property to the line where you define the $row object ?

$row = "" | Select ...,VP,...


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

0 Kudos
crosen
Contributor
Contributor

I did have it defined.  After some more tweaking I got my desired resulte with -match.

Now I just need a CPU utilization metric and the ability to split a variable into pieces like I do in perl today...

($name,$notes) = split(/,/,$item);

$name =~ s/"//g;
  $notes =~ s/"//g;

0 Kudos
LucD
Leadership
Leadership

How does that variable look ?

CPU metrics for host or VM ?

Shouldn't be too difficult.

$cpuAvg = (Get-Stat -Entity $esx -Stat cpu.usage.average -Start (Get-Date).AddDays(-1) | Measure-Object -Property Value -Average).Average


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

0 Kudos
crosen
Contributor
Contributor

CPU for the VM.

The Notes fields comes in like that "EXP:13 AUG 11;DOB:13 AUG 09;OWN:name1;name2;PROD:product" and need to split that into variables for $exp, $dob, $owner1, $owner2 (which can be blank), and $prod.

0 Kudos
LucD
Leadership
Leadership

A simple way to split that string could be something like this

$t = "EXP:13 AUG 11;DOB:13 AUG 09;OWN:name1;name2;PROD:product"
$temp = $t.Split(';')
$exp = $temp[0].Split(':')[1]
$dob = $temp[1].Split(':')[1]
$owner1 = $temp[2].Split(':')[1]
$owner2 = $temp[3]
$prod = $temp[4].Split(':')[1]

If you want the VM stats, you just have to give a $vm to the -Entity parameter.

$vm = Get-VM MyVM

Get-Stat -Entity $vm ...


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

0 Kudos