Report your VM growth per Cluster (Part 1of2 Collect Data)
What about a Report about your VM growth per Cluster?
The only thing we use is Excel, PowerCLI and HTML-Reports. I show you how to build that.
First we collect our data with PowerCLI (4 Reports)
- VMs per Cluster
- Count Guest OS
- Host Inventory
- Datastore Inventory
VMs per Cluster:
#Load Powercli Snapin Add-PSSnapin VMware.VimAutomation.Core #Connect vCenter Server Connect-VIServer -server yourvcenter.local -User [email protected] -password yourpassword #Define Var $vmscsv = "L:\HTML-Reports\VMs-per-Cluster\CSV\All-VMs" + ".csv" #html-out files $vmhtml = "L:\HTML-Reports\VMs-per-Cluster\All-VMs" + ".html" #html custom $custom = '<style> BODY{background-color:#A4D7D2;} 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;} TD{border-width:1px; padding:0px; border-style:solid; border-color:black;} </style>' #get-cluster | select-object name, @{Name="VMCount"; Expression = {(get-vm -location $_ | measure-object).count }} | Out-File -Append -FilePath $fileNameVM $ClusterA = get-cluster ClusterA| select-object name, @{Name="VMCount"; Expression = {(get-vm -location $_ | measure-object).count }},@{Label='Date';Expression={(Get-Date).ToString('dd-MM-yyyy')}} $ClusterB = get-cluster ClusterB| select-object name, @{Name="VMCount"; Expression = {(get-vm -location $_ | measure-object).count }},@{Label='Date';Expression={(Get-Date).ToString('dd-MM-yyyy')}} $ClusterC = get-cluster ClusterC| select-object name, @{Name="VMCount"; Expression = {(get-vm -location $_ | measure-object).count }},@{Label='Date';Expression={(Get-Date).ToString('dd-MM-yyyy')}} $ClusterD = get-cluster ClusterD| select-object name, @{Name="VMCount"; Expression = {(get-vm -location $_ | measure-object).count }},@{Label='Date';Expression={(Get-Date).ToString('dd-MM-yyyy')}} $ClusterE = get-cluster ClusterE| select-object name, @{Name="VMCount"; Expression = {(get-vm -location $_ | measure-object).count }},@{Label='Date';Expression={(Get-Date).ToString('dd-MM-yyyy')}} #Build Array $Object = New-Object PSObject -Property @{ Date = $ClusterA.Date $ClusterA.name = $ClusterA.VMCount $ClusterB.name = $ClusterB.VMCount $ClusterC.name = $ClusterC.VMCount $ClusterD.name = $ClusterD.VMCount $ClusterE.name = $ClusterE.VMCount "All VMs" = $ClusterA.VMCount+$ClusterB.VMCount+$ClusterC.VMCount+$ClusterC.VMCount+$ClusterD.VMCount+ClusterE.VMCount } #Sort Object & Convert to CSV $Object | select "Date","All VMs",$ClusterA.name,$ClusterB.name,$ClusterC.name,$ClusterD.name,$ClusterE.name | export-csv -Append -Delimiter ";" -Encoding UTF8 -Path $vmscsv #Convert to Html Import-Csv $vmscsv -Delimiter ";" | ConvertTo-HTML | Out-File $vmhtml #Disconnect vCenter Server Disconnect-VIServer * -Confirm:$false
Count Guest OS:
#Load Powercli Snapin Add-PSSnapin VMware.VimAutomation.Core #Connect vCenter Server Connect-VIServer -server yourvcenter.local -User [email protected] -password yourpasswd #def var $path1 = "L:\HTML-Reports\Kennzahlen\GuestOS\CSV\GuestOS-latest" + ".csv" $path2 = "L:\HTML-Reports\Kennzahlen\GuestOS\GuestOS-latest" + ".html" #get vms by guest name $arrOS = ( Get-VM | Get-View).summary.config.guestFullName $arrOS | Group-Object | Where-Object {$_.Count -gt 1} | select Name, Count | sort Name | export-csv -Delimiter ";" -Encoding UTF8 -Path $path1 #convert to html Import-Csv $path1 -Delimiter ";" | ConvertTo-HTML | Out-File $path2 #Disconnect vCenter Server Disconnect-VIServer * -Confirm:$false
Host Inventory:
########################################################################################### # Creates a HTML Output of your Host with informations like Name, Manufacturer,Version,etc# ########################################################################################### #Load Powercli Snapin Add-PSSnapin VMware.VimAutomation.Core #Connect vCenter Server Connect-VIServer -server yourvcenter.local -User [email protected] -password yourpassword #Define Var $htmlfile = "L:\HTML-Reports\Inventory\ESX-Hosts\older-versions\Hosts-" + (Get-Date -Format yyyy-MM-dd) + ".html" $htmlfile2 = "L:\HTML-Reports\Inventory\ESX-Hosts\Hosts-lastest-" + ".html" $date = (Get-Date -Format yyyy-MM-dd) $logo = '<img src="http://your-logo.svg" alt="" align="right">' #html custom $custom = '<style> BODY{background-color:#A4D7D2;} TABLE{border-width:1px; border-style:solid; border-color:black; border-collapse:collapse;} TH{border-width:1px; padding:1px; border-style:solid; border-color:black;} TD{border-width:1px; padding:1px; border-style:solid; border-color:black;} </style>' function Get-VMHostinventory { <# .SYNOPSIS Collects .DESCRIPTION Detailed Description .EXAMPLE Get-VMHostinventory youresxhost Get-VMHostinventory * explains how to use the command can be multiple lines .EXAMPLE Get-cdpinfo another example can have as many examples as you like #> param ( [Parameter(Mandatory=$true)] $EsxHost ) foreach ($vmhost in (Get-VMHost $EsxHost)) { Write-host $vmhost.Name if ($vmhost.Version -ne "4.1.0") { $esxcli = $vmhost | Get-EsxCli $serviceTag = $esxcli.hardware.platform.get().SerialNumber } else { $serviceTag = $vmhost.ExtensionData.summary.hardware.otheridentifyinginfo | select-object -ExpandProperty IdentifierValue -last 1 } #Esxihost Management IP and vlan ID $Managementinfo = $vmhost | Get-VMHostNetworkAdapter | Where-Object {$_.ManagementTrafficEnabled -eq $true} $VirtualPortGroup = $vmhost | Get-VirtualPortGroup $IPinfo = $Managementinfo | select-object -ExpandProperty ip $ManagementPortGroup = $Managementinfo.extensiondata.spec $ManagementIP = $IPinfo -join ", " $MulitvLans = @() if ($ManagementPortGroup.DistributedVirtualPort -ne $null) { $vLanIDinfo = $VirtualPortGroup | Where-Object {$Managementinfo.PortGroupName -contains $_.name} foreach ($MGMTVlan in $vLanIDinfo) { $MulitvLans += $MGMTVlan.ExtensionData.config.DefaultPortConfig.Vlan.VlanId } $vLanID = $MulitvLans -join ", " } else { $vLanIDinfo = $VirtualPortGroup | Where-Object {$ManagementPortGroup.Portgroup -contains $_.name } | Select-Object -ExpandProperty VLanId foreach ($MGMTVlan in $vLanIDinfo) { $MulitvLans += $MGMTVlan } $vLanID = $MulitvLans -join ", " } #EsxiHost CPU info $HostCPU = $vmhost.ExtensionData.Summary.Hardware.NumCpuPkgs $HostCPUcore = $vmhost.ExtensionData.Summary.Hardware.NumCpuCores/$HostCPU #All Virtual Machines Info $VMs = $vmhost | Get-VM $PoweredOnVM = $VMs | Where-Object {$_.PowerState -eq "PoweredOn"} #EsxiHost and VM -- CPU calculation $AssignedTotalvCPU = $VMs | Measure-Object NumCpu -Sum | Select-Object -ExpandProperty sum $PoweredOnvCPU = $PoweredOnVM | Measure-Object NumCpu -Sum | Select-Object -ExpandProperty sum $onecoreMhz = $vmhost.CPUTotalMhz / $vmhost.NumCpu $TotalPoweredOnMhz = $onecoreMhz * $PoweredOnvCPU #EsxiHost and VM -- Memory calculation $TotalMemory = [math]::round($vmhost.MemoryTotalGB) $Calulatedvmmemory = $VMs | Measure-Object MemoryGB -sum | Select-Object -ExpandProperty sum $TotalvmMemory = [math]::round($Calulatedvmmemory) $Calulatedvmmemory = $PoweredOnVM | Measure-Object MemoryGB -sum | Select-Object -ExpandProperty sum $PoweredOn_vMemory = "{0:N2}" -f $Calulatedvmmemory #EsxiHost Domain Details $domain = ($vmhost | Get-VMHostAuthentication).Domain #Cluster and Datstore info $Clusterinfo = $vmhost | Get-Cluster $Clustername = $Clusterinfo.Name $DataCenterinfo = Get-DataCenter -VMHost $VMHost.Name $Datacentername = $DataCenterinfo.Name #vCenterinfo $vCenter = $vmhost.ExtensionData.CLient.ServiceUrl.Split('/:')[3] $vcenterversion = $global:DefaultVIServers | where {$_.Name -eq $vCenter} | %{"$($_.Version) build $($_.Build)"} #vmhost SSH service Staus $SSHservice = $vmhost | Get-VMHostService | Where-object {$_.key -eq "Tsm-ssh"} | Select-Object -ExpandProperty running #vmhost Uptime $UPtime = (Get-Date) - ($vmhost.ExtensionData.Runtime.BootTime) | Select-Object -ExpandProperty days #BIOS $BIOS = $vmhost.ExtensionData.Hardware.BiosInfo.BiosVersion #vmhost syslog server settings if ($vmhost.Version -ne "4.1.0") { $syslog = ($vmhost | Get-AdvancedSetting -Name Syslog.global.logHost).value } else {$syslog = "Not Supported"} #vmhost Dump collector $DumpCollector = $esxcli.system.coredump.network.get().NetworkServerIP $VmHostresult = New-Object PSObject $VmHostresult | add-member -MemberType NoteProperty -Name "Name" -Value $vmhost.Name $VmHostresult | add-member -MemberType NoteProperty -Name "Management IP" -Value $ManagementIP $VmHostresult | add-member -MemberType NoteProperty -Name "vLan ID" -Value $vlanID $VmHostresult | add-member -MemberType NoteProperty -Name "PowerState" -Value $vmhost.PowerState $VmHostresult | add-member -MemberType NoteProperty -Name "Manufacturer" -Value $vmhost.Manufacturer $VmHostresult | add-member -MemberType NoteProperty -Name "Model" -Value $vmhost.Model $VmHostresult | add-member -MemberType NoteProperty -Name "Service_Tag" -Value $serviceTag $VMHostresult | add-member -MemberType NoteProperty -Name "TotalVms" -Value $VMs.count $VMHostresult | add-member -MemberType NoteProperty -Name "PoweronVMs" -Value $PoweredOnvm.Count $VmHostresult | add-member -MemberType NoteProperty -Name "ProcessorType" -Value $VMHost.ProcessorType $VmHostresult | add-member -MemberType NoteProperty -Name "CPU_Sockets" -Value $HostCPU $VmHostresult | add-member -MemberType NoteProperty -Name "CPU_core_per_socket" -Value $HostCPUcore $VmHostresult | add-member -MemberType NoteProperty -Name "Logical_CPUs" -Value $vmhost.Numcpu $VmHostresult | add-member -MemberType NoteProperty -Name "TotalHost_Mhz" -Value $vmhost.CPUTotalMhz $VmHostresult | add-member -MemberType NoteProperty -Name "AssignedTotal_vCPUs" -Value $AssignedTotalvCPU $VmHostresult | add-member -MemberType NoteProperty -Name "PoweredOn_vCPUs" -Value $PoweredOnvCPU $VmHostresult | add-member -MemberType NoteProperty -Name "PoweredOn_Mhz" -Value $TotalPoweredOnMhz $VmHostresult | add-member -MemberType NoteProperty -Name "Memory(GB)" -Value $TotalMemory $VmHostresult | add-member -MemberType NoteProperty -Name "AssignedTotal-vMemory(GB)" -Value $TotalvmMemory $VmHostresult | add-member -MemberType NoteProperty -Name "PoweredOn-vMemory(GB)" -Value $PoweredOn_vMemory $VmHostresult | add-member -MemberType NoteProperty -Name "Esxi-Version" -Value $vmhost.Version $VmHostresult | add-member -MemberType NoteProperty -Name "Build-Number" -Value $vmhost.Build $VmHostresult | add-member -MemberType NoteProperty -Name "Domain" -Value $domain $VmHostresult | add-member -MemberType NoteProperty -Name "Max-EVC-Key" -Value $vmhost.ExtensionData.Summary.MaxEVCModeKey $VmHostresult | add-member -MemberType NoteProperty -Name "Cluster" -Value $ClusterName $VmHostresult | add-member -MemberType NoteProperty -Name "DataCenter" -Value $DatacenterName $VmHostresult | add-member -MemberType NoteProperty -Name "vCenter Server" -Value $vcenter $VmHostresult | add-member -MemberType NoteProperty -Name "vCenter version" -Value $vcenterversion $VMHostresult | add-member -MemberType NoteProperty -Name "Esxi-status" -Value $vmhost.ExtensionData.Summary.OverallStatus $VMHostresult | add-member -MemberType NoteProperty -Name "Physical-Nics" -Value $vmhost.ExtensionData.summary.hardware.NumNics $VMHostresult | add-member -MemberType NoteProperty -Name "SSH-Enabled" -Value $SSHservice $VMHostresult | add-member -MemberType NoteProperty -Name "Uptime" -Value $UPtime $VMHostresult | add-member -MemberType NoteProperty -Name "BIOS" -Value $BIOS $VMHostresult | add-member -MemberType NoteProperty -Name "Syslog-Server" -Value $syslog $VMHostresult | add-member -MemberType NoteProperty -Name "Dump-Collector" -Value $DumpCollector $VmHostresult } } # Get-VMHostinventory #To write information to csv file Get-VMHostinventory -EsxHost * | ConvertTo-Html -Title "Hostinventory" -Body "<H2> Hostinventory $logo</H2> <br> <H3>Reporting Date :$date </H3> $custom " |Out-File $htmlfile #Disconnect Disconnect-VIServer * -Confirm:$false #copy files for Archive cp $htmlfile $htmlfile2
Datastore Inventory:
#Load Powercli Snapin Add-PSSnapin VMware.VimAutomation.Core #Connect vCenter Server Connect-VIServer -server yourvcenter.local -User [email protected] -password yourpasswd $excludeDS = "*local*" $excludeDS2 = "*vsphere-iso*" $datastores = Get-Datastore | Sort Name| where {$_.Name -notlike $excludeDS} | where {$_.Name -notlike $excludeDS2} $htmlfile = "L:\HTML-Reports\Kennzahlen\Datastore\Datastores-latest.html" $htmlfile2 = "L:\HTML-Reports\Kennzahlen\Datastore\older-versions\Datastores-" + (Get-Date -Format yyyy-MM-dd) + ".html" $csvfile = "L:\HTML-Reports\Kennzahlen\Datastore\CSV\Datastores-" + (Get-Date -Format yyyy-MM-dd) + ".csv" $date = Get-Date $logo = '<img src="http://your-logo.svg" alt="" align="right">' #html custom $custom = '<style> BODY{background-color:#A4D7D2;} 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;} TD{border-width:1px; padding:0px; border-style:solid; border-color:black;} </style>' Function Percentcal { param( [parameter(Mandatory = $true)] [int]$InputNum1, [parameter(Mandatory = $true)] [int]$InputNum2) $InputNum1 / $InputNum2*100 } ForEach ($ds in $datastores) { if (($ds.Name -match “Shared”) -or ($ds.Name -match “”)) { $PercentFree = Percentcal $ds.FreeSpaceMB $ds.CapacityMB $PercentFree = “{0:N2}” -f $PercentFree $ds | Add-Member -type NoteProperty -name PercentFree -value $PercentFree } } $datastores | Select Name,@{N=”UsedSpaceGB”;E={[Math]::Round(($_.ExtensionData.Summary.Capacity – $_.ExtensionData.Summary.FreeSpace)/1GB,0)}},@{N=”TotalSpaceGB”;E={[Math]::Round(($_.ExtensionData.Summary.Capacity)/1GB,0)}} ,PercentFree | Export-Csv $csvfile -NoTypeInformation # Convert to HTML import-csv -path $csvfile | ConvertTo-Html -Title "Datastores" -Body "<H2> $logo Datastores </H2> <br> <H3>Reporting Date:$date <br><br> <br> </H3> $custom " |Out-File $htmlfile #Copy for Archive cp $htmlfile $htmlfile2 #Disconnect Disconnect-VIServer * -Confirm:$false