VMware Cloud Community
piercj2
Enthusiast
Enthusiast
Jump to solution

ESXi Host EOL report

Hi All,

I've created the below to generate a report containing End of Life / End of Support information for approx 2000 ESXi Hosts, spread across multiple vCenters.

The report works to a point. I've just noticed that it's returning the same Serial numbers for a lot of the ESXi Hosts, these should all be unique. I've also noticed that the model numbers are not always correct either. If i run the script against individual ESXi Hosts, the data returned is correct.

The script runs without error so i don't understand why duplicate/incorrect information is being returned for some of the Servers.

Could it be that i don't have enough memory/cpu on the server that's running the script ?

Should i be using Get-View instead of Get-Esxcli to optimize the data collection ?

Should i be setting each variable to null before moving to the next ESXi Host (seems wasteful)

$cred = Get-Credential 'username@company.com'

$vCenters = @(

    "vc1.company.com"

    "vc2.company.com"

    "vc3.company.com"

    "vc4.company.com"

    )

Connect-VIServer -Server $vCenters -Credential $cred -ErrorAction SilentlyContinue

# Server model to EOL date mappings, edit to add/correct dates

$vmHostModelEolMapping = @{

    "UCS-C210" = "2020/Jun"

    "UCS-C220" = "2020/Jun"

    "UCS-C240" = "2018/Aug"

    "UCS-C420" = "2017/Jan"

    "PowerEdge R630" = "2018/May"

    "PowerEdge R710" = "2016/May"

    "PowerEdge R730xd" = "2018/May"

    "PowerEdge R900"  = "2015/Jul"

    "PowerEdge R910" = "2015/Mar"

    }

# Collect Server details

$results = @()

foreach ($vmHost in Get-VMHost) {

    $esxcli = Get-EsxCli -vmhost $vmHost.name -V2 -ErrorAction SilentlyContinue

    $vcName = [System.Net.Dns]::GetHostEntry((get-view $vmHost -ErrorAction SilentlyContinue).summary.managementserverip).HostName

    $vmHostName = $vmHost.Name

    $vmHostVendor = $esxcli.hardware.platform.get.invoke().VendorName

    $vmHostModel = $esxcli.hardware.platform.get.invoke().ProductName

    $vmHostSerial = $esxcli.hardware.platform.get.invoke().SerialNumber

    $EolDate = "Unknown"

    if ($vmHostModelEolMapping.ContainsKey($vmHostModel)){

        $EolDate = $vmHostModelEolMapping[$vmHostModel]

        }

    $prop = [pscustomobject] @{

            vCenter = $vcName

            "ESXi Host Name" = $vmHostName

            Vendor = $vmHostVendor

            Model = $vmHostModel

            Serial = $vmHostSerial

            EOL = $EolDate

    }

    $results+=$prop

}

$results | Sort-Object vCenter,"ESXi Host Name" | Export-Csv -path c:\Temp\EOLreport.csv

Tags (3)
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

When the Get-EsxCli for one or another reason fails, the script will continue with the values of the previous iteration in the loop.

Perhaps this try-catch construct could avoid that

$cred = Get-Credential 'username@company.com'

$vCenters = @(

    "vc1.company.com"

    "vc2.company.com"

    "vc3.company.com"

    "vc4.company.com"

)

Connect-VIServer -Server $vCenters -Credential $cred -ErrorAction SilentlyContinue

# Server model to EOL date mappings, edit to add/correct dates

$vmHostModelEolMapping = @{

    "UCS-C210"         = "2020/Jun"

    "UCS-C220"         = "2020/Jun"

    "UCS-C240"         = "2018/Aug"

    "UCS-C420"         = "2017/Jan"

    "PowerEdge R630"   = "2018/May"

    "PowerEdge R710"   = "2016/May"

    "PowerEdge R730xd" = "2018/May"

    "PowerEdge R900"   = "2015/Jul"

    "PowerEdge R910"   = "2015/Mar"

}

# Collect Server details

$results = @()

