venerdì 8 agosto 2025

[NSX - KB406460 ] NSX_OPSAGENT on ESXi node

Issue


Today has been release the KB 406460 related "The memory usage of agent NSX_OPSAGENT on ESXi node <UUID> has reached <kb> kilobytes which is at or above the high threshold value of 80%"


Solution


As a temporary workaround to the issue as mentioned in option 1, which consist in to restart OpsAgent on the affected hosts; I wrote a short prowershell script to restart the agent on all hosts connected to vCenter Cluster.
Let's see it below:

##########
# 
# Run remote commands (Linux like) on esxi hosts to restart /etc/init.d/nsx-opsagent
#
# How it works:
# 	Connect to vCenter
# 	Get the list of ESXi hosts from the cluster
# 	Enable SSH on host
# 	Restart "/etc/init.d/nsx-opsagent" service on the host
# 	Disable SSH on host
#
# Requirement: Install-Module -Name Posh-SSH
#
# LM 22.05.2025
##
Import-Module -Name Posh-SSH

#Replace the parameter below with your values
$esxiUser = "root"
$esxiPassword = "<ESXi - PASSWORD>"
$vc = "<vCenter IP or FQDN>"
$vcUser = "administrator@vsphere.local"
$vcPassword = "<vCenter Password>"
$clusterName = "<Cluster Name>"

Connect-VIServer -Server $vc -User $vcUser -Password $vcPassword

$count=0
foreach ($esxiIP in (Get-Cluster -Name $clusterName | Get-VMHost)) {
  $count = $count + 1      
  Write-Host " ----------------------- $($esxiIP) ----------------------------------"
  # Enable SSH 
  Write-Host " Enabling SSH! " -ForegroundColor Green
  Get-VMHost -Name $esxiIP| Get-VMHostService | ?{"TSM-SSH" -eq $_.Key} | Start-VMHostService

  #SSH connection and service restart 
    $session = New-SSHSession -ComputerName $esxiIP -Credential (New-Object System.Management.Automation.PSCredential($esxiUser, (ConvertTo-SecureString $esxiPassword -AsPlainText -Force)))  -Force
    if ($session.Connected) {
        $command = "/etc/init.d/nsx-opsagent restart"
        $result = Invoke-SSHCommand -SessionId $session.SessionId -Command $command 
    
        if ($result.ExitStatus -eq 0) {
            Write-Host "Service restarted! on Host ->"$esxiIP -ForegroundColor Green
        } else {
            Write-Host "Error on host $($esxiIP): $($result.Error)" -ForegroundColor Red
        }
    
        Remove-SSHSession -SessionId $session.SessionId | Out-Null
    } else {
        Write-Host "SSH Connection failed! on Host ->"$esxiIP -ForegroundColor Red
    }

  sleep 1
  # Disable SSH
  Get-VMHost -Name $esxiIP| Get-VMHostService | ?{"TSM-SSH" -eq $_.Key} | Stop-VMHostService -Confirm:$false

  Write-Host " ----------------------------------------------------------------------------"
  Write-Host
}

Disconnect-VIServer -Server $vc -Confirm:$false

    



That's it.

lunedì 17 febbraio 2025

[NSX - Search for Objects] Quick TIP

Issue


Why if I do a search in the NSX "search bar" with the admin user, I get results and if I do the same search with another user (who identifies himself via vIDM, which has the same roles and permissions as the admin user), I get more information?? Both are "Enterprise Admin".
See pictures below, search with admin user ...
... search with another "Enterprise Admin" user.


Solution


When NSX is first installed, it does not set the "User Interface Mode Toggle" by default in System > Settings > General Settings > User Interface ...
When searching this leads to an incomplete results.
Changing to Policy Mode ...
... repeating the search with the Admin user .... now we have the complete result ...
Further information regarding the "Search for Objects" can be found at the following link.

That's it.

mercoledì 15 gennaio 2025

[NSX] Export Segment list into Excel

Issue


