Bookmark this page

Guided Exercise: Implementing Dynamic Routing with OSPF

In this exercise, you will automate the process of configuring dynamic routing with OSPF.

Outcomes

You should be able to:

  • Compose NOS-specific device configuration templates to provide parameterized configuration statements.

  • Perform a play that configures OSPF on network devices.

  • Verify that the outcome is as intended.

Open a terminal window on the workstation VM and change to the ~/proj/ directory.

  1. Compose NOS-specific device configuration templates to provide parameterized configuration statements.

    1. Create a Jinja2 template that constructs statements to configure OSPF on VyOS devices. Create a file named j2/vyos-ospf.j2 with the following content:

      {% for intf in layer3_data[inventory_hostname] %}
      {% if intf.name == 'lo' %}
      set protocols ospf parameters router-id {{ intf.ipv4 | ipaddr('address') }}
      set protocols ospf log-adjacency-changes
      set protocols ospf redistribute connected metric-type 2
      {% if inventory_hostname == 'spine01' or inventory_hostname == 'spine02' %}
      set protocols ospf default-information originate always
      set protocols ospf default-information originate metric 10
      set protocols ospf default-information originate metric-type 2
      {% endif %}
      {% else %}
      set protocols ospf area 0 network {{ intf.ipv4 | ipaddr('network/prefix') }}
      {% endif %}
      {% endfor %}
    2. Create a Jinja2 template that constructs statements to configure OSPF on IOS devices. Create a file named j2/ios-ospf.j2 with the following content: Note the line starting with network may have wrapped; it should end with area 0.

      router ospf 1
      {% for intf in layer3_data[inventory_hostname] %}
      {% if intf.name.startswith('Loopback') %}
       router-id {{ intf.ipv4 | ipaddr('address') }}
      {% else %}
       network {{ intf.ipv4 | ipaddr('network') }} {{ intf.ipv4 | ipaddr('hostmask') }} area 0
      {% endif %}
      {% endfor %}

      Important

      There should be a single, very long line between {% else %} and {% endif %} that starts with a space and the word network and ends with area 0. The line might be wrapped due to length in this student guide.

  2. Perform a play that configures OSPF on network devices.

    1. Compose a playbook that configures OSPF based on data and templates. Create a file named ospf-consolidation.yml with the following content:

      ---
      - name: play that configures OSPF according to data and templates
        hosts: network
        vars:
          vyos_ospf_template: j2/vyos-ospf.j2
          ios_ospf_template: j2/ios-ospf.j2
      
        vars_files:
          - vars/consolidation-data.yml
      
        tasks:
      
        - name: configure ospf on vyos
          vyos_config:
            src: "{{ vyos_ospf_template }}"
            save: True
          when: ansible_network_os == 'vyos'
      
        - name: configure ospf on ios
          ios_config:
            src: "{{ ios_ospf_template }}"
            save_when: changed
          when: ansible_network_os == 'ios'
    2. Check playbook syntax, then perform the play. If you are having trouble, you may refer to http://materials.example.com/full from your workstation.

      [student@workstation proj]$ ansible-playbook --syntax-check \
      > ospf-consolidation.yml
      
      Playbook: ospf-consolidation.yml
      [student@workstation proj]$ ansible-playbook ospf-consolidation.yml
  3. Execute an ad hoc command that displays IP routes on VyOS device spine01.

    [student@workstation proj]$ ansible -m vyos_command \
    > -a "commands='sh ip ro'" spine01
    spine01 | SUCCESS => {
    ...output omitted...
        "stdout_lines": [
            [
                "Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,",
                "       I - ISIS, B - BGP, > - selected route, * - FIB route",
                "",
                "O   0.0.0.0/0 [110/10] via 10.10.5.2, 00:07:07",
                "S>* 0.0.0.0/0 [1/0] via 172.16.2.2, eth5",
                "C>* 10.0.0.1/32 is directly connected, lo",
                "O>* 10.0.0.2/32 [110/20] via 10.10.5.2, eth1, 00:11:03",
                " *           via 10.10.6.2, eth2, 00:11:03",
                "O>* 10.0.0.11/32 [110/20] via 10.10.5.2, eth1, 00:11:03",
                "O>* 10.0.0.12/32 [110/20] via 10.10.6.2, eth2, 00:11:13",
                "O   10.10.5.0/30 [110/10] is directly connected, eth1, 00:12:08",
                "C>* 10.10.5.0/30 is directly connected, eth1",
                "O   10.10.6.0/30 [110/10] is directly connected, eth2, 00:12:08",
                "C>* 10.10.6.0/30 is directly connected, eth2",
                "O>* 10.10.7.0/30 [110/20] via 10.10.5.2, eth1, 00:11:04",
                "O>* 10.10.8.0/30 [110/20] via 10.10.6.2, eth2, 00:11:14",
                "O   10.10.10.0/30 [110/20] via 10.10.5.2, 00:11:04",
                "S>* 10.10.10.0/30 [1/0] via 10.10.5.2, eth1",
                "C>* 127.0.0.0/8 is directly connected, lo",
                "O   172.16.2.0/30 [110/10] is directly connected, eth5, 00:12:07",
                "C>* 172.16.2.0/30 is directly connected, eth5",
                "O>* 172.16.10.0/30 [110/11] via 172.16.2.2, eth5, 00:12:03",
                "O   172.25.250.0/24 [110/20] via 10.10.5.2, 00:11:03",
                "               via 10.10.6.2, 00:11:03",
                "C>* 172.25.250.0/24 is directly connected, eth0",
                "O>* 192.168.10.0/30 [110/20] via 10.10.6.2, eth2, 00:11:14"
            ]
        ]
    }
  4. Execute an ad hoc command that displays IP routes on IOS device cs01.

    [student@workstation proj]$ ansible -m ios_command -a "commands='sh ip ro'" cs01
    cs01 | SUCCESS => {
    ...output omitted...
        "stdout_lines": [
            [
                "Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP",
                "       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area ",
                "       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2",
                "       E1 - OSPF external type 1, E2 - OSPF external type 2",
                "       i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2",
                "       ia - IS-IS inter area, * - candidate default, U - per-user static route",
                "       o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP",
                "       a - application route",
                "       + - replicated route, % - next hop override, p - overrides from PfR",
                "",
                "O*E2 0.0.0.0/0 [110/10] via 172.16.2.1, 00:11:46, GigabitEthernet2",
                "   10.0.0.0/8 is variably subnetted, 8 subnets, 2 masks",
                "O E2 10.0.0.2/32 [110/20] via 172.16.2.1, 00:11:46, GigabitEthernet2",
                "O E2 10.0.0.11/32 [110/20] via 172.16.2.1, 00:11:46, GigabitEthernet2",
                "O E2 10.0.0.12/32 [110/20] via 172.16.2.1, 00:11:46, GigabitEthernet2",
                "O    10.10.5.0/30 [110/11] via 172.16.2.1, 00:11:36, GigabitEthernet2",
                "O    10.10.6.0/30 [110/11] via 172.16.2.1, 00:11:56, GigabitEthernet2",
                "O    10.10.7.0/30 [110/21] via 172.16.2.1, 00:11:36, GigabitEthernet2",
                "O    10.10.8.0/30 [110/21] via 172.16.2.1, 00:11:46, GigabitEthernet2",
                "O    10.10.10.0/30 [110/21] via 172.16.2.1, 00:11:36, GigabitEthernet2",
                "   172.16.0.0/16 is variably subnetted, 5 subnets, 2 masks",
                "C    172.16.0.1/32 is directly connected, Loopback1",
                "C    172.16.2.0/30 is directly connected, GigabitEthernet2",
                "L    172.16.2.2/32 is directly connected, GigabitEthernet2",
                "C    172.16.10.0/30 is directly connected, GigabitEthernet4",
                "L    172.16.10.1/32 is directly connected, GigabitEthernet4",
                "   172.25.0.0/16 is variably subnetted, 2 subnets, 2 masks",
                "C    172.25.250.0/24 is directly connected, GigabitEthernet1",
                "L    172.25.250.195/32 is directly connected, GigabitEthernet1",
                "   192.168.10.0/30 is subnetted, 1 subnets",
                "O    192.168.10.0 [110/21] via 172.16.2.1, 00:11:46, GigabitEthernet2"
                "O    192.168.5.0 [110/11] via 172.16.5.1, 00:03:58, GigabitEthernet3",
                "   192.168.10.0/30 is subnetted, 1 subnets",
                "O    192.168.10.0 [110/21] via 172.16.5.1, 00:03:58, GigabitEthernet3"
            ]
        ]
    }

This concludes the guided exercise.

Revision: do457-2.5-4693601