foreach ($vmHost in Get-VMHost) {

    $vcName = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorAction SilentlyContinue).summary.managementserverip).HostName

    $vmHostName = $vmHost.Name

    $EolDate = "Unknown"

    $vmHostVendor = ''

    $vmHostModel = ''

    $vmHostSerial = ''


    try {

        $esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop

        $vmHostVendor = $esxcli.hardware.platform.get.invoke().VendorName

        $vmHostModel = $esxcli.hardware.platform.get.invoke().ProductName

        $vmHostSerial = $esxcli.hardware.platform.get.invoke().SerialNumber

        if ($vmHostModelEolMapping.ContainsKey($vmHostModel)) {

            $EolDate = $vmHostModelEolMapping[$vmHostModel]

        }

    }

    catch {

        Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)"

    }

    $prop = [pscustomobject] @{

        vCenter          = $vcName

        "ESXi Host Name" = $vmHostName

        Vendor           = $vmHostVendor

        Model            = $vmHostModel

        Serial           = $vmHostSerial

        EOL              = $EolDate

    }

    $results += $prop

}

$results | Sort-Object vCenter, "ESXi Host Name" | Export-Csv -path c:\Temp\EOLreport.csv


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

View solution in original post

Reply
0 Kudos
20 Replies
LucD
Leadership
Leadership
Jump to solution

When the Get-EsxCli for one or another reason fails, the script will continue with the values of the previous iteration in the loop.

Perhaps this try-catch construct could avoid that

$cred = Get-Credential 'username@company.com'

$vCenters = @(

    "vc1.company.com"

    "vc2.company.com"

    "vc3.company.com"

    "vc4.company.com"

)

Connect-VIServer -Server $vCenters -Credential $cred -ErrorAction SilentlyContinue

# Server model to EOL date mappings, edit to add/correct dates

$vmHostModelEolMapping = @{

    "UCS-C210"         = "2020/Jun"

    "UCS-C220"         = "2020/Jun"

    "UCS-C240"         = "2018/Aug"

    "UCS-C420"         = "2017/Jan"

    "PowerEdge R630"   = "2018/May"

    "PowerEdge R710"   = "2016/May"

    "PowerEdge R730xd" = "2018/May"

    "PowerEdge R900"   = "2015/Jul"

    "PowerEdge R910"   = "2015/Mar"

}

# Collect Server details

$results = @()

foreach ($vmHost in Get-VMHost) {

    $vcName = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorAction SilentlyContinue).summary.managementserverip).HostName

    $vmHostName = $vmHost.Name

    $EolDate = "Unknown"

    $vmHostVendor = ''

    $vmHostModel = ''

    $vmHostSerial = ''


    try {

        $esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop

        $vmHostVendor = $esxcli.hardware.platform.get.invoke().VendorName

        $vmHostModel = $esxcli.hardware.platform.get.invoke().ProductName

        $vmHostSerial = $esxcli.hardware.platform.get.invoke().SerialNumber

        if ($vmHostModelEolMapping.ContainsKey($vmHostModel)) {

            $EolDate = $vmHostModelEolMapping[$vmHostModel]

        }

    }

    catch {

        Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)"

    }

    $prop = [pscustomobject] @{

        vCenter          = $vcName

        "ESXi Host Name" = $vmHostName

        Vendor           = $vmHostVendor

        Model            = $vmHostModel

        Serial           = $vmHostSerial

        EOL              = $EolDate

    }

    $results += $prop

}

$results | Sort-Object vCenter, "ESXi Host Name" | Export-Csv -path c:\Temp\EOLreport.csv


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

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

LucD,

I ran the script but its shows blanks for all the host with error for each host

pastedImage_0.png

  

ModelSerialEOL
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Unknown
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There was a typo in the Get-EsxCli line.
I corrected the code above, give it another try.


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

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

Ok, LucD,

This time serial/Model is showing but EOL is unknown status...

  

VendorModelEOL
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown

   

Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-EX-M4-1Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSB-B200-M4Unknown
Cisco Systems IncUCSC-C220-M4SUnknown
Cisco Systems IncUCSC-C220-M4SUnknown
Cisco Systems IncUCSC-C220-M4SUnknown
Cisco Systems IncUCSC-C220-M4SUnknown

thanks

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The names listed under Model are not present in the $vmHostModelEolMapping hash table.
So the 'Unknown' seems to be correct


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

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Thanks Luc, that worked as expected.

After your first suggestion i got a lot of blank information back but quickly spotted the typo and once corrected it worked perfectly, thanks.

