Skip to main content

It’s since some time that I’m working on a complex NSX-V to NSX-T migration and one of the fundamental phases of this migration is to prepare and remediate the current NSX-V environment in order to be correctly migrated to NSX-T.
One of the main requirements for every migration scenario is to fix the export version of Distributed Firewall must be set to 1000 on hosts before you migrate them to NSX-T Data Center. You must verify the export version and update if necessary. This last phrase is taken directly from the documentation published by VMWare here: https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.1/migration/GUID-993AB7A8-C560-43C0-B7B0-B5A58EC6884D.html
If you read the document you saw that you need to connect to every host prepared with NSX, get the Distributed Firewall Filter for the hosts with this command:
vsipioctl getfilters | grep "Filter Name" | grep "sfw.2"

Then select one of the vnic with this command for getting the value:
vsipioctl getexportversion -f nic-2112467-eth0-vmware-sfw.2

and then if it is not configured to “1000” you need to remediate using this command:
vsipioctl setexportversion -f nic-2112467-eth0-vmware-sfw.2 -e 1000

This is the first method for remediating the configuration, the second method according to the documentation is Disable and then enable Distributed Firewall on the cluster.

In some cases, the second method can’t be an option because you have a high number of clusters, hosts with some workload inside, and moving things around disabling and enabling the DFW is not possible.

So for this reason I thought about a third possibility that I will call “THE THIRD METHOD” and of course, I’m talking about a script that will help with this simple but really long task.
Basically what the script needs to connect via SSH to every prepped NSX-v host, use the command on the first method for getting a full list of the DFW Export and then allowing you to remediate the configuration with the second command, so the goal is to remediate everything in a faster and simpler way.
Before digging into the scripts I need to honor those who helped me and he clearly did all the job allowing me to focus on other checks and preparation tasks :). Thank you to Alexander Beck who wrote the script in a bunch of minutes and saved multiple hours of work! GRAZIE ALEX!

What Alex did was create a nice script that is basically getting the DVFilter configuration by connecting to every host of a cluster. But this doesn’t end here, the second step of the script is providing the list of all “nics” from an NSX-V prepped cluster and allowing you to remediate setting the ones that you select to “1000”.

Easy Peasy ah? But before enjoying our lives by launching the script and fully remediating the NSX-V environment you need to satisfy the following requirements:

PowerCli Must be installed on the Client/Jumpserver you use for connecting to the vCenter and Host
– You need an additional module called POSH-SSH (https://github.com/darkoperator/Posh-SSH) for automating via PowerShell the connection via SSH to the Host
vCenter and ESXi host must be connected AD and you must use the same Administrative user (from AD) for connecting to vCenter and the Hosts

N.B: You can rework the script for using other credentials but it was developed for connecting using AD Credentials with Admin Permissions on vCenter and ESXi Hosts. Before launch, it modifies this line by putting the name of your vcenter.

$vCenterSelect = @(“vcenter2.domain.local”,”vcenter1.domain.local”) | Out-GridView -PassThru -Title “Please select vCenter”


N.B 2: Remember the script provided here below needs proper testing before being launched against a production environment. Run it at your own risk.


Hopefully, this will be useful for some of you.

<# Check Export Version #>

function FN_NULL_OR_ZERO($testsubj)
{
    if($testsubj -eq $null)
    {
        Write-Error "Please select item!"
        return $true
    }
    if($testsubj.count -eq 0)
    {
        Write-Error "Please select item!"
        return $true
    }

    if($testsubj.count -gt 1)
    {
        Write-Error "Please select only one item!"
        return $true
    }
    return $false
}
function Save-File([string] $initialDirectory ) 
{

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null

    $OpenFileDialog = New-Object System.Windows.Forms.SaveFileDialog
    $OpenFileDialog.initialDirectory = $initialDirectory
    $OpenFileDialog.filter = "All files (*.*)| *.*"
    $OpenFileDialog.ShowDialog() |  Out-Null

    return $OpenFileDialog.filename
} 

Write-Host -NoNewline "Checking if a vCenter is Connected ...."
if($global:defaultviserver -ne $null)
{
    Write-Host  " Not ok"
    Write-Warning "You need to disconnect from all vCenters"
    Disconnect-VIServer * -Force
    if($global:defaultviserver -ne $null) { Write-Error "You have not disconnected!"; Exit}
} else {
    Write-Host  " ok"
}

Write-Host -NoNewline "Please select vCenter .... "
$vCenterSelect = @("vcenter1.domain.local,vcenter2.domain.local") | Out-GridView -PassThru -Title "Please select vCenter"
if(FN_NULL_OR_ZERO -testsubj $vCenterSelect) { Exit }
Write-Host "$vCenterSelect selected"

Write-Host -NoNewline "Trying to connect to $vCenterSelect ... "
try{
    Connect-VIServer $vCenterSelect -ErrorAction Stop | Out-Null
    Write-Host "Ok!"
} catch {
    Write-Host "Failed!"
    Exit
}
Write-Host -NoNewline "Grepp all Clusters .... "
try {  
    $AllClusters = Get-Cluster -ErrorAction Stop
    Write-Host " $($AllClusters.count) Found"
} catch {
    Write-Host " Failed"
    Exit
}

Write-Host -NoNewline "Please select Cluster .... "
$Cluster = $AllClusters | Out-GridView -Title "Please selct Cluster" -PassThru
if(FN_NULL_OR_ZERO -testsubj $Cluster) { Exit }
Write-Host " $($Cluster.Name) selected!"

Write-Host -NoNewline "Please provide Credentails for SSH .... "
$Credential = Get-Credential 
if($Credential -eq $null)
{
    Write-Host -ForegroundColor Red " Failed"
} else {
    Write-Host -ForegroundColor Green " OK"
}

Write-Host "+++++++++++ Input Completed +++++++++++"
Write-Host "vCenter $($global:defaultviserver.Name)"
Write-Host "Cluster $($Cluster.Name)"
Write-Host "Input ok?"
$UserInput = Read-Host "Please write Yes if ok"
if($UserInput -ne "Yes") { Write-Warning "Action canceled by user!"; Exit}

#*********************************** Script start *********************************#
#
# 
#
Write-Host "+++++++++++ Start +++++++++++"
Write-Host -NoNewline "Grepp all Host .... "
try {  
    $AllHosts = $Cluster | Get-VMHost -ErrorAction Stop
    Write-Host -ForegroundColor Green " $($AllHosts.count) Found"
} catch {
    Write-Host -ForegroundColor Red " Failed"
    Exit
}
if($AllHosts.count -lt 1)
{
    Write-Error "No hosts found"
    Exit
}
Write-Host "+++++++++++ Enable SSH +++++++++++"
foreach($vmhost in $AllHosts)
{
    Write-Host -NoNewline "Trying to enable SSH  on $($vmhost.Name) .... "
    try{
        Start-VMHostService -ErrorAction Stop -HostService ($vmhost | Get-VMHostService | Where { $_.Key -eq "TSM-SSH"} ) | Out-Null
        Write-Host -ForegroundColor Green "OK"
    } catch {
        Write-Host -ForegroundColor Red "Failed"
        Exit
    }
}
# Define an output table object with required columns:
$table = New-Object System.Data.DataTable
$col1 = New-Object System.Data.DataColumn Host,([string])
$col2 = New-Object System.Data.DataColumn VMName,([string])
$col3 = New-Object System.Data.DataColumn NIC,([string])
$col4 = New-Object System.Data.DataColumn ExportVersion,([int])
$table.Columns.Add($col1)
$table.Columns.Add($col2)
$table.Columns.Add($col3)
$table.Columns.Add($col4)

Write-Host "+++++++++++ Connect SSH +++++++++++"
foreach($vmhost in $AllHosts)
{
    Write-Debug "Check if there are any SSH-Sessions Active"
    Get-SSHSession | Remove-SSHSession 
    Write-Host -NoNewline "[$($vmhost.Name)] Trying to connect via SSH .... "
    try{
        $ResposneSSH = New-SSHSession -ComputerName $vmhost.Name -Credential $Credential -Port 22 -AcceptKey:$true -ErrorAction Stop
        Write-Host -ForegroundColor Green "OK"
    } catch {
        Write-Host -ForegroundColor Red "Failed"
        Write-Host $_
        continue
    }
    if((Get-SSHSession | Select-Object -ExpandProperty Connected) -ne $true)
    {
        Write-Error "There was a Error with the connect"
        continue
    }

    Write-Host -NoNewline "[$($vmhost.Name)] Trying to execute summarize-dvfilter .... "
    try { 
        $dvflist = Invoke-SSHCommand -SessionId $ResposneSSH.SessionId -Command "summarize-dvfilter" -ErrorAction Stop
        Write-Host -ForegroundColor Green "OK"
    } catch {
        Write-Host -ForegroundColor Red "Failed"
    }
    Write-Host -NoNewline "[$($vmhost.Name)] Trying to execute vsipioctl getexportversion for all Items .... "
    try {
        ForEach ($item in $dvflist.Output) {
            # If we see a new VM identifier, update our current VMName setting:
            if ($item -match '(?<=vmm0:)(.*)(?= vcUuid:)') {
                $VMName = $matches[0]
            }
            # If we see a line that looks like a fw export, grab that and run vsipioctl on it:
            if ($item -match '(?<=name: )(.*sfw.2)') {
                $VMNic = $matches[0]
                $fwexport = Invoke-SSHCommand -SessionId 0 -Command "vsipioctl getexportversion -f $VMnic"
                # Parse the returned 'Current Export Version' from vsipioctl:
                $exmatch = $fwexport.Output[0] -match '(?<=version: )(.*)'
                $exportVersion = $matches[0]
                # Add a table row that includes the VM name, NIC ID and exportversion:
                $row = $table.NewRow()
                $row.Host = $vmhost.Name
                $row.VMName = $VMName
                $row.NIC = $VMNic
                $row.ExportVersion = $exportVersion
                $table.Rows.Add($row)
            }
        }
        Write-Host -ForegroundColor Green "OK"
    } catch {
        Write-Host -ForegroundColor Red "Failed"
        Write-Error $_
    }
}
Write-Host "+++++++++++ Finished SSH +++++++++++"
Write-Host "Please select now the Versions to Update ... "
$toUpdate = $table | Out-GridView -Title "Please select Items to update" -PassThru
if($toUpdate -eq $null)
{
    Write-Warning "Nothing selected!"
    Exit
}
if($toUpdate.count -eq 0)
{
    Write-Warning "Nothing selected!"
    Exit
}
Write-Host "These Items will be updated ... "
$toUpdate | Format-Table

$UserInput = Read-Host "Please write Yes if ok"
if($UserInput -ne "Yes") { Write-Warning "Action canceled by user!"; Exit}

foreach($Item in $toUpdate)
{
    Write-Debug "Check if there are any SSH-Sessions Active"
    Get-SSHSession | Remove-SSHSession
    $vmhost = Get-VMHost $item.Host
    Write-Host -NoNewline "[$($vmhost.Name)] Trying to connect via SSH .... "
    try{
        $ResposneSSH = New-SSHSession -ComputerName $vmhost.Name -Credential $Credential -Port 22 -AcceptKey:$true -ErrorAction Stop
        Write-Host -ForegroundColor Green "OK"
    } catch {
        Write-Host -ForegroundColor Red "Failed"
        Write-Host $_
        continue
    }
    if((Get-SSHSession | Select-Object -ExpandProperty Connected) -ne $true)
    {
        Write-Error "There was a Error with the connect"
        continue
    }

    Write-Host -NoNewline "[$($vmhost.Name)] Trying to execute update .... "
    try { 
        $UpdateResponse = Invoke-SSHCommand -SessionId $ResposneSSH.SessionId -Command "vsipioctl setexportversion -f $($Item.NIC) -e 1000" -ErrorAction Stop
        Write-Host -ForegroundColor Green "OK"
    } catch {
        Write-Host -ForegroundColor Red "Failed"
    }
}

Leave a Reply