Create NSX-T Tier-0 Gateway using Policy API

Share this:

Some Background

The fact that you have ended up reading this Blog Post, most probably means you are very aware of what the Policy API is, how cool and flexible it is, how you can use a declarative approach to define things and just run one API call to create it all. Sounds just simple and awesome right?

If only it was as simple to find a good reference guide on how exactly to do things, as looking through NSX-T REST API guide can be a bit complex. And in general there are not many Policy API related guides available on the Internet. Some videos on Youtube, couple of blog posts, some recorded VMworld sessions, and then there is this document, which, IMHO, is one of the best, if not the best, sources of information. (I hope they will keep it up to date!)

That document explains how to work with the Policy API structure, and even has some nice examples on how you can create a Tier-0 (almost), Tier-1, some segments and Firewall rules.

One thing it is missing though, is detailed instructions on how to create a real Tier-0. I mean, it explains how to create Tier-0 as an object in NSX-T, but it is not showing how to initiate the SR component of Tier-0, place Tier-0 in correct Edge Node Cluster, how to attach Uplinks to it, and so on. Realistically, how many times have you seen a Tier-0 deployed without any uplinks?

My guess is that, it is not covered in that doc, because the approach to do it falls a bit out of Policy API “idea” and its declarative nature. You will see what I mean below.

Requirements and Use Case

OK, so what are we creating here today? A Tier-0 gateway with following:

  • T0 running in Active/Standby mode on a two node Edge Node Cluster
  • SR component initiated on both Edge Nodes
  • Uplinks configured on both Edge Nodes (IP/Subnet)
  • Default Gateway configured

Unfortunately, we cannot do this all in one go using Policy API declarative model. We will have to pre-create certain things.

  1. We need to pre-create objects to connect our uplinks to. These can be either Distributed Port Groups, or VLAN based Segments (as in my case here)
  2. We need existing Edge Nodes which are part of an Edge Node Cluster.

I will assume you have the points above already in place, and will not describe those, but, if you will need help, just let me know down in the comments. Maybe you can also take a look on my previous post about Creating Segments using Policy API.

API Call

As you know, most of the creation actions in Policy API are using PATCH method. that is true also in this case. So you need to run a REST API call with PATCH method to the infra endpoint.

PATCH https://{{nsx_manager_ip}}/policy/api/v1/infra

JSON Payload

{
  "resource_type":"Infra",
  "children":[
    {
      "resource_type":"ChildTier0",
      "marked_for_delete":"false",
      "Tier0":{
        "resource_type":"Tier0",
        "id":"{{t0_name_id}}",
        "ha_mode":"ACTIVE_STANDBY",
        "children":[
          {
            "resource_type":"ChildLocaleServices",
            "LocaleServices":{
              "edge_cluster_path":"/infra/sites/default/enforcement-points/default/edge-clusters/{{edge_cluster_id}}",
              "resource_type":"LocaleServices",
              "id":"{{t0_name_id}}-SR",
              "children":[
                {
                  "Tier0Interface":{
                    "edge_path":"/infra/sites/default/enforcement-points/default/edge-clusters/{{edge_cluster_id}}/edge-nodes/{{edge_cluster_member_1_id}}",
                    "segment_path":"/infra/segments/{{t0_uplink_ls_name}}",
                    "type":"EXTERNAL",
                    "resource_type":"Tier0Interface",
                    "id":"{{t0_uplink1_name}}",
                    "display_name":"{{t0_uplink1_name}}",
                    "children":[],
                    "marked_for_delete":false,
                    "subnets":[
                      {
                        "ip_addresses":[
                          "{{t0_uplink1_ip}}"
                        ],
                        "prefix_len":"{{t0_uplinks_subnetmask}}"
                      }
                    ]
                  },
                  "resource_type":"ChildTier0Interface",
                  "marked_for_delete":false
                },
                {
                  "Tier0Interface":{
                    "edge_path":"/infra/sites/default/enforcement-points/default/edge-clusters/{{edge_cluster_id}}/edge-nodes/{{edge_cluster_member_2_id}}",
                    "segment_path":"/infra/segments/{{t0_uplink_ls_name}}",
                    "type":"EXTERNAL",
                    "resource_type":"Tier0Interface",
                    "id":"{{t0_uplink2_name}}",
                    "display_name":"{{t0_uplink2_name}}",
                    "children":[],
                    "marked_for_delete":false,
                    "subnets":[
                      {
                        "ip_addresses":[
                          "{{t0_uplink2_ip}}"
                        ],
                        "prefix_len":"{{t0_uplinks_subnetmask}}"
                      }
                    ]
                  },
                  "resource_type":"ChildTier0Interface",
                  "marked_for_delete":false
                }
              ]
            }
          },
          {
            "resource_type":"ChildStaticRoutes",
            "marked_for_delete":false,
            "StaticRoutes":{
              "network":"0.0.0.0/0",
              "next_hops":[
                {
                  "ip_address":"{{t0_uplinks_default_gw}}",
                  "admin_distance":1
                }
              ],
              "resource_type":"StaticRoutes",
              "id":"Default",
              "display_name":"Default",
              "children":[],
              "marked_for_delete":false
            }
          }
        ]
      }
    }
  ]
}