Starting from a post I wrote some time ago; about creating Session Cookies on Powershell for authentication in NSX, [NSX] - API Authentication Using a Session Cookie on PowerShell.
I had to create a script to export the complete list of segments configured in NSX, with their Subnets/Gateways, Tier-1s, Tier-0s, IDs, Transport Zones.
Below few line of code to do that. The code is provided without warranty, use at your own risk.

Solution


The script looks like this:

###################################################################
# list_nsx_segments.ps1
#
# LM v. 0.8
#
# This script uses the "ImportExcel" library 
# https://www.powershellgallery.com/packages/ImportExcel/7.8.10
# If not present install: Install-Module ImportExcel
# 
# Input parameters: NSX_MANGER_FQDN
#		    NSX_Username
#		    NSX_Password
#

param(
    [string] $nsx_manager = '<NSX_MANAGER_FQDN>'
)

#Used to handle/skip certificates
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
        return true;
    }
}
"@
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

function createSession {
    $script:session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
    $script:headers = @{}
    $script:nsx_uri = "https://" + $nsx_manager
    #$uri = $nsx_uri + "/api/session/create"
    $private:body = "j_username=$($nsx_user)&j_password=$($nsx_pass)"
    
    try {
        $response = invoke-webrequest -contentType "application/x-www-form-urlencoded" -WebSession $session -uri $($nsx_uri + "/api/session/create") -Method 'POST' -Body $body -usebasicparsing -Erroraction Stop
        $xsrftoken = $response.headers["X-XSRF-TOKEN"]
 
        #$response
        $script:loginSuccess = $true
        $script:headers.Add("X-XSRF-TOKEN", $xsrftoken)
        $script:headers.Add("Accept", "application/json")
        $script:headers.Add('Content-Type','"application/x-www-form-urlencoded')
    }
    catch {
        Write-Host "Failed" -ForegroundColor Red
        Write-Host "$($_.Exception)" -ForegroundColor Red
        write-host "Error Details:" $_.ErrorDetails.Message -ForegroundColor Magenta
        $script:loginSuccess = $false
    }
}

#If you want insert Credential on fly uncomment the three lines below here and comment the hardcoded credentials 
#$MyCredential = Get-Credential -Message "Insert $nsx_manager "
#$nsx_user = $MyCredential.UserName
#$nsx_pass = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($MyCredential.Password))

#Harcoded credentials; uncomment if you don't want to insert them with Get-Credential function
$nsx_user = 'admin'
$nsx_pass = 'VMware1!VMware1!'


#Create the cookie session 
createSession


$response_t0s = $null
$response_t1s = $null
$response_seg = $null
$response_tz = $null

#Query the Tier-0s
$response_t0s = Invoke-webrequest -WebSession $session -uri $($nsx_uri + "/policy/api/v1/infra/tier-0s") -Method 'GET' -Headers $headers -usebasicparsing -Erroraction Stop
if ($response_t0s.statuscode -eq '200') {
    #echo $response_t0s.Content #print Json format
    $keyValue_t0s= ConvertFrom-Json $response_t0s.Content | Select-Object -expand "results"
    $sheet_t0s = $keyValue_t0s | select @{Name='T0 Name';Expression={$_.display_name}}, 
                                        @{Name='ID';Expression={$_.id}}
} else {
    Write-Host
    Write-Host
    write-Host -ForegroundColor red " !!! Somenthing went wrong !!! "
    exit 9
}
#RAW data check
#$sheet_t0s | Sort-Object -Property "T0 Name" | Out-Gridview

#Query the Tier-1s
$response_t1s = Invoke-webrequest -WebSession $session -uri $($nsx_uri + "/policy/api/v1/infra/tier-1s") -Method 'GET' -Headers $headers -usebasicparsing -Erroraction Stop
if ($response_t1s.statuscode -eq '200') {
    #echo $response_t1s.Content #print Json format
    $keyValue_t1s= ConvertFrom-Json $response_t1s.Content | Select-Object -expand "results"
    $sheet_t1s = $keyValue_t1s | select @{Name='T1 Name';Expression={$_.display_name}}, 
                                        @{Name='ID';Expression={$_.id}}

}
#RAW data check
#$sheet_t1s | Sort-Object -Property "T1 Name" | Out-Gridview

