Export / Backup VMware NSX ESG/DLR configurations with PowerNSX (part 1, ESGs)

Share this:

Why do you need this.

If you work with VMware NSX on daily basis you should care about Backup & Restore procedure. According to VMware you can schedule NSX Manager backup and think you are on safe side but restore procedure requires to perform full NSX Manager restore and then redeploy some or all NSX components. This will overwrite the whole your current network configuration and as result is not suitable for partial restore (several components only) on Production environments.

VMware example:

The way you can do it with PowerNSX.

So my idea was to schedule the task which is going to read all ESGs and DLRs configuration parameters and store it in human readable text files. The parameters are saved in the same order as you use them during manual deployment for new ESG/DLR so you don’t need to scroll forward and backward to find necessary parameter. In this case you can re-deploy any Edge or DLR manually with NSX GUI to restore network configuration. Also exported files can be used as reference to track the configuration and changes back in time which could be helpful sometimes.

This post is the Part 1 of my blog, it contains the script I wrote for ESGs export. Next post will be for DLRs export.

How to use this script

You just need to replace vCenter name for variable “$vCenterServerName” by vCenter FQDN or IP specific to your environment. 

After start the script asks for vCenter credentials, creates the subfolder in format “ESGs-Config-Export-dd_mm_yyyy-hh_mm”, reads list of all ESGs with parameters and stores in text files, separate file for each ESG in format “Config-for-ESG_esgName”.

PowerNSX script

###########################################
##### Export NSX ESG configuration    #####
##### (c) Yevgeniy Steblyanko         #####
##### ver 0.1.0, 23.03.2020           #####
###########################################

# Change vCenter name with your vCenter FQDN or IP
$vCenterServerName = "vCenterName"

Write-Host -foregroundcolor "Green" "Script for _Export ESG & DLR configurations_ started..."
Connect-NsxServer -vCenterServer $vCenterServerName

$currentDate = Get-Date -Format "dd_MM_yyyy-HH_mm"
If (-Not (Test-Path -LiteralPath ("ESGs-Config-Export-" + $currentDate ))){ $outputFileFolder = New-Item ("ESGs-Config-Export-" + $currentDate) -itemtype directory}

Write-Host "Collecting information for ESGs"
$allESGs = Get-NsxEdge
Write-Host "Found" $allESGs.count "ESGs"

Write-Host "Collecting the rest NSX objects"
$allLSs = Get-NsxLogicalSwitch
$VDSwitches = Get-VDSwitch
$VDPorts = $VDSwitches | Get-VDPortgroup

