Home > Back-end >  Add-member giving output with multiple header
Add-member giving output with multiple header

Time:12-03

I am having a code which is giving me output like below

ESXi                Datastore                           ReadIOPS WriteIOPS ReadLatency[ms] WriteLatency[ms] ReadRate[KBps] WriteRate[KBps]
----                ---------                           -------- --------- --------------- ---------------- -------------- ---------------
999_TEST8AP          EV_8190                                  0        1         0               3                0              13             



ESXi                Datastore                           ReadIOPS WriteIOPS ReadLatency[ms] WriteLatency[ms] ReadRate[KBps] WriteRate[KBps]
----                ---------                           -------- --------- --------------- ---------------- -------------- ---------------
999_TANS2AP         DEV_8190                                  0        2         0               1                0              14             

I need to write this output in html. please let me know how to display only one header instead of multiple header for each server.

Also please help me with writing this to html. going forward there will be multiple datastore and VM's on which I need to execute this code

This is the code


[CmdletBinding()]
param(
   
    [String]$vcenter=""
)
Begin {
    #Ignore invalid certificate
    Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false -Verbose

    try {
        #Connect to VCSA
        Connect-VIServer -Server $vcenter  
    }
    catch {
        Write-Host "Incorrect vCenter creds!"
        $PSCmdlet.ThrowTerminatingError($PSItem)
    }

    #Collect list of datastore names
    if (-not (test-path -path C:\datastore_list.txt)) {
        Disconnect-VIServer $vcenter -Confirm:$false
        Write-Error 'The file datastore_list.txt does not exist!' -ErrorAction Stop
    }
    else {
        $list1 = Get-Content C:\datastore_list.txt
    }
    
    #Collect list of ESXi servers
    if (-not (test-path -path C:\esxi_list.txt)) {
        Disconnect-VIServer $vcenter -Confirm:$false
        Write-Error 'The file esxi_list.txt does not exist!' -ErrorAction Stop
    }
    else {
        $list2 = Get-Content C:\esxi_list.txt
    }
}

Process {
    #Function to collect datastore performance stats
    Function datastore_perf ($host_name) {

        $stat_array =@()

        For ($i = 0; $i -lt $list1.count; $i  ){ 
            $datastore_name = $list1
            
            if($datastore_name) {
                $instance_id = (Get-Datastore $datastore_name).ExtensionData.Info.Vmfs.Uuid
            
                $t1 = Get-Stat -Entity $host_name -Stat datastore.numberReadAveraged.average -MaxSamples 1 -Realtime -Instance $instance_id 
                $t2 = Get-Stat -Entity $host_name -Stat datastore.numberWriteAveraged.average -MaxSamples 1 -Realtime -Instance $instance_id 
                $t3 = Get-Stat -Entity $host_name -Stat datastore.totalReadLatency.average -MaxSamples 1 -Realtime -Instance $instance_id 
                $t4 = Get-Stat -Entity $host_name -Stat datastore.totalWriteLatency.average -MaxSamples 1 -Realtime -Instance $instance_id 
                
                $t6 = Get-Stat -Entity $host_name -Stat datastore.read.average -MaxSamples 1 -Realtime -Instance $instance_id
                $t7 = Get-Stat -Entity $host_name -Stat datastore.write.average -MaxSamples 1 -Realtime -Instance $instance_id

                $stat_object = New-Object System.Object
            
                $read_iops = $t1[0].Value
                $write_iops = $t2[0].Value
                $read_latency = $t3[0].Value
                $write_latency = $t4[0].Value
                
                $read_avg = $t6[0].Value
                $write_avg = $t7[0].Value


                $stat_object | Add-Member -Type NoteProperty -Name ESXi -Value "$host_name"
                $stat_object | Add-Member -Type NoteProperty -Name Datastore -Value "$datastore_name"
                $stat_object | Add-Member -Type NoteProperty -Name ReadIOPS -Value "$read_iops"
                $stat_object | Add-Member -Type NoteProperty -Name WriteIOPS -Value "$write_iops"
                $stat_object | Add-Member -Type NoteProperty -Name ReadLatency[ms] -Value "$read_latency"
                $stat_object | Add-Member -Type NoteProperty -Name WriteLatency[ms] -Value "$write_latency"
                
                $stat_object | Add-Member -Type NoteProperty -Name ReadRate[KBps] -Value "$read_avg"
                $stat_object | Add-Member -Type NoteProperty -Name WriteRate[KBps] -Value "$write_avg"


                $stat_array  = $stat_object
            }
        }
        cls

                $Header = @"
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
"@
        $stat_array | ConvertTo-Html -head $Header | Out-File -FilePath C:\stat_report.html -Append
    }
    }
}

