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
Yevgeniy Steblyanko
Latest posts by Yevgeniy Steblyanko (see all)
- Automate bulk Windows and Linux VMs creation from template with Guest OS customization - July 18, 2024
- VMware NSX VPN tunnels statistics collection with PowerShell - February 29, 2024
- vSphere & NSX: Active Directory over LDAPs authentication - February 3, 2022
Pingback: Export / Backup VMware NSX ESG/DLR configurations with PowerNSX (part 2, DLRs) - The Virtualist
Nice work Yevgeniy.