Variables
Ansible

Ansible NXOS Variables

Under the majority of the role directories you'll notice a ".yml" file. Playbooks are written in a simple markup language called YAML, which stands for YAML Ain't Markup Language. YAML is used as it's even easier to read than data structure formats such as XML or JSON that you have previously examined.

YAML files optionally begin with --- at the top of the file to signify the start of the file. Following the file start, comes the Ansible modules written in YAML syntax. YAML syntax for Ansible modules are expressed as a list of key/value pairs. A list simply begins with a "- " (a dash followed by a space) while, as in previous examples, dictionaries use ":".

Below you can see an example of YAML syntax that contains a list of dictionaries and where the dictionaries contain lists:

    
        - name: CONFIGURE PIM ANYCAST RP
          cisco.nxos.nxos_config:
            lines:
              - ip pim anycast-rp {{ rp_address }} {{ s1_loopback }}
              - ip pim anycast-rp {{ rp_address }} {{ s2_loopback }}

        - name: CONFIGURE PIM RP
          cisco.nxos.nxos_pim_rp_address:
            rp_address: "{{ rp_address }}"
    

In the example above, you were introduced to two things:

  1. cisco.nxos.nxos_config and cisco.nxos.nxos_pim_rp_address which are existing Ansible Network modules from the Cisco NXOS collection.
  2. variables defined using Jinja syntax with the {{ }} brackets and how to use them.

Within the documentation for each network module there is a synopsis of what function the module performs and a table of parameters or keys. The tabulated parameters inform the user which parameters are required for the module to function as a task, which parameters are optional, and what the defaults are for those parameters.

As an example, each of these core network modules have basic requirements for arguments to access the device, albeit, some of these parameters may not apply to the network operating system you work with:

  • host - defines the hostname or IP address of the remote host
  • port - defines the port to connect to
  • username - defines the username to use to authenticate the connection
  • password - defines the password to use to authenticate the connection
  • connection - defines the type of connection transport to build
  • become - enables privilege escalation for devices that require it
  • become_password - defines the password, if needed, for privilege escalation

Ansible allows you to define and reference variables in your playbook tasks using Jinja2 templating; a templating language for Python. A YAML gotcha for Jinja2 is that if you start the line with a Jinja2 templated variable, for example "{{inventory_hostname}}", then the entire line must be in quotes.