End {
    $result = $list2 | ForEach-Object { datastore_perf -host_name $PSItem }
}

html sample

enter image description here

CodePudding user response:

A few things I would change in your code:

  • $datastore_name = $list1 --> $datastore_name = $list1[$i]
  • do not use = to add to an array because this is time and memory costly (on each iteration the entire array needs to be built that way). Instead, have your function simply output a PsCustomObject and gather all in variable $result
  • join the string array from ConvertTo-Html with newlines and do not use -Append to write the output HTML file
  • Prefer Set-Content over Out-File, because in PowerShell up to and including version 5.1, the encoding for Out-File is Unicode (UTF16-LE) which is probably not what you want.

Try

[CmdletBinding()]
param(
    [String]$vcenter=""
)
Begin {
    #Ignore invalid certificate
    Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false -Verbose

    try {
        #Connect to VCSA
        Connect-VIServer -Server $vcenter  
    }
    catch {
        Write-Host "Incorrect vCenter creds!"
        $PSCmdlet.ThrowTerminatingError($PSItem)
    }

    #Collect list of datastore names
    if (-not (test-path -Path 'C:\datastore_list.txt')) {
        Disconnect-VIServer $vcenter -Confirm:$false
        Write-Error 'The file datastore_list.txt does not exist!'
    }
    else {
        $list1 = Get-Content -Path 'C:\datastore_list.txt'
    }

    #Collect list of ESXi servers
    if (-not (test-path -path C:\esxi_list.txt)) {
        Disconnect-VIServer $vcenter -Confirm:$false
        Write-Error 'The file esxi_list.txt does not exist!'
    }
    else {
        $list2 = Get-Content 'C:\esxi_list.txt'
    }
}

Process {
    #Function to collect datastore performance stats
    function datastore_perf ($host_name) {
        for ($i = 0; $i -lt $list1.count; $i  ){ 
            $datastore_name = $list1[$i]
        
            if($datastore_name) {
                $instance_id = (Get-Datastore $datastore_name).ExtensionData.Info.Vmfs.Uuid
        
                $t1 = Get-Stat -Entity $host_name -Stat datastore.numberReadAveraged.average -MaxSamples 1 -Realtime -Instance $instance_id 
                $t2 = Get-Stat -Entity $host_name -Stat datastore.numberWriteAveraged.average -MaxSamples 1 -Realtime -Instance $instance_id 
                $t3 = Get-Stat -Entity $host_name -Stat datastore.totalReadLatency.average -MaxSamples 1 -Realtime -Instance $instance_id 
                $t4 = Get-Stat -Entity $host_name -Stat datastore.totalWriteLatency.average -MaxSamples 1 -Realtime -Instance $instance_id 
                $t6 = Get-Stat -Entity $host_name -Stat datastore.read.average -MaxSamples 1 -Realtime -Instance $instance_id
                $t7 = Get-Stat -Entity $host_name -Stat datastore.write.average -MaxSamples 1 -Realtime -Instance $instance_id
                # simply output an object with the properties you need
                # this output will be collected below in variable $result
                [PsCustomObject]@{
                    'ESXi'             = $host_name
                    'Datastore'        = $datastore_name
                    'ReadIOPS'         = $t1[0].Value
                    'WriteIOPS'        = $t2[0].Value
                    'ReadLatency[ms]'  = $t3[0].Value
                    'WriteLatency[ms]' = $t4[0].Value
                    'ReadRate[KBps]'   = $t6[0].Value
                    'WriteRate[KBps]'  = $t7[0].Value
                }
            }
        }
    }

    $result = $list2 | ForEach-Object { datastore_perf -host_name $_ }

    $Header = @"
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
"@

    # write the HTML file
    ($result | ConvertTo-Html -Head $Header) -join [environment]::NewLine | Set-Content -Path 'C:\stat_report.html'
}
  • Related