Here I have a collection of commands for reference. Ansible can be run using ad-hoc commands or playbooks.
Ad-hoc commands are all in the single command. Raw commands are entered in the Ad-hoc mode and are the commands that would usually be entered into the CLI of the network device or server.
Playbooks are a series of plays to commands that will be run and on which devices. They can have variables in and get fairly complex.
This post will be a quick reference guide for Ansible commands on my Cisco lab.
All of the playbooks can be found on my Github
Quick Contents
Ad-hoc Commands
My Ansible inventory file has 4 devices that are split into two groups. There are only IP addresses as I am not using any DNS for the lab. In a larger environment have DNS and device hostnames is a better idea.
0 1 2 3 4 5 6 7 8 |
[lab_core] 172.16.1.104 [lab_access] 172.16.1.102 172.16.1.103 172.16.1.124 |
Switch2 that has the IP address of 172.16.1.102 is on an older version of IOS that supports DH1 and SHA1 only. Meaning that I can SSH to it. The fix I found that worked for me was to use paramiko. This can be set when running the Ansible command “-c paramiko”.
0 1 2 |
ansible-playbook -i inventory/router_switch_inv.ini playbooks/pb_showmac -u admin -k -c paramiko |
Run commands for all devices in the inventory
0 1 2 |
ansible all -i ./router_switch_inv.ini -m raw -a "show ip int br" -u admin -k |
Run commands for the group lab_access in the inventory
0 1 2 |
ansible lab_access -i ./router_switch_inv.ini -m raw -a "show ip int br" -u admin -k |
Run commands for a group, and grep for the “show version” uptime. Output included.
0 1 2 3 4 |
$ ansible lab_core -i ./router_switch_inv.ini -m raw -a "show version" -u admin -k | grep uptime SSH password: R1 uptime is 1 day, 3 hours, 49 minutes |
There is an option to redirect the output into a text file instead of displaying it to the terminal.
0 1 2 |
ansible lab_access -i ./router_switch_inv.ini -m raw -a "show run" -u admin -k | grep username > usernames.txt |
Playbooks
The playbooks are a way of running more than just single commands. There can be multiple plays, tasks and logic applied.
All of these playbooks can be found on my Github
Basic Playbook
I have tested a basic playbook that just runs the command “show mac address table”. This is a raw command as was performed in the ad hoc mode.
My router 172.16.1.104 does not have a MAC table as it is not a switch and so has an error.
This is where groups come in handy.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
$ ansible-playbook -i inventory/router_switch_inv.ini playbooks/pb1_basic.yml -u admin -k -c paramiko SSH password: PLAY [Get MAC address table information] ************************************************************************** TASK [show MAC address table] ************************************************************************************* changed: [172.16.1.102] changed: [172.16.1.103] changed: [172.16.1.124] changed: [172.16.1.104] TASK [debug] ****************************************************************************************************** ok: [172.16.1.104] => { "print_output.stdout_lines": [ "", "Line has invalid autocommand \"show mac address-table\"" ] } ok: [172.16.1.102] => { "print_output.stdout_lines": [ " Mac Address Table", "-------------------------------------------", "", "Vlan Mac Address Type Ports", "---- ----------- -------- -----", " 1 0cec.3167.8301 DYNAMIC Et0/0", "Total Mac Addresses for this criterion: 1" ] } ok: [172.16.1.103] => { "print_output.stdout_lines": [ " Mac Address Table", "-------------------------------------------", "", "Vlan Mac Address Type Ports", "---- ----------- -------- -----", " 1 0cec.3167.8301 DYNAMIC Et0/0", "Total Mac Addresses for this criterion: 1" ] } ok: [172.16.1.124] => { "print_output.stdout_lines": [ " Mac Address Table", "-------------------------------------------", "", "Vlan Mac Address Type Ports", "---- ----------- -------- -----", " 1 0cec.3167.8301 DYNAMIC Et0/0", "Total Mac Addresses for this criterion: 1" ] } PLAY RECAP ******************************************************************************************************** 172.16.1.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.103 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.104 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.124 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 |
The playbook to get this output is show below
0 1 2 3 4 5 6 7 8 9 10 11 12 |
--- - name: Get MAC address table information hosts: all gather_facts: false tasks: - name: show MAC address table raw: "show mac address-table" register: print_output - debug: var=print_output.stdout_lines |
IOS Show Command Playbook
This playbook uses the IOS command module which needs to first be installed. Documentation can be found here.
This is for running “show” type commands only.
The install is run in the terminal.
0 1 2 |
ansible-galaxy collection install cisco.ios |
I also need to update my inventory file to group all the devices together in a single group. This is done to use group variables. The variables can hold things such as credentials and device types.
Original Inventory
0 1 2 3 4 5 6 7 8 |
[lab_core] 172.16.1.104 [lab_access] 172.16.1.102 172.16.1.103 172.16.1.124 |
New Inventory
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[all_devices] 172.16.1.104 172.16.1.102 172.16.1.103 172.16.1.124 [lab_core] 172.16.1.104 [lab_access] 172.16.1.102 172.16.1.103 172.16.1.124 |
The name of the groups are used in the group variables is used in the group variable directory and the file name. This is very important otherwise it will not work. See the diagram.
Another change I have made is to the default inventory file. This is now pointing to my inventory file.
The change is made in the ansible.cfg file located in /etc/ansible.
These are the two line I added
0 1 2 3 |
[defaults] inventory = /home/stef/Ansible/inventory/router_switch_inv.ini |
The good thing is the the “-c paramiko” flag still works so access to all fours devices still. and the command is much smaller.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
ansible-playbook playbooks/pb2_ioscommand.yml -c paramiko PLAY [show version and other user level commands] ******************************************************************************************** TASK [run multiple commands on remote nodes] ************************************************************************************************* [WARNING]: ansible-pylibssh not installed, falling back to paramiko [WARNING]: ansible-pylibssh not installed, falling back to paramiko [WARNING]: ansible-pylibssh not installed, falling back to paramiko [WARNING]: ansible-pylibssh not installed, falling back to paramiko ok: [172.16.1.102] ok: [172.16.1.103] ok: [172.16.1.124] ok: [172.16.1.104] TASK [debug] ********************************************************************************************************************************* ok: [172.16.1.102] => { "print_output.stdout_lines": [ [ "Cisco IOS Software, Linux Software (I86BI_LINUX_L2-UPK9-M), Experimental Version 15.0(20121031:162848) [dstivers-oct25-2012-golden_spike 103]", "Copyright (c) 1986-2012 by Cisco Systems, Inc.", "Compiled Wed 31-Oct-12 09:42 by dstivers", "", "ROM: Bootstrap program is Linux", "", " SW2 uptime is 2 hours, 49 minutes", "System returned to ROM by reload at 0", "System image file is \"unix:/opt/gns3/images/IOU/i86bi-linux-l2-upk9-15.0b.bin\"", "Last reload reason: Unknown reason", "", "", "", "This product contains cryptographic features and is subject to United", "States and local country laws governing import, export, transfer and", "use. Delivery of Cisco cryptographic products does not imply", "third-party authority to import, export, distribute or use encryption.", "Importers, exporters, distributors and users are responsible for", "compliance with U.S. and local country laws. By using this product you", "agree to comply with applicable laws and regulations. If you are unable", "to comply with U.S. and local laws, return this product immediately.", "", "A summary of U.S. laws governing Cisco cryptographic products may be found at:", "http://www.cisco.com/wwl/export/crypto/tool/stqrg.html", "", "If you require further assistance please contact us by sending email to", "export@cisco.com.", "", "Linux Unix (Intel-x86) processor with 202485K bytes of memory.", "Processor board ID 2048002", "16 Ethernet interfaces", "16K bytes of NVRAM.", "", "Configuration register is 0x0" ], [ "Interface IP-Address OK? Method Status Protocol", "Ethernet0/0 unassigned YES unset up up ", "Ethernet0/1 unassigned YES unset up up ", "Ethernet0/2 unassigned YES unset up up ", "Ethernet0/3 unassigned YES unset up up ", "Ethernet1/0 unassigned YES unset up up ", "Ethernet1/1 unassigned YES unset up up ", "Ethernet1/2 unassigned YES unset up up ", "Ethernet1/3 unassigned YES unset up up ", "Ethernet2/0 unassigned YES unset up up ", "Ethernet2/1 unassigned YES unset up up ", "Ethernet2/2 unassigned YES unset up up ", "Ethernet2/3 unassigned YES unset up up ", "Ethernet3/0 unassigned YES unset up up ", "Ethernet3/1 unassigned YES unset up up ", "Ethernet3/2 unassigned YES unset up up ", "Ethernet3/3 unassigned YES unset up up ", "Vlan1 172.16.1.102 YES NVRAM up up" ] ] } ok: [172.16.1.124] => { "print_output.stdout_lines": [ [ "Cisco IOS Software, Solaris Software (I86BI_LINUXL2-IPBASEK9-M), Experimental Version 15.1(20130726:213425) [dstivers-july26-2013-team_track 105]", "Copyright (c) 1986-2013 by Cisco Systems, Inc.", "Compiled Fri 26-Jul-13 16:12 by dstivers", "", "ROM: Bootstrap program is Linux", "", "SW4 uptime is 3 hours, 34 minutes", "System returned to ROM by reload at 0", "System image file is \"unix:/opt/gns3/images/IOU/i86bi-linux-l2-ipbasek9-15.1g.bin\"", "Last reload reason: Unknown reason", "", "", "", "This product contains cryptographic features and is subject to United", "States and local country laws governing import, export, transfer and", "use. Delivery of Cisco cryptographic products does not imply", "third-party authority to import, export, distribute or use encryption.", "Importers, exporters, distributors and users are responsible for", "compliance with U.S. and local country laws. By using this product you", "agree to comply with applicable laws and regulations. If you are unable", "to comply with U.S. and local laws, return this product immediately.", "", "A summary of U.S. laws governing Cisco cryptographic products may be found at:", "http://www.cisco.com/wwl/export/crypto/tool/stqrg.html", "", "If you require further assistance please contact us by sending email to", "export@cisco.com.", "", "Linux Unix (Intel-x86) processor with 199474K bytes of memory.", "Processor board ID 2048005", "16 Ethernet interfaces", "1 Virtual Ethernet interface", "16K bytes of NVRAM.", "", "Configuration register is 0x0" ], [ "Interface IP-Address OK? Method Status Protocol", "Ethernet0/0 unassigned YES unset up up ", "Ethernet0/1 unassigned YES unset up up ", "Ethernet0/2 unassigned YES unset up up ", "Ethernet0/3 unassigned YES unset up up ", "Ethernet1/0 unassigned YES unset up up ", "Ethernet1/1 unassigned YES unset up up ", "Ethernet1/2 unassigned YES unset up up ", "Ethernet1/3 unassigned YES unset up up ", "Ethernet2/0 unassigned YES unset up up ", "Ethernet2/1 unassigned YES unset up up ", "Ethernet2/2 unassigned YES unset up up ", "Ethernet2/3 unassigned YES unset up up ", "Ethernet3/0 unassigned YES unset up up ", "Ethernet3/1 unassigned YES unset up up ", "Ethernet3/2 unassigned YES unset up up ", "Ethernet3/3 unassigned YES unset up up ", "Vlan1 172.16.1.124 YES manual up up" ] ] } ok: [172.16.1.104] => { "print_output.stdout_lines": [ [ "Cisco IOS Software, 7200 Software (C7200-ADVIPSERVICESK9-M), Version 15.2(4)S5, RELEASE SOFTWARE (fc1)", "Technical Support: http://www.cisco.com/techsupport", "Copyright (c) 1986-2014 by Cisco Systems, Inc.", "Compiled Thu 20-Feb-14 06:51 by prod_rel_team", "", "ROM: ROMMON Emulation Microcode", "BOOTLDR: 7200 Software (C7200-ADVIPSERVICESK9-M), Version 15.2(4)S5, RELEASE SOFTWARE (fc1)", "", "R1 uptime is 3 hours, 6 minutes", "System returned to ROM by unknown reload cause - suspect boot_data[BOOT_COUNT] 0x0, BOOT_COUNT 0, BOOTDATA 19", "System image file is \"tftp://255.255.255.255/unknown\"", "Last reload type: Normal Reload", "Last reload reason: unknown reload cause - suspect boot_data[BOOT_COUNT] 0x0, BOOT_COUNT 0, BOOTDATA 19", "", "", "", "This product contains cryptographic features and is subject to United", "States and local country laws governing import, export, transfer and", "use. Delivery of Cisco cryptographic products does not imply", "third-party authority to import, export, distribute or use encryption.", "Importers, exporters, distributors and users are responsible for", "compliance with U.S. and local country laws. By using this product you", "agree to comply with applicable laws and regulations. If you are unable", "to comply with U.S. and local laws, return this product immediately.", "", "A summary of U.S. laws governing Cisco cryptographic products may be found at:", "http://www.cisco.com/wwl/export/crypto/tool/stqrg.html", "", "If you require further assistance please contact us by sending email to", "export@cisco.com.", "", "Cisco 7206VXR (NPE400) processor (revision A) with 491520K/32768K bytes of memory.", "Processor board ID 4279256517", "R7000 CPU at 150MHz, Implementation 39, Rev 2.1, 256KB L2 Cache", "6 slot VXR midplane, Version 2.1", "", "Last reset from power-on", "", "PCI bus mb0_mb1 (Slots 0, 1, 3 and 5) has a capacity of 600 bandwidth points.", "Current configuration on bus mb0_mb1 has a total of 240 bandwidth points. ", "This configuration is within the PCI bus capacity and is supported. ", "", "PCI bus mb2 (Slots 2, 4, 6) has a capacity of 600 bandwidth points.", "Current configuration on bus mb2 has a total of 0 bandwidth points ", "This configuration is within the PCI bus capacity and is supported. ", "", "Please refer to the following document \"Cisco 7200 Series Port Adaptor", "Hardware Configuration Guidelines\" on Cisco.com <http://www.cisco.com>", "for c7200 bandwidth points oversubscription and usage guidelines.", "", "", "4 Ethernet interfaces", "1 FastEthernet interface", "509K bytes of NVRAM.", "", "8192K bytes of Flash internal SIMM (Sector size 256K).", "Configuration register is 0x2102" ], [ "Interface IP-Address OK? Method Status Protocol", "FastEthernet0/0 172.16.1.104 YES NVRAM up up ", "Ethernet1/0 unassigned YES NVRAM up up ", "Ethernet1/0.10 10.10.1.1 YES NVRAM up up ", "Ethernet1/0.20 10.20.1.1 YES NVRAM up up ", "Ethernet1/1 unassigned YES NVRAM administratively down down ", "Ethernet1/2 unassigned YES NVRAM administratively down down ", "Ethernet1/3 unassigned YES NVRAM administratively down down" ] ] } ok: [172.16.1.103] => { "print_output.stdout_lines": [ [ "Cisco IOS Software, Solaris Software (I86BI_LINUXL2-IPBASEK9-M), Experimental Version 15.1(20130726:213425) [dstivers-july26-2013-team_track 105]", "Copyright (c) 1986-2013 by Cisco Systems, Inc.", "Compiled Fri 26-Jul-13 16:12 by dstivers", "", "ROM: Bootstrap program is Linux", "", "SW3 uptime is 3 hours, 33 minutes", "System returned to ROM by reload at 0", "System image file is \"unix:/opt/gns3/images/IOU/i86bi-linux-l2-ipbasek9-15.1g.bin\"", "Last reload reason: Unknown reason", "", "", "", "This product contains cryptographic features and is subject to United", "States and local country laws governing import, export, transfer and", "use. Delivery of Cisco cryptographic products does not imply", "third-party authority to import, export, distribute or use encryption.", "Importers, exporters, distributors and users are responsible for", "compliance with U.S. and local country laws. By using this product you", "agree to comply with applicable laws and regulations. If you are unable", "to comply with U.S. and local laws, return this product immediately.", "", "A summary of U.S. laws governing Cisco cryptographic products may be found at:", "http://www.cisco.com/wwl/export/crypto/tool/stqrg.html", "", "If you require further assistance please contact us by sending email to", "export@cisco.com.", "", "Linux Unix (Intel-x86) processor with 199474K bytes of memory.", "Processor board ID 2048003", "16 Ethernet interfaces", "1 Virtual Ethernet interface", "16K bytes of NVRAM.", "", "Configuration register is 0x0" ], [ "Interface IP-Address OK? Method Status Protocol", "Ethernet0/0 unassigned YES unset up up ", "Ethernet0/1 unassigned YES unset up up ", "Ethernet0/2 unassigned YES unset up up ", "Ethernet0/3 unassigned YES unset up up ", "Ethernet1/0 unassigned YES unset up up ", "Ethernet1/1 unassigned YES unset up up ", "Ethernet1/2 unassigned YES unset up up ", "Ethernet1/3 unassigned YES unset up up ", "Ethernet2/0 unassigned YES unset up up ", "Ethernet2/1 unassigned YES unset up up ", "Ethernet2/2 unassigned YES unset up up ", "Ethernet2/3 unassigned YES unset up up ", "Ethernet3/0 unassigned YES unset up up ", "Ethernet3/1 unassigned YES unset up up ", "Ethernet3/2 unassigned YES unset up up ", "Ethernet3/3 unassigned YES unset up up ", "Vlan1 172.16.1.103 YES NVRAM up up" ] ] } PLAY RECAP *********************************************************************************************************************************** 172.16.1.102 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.103 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.104 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.16.1.124 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 |
Magic Variable Playbook
A magic variable is a way of getting variables into the playbook. Jinja is used, this is a way of getting python like syntax. I have used this in flask for the HTML templates.
This playbook is going to connect to the devices, run “show version”, print the output to the console and then save that output as the inventory hostname. In my case the IP address of each device.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
--- - name: Backup show version and other user level commands hosts: all gather_facts: false connection: network_cli tasks: - name: Show an save version ./output ios_command: commands: - show version register: print_output - debug: var=print_output.stdout_lines - name: save output to a file copy: content="{{ print_output.stdout[0] }}" dest="./output/{{ inventory_hostname }}.txt" |
The output as expected…
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ ansible-playbook -c paramiko playbooks/pb3_magicvars.yml $ ls output/ 172.16.1.102.txt 172.16.1.103.txt 172.16.1.104.txt 172.16.1.124.txt $ head output/172.16.1.102.txt Cisco IOS Software, Linux Software (I86BI_LINUX_L2-UPK9-M), Experimental Version 15.0(20121031:162848) [dstivers-oct25-2012-golden_spike 103] Copyright (c) 1986-2012 by Cisco Systems, Inc. Compiled Wed 31-Oct-12 09:42 by dstivers ROM: Bootstrap program is Linux SW2 uptime is 3 hours, 9 minutes System returned to ROM by reload at 0 System image file is "unix:/opt/gns3/images/IOU/i86bi-linux-l2-upk9-15.0b.bin" |
Cisco Facts Playbook
Gathering facts is a default option that can be performed on Linux servers. For network devices they need an additional install for Ansible to know what to look for.
This is the Cisco facts module, use the examples to get different facts out. The examples go into a task. The playbooks below show examples of the output being saved as a JSON file for easy manipulation.
0 1 2 3 4 5 6 7 8 9 10 11 12 |
--- - name: Gather legacy and resource facts hosts: all_devices gather_facts: false connection: network_cli tasks: - name: ssh facts register: iosfacts_out ios_facts: - copy: content="{{ iosfacts_out | to_nice_json }}" dest="output/{{inventory_hostname}}_iosfacts.json" |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
stef@stef-VirtualBox:~/Ansible$ansible-playbook -c paramiko playbooks/pb4_iosfacts.yml stef@stef-VirtualBox:~/Ansible$ ls output/ 172.16.1.102_iosfacts.json 172.16.1.103_iosfacts.json 172.16.1.104_iosfacts.json 172.16.1.124_iosfacts.json stef@stef-VirtualBox:~/Ansible$ cat output/172.16.1.102_iosfacts.json { "ansible_facts": { "ansible_net_api": "cliconf", "ansible_net_gather_network_resources": [], "ansible_net_gather_subset": [ "default" ], "ansible_net_hostname": " SW2", "ansible_net_image": "unix:/opt/gns3/images/IOU/i86bi-linux-l2-upk9-15.0b.bin", "ansible_net_iostype": "IOS", "ansible_net_python_version": "3.8.10", "ansible_net_serialnum": "2048002", "ansible_net_system": "ios", "ansible_net_version": "15.0(20121031:162848)", "ansible_network_resources": {} }, "changed": false, "failed": false |
A second playbook to get the idea of using the examples to get different output. This playbook gets interface facts and running config. Everything but the hardware.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
--- - name: Gather legacy and resource facts hosts: all_devices gather_facts: false connection: network_cli tasks: - name: Gather legacy and resource facts register: iosfacts_out cisco.ios.ios_facts: gather_subset: - '!hardware' - copy: content="{{ iosfacts_out | to_nice_json }}" dest="output/{{inventory_hostname}}_iosfacts2.json" |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
stef@stef-VirtualBox:~/Ansible$ ansible-playbook -c paramiko playbooks/pb5_iosfacts2.yml stef@stef-VirtualBox:~/Ansible$ head output/172.16.1.102_iosfacts2.json { "ansible_facts": { "ansible_net_all_ipv4_addresses": [ "172.16.1.102" ], "ansible_net_all_ipv6_addresses": [], "ansible_net_api": "cliconf", "ansible_net_config": "Building configuration...\n\nCurrent configuration : 1799 bytes\n!\nversion 15.0\nservice timestamps debug datetime msec\nservice timestamps log datetime msec\nno service password-encryption\n!\nhostname SW2\n!\nboot-start-marker\nboot-end-marker\n!\n!\nlogging discriminator EXCESS severity drops 6 msg-body drops EXCESSCOLL \nlogging buffered 50000\nno logging console\nenable secret 5 $1$bqnu$ZgPpJtmAWhtm.XOeqqmGl1\n!\nusername admin password 0 Stefan2020\naaa new-model\n!\n!\n!\n!\n!\naaa session-id common\nno ip icmp rate-limit unreachable\n!\nip cef\nno ip domain-lookup\nip domain-name scrap.lab\n!\nno ipv6 cef\n!\n!\n!\nspanning-tree mode pvst\nspanning-tree extend system-id\n!\nvlan internal allocation policy ascending\n!\nip tcp synwait-time 5\nip ssh version 2\n! \n!\n!\n!\n!\n!\ninterface Ethernet0/0\n switchport mode access\n duplex auto\n!\ninterface Ethernet0/1\n switchport access vlan 10\n switchport mode access\n duplex auto\n!\ninterface Ethernet0/2\n duplex auto\n!\ninterface Ethernet0/3\n duplex auto\n!\ninterface Ethernet1/0\n duplex auto\n!\ninterface Ethernet1/1\n duplex auto\n!\ninterface Ethernet1/2\n duplex auto\n!\ninterface Ethernet1/3\n duplex auto\n!\ninterface Ethernet2/0\n duplex auto\n!\ninterface Ethernet2/1\n duplex auto\n!\ninterface Ethernet2/2\n duplex auto\n!\ninterface Ethernet2/3\n duplex auto\n!\ninterface Ethernet3/0\n duplex auto\n!\ninterface Ethernet3/1\n duplex auto\n!\ninterface Ethernet3/2\n duplex auto\n!\ninterface Ethernet3/3\n switchport trunk encapsulation dot1q\n switchport mode trunk\n duplex auto\n!\ninterface Vlan1\n ip address 172.16.1.102 255.255.255.0\n!\n!\nip forward-protocol nd\nno ip http server\nip route 0.0.0.0 0.0.0.0 172.16.1.1\n!\n!\n!\n!\n!\ncontrol-plane\n!\n!\nline con 0\n exec-timeout 0 0\n privilege level 15\n logging synchronous\nline aux 0\n exec-timeout 0 0\n privilege level 15\n logging synchronous\nline vty 0 4\n privilege level 15\n password Stefan2020\n transport input ssh\n!\nend", "ansible_net_gather_network_resources": [], "ansible_net_gather_subset": [ |
Playbook IOS Configuration – Single Device
This, like the IOS command playbook requires an Ansible module. This is the same as was installed previously.
0 1 2 |
ansible-galaxy collection install cisco.ios |
The biggest hurdle to overcome for this is getting past the enable password. There are three methods I have used to do this.
The first is probably the most simple, configure SSH users logging in with privilege level 15 as part of the standard device config.
The second is to store the passwords in the group_vars file. This can be revisited later for Ansible vault.
0 1 2 3 4 5 6 7 8 9 10 |
$ cat inventory/group_vars/all_devices/all_devices.yml --- ansible_network_os: ios ansible_user: admin ansible_password: Stefan2020 ansible_become: yes ansible_become_method: enable ansible_become_password: cisco |
The third is to ask for the credentials when running the Ansible playbook, and having the “become” modules in the playbook task. I have used this one as a demonstration. The playbook logins into R1 172.16.1.104 and configures OSPF for all addresses.
0 1 2 |
$ ansible-playbook playbooks/pb6_iosconfig.yml --ask-become-pass |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
--- - name: Manage GNS3 devices hosts: 172.16.1.104 gather_facts: false connection: network_cli tasks: - name: enable ospf ios_config: parents: router ospf 1 lines: - network 0.0.0.0 255.255.255.255 area 0 become: yes become_method: enable register: print_output - debug: var=print_output |
Playbook IOS Configuration – Multi Device
Each play in a playbook can be performed on a set of devices. These can be groups, single or multiple hosts.
Group named lab_core
0 1 2 3 4 |
--- - name: Play1 - Manage GNS3 devices hosts: lab_core |
Single device, as appears in the inventory
0 1 2 3 4 |
--- - name: Play1 - Manage GNS3 devices hosts: 172.16.1.102 |
Multiple device, as they appear in the inventory
0 1 2 3 4 |
--- - name: Play1 - Manage GNS3 devices hosts: 172.16.1.102, 172.16.1.104, 172.16.1.124 |
Playbook IOS Configuration – Multiple Tasks
There can be multiple tasks in a single playbook that performs different functions for the same devices or a subset of them. In this playbook there tare two tasks to configure basic commands on the switches of the lab topology.
0 1 2 |
$ ansible-playbook -c paramiko playbooks/pb8_multitasks.yml |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
--- - name: Manage GNS3 devices hosts: lab_access gather_facts: false connection: network_cli tasks: - name: TASK1 - Global config settings ios_config: lines: - vtp mode transparent - spanning-tree mode rapid-pvst - errdisable recovery cause all - port-channel load-balance src-dst-ip - ip name-server 8.8.8.8 - snmp-server community python1 RO - snmp-server community python2 RW become: yes become_method: enable register: print_output - debug: var=print_output - name: TASK2 - Global config settings ios_config: parents: ipv6 nd raguard policy HOST_POLICY lines: - ntp server 87.81.181.2 - ntp update-calendar - clock timezone PST -8 - clock summer-time PDT recurring - service timestamps debug datetime msec localtime - service timestamps log datetime msec localtime become: yes become_method: enable register: print_output - debug: var=print_output |
Playbook IOS Configuration – Multiple Plays
There can be multiple plays in a single playbook. Each play has its own set of hosts to select and tasks associated with that play.
I have moved the enable password into the group_vars file for these plays.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$ tree . ├── default ansible hosts ├── inventory │ ├── group_vars │ │ └── all_devices │ │ └── all_devices.yml │ ├── router_switch_inv.ini │ └── usernames.txt ├── output │ ├── 172.16.1.102_iosfacts2.json │ ├── 172.16.1.103_iosfacts2.json │ ├── 172.16.1.104_iosfacts2.json │ └── 172.16.1.124_iosfacts2.json └── playbooks ├── pb1_basic.yml ├── pb2_ioscommand.yml ├── pb3_magicvars.yml ├── pb4_iosfacts.yml ├── pb5_iosfacts2.yml ├── pb6_iosconfig.yml ├── pb7_multitasks.yml └── pb8_multiplays.yml 5 directories, 16 files |
0 1 2 3 4 5 6 7 8 |
cat all_devices.yml --- ansible_network_os: ios ansible_user: admin ansible_password: Stefan2020 ansible_become_password: cisco |
In this example playbook I have two plays. The first is to enable OSPF on the router. And the second play is to create 4 VLANs on the selected switches.
0 1 2 3 4 |
ansible-playbook -c paramiko playbooks/pb8_multiplays.yml ansible-playbook -c paramiko playbooks/pb8_multiplays.yml --ask-become-pass |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
--- - name: Play1 - Manage GNS3 devices hosts: 172.16.1.104 gather_facts: false connection: network_cli tasks: - name: enable ospf ios_config: parents: router ospf 1 lines: - network 0.0.0.0 255.255.255.255 area 0 become: yes become_method: enable register: print_output - debug: var=print_output - name: Play 2 - Switch specific config hosts: 172.16.1.103, 172.16.1.124 gather_facts: false connection: network_cli tasks: - name: Create VLANs ios_config: lines: - vlan 200 - vlan 201 - vlan 202 - vlan 203 become: yes become_method: enable register: print_output - debug: var=print_output |