Create a role to back up managed network nodes, and then use the backups to help create Jinja2 templates to generate configuration files.
Outcomes
Use Git to create a branch, commit changes, and push changes to a branch.
Create and use a role that backs up managed nodes.
Create a playbook that generates configuration files from Jinja2 templates.
Configure NTP, DNS, and Syslog on managed nodes by using generated configuration files.
As the student user on the workstation machine, use the lab command to prepare your system for this exercise:
[student@workstation ~]$ lab start compreview-cr3
Specifications
This exercise creates a role to back up managed nodes. The backups are then converted to Jinja2 templates, which are used to generate new configuration files to configure NTP, DNS, and Syslog on the managed nodes.
All files in this exercise must be stored on the workstation machine in the /home/student/git-repos/compreview directory, or a subdirectory thereof.
The /home/student/git-repos/compreview directory contains an Ansible project managed by Git.
The lab start command cloned a Git project to that directory.
Create a branch named cr3, commit all your finished work to that branch, and at the end of this activity, push that branch to the remote repository.
Create a role named net_backup in the /home/student/git-repos/compreview/roles directory.
Define the following variables in the defaults/main.yml file for the net_backup role:
| Variable name | Variable value |
|---|---|
backup_tmp
|
/tmp
|
backup_store
|
/backups
|
delegate_host
|
workstation.lab.example.com
|
Create the tasks/junos.yml file for the net_backup role.
The file must accomplish the following objectives:
Enable the NETCONF service.
Create backups of the configurations of the Junos-based managed nodes.
Use the backup_tmp variable for the dir_path parameter and use "{{ inventory_hostname }}.cfg" as the value for the filename parameter.
Create the tasks/ios.yml file for the net_backup role.
The file must accomplish the following objective:
Create backups of the configurations of the IOS-based managed nodes.
Use the backup_tmp variable for the dir_path parameter and use "{{ inventory_hostname }}.cfg" as the value for the filename parameter.
Create the tasks/store_backups.yml file for the net_backup role.
The file must accomplish the following objectives:
Delegate all tasks in the file to the host defined by the delegate_host variable.
Use the ansible.builtin.file module to create the directory defined by the backup_store variable if it does not already exist on the delegated host.
Copy the configuration backup files from the directory defined by the backup_tmp variable to the directory defined by the backup_store variable on the delegated host.
Run all tasks with privilege escalation enabled.
Update the tasks/main.yml file for the net_backup role.
The file must accomplish the following objectives:
Include the junos.yml task file for managed nodes that define the junipernetworks.junos.junos value for the ansible_network_os variable.
Include the ios.yml task file for managed nodes that define the cisco.ios.ios value for the ansible_network_os variable.
Include the store_backups.yml task file.
Create and run a playbook named net_backup.yml that targets the managed nodes in the junos and ios inventory groups, does not gather facts, and includes the net_backup role.
Modify Jinja2 templates to add NTP, DNS, and Syslog servers.
The junos.j2 and ios.j2 templates are stored in the /home/student/git-repos/compreview/templates directory.
Update the templates to add the additional NTP, DNS, and Syslog information using the variables in the /home/student/git-repos/compreview/group_vars/all directory.
Create and run the generate_config.yml playbook.
The play should target the workstation.lab.example.com host, be run using privilege escalation, and should become the student user.
Use the ansible.builtin.template module to generate new configuration files.
Add a task that uses the templates/junos.j2 template to create a configuration file for each host in the junos group.
Add a task that uses the templates/ios.j2 template to create a configuration file for each host in the ios group.
Save the filenames for the configuration files in the format of , such as hostname.cfgiosxe1.lab.example.com.cfg, and save the configuration files in the project configs directory.
Use the playbook_dir magic variable to help specify a path to the project configs directory.
Inspect the newly generated configuration files to verify that the correct values were used for the NTP, DNS, and Syslog information from the variables in the /home/student/git-repos/compreview/group_vars directory.
Create and run the deploy.yml playbook to deploy the newly generated configuration files to the appropriate managed node.
The playbook should contain one play that targets the ios and junos inventory groups.
Run the show_run.yml playbook to verify that the configuration changes were made.
Commit and push all the changes that you made in the /home/student/git-repos/compreview directory to the remote Git repository.
Use Generate and apply configurations as the commit message.
Make sure that you are in the /home/student directory before grading your work with the lab grade command.
Change to the /home/student/git-repos/compreview directory and then create a branch named cr3 for this exercise.
Change to the /home/student/git-repos/compreview directory:
[student@workstation ~]$ cd ~/git-repos/compreview
[student@workstation compreview]$Create a branch named cr3 and check it out:
[student@workstation compreview]$ git checkout -b cr3
Switched to a new branch 'cr3'Create the net_backup role in the /home/student/git-repos/compreview/roles directory.
Create the roles directory and create the initial role structure and files:
[student@workstation compreview]$mkdir roles; cd roles[student@workstation roles]$ansible-galaxy init net_backup- Role net_backup was created successfully
Set the backup_tmp variable to /tmp in the defaults/main.yml file.
Add the following line to the net_backup/defaults/main.yml file:
---
# defaults file for net_backup
backup_tmp: /tmpSet the backup_store variable to /backups in the defaults/main.yml file.
Add the following line to the net_backup/defaults/main.yml file:
---
# defaults file for net_backup
backup_tmp: /tmp
backup_store: /backupsSet the delegate_host variable to workstation.lab.example.com in the defaults/main.yml file.
Add the following line to the net_backup/defaults/main.yml file:
---
# defaults file for net_backup
backup_tmp: /tmp
backup_store: /backups
delegate_host: workstation.lab.example.comCreate the net_backup/tasks/junos.yml task file to enable the NETCONF service and create backups of the configurations from the Junos managed nodes.
Use the backup_tmp variable for the dir_path parameter and use "{{ inventory_hostname }}.cfg" as the value for the filename parameter.
Create the net_backup/tasks/junos.yml file with the following content:
---
- name: Enable the netconf service on port 830
vars:
ansible_connection: ansible.netcommon.network_cli
junipernetworks.junos.junos_netconf:
netconf_port: 830
state: present
- name: Back up Junos configurations
junipernetworks.junos.junos_config:
backup: true
backup_options:
dir_path: "{{ backup_tmp }}"
filename: "{{ inventory_hostname }}.cfg"Create the net_backup/tasks/ios.yml task file to create backups of the configurations from the IOS managed nodes.
Use the backup_tmp variable for the dir_path parameter and use "{{ inventory_hostname }}.cfg" as the value for the filename parameter.
Create the net_backup/tasks/ios.yml file with the following content:
---
- name: Back up IOS XE configurations
cisco.ios.ios_config:
backup: true
backup_options:
dir_path: "{{ backup_tmp }}"
filename: "{{ inventory_hostname }}.cfg"Create the net_backup/tasks/store_backups.yml task file to copy the configuration backup files from the directory defined by the backup_tmp variable to the directory defined by the backup_store directory on the delegated host.
Delegate all tasks in the file to the host defined by the delegate_host variable and enable privilege escalation for all tasks.
Use the ansible.builtin.file module to create the directory defined by the backup_store variable if it does not already exist on the delegated host, and then copy the configuration backup files.
Create the net_backup/tasks/store_backups.yml file with the following content:
---
- name: Create the backup store directory
ansible.builtin.file:
path: "{{ backup_store }}"
state: directory
recurse: true
become: true
delegate_to: "{{ delegate_host }}"
- name: Store the latest backup files
ansible.builtin.copy:
src: "{{ backup_tmp }}/{{ inventory_hostname }}.cfg"
dest: "{{ backup_store }}"
mode: "0664"
become: true
delegate_to: "{{ delegate_host }}"The mode parameter sets the operating system level permissions of the destination file.
This parameter is optional, but omitting the parameter results in a lint warning.
Update the net_backup/tasks/main.yml task file to include the tasks in the junos.yml, ios.yml, and store_backups.yml task files.
The tasks in the junos.yml task file should only run on managed nodes running the junipernetworks.junos.junos network OS.
The tasks in the ios.yml task file should only run on managed nodes running the cisco.ios.ios network OS.
Update the net_backup/tasks/main.yml file with the following content:
--- # tasks file for net_backup- name: Back up Junos network device configswhen: ansible_network_os == 'junipernetworks.junos.junos'ansible.builtin.include_tasks:file: junos.yml- name: Back up IOS network device configswhen: ansible_network_os == 'cisco.ios.ios'ansible.builtin.include_tasks:file: ios.yml- name: Persistently store backup filesansible.builtin.include_tasks:file: store_backups.yml
(Optional) Delete the files and directories that the role does not use:
[student@workstation roles]$cd net_backup[student@workstation net_backup]$rm -rf README.md files handlers meta \templates tests vars[student@workstation net_backup]$tree. ├── defaults │ └── main.yml └── tasks ├── ios.yml ├── junos.yml ├── main.yml └── store_backups.yml 2 directories, 5 files
Return to the /home/student/git-repos/compreview directory:
[student@workstation net_backup]$ cd ~/git-repos/compreviewCreate and run the net_backup.yml playbook in the /home/student/git-repos/compreview directory.
The playbook targets the managed nodes in the junos and ios inventory groups, and includes the net_backup role.
Create the net_backup.yml playbook with the following content:
---
- name: Back up managed network node configurations
hosts:
- junos
- ios
gather_facts: false
tasks:
- name: Back up network managed node configurations
ansible.builtin.include_role:
name: net_backupRun the net_backup.yml playbook:
[student@workstation compreview]$ ansible-navigator run net_backup.yml
...output omitted...Modify the Jinja2 templates to add NTP, DNS, and Syslog servers.
The junos.j2 and ios.j2 templates are stored in the /home/student/git-repos/compreview/templates directory.
Update the templates to add the additional NTP, DNS, and Syslog information with the variables in the /home/student/git-repos/compreview/group_vars/all directory.
Inspect the ntp_servers variable in the group_vars/all/ntp_servers.yml file:
--- ntp_servers: - 172.25.23.240 - 172.25.23.230
Inspect the nameservers variable in the group_vars/all/nameservers.yml file:
--- nameservers: - 172.25.250.220 - 172.25.240.220
Inspect the syslog_servers variable in the group_vars/all/syslog_servers.yml file:
---
syslog_servers:
- name: syslog01
address: 192.168.10.10
- name: syslog02
address: 192.168.11.10Inspect the templates/junos.j2 file.
Note the format used by the Juniper Junos configuration file to configure the NTP, DNS, and Syslog server IP addresses:
{# Edit this template to perform the actions stated in the comments #}
{# loop through each name server #}
set system name-server 1.2.3.4
set system name-server 5.6.7.8
{# loop through each syslog server #}
set system syslog host host1 source-address 1.2.3.4
set system syslog host host2 source-address 5.6.7.8
{# loop through each ntp server #}
set system ntp server 1.2.3.4
set system ntp server 5.6.7.8Inspect the templates/ios.j2 file.
Note the format used by the Cisco IOS configuration file to configure the NTP, DNS, and Syslog server IP addresses:
{# Edit this template to perform the actions stated in the comments #}
{# Add both nameservers from variable #}
ip name-server {{ nameservers[0] }} {{ nameservers[1] }}
{# loop through each syslog server #}
logging host 1.2.3.4
logging host 5.6.7.8
{# loop through each ntp server #}
ntp server 1.2.3.4 version 2
ntp server 5.6.7.8 version 2Modify the templates/junos.j2 template file.
Replace the NTP, DNS, and Syslog server sections under the comments using for statements to loop through the variables in the group_vars/all directory.
The final Jinja2 template must consist of the following content:
{# Edit this template to perform the actions stated in the comments #}
{# loop through each name server #}
{% for NAMESERVER in nameservers %}
set system name-server {{ NAMESERVER }}
{% endfor %}
{# loop through each syslog server #}
{% for SYSLOG in syslog_servers %}
set system syslog host {{ SYSLOG['name'] }} source-address {{ SYSLOG['address'] }}
{% endfor %}
{# loop through each ntp server #}
{% for NTP in ntp_servers %}
set system ntp server {{ NTP }}
{% endfor %}Modify the templates/ios.j2 template file.
Replace the Syslog and NTP server sections under the comments using for statements to loop through the variables in the group_vars/all directory.
The final Jinja2 template must consist of the following content:
{# Edit this template to perform the actions stated in the comments #}
{# Add both nameservers from variable #}
ip name-server {{ nameservers[0] }} {{ nameservers[1] }}
{# loop through each syslog server #}
{% for SYSLOG in syslog_servers %}
logging host {{ SYSLOG['address'] }}
{% endfor %}
{# loop through each ntp server #}
{% for NTP in ntp_servers %}
ntp server {{ NTP }} version 2
{% endfor %}The DNS servers have already been configured to use the correct variables in this file by using one method to place both name servers on the same line.
Another option is to use a for statement inline as shown in the following example:
{# Add both nameservers from variable #}
ip name-server{% for SERVER in nameservers %} {{ SERVER }}{% endfor %}
{# loop through each syslog server #}Note that there is an extra blank line in this example.
Without this extra blank line, the first logging host is placed on the same line as the ip name-server line.
Create and run the generate_config.yml playbook, which uses the ansible.builtin.template module to generate new configuration files.
Save the filenames for the configuration files in the format of , such as hostname.cfgiosxe1.lab.example.com.cfg, and save the configuration files in the project configs directory.
Begin the generate_config.yml playbook by targeting the workstation.lab.example.com host and setting the config_dir and template_dir variables:
---- name: Generate configuration files from templateshosts: workstation.lab.example.combecome: truebecome_user: studentgather_facts: falsevars:config_dir: "{{ playbook_dir }}/configs"tasks:
Create a task that generates the configuration files for the managed Juniper nodes:
- name: Generate Juniper configuration filesansible.builtin.template:src: templates/junos.j2dest: "{{ config_dir }}/{{ item }}.cfg"mode: "0664"loop: "{{ groups['junos'] }}"
Create a second task that generates the configuration files for the managed Cisco nodes.
The completed generate_config.yml playbook must consist of the following content:
---
- name: Generate configuration files from templates
hosts: workstation.lab.example.com
become: true
become_user: student
gather_facts: false
vars:
config_dir: "{{ playbook_dir }}/configs"
tasks:
- name: Generate Juniper configuration files
ansible.builtin.template:
src: templates/junos.j2
dest: "{{ config_dir }}/{{ item }}.cfg"
mode: "0664"
loop: "{{ groups['junos'] }}"
- name: Generate Cisco configuration files
ansible.builtin.template:
src: templates/ios.j2
dest: "{{ config_dir }}/{{ item }}.cfg"
mode: "0664"
loop: "{{ groups['ios'] }}"Run the generate_config.yml playbook:
[student@workstation compreview]$ ansible-navigator run generate_config.yml
...output omitted...Inspect the newly generated configuration files to verify that the correct values were used for the NTP, DNS, and Syslog information from the variables in the /home/student/git-repos/compreview/group_vars directory.
Inspect the configs/junos1.lab.example.com.cfg file.
Note that the IP address values match the values in the /home/student/git-repos/compreview/group_vars directory:
set system name-server172.25.250.220set system name-server172.25.240.220set system syslog host syslog01 source-address192.168.10.10set system syslog host syslog02 source-address192.168.11.10set system ntp server172.25.23.240set system ntp server172.25.23.230
Inspect the configs/iosxe1.lab.example.com.cfg file.
Note that the IP address values match the values in the /home/student/git-repos/compreview/group_vars directory:
ip name-server172.25.250.220172.25.240.220logging host192.168.10.10logging host192.168.11.10ntp server172.25.23.240version 2 ntp server172.25.23.230version 2
The ip name-server line should have a space before the first IP address, a space between the IP addresses, and this line should not include the first logging host line.
Create and run the deploy.yml playbook to deploy the newly generated configuration files to the appropriate managed node.
Begin the deploy.yml playbook by targeting the junos and ios inventory groups:
---- name: Configure managed nodeshosts:- junos- iosgather_facts: falsetasks:
Add a task to deploy the Junos configurations:
- name: Deploy Junos configuration
when: ansible_network_os == 'junipernetworks.junos.junos'
junipernetworks.junos.junos_config:
src: configs/{{ inventory_hostname }}.cfgAdd a task to deploy the IOS configurations.
The completed deploy.yml playbook must consist of the following content:
---
- name: Configure managed nodes
hosts:
- junos
- ios
gather_facts: false
tasks:
- name: Deploy Junos configuration
when: ansible_network_os == 'junipernetworks.junos.junos'
junipernetworks.junos.junos_config:
src: configs/{{ inventory_hostname }}.cfg
- name: Deploy IOS configuration
when: ansible_network_os == 'cisco.ios.ios'
cisco.ios.ios_config:
src: configs/{{ inventory_hostname }}.cfgRun the deploy.yml playbook:
[student@workstation compreview]$ ansible-navigator run deploy.yml
...output omitted...Run the show_run.yml playbook to verify that the NTP, DNS, and Syslog server configurations have been added to the managed nodes:
[student@workstation compreview]$ansible-navigator run show_run.yml...output omitted... TASK [Display configured NTP servers] ***************************************** ok: [junos1.lab.example.com] => { "actual_ntp_servers": [ "1.2.3.4", "5.6.7.8","172.25.23.240","172.25.23.230"] } ...output omitted... ok: [iosxe1.lab.example.com] => { "actual_ntp_servers": [ "5.6.7.8","172.25.23.240", "1.2.3.4","172.25.23.230"] } ...output omitted... TASK [Display configured DNS name servers] ************************************ ok: [junos1.lab.example.com] => { "actual_dns_servers": [ "1.2.3.4", "5.6.7.8","172.25.250.220","172.25.240.220"] } ...output omitted... ok: [iosxe1.lab.example.com] => { "actual_dns_servers": [ "1.2.3.4", "5.6.7.8","172.25.250.220","172.25.240.220"] } ...output omitted... TASK [Display configured Syslog servers] ************************************** ok: [junos1.lab.example.com] => { "actual_syslog_servers": [ { "name": "host1", "source-address": "1.2.3.4" }, { "name": "host2", "source-address": "5.6.7.8" }, {"name": "syslog01","source-address": "192.168.10.10"}, {"name": "syslog02","source-address": "192.168.11.10"} ] } ...output omitted... ok: [iosxe1.lab.example.com] => { "actual_syslog_servers": [ "1.2.3.4", "5.6.7.8","192.168.10.10","192.168.11.10"] } ...output omitted...
Commit and push all the changes that you made in the /home/student/git-repos/compreview directory to the remote Git repository.
Use Generate and apply configurations as the commit message.
Use VS Code or the git add command to add the new and updated files and directories:
[student@workstation compreview]$ git add .Use VS Code or the git status command to display the list of files that you staged for the next commit:
[student@workstation compreview]$ git status
On branch cr3
Your branch is up to date with 'origin/cr3'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: configs/iosxe1.lab.example.com.cfg
new file: configs/iosxe2.lab.example.com.cfg
new file: configs/junos1.lab.example.com.cfg
new file: configs/junos2.lab.example.com.cfg
new file: deploy.yml
new file: generate_config.yml
new file: net_backup.yml
...output omitted...Use VS Code or the git commit command to commit the files.
Use Generate and apply configurations as the commit message:
[student@workstation compreview]$git commit -m \"Generate and apply configurations"[cr3 5574r79] Generate and apply configurations ...output omitted...
Use VS Code or the git push command to update the remote Git repository:
[student@workstation compreview]$ git push -u origin cr3
...output omitted...
To git.lab.example.com:student/compreview.git
* [new branch] cr3 -> cr3
Branch 'cr3' set up to track remote branch 'cr3' from 'origin'.Close the /home/student/git-repos/compreview directory in VS Code.
Return to the /home/student directory in the GNOME terminal.
Click → in VS Code to close the /home/student/git-repos/compreview directory.
Run the cd command in the GNOME terminal to return to the student home directory:
[student@workstation compreview]$ cd