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.

5 comments

    1. From the Tier-0.
      These IDs can be found in different ways. One quick way is by locating the BGP neighbor entries in NSX Manager, click the three vertically aligned dots to the left of a neighbor entry and click “Copy Path to Clipboard”. This path contains the ID.

      Like

      1. Hi Rutger,
        One question:
        Is there the idempotency avaiable in this modules and others or not?
        Thanks
        Giovanni

        Like

      2. Hi, In case you use PATCH as the method it should be idempotent 😉
        As for the other Ansible NSX-T modules they should be handling this properly. In my experience they do.

        Like

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 )

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.