#Query the Segments
$response_seg = Invoke-webrequest -WebSession $session -uri $($nsx_uri + "/policy/api/v1/infra/segments") -Method 'GET' -Headers $headers -usebasicparsing -Erroraction Stop
if ($response_seg.statuscode -eq '200') {
    # echo $response_seg.Content #print Json format
    $keyValue_seg= ConvertFrom-Json $response_seg.Content | Select-Object -expand "results"
    $sheet_seg = $keyValue_seg | select @{Name='Segment';Expression={$_.display_name}}, 
                                        @{Name='Connected-GW';Expression={$_.connectivity_path}},
                                        @{Name='Transport Zone';Expression={$_.transport_zone_path}},
                                        @{Name='Gateway'; Expression={$_.subnets.gateway_address}}, 
                                        @{Name='Type'; Expression={$_.type}}, 
                                        @{Name='Ports_Interfaces';Expression={0}},
                                        @{Name='Admin State'; Expression={$_.admin_state}},
                                        @{Name='Seg_ID'; Expression={$_.id}}
                                  
}
# RAW data check
#$sheet_seg | Sort-Object -Property Segment | Out-Gridview

#Query the Transport zones
$response_tz = Invoke-webrequest -WebSession $session -uri $($nsx_uri + "/api/v1/transport-zones") -Method 'GET' -Headers $headers -usebasicparsing -Erroraction Stop
if ($response_tz.statuscode -eq '200') {
    #echo $response_tz.Content
    $keyValue_tz= ConvertFrom-Json $response_tz.Content | Select-Object -expand "results"
    $sheet_tz = $keyValue_tz | select @{Name='TZ Name';Expression={$_.display_name}}, 
                                       @{Name='Type';Expression={$_.transport_type}},
                                       @{Name='ID';Expression={$_.id}}
                                        
}
#RAW data
#$sheet_tz |  Sort-Object -Property "TZ Name" | Out-Gridview

###########
#Replace RAW data with the right Name into Segments.
foreach($seg in $sheet_seg) {
    # Replace Tier-0s with Name (instead of raw data)
    if ($seg."Connected-GW" -ne $null) {
        $t0= $keyValue_t0s | Where-Object { $_.path -eq $($seg."Connected-GW") } | select display_name
        if ( $t0.display_name -ne $null) {
            $seg."Connected-GW" = $t0.display_name
        } 
    }  
    # Replace Tier-1s with Name (instead of raw data)
    if ($seg."Connected-GW" -ne $null) {
        $t1= $keyValue_t1s | Where-Object { $_.path -eq $($seg."Connected-GW") } | select display_name
        if ( $t1.display_name -ne $null) {
            $seg."Connected-GW" = $t1.display_name
        } 
    }  
    # Replace Transport Zone with Name (instead of raw data)
    if ($seg."Transport Zone" -ne $null) {
        $tz_id = $seg."Transport Zone".split("/")[7]
        $tz= $keyValue_tz | Where-Object { $_.id -eq $($tz_id) } | select display_name
        $seg."Transport Zone" = $tz.display_name
    }
    #Start-Sleep -Milliseconds 40
    #write-host $seg.Seg_ID
    $response_ports = Invoke-webrequest -WebSession $session -uri $($nsx_uri + "/policy/api/v1/infra/segments/$($seg.Seg_ID)/ports") -Method 'GET' -Headers $headers -usebasicparsing -Erroraction Stop
    if ($response_ports.statuscode -eq '200') {
        #echo $response_ports.Content       
        $seg."Ports_Interfaces" = (ConvertFrom-Json $response_ports.Content |  select "result_count").result_count                   
    }
}

#$sheet_seg | Sort-Object -Property Segment | Out-GridView
$sheet_seg | Sort-Object -Property Segment | Export-Excel

write-host 
Write-Host -foreground Green "Script correctly executed on NSX:"$nsx_manager

    
... and the result looks like the follow:

I hope it will be useful.

That's it.