HomeGuidesAPI Reference
GuidesAPI ReferenceGitHubAirheads Developer CommunityLog In
Guides

Day 0 Provisioning

Day 0 provisioning workflows with AOS-CX and Ansible

Let's create a Day 0 provisioning workflow that dynamically generates a device configuration from a template and then pushes the configuration to a switch.

Template, Generate, and Upload

Among the most popular Day 0 processes in networking, this workflow operates as follows:

  • Dynamically generate a configuration for a switch from a Jinja2 template
  • Instruct the device to TFTP-download the resultant configuration to itself

Concepts

  • template module: this module accepts a template and renders an output file.
  • TFTP server: this server hosts files that a switch can download using the TFTP mechanism. This example assumes that the Ansible control machine is also acting as the TFTP server.

Workflow

  1. Create a Jinja2 template. This file should resemble an AOS-CX switch configuration, except with parts of the configuration parametrized using variables. These dynamic fields will be populated when the template is rendered. An easy way to create the template is to first manually configure a device fully using the CLI, then copy that "final" configuration from the switch into a Jinja2 file, and then generalize it using variables. Jinja2 templates should reside in a directory named "templates" and possess the ".j2" file extension.

Examples of AOS-CX templates can be found here:

  • For Spine / Leaf OSPF Fabric:
  • For Spine / VSX Leaf eBGP EVPN VXLAN Fabric:
    • VSX Leaf in eBGP VXLAN DC Fabric
    • Spine in eBGP VXLAN DC Fabric
      hostname {{hostname}}
      !
      !
      !
      ssh server vrf mgmt
      !
      !
      !
      !
      !
      vlan 1
      interface mgmt
          no shutdown
          ip static {{oobm_ip}}/{{oobm_mask}}
          default-gateway {{oobm_default_gateway}}
      system interface-group 1 speed 10g
          !interface group 1 contains ports 1/1/1-1/1/12
      system interface-group 3 speed 10g
          !interface group 3 contains ports 1/1/25-1/1/36
      system interface-group 4 speed 10g
          !interface group 4 contains ports 1/1/37-1/1/48    
      interface {{vsx_ka}} 
          no shutdown
          description VSX KA
      {% if vsx_role == 'primary' %}
          ip address {{vsx_ka_ip_primary}}/31
      {% else %}
          ip address {{vsx_ka_ip_secondary}}/31
      {% endif %}    
      interface {{vsx_isl}} 
          no shutdown
          description VSX ISL
          no routing
          vlan trunk native 1 tag
          vlan trunk allowed all
      interface {{spine1_int}} 
          no shutdown
          description Spine1
          ip address {{spine1_int_ip}}/31
      interface {{spine2_int}} 
          no shutdown
          description Spine2
          ip address {{spine2_int_ip}}/31
      interface loopback 0
          ip address {{loopback0_ip}}/32
      interface loopback 1
          ip address {{loopback1_ip}}/32
      vsx
          inter-switch-link {{vsx_isl}}
          role {{vsx_role}}
      {% if vsx_role == 'primary' %}
          keepalive peer {{vsx_ka_ip_secondary}} source {{vsx_ka_ip_primary}}
      {% else %}
          keepalive peer {{vsx_ka_ip_primary}} source {{vsx_ka_ip_secondary}}
      {% endif %}
          no split-recovery
      router bgp {{asn}}
          bgp router-id {{loopback0_ip}}
          bgp fast-external-fallover
          bgp bestpath as-path multipath-relax
          neighbor {{spine1_a_ip}} remote-as {{spine1_asn}}
          neighbor {{spine1_b_ip}} remote-as {{spine1_asn}}
          neighbor {{spine2_a_ip}} remote-as {{spine2_asn}}
          neighbor {{spine2_b_ip}} remote-as {{spine2_asn}}
          address-family ipv4 unicast
              neighbor {{spine1_a_ip}} activate
              neighbor {{spine1_b_ip}} activate
              neighbor {{spine2_a_ip}} activate
              neighbor {{spine2_b_ip}} activate
              redistribute connected
              network {{loopback0_ip}}/32
              network {{loopback1_ip}}/32
          exit-address-family
      !
      https-server rest access-mode read-write
      https-server vrf mgmt
      hostname Leaf1b
      !
      !
      !
      ssh server vrf mgmt
      !
      !
      !
      !
      !
      vlan 1
      interface mgmt
          no shutdown
          ip static 10.100.1.21/24}
          default-gateway 10.10.10.254
      system interface-group 1 speed 10g
          !interface group 1 contains ports 1/1/1-1/1/12
      system interface-group 3 speed 10g
          !interface group 3 contains ports 1/1/25-1/1/36
      system interface-group 4 speed 10g
          !interface group 4 contains ports 1/1/37-1/1/48
      interface 1/1/22
          no shutdown
          description VSX KA
          ip address 10.1.2.1/31
      interface 1/1/23
          no shutdown
          description VSX ISL
          no routing
          vlan trunk native 1 tag
          vlan trunk allowed all
      interface 1/1/19
          no shutdown
          description Spine1
          ip address 192.168.2.4/31
      interface 1/1/20
          no shutdown
          description Spine2
          ip address 192.168.2.6/31
      interface loopback 0
          ip address 192.168.1.2/32
      interface loopback 1
          ip address 192.168.100.2/32
      vsx
          inter-switch-link 1/1/23
          role secondary
          keepalive peer 10.1.2.0 source 10.1.2.1
          no split-recovery
      router bgp 65001
          bgp router-id 192.168.1.2
          bgp fast-external-fallover
          bgp bestpath as-path multipath-relax
          neighbor 192.168.2.1 remote-as 65101
          neighbor 192.168.2.5 remote-as 65101
          neighbor 192.168.2.3 remote-as 65102
          neighbor 192.168.2.7 remote-as 65102
          address-family ipv4 unicast
              neighbor 192.168.2.1 activate
              neighbor 192.168.2.5 activate
              neighbor 192.168.2.3 activate
              neighbor 192.168.2.7 activate
              redistribute connected
              network 192.168.1.2/32
              network 192.168.100.2/32
          exit-address-family
      !
      https-server rest access-mode read-write
      https-server vrf mgmt
  1. Define any variables required for the template. It is best to define common variables at the group level to avoid unnecessary repetition and promote proper abstraction.

