@"
===============================================================================
Title: Export-VMInfo.ps1
Description: Exports VM Information from vCenter into a .CSV file for importing into anything
Usage: .\Export-VMInfo.ps1
Date: 04/03/2010
http://www.wooditwork.com/2010/08/16/exporting-all-that-useful-vm-information-with-powercli/
===============================================================================
"@
IF (Get-PSSnapin | where {$_.name -eq "VMware.VimAutomation.Core"})
{write-host "VMware.VimAutomation.Core snapin already loaded"}
Else
{
write-host "Loading VMware.VimAutomation.Core snapin"
add-PSSnapin VMware.VimAutomation.Core
write-host "VMware.VimAutomation.Core snapin Loaded"
}
$VirtualCenters= "vmvc1","vmvc2"
$Report = @()
$ExportFilePath = "c:\temp\Export-VMInfo.csv"
Function check-even ($num) {[bool]!($num%2)}
$smtpServer = "mail.blah.com"
$To = "Kevin Curran <kcurran@blah.com>"
$From = "AD Reporting <ADReporting@blah.com>"
function Get-VMSerial
{
param([VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]$VirtualMachine)
$s = ($VirtualMachine.ExtensionData.Config.Uuid).Replace("-", "")
$Uuid = "VMware-"
for ($i = 0; $i -lt $s.Length; $i += 2)
{
$Uuid += ("{0:x2}" -f [byte]("0x" + $s.Substring($i, 2)))
if ($Uuid.Length -eq 30) { $Uuid += "-" } else { $Uuid += " " }
}
Write-Output $Uuid.TrimEnd()
}
foreach ($VC in $VirtualCenters)
{
Connect-VIServer $VC
$VMs = Get-VM
$Datastores = Get-Datastore | select Name, Id
$VMHosts = Get-VMHost | select Name, Parent
$VMHostDataCenter=Get-Datacenter | foreach {
$Datacenter = $_.name
$_ | Get-VMHost | select @{Name="VMHost";Expression={($_.Name)}}, @{Name="DataCenter";Expression={($Datacenter)}}
}
$DataCenters= Get-Datacenter
#Collect Cluster Stats for email body
$VMsPerCLuster +=foreach ($DataCenter in $DataCenters)
{
$clusters=get-cluster -Location $DataCenter.Name
if ($clusters -eq $null)
{(get-vm -Location $DataCenter.Name).count | select @{Name="Name";Expression= {$DataCenter.Name}},
@{Name="Hosts";Expression={((Get-VMHost -Location $DataCenter.Name) | measure ).count}},
@{Name="VMs";Expression={(get-vm -Location $DataCenter.Name).count}},
@{Name="DataCenter";Expression={($DataCenter)}}
}
else
{
get-cluster -Location $DataCenter.Name | select Name, @{Name="Hosts"; Expression = {($_.ExtensionData.Host).count}},
@{Name="VMs"; Expression = {(Get-VM -Location $_.Name).count}},
@{Name="DataCenter";Expression={($DataCenter)}}
}
}
#collect VM data for attached list of vms
ForEach ($VM in $VMs) {
$counter ++
Write-Host $counter $VM.name
$VMView = $VM | Get-View
$Annotation = $vm | Get-Annotation
$VMInfo = {} | Select VMName,Powerstate,OS,IPAddress,ToolsStatus,Host,
Cluster,Datacenter,Datastore,inSRMResourcePool,NumCPU,MemMb,ProvisionedSpaceGB,
UsedSpaceGB,DiskGb,DiskFree,DiskUsed,Notes,BusinessOwner,
CreationDate,DownTimeWindow,PrimarySysAdmin,Tier,SerialNumber
$VMInfo.VMName = $vm.name
$VMInfo.Powerstate = $vm.Powerstate
$VMInfo.OS = $vm.Guest.OSFullName
$VMInfo.IPAddress = $vm.Guest.IPAddress[0]
$VMInfo.ToolsStatus = $VMView.Guest.ToolsStatus
$VMInfo.Host = $vm.VMhost.name
$VMInfo.Cluster = $vm.VMhost.Parent.Name
$VMInfo.Datacenter = ($VMHostDataCenter | where {$_.VMHost -eq $vm.VMhost.name} | select DataCenter).DataCenter
$VMInfo.Datastore = ($Datastores | where {$_.ID -match ($vmview.Datastore | Select -First 1).Value}).Name
$VMInfo.inSRMResourcePool = $vm.ResourcePool.Name -like "*SRM*"
$VMInfo.NumCPU = $vm.NumCPU
$VMInfo.MemMb = [Math]::Round(($vm.MemoryMB),2)
$VMInfo.ProvisionedSpaceGB = [Math]::Round($vm.ProvisionedSpaceGB)
$VMInfo.UsedSpaceGB = [Math]::Round($vm.UsedSpaceGB)
$VMInfo.DiskGb = [Math]::Round((($vm | get-harddisk | Measure-Object -Property CapacityKB -Sum).Sum * 1KB / 1GB),2)
$VMInfo.DiskFree = [Math]::Round((($vm.Guest.Disks | Measure-Object -Property FreeSpace -Sum).Sum / 1GB),2)
$VMInfo.DiskUsed = $VMInfo.DiskGb - $VMInfo.DiskFree
$VMInfo.Notes = $vm.Notes
$VMInfo.BusinessOwner = ($Annotation | where {$_.Name -eq "Business Owner"}).value
$VMInfo.CreationDate = ($Annotation | where {$_.Name -eq "Creation Date"}).value
$VMInfo.DownTimeWindow = ($Annotation | where {$_.Name -eq "Down Time Window"}).value
$VMInfo.PrimarySysAdmin = ($Annotation | where {$_.Name -eq "Primary SysAdmin"}).value
$VMInfo.Tier = ($Annotation | where {$_.Name -eq "Tier"}).value
$VMInfo.SerialNumber = Get-VMSerial $vm
$Report += $VMInfo
}
Disconnect-VIServer -Confirm:$False
}
#Export VM List Report to a File to attach to email
$Report = $Report | Sort-Object VMName
IF ($Report -ne "") {
$report | Export-Csv $ExportFilePath -NoTypeInformation
}
#Create a summary report to email VM to Host ratios
#Add Ratios
$VMStats=$VMsPerCLuster | Select DataCenter, Name, Hosts, VMs, @{Name="Ratio"; Expression = {"{0:n2} to 1" -f(($_.VMs) / ($_.Hosts)) }}
$TotalHosts = ($VMStats | Measure-Object -Sum -Property Hosts).sum
$TotalVMs = ($VMStats | Measure-Object -Sum -Property VMs).sum
$TotalRatio = "{0:n2} to 1" -f(($TotalVMs) / ($TotalHosts))
$TotalMessage = "<H2>Totals</H2>Total Hosts`: $totalHosts <br>Total VMs`: $totalVMs <br>Total Ratio`: $totalRatio <br>"
$SumaryReport= $VMStats | Group-Object -Property DataCenter | Sort Name
foreach ($RPTDataCtr in $SumaryReport)
{
$RPTDC = switch ($RPTDataCtr.Name)
{
"LADC" {"LA"}
"NYDC" {"NY"}
"CDC" {"Chicago"}
"FDC" {"Florida"}
default {$_}
}
$TempHTML = $null
$SubTotalHosts = $null
$SubTotalVMs = $null
$SubTotalRatio = $null
$SubTotalHosts = ($RPTDataCtr.Group | Measure-Object -Sum -Property Hosts).sum
$SubTotalVMs = ($RPTDataCtr.Group | Measure-Object -Sum -Property VMs).sum
$SubTotalRatio = "{0:n2} to 1" -f(($SubTotalVMs) / ($SubTotalHosts))
$TempHTML= $RPTDataCtr.Group | ConvertTo-Html -Fragment -Property Name, Hosts, VMs, Ratio -PreContent "<b>$RPTDC</b>" | ForEach-Object {$_}
$TempHTML = $TempHTML -Replace "</table>","<tr style=`"font-weight`: bold`;`"><td>Total</td><td>$SubTotalHosts</td><td>$SubTotalVMs</td><td>$SubTotalRatio</td></tr>`r`n</table>"
$Message += $TempHTML
#$Message+= $RPTDataCtr.Group | ConvertTo-Html -Fragment -Property Name, Hosts, VMs, Ratio -PreContent "<H2>$($RPTDataCtr.Name)</H2>" | ForEach-Object {$_}
}
#$Message= $VMStats | sort -Property Name | ConvertTo-Html
#$Message= $VMStats | sort -Property Name | ConvertTo-Html -PreContent "Current VM Stats <H2>VM Ratios </H2>" | ForEach-Object {$_}
$ModifiedHTML=ForEach ($line in $Message)
{
$counter++
if (check-even $counter)
{$line.replace('<tr><td>','<tr class="d0"><td>')}
Else
{$line.replace('<tr><td>','<tr class="d1"><td>')}
}
$PreMessage = @"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTML TABLE</title>
<style>
BODY{background-color:white;}
TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:MidnightBlue; color:Yellow}
TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}
TR.D0 TD {background-color: White; color: black;}
TR.D1 TD {background-color: LawnGreen; color: black;}
</style>
</head><body>
“@
$PostMessage += "<br>This script was run by " + $env:username + " on " + $env:COMPUTERNAME
$PostMessage += "<br>ScriptName: $($MyInvocation.MyCommand) "
$PostMessage += "<br>Script path: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"
$PostMessage += "</body></html>"
$html = $PreMessage + $TotalMessage + $($ModifiedHTML | out-string) + $PostMessage
#Send Message
Send-MailMessage -From $From -To $To -SmtpServer $smtpServer `
-Subject "VM Ratios" -BodyasHTML $HTML -Attachments $ExportFilePath