Automating NDFC using Ansible
This section contains several examples automating Nexus Dashboard Fabric Controller (NDFC) with Ansible. Whilst this example is not part of the Nexus-as-Code data model, it offers more seasoned Ansible users several comprehensive examples to automate the provisioning of Ethernet Virtual Private Network (EVPN) fabrics using NDFC.
Getting started
This repo contains Ansible Roles and example playbooks that, together, implement a basic Spine/Leaf VXLAN/EVPN fabric using Cisco's DCNM/NDFC Controller.
Two identical child fabrics and a multisite domain (MSD) fabric are defined in the role ndfc_common
. The two child fabrics use non-overlapping underlay addressing to facilitate interconnection via a multi-site domain (MSD) fabric, which is also defined in ndfc_common
; specifically, in ndfc_common/vars/main.yml
The main playbooks, which create the two fabrics and the MSD fabric are located in the top-level directory.
Ref |
Playbook |
Description |
1 |
example_ndfc_rest_fabric_switch_create_f1.yml |
creates VXLAN/EVPN fabric f1 without connectivity to an MSD fabric |
2 |
example_ndfc_rest_fabric_switch_create_f2.yml |
creates VXLAN/EVPN fabric f2 without connectivity to an MSD fabric |
3 |
example_ndfc_rest_fabric_msd_create_with_children.yml |
creates VXLAN/EVPN fabrics f1 and f2, connecting them through an MSD fabric |
You should use either (1 and 2) OR 3 (which creates 1 and 2, but with MSD connectivity). That is, (1 and 2) are mutually exclusive to 3.
These playbooks leverage many of the included roles.
The remaining Roles are offered as examples which either provide extra functionality (e.g. create external fabrics, and service nodes) or facilitate various day2 ops, such as deleting a fabric, etc.
To clone this repo
Dependencies
Cisco Nexus Dashboard (ND) + Nexus Dashboard Fabric Controller (NDFC)
ndfc-roles has been tested with the following ND+NDFC versions
Tested |
ND |
NDFC |
Yes |
2.3(2d) |
12.1.2e |
Yes |
2.2(1h) |
12.1.1e |
Yes |
2.1(2d) |
12.0.2f |
cisco.dcnm Ansible Collection Version 2.1.0
The Ansible Roles in this repo require that version 2.1.0 of the cisco.dcnm Collection be installed. A requirements.yml
file is included in the top-level directory which will install this collection. Or you may do so explicitly. It's recommended to use requirements.yml
as this file may be updated with other dependencies later.
NOTE: Some earlier versions of the cisco.dcnm Ansible Collection are known not to work due to NDFC API changes involving VPC interfaces.
Example using requirements.yml
Example using explicit Collection Version 2.1.0
jmespath
The Ansible Roles in this repo make extensive use of json_query()
which requires that jmespath be installed. To install (preferably, you're running Ansible within a python virtual environment):
Ansible Custom Configuration
NDFC requires increasing the default timeout for persistent connections from the default of 30 seconds to >= 1000 seconds. We have provided an ansible.cfg file with the requisite changes in this repo's top-level directory. If you would rather edit your existing ansible.cfg file (where ever it is), the changes are shown below.
Fabric Characteristics
The characteristics of the child/site fabrics are as follows (see also the included PDF for a topology).
- 2 Spine acting as Route Reflectors for all Leaf and Border Gateway
- 4 Leaf / VTEP (2 VPC pairs using fabric-peering for their virtual peer-link)
- 2 Border Gateway / VTEP
- 2 VRF: v1 and v2
- L3 (ipv4 / ipv6) connectivity between VRF v1 and v2 (import/export of route-targets)
- L2 connectivity within each VRF
- OSPF underlay
- VXLAN/EVPN Replication Mode: Ingress
Spines and Leafs can be added/removed by updating the Common Role Variables described below.
Common Role Variables
To use these Roles, and example playbooks, you'll need to update some common variables used across all Roles. These are maintained in inventory/groups_vars.
Inventory
Next, you'll need to edit the following to add your NDFC username and password and the username/password for the switches comprising your fabric(s)
It is recommended (but not mandatory) that you encrypt these passwords. Below is one way to do this.
Modify ./inventory/group_vars/ndfc
Edit ansible_password
(password for NDFC controller) and device_password
(password for NX-OS switches)
Add ansible_password
and device_password
in encrypted format (or non-encrypted, if you don't care about security). These are the passwords you use to login to your NDFC Controller, and NX-OS switches, respectively.
To add encrypted passwords for the NDFC controller and NX-OS devices, issue the following from this repo's top-level directory.
ansible-vault will prompt you for a vault password, which you'll use to decrypt these passwords (using ansible-playbook --ask-vault-pass
) when running the example playbooks.
Example:
If you don't care about security, you can add a non-encrypted password by editing the file directly.
The following are example unencrypted passwords for the NDFC controller and NX-OS devices added to this file:
Edit ansible_user
Change ansible_user
in the same file to the username associated with the above password that you're using on NDFC.
Change device_username
in the same file to the username used to login to your NX-OS switches.
Example:
Update ./inventory/hosts/hosts
with the IP address of your NDFC Controller
To run a playbook if you encrypted your NDFC password
When prompted, enter the password you used in response to the ansible-vault command in step 1 above.
Or, to run a playbook if you didn't encrypt the NDFC password
Roles
Role naming conventions used in this repo.
- If a Role pushes a specific Ansible state, that state is included in the Role's name.
- If a Role requires the user to provide the Ansible state, the Role's name does not include the state.
- If a Role uses the NDFC REST API, its name includes
_rest_
(e.g. ndfc_rest_rediscover
)
Role |
Description |
[ndfc_common] |
Common variables used by all other Roles (update: now part of group_vars) |
ndfc_device_config_get |
Retrieve local configuration for device, given device_name |
ndfc_device_deleted |
Delete a device from a fabric, given device_name |
ndfc_device_deleted_all |
Delete all devices in a fabric, given fabric_name |
ndfc_device_generated_configs_all_get |
Query and display all populated generated_configs on all devices, given fabric_name |
ndfc_device_generated_configs_get |
Retrieve device generated configs, given device_name |
ndfc_device_info_get |
Return info on device from the NDFC controller in var device_info , given device_name |
ndfc_device_interface_config_all_get |
Retrieve and display interface configuration on all devices in a fabric, given fabric_name , interface_name |
ndfc_device_ipv4_address_local_get |
Retrieve device ipv4 address from local vars, given device_name |
ndfc_device_ipv4_address_remote_get |
Retrieve device ipv4 address from NDFC controller, given device_name |
ndfc_device_merged |
Merge a device into the topology, given device_name |
ndfc_device_merged_all |
Merge all devices into a fabric, given fabric_name |
ndfc_device_model_number_get |
Retrieve device model number device_model_number , given device_name |
ndfc_device_serial_number_get |
Retrieve device serial number device_serial_number , given fabric_name , device_name |
ndfc_fabric_config_get |
Retrieve local configuration for fabric, given fabric_name |
ndfc_network_config_get |
Retrieve local configuration for network, given network_name |
ndfc_network_deleted |
Delete a network, given fabric_name , network_name |
ndfc_network_deleted_all |
Delete all networks within a fabric, given fabric_name |
ndfc_network_info_get |
Retrieve network_info dictionary, given network_name |
ndfc_network_replaced |
Replace network on the NDFC controller with its current local definition, given network_name |
ndfc_network_replaced_all |
Replace all networks within a fabric with their current local definitions, given fabric_name |
ndfc_policy_vrf_rt_import_evpn |
Import a vrf's route-targets into another vrf on a single device, given device_name |
ndfc_policy_vrf_rt_import_evpn_loop |
Import a vrf's route-targets into another vrf on a list of devices, given a list of device_name |
ndfc_rest_config_deploy |
NDFC REST API POST calls to config-save and config-deploy for a device, given device_name |
ndfc_rest_config_deploy_all |
NDFC REST API POST calls to config-save and config-deploy for a fabric, given fabric_name |
ndfc_rest_device_list_by_fabric |
Retrieve list of devices in fabric, given fabric_name |
ndfc_rest_device_set_role |
Set a device's role, given device_name , and role |
ndfc_rest_fabric_access_mode_get |
Retrieve a fabric's access mode, given fabric_name |
ndfc_rest_fabric_access_mode_set |
Set a fabric's access mode, given fabric_name , and read_only |
ndfc_rest_fabric_active_fabrics_get |
Queries NDFC controller for list of active fabrics |
ndfc_rest_fabric_asn_get |
Retrieve a fabric's BGP ASN, given fabric_name |
ndfc_rest_fabric_delete |
Delete a fabric, given fabric_name |
[ndfc_rest_fabric_external_create] |
Create an external fabric, given fabric_name |
ndfc_rest_fabric_info_get |
Retrieve a fabric's information from the NDFC controller, given fabric_name |
ndfc_rest_fabric_msd_child_add |
Add a child fabric to an MSD fabric, given child_fabric , and msd_fabric |
ndfc_rest_fabric_msd_child_remove |
Remove a child fabric from an MSD fabric, given child_fabric , and msd_fabric |
[ndfc_rest_fabric_msd_create] |
Create a multi-side domain fabric, given msd_fabric |
[ndfc_rest_fabric_switch_create] |
Create a switch fabric, given fabric_name |
ndfc_rest_interface_no_shutdown |
Administratively no shutdown interface, given device_name , interface_name |
ndfc_rest_interface_shutdown |
Administratively shutdown interface, given device_name , interface_name |
[ndfc_rest_rediscover] |
Rediscover a device, given device_name |
ndfc_rest_service_node_add |
Add a service node, given service_node_name |
ndfc_rest_vpc_create |
Create a VPC pair, given fabric_name , vpc_name |
ndfc_rest_vpc_delete |
Delete a VPC pair, given fabric_name , vpc_name |
ndfc_rest_vrf_list_by_fabric |
Return list of VRFs in a given fabric in var vrf_list , given fabric_name |
ndfc_service_node_deleted |
Delete a service node, given service_node_name |
ndfc_service_node_merged |
Create a service node, given service_node_name |
ndfc_vpc_interface_merged_all |
Create (merge) all vpc interfaces for a vpc pair, given vpc_name |
ndfc_vrf_all |
merge/delete all vrfs in a fabric, given fabric_name |
ndfc_vrf_config_get |
Retrieve local configuration for vrf in json object vrf_config , given vrf_name |
ndfc_vrf_query |
Retrieve NDFC controller configuration for VRF in json object vrf_info , given vrf_name |
ndfc_vrf_replaced |
Update (replaced) a vrf, given vrf_name |