If ($allESGs.count -gt 0) {
  Foreach ($ESG in $allESGs)
  {
      $ESGExport = ""
      Write-Host  "Collecting info for " -NoNewLine
      Write-Host  -foregroundcolor "Yellow" $ESG.name
      $ESGExport += "Name = " + $ESG.name + "`n"
      $ESGExport += "Hostname = " + $ESG.fqdn + "`n"
      $ESGExport += "Description = " + $ESG.description + "`n"
      $ESGExport += "Edge ID = " + $ESG.id + "`n"
      $ESGExport += "Type = " + $ESG.type
          if ($ESG.type -eq "gatewayServices"){$ESGExport += " (Edge Services Gateway)"}
          $ESGExport += "`n"
      $ESGExport += "Enable High Availability = " + $ESG.features.highAvailability.enabled + "`n"
      $ESGExport += "CLI credentials (User Name) = " + $ESG.cliSettings.userName + "`n"
      $ESGExport += "Enable SSH access = " + $ESG.cliSettings.remoteAccess + "`n"
      $ESGExport += "Enable FIPS mode = " + $ESG.enableFips + "`n"
      $ESGExport += "Enable Auto rule generation = " + $ESG.autoConfiguration.enabled + "`n"
      $ESGExport += "Edge Control Level Logging = " + $ESG.vseLogLevel + "`n"
      $ESGExport += "Datacenter = " + $ESG.datacenterName + "`n"
      $ESGExport += "Appliance Size = " + $ESG.appliances.applianceSize + "`n"
      $ESGExport += "`n"

      $ESGExport += "NSX Edge Appliances: " + "`n"
          Foreach($ESGappliance in $ESG.appliances.appliance){
              $ESGExport += "  Index: " + $ESGappliance.highAvailabilityIndex + "`n"
              $ESGExport += "    Name: " + $ESGappliance.vmName + "`n"
              $ESGExport += "    Cluster/Resource Pool: " + $ESGappliance.resourcePoolName + "`n"
              $ESGExport += "    Datastore: " + $ESGappliance.datastoreName + "`n"
              $ESGExport += "    Folder: " + $ESGappliance.vmFolderName + "`n"
              $ESGExport += "    Resource Reservation: "
              $ESGExport += " CPU = " + $ESGappliance.cpuReservation.reservation
              $ESGExport += ", Memory = " + $ESGappliance.memoryReservation.reservation +  "`n"
          }
      $ESGExport += "Configure interfaces" + "`n"
          Foreach($ESGvnic in $ESG.vnics.vnic){
              $ESGExport += "  Index: " + $ESGvnic.index
              If ($ESGvnic.portgroupId){
                  $ESGExport += "`n    Name: " + $ESGvnic.name + "`n"
                  $ESGExport += "    Type: " + $ESGvnic.type + "`n"
                  $ESGExport += "    Connectivity Status: "
                      If ($ESGvnic.isConnected -eq "true") {$ESGExport += "Connected`n"}
                      Else {$ESGExport += "Disonnected`n"}
                  $ESGExport += "    Connected to: "
                  If (($ESGvnic.portgroupId -like "universalwire-*") -or ($ESGvnic.portgroupId -like "virtualwire-*")) {       # Find LogicalSwitch name
                      $LS = $allLSs | Where-Object {$_.objectId -eq $ESGvnic.portgroupId}
                      $ESGExport += "Logical Switch -> " + $LS.name + "`n"
                  }
                  ElseIf ($ESGvnic.portgroupId -like "dvportgroup-*"){                            # Find Distributed Virtual Portgroup name
                      $VDPort = $VDPorts | Where-Object {$_.Key -eq $ESGvnic.portgroupId}
                      $ESGExport += "DistributedVirtualPortgroup -> " + $VDPort.name + "`n"
                  }
                  Else { $ESGExport += "unknown type -> " + $ESGvnic.portgroupId + "`n" }
                  Foreach ($ESGvnicAddressGroup in $ESGvnic.addressGroups.addressGroup) {         # find Primary and Secondary IP addresses for vNIC
                    $ESGExport += "      Primary IP Address: " + $ESGvnicAddressGroup.primaryAddress + "`n"
                    Foreach ($ESGvnicAddressGroupSecondaryAddress in $ESGvnicAddressGroup.secondaryAddresses.ipAddress) {
                      $ESGExport += "        Secondary IP Address: " + $ESGvnicAddressGroupSecondaryAddress + "`n"
                    }
                     $ESGExport += "        Subnet Prefix Length: " + $ESGvnicAddressGroup.subnetPrefixLength + "`n"
                  }
                  $ESGExport += "    MTU: " + $ESGvnic.mtu + "`n"
                  $ESGExport += "    Enable Proxy Arp: " + $ESGvnic.enableProxyArp + "`n"
                  $ESGExport += "    Enable Send Redirects: " + $ESGvnic.enableSendRedirects + "`n"
              }
              Else { $ESGExport += " (Not configured)`n" }                                         # Nothing configured for this NIC
          }

      $ESGRouting = $ESG | Get-NsxEdgeRouting
      If ($ESGRouting.staticRouting.defaultRoute) {
          $ESGExport += "Configure default gateway: true`n"
          $ESGdefaultRouteNIC = $ESG.vnics.vnic | Where-Object {$_.index -eq $ESGRouting.staticRouting.defaultRoute.vnic}
          $ESGExport += "  vNIC: " + $ESGdefaultRouteNIC.name + "`n"
          $ESGExport += "  Gateway IP: " + $ESGRouting.staticRouting.defaultRoute.gatewayAddress + "`n"
          $ESGExport += "  Admin distance: " + $ESGRouting.staticRouting.defaultRoute.adminDistance + "`n"
      }
      Else {$ESGExport += "Configure default gateway: false`n"}

      #Configure Firewall default policy
      $ESGDefaultFirewall = $ESG.features.firewall
      $ESGExport += "Configure Firewall default policy: " + $ESGDefaultFirewall.enabled + "`n"
      If ($ESGDefaultFirewall.enabled -eq "true") {
        $ESGExport += "  Firewall default action: " + $ESGDefaultFirewall.defaultPolicy.action + "`n"
        $ESGExport += "  Firewall default logging: " + $ESGDefaultFirewall.defaultPolicy.loggingEnabled + "`n"
      }

      #Configure HA parameters
      $ESGDefaultHA = $ESG.features.highAvailability
      $ESGExport += "Configure HA: " + $ESGDefaultHA.enabled + "`n"
      If ($ESGDefaultHA.enabled -eq "true") {
        $ESGExport += "  vNIC: " + $ESGDefaultHA.vnic + "`n"
        $ESGExport += "  Declare Dead Time: " + $ESGDefaultHA.declareDeadTime + "`n"
        $ESGExport += "  Enable logging: " + $ESGDefaultHA.logging.enable + "`n"
        $ESGExport += "  Log level: " + $ESGDefaultHA.logging.loglevel + "`n"
      }

      ### After deployment tasks
      $ESGExport += "`nAfter deployment tasks`n`n"

      # Configuration
      $ESGExport += "Configuration`n"

      # Syslog configuration
      $ESGExport += "  Syslog`n"
      $ESGExport += "    Syslog Enabled: " + $ESG.features.syslog.enabled + "`n"
      Foreach ($ESGsyslogServer in $ESG.features.syslog.serverAddresses.ipAddress) {
        $ESGExport += "    Syslog Server: " + $ESGsyslogServer + "`n"
      }
      $ESGExport += "    Protocol: " + $ESG.features.syslog.protocol + "`n"

      # DNS Configuration
      $ESGExport += "  DNS Configuration`n"
      $ESGDNS = $ESG | Get-NsxDns
      $ESGExport += "    Enable DNS service: " + $ESGDNS.enabled + "`n"
      $ESGExport += "      Interface: " + $ESGDNS.listeners.vnic + "`n"
      Foreach ($ESGDNSServer in $ESGDNS.dnsViews.dnsView.forwarders.ipAddress) {
        $ESGExport += "      DNS Server: " + $ESGDNSServer + "`n"
      }
      $ESGExport += "      Cache Size: " + $ESGDNS.cacheSize + "`n"
      $ESGExport += "    Enable Logging: " + $ESGDNS.logging.enable + "`n"
      $ESGExport += "      Log level: " + $ESGDNS.logging.logLevel + "`n"

      # Global Configuration
      $ESGExport += "Global Configuration`n"
      $ESGExport += "  ECMP: " + $ESGRouting.routingGlobalConfig.ecmp + "`n"
      # Default Gateway
      If ($ESGRouting.staticRouting.defaultRoute) {
        $ESGExport += "  Default Gateway`n"
        $ESGdgwvNic = $ESG.vnics.vnic | Where-Object {$_.index -eq $ESGRouting.staticRouting.defaultRoute.vnic}
        $ESGExport += "    vNIC: " + $ESGRouting.staticRouting.defaultRoute.vnic + " (" + $ESGdgwvNic.name + ")" + "`n"
        $ESGExport += "    Gateway IP: " + $ESGRouting.staticRouting.defaultRoute.gatewayAddress + "`n"
        $ESGExport += "    Admin distance: " + $ESGRouting.staticRouting.defaultRoute.adminDistance + "`n"
        $ESGExport += "    Description: " + $ESGRouting.staticRouting.defaultRoute.description + "`n"
      }
      Else {$ESGExport += "  Default Gateway: none`n"}

      $ESGExport += "  Dynamic Routing Configuration`n"
      # Dynamic Routing Configuration
      $ESGExport += "    Router ID: " + $ESGRouting.routingGlobalConfig.routerId + "`n"

      # Static Routes
      $ESGRoutingStaticRoutes = $ESGRouting.staticRouting.staticRoutes.route | Where {$_.type -eq "user"}
      If ($ESGRoutingStaticRoutes) {
        $ESGExport += "  Static Routes`n"
        Foreach ($ESGRoutingStaticRoute in $ESGRoutingStaticRoutes) {
          $ESGExport += "    Network: " + $ESGRoutingStaticRoute.network
          $ESGExport += ", Next Hop: " + $ESGRoutingStaticRoute.nextHop
          If ($ESGRoutingStaticRoute.vnic) {
            $ESGstaticRoutevNicName = ($ESG.vnics.vnic | Where-Object {$_.index -eq $ESGRoutingStaticRoute.vnic}).name
          }
          Else {$ESGstaticRoutevNicName = "none"}
          $ESGExport += ", Interface: " + $ESGstaticRoutevNicName
          $ESGExport += ", Admin Distance: " + $ESGRoutingStaticRoute.adminDistance
          $ESGExport += ", Description: " + $ESGRoutingStaticRoute.description
          $ESGExport += "`n"
        }
      }
      Else {$ESGExport += "  Static Routes: none`n"}

      # BGP
      # Get info for BGP if Enabled
      If ($ESGRouting.bgp.enabled -eq "true") {
        $ESGExport += "  BGP Configuration`n"
        $ESGExport += "    Enable BGP: " + $ESGRouting.bgp.enabled + "`n"
        $ESGExport += "    Enable Graceful Restart: " + $ESGRouting.bgp.gracefulRestart + "`n"
        $ESGExport += "    Enable Default Originate: " + $ESGRouting.bgp.defaultOriginate + "`n"
        $ESGExport += "    Local AS: " + $ESGRouting.bgp.localASNumber + "`n"
        $ESGExport += "  BGP Neighbours" + "`n"
        Foreach ($ESGRoutingBgpNeighbour in $ESGRouting.bgp.bgpNeighbours.bgpNeighbour) {
          $ESGExport += "    IP Address: " + $ESGRoutingBgpNeighbour.ipAddress + "`n"
          $ESGExport += "      Remote AS: " + $ESGRoutingBgpNeighbour.remoteASNumber + "`n"
          $ESGExport += "      Remove Private AS: " + $ESGRoutingBgpNeighbour.removePrivateAS + "`n"
          $ESGExport += "      Weight: " + $ESGRoutingBgpNeighbour.weight + "`n"
          $ESGExport += "      Keep Alive Time: " + $ESGRoutingBgpNeighbour.keepAliveTimer + "`n"
          $ESGExport += "      Hold Down Time: " + $ESGRoutingBgpNeighbour.holdDownTimer + "`n"
          If ($ESGRoutingBgpNeighbour.password) {
            $ESGExport += "      Password exists: true`n" }
          Else {$ESGExport += "      Password exists: false`n"}
          # collect BGP Filters
          If ($ESGRoutingBgpNeighbour.bgpFilters.bgpFilter) {
            $ESGExport += "      BGP Filters`n"
            Foreach ($ESGRoutingBgpNeighbourbgpFilter in $ESGRoutingBgpNeighbour.bgpFilters.bgpFilter) {
              $ESGExport += "        Direction: " + $ESGRoutingBgpNeighbourbgpFilter.direction + "`n"
              $ESGExport += "         Action: " + $ESGRoutingBgpNeighbourbgpFilter.action + "`n"
              $ESGExport += "         Network: " + $ESGRoutingBgpNeighbourbgpFilter.network + "`n"
              $ESGExport += "         IP Prefix GE: " + $ESGRoutingBgpNeighbourbgpFilter.ipPrefixGe + "`n"
              $ESGExport += "         IP Prefix LE: " + $ESGRoutingBgpNeighbourbgpFilter.ipPrefixLe + "`n"
            }
          }
          Else {$ESGExport += "      BGP Filters: none`n"}
        }
      }
      Else {$ESGExport += "  BGP Configuration: none`n"}
      # collect Route Redistribution
      $ESGExport += "  Route Redistribution OSPF: " + $ESGRouting.ospf.redistribution.enabled + "`n"
      If ($ESGRouting.bgp.redistribution.enabled) {$ESGExport += "  Route Redistribution BGP: " + $ESGRouting.bgp.redistribution.enabled + "`n"}
      Else {$ESGExport += "  Route Redistribution BGP: none`n"}
      # collect IP Prefixes
      If ($ESGRouting.routingGlobalConfig.ipPrefixes.ipPrefix) {
        $ESGExport += "  IP Prefixes`n"
        Foreach ($ESGroutingGlobalConfigIpPrefix in $ESGRouting.routingGlobalConfig.ipPrefixes.ipPrefix) {
          $ESGExport += "    Name: " + $ESGroutingGlobalConfigIpPrefix.name + "`n"
          $ESGExport += "      IP/Network: " + $ESGroutingGlobalConfigIpPrefix.ipAddress + "`n"
          $ESGExport += "      IP Prefix GE: " + $ESGroutingGlobalConfigIpPrefix.ge + "`n"
          $ESGExport += "      IP Prefix LE: " + $ESGroutingGlobalConfigIpPrefix.le + "`n"
        }
      }
      # Route Redistribution Table
      If ($ESGRouting.bgp.redistribution.rules.rule) {
        $ESGExport += "  Route Redistribution Table" + "`n"
        Foreach ($ESGRoutingBgpRedistributionRule in $ESGRouting.bgp.redistribution.rules.rule) {
          $ESGExport += "    ID: " + $ESGRoutingBgpRedistributionRule.id + ","
          $ESGExport += " Learner: BGP,"
          $ESGExport += " From: "
          If ($ESGRoutingBgpRedistributionRule.from.ospf -eq "true") {$ESGExport += "OSPF,"}
          If ($ESGRoutingBgpRedistributionRule.from.bgp -eq "true") {$ESGExport += "BGP,"}
          If ($ESGRoutingBgpRedistributionRule.from.static -eq "true") {$ESGExport += "Static Routes,"}
          If ($ESGRoutingBgpRedistributionRule.from.connected -eq "true") {$ESGExport += "Connected,"}
          If ($ESGRoutingBgpRedistributionRule.prefixName) {$ESGExport += " Prefix: " + $ESGRoutingBgpRedistributionRule.prefixName + ","}
          Else {$ESGExport += " Prefix: Any,"}
          $ESGExport += " Action: " + $ESGRoutingBgpRedistributionRule.action
          $ESGExport += "`n"
        }
      }

      $ESGExport += "`n"

      $outputFileName = "Config-for-ESG_" + $ESG.name + ".txt"
      $ESGExport | Out-File -filePath ($outputFileFolder.Name + "\" + $outputFileName)
  }
}

Disconnect-NsxServer -vCenterServer $vCenterServerName
Disconnect-VIServer -Server $vCenterServerName -Confirm:$False

Write-Host -foregroundcolor "Green" "`nScript completed!"

Example of output file

Example of output file created by script (all customer specific names and IPs are replaced by *** for security reasons)

Name = test-esg1
Hostname = test-esg1
Description = Test Edge
Edge ID = edge-178
Type = gatewayServices (Edge Services Gateway)
Enable High Availability = true
CLI credentials (User Name) = admin
Enable SSH access = false
Enable FIPS mode = false
Enable Auto rule generation = true
Edge Control Level Logging = info
Datacenter = DC1
Appliance Size = compact

NSX Edge Appliances:
  Index: 0
    Name: test-esg1-0
    Cluster/Resource Pool: DC1-E1
    Datastore: dc1-e1-vsan
    Folder: NSX_EDGEs
    Resource Reservation:  CPU = 0, Memory = 0
  Index: 1
    Name: test-esg1-1
    Cluster/Resource Pool: DC1-E1
    Datastore: dc1-e1-vsan
    Folder: NSX_EDGEs
    Resource Reservation:  CPU = 0, Memory = 0
Configure interfaces
  Index: 0
    Name: NIC-Internal1
    Type: internal
    Connectivity Status: Connected
    Connected to: Logical Switch -> dc1-transit1
      Primary IP Address: 192.168.***.***
        Subnet Prefix Length: **
      Primary IP Address: 192.168.***.***
        Secondary IP Address: 192.168.***.***
        Secondary IP Address: 192.168.***.***
        Subnet Prefix Length: **
    MTU: 1500
    Enable Proxy Arp: false
    Enable Send Redirects: false
  Index: 1
    Name: NIC-Internal2
    Type: internal
    Connectivity Status: Connected
    Connected to: Logical Switch -> dc1-transit2
      Primary IP Address: 192.168.***.***
        Subnet Prefix Length: **
    MTU: 1500
    Enable Proxy Arp: false
    Enable Send Redirects: true
  Index: 2
    Name: NIC-Uplink1
    Type: uplink
    Connectivity Status: Connected
    Connected to: DistributedVirtualPortgroup -> dc1-dvs1-***
      Primary IP Address: 192.168.***.***
        Subnet Prefix Length: **
    MTU: 1500
    Enable Proxy Arp: false
    Enable Send Redirects: true
  Index: 3 (Not configured)
  Index: 4 (Not configured)
  Index: 5 (Not configured)
  Index: 6 (Not configured)
  Index: 7 (Not configured)
  Index: 8 (Not configured)
  Index: 9 (Not configured)
Configure default gateway: true
  vNIC: NIC-Uplink1
  Gateway IP: 192.168.***.***
  Admin distance: 1
Configure Firewall default policy: true
  Firewall default action: deny
  Firewall default logging: false
Configure HA: true
  vNIC: any
  Declare Dead Time: 15
  Enable logging: false
  Log level: info

After deployment tasks

Configuration
  Syslog
    Syslog Enabled: true
    Syslog Server: ***.local
    Protocol: UDP
  DNS Configuration
    Enable DNS service: true
      Interface: NIC-Internal1
      DNS Server: 192.168.***.***
      DNS Server: 192.168.***.***
      Cache Size: 16
    Enable Logging: false
      Log level: info
Global Configuration
  ECMP: false
  Default Gateway
    vNIC: 0 (NIC-Uplink1)
    Gateway IP: 192.168.***.***
    Admin distance: 1
    Description: Some text
  Dynamic Routing Configuration
    Router ID: 192.168.***.***
  Static Routes
    Network: 192.168.***.***/**, Next Hop: 192.168.***.***, Interface: NIC-Uplink1, Admin Distance: 1, Description:
    Network: 192.168.***.***/**, Next Hop: 192.168.***.***, Interface: none, Admin Distance: 10, Description: Route to subnet B
  BGP Configuration
    Enable BGP: true
    Enable Graceful Restart: true
    Enable Default Originate: false
    Local AS: ***.***
  BGP Neighbours
    IP Address: 192.168.***.***
      Remote AS: ***.***
      Remove Private AS: true
      Weight: 60
      Keep Alive Time: 60
      Hold Down Time: 180
      Password exists: false
      BGP Filters
        Direction: in
         Action: permit
         Network: 192.168.***.***/**
         IP Prefix GE: **
         IP Prefix LE: **
        Direction: out
         Action: deny
         Network: 192.168.***.***/**
         IP Prefix GE:
         IP Prefix LE:
    IP Address: 192.168.***.***
      Remote AS: ***.***
      Remove Private AS: false
      Weight: 60
      Keep Alive Time: 60
      Hold Down Time: 180
      Password exists: true
      BGP Filters
        Direction: in
         Action: permit
         Network: 192.168.***.***/**
         IP Prefix GE:
         IP Prefix LE:
    IP Address: 192.168.***.***
      Remote AS: ***.***
      Remove Private AS: true
      Weight: 30
      Keep Alive Time: 5
      Hold Down Time: 15
      Password exists: false
      BGP Filters: none
  Route Redistribution OSPF: false
  Route Redistribution BGP: true
  IP Prefixes
    Name: Pref1
      IP/Network: 192.168.***.***/**
      IP Prefix GE: **
      IP Prefix LE: **
    Name: Pref2
      IP/Network: 192.168.***.***/**
      IP Prefix GE: **
      IP Prefix LE: **
  Route Redistribution Table
    ID: 0, Learner: BGP, From: Static Routes, Prefix: Pref1, Action: deny
    ID: 1, Learner: BGP, From: Connected, Prefix: Any, Action: permit

Current version doesn’t include DHCP, NAT, LoadBalancer, VPN configs because it was not the case for current customer. Might be I will work on further versions and add this functionality later.

Software Versions

This script was tested in the environment with the following components:

  • VMware vSphere 6.5
  • VMware NSX-V 6.4.1
  • VMware PowerCLI 10.5.0
  • PowerNSX 3.0.1174
The following two tabs change content below.

Yevgeniy Steblyanko

Yevgeniy Steblyanko is an Infrastructure Architect/SME with experience in virtualization area for more than 15 years. His areas of interest are VMware vSphere, vSAN, NSX, automation on PowerCLI/PowerNSX. He has VMware certifications: VCIX-DCV, VCIX-NV.

About Yevgeniy Steblyanko

Yevgeniy Steblyanko is an Infrastructure Architect/SME with experience in virtualization area for more than 15 years. His areas of interest are VMware vSphere, vSAN, NSX, automation on PowerCLI/PowerNSX. He has VMware certifications: VCIX-DCV, VCIX-NV.
Bookmark the permalink.

2 Comments

  1. Pingback: Export / Backup VMware NSX ESG/DLR configurations with PowerNSX (part 2, DLRs) - The Virtualist

  2. Nice work Yevgeniy.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.