BrownField/Networking/VPN-SDWAN/NSX-T/Scripts/New-IfNotExist-Segment.ps1 (351 lines of code) (raw):

function New-IfNotExist-Segment { param( [string]$avsnsxTmanager, [string]$nsxtUserName, [SecureString]$nsxtPassword, [string]$tier1GatewayName, [string]$segmentName, [string]$dnsServerAddress, [string]$dhcpProfilePath ) $segmentAddress = Get-Segment -avsnsxTmanager $avsnsxTmanager ` -nsxtUserName $nsxtUserName ` -nsxtPassword $nsxtPassword ` -segmentName $segmentName if ($segmentAddress) { Write-Host "Segment '$segmentName' already exists." } else { try { Write-Host "Segment '$segmentName' not found. Creating..." $segmentAddress = New-Segment -avsnsxTmanager $avsnsxTmanager ` -nsxtUserName $nsxtUserName ` -nsxtPassword $nsxtPassword ` -tier1GatewayName $tier1GatewayName ` -segmentName $segmentName ` -dnsServerAddress $dnsServerAddress ` -dhcpProfilePath $dhcpProfilePath } catch { Write-Error "Failed to create segment '$segmentName': $_" } } return $segmentAddress } function Get-Segment { param( [string]$avsnsxTmanager, [string]$nsxtUserName, [SecureString]$nsxtPassword, [string]$segmentName ) $segmenturl = "$avsnsxTmanager/policy/api/v1/search/aggregate?page_size=50&cursor=0&sort_by=display_name" + "&sort_ascending=true" $body = @{ primary = @{ resource_type = "Segment" filters = @( @{ field_names = "!_exists_" value = "advanced_config.origin_id" case_sensitive = $true } ) } related = @( @{ resource_type = "Tier0 OR Tier1" join_condition = "path:connectivity_path" alias = "connectivity" }, @{ resource_type = "SegmentDiscoveryProfileBindingMap" join_condition = "parent_path:path" alias = "SegmentDiscoveryProfileBindingMap" }, @{ resource_type = "SegmentSecurityProfileBindingMap" join_condition = "parent_path:path" alias = "SegmentSecurityProfileBindingMap" }, @{ resource_type = "SegmentQoSProfileBindingMap" join_condition = "parent_path:path" alias = "SegmentQoSProfileBindingMap" }, @{ resource_type = "IPDiscoveryProfile" join_condition = "path:$1.ip_discovery_profile_path" alias = "IPDiscoveryProfile" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "MacDiscoveryProfile" join_condition = "path:$1.mac_discovery_profile_path" alias = "MacDiscoveryProfile" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "SpoofGuardProfile" join_condition = "path:$2.spoofguard_profile_path" alias = "SpoofGuardProfile" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "SegmentSecurityProfile" join_condition = "path:$2.segment_security_profile_path" alias = "SegmentSecurityProfile" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "QoSProfile" join_condition = "path:$3.qos_profile_path" alias = "QoSProfile" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "DhcpServerConfig OR DhcpRelayConfig" join_condition = "path:dhcp_config_path" alias = "DhcpServerConfig" included_fields = "path,parent_path,display_name,id,edge_cluster_path,resource_type,server_addresses" }, @{ resource_type = "L2VPNSession" join_condition = "path:l2_extension.l2vpn_paths" alias = "l2vpn_session" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "Ipv6NdraProfile" join_condition = "path:advanced_config.ndra_profile_path" alias = "Ipv6NdraProfile" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "SegmentPort" join_condition = "parent_path:path" alias = "segment_ports" size = 0 }, @{ resource_type = "PolicyTransportZone" join_condition = "path:transport_zone_path" alias = "transport_zone" included_fields = "path,parent_path,display_name,id,tz_type,uplink_teaming_policy_names,nsx_id,unique_id,authorized_vlans" }, @{ resource_type = "EnforcementPoint" join_condition = "path:$13.parent_path" alias = "EnforcementPoint" size = 0 }, @{ resource_type = "Site" join_condition = "path:$14.parent_path" alias = "Site" included_fields = "path,parent_path,display_name,id,unique_id" }, @{ resource_type = "IpAddressPool" join_condition = "path:advanced_config.address_pool_paths" alias = "ip_address_pool" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "MetadataProxyConfig" join_condition = "path:metadata_proxy_paths" alias = "MetadataProxyConfig" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "EvpnTenantConfig" join_condition = "path:evpn_tenant_config_path" alias = "evpn_tenant" included_fields = "path,parent_path,display_name,id,mappings" }, @{ resource_type = "GenericPolicyRealizedResource" join_condition = "intent_paths:path" alias = "GenericPolicyRealizedResource" }, @{ resource_type = "Tier1Interface OR Tier0Interface" join_condition = "segment_path:path" alias = "interfaces" size = 0 }, @{ resource_type = "Ipv6NdraProfile" join_condition = "path:$0.ipv6_profile_paths" alias = "gatewayNdraProfile" included_fields = "path,parent_path,display_name,id" }, @{ resource_type = "Alarm" join_condition = "alarm_source:path" alias = "alarms_Segment" included_fields = "alarm_source,severity,status" } ) } $body = $body | ConvertTo-Json -Depth 10 try { $response = Invoke-APIRequest -method "POST" ` -url $segmenturl ` -body $body ` -avsnsxtUrl $avsnsxTmanager ` -avsnsxtUserName $nsxtUserName ` -avsnsxtPassword $nsxtPassword $segment = $response.results | Where-Object { $_.primary -and $_.primary.display_name -and $_.primary.display_name -eq $segmentName } | Select-Object -ExpandProperty primary | Select-Object -ExpandProperty subnets | Select-Object -ExpandProperty network if ($null -eq $segment) { return $false }else { return $segment } } catch { Write-Error "Failed to get NSX-T Segment: $_" return $false } } function New-Segment { param( [string]$avsnsxTmanager, [string]$nsxtUserName, [SecureString]$nsxtPassword, [string]$tier1GatewayName, [string]$segmentName, [string]$dnsServerAddress, [string]$dhcpProfilePath ) $transportZonePath = Get-TransportZone_Path -avsnsxTmanager $avsnsxTmanager ` -nsxtUserName $nsxtUserName ` -nsxtPassword $nsxtPassword $segmentConfig = New-SegmentConfig -dnsAddress $dnsServerAddress if ($null -eq $transportZonePath -or $null -eq $segmentConfig) { Write-Error "Failed to create NSX-T Segment: Invalid transport zone path or DHCP configuration." return } $newsegmenturl = "$avsnsxTmanager/policy/api/v1/infra?enforce_revision_check=true" $segmentDetails = @{ resource_type = "Segment" display_name = $segmentName subnets = @( @{ gateway_address = $segmentConfig.Gateway_Address dhcp_ranges = @($segmentConfig.DHCP_Ranges) dhcp_config = @{ resource_type = "SegmentDhcpV4Config" lease_time = 86400 dns_servers = @($dnsServerAddress, "1.1.1.1") } } ) replication_mode = "MTEP" transport_zone_path = $transportZonePath admin_state = "UP" advanced_config = @{ address_pool_paths = @() multicast = $true urpf_mode = "STRICT" connectivity = "ON" } connectivity_path = "/infra/tier-1s/$tier1GatewayName" id = $segmentName } $body = @{ resource_type = "Infra" children = @( @{ resource_type = "ChildSegment" Segment = $segmentDetails } ) } $jsonBody = $body | ConvertTo-Json -Depth 10 #write-host $jsonBody try { $response = Invoke-APIRequest -method "PATCH" ` -url $newsegmenturl ` -avsnsxtUrl $avsnsxTmanager ` -avsnsxtUserName $nsxtUserName ` -avsnsxtPassword $nsxtPassword ` -body $jsonBody if ($null -eq $response) { Write-Error "Failed to create NSX-T Segment." }elseif ($null -ne $response) { Write-Host "NSX-T Segment '$segmentName' created successfully." return $segmentConfig.Gateway_Address } } catch { Write-Error "Failed to create NSX-T Segment: $_" } } function New-SegmentConfig { param ( [string]$dnsAddress ) try { # Extract the base network address and subnet mask $originalNetwork = $dnsAddress $prefixLength = 24 # Generate a new network address that does not overlap with the original network $newNetworkBytes = [System.Net.IPAddress]::Parse($originalNetwork).GetAddressBytes() $newNetworkBytes[2] = ($newNetworkBytes[2] + 1) % 256 # Change the third octet to ensure a different network $newNetwork = [System.Net.IPAddress]::new($newNetworkBytes).ToString() # Calculate the gateway address (first address in the new subnet) $gatewayAddress = "$($newNetwork.Split('.')[0..2] -join '.').1/$prefixLength" # Calculate the DHCP range for the new network $dhcpServerIP = [System.Net.IPAddress]::Parse($newNetwork) $dhcpServerBytes = $dhcpServerIP.GetAddressBytes() # DHCP range (excluding the gateway address) $dhcpServerBytes[3] = 2 $dhcpRangeStart = [System.Net.IPAddress]::new($dhcpServerBytes) $dhcpServerBytes[3] = 254 $dhcpRangeEnd = [System.Net.IPAddress]::new($dhcpServerBytes) $dhcpRange = "$dhcpRangeStart-$dhcpRangeEnd" return @{ Gateway_Address = $gatewayAddress DHCP_Ranges = @($dhcpRange) } } catch { Write-Error "Failed to calculate DHCP configuration: $_" return $null } } function Get-TransportZone_Path { param( [string]$avsnsxTmanager, [string]$nsxtUserName, [SecureString]$nsxtPassword ) $transportZonePathUrl = "$avsnsxTmanager/policy/api/v1/infra/sites/default/" + "enforcement-points/default/transport-zones" try { $response = Invoke-APIRequest -method "Get" ` -url $transportZonePathUrl ` -avsnsxtUrl $avsnsxTmanager ` -avsnsxtUserName $nsxtUserName ` -avsnsxtPassword $nsxtPassword if ($null -eq $response -or $null -eq $response.results -or $response.results.Count -eq 0) { return $null } foreach ($transportZone in $response.results) { if ($transportZone.description -eq "Overlay Transport Zone") { return $transportZone.path } } } catch { Write-Error "Failed to get NSX-T Transport Zone Path: $_" return $null } }