To anyone who wants to use this, run it first to get back the server model details as, this information is detailed on the Host, e.g. you may be using Cisco UCS C210's but, this report identifies these as R210-2121605W .

When you have all your Server models, google the EOL date and edit the  $vmHostModelEolMapping hash table to match your servers.

piercj2
Enthusiast
Enthusiast
Jump to solution

I've re-worked this to make it a bit more user friendly :smileygrin:

The script can take a long time to run, depending on quantity of VC's and Hosts so i've also added a progress bar.

If anyone thinks this can be optimized in any way, please feel free to post comments

# login to vCenter(s) - use CTRL to select multiple vCenters

$cred = Get-Credential -Message "  ***********  Enter vCenter Credentials  ***********"

$vCenters = @(

    "vc1.company.com"

    "vc2.company.com"

    "vc3.company.com"

    "vc4.company.com"

    "vc5.company.com"

    )

$selectedVC = $vCenters | Out-GridView -Title "  ***  vCenter Listing - Select required vCenter(s)  ***" -OutputMode Multiple

Connect-VIServer -Server $selectedVC -Credential $cred -ErrorAction SilentlyContinue

# Server model to EOL date mappings, edit to add/correct dates

$vmHostModelEolMapping = @{

    # Cisco Servers

    "B230-BASE-M2" = "2020/Jun"

    "C260-BASE-2646" = "2020/Jun"

    "UCSB-B200-M4" = "2024/Feb"

    "UCSC-BASE-M2-C460" = "2020/Apr"

    # Dell Servers

    "PowerEdge R630" = "2018/May"

    "PowerEdge R640" = " "

    "PowerEdge R710" = "2016/May"

    # VxRails

    "VxRail E460" = "2023/05"

    "VxRail P570F"= " "

    }

# Status Bar Variables

$vmHosts = Get-VMHost

$count = $vmHosts.count

$i = 1

# Collect Server details

$results = @()

foreach ($vmHost in $vmHosts) {

    Write-Progress -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost" -PercentComplete (($i*100)/$count)

    $vcName = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorAction SilentlyContinue).summary.managementserverip).HostName

    $vmHostName = $vmHost.Name

    $EolDate = "Unknown"

    $vmHostVendor = ''

    $vmHostModel = ''

    $vmHostSerial = ''

    try {

        $esxcli = $null

        $esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop

        $vmHostVendor = $esxcli.hardware.platform.get.invoke().VendorName

        $vmHostModel = $esxcli.hardware.platform.get.invoke().ProductName

        $vmHostSerial = $esxcli.hardware.platform.get.invoke().SerialNumber

        if ($vmHostModelEolMapping.ContainsKey($vmHostModel)) {

            $EolDate = $vmHostModelEolMapping[$vmHostModel]

            }

        }

    catch {

        Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)"

        }

    $prop = [pscustomobject] @{

        vCenter          = $vcName

        "ESXi Host Name" = $vmHostName

        Vendor           = $vmHostVendor

        Model            = $vmHostModel

        Serial           = $vmHostSerial

        EOL              = $EolDate

        }

   

    $i++

    $results += $prop

}

<#

    requirement: ImportExcel module

    Verify that ImportExcel is installed with 'Get-Module -ListAvailable ImportExcel'

    If not installed, install with 'Find-Module ImportExcel | Install-Module'

    Get available commands with 'Get-Command -Module ImportExcel'

#>

If (!(Get-module -ListAvailable "ImportExcel")) {

    Find-Module -Name ImportExcel | Install-Module

    }

$ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks

$hash = @{

    Path = "C:\Temp\EOLreport.xlsx"

    Show = $true;

    AutoSize = $true;

    AutoFilter = $true;

    ConditionalText = $ContainsBlanks

    ShowPercent = $true;

    #PivotTableName = "ESXi Version Detail";

    #IncludePivotTable = $true;

    #PivotRows = 'Version';

    #PivotData = @{'Version' = 'Count'};

    #IncludePivotChart = $true;

    #ChartType = "PieExploded";

    HideSheet = "Sheet1";

    }

Remove-Item $hash.Path -ErrorAction Ignore

$results | Sort-Object vCenter,"ESXi Host Name" | Export-Excel @hash

LucD
Leadership
Leadership
Jump to solution

