Bookmark this page

Guided Exercise: Configuring and Verifying Specific Device Settings

Write a playbook containing tasks to configure specific settings on specific devices using conditions and loops, and verify the device state before and after configuration.

Outcomes

  • Create a playbook that configures interfaces by looping over variable list items.

As the student user on the workstation machine, use the lab command to prepare your system for this exercise. This command also creates a project directory with the files needed for the exercise.

[student@workstation ~]$ lab start task-loops

Instructions

  1. Open the /home/student/task-loops directory in VS Code and then create the group_vars/ios/interfaces.yml file to store interface information about the Cisco IOS managed nodes.

    1. Open VS Code and click FileOpen Folder.

    2. Navigate to Hometask-loops and click Open.

      Note

      If prompted, select Trust the authors of all files in the parent folder 'student', and then click Yes, I trust the authors.

    3. Create the group_vars/ios/interfaces.yml file with the following content:

      ---
      interfaces:
        iosxe1.lab.example.com:
          - name: Loopback0
            description: Managed by Ansible
            enabled: true
            ipv4: "10.10.10.10/32"
      
          - name: GigabitEthernet2
            description: Managed by Ansible
            enabled: true
            ipv4: "172.25.150.20/24"
      
        iosxe2.lab.example.com:
          - name: Loopback0
            description: Managed by Ansible
            enabled: true
            ipv4: "10.10.20.10/32"
      
          - name: GigabitEthernet2
            description: Managed by Ansible
            enabled: true
            ipv4: "172.25.150.21/24"

      Important

      This step intentionally omits configuring the GigabitEthernet1 interfaces. Configuring the GigabitEthernet1 interfaces incorrectly might result in you being unable to connect to the iosxe1.lab.example.com or iosxe2.lab.example.com managed nodes. If this happens, then you might need to recreate your lab environment.

  2. Create the configure_interfaces.yml playbook in the /home/student/task-loops directory. This playbook loops through the interfaces defined in the group_vars/ios/interfaces.yml file.

    1. Create the configure_interfaces.yml playbook and target managed nodes in the ios inventory group. Add a task to gather interface facts and a second task that displays the content of the ansible_facts['net_interfaces'] variable:

      ---
      - name: Configure Cisco IOS interfaces
        hosts: ios
        gather_facts: false
        tasks:
          - name: Gather interface facts (pre)
            cisco.ios.ios_facts:
              gather_subset:
                - interfaces
      
          - name: Show ansible_facts['net_interfaces'] (pre)
            ansible.builtin.debug:
              var: ansible_facts['net_interfaces']
    2. Add a task to the end of the play that uses the cisco.ios.ios_interfaces module to configure basic interface information. This task must ensure that an interface with the specified name exists. The task might add a description to the interface and either enables or disables the interface.

      ...output omitted...
      
          - name: Configure basic interface information
            when: 1
              - interfaces is defined
              - interfaces[inventory_hostname] is defined
            cisco.ios.ios_interfaces:
              config:
                - name: "{{ item['name'] }}" 2
                  description: "{{ item['description'] | default(omit) }}" 3
                  enabled: "{{ item['enabled'] | default(false) }}" 4
              state: merged
            loop: "{{ interfaces[inventory_hostname] }}" 5

      1

      The playbook implicitly includes variables in the group_vars/ios directory. Because the loop keyword in this task uses the interfaces[inventory_hostname] variable, both the interfaces and the interfaces[inventory_hostname] variables must be defined or Ansible skips running the task. For example, the interfaces['iosxe1.lab.example.com'] variable must be defined or Ansible skips running the task for the iosxe1.lab.example.com managed node.

      2

      The list item must define the name variable.

      3

      If the list item does not define the description variable, then the default filter does not specify a default value. Because of this default filter, Ansible does not generate an error if the description variable is not defined.

      4

      If the list item does not define the enabled variable, then the default filter provides the false Boolean value.

      5

      The task loops through elements of the interfaces variable and uses the inventory_hostname variable to identify each dictionary.

    3. Add a task to the end of the play that uses the cisco.ios.ios_l3_interfaces module to configure IPv4 addresses for the defined interfaces. In addition to the conditions in the previous task, Ansible only runs this second task if the list item defines the ipv4 variable:

      ...output omitted...
      
          - name: Configure L3 interface information
            when:
              - interfaces is defined
              - interfaces[inventory_hostname] is defined
              - item['ipv4'] is defined
            cisco.ios.ios_l3_interfaces:
              config:
                - name: "{{ item['name'] }}"
                  ipv4:
                    - address: "{{ item['ipv4'] }}"
              state: merged
            loop: "{{ interfaces[inventory_hostname] }}"
    4. Add a task to the end of the play that pauses the play for five seconds. This pause allows time for the interface to come up before querying for interface facts again. You only need to run the task once rather that once for each managed node.

      ...output omitted...
          - name: Pause 5 seconds
            ansible.builtin.pause:
              seconds: 5
            run_once: true
    5. Add two tasks to the end of the play to gather interface facts and display the content of the ansible_facts['net_interfaces'] variable. If you copy and paste the first two task in the play, then change pre to post for the final two tasks.

      The entire playbook consists of the following content:

      ---
      - name: Configure Cisco IOS interfaces
        hosts: ios
        gather_facts: false
        tasks:
          - name: Gather interface facts (pre)
            cisco.ios.ios_facts:
              gather_subset:
                - interfaces
      
          - name: Show ansible_facts['net_interfaces'] (pre)
            ansible.builtin.debug:
              var: ansible_facts['net_interfaces']
      
          - name: Configure basic interface information
            when:
              - interfaces is defined
              - interfaces[inventory_hostname] is defined
            cisco.ios.ios_interfaces:
              config:
                - name: "{{ item['name'] }}"
                  description: "{{ item['description'] | default(omit) }}"
                  enabled: "{{ item['enabled'] | default(false) }}"
              state: merged
            loop: "{{ interfaces[inventory_hostname] }}"
      
          - name: Configure L3 interface information
            when:
              - interfaces is defined
              - interfaces[inventory_hostname] is defined
              - item['ipv4'] is defined
            cisco.ios.ios_l3_interfaces:
              config:
                - name: "{{ item['name'] }}"
                  ipv4:
                    - address: "{{ item['ipv4'] }}"
              state: merged
            loop: "{{ interfaces[inventory_hostname] }}"
      
          - name: Pause 5 seconds
            ansible.builtin.pause:
              seconds: 5
            run_once: true
      
          - name: Gather interface facts (post)
            cisco.ios.ios_facts:
              gather_subset:
                - interfaces
      
          - name: Show ansible_facts['net_interfaces'] (post)
            ansible.builtin.debug:
              var: ansible_facts['net_interfaces']
  3. Run the configure_interfaces.yml playbook.

    1. Switch to the Terminal tab in VS Code, or change to the /home/student/task-loops directory in a GNOME terminal.

    2. Run the playbook:

      [student@workstation task-loops]$ ansible-navigator run configure_interfaces.yml
      ...output omitted...
    3. Scroll back through the playbook output and notice the following in the Show ansible_facts['net_interfaces'] (pre) task for each managed node.

      • The GigabitEthernet1 and GigabitEthernet2 interfaces do not have descriptions.

      • The GigabitEthernet1 interface already has an IPv4 addresses.

      • The GigabitEthernet2 interface does not have an IPv4 address and displays the administratively down operational status.

      • The Loopback0 interface does not exist.

      Note

      The ansible-navigator.yml file in this project enables playbook artifacts. If desired, you can review the output of the playbook using the ansible-navigator replay command. You might select the artifact file name using tab completion. You might also consider using the -m interactive option so that you can selectively view the output of specific tasks.

      For example:

      [student@workstation task-loops]$ ansible-navigator replay -m interactive \
      configure_interfaces-artifact-2023-08-14T13\:58\:15.922542+00\:00.json
    4. Scroll back through the playbook output and notice that the Configure basic interface information task performed the following tasks:

      • Added the Loopback0 interface to both managed nodes

      • Added the Managed by Ansible description to each Loopback0 and GigabitEthernet2 interface

      • Did not add a description to the GigabitEthernet1 interfaces because the interfaces.yml file does not define the GigabitEthernet1 interfaces

      • Enabled the GigabitEthernet2 interface on both managed nodes

    5. Scroll back through the playbook output and notice that the Configure L3 interface information task performed the following tasks:

      • Added IPv4 addresses to each Loopback0 interface

      • Added IPv4 addresses to each GigabitEthernet2 interface

    6. Scroll back through the playbook output and notice the following in the Show ansible_facts['net_interfaces'] (post) task for each managed node.

      • You can see the added descriptions for the Loopback0 and GigabitEthernet2 interfaces.

      • You can see the added IPv4 addresses for the Loopback0 and GigabitEthernet2 interfaces.

      • You can see that the GigabitEthernet2 interface displays the up operational status.

      Important

      If either GigabitEthernet2 interface displays the down operational status, then the playbook probably did not wait long enough before querying for interface information. Run the query_interfaces.yml playbook to display interface facts without making any changes. Each GigabitEthernet2 interface should display the up operational status.

      [student@workstation task-loops]$ ansible-navigator run query_interfaces.yml
      ...output omitted...
  4. Click FileClose Folder in VS Code to close the /home/student/task-loops directory, or run the cd command in a GNOME terminal to return to the student home directory:

    [student@workstation task-loops]$ cd

Finish

On the workstation machine, use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish task-loops

Revision: do457-2.3-7cfa22a