Variables can be defined in various locations and Ansible has a precedence system for understanding what and when a variable would be overridden if used in more than one location. The precedence for a variable can be seen below. As an example, a variable in the role defaults directory would be overridden by a variable in the playbook global_vars/all directory and file. Further, both of these are overridden by the local vars directory within the specific role, role vars.

  • role defaults (defined in role/defaults/main.yml)
  • inventory file or script group vars
  • inventory group_vars/all
  • playbook group_vars/all
  • inventory group_vars/*
  • playbook group_vars/*
  • inventory file or script host vars
  • inventory host_vars/*
  • playbook host_vars/*
  • host facts
  • play vars
  • play vars_prompt
  • play vars_files
  • role vars (defined in role/vars/main.yml)
  • block vars (only for tasks in block)
  • task vars (only for the task)
  • role (and include_role) params
  • include params
  • include_vars
  • set_facts / registered vars
  • extra vars (always win precedence)


Step 1 - Create Ansible Config File

Create an ansible.cfg file to disable hostkey checking and set your python interpreter for the purposes of this lab.

    
        touch /home/cisco/Documents/nxapilab/ansible-nxos/ansible.cfg
        cat <<EOF >> /home/cisco/Documents/nxapilab/ansible-nxos/ansible.cfg
        [defaults]
        interpreter_python = /home/cisco/.pyenv/versions/nxapilab/bin/python
        host_key_checking = False

        collections_path = $PYENV_VIRTUAL_ENV/lib/python3.11/site-packages/ansible_collections

        [persistent_connection]
        command_timeout=1000
        connect_timeout=1000
        EOF
        


Step 2 - Create Ansible Global Vars File

Copy the below YAML into the your Terminal window to create the all file and populate contents of the file for the ansible_connection, ansible_network_os, and username/password information used to connect direct to the devices. This all YAML file also contains OSPF parameters and NTP server information that is used across all devices. Again, this is a file with key/value pairs. group_vars/all is where you place universal variables that apply for all devices.

Note

For passwords, it is best practice to leverage something like Ansible Vault. For simplicity, clear text is used.

    
        touch /home/cisco/Documents/nxapilab/ansible-nxos/group_vars/all.yml
        cat <<EOF >> /home/cisco/Documents/nxapilab/ansible-nxos/group_vars/all.yml
        ---
        
        ansible_connection: ansible.netcommon.httpapi
        ansible_httpapi_port: 443
        ansible_httpapi_use_ssl: true
        ansible_httpapi_validate_certs: false
        ansible_network_os: cisco.nxos.nxos
        ansible_user: admin
        ansible_httpapi_pass: cisco.123

        ntp_server: 10.81.254.131

        ospf:
          process_id: UNDERLAY
          area_id: 0.0.0.0
        EOF
        


Ansible Spine Group Vars

Copy the below YAML into the spine role vars directory main.yml file. The variables here will be used to configure specific features for VXLAN EVPN and BGP parameters. Remember, each of these are a dictionary with key/value pairs or a dictionary that contains a list of dictionaries.

    
        touch /home/cisco/Documents/nxapilab/ansible-nxos/group_vars/spines.yml
        cat <<EOF >> /home/cisco/Documents/nxapilab/ansible-nxos/group_vars/spines.yml
        ---
        # var file for spines group

        features:
          - ospf
          - pim
          - bgp
          - nv overlay
          - netconf
          - restconf
        
        bgp:
          asn: 65001
          neighbors:
            - neighbor: 10.0.0.101
              remote_as: 65001
              update_source: loopback0
            - neighbor: 10.0.0.102
              remote_as: 65001
              update_source: loopback0
        EOF
        


Ansible Leaf Group Vars

Copy the below YAML into the leaf role vars directory main.yml file. The variables here will be used to for specific features for VXLAN EVPN, BGP parameters, SVI parameters, and VXLAN parameters, such as tenant VRFs and VLANs mapped to specific VNIs. Remember, each of these are a dictionary with key/value pairs or a dictionary that contains a list of dictionaries.

    
        touch /home/cisco/Documents/nxapilab/ansible-nxos/group_vars/leafs.yml
        cat <<EOF >> /home/cisco/Documents/nxapilab/ansible-nxos/group_vars/leafs.yml
        ---
        # var file for leafs group

        features:
          - ospf
          - pim
          - bgp
          - nv overlay
          - vn-segment-vlan-based
          - interface-vlan
          - netconf
          - restconf

        bgp:
          asn: 65001
          neighbors:
            - neighbor: 10.0.0.1
              remote_as: 65001
              update_source: loopback0

        vrfs:
          - vrf_name: &refvrf_ansiblevrf AnsibleVRF
            vlan_name: *refvrf_ansiblevrf
            vlan_id: 500
            vni_id: 50000

        networks:
          - vrf_name: *refvrf_ansiblevrf
            vlan_name: AnsibleNet1
            vlan_id: 101
            vni_id: 10101
            addr: 192.168.101.1
            mask: 24
            mcast_grp: 239.1.1.1
          - vrf_name: *refvrf_ansiblevrf
            vlan_name: AnsibleNet2
            vlan_id: 102
            vni_id: 10102
            addr: 192.168.102.1
            mask: 24
            mcast_grp: 239.1.1.2
        EOF
        


Step 3 - Create Ansible Host Vars & Role Vars Files

For each role, you are now going to create the variables to be used per device and commonly across all devices specified within the role. The device specific variables will be defined under the host_vars directory for each device. The common variables to be used across all devices will be defined under roles/spine/vars/main.yml and roles/leaf/vars/main.yml respectively.


Ansible Spine1 Host Vars

Copy the below YAML files into the host_vars directory for your Spine1 device. These device specific variables include physical interface information, such as IP addressing, and Loopback interface information for Underlay routing, such as peering, router-id and PIM RP address.

In this YAML file, you will see the use of the anchor and alias feature of YAML. This is a way to reuse pieces of YAML in other parts of a YAML file. Here, you create two different data structures for two different types of layer 3 interfaces. Then, you combine them into a list of layer 3 interfaces.

    
        touch /home/cisco/Documents/nxapilab/ansible-nxos/host_vars/10.15.1.11.yml
        cat <<EOF >> /home/cisco/Documents/nxapilab/ansible-nxos/host_vars/10.15.1.11.yml
        ---
        # vars file for staging-spine1

        hostname: staging-spine1

        layer3_physical_interfaces: &l3
          - interface: Ethernet1/1
            description: To L1 Eth1/11
            ip_address: 10.1.1.0
            mask: 31
            mtu: 9216
          - interface: Ethernet1/2
            description: To L2 Eth1/11
            ip_address: 10.1.1.2
            mask: 31
            mtu: 9216

        loopback_interfaces: &lo
          - interface: loopback0 
            description: Routing Loopback
            ip_address: 10.0.0.1
            mask: 32
          - interface: loopback250
            description: PIM Anycast RP Loopback
            ip_address: 10.250.250.1
            mask: 32

        all_layer3_interfaces:
          - *l3
          - *lo
        EOF
        

Ansible Leaf1 Host Vars

Copy the below YAML files into the host_vars directory for your Leaf1 device. Like your spine device specific variables include physical interface information, such as IP addressing, and Loopback interface information for Underlay routing, such as for peering, router-id, etc and VTEP address.

    
        touch /home/cisco/Documents/nxapilab/ansible-nxos/host_vars/10.15.1.12.yml
        cat <<EOF >> /home/cisco/Documents/nxapilab/ansible-nxos/host_vars/10.15.1.12.yml
        ---
        # vars file for staging-leaf1

        hostname: staging-leaf1

        layer3_physical_interfaces: &l3
          - interface: Ethernet1/10
            description: To S1 Eth1/1
            mode: layer3
            ip_address: 10.1.1.1
            mask: 31
            mtu: 9216

        loopback_interfaces: &lo
          - interface: loopback0
            description: Routing Loopback
            ip_address: 10.0.0.101
            mask: 32
          - interface: loopback1
            description: VTEP Loopback
            ip_address: 10.100.100.101
            mask: 32

        all_layer3_interfaces:
          - *l3
          - *lo
        EOF
        

Ansible Leaf2 Host Vars

Copy the below YAML files into the host_vars directory for your Leaf2 device. Like your spine device specific variables include physical interface information, such as IP addressing, and Loopback interface information for Underlay routing, such as for peering, router-id, etc and VTEP address.

    
        touch /home/cisco/Documents/nxapilab/ansible-nxos/host_vars/10.15.1.13.yml
        cat <<EOF >> /home/cisco/Documents/nxapilab/ansible-nxos/host_vars/10.15.1.13.yml
        ---
        # vars file for staging-leaf2

        hostname: staging-leaf2

        layer3_physical_interfaces: &l3
          - interface: Ethernet1/10
            description: To S1 Eth1/2
            mode: layer3
            ip_address: 10.1.1.3
            mask: 31
            mtu: 9216

        loopback_interfaces: &lo
          - interface: loopback0
            description: Routing Loopback
            ip_address: 10.0.0.102
            mask: 32
          - interface: loopback1
            description: VTEP Loopback
            ip_address: 10.100.100.102
            mask: 32

        all_layer3_interfaces:
          - *l3
          - *lo
        EOF
        


With all your variables in place, continue to the next section to build the tasks for configuring the VXLAN EVPN fabric.