Quick Tip – Ansible Module “nsxt_rest”

Posted by

There are Ansible modules for configuring most of the NSX-T platform components, but for certain configuration tasks it might be quicker (or even necessary) to GET/POST/PUT/PATCH/DELETE to the NSX-T REST API directly.

Now, in those situations you could use curl or Postman or any of the other REST API clients out there, but if you would actually prefer to stay within your Ansible system instead of doing “quick and dirties” that aren’t documented, traceable, or reusable, the “nsxt_rest” module could be an interesting alternative.

The “nsxt_rest” module is part of the official Ansible NSX-T modules that is maintained by VMware. The module gives you direct access to the NSX-T REST API and basically lets you configure anything you can configure through the NSX-T REST API. In other words, this is the only module you will ever need. 😉

Example

I recently had to test and re-test Tier-0 route filtering settings in different environments. I used the opportunity to create a simple Ansible Playbook with some tasks using the “nsxt_rest” module. This Playbook is maintained on GitHub, but I will post a static version of it here just for reference:

---
- hosts: localhost
  name: ConfigureEgress.yml
  vars:
    NsxManagerAddress:     pod-220-nsxt-lm-1.sddc.lab                  # FQDN or IP address of your NSX Manager
    NsxManagerUser:        admin                                       # NSX Manager username
    NsxManagerPassword:    VMware1!VMware1!                            # NSX Manager password
    Tier0:                 T0-Gateway-01                               # Name of the Tier-0 Gateway
    LocalAs:               65001                                       # ASN on the NSX side
    RemoteAs:              65000                                       # ASN on the physical router side
    Prefix1:               any                                         # Name of the "Any" prefix
    Prefix2:               default-route                               # Name of the "Default Route" prefix                  
    RouteMapIn:            rm-in                                       # Name of the route map that is applied to the "In" filter
    RouteMapOut:           rm-out                                      # Name of the route map that is applied to the "Out" filter
    NeighborID1:           101eeb51-c0e7-41b3-b56a-5d8df4c29226        # ID of BGP neighbor #1 entry that should be configured with the filters
    NeighborIP1:           10.203.236.1                                # IP address of BGP neighbor #1 that should be configured with the filters
    NeighborID2:           d56e1a6f-d125-448a-8753-ca4b53bbf4bc        # ID of BGP neighbor #2 entry that should be configured with the filters
    NeighborIP2:           10.203.237.1                                # IP address of BGP neighbor #2 that should be configured with the filters
  tasks:

  
    - name: Create prefix lists for "Any" and "Default Route"
      nsxt_rest:
        hostname: "{{ NsxManagerAddress }}"
        username: "{{ NsxManagerUser }}"
        password: "{{ NsxManagerPassword }}"
        validate_certs: false
        method: patch
        path: "/policy/api/v1/infra/tier-0s/{{ Tier0 }}/prefix-lists/{{ item.name }}"
        content:
          {
            "prefixes": [
                {
                    "network": "{{ item.network }}",
                    "action": "{{ item.action }}"
                }
            ]
          }
      loop:
        - { name: "{{ Prefix1 }}", network: "ANY", action: "PERMIT" }
        - { name: "{{ Prefix2 }}", network: "0.0.0.0/0", action: "PERMIT" }


    - name: Create route map for the "In" filter
      nsxt_rest:
        hostname: "{{ NsxManagerAddress }}"
        username: "{{ NsxManagerUser }}"
        password: "{{ NsxManagerPassword }}"
        validate_certs: false
        method: patch
        path: "/policy/api/v1/infra/tier-0s/{{ Tier0 }}/route-maps/{{ RouteMapIn }}"
        content:
          {
             "entries":[
                {
                   "prefix_list_matches":[
                      "/infra/tier-0s/T0-Gateway-01/prefix-lists/{{ Prefix1 }}"
                   ],
                   "set":{
                      "local_preference":90
                   },
                   "action":"PERMIT"
                },
                {
                   "prefix_list_matches":[
                      "/infra/tier-0s/T0-Gateway-01/prefix-lists/{{ Prefix2 }}"
                   ],
                   "set":{
                      "local_preference":80
                   },
                   "action":"PERMIT"
                }
             ]
          }


    - name: Create route map for the "Out" filter 
      nsxt_rest:
        hostname: "{{ NsxManagerAddress }}"
        username: "{{ NsxManagerUser }}"
        password: "{{ NsxManagerPassword }}"
        validate_certs: false
        method: patch
        path: "/policy/api/v1/infra/tier-0s/{{ Tier0 }}/route-maps/{{ RouteMapOut }}"
        content:
          {
             "entries":[
                {
                   "prefix_list_matches":[
                      "/infra/tier-0s/T0-Gateway-01/prefix-lists/{{ Prefix1 }}"
                   ],
                   "set":{
                      "as_path_prepend":"{{ LocalAs }}",
                      "local_preference":100
                   },
                   "action":"PERMIT"
                }
             ]
          }


    - name: Add the filters to the BGP neighbor entries
      nsxt_rest:
        hostname: "{{ NsxManagerAddress }}"
        username: "{{ NsxManagerUser }}"
        password: "{{ NsxManagerPassword }}"
        validate_certs: false
        method: patch
        path: "/policy/api/v1/infra/tier-0s/{{ Tier0 }}/locale-services/{{ Tier0 }}_Locale_Services/bgp/neighbors/{{ item.neighbor }}"
        content:
          {
             "neighbor_address" : "{{ item.ip }}",
             "remote_as_num" : "{{ item.as }}",
             "in_route_filters":[
                "/infra/tier-0s/{{ Tier0 }}/route-maps/{{ RouteMapIn }}"
             ],
             "out_route_filters":[
                "/infra/tier-0s/{{ Tier0 }}/route-maps/{{ RouteMapOut }}"
             ],
             "route_filtering":[
                {
                   "enabled":true,
                   "address_family":"IPV4",
                   "in_route_filters":[
                      "/infra/tier-0s/{{ Tier0 }}/route-maps/{{ RouteMapIn }}"
                   ],
                   "out_route_filters":[
                      "/infra/tier-0s/{{ Tier0 }}/route-maps/{{ RouteMapOut }}"
                   ]
                }
             ]
          }
      loop:
        - { neighbor: "{{ NeighborID1 }}", ip: "{{ NeighborIP1 }}", as: "{{ RemoteAs }}" }
        - { neighbor: "{{ NeighborID2 }}", ip: "{{ NeighborIP2 }}", as: "{{ RemoteAs }}" }

This is looks very similar to using curl commands, except now it’s wrapped in an Ansible Playbook that I can easily check in to some version control system, share, and re-use. I think those are some pretty nice benefits.

Thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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