Examples of inventories can be found here:

  1. For Spine / Leaf OSPF Fabric:
    * Inventory file: This is an example in which all the template variables are defined in a single file. Although it's easy to locate the variable-containing file, the file itself is lengthy and somewhat repetitive.

  2. For Spine / VSX Leaf eBGP EVPN VXLAN Fabric:
    * Inventory file: This is an INI-formatted example in which the devices in the environment are grouped, with multiple levels of grouping.
    * Group variable files:

    • group_vars/aoscx_switches
    • group_vars/branch1_dcn_switches
    • group_vars/leafs
    • group_vars/spines
      ##########################
      # EBGP EVPN VXLAN VSX SPINE LEAF FABRIC DEPLOY
      # Example Inventory
      ##########################
      
      [aoscx_switches]
      Spine1 ansible_host=10.100.1.1
      Spine2 ansible_host=10.100.1.2
      Leaf1a ansible_host=10.100.1.11
      Leaf1b ansible_host=10.100.1.21
      Leaf2a ansible_host=10.100.1.12
      Leaf2b ansible_host=10.100.1.22
      Leaf3a ansible_host=10.100.1.13
      Leaf3b ansible_host=10.100.1.23
      
      [branch1_dcn_switches]
      Leaf1a
      Leaf1b
      Leaf2a
      Leaf2b
      Leaf3a
      Leaf3b
      Spine1
      Spine2
      
      [leafs]
      Leaf1a
      Leaf1b
      Leaf2a
      Leaf2b
      Leaf3a
      Leaf3b
      
      [spines]
      Spine1
      Spine2
      ansible_user: admin
      ansible_password: admin
      ansible_net_user: admin
      ansible_net_password: admin
      ansible_connection: local
      config_template: spine.j2
      leaf1b_int: 1/1/43
      leaf1a_int: 1/1/44
      leaf2a_int: 1/1/45
      leaf2b_int: 1/1/46
      leaf3a_int: 1/1/47
      leaf3b_int: 1/1/48
      hostname: Spine2
      oobm_ip: 10.100.1.2
      asn: "{{spine2_asn}}"
      leaf1a_int_ip: 192.168.2.3
      leaf1b_int_ip: 192.168.2.7
      leaf2a_int_ip: 192.168.2.11
      leaf2b_int_ip: 192.168.2.15
      leaf3a_int_ip: 192.168.2.19
      leaf3b_int_ip: 192.168.2.23
      loopback0_ip: 192.168.1.12
      leaf1a_ip: 192.168.2.2
      leaf1b_ip: 192.168.2.6
      leaf2a_ip: 192.168.2.10
      leaf2b_ip: 192.168.2.14
      leaf3a_ip: 192.168.2.18
      leaf3b_ip: 192.168.2.22
  3. Create the Ansible playbook. Write a play and task to render the configuration using the template module, referencing the module documentation page linked in Concepts if necessary. The destination will be the full path to the file wherein the final configuration will be rendered. It is recommended that you validate the generated configuration file by copying its contents onto the switch and checking that the switch reflects the expected state.

    ---
    - hosts: aoscx_switches
      tasks:
        - name: Generate Config from Template for Device
          template: src="leaf.j2" dest="/var/lib/tftpboot/switch_config.conf" mode='0777'
  4. Lastly, add another task, using the aoscx_upload_config module, to make the switch pull the resulting configuration onto itself with TFTP. Since this task calls an AOS-CX module, don't forget to include the role (or collection) in the play!

    ---
    - hosts: aoscx_switches
      roles:
        - role: arubanetworks.aoscx_role
      tasks:
        - name: Generate Config from Template for Device
          template: src="golden_config_template.j2" dest="/var/lib/tftpboot/switch_config.conf" mode='0777'
    
        - name: Copy Config from TFTP Server to Running Config
          aoscx_upload_config:
            config_name: 'running-config'
            remote_config_file_tftp_path: 'tftp://192.168.1.2/switch_config.conf'
            vrf: 'mgmt'

What’s Next

Did this page help you?