Hey Checkyourlogs Fans,

I’m Writing you here tonight with some great news about a new Hyper-V and Azure Stack HCI report that I’ve been working on.

I had a customer ask me to get them a list of all Virtual Machines running on Hyper-V Servers in their Domain.

The problem was that they didn’t know how many Hyper-V Servers or VM’s they had running.

This customer wasn’t using SCVMM, so that wasn’t an option.

 

Off to PowerShell.

First Off à In Researching how to write crisp reports using PowerShell I found the ultimate repository.


 

It was courtesy of Klys Przemyslaw. Please follow him on Twitter – @przemyslawklys

He has written a ton of open source modules for reporting in HTML, Word, Excel, and many other sources.

The module of his that I leveraged for this report was PSWriteHTML.

It can be found at:

https://github.com/EvotecIT


 

My Script is pretty straight forward and has 2 functions:

  1. Test-Server – Which tests connectivity to the Server Found
  2. Get-HyperVServersinAD – Which hunts for the Service Connection Point “Microsoft Hyper-V” object

Here is the Github Link to my Script.

https://github.com/dkawula/Operations/blob/master/Hyper-V/Find-HyperVServerFromDomainandVMs-Report.ps1

 

Here is a current working copy of the code

#Install the Required Modules for this Script

Install-Module PSWriteHTML
Install-WindowsFeature -Name RSAT-AD-PowerShell
Install-WindowsFeature -Name Hyper-V-PowerShell

#Test Server Function to check connectivity
Function Test-Server {
        [CmdletBinding()]

        # Parameters used in this function
        param
        ( 
            [Parameter(Position=0, Mandatory = $true, HelpMessage="Provide server names", ValueFromPipeline = $false)] 
            $ComputerName
        ) 

        $Array = @()

        ForEach($Server in $ComputerName)
        {
            $Server = $Server.Trim()

            Write-Verbose "Checking $Server"

            $SMB = $null
            $Object = $null
            $Status = $null

            $SMB = Test-Path "\\$server\c$"

            If($SMB -eq "True")
            {
                Write-Verbose "$Server is up"
                $Status = "True"
                $Object = New-Object PSObject -Property ([ordered]@{ 

                    Server                = $Server
                    "Is Online?"          = $Status
                })

                $Array += $Object
            }
            Else
            {
                Write-Verbose "$Server is down"
                $Status = "False"
                $Object = New-Object PSObject -Property ([ordered]@{ 

                    Server                = $Server
                    "Is Online?"          = $Status

                })

                $Array += $Object
            }
        }

    If($Array)
    {
        return $Array
    }
}

#Get-HyperVServersinAD
#I had an issue where the SCP's were not defined on two of my cluster nodes
#Had to manually create the object and then the script worked

function Get-HyperVServersInAD {            
[cmdletbinding()]            
param(            
)            
try {            
 Import-Module ActiveDirectory -ErrorAction Stop            
} catch {            
 Write-Warning "Failed to import Active Directory module. Exiting"            
 return            
}            

try {            
 $Hypervs = Get-ADObject -Filter 'ObjectClass -eq "serviceConnectionPoint" -and Name -eq "Microsoft Hyper-V"' -ErrorAction Stop            
} catch {            
 Write-Error "Failed to query active directory. More details : $_"            
}            
foreach($Hyperv in $Hypervs) {            
 $temp = $Hyperv.DistinguishedName.split(",")            
 $HypervDN = $temp[1..$temp.Count] -join ","            
 $Comp = Get-ADComputer -Id $HypervDN -Prop *            
 $OutputObj = New-Object PSObject -Prop (            
 @{            
  HyperVName = $Comp.Name            
  OSVersion = $($comp.operatingSystem)            
 })            
 $OutputObj            
}            
}

$HyperVServers = Get-HyperVServersInAD
$HyperVServers1 = $HypervServers.HyperVName
$HyperVServers1

ForEach ($HyperVNode in $HyperVServers1) {
Try{
Write-Host "Gathering VM INfo for $HyperVNode"
$HypervVms += Invoke-Command $HyperVNode {Get-VM}
#$output += $HypervVMs | ConvertTo-Html
}
Catch{
"Connection Error: $HyperVNode" 

$ConnectionErrors += "Connection Error: $HyperVNode" 

}
}

