Introduction:
This post is a continuation of my experimentation with NSX-T deployment automation, working on a method to quickly deploy typical network topologies for repro and testing. In the first post of this series, we used cURL and JQ to collect NSX-T UUIDs and deploy a new Tier-0 gateway. Now we will look at the steps required to implement a fully functional lab configuration consisting of Tier-0, Tier-1, Segments, DNS, and BGP.
Desired Lab Topology to test NSX-T Deployment Automation
The following lab topology covers a variety of test scenarios. The goal is to use NSX-T Deployment Automation to deploy this setup.
Define site-specific variables
Let’s start by defining some site-specific variables that should help simplify cURL command syntax, and to make the script more generic. We will add these to a Linux shell executable file named “nsx-t-automation.sh”, and will echo them back as a reminder when running the script.
echo "Define site specific variables:" nsxtpasswd='VMware1!VMware1!' echo "NSX-T admin password: $nsxtpasswd" nsxtvip="nsxtmgr.core.hypervizor.com" echo "NSX-T FQDN: $nsxtvip"
Collect required site-specific UUIDs
Some UUIDs are required for the creation of the topology, such as transport zone and edge cluster UUIDs, and are collected using cIRL and JQ. There are some assumptions made in this example, that transport zones and an edge cluster exist. Keep in mind that these could have been created as part of the automation process, and that this example is for illustrative purposes.
echo "" echo "Collect site specific IDs:" overlay_transport_zone_id=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/policy/api/v1/infra/sites/default/enforcement-points/default/transport-zones" | jq -r '.results[0].id') echo "Overlay Transport Zone ID: $overlay_transport_zone_id" vlan_transport_zone_id=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/policy/api/v1/infra/sites/default/enforcement-points/default/transport-zones" | jq -r '.results[1].id') echo "VLAN Transport Zone ID: $vlan_transport_zone_id" edge_cluster_id=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/api/v1/edge-clusters" | jq -r '.results[].id') echo "Edge Cluster ID: $edge_cluster_id" edge_node_0=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/api/v1/edge-clusters" | jq -r '.results[0].members[0].transport_node_id') echo "Edge Node 0: $edge_node_0" edge_node_1=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/api/v1/edge-clusters" | jq -r '.results[0].members[1].transport_node_id') echo "Edge Node 1: $edge_node_1"
Step 1: Create an External Segment
We will add an external segment using the UI, and then use curl to review the resulting configuration in JSON format. This is a good approach as you get more familiar with the NSX-T REST API.
Notice that to create the external segment, the following parameters are required:
- Segment Name
- Transport Zone
- VLAN
Use curl to review the resulting configuration in JSON format.
curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/policy/api/v1/infra/segments" | jq '.'
Once again, notice that to create the external segment, the following parameters are required:
- Segment Name: external-segment
- Transport Zone: 80a2b6a0-d2d1-4b0a-a42e-7dcb9a6f2d62: $vlan_transport_zone_id was collected earlier
- VLAN: 0
Also notice that some sections, such as advanced_config are default and optional, so they don’t need to be specified in the creation of the external segment.
Here is the resulting cURL command to create the external segment, where we use $vlan_transport_zone_id collected earlier, and the three required parameters:
echo "Step 1: Create External Segment" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"type": "DISCONNECTED","vlan_ids": ["0"],"transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/'"$vlan_transport_zone_id"'"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/segments/external-segment" external_segment_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/segments/external-segment" | jq -r '.id') echo "External segment id: $external_segment_id"
PUT or PATCH, that is the question:
Notice that in the creation of the external segment we used the PATCH command. This could also have been performed using a PUT. The PATCH and PUT can both be used to create or update a segment, expect that PUT has some additional overhead, where the “_revision” property must be specified. In order to prevent one client from overwriting another client’s updates, NSX-T employs a technique called optimistic concurrency control. In the sample NSX-T automation script for the lab environment, we are not concerned with multiple REST API clients, so a more simple PATCH will suffice.
Step 2: Create Tier-0 Gateway
Now that we ‘ve established an approach in creating an object in detail, we will continue to add NSX-T objects.
echo "Step 2: Create Tier-0 Gateway" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"transit_subnets": ["100.64.0.0/16"],"internal_transit_subnets": ["169.254.0.0/24"]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0"
Step 3: Instantiate Tier-0 on Edge Cluster, and configure route redistribution
echo "Step 3: Instantiate Tier-0 on Edge Cluster, and configure route redistribution" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"route_redistribution_types": [ "TIER1_CONNECTED", "TIER0_CONNECTED" ],"edge_cluster_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default"
Step 4: Add two uplink interfaces to Tier-0
echo "Step 4: Add two uplink interfaces to Tier-0" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"edge_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'/edge-nodes/'"$edge_node_1"'","segment_path": "/infra/segments/external-segment","type": "EXTERNAL","subnets": [ {"ip_addresses": ["192.168.100.102"],"prefix_len": 24}]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/interfaces/external-uplink1" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"edge_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'/edge-nodes/'"$edge_node_0"'","segment_path": "/infra/segments/external-segment","type": "EXTERNAL","subnets": [ {"ip_addresses": ["192.168.100.103"],"prefix_len": 24}]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/interfaces/external-uplink2"
Step 5: Change Tier-0 BGP AS
echo "Step 5: Change Tier-0 BGP AS" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"local_as_num": "65111"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/bgp"
Step 6: Add BGP Peer
echo "Step 6: Add BGP Peer" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"neighbor_address": "192.168.100.2","remote_as_num": "65100","out_route_filters": ["/infra/tier-0s/lab-tier-0/prefix-lists/prefixlist-out-default"]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/bgp/neighbors/peer1"
Step 7: Create DHCP Server
echo "Step 7: Create DHCP Server" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"server_address": "192.168.60.1/24","edge_cluster_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'","lease_time": 86400}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/dhcp-server-configs/DHCP_Server"
Step 8: Create Tier-1 Gateway, and configure route redistribution
echo "Step 8: Create Tier-1 Gateway, and configure route redistribution" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"tier0_path": "/infra/tier-0s/lab-tier-0","failover_mode": "NON_PREEMPTIVE","enable_standby_relocation": false,"dhcp_config_paths": ["/infra/dhcp-server-configs/DHCP_Server"],"route_advertisement_types": ["TIER1_CONNECTED","TIER1_IPSEC_LOCAL_ENDPOINT"]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-1s/lab-tier-1"
Step 9: Instantiate Tier-1 in Edge Cluster
echo "Step 9: Instantiate Tier-1 in Edge Cluster" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"edge_cluster_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-1s/lab-tier-1/locale-services/default"
Step 10: Add Tier-1 Segment
echo "Step 10: Add Tier-1 Segment" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"type": "ROUTED","subnets": [{"gateway_address": "192.168.70.1/24","dhcp_ranges": ["192.168.70.100-192.168.70.199"], "network": "192.168.70.0/24"}],"connectivity_path": "/infra/tier-1s/lab-tier-1","transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/'"$overlay_transport_zone_id"'"}}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/segments/seg1" echo "All Done!" echo ""
Putting it all together, the completed Linux shell executable
I’ve added a GET after each PATCH command to verify on each step that the object was successfully completed.
echo "" echo "This script tested on NSX-T 2.5.0 and 2.5.1" echo "Define site specific variables:" nsxtpasswd='VMware1!VMware1!' echo "NSX-T admin password: $nsxtpasswd" nsxtvip="nsxtmgr.core.hypervizor.com" echo "NSX-T FQDN: $nsxtvip" echo "" echo "Collect site specific IDs:" overlay_transport_zone_id=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/policy/api/v1/infra/sites/default/enforcement-points/default/transport-zones" | jq -r '.results[0].id') echo "Overlay Transport Zone ID: $overlay_transport_zone_id" vlan_transport_zone_id=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/policy/api/v1/infra/sites/default/enforcement-points/default/transport-zones" | jq -r '.results[1].id') echo "VLAN Transport Zone ID: $vlan_transport_zone_id" edge_cluster_id=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/api/v1/edge-clusters" | jq -r '.results[].id') echo "Edge Cluster ID: $edge_cluster_id" edge_node_0=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/api/v1/edge-clusters" | jq -r '.results[0].members[0].transport_node_id') echo "Edge Node 0: $edge_node_0" edge_node_1=$(curl --silent -k -u admin:$nsxtpasswd -X GET "https://$nsxtvip/api/v1/edge-clusters" | jq -r '.results[0].members[1].transport_node_id') echo "Edge Node 1: $edge_node_1" echo "" echo "Step 1: Create External Segment" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"type": "DISCONNECTED","vlan_ids": ["0"],"transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/'"$vlan_transport_zone_id"'"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/segments/external-segment" external_segment_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/segments/external-segment" | jq -r '.id') echo "External segment ID: $external_segment_id" echo "" echo "Step 2: Create Tier-0 Gateway" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"transit_subnets": ["100.64.0.0/16"],"internal_transit_subnets": ["169.254.0.0/24"]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0" tier_0_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0" | jq -r '.id') echo "Tier-0 ID: $tier_0_id" echo "" echo "Step 3: Instantiate Tier-0 on Edge Cluster, and configure route redistribution" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"route_redistribution_types": [ "TIER1_CONNECTED", "TIER0_CONNECTED" ],"edge_cluster_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default" tier_0_clutser_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default" | jq -r '.edge_cluster_path') echo "Tier-0 Cluster ID: $tier_0_clutser_id" echo "" echo "Step 4: Add two uplink interfaces to Tier-0" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"edge_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'/edge-nodes/'"$edge_node_1"'","segment_path": "/infra/segments/external-segment","type": "EXTERNAL","subnets": [ {"ip_addresses": ["192.168.100.102"],"prefix_len": 24}]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/interfaces/external-uplink1" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"edge_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'/edge-nodes/'"$edge_node_0"'","segment_path": "/infra/segments/external-segment","type": "EXTERNAL","subnets": [ {"ip_addresses": ["192.168.100.103"],"prefix_len": 24}]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/interfaces/external-uplink2" external_uplink1_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/interfaces/external-uplink1" | jq -r '.id') echo "External Uplink1 ID: $external_uplink1_id" external_uplink2_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/interfaces/external-uplink2" | jq -r '.id') echo "External Uplink2 ID: $external_uplink2_id" echo "" echo "Step 5: Change Tier-0 BGP AS" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"local_as_num": "65111"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/bgp" BGP_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/bgp" | jq -r '.id') echo "BGP ID: $BGP_id" echo "" echo "Step 6: Add BGP Peer" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"neighbor_address": "192.168.100.2","remote_as_num": "65100","out_route_filters": ["/infra/tier-0s/lab-tier-0/prefix-lists/prefixlist-out-default"]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/bgp/neighbors/peer1" BGP_peer_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-0s/lab-tier-0/locale-services/default/bgp/neighbors/peer1" | jq -r '.id') echo "BGP Peer ID: $BGP_peer_id" echo "" echo "Step 7: Create DHCP Server" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"server_address": "192.168.60.1/24","edge_cluster_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'","lease_time": 86400}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/dhcp-server-configs/DHCP_Server" dhcp_server_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/dhcp-server-configs/DHCP_Server"| jq -r '.id') echo "DHCP Server ID: $dhcp_server_id" echo "" echo "Step 8: Create Tier-1 Gateway, and configure route redistribution" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"tier0_path": "/infra/tier-0s/lab-tier-0","failover_mode": "NON_PREEMPTIVE","enable_standby_relocation": false,"dhcp_config_paths": ["/infra/dhcp-server-configs/DHCP_Server"],"route_advertisement_types": ["TIER1_CONNECTED","TIER1_IPSEC_LOCAL_ENDPOINT"]}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-1s/lab-tier-1" tier_1_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-1s/lab-tier-1" | jq -r '.id') echo "Tier-1 ID: $tier_1_id" echo "" echo "Step 9: Instantiate Tier-1 in Edge Cluster" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"edge_cluster_path": "/infra/sites/default/enforcement-points/default/edge-clusters/'"$edge_cluster_id"'"}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/tier-1s/lab-tier-1/locale-services/default" tier_1_clutser_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/tier-1s/lab-tier-1/locale-services/default" | jq -r '.edge_cluster_path') echo "Tier-1 Cluster ID: $tier_1_clutser_id" echo "" echo "Step 10: Add Tier-1 Segment" curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -d '{"type": "ROUTED","subnets": [{"gateway_address": "192.168.70.1/24","dhcp_ranges": ["192.168.70.100-192.168.70.199"], "network": "192.168.70.0/24"}],"connectivity_path": "/infra/tier-1s/lab-tier-1","transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/'"$overlay_transport_zone_id"'"}}' -X PATCH "https://$nsxtvip/policy/api/v1/infra/segments/seg1" tier1_segment_id=$(curl --silent -k -u admin:$nsxtpasswd -H "Content-Type: application/json" -X GET "https://$nsxtvip/policy/api/v1/infra/segments/seg1"| jq -r '.id') echo "Tier-1 Segment ID: $tier1_segment_id" echo "" echo "All Done!" echo ""
Running the completed Linux shell executable
We are starting without any networking objects:
Add execute permissions to the Linux shell executable: chmod +x nsx-t-automation.sh Run the Linux shell executable ./nsx-t-automation.sh This script tested on NSX-T 2.5.0 and 2.5.1 Define site specific variables: NSX-T admin password: VMware1!VMware1! NSX-T FQDN: nsxtmgr.core.hypervizor.com Collect site specific IDs: Overlay Transport Zone ID: 68b56dac-09ac-4155-af2e-7f43419cbf0f VLAN Transport Zone ID: d325d53e-eab6-4afe-953d-5d87637cc98a Edge Cluster ID: 6d73abe2-8233-4d76-9290-6bd66999b198 Edge Node 0: d1de934a-0968-11ea-af85-0050569657e0 Edge Node 1: 0d249652-0969-11ea-b387-00505696c478 Step 1: Create External Segment External segment ID: external-segment Step 2: Create Tier-0 Gateway Tier-0 ID: lab-tier-0 Step 3: Instantiate Tier-0 on Edge Cluster, and configure route redistribution Tier-0 Cluster ID: /infra/sites/default/enforcement-points/default/edge-clusters/6d73abe2-8233-4d76-9290-6bd66999b198 Step 4: Add two uplink interfaces to Tier-0 External Uplink1 ID: external-uplink1 External Uplink2 ID: external-uplink2 Step 5: Change Tier-0 BGP AS BGP ID: bgp Step 6: Add BGP Peer BGP Peer ID: peer1 Step 7: Create DHCP Server DHCP Server ID: DHCP_Server Step 8: Create Tier-1 Gateway, and configure route redistribution Tier-1 ID: lab-tier-1 Step 9: Instantiate Tier-1 in Edge Cluster Tier-1 Cluster ID: /infra/sites/default/enforcement-points/default/edge-clusters/6d73abe2-8233-4d76-9290-6bd66999b198 Step 10: Add Tier-1 Segment Tier-1 Segment ID: seg1 All Done!
After running the NSX-T automation script, the basic topology has been successfully deployed:
Upcoming in NSX-T Deployment Automation – Part 3
This completes Part 2 of NSX-T Deployment Automation, the steps required to implement a fully functional lab configuration consisting of Tier-0, Tier-1, Segments, DNS, and BGP. In the future, we will look at tieing similar steps together with an Ansible Playbook.