Note: Starting NSX-T 3.1 this API changed a bit. The edge_path field does not need to include Edge Node ID any more, it only needs Cluster ID and Edge Node identifier in the end (0 or 1 in case of two node cluster) instead of full Edge Node ID. In versions prior to 3.1 you will need to fetch full Edge Node ID using another API call or using GUI

I used Jinja2 templating in the payload, so make sure to replace the variables with the right values for your environment.

If you are using Postman, this can be simply done using the built in Postman environment variables. Below, you can find the Postman Variables file which can be imported and edited.

Postman variable file

{
	"id": "ee339eb3-21f9-4002-98ea-58bdf3b6e6a1",
	"name": "Create_T0",
	"values": [
		{
			"key": "t0_name_id",
			"value": "",
			"enabled": true
		},
		{
			"key": "edge_cluster_member_1_id",
			"value": "0",
			"enabled": true
		},
		{
			"key": "edge_cluster_member_2_id",
			"value": "1",
			"enabled": true
		},
		{
			"key": "t0_uplink_ls_name",
			"value": "",
			"enabled": true
		},
		{
			"key": "t0_uplink1_name",
			"value": "",
			"enabled": true
		},
		{
			"key": "t0_uplink1_ip",
			"value": "",
			"enabled": true
		},
		{
			"key": "t0_uplink2_name",
			"value": "",
			"enabled": true
		},
		{
			"key": "t0_uplink2_ip",
			"value": "",
			"enabled": true
		},
		{
			"key": "t0_uplinks_default_gw",
			"value": "",
			"enabled": true
		},
		{
			"key": "t0_uplinks_subnetmask",
			"value": "",
			"enabled": true
		},
		{
			"key": "edge_cluster_id",
			"value": "",
			"enabled": true
		}
	],
	"_postman_variable_scope": "environment",
	"_postman_exported_at": "2019-12-27T13:59:59.430Z",
	"_postman_exported_using": "Postman/7.14.0"
}

Result

As a result you will have a Tier-0 Gateway, with Uplink on Edge nodes 1 and 2 running in an active/Standby HA mode on Edge Node Cluster. From here you can start creating Tier-1 gateways or Segments and connecting those to this Tier-0.

Actually, if you will want to take one step further, you can call this REST API call from any automation tool or any programming language out there, and automate creation of Tier-0 gateways. I have it done using Ansible for example. Let me know if you are interested to see it.

Is there any other object you are having troubles creating using NSX-T APIs? Let me know, maybe I have already figured it out.

Special thanks to Jack (@jackcherkas) for reviewing this blog post and helping me tune it.

The following two tabs change content below.
Aram Avetisyan is an IT specialist with more than 18 years experience. He has rich background in various IT related fields like Cloud, Virtualization and SDN. He holds several industry level certifications including but not limited to VCIX-DCV, VCIX-NV. He is also a vEXPERT in years 2014-2021.

About Aram Avetisyan

Aram Avetisyan is an IT specialist with more than 18 years experience. He has rich background in various IT related fields like Cloud, Virtualization and SDN. He holds several industry level certifications including but not limited to VCIX-DCV, VCIX-NV. He is also a vEXPERT in years 2014-2021.
Bookmark the permalink.

One Comment

  1. Pingback: Automating (NSX-T) REST API using Ansible URI module - The Virtualist

Leave a Reply

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