Great, thanks for sharing that.

While playing with the script, I think there might be some performance improvements possible.

By using Foreach-Object and a Pipelinevariable, everything can be set up in a pipeline construct.
No need to have a $results variable.

The following also only uses 1 $esxcli method call, instead of three.

The If-Then for the EOL can also be eliminated.

If the Model is not in the hash table, it will return $null. Since the -replace operator can use a RegEx, we test for an empty string () with "^$") and replace it with 'Unknown'.


These are not corrections, just some suggestions :smileygrin:


# login to vCenter(s) - use CTRL to select multiple vCenters

$cred = Get-Credential -Message "  ***********  Enter vCenter Credentials  ***********"

$vCenters = @(

    "vc1.company.com"

    "vc2.company.com"

    "vc3.company.com"

    "vc4.company.com"

    "vc5.company.com"

)

$selectedVC = $vCenters | Out-GridView -Title "  ***  vCenter Listing - Select required vCenter(s)  ***" -OutputMode Multiple

Connect-VIServer -Server $selectedVC -Credential $cred -ErrorAction SilentlyContinue

# Server model to EOL date mappings, edit to add/correct dates

$vmHostModelEolMapping = @{

    # Cisco Servers

    "B230-BASE-M2"      = "2020/Jun"

    "C260-BASE-2646"    = "2020/Jun"

    "UCSB-B200-M4"      = "2024/Feb"

    "UCSC-BASE-M2-C460" = "2020/Apr"

    # Dell Servers

    "PowerEdge R630"    = "2018/May"

    "PowerEdge R640"    = " "

    "PowerEdge R710"    = "2016/May"

    # VxRails

    "VxRail E460"       = "2023/05"

    "VxRail P570F"      = " "

}

If (!(Get-Module -ListAvailable "ImportExcel")) {

    Find-Module -Name ImportExcel | Install-Module

}


$ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks

$hash = @{

    Path            = "C:\Temp\EOLreport.xlsx"

    Show            = $true;

    AutoSize        = $true;

    AutoFilter      = $true;

    ConditionalText = $ContainsBlanks

    ShowPercent     = $true;

    #PivotTableName = "ESXi Version Detail";

    #IncludePivotTable = $true;

    #PivotRows = 'Version';

    #PivotData = @{'Version' = 'Count'};

    #IncludePivotChart = $true;

    #ChartType = "PieExploded";

    HideSheet       = "Sheet1";

}

Remove-Item $hash.Path -ErrorAction Ignore


Get-VMHost -PipelineVariable vmhost |

ForEach-Object -Process {

    try {

        $esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop

        $platform = $esxcli.hardware.platform.get.invoke()

    }

    catch {

        Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)"

    }

    [pscustomobject] @{

        vCenter          = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorAction SilentlyContinue).summary.managementserverip).HostName

        "ESXi Host Name" = $vmHost.Name

        Vendor           = $platform.VendorName

        Model            = $platform.ProductName

        Serial           = $platform.SerialNumber

        EOL              = $vmHostModelEolMapping[$platform.ProductName] -replace "^$", 'Unknown'

    }

} | Sort-Object vCenter, "ESXi Host Name" | Export-Excel @hash


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

vmk2014
Expert
Expert
Jump to solution

LucD,

I tried to excute but it shows an error and it never proceed further in console.

Name                           Port  User

----                           ----  ----

vc1.sg.con... 443   SGC\vk1

Install-Module : Administrator rights are required to install modules in 'C:\Program Files\WindowsPowerShell\Modules'.

Log on to the computer with an account that has Administrator rights, and then try again, or install

'D:\Users\vk1\Documents\WindowsPowerShell\Modules' by adding "-Scope CurrentUser" to your command. You can

also try running the Windows PowerShell session with elevated rights (Run as Administrator).

At D:\vk1\ESXHost-EOL.ps1:63 char:37

+     Find-Module -Name ImportExcel | Install-Module

+                                     ~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Install-Module], ArgumentException

    + FullyQualifiedErrorId : InstallModuleNeedsCurrentUserScopeParameterForNonAdminUser,Install-Module

New-ConditionalText : The term 'New-ConditionalText' is not recognized as the name of a cmdlet, function, script file,

or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and

try again.

At D:\vk1\ESXHost-EOL.ps1:68 char:19

