Automation

 View Only

Code execution takes 45 seconds- can we reduce this?

  • 1.  Code execution takes 45 seconds- can we reduce this?

    Posted Aug 15, 2024 11:51 PM

    I have the following code which takes a DVSwitch and deduces which port is the active uplink port. As-is, the code reports the correct information as shown here:

    Script Starting.
    Already connected to vCenter server 'MyvCenter'. Continuing...
    Connected to vCenter: MyvCenter.
    
    Host Name: MyHost:
    Switch: vSwitch0:
    +-------------------------------------------------------------------------------------+
    vCenter Name:
    PortGroup Name:  VM Network
    PortGroup Key:   key-vim.host.PortGroup-VM Network
    Is Uplink:       NA
    vLAN:            0
    Active Uplinks:
    Standby Uplinks:
    +-------------------------------------------------------------------------------------+
    
    +-------------------------------------------------------------------------------------+
    vCenter Name:
    PortGroup Name:  Management Network
    PortGroup Key:   key-vim.host.PortGroup-Management Network
    Is Uplink:       NA
    vLAN:            1001
    Active Uplinks:  vmnic0 vmnic2
    Standby Uplinks:
    +-------------------------------------------------------------------------------------+
    
    Function GetSTDSwitchDetails took 0.2422151 seconds to execute.
    WARNING: Parameter -Distributed is obsolete. To retrieve distributed switches, use Get-VDSwitch cmdl
    Switch: dvSwitch - Resource:
    WARNING: Parameter -Distributed is obsolete. To retrieve distributed portgroups, use Get-VDPortgroup
    [ForEach ($ActiveUplinkPort in $ActiveUplinkPorts)] took 453.8898787 seconds to execute.
    [ForEach ($ActiveUplinkPort in $ActiveUplinkPorts)] took 453.8898787 seconds to execute.
    +-------------------------------------------------------------------------------------+
    vCenter Name:    MyvCenter
    PortGroup Name:  MyPortGroup_01
    PortGroup Key:   dvportgroup-1234567
    Is Uplink:       False
    vLAN:            1234
    Active Uplinks:  dvUplink1 (vmnic4) dvUplink2 (vmnic5)
    Standby Uplinks: -
    +-------------------------------------------------------------------------------------+
    
    [ForEach $ESXiPG in $PG] took 436.7717849 seconds to execute.
    [ForEach ($ActiveUplinkPort in $ActiveUplinkPorts)] took 453.8898787 seconds to execute.
    [ForEach ($ActiveUplinkPort in $ActiveUplinkPorts)] took 453.8898787 seconds to execute.
    +-------------------------------------------------------------------------------------+
    vCenter Name:    MyvCenter
    PortGroup Name:  MyPortGroup_02
    PortGroup Key:   dvportgroup-1234568
    Is Uplink:       False
    vLAN:            1235
    Active Uplinks:  dvUplink1 (vmnic4) dvUplink2 (vmnic5)
    Standby Uplinks: -
    +-------------------------------------------------------------------------------------+
    
    [ForEach $ESXiPG in $PG] took 0.9595045 seconds to execute.
    [ForEach ($ActiveUplinkPort in $ActiveUplinkPorts)] took 453.8898787 seconds to execute.
    [ForEach ($ActiveUplinkPort in $ActiveUplinkPorts)] took 453.8898787 seconds to execute.
    ....
    ....

    Without copying the whole script here, I'll break it down into key components so you can see what I've done:

    Function GetDVSwitchDetails
        {
        param(
            [Object]$ESXiHost,
            [Object]$oSwitchObject
            )
        $section1Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
        # Retrieve vCenter Name.
        $vCenterName = $oSwitchObject.ExtensionData.Client.ServiceUrl.Split('/')[2]
        # Get all port groups on this host on this switch.
        $PG = get-virtualportgroup -VMHost $esxihost -VirtualSwitch $oSwitchObjects -Distributed
        # Get all switch ports for this switch.
        $AllSwitchPorts = Get-VDPort -VDSwitch $oSwitchObject.name
        $tmpAllPortGroups = @()
        ForEach ($ESXiPG in $PG)
            {
            $section11Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
            $Item = New-Object PSObject
            # VLANID can be a single value or an object with 2 properties: Start & End.
            # Need to combine both values, when they show up, into one value.
            $vLANID = $ESXiPG.extensionData.Config.DefaultPortConfig.VLAN.VLANID
            If ([String]::IsNullOrEmpty($vLANID.Start))             {            $vLANID_All = $vLANID            }
            Else
                {            $vLANID_All = $(@($vLANID.Start, $vLANID.End) -join "-" )            }
            
            # Get all Active uplinks for this port group.
            $ActiveUplinkPorts = $ESXiPG.extensionData.Config.DefaultPortConfig.UplinkTeamingPolicy.UplinkPortOrder.ActiveUplinkPort
            $vLANActiveUplinkPortNames = @()
            # Get vmnic name from dvUplink##.
            ForEach ($ActiveUplinkPort in $ActiveUplinkPorts)
                {
                # Search all switch ports on the selected switch where the host is the same as the current host and the uplink name is the same as the current uplink name.
                $section111Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
                $ActiveUplinkPortVMNIC = ($AllSwitchPorts | Where-object {$_.ProxyHost.Name -eq $esxihost -and $_.name -eq $ActiveUplinkPort}).ConnectedEntity
                $vLANActiveUplinkPortNames += "$ActiveUplinkPort ($($ActiveUplinkPortVMNIC.Name))"
                $section1Stopwatch.Stop()
                Write-Host "[ForEach (`$ActiveUplinkPort in `$ActiveUplinkPorts)] took $($section1Stopwatch.Elapsed.TotalSeconds) seconds to execute." -BackgroundColor DarkMagenta -ForegroundColor Magenta
                }
    
    # =========================================================================
    
    $AllPortGroups = @()
    # Cycle thru all hosts in the vCenter.
    foreach($esx in Get-VMHost)
        {
        Write-Host "Host Name: $($esx.name):"
        # Get all Standard switches connected to this host.
        $oSwitchObjects = Get-VirtualSwitch -VMHost $esx -Standard
        # Cycle thru each Standard switch and return the connected port groups.
        ForEach($oSwitchObject in $oSwitchObjects)
            {
            Write-Host "Switch: $($oSwitchObject.Name):"
            $AllPortGroups += GetSTDSwitchDetails -ESXiHost $esx -oSwitchObject $oSwitchObject
            }
        # Get all Distributed switches connected to this host.
        $oSwitchObjects = Get-VirtualSwitch -VMHost $esx -Distributed
        # Cycle thru each Distributed switch and return the connected port groups.
        ForEach($oSwitchObject in $oSwitchObjects)
            {
            Write-Host "Switch: $($oSwitchObject.Name):"
            $AllPortGroups += GetDVSwitchDetails -ESXiHost $esx -oSwitchObject $oSwitchObject
            }
        }
    

    The line of code which takes around 50 seconds to execute (actually on the vCenter used above, it took around 453s) each time is this one:

    $ActiveUplinkPortVMNIC = ($AllSwitchPorts | Where-object {$_.ProxyHost.Name -eq $esxihost -and $_.name -eq $ActiveUplinkPort}).ConnectedEntity

    The variable "$AllSwitchPorts" contains 782 records looking like the following (rows have been culled and values have been changed):

    Key Name ConnectedEntity Portgroup IsLinkUp MacAddress Vlan Switch
    2 My_mgmt_2000 dvSwitch-M...
    5 Network adapter 1 My_mgmt_2000 TRUE 00:50:56:a0:bf:33 dvSwitch-M...
    9 Network adapter 1 My_mgmt_2000 FALSE dvSwitch-M...
    12 My_mgmt_2000 FALSE dvSwitch-M...
    17 Network adapter 2 My_mgmt_2000 FALSE dvSwitch-M...
    130 vmk1 My_vmotion_... TRUE 00:50:56:68:05:aa dvSwitch-M...
    133 My_vmotion_... dvSwitch-M...
    672 vmk3 SiteE_NFS_MGT_2020 TRUE 00:50:56:61:89:a6 dvSwitch-M...
    673 SiteE_NFS_MGT_2020 dvSwitch-M...
    194 Network adapter 1 My_MyAppdmz_3020 FALSE dvSwitch-M...
    196 Network adapter 2 My_MyAppdmz_3020 FALSE dvSwitch-M...
    198 Network adapter 1 My_MyAppdmz_3020 TRUE 00:50:56:a0:51:80 dvSwitch-M...
    200 My_MyAppdmz_3020 dvSwitch-M...
    322 My_MyAppsto_3002 dvSwitch-M...
    466 My_MyApplbdmz_2100 dvSwitch-M...
    473 Network adapter 1 My_MyApplbdmz_2100 TRUE 00:50:56:a0:3a:12 dvSwitch-M...
    474 My_MyApplbtrunk dvSwitch-M...
    600 Network adapter 2 My_MyApplbtrunk TRUE 00:50:56:a0:7d:f5 dvSwitch-M...
    606 My_shdss_2003 dvSwitch-M...
    624 Network adapter 1 My_shdss_2003 FALSE dvSwitch-M...
    625 Network adapter 1 My_shdss_2003 TRUE 00:50:56:a0:eb:d3 dvSwitch-M...
    800 dvUplink1 vmnic1 dvSwitch-MGT-DVUp... TRUE 00:00:00:00:00:00 dvSwitch-M...
    801 dvUplink2 vmnic7 dvSwitch-MGT-DVUp... TRUE 00:00:00:00:00:00 dvSwitch-M...
    808 dvUplink1 vmnic3 dvSwitch-MGT-DVUp... TRUE 00:00:00:00:00:00 dvSwitch-M...
    632 Infra_SQL_HA_v2026 dvSwitch-M...
    806 dvUplink1 vmnic6 dvSwitch-MGT-DVUp... TRUE 00:00:00:00:00:00 dvSwitch-M...
    807 dvUplink2 vmnic1 dvSwitch-MGT-DVUp... TRUE 00:00:00:00:00:00 dvSwitch-M...
    648 My_proxynet_v2010 dvSwitch-M...
    655 Network adapter 1 My_proxynet_v2010 FALSE dvSwitch-M...
    656 vmk2 My_backup_v2028 TRUE 00:50:56:65:ce:cc dvSwitch-M...
    659 My_backup_v2028 dvSwitch-M...
    664 Network adapter 3 My_SQLMyApp_3045 FALSE dvSwitch-M...
    665 Network adapter 2 My_SQLMyApp_3045 TRUE 00:50:56:a0:83:a9 dvSwitch-M...
    667 My_SQLMyApp_3045 dvSwitch-M...

    For this particular host, the result should be:

     $vLANActiveUplinkPortNames
    dvUplink2 (vmnic7)
    

    Please let me know what I should do.

    Thanks.

    PS: Special shout-out to LucD who helped me develop the code for this.