$HypervVms | Where VMName -notlike *Replica* | Select VMName,PSComputerName,State,UpTime,Version,Generation,IntegrationServiceState,OperationalStatus,CPUUsage,ProcessorCount,MemoryAssigned,MemoryDemand,MemoryStatus,MemoryStartup,DynamicMemoryEnabled,MemoryMinimum,MemoryMaximum,IntegrationServicesVersion,ResourceMeteringEnabled,ConfigurationLocation,SnapshotFileLocation,AutomaticStartAction,AutomaticStopAction,AutomaticStartDelay,SmartPagingFilePath,NumaAligned,NumaNodesCount,NumaSocketCount,IsClustered,SizeofSystemFiles,ParentSnapshotId,ParentSnapshotName| Out-GridHtml -Title "Standalone HVHosts" 
$HypervVms | Where VMName -like *Replica* | Select VMName,PSComputerName,State,UpTime,Version,Generation,IntegrationServiceState,OperationalStatus,CPUUsage,ProcessorCount,MemoryAssigned,MemoryDemand,MemoryStatus,MemoryStartup,DynamicMemoryEnabled,MemoryMinimum,MemoryMaximum,IntegrationServicesVersion,ResourceMeteringEnabled,ConfigurationLocation,SnapshotFileLocation,AutomaticStartAction,AutomaticStopAction,AutomaticStartDelay,SmartPagingFilePath,NumaAligned,NumaNodesCount,NumaSocketCount,IsClustered,SizeofSystemFiles,ParentSnapshotId,ParentSnapshotName| Out-GridHtml -Title "Replica VMs" 
$HypervVms | Where IsClustered -eq True | Select VMName,PSComputerName,State,UpTime,Version,Generation,IntegrationServiceState,OperationalStatus,CPUUsage,ProcessorCount,MemoryAssigned,MemoryDemand,MemoryStatus,MemoryStartup,DynamicMemoryEnabled,MemoryMinimum,MemoryMaximum,IntegrationServicesVersion,ResourceMeteringEnabled,ConfigurationLocation,SnapshotFileLocation,AutomaticStartAction,AutomaticStopAction,AutomaticStartDelay,SmartPagingFilePath,NumaAligned,NumaNodesCount,NumaSocketCount,IsClustered,SizeofSystemFiles,ParentSnapshotId,ParentSnapshotName| Out-GridHtml -Title "HCI Clusters" 
$TestConnectivity | Test-Server -ComputerName $HyperVServers1 -verbose | Out-GridHtml -Title "Connectivity Checks" 
$ConnectionErrors | Out-GridHtml -Title "Connection Errors" 

 

I haven’t added a mailto function into this script. What I wanted to show you want the output using PSWriteHTML’s (Out-GridViewHTML), which is a killer alternative to Out-Gridview.

This Function not only build up the HTML Code required; it also gives buttons on the webpage to export to CSV,Excel,or PDF.

Check it out below (The Search Box works great)

Here is code I used to generate this:

$HypervVms | Where VMName -notlike *Replica* | Select VMName,PSComputerName,State,UpTime,Version,Generation,IntegrationServiceState,OperationalStatus,CPUUsage,ProcessorCount,MemoryAssigned,MemoryDemand,MemoryStatus,MemoryStartup,DynamicMemoryEnabled,MemoryMinimum,MemoryMaximum,IntegrationServicesVersion,ResourceMeteringEnabled,ConfigurationLocation,SnapshotFileLocation,AutomaticStartAction,AutomaticStopAction,AutomaticStartDelay,SmartPagingFilePath,NumaAligned,NumaNodesCount,NumaSocketCount,IsClustered,SizeofSystemFiles,ParentSnapshotId,ParentSnapshotName| Out-GridHtml -Title "Standalone HVHosts" 
$HypervVms | Where VMName -like *Replica* | Select VMName,PSComputerName,State,UpTime,Version,Generation,IntegrationServiceState,OperationalStatus,CPUUsage,ProcessorCount,MemoryAssigned,MemoryDemand,MemoryStatus,MemoryStartup,DynamicMemoryEnabled,MemoryMinimum,MemoryMaximum,IntegrationServicesVersion,ResourceMeteringEnabled,ConfigurationLocation,SnapshotFileLocation,AutomaticStartAction,AutomaticStopAction,AutomaticStartDelay,SmartPagingFilePath,NumaAligned,NumaNodesCount,NumaSocketCount,IsClustered,SizeofSystemFiles,ParentSnapshotId,ParentSnapshotName| Out-GridHtml -Title "Replica VMs" 
$HypervVms | Where IsClustered -eq True | Select VMName,PSComputerName,State,UpTime,Version,Generation,IntegrationServiceState,OperationalStatus,CPUUsage,ProcessorCount,MemoryAssigned,MemoryDemand,MemoryStatus,MemoryStartup,DynamicMemoryEnabled,MemoryMinimum,MemoryMaximum,IntegrationServicesVersion,ResourceMeteringEnabled,ConfigurationLocation,SnapshotFileLocation,AutomaticStartAction,AutomaticStopAction,AutomaticStartDelay,SmartPagingFilePath,NumaAligned,NumaNodesCount,NumaSocketCount,IsClustered,SizeofSystemFiles,ParentSnapshotId,ParentSnapshotName| Out-GridHtml -Title "HCI Clusters" 


Here is an example of the .XLS export feature


 

I hope you enjoy the report and a new modern way of building HTML Reports.


Thanks,


Dave