+ $ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks

+                   ~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ObjectNotFound: (New-ConditionalText:String) [], CommandNotFoundException

    + FullyQualifiedErrorId : CommandNotFoundException

Get-EsxCli failed for ESX2.host.com

thanks

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

To install a module for All Users, you have to start your PowerShell sessions 'As Administrator'.
The alternative is to install the module for the CurrentUser (the -Scope CurrentUser mentioned in the error).


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

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

Ok, i did run as Administrator but it ended with blank report. EOLreport.csv = 0 KB

pastedImage_0.png

thanks

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

My bad, I didn't place the object in the pipeline.
I corrected the code above


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

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

Ok, i did run the script,

Get-VMHost : 1/30/2020 7:43:34 PM       Get-VMHost              Sequence contains more than one matching eleme

t D:\vmk\ESXHost-EOL.ps1:110 char:1

Get-VMHost -PipelineVariable vmhost |

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   + CategoryInfo          : NotSpecified: (:) [Get-VMHost], VimException

   + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVMH

xception calling "GetHostEntry" with "1" argument(s): "No such host is known"

t D:\vmk\ESXHost-EOL.ps1:130 char:5

     [pscustomobject] @{

     ~~~~~~~~~~~~~~~~~~~

   + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

   + FullyQualifiedErrorId : SocketException

xception calling "GetHostEntry" with "1" argument(s): "No such host is known"

t D:\vmk\ESXHost-EOL.ps1:130 char:5

     [pscustomobject] @{

     ~~~~~~~~~~~~~~~~~~~

   + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

   + FullyQualifiedErrorId : SocketException

xception calling "GetHostEntry" with "1" argument(s): "No such host is known"

t D:\vmk\ESXHost-EOL.ps1:130 char:5

Get-EsxCli failed for Host2.com

thanks

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not sure what is happening there, must be something in your script.

Also confused by the line numbers in the errors.

Line 110?

What else is in that .ps1 file?


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

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Thanks Luc,

Those optimizations are great, really helpful.

One question with them though. Previously i was using a count of the Hosts to generate a status bar

# Status Bar Variables

$vmHosts = Get-VMHost

$count = $vmHosts.count

$i = 1

# Collect Server details

$results = @()

foreach ($vmHost in $vmHosts) {

    Write-Progress -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost" -PercentComplete (($i*100)/$count)

Using a pipeline variable, how do i now count the total Hosts ?

Should i do something like

$vmHosts = Get-VMHost

$count = $vmHosts.count

$i = 1

Get-VMHost -PipelineVariable $vmhosts |

ForEach-Object -Process {

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I would avoid doing the Get-VMHost twice.

As a skeleton, something like this

$vmHostAll = Get-VMHost

$i = 1

$vmHostAll | ForEach-Object -PipelineVariable vmhost -Process {

    Write-Progress -PercentComplete ($i/$vmhostAll.Count*100) -Activity 'In loop'

    $i++

}


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

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Getting an error (and looks like i don't fully understand your optimizations)

$vmHostAll = Get-VMHost


= 1


| ForEach-Object -PipelineVariable vmhost -Process {

Write-Progress -PercentComplete ($i/$vmHostAll.count*100) -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost"


$i++


try {

$esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop


$platform = $esxcli.hardware.platform.get.invoke()

catch {

Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)"


the above returns

Get-EsxCli failed for

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At line:135 char:69

+ ... r          = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorA ...

+                                                           ~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not sure where that Get-View is coming from.

In any case, this is the complete script with the Write-Progress.

# login to vCenter(s) - use CTRL to select multiple vCenters

$cred = Get-Credential -Message "  ***********  Enter vCenter Credentials  ***********"

$vCenters = @(

    "vc1.company.com"

    "vc2.company.com"

    "vc3.company.com"

    "vc4.company.com"

    "vc5.company.com"

)

$selectedVC = $vCenters | Out-GridView -Title "  ***  vCenter Listing - Select required vCenter(s)  ***" -OutputMode Multiple

Connect-VIServer -Server $selectedVC -Credential $cred -ErrorAction SilentlyContinue

# Server model to EOL date mappings, edit to add/correct dates

$vmHostModelEolMapping = @{

    # Cisco Servers

    "B230-BASE-M2"      = "2020/Jun"

    "C260-BASE-2646"    = "2020/Jun"

    "UCSB-B200-M4"      = "2024/Feb"

    "UCSC-BASE-M2-C460" = "2020/Apr"

    # Dell Servers

    "PowerEdge R630"    = "2018/May"

    "PowerEdge R640"    = " "

    "PowerEdge R710"    = "2016/May"

    # VxRails

    "VxRail E460"       = "2023/05"

    "VxRail P570F"      = " "

}

If (!(Get-Module -ListAvailable "ImportExcel")) {

    Find-Module -Name ImportExcel | Install-Module

}


ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks

$hash = @{

    Path            = "C:\Temp\EOLreport.xlsx"

    Show            = $true;

    AutoSize        = $true;

    AutoFilter      = $true;

    ConditionalText = $ContainsBlanks

    ShowPercent     = $true;

    #PivotTableName = "ESXi Version Detail";

    #IncludePivotTable = $true;

    #PivotRows = 'Version';

    #PivotData = @{'Version' = 'Count'};

    #IncludePivotChart = $true;

    #ChartType = "PieExploded";

    HideSheet       = "Sheet1";

}

Remove-Item $hash.Path -ErrorAction Ignore


$vmHostAll = Get-VMHost


$i = 1

$vmHostAll | ForEach-Object -PipelineVariable vmhost -Process {

    Write-Progress -PercentComplete ($i / $vmHostAll.count * 100) -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost"

    $i++


    try {

        $esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop

        $platform = $esxcli.hardware.platform.get.invoke()

    }

    catch {

        Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)"

    }

    [pscustomobject] @{

        vCenter          = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorAction SilentlyContinue).summary.managementserverip).HostName

        "ESXi Host Name" = $vmHost.Name

        Vendor           = $platform.VendorName

        Model            = $platform.ProductName

        Serial           = $platform.SerialNumber

        EOL              = $vmHostModelEolMapping[$platform.ProductName] -replace "^$", 'Unknown'

    }

} | Sort-Object vCenter, "ESXi Host Name" | Export-Excel @hash


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

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Thanks Luc,

Running your last iteration of the code, i was still getting errors. Through a process of trial and error i spotted that the when using $vmhost variable,the following calls were failing

  • Get-EsxCli was returning nothing
  • Get-View was complaining about a null or empty argument

Get-EsxCli failed for

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At line:138 char:69

+ ... r          = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorA ...

+                                                           ~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

I changed the code to the below (replacing the $vmhost with $_ in the "try" statement and in the [pscustomobject])

$vmHostAll = Get-VMHost

$i = 1

$vmHostAll | ForEach-Object -PipelineVariable vmhost -Process {

    Write-Progress -PercentComplete ($i / $vmHostAll.count * 100) -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost"

    read-host "Press ENTER to Continue..."

    $i++

    try {

        $esxcli = Get-EsxCli -vmhost $_ -V2 -ErrorAction Stop

        $platform = $esxcli.hardware.platform.get.invoke()

        }

    catch {

        Write-Host -ForegroundColor red  "Get-EsxCli failed for $($_.Name)"

        }

    [pscustomobject] @{

        vCenter          = [System.Net.Dns]::GetHostEntry((Get-View $_ -ErrorAction SilentlyContinue).summary.managementserverip).HostName

        "ESXi Host Name" = $_.Name

        Vendor           = $platform.VendorName

        Model            = $platform.ProductName

        Serial           = $platform.SerialNumber

        EOL              = $vmHostModelEolMapping[$platform.ProductName] -replace "^$", 'Unknown'

        }

} | Sort-Object vCenter, "ESXi Host Name" | Export-Excel @hash

The output was now correct except for the Progress Bar, the Status was now reading

"Getting info on @{vCenter=vc1.company.com; ESXi Host Name=Host1.company.com; Vendor=Dell; Model=Poweredge R910; Serial =123abc; EOL=2015/Mar/29}"

I switched the Status from "Getting info on $vmHost" to "Getting info on $_", ran the code again and it worked 100%

I haven't used pscustomobjects before so don't understand what's happening here but, wanted to post it in case it helps others.

To keep this comment clean, i'm attaching the working code with your optimizations

Thanks again !

Reply
0 Kudos