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.
Great posst thankyou
LikeLike
Where do the NeighborID1 variable values come from?
LikeLike
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.
LikeLike
Hi Rutger,
One question:
Is there the idempotency avaiable in this modules and others or not?
Thanks
Giovanni
LikeLike
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.
LikeLike