07-14-2020, 02:38 AM
Automating Network Devices with Ansible
<div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/07/automating-network-devices-with-ansible.png" width="1024" height="237" title="" alt="" /></div><div><p>Ansible is a great automation tool for system and network engineers, with Ansible we can automate small network to a large scale enterprise network. I have been using Ansible to automate both Aruba, and Cisco switches from my Fedora powered laptops for a couple of years. This article covers the requirements and executing a couple of playbooks.</p>
<p> <span id="more-31280"></span> </p>
<h2>Configuring Ansible</h2>
<p>If Ansible is not installed, it can be installed using the command below</p>
<pre class="wp-block-preformatted">$ sudo dnf -y install ansible</pre>
<p>Once installed, create a folder in your home directory or a directory of your preference and copy the ansible configuration file. For this demonstration, I will be using the following.</p>
<pre class="wp-block-preformatted">$ mkdir -pv /home/$USER/network_automation
$ sudo cp -v /etc/ansible.cfg /home/$USER/network_automation
$ cd /home/$USER/network_automation
$ sudo chown $USER.$USER && chmod 0600 ansible.cfg</pre>
<p>To prevent lengthy commands from failing, edit the ansible.cfg and append the following lines. We must add the persistent connection and set the desired time in seconds for the <em>command_timeout</em> as demonstrated below. A use case where this is useful is when you are performing backups of a network device that has a lengthy configuration.</p>
<pre class="wp-block-preformatted">$ vim ansible.cfg
[persistent_connection]
command_timeout = 300
connection_timeout = 30</pre>
<h3>Requirements</h3>
<p>If SELinux is enabled, you will need to install SELinux binding, which is required when using the copy module.</p>
<pre class="wp-block-preformatted"># Install SELinux bindings
dnf -y install python3-libselinux python3-libsemanage</pre>
<h3>Creating the inventory</h3>
<p>The inventory holds the names of the network assets, and grouping of the assets are in square brackets <em>[]</em>, below is a sample inventory.</p>
<pre class="wp-block-preformatted">[site_a]
Core_A ansible_host=192.168.122.200
Distro_A ansible_host=192.168.122.201
Distro_B ansible_host=192.168.122.202</pre>
<div class="wp-block-jetpack-markdown">
<p>Group vars can be used to address the common variables, for example, credentials, network operating system, and so on. Ansible document on <a href="https://docs.ansible.com/ansible/latest/network/getting_started/first_inventory.html">inventory</a> provides additional details.</p>
</div>
<h2>Playbook</h2>
<div class="wp-block-jetpack-markdown">
<blockquote>
<p>Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.<br />
<a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks.html">Ansible Playbook</a></p>
</blockquote>
</div>
<h3>Read Operations</h3>
<div class="wp-block-jetpack-markdown">
<p>Let us create a simple playbook to run a show command to read the configuration on a few switches.</p>
<pre> <div class="codecolorer-container text default language-yaml" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace"> 1 ---<br />
2 - name: Basic Playbook<br />
3 hosts: site_a<br />
4 connection: local<br />
5 <br />
6 tasks:<br />
7 - name: Get Interface Brief<br />
8 ios_command:<br />
9 commands:<br />
10 - show ip interface brief | e una<br />
11 register: interfaces<br />
12 <br />
13 - name: Print results<br />
14 debug:<br />
15 msg: "{{ interfaces.stdout[0] }}</div></div> </pre>
<figure><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/07/automating-network-devices-with-ansible.png" alt="Without Debug" /></figure>
</p>
<figure><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/07/automating-network-devices-with-ansible-1.png" alt="With Debug" /></figure>
</p>
<p>The above images show the differences without and with the debug module respectively.</p>
<p>Let’s break the playbook into three blocks, starting with lines 1 to 4.</p>
<ul>
<li>The three dashes/hyphens starts the YAML document</li>
<li>The hosts defines the hosts or host groups, multiple groups are comma-separated</li>
<li>Connection defines the methodology to connect to the network devices. Another option is network_cli (recommended method) and will be used later in this article. See <a href="https://docs.ansible.com/ansible/latest/network/user_guide/platform_ios.html">IOS Platform Options</a> for more details.</li>
</ul>
<p>Lines 6 to 11 starts the tasks, we will be using <a href="https://docs.ansible.com/ansible/latest/modules/ios_command_module.html">ios_command</a> and <a href="https://docs.ansible.com/ansible/latest/modules/ios_config_module.html">ios_config</a>. This play will execute the show command <em>show ip interface brief | e una</em> and save the output from the command into the interfaces variable, with the register key.</p>
<p>Lines 13 to 15, by default, when you execute a show command you will not see the output, though this is not used during automation. It is very useful for debugging; therefore, the debug module was used.</p>
<p>The below video shows the execution of the playbook. There are a couple of ways you can execute the playbook.</p>
<ul>
<li>Passing arguments to the command line, for example, include <em>-u <username></em> <em>-k</em> to prompt for the remote user credentials</li>
</ul>
<pre> <div class="codecolorer-container text default" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">ansible-playbook -i inventory show_demo.yaml -u admin -k</div></div> </pre>
<ul>
<li>Include the credentials in the host or group vars</li>
</ul>
<pre> <div class="codecolorer-container text default" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">ansible-playbook -i inventory show_demo.yaml</div></div> </pre>
</div>
<div class="wp-block-jetpack-markdown">
<blockquote>
<p>Never store passwords in plain text. We recommend using SSH keys to authenticate SSH connections. Ansible supports ssh-agent to manage your SSH keys. If you must use passwords to authenticate SSH connections, we recommend encrypting them with<br />
<a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_vault.html#playbooks-vault">Using Vault in Playbooks</a></p>
</blockquote>
</div>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-25-06-20-100214.webm"></video><figcaption>Passing arguments to the command line</figcaption></figure>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-25-06-20-100811.webm"></video><figcaption>Credentials in the inventory</figcaption></figure>
<p>If we want to save the output to a file, we will use the copy module as shown in the playbook below. In addition to using the copy module, we will include the <em>backup_dir</em> variable to specify the directory path.</p>
<div class="wp-block-jetpack-markdown">
<pre> <div class="codecolorer-container text default" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">---<br />
- name: Get System Infomation<br />
hosts: site_a<br />
connection: network_cli<br />
gather_facts: no<br />
<br />
vars:<br />
backup_dir: /home/eramirez/dev/ansible/fedora_magazine<br />
<br />
tasks:<br />
- name: get system interfaces<br />
ios_command:<br />
commands:<br />
- show ip int br | e una<br />
register: interface<br />
<br />
- name: Save result to disk<br />
copy:<br />
content: "{{ interface.stdout[0] }}"<br />
dest: "{{ backup_dir }}/{{ inventory_hostname }}.txt"</div></div> </pre>
<p>To demonstrate the use of variables in the inventory, we will use plain text. This method <strong>Must</strong> not be used in production.</p>
<pre> <div class="codecolorer-container text default language-yaml" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">[site_a]<br />
Core_A ansible_host=192.168.122.200<br />
Distro_A ansible_host=192.168.122.201<br />
Distro_B ansible_host=192.168.122.202<br />
[all:vars]<br />
ansible_connection=network_cli<br />
ansible_network_os=ios<br />
ansible_user=admin<br />
ansible_password=fedora<br />
ansible_become=yes<br />
ansible_become_password=yes<br />
ansible_become_method=enable</div></div> </pre>
</div>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-24-06-20-234555.webm"></video></figure>
<h3>Write Operations</h3>
<div class="wp-block-jetpack-markdown">
<p>In the previous section, we saw that we could get information from the network devices; in this section, we will write (add/modify) the configuration on these network devices. To make changes to the network device, we will be using the <a href="https://docs.ansible.com/ansible/latest/modules/ios_config_module.html">ios config</a> module.</p>
</div>
<div class="wp-block-jetpack-markdown">
<p>Let us create a playbook to configure a couple of interfaces in all of the network devices in site_a. We will first take a backup of the current configuration of all devices in site_a. Lastly, we will save the configuration.</p>
<pre> <div class="codecolorer-container text default language-yaml" style="overflow:auto;border:1px solid #9F9F9F;width:435px;height:300px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">---<br />
- name: Get System Infomation<br />
hosts: site_a<br />
connection: network_cli<br />
gather_facts: no<br />
<br />
vars:<br />
backup_dir: /home/eramirez/dev/ansible/fedora_magazine<br />
<br />
tasks:<br />
- name: Backup configs<br />
ios_config:<br />
backup: yes<br />
backup_options:<br />
filename: "{{ inventory_hostname }}_running_cfg.txt"<br />
dir_path: "{{ backup_dir }}"<br />
<br />
- name: get system interfaces<br />
ios_config:<br />
lines:<br />
- description Raspberry Pi<br />
- switchport mode access<br />
- switchport access vlan 100<br />
- spanning-tree portfast<br />
- logging event link-status<br />
- no shutdown<br />
parents: "{{ item }}"<br />
with_items:<br />
- interface FastEthernet1/12<br />
- interface FastEthernet1/13<br />
<br />
- name: Save switch configuration<br />
ios_config:<br />
save_when: modified</div></div> </pre>
</div>
<p>Before we execute the playbook, we will first validate the interface configuration. We will then run the playbook and confirm the changes as illustrated below.</p>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-25-06-20-113943.webm"></video></figure>
<h2>Conclusion</h2>
<p>This article is a basic introduction to whet your appetite that demonstrates how Ansible is used to manage network devices. Ansible is capable of automating a vast network, which includes MPLS routing and performing validation before executing the next task.</p>
</div>
https://www.sickgaming.net/blog/2020/07/...h-ansible/
<div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/07/automating-network-devices-with-ansible.png" width="1024" height="237" title="" alt="" /></div><div><p>Ansible is a great automation tool for system and network engineers, with Ansible we can automate small network to a large scale enterprise network. I have been using Ansible to automate both Aruba, and Cisco switches from my Fedora powered laptops for a couple of years. This article covers the requirements and executing a couple of playbooks.</p>
<p> <span id="more-31280"></span> </p>
<h2>Configuring Ansible</h2>
<p>If Ansible is not installed, it can be installed using the command below</p>
<pre class="wp-block-preformatted">$ sudo dnf -y install ansible</pre>
<p>Once installed, create a folder in your home directory or a directory of your preference and copy the ansible configuration file. For this demonstration, I will be using the following.</p>
<pre class="wp-block-preformatted">$ mkdir -pv /home/$USER/network_automation
$ sudo cp -v /etc/ansible.cfg /home/$USER/network_automation
$ cd /home/$USER/network_automation
$ sudo chown $USER.$USER && chmod 0600 ansible.cfg</pre>
<p>To prevent lengthy commands from failing, edit the ansible.cfg and append the following lines. We must add the persistent connection and set the desired time in seconds for the <em>command_timeout</em> as demonstrated below. A use case where this is useful is when you are performing backups of a network device that has a lengthy configuration.</p>
<pre class="wp-block-preformatted">$ vim ansible.cfg
[persistent_connection]
command_timeout = 300
connection_timeout = 30</pre>
<h3>Requirements</h3>
<p>If SELinux is enabled, you will need to install SELinux binding, which is required when using the copy module.</p>
<pre class="wp-block-preformatted"># Install SELinux bindings
dnf -y install python3-libselinux python3-libsemanage</pre>
<h3>Creating the inventory</h3>
<p>The inventory holds the names of the network assets, and grouping of the assets are in square brackets <em>[]</em>, below is a sample inventory.</p>
<pre class="wp-block-preformatted">[site_a]
Core_A ansible_host=192.168.122.200
Distro_A ansible_host=192.168.122.201
Distro_B ansible_host=192.168.122.202</pre>
<div class="wp-block-jetpack-markdown">
<p>Group vars can be used to address the common variables, for example, credentials, network operating system, and so on. Ansible document on <a href="https://docs.ansible.com/ansible/latest/network/getting_started/first_inventory.html">inventory</a> provides additional details.</p>
</div>
<h2>Playbook</h2>
<div class="wp-block-jetpack-markdown">
<blockquote>
<p>Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.<br />
<a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks.html">Ansible Playbook</a></p>
</blockquote>
</div>
<h3>Read Operations</h3>
<div class="wp-block-jetpack-markdown">
<p>Let us create a simple playbook to run a show command to read the configuration on a few switches.</p>
<pre> <div class="codecolorer-container text default language-yaml" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace"> 1 ---<br />
2 - name: Basic Playbook<br />
3 hosts: site_a<br />
4 connection: local<br />
5 <br />
6 tasks:<br />
7 - name: Get Interface Brief<br />
8 ios_command:<br />
9 commands:<br />
10 - show ip interface brief | e una<br />
11 register: interfaces<br />
12 <br />
13 - name: Print results<br />
14 debug:<br />
15 msg: "{{ interfaces.stdout[0] }}</div></div> </pre>
<figure><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/07/automating-network-devices-with-ansible.png" alt="Without Debug" /></figure>
</p>
<figure><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/07/automating-network-devices-with-ansible-1.png" alt="With Debug" /></figure>
</p>
<p>The above images show the differences without and with the debug module respectively.</p>
<p>Let’s break the playbook into three blocks, starting with lines 1 to 4.</p>
<ul>
<li>The three dashes/hyphens starts the YAML document</li>
<li>The hosts defines the hosts or host groups, multiple groups are comma-separated</li>
<li>Connection defines the methodology to connect to the network devices. Another option is network_cli (recommended method) and will be used later in this article. See <a href="https://docs.ansible.com/ansible/latest/network/user_guide/platform_ios.html">IOS Platform Options</a> for more details.</li>
</ul>
<p>Lines 6 to 11 starts the tasks, we will be using <a href="https://docs.ansible.com/ansible/latest/modules/ios_command_module.html">ios_command</a> and <a href="https://docs.ansible.com/ansible/latest/modules/ios_config_module.html">ios_config</a>. This play will execute the show command <em>show ip interface brief | e una</em> and save the output from the command into the interfaces variable, with the register key.</p>
<p>Lines 13 to 15, by default, when you execute a show command you will not see the output, though this is not used during automation. It is very useful for debugging; therefore, the debug module was used.</p>
<p>The below video shows the execution of the playbook. There are a couple of ways you can execute the playbook.</p>
<ul>
<li>Passing arguments to the command line, for example, include <em>-u <username></em> <em>-k</em> to prompt for the remote user credentials</li>
</ul>
<pre> <div class="codecolorer-container text default" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">ansible-playbook -i inventory show_demo.yaml -u admin -k</div></div> </pre>
<ul>
<li>Include the credentials in the host or group vars</li>
</ul>
<pre> <div class="codecolorer-container text default" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">ansible-playbook -i inventory show_demo.yaml</div></div> </pre>
</div>
<div class="wp-block-jetpack-markdown">
<blockquote>
<p>Never store passwords in plain text. We recommend using SSH keys to authenticate SSH connections. Ansible supports ssh-agent to manage your SSH keys. If you must use passwords to authenticate SSH connections, we recommend encrypting them with<br />
<a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_vault.html#playbooks-vault">Using Vault in Playbooks</a></p>
</blockquote>
</div>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-25-06-20-100214.webm"></video><figcaption>Passing arguments to the command line</figcaption></figure>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-25-06-20-100811.webm"></video><figcaption>Credentials in the inventory</figcaption></figure>
<p>If we want to save the output to a file, we will use the copy module as shown in the playbook below. In addition to using the copy module, we will include the <em>backup_dir</em> variable to specify the directory path.</p>
<div class="wp-block-jetpack-markdown">
<pre> <div class="codecolorer-container text default" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">---<br />
- name: Get System Infomation<br />
hosts: site_a<br />
connection: network_cli<br />
gather_facts: no<br />
<br />
vars:<br />
backup_dir: /home/eramirez/dev/ansible/fedora_magazine<br />
<br />
tasks:<br />
- name: get system interfaces<br />
ios_command:<br />
commands:<br />
- show ip int br | e una<br />
register: interface<br />
<br />
- name: Save result to disk<br />
copy:<br />
content: "{{ interface.stdout[0] }}"<br />
dest: "{{ backup_dir }}/{{ inventory_hostname }}.txt"</div></div> </pre>
<p>To demonstrate the use of variables in the inventory, we will use plain text. This method <strong>Must</strong> not be used in production.</p>
<pre> <div class="codecolorer-container text default language-yaml" style="overflow:auto;border:1px solid #9F9F9F;width:435px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">[site_a]<br />
Core_A ansible_host=192.168.122.200<br />
Distro_A ansible_host=192.168.122.201<br />
Distro_B ansible_host=192.168.122.202<br />
[all:vars]<br />
ansible_connection=network_cli<br />
ansible_network_os=ios<br />
ansible_user=admin<br />
ansible_password=fedora<br />
ansible_become=yes<br />
ansible_become_password=yes<br />
ansible_become_method=enable</div></div> </pre>
</div>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-24-06-20-234555.webm"></video></figure>
<h3>Write Operations</h3>
<div class="wp-block-jetpack-markdown">
<p>In the previous section, we saw that we could get information from the network devices; in this section, we will write (add/modify) the configuration on these network devices. To make changes to the network device, we will be using the <a href="https://docs.ansible.com/ansible/latest/modules/ios_config_module.html">ios config</a> module.</p>
</div>
<div class="wp-block-jetpack-markdown">
<p>Let us create a playbook to configure a couple of interfaces in all of the network devices in site_a. We will first take a backup of the current configuration of all devices in site_a. Lastly, we will save the configuration.</p>
<pre> <div class="codecolorer-container text default language-yaml" style="overflow:auto;border:1px solid #9F9F9F;width:435px;height:300px"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">---<br />
- name: Get System Infomation<br />
hosts: site_a<br />
connection: network_cli<br />
gather_facts: no<br />
<br />
vars:<br />
backup_dir: /home/eramirez/dev/ansible/fedora_magazine<br />
<br />
tasks:<br />
- name: Backup configs<br />
ios_config:<br />
backup: yes<br />
backup_options:<br />
filename: "{{ inventory_hostname }}_running_cfg.txt"<br />
dir_path: "{{ backup_dir }}"<br />
<br />
- name: get system interfaces<br />
ios_config:<br />
lines:<br />
- description Raspberry Pi<br />
- switchport mode access<br />
- switchport access vlan 100<br />
- spanning-tree portfast<br />
- logging event link-status<br />
- no shutdown<br />
parents: "{{ item }}"<br />
with_items:<br />
- interface FastEthernet1/12<br />
- interface FastEthernet1/13<br />
<br />
- name: Save switch configuration<br />
ios_config:<br />
save_when: modified</div></div> </pre>
</div>
<p>Before we execute the playbook, we will first validate the interface configuration. We will then run the playbook and confirm the changes as illustrated below.</p>
<figure class="wp-block-video"><video controls src="https://fedoramagazine.org/wp-content/uploads/2020/06/Screencast-from-25-06-20-113943.webm"></video></figure>
<h2>Conclusion</h2>
<p>This article is a basic introduction to whet your appetite that demonstrates how Ansible is used to manage network devices. Ansible is capable of automating a vast network, which includes MPLS routing and performing validation before executing the next task.</p>
</div>
https://www.sickgaming.net/blog/2020/07/...h-ansible/