Use cases¶
Now, imagine if from your PC at your work, or when you go to support one of your customers, in a couple of minutes you can perform all of the following basics out of the box procedures, they will see you as a hero!
You could even redirect the logging of several network devices to your PC while you are working in order to see them with a syslog server on your PC, or only with the Salt event-bus, and after the jobs is done, revert the syslog change in seconds.
All this examples are running against a GNS3 virtual lab in my PC, you can do the same with the VM or installing it following the install guides. I am only running legacy IOS but they support others OS via NAPALM, and of course, regular server operating system.
Some tips before we start:
netor scripts
In time i will create netor-x style script just as a mask of the following commands, and again, ir order to try to make it easier to start using Ansible ans Salt. And i will had a simple command to update the /bin folder.
Ansible:
- I am providing a couple of playbook, some parses, and scripts for you to experiment.
- You might see some warning related to Python2 getting to end of support, and some other pieces of code about to get deprecated. Typical linux style, letting you know about thing that are about to change.
- you con limit the devices to execute a playbook by adding
-l xxx
. Where xxx is regEx filter. - you can add
--check --diff
to check commands before applying and to show the differences to apply. - you can send information from the playbook to a parser to crop information and/or to script to do something else, this means that there is communication between to move information and act accordingly.
ansible-playbook
is the command to execute playbooks, you have to cd to the playbooks directory- Ansible is kind of static, because it only do something when you enter a command. If you want to trigger actions you have to use an external tool, like Nagios. If Nagios detects something execute this Ansible playbook.
Salt:
- what it super cool about Salt is the even if the commands are weird at the beginning, all of the modules/functions have a help right at the command line, i will show you how.
salt
is for execution online commands against the devicessalt-run
is for executing commands with information that Salt already- to every command you can add at the end
-l debug
to check what is going on. - it has incredible
net.bgp
module to check for information, to configure and potentially react. - Salt has a cache database with information gathered by runners, the cool thing about this is that you don’t need to install and maintain a separate DB to store information like regular network management software requires.
- Salt has an event bus, which you can see with
salt-run state.event pretty=True
, the amazing thing about this is that you can start thinking in Orchestration, or in other words, define a reactor to an event when some message gets to the event bus. You can even attach a chat bot.
Ansible examples¶
From easy to hard
Make a backup
*adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook backup.yml -l c1*
PLAY [Backup devices configs] *************************************************************************************************
TASK [Read IOS configs] *******************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
ok: [c1_s1_ua-1]
TASK [Save IOS config] ********************************************************************************************************
changed: [c1_s1_cpe]
changed: [c1_s1_ua-1]
changed: [c1_s1_co-1]
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ls -la ../backup/
total 160
drwxr-xr-x 2 adrian adrian 4096 Nov 15 22:49 .
drwxr-xr-x 6 adrian adrian 4096 Nov 15 22:47 ..
-rw-rw-r-- 1 adrian adrian 3428 Nov 15 22:49 show_run_c1_s1_co-1.txt
-rw-rw-r-- 1 adrian adrian 2262 Nov 15 22:49 show_run_c1_s1_cpe.txt
-rw-rw-r-- 1 adrian adrian 3082 Nov 15 22:49 show_run_c1_s1_ua-1.txt
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$
show arp tables
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook show-arp.yml -l c1_s1_cpe
PLAY [Show IP ARP] ************************************************************************************************************
TASK [Show IP ARP] ************************************************************************************************************
ok: [c1_s1_cpe]
TASK [debug] ******************************************************************************************************************
ok: [c1_s1_cpe] => {
"list_of_ip_arp.stdout_lines": [
[
"Protocol Address Age (min) Hardware Addr Type Interface",
"Internet 10.0.12.1 68 c201.375c.0001 ARPA FastEthernet0/0",
"Internet 10.0.12.2 - c202.5d80.0000 ARPA FastEthernet0/0",
"Internet 10.100.12.1 - c202.5d80.0001 ARPA FastEthernet0/1",
"Internet 10.100.12.2 68 c204.5f8c.0000 ARPA FastEthernet0/1"
]
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_cpe : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
gather-facts, which is the device basic information
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook gather-facts.yml -l c1_s1_cpe
PLAY [Gather IOS facts] *******************************************************************************************************
TASK [gather all facts] *******************************************************************************************************
ok: [c1_s1_cpe]
TASK [Display the OS version] *************************************************************************************************
ok: [c1_s1_cpe] => {
"msg": "The hostname is r2 and the OS is 12.4(15)T13"
}
TASK [Display config] *********************************************************************************************************
ok: [c1_s1_cpe] => {
"msg": {
"ansible_facts": {
"ansible_net_api": "cliconf",
"ansible_net_config": "!\nversion 12.4\nno service pad\nservice tcp-keepalives-in\nservice tcp-keepalives-out\nservice timestamps debug datetime msec localtime show-timezone\nservice timestamps log datetime msec localtime show-timezone\nservice password-encryption\n!\nhostname r2\n!\nboot-start-marker\nboot-end-marker\n!\nlogging buffered 32000\nno logging console\nenable secret 5 $1$QAh2$FiUShFDsaikloAgWmKsW1.\n!\naaa new-model\n!\n!\naaa authentication login default local-case\naaa authorization exec default local \n!\n!\naaa session-id common\nmemory-size iomem 5\nno ip source-route\nip options drop\nip cef\n!\n!\nip dhcp bootp ignore\n!\n!\nno ip domain lookup\nip domain name quadrant.edu\n!\nmultilink bundle-name authenticated\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\nfile prompt quiet\nusername cisco privilege 15 secret 5 $1$OKM5$WoIzwQQ6Xrlt3ymrIH8VE/\narchive\n log config\n hidekeys\n! \n!\n!\n!\nip ssh version 2\nip scp server enable\n!\n!\n!\n!\ninterface FastEthernet0/0\n description to_r1\n ip address 10.0.12.2 255.255.255.0\n no ip redirects\n no ip proxy-arp\n duplex auto\n speed auto\n!\ninterface FastEthernet0/1\n description to_inside\n ip address 10.100.12.1 255.255.255.0\n no ip redirects\n no ip proxy-arp\n duplex auto\n speed auto\n!\ninterface FastEthernet1/0\n no ip address\n shutdown\n duplex auto\n speed auto\n!\nrouter eigrp 1\n network 10.0.0.0\n no auto-summary\n!\nip forward-protocol nd\nip route 0.0.0.0 0.0.0.0 10.0.12.1\n!\n!\nno ip http server\nno ip http secure-server\n!\nip sla 1\n udp-echo 10.0.12.1 999\n timeout 4000\n tag probe1_test2\n frequency 5\n history lives-kept 1\n history buckets-kept 3\n history filter all\nip sla 2\n icmp-echo 10.0.12.1\n tag probe1_test1\n history lives-kept 1\n history filter all\nsnmp-server community snmpCommunity RW\nsnmp-server community read_only RO\nsnmp-server community read_write RW\n!\n!\n!\n!\n!\n!\ncontrol-plane\n!\n!\n!\n!\n!\n!\n!\n!\n!\nbanner login ^C\n\nUnauthorized access is prohibited!\n\n^C\n!\nline con 0\n exec-timeout 20 0\n logging synchronous\nline aux 0\n exec-timeout 0 1\n no exec\n transport output none\nline vty 0 4\n exec-timeout 20 0\n logging synchronous\n transport input ssh\n transport output ssh\nline vty 5 15\n exec-timeout 20 0\n logging synchronous\n transport input ssh\n transport output ssh\n!\nntp server 10.0.0.2\n!\nend",
"ansible_net_gather_network_resources": [],
"ansible_net_gather_subset": [
"default",
"config"
],
"ansible_net_hostname": "r2",
"ansible_net_image": "tftp://255.255.255.255/unknown",
"ansible_net_iostype": "IOS",
"ansible_net_model": "3725",
"ansible_net_python_version": "2.7.15+",
"ansible_net_serialnum": "FTX0945W0MY",
"ansible_net_system": "ios",
"ansible_net_version": "12.4(15)T13",
"ansible_network_resources": {},
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"failed": false,
"warnings": [
"default value for \`gather_subset` will be changed to \`min` from \`!config` v2.11 onwards",
"Platform linux on host c1_s1_cpe is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information."
]
}
}
PLAY RECAP ********************************************************************************************************************
c1_s1_cpe : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
add a regular show command at ‘cmd=’
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook ios-show-cmd.yml -e cmd="'run | inc snmp'" -l c1_s1
PLAY [IOS show cmd] ***********************************************************************************************************
TASK [IOS show cmd] ***********************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
ok: [c1_s1_ua-1]
TASK [debug] ******************************************************************************************************************
ok: [c1_s1_co-1] => {
"output.stdout_lines": [
[
"snmp-server community snmpCommunity RW"
]
]
}
ok: [c1_s1_ua-1] => {
"output.stdout_lines": [
[
"snmp-server community snmpCommunity RW"
]
]
}
ok: [c1_s1_cpe] => {
"output.stdout_lines": [
[
"snmp-server community snmpCommunity RW",
"snmp-server community read_only RO",
"snmp-server community read_write RW"
]
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook ios-show-cmd.yml -e "cmd='ip int bri'" -l c1_s1
PLAY [IOS show cmd] ***********************************************************************************************************
TASK [IOS show cmd] ***********************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
ok: [c1_s1_ua-1]
TASK [debug] ******************************************************************************************************************
ok: [c1_s1_cpe] => {
"output.stdout_lines": [
[
"Interface IP-Address OK? Method Status Protocol",
"FastEthernet0/0 10.0.12.2 YES NVRAM up up ",
"FastEthernet0/1 10.100.12.1 YES NVRAM up up ",
"FastEthernet1/0 unassigned YES NVRAM administratively down down"
]
]
}
ok: [c1_s1_co-1] => {
"output.stdout_lines": [
[
"Interface IP-Address OK? Method Status Protocol",
"FastEthernet0/0 10.100.12.2 YES NVRAM up up ",
"FastEthernet0/1 unassigned YES unset administratively down down ",
"FastEthernet1/0 unassigned YES unset up up ",
"FastEthernet1/1 unassigned YES unset up down ",
"FastEthernet1/2 unassigned YES unset up down ",
"FastEthernet1/3 unassigned YES unset up down ",
"FastEthernet1/4 unassigned YES unset up down ",
"FastEthernet1/5 unassigned YES unset up down ",
"FastEthernet1/6 unassigned YES unset up down ",
"FastEthernet1/7 unassigned YES unset up down ",
"FastEthernet1/8 unassigned YES unset up down ",
"FastEthernet1/9 unassigned YES unset up down ",
"FastEthernet1/10 unassigned YES unset up down ",
"FastEthernet1/11 unassigned YES unset up down ",
"FastEthernet1/12 unassigned YES unset up down ",
"FastEthernet1/13 unassigned YES unset up down ",
"FastEthernet1/14 unassigned YES unset up down ",
"FastEthernet1/15 unassigned YES unset up down ",
"Vlan1 unassigned YES NVRAM administratively down down ",
"Vlan10 10.100.200.1 YES NVRAM up up"
]
]
}
ok: [c1_s1_ua-1] => {
"output.stdout_lines": [
[
"Interface IP-Address OK? Method Status Protocol",
"FastEthernet0/0 unassigned YES NVRAM administratively down down ",
"FastEthernet0/1 unassigned YES NVRAM administratively down down ",
"FastEthernet1/0 unassigned YES unset up up ",
"FastEthernet1/1 unassigned YES unset up up ",
"FastEthernet1/2 unassigned YES unset up up ",
"FastEthernet1/3 unassigned YES unset up down ",
"FastEthernet1/4 unassigned YES unset up down ",
"FastEthernet1/5 unassigned YES unset up down ",
"FastEthernet1/6 unassigned YES unset up down ",
"FastEthernet1/7 unassigned YES unset up down ",
"FastEthernet1/8 unassigned YES unset up down ",
"FastEthernet1/9 unassigned YES unset up down ",
"FastEthernet1/10 unassigned YES unset up down ",
"FastEthernet1/11 unassigned YES unset up down ",
"FastEthernet1/12 unassigned YES unset up down ",
"FastEthernet1/13 unassigned YES unset up down ",
"FastEthernet1/14 unassigned YES unset up down ",
"FastEthernet1/15 unassigned YES unset up down ",
"Vlan1 unassigned YES NVRAM administratively down down ",
"Vlan10 10.100.200.2 YES NVRAM up up"
]
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook ios-show-cmd.yml -e "cmd='ip arp'" -l c1_s1
PLAY [IOS show cmd] ***********************************************************************************************************
TASK [IOS show cmd] ***********************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
TASK [debug] ******************************************************************************************************************
ok: [c1_s1_co-1] => {
"output.stdout_lines": [
[
"Protocol Address Age (min) Hardware Addr Type Interface",
"Internet 10.100.12.1 75 c202.5d80.0001 ARPA FastEthernet0/0",
"Internet 10.100.12.2 - c204.5f8c.0000 ARPA FastEthernet0/0",
"Internet 10.100.200.1 - c204.5f8c.0000 ARPA Vlan10",
"Internet 10.100.200.2 75 c206.1b68.0000 ARPA Vlan10"
]
]
}
ok: [c1_s1_cpe] => {
"output.stdout_lines": [
[
"Protocol Address Age (min) Hardware Addr Type Interface",
"Internet 10.0.12.1 75 c201.375c.0001 ARPA FastEthernet0/0",
"Internet 10.0.12.2 - c202.5d80.0000 ARPA FastEthernet0/0",
"Internet 10.100.12.1 - c202.5d80.0001 ARPA FastEthernet0/1",
"Internet 10.100.12.2 75 c204.5f8c.0000 ARPA FastEthernet0/1"
]
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
show interfaces
This playbook is using the ansible network engine role and/with a parser, which means that the standard output is being send to an external script to crop that output and give back the results to Ansible to show it.
You can still get the same info in a simpler way, the interesting part here is to show the power of roles, parses, and scripts, in order to process the regular output.
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook ne-showintf.yml -l c1_s1
PLAY [GENERATE A REPORT] ******************************************************************************************************
TASK [CAPTURE SHOW IP INTERFACE] **********************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
TASK [PARSE THE RAW OUTPUT] ***************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
TASK [Display the data] *******************************************************************************************************
ok: [c1_s1_cpe] => {
"interface_facts": {
"FastEthernet0/0": {
"config": {
"description": "to_r1",
"mtu": "1500",
"name": "FastEthernet0/0",
"type": null
}
},
"FastEthernet0/1": {
"config": {
"description": "to_inside",
"mtu": "1500",
"name": "FastEthernet0/1",
"type": "AmdFE"
}
}
}
}
ok: [c1_s1_co-1] => {
"interface_facts": {
"FastEthernet0/0": {
"config": {
"description": "to_inet",
"mtu": "1500",
"name": "FastEthernet0/0",
"type": null
}
},
"FastEthernet1/0": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/0",
"type": null
}
},
"FastEthernet1/1": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/1",
"type": null
}
},
"FastEthernet1/10": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/10",
"type": null
}
},
"FastEthernet1/11": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/11",
"type": null
}
},
"FastEthernet1/12": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/12",
"type": null
}
},
"FastEthernet1/13": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/13",
"type": null
}
},
"FastEthernet1/14": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/14",
"type": null
}
},
"FastEthernet1/15": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/15",
"type": "EtherSVI"
}
},
"FastEthernet1/2": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/2",
"type": null
}
},
"FastEthernet1/3": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/3",
"type": null
}
},
"FastEthernet1/4": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/4",
"type": null
}
},
"FastEthernet1/5": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/5",
"type": null
}
},
"FastEthernet1/6": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/6",
"type": null
}
},
"FastEthernet1/7": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/7",
"type": null
}
},
"FastEthernet1/8": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/8",
"type": null
}
},
"FastEthernet1/9": {
"config": {
"description": null,
"mtu": "1500",
"name": "FastEthernet1/9",
"type": null
}
},
"Vlan10": {
"config": {
"description": "LAN",
"mtu": "1500",
"name": "Vlan10",
"type": "EtherSVI"
}
}
}
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
** Another example of parsers to show ip interface brief**
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook ne-showipintf.yml -l c1_s1
PLAY [GENERATE A REPORT] ******************************************************************************************************
TASK [CAPTURE SHOW IP INTERFACE] **********************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
TASK [PARSE THE RAW OUTPUT] ***************************************************************************************************
ok: [c1_s1_co-1]
ok: [c1_s1_ua-1]
ok: [c1_s1_cpe]
TASK [DISPLAY THE DATA] *******************************************************************************************************
ok: [c1_s1_cpe] => {
"ip_interface_facts": [
{
"FastEthernet0/0": {
"data": {
"admin_state": "up",
"ip": "10.0.12.2",
"name": "FastEthernet0/0",
"protocol_state": "up"
}
}
},
{
"FastEthernet0/1": {
"data": {
"admin_state": "up",
"ip": "10.100.12.1",
"name": "FastEthernet0/1",
"protocol_state": "up"
}
}
}
]
}
ok: [c1_s1_co-1] => {
"ip_interface_facts": [
{
"FastEthernet0/0": {
"data": {
"admin_state": "up",
"ip": "10.100.12.2",
"name": "FastEthernet0/0",
"protocol_state": "up"
}
}
},
{
"Vlan10": {
"data": {
"admin_state": "up",
"ip": "10.100.200.1",
"name": "Vlan10",
"protocol_state": "up"
}
}
}
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
this example send the output to a python script which proceses the data and returns a dictornary to Ansible in order to format the output
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook ne-show-ver.yml -l c1_s1
PLAY [Show Cisco HW, SN, and SW version] **************************************************************************************
TASK [Show version] ***********************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
ok: [c1_s1_ua-1]
TASK [PARSE THE RAW OUTPUT] ***************************************************************************************************
ok: [c1_s1_ua-1]
ok: [c1_s1_co-1]
ok: [c1_s1_cpe]
TASK [execute python script] **************************************************************************************************
changed: [c1_s1_co-1 -> localhost]
changed: [c1_s1_ua-1 -> localhost]
changed: [c1_s1_cpe -> localhost]
TASK [debug] ******************************************************************************************************************
ok: [c1_s1_co-1] => {
"output.stdout_lines": [
"Hostname: c1_s1_co-1",
"Serial_Number: FTX0945W0MY",
"Software_Release: fc3",
"Hardware_Version: 3725",
"Software_Version: 12.4(15)T13",
"Software_Image: C3725-ADVENTERPRISEK9-M"
]
}
ok: [c1_s1_cpe] => {
"output.stdout_lines": [
"Hostname: c1_s1_cpe",
"Serial_Number: FTX0945W0MY",
"Software_Release: fc3",
"Hardware_Version: 3725",
"Software_Version: 12.4(15)T13",
"Software_Image: C3725-ADVENTERPRISEK9-M"
]
}
ok: [c1_s1_ua-1] => {
"output.stdout_lines": [
"Hostname: c1_s1_ua-1",
"Serial_Number: FTX0945W0MY",
"Software_Release: fc3",
"Hardware_Version: 3725",
"Software_Version: 12.4(15)T13",
"Software_Image: C3725-ADVENTERPRISEK9-M"
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
example on how to set up snmp
In this case, the configuration was applied to two devices, because the 3rd one already had it. Look for the word “changed”
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook set-snmp.yml -l c1_s1
PLAY [Set SNMP] ***************************************************************************************************************
TASK [Configure SNMP comminities on devices] **********************************************************************************
ok: [c1_s1_cpe]
changed: [c1_s1_co-1]
changed: [c1_s1_ua-1]
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook ios-show-cmd.yml -e "cmd='run | inc snmp'" -l c1_s1
PLAY [IOS show cmd] ***********************************************************************************************************
TASK [IOS show cmd] ***********************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
ok: [c1_s1_ua-1]
TASK [debug] ******************************************************************************************************************
ok: [c1_s1_cpe] => {
"output.stdout_lines": [
[
"snmp-server community snmpCommunity RW",
"snmp-server community read_only RO",
"snmp-server community read_write RW"
]
]
}
ok: [c1_s1_co-1] => {
"output.stdout_lines": [
[
"snmp-server community snmpCommunity RW",
"snmp-server community read_only RO",
"snmp-server community read_write RW"
]
]
}
ok: [c1_s1_ua-1] => {
"output.stdout_lines": [
[
"snmp-server community snmpCommunity RW",
"snmp-server community read_only RO",
"snmp-server community read_write RW"
]
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
another case of show arp
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook show-arp.yml -l c1_s1
PLAY [Show IP ARP] ************************************************************************************************************
TASK [Show IP ARP] ************************************************************************************************************
ok: [c1_s1_cpe]
ok: [c1_s1_co-1]
ok: [c1_s1_ua-1]
TASK [debug] ******************************************************************************************************************
ok: [c1_s1_co-1] => {
"list_of_ip_arp.stdout_lines": [
[
"Protocol Address Age (min) Hardware Addr Type Interface",
"Internet 10.100.12.1 78 c202.5d80.0001 ARPA FastEthernet0/0",
"Internet 10.100.12.2 - c204.5f8c.0000 ARPA FastEthernet0/0",
"Internet 10.100.200.1 - c204.5f8c.0000 ARPA Vlan10",
"Internet 10.100.200.2 78 c206.1b68.0000 ARPA Vlan10"
]
]
}
ok: [c1_s1_ua-1] => {
"list_of_ip_arp.stdout_lines": [
[
"Protocol Address Age (min) Hardware Addr Type Interface",
"Internet 10.100.200.1 78 c204.5f8c.0000 ARPA Vlan10",
"Internet 10.100.200.2 - c206.1b68.0000 ARPA Vlan10"
]
]
}
ok: [c1_s1_cpe] => {
"list_of_ip_arp.stdout_lines": [
[
"Protocol Address Age (min) Hardware Addr Type Interface",
"Internet 10.0.12.1 78 c201.375c.0001 ARPA FastEthernet0/0",
"Internet 10.0.12.2 - c202.5d80.0000 ARPA FastEthernet0/0",
"Internet 10.100.12.1 - c202.5d80.0001 ARPA FastEthernet0/1",
"Internet 10.100.12.2 78 c204.5f8c.0000 ARPA FastEthernet0/1"
]
]
}
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
getting better, this one checks if an ACL is already there, and if not it will apply it
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook check-acl.yml -l c1_s1 --check
PLAY [Check or create exact ACL order] ****************************************************************************************
TASK [Check or create exact ACL order] ****************************************************************************************
changed: [c1_s1_cpe]
changed: [c1_s1_co-1]
changed: [c1_s1_ua-1]
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
adrian@adrian-VirtualBox:~/netor/netor/ansible/playbooks$ ansible-playbook check-acl.yml -l c1_s1 --check --diff
PLAY [Check or create exact ACL order] ****************************************************************************************
TASK [Check or create exact ACL order] ****************************************************************************************
changed: [c1_s1_cpe]
changed: [c1_s1_co-1]
changed: [c1_s1_ua-1]
PLAY RECAP ********************************************************************************************************************
c1_s1_co-1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_cpe : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c1_s1_ua-1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Salt examples¶
From easy to hard
basic to test the connection between Salt and the devices
adrian@adrian-VirtualBox:~$ sudo salt 'c1_s1*' test.ping
c1_s1_ua-1:
True
c1_s1_co-1:
True
c1_s1_cpe:
True
you can also add the ``-l debug`` flag
adrian@adrian-VirtualBox:~$ sudo salt 'c1_s1*' test.ping -l debug
[DEBUG ] Reading configuration from /etc/salt/master
[DEBUG ] Using cached minion ID from /etc/salt/minion_id: adrian-VirtualBox
[DEBUG ] Missing configuration file: /home/adrian/.saltrc
[DEBUG ] Configuration file path: /etc/salt/master
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[DEBUG ] Reading configuration from /etc/salt/master
[DEBUG ] Using cached minion ID from /etc/salt/minion_id: adrian-VirtualBox
[DEBUG ] Missing configuration file: /home/adrian/.saltrc
[DEBUG ] MasterEvent PUB socket URI: /var/run/salt/master/master_event_pub.ipc
[DEBUG ] MasterEvent PULL socket URI: /var/run/salt/master/master_event_pull.ipc
[DEBUG ] Initializing new AsyncZeroMQReqChannel for ('/home/adrian/netor-master/netor/salt/config/pki/master', 'adrian-VirtualBox_master', 'tcp://127.0.0.1:4506', 'clear')
[DEBUG ] Connecting the Minion to the Master URI (for the return server): tcp://127.0.0.1:4506
[DEBUG ] Trying to connect to: tcp://127.0.0.1:4506
[DEBUG ] Closing AsyncZeroMQReqChannel instance
[DEBUG ] LazyLoaded local_cache.get_load
[DEBUG ] Reading minion list from /var/cache/salt/master/jobs/ba/6ceb1709725e52888fafec43611acca92cb7287fe14f0aab323f7711bbc3f0/.minions.p
[DEBUG ] get_iter_returns for jid 20191116123204208193 sent to {'c1_s1_cpe', 'c1_s1_co-1', 'c1_s1_ua-1'} will timeout at 12:32:09.226416
[DEBUG ] jid 20191116123204208193 return from c1_s1_ua-1
[DEBUG ] return event: {'c1_s1_ua-1': {'ret': True, 'retcode': 0, 'jid': '20191116123204208193'}}
[DEBUG ] LazyLoaded nested.output
c1_s1_ua-1:
True
[DEBUG ] jid 20191116123204208193 return from c1_s1_cpe
[DEBUG ] return event: {'c1_s1_cpe': {'ret': True, 'retcode': 0, 'jid': '20191116123204208193'}}
[DEBUG ] LazyLoaded nested.output
c1_s1_cpe:
True
[DEBUG ] jid 20191116123204208193 return from c1_s1_co-1
[DEBUG ] return event: {'c1_s1_co-1': {'ret': True, 'retcode': 0, 'jid': '20191116123204208193'}}
[DEBUG ] LazyLoaded nested.output
c1_s1_co-1:
True
[DEBUG ] jid 20191116123204208193 found all minions {'c1_s1_cpe', 'c1_s1_ua-1', 'c1_s1_co-1'}
[DEBUG ] Closing IPCMessageSubscriber instance
adrian@adrian-VirtualBox:~$
this is i think the coolest and easiest function of Salt
The net.find module allows you to search in 3 seconds information gathered by mining. Lets look for IP address, MACs, interface descriptions, vlan, etc. configured on the devices.
adrian@adrian-VirtualBox:~/netor/netor/salt$ sudo salt-run net.find 10.0.0.0/8 best=False
Details for all interfaces that include network 10.0.0.0/8
------------------------------------------------------------------------------------------------------------------------------
| Device | Interface | Interface Description | IP Addresses | Enabled | UP | MAC Address | Speed [Mbps] |
------------------------------------------------------------------------------------------------------------------------------
| c1_s1_co-1 | FastEthernet0/0 | to_inet | 10.100.12.2/24 | True | True | C2:04:5F:8C:00:00 | 10 |
------------------------------------------------------------------------------------------------------------------------------
| c1_s1_co-1 | Vlan10 | LAN | 10.100.200.1/24 | True | True | C2:04:5F:8C:00:00 | 100 |
------------------------------------------------------------------------------------------------------------------------------
| c1_s1_cpe | FastEthernet0/0 | to_r1 | 10.0.12.2/24 | True | True | C2:02:5D:80:00:00 | 10 |
------------------------------------------------------------------------------------------------------------------------------
| c1_s1_cpe | FastEthernet0/1 | to_inside | 10.100.12.1/24 | True | True | C2:02:5D:80:00:01 | 10 |
------------------------------------------------------------------------------------------------------------------------------
| c1_s1_ua-1 | Vlan10 | user1 | 10.100.200.2/24 | True | True | C2:06:1B:68:00:00 | 100 |
------------------------------------------------------------------------------------------------------------------------------
| c2_s1_co-1 | FastEthernet0/0 | to_inet | 10.101.23.2/24 | True | True | C2:05:48:3C:00:00 | 10 |
------------------------------------------------------------------------------------------------------------------------------
| c2_s1_co-1 | Vlan10 | LAN | 10.101.201.1/24 | True | True | C2:05:48:3C:00:00 | 100 |
------------------------------------------------------------------------------------------------------------------------------
| c2_s1_cpe | FastEthernet0/0 | to_r1 | 10.0.13.2/24 | True | True | C2:03:29:20:00:00 | 10 |
------------------------------------------------------------------------------------------------------------------------------
| c2_s1_cpe | FastEthernet0/1 | to_inside | 10.101.23.1/24 | True | True | C2:03:29:20:00:01 | 10 |
------------------------------------------------------------------------------------------------------------------------------
| c2_s1_ua-1 | Vlan10 | user1 | 10.101.201.2/24 | True | True | C2:07:61:70:00:00 | 100 |
------------------------------------------------------------------------------------------------------------------------------
None
adrian@adrian-VirtualBox:~/netor/netor/salt$ sudo salt-run net.find Vlan10
Pattern "Vlan10" found in the description of the following interfaces
Details for interface Vlan10
------------------------------------------------------------------------------------------------------------------------
| Device | Interface | Interface Description | IP Addresses | Enabled | UP | MAC Address | Speed [Mbps] |
------------------------------------------------------------------------------------------------------------------------
| c1_s1_ua-1 | Vlan10 | user1 | 10.100.200.2/24 | True | True | C2:06:1B:68:00:00 | 100 |
------------------------------------------------------------------------------------------------------------------------
| c2_s1_ua-1 | Vlan10 | user1 | 10.101.201.2/24 | True | True | C2:07:61:70:00:00 | 100 |
------------------------------------------------------------------------------------------------------------------------
Details for all interfaces on device Vlan10
Pattern "Vlan10" found in one of the following LLDP details
LLDP Neighbors for interface Vlan10
LLDP Neighbors for all interfaces on device Vlan10
MAC Address(es) on device Vlan10
MAC Address(es) on interface Vlan10
ARP Entries on device Vlan10
ARP Entries on interface Vlan10
---------------------------------------------------------------------
| Age | Device | Interface | IP | MAC |
---------------------------------------------------------------------
| 108.0 | c1_s1_ua-1 | Vlan10 | 10.100.200.1 | C2:04:5F:8C:00:00 |
---------------------------------------------------------------------
| 0.0 | c1_s1_ua-1 | Vlan10 | 10.100.200.2 | C2:06:1B:68:00:00 |
---------------------------------------------------------------------
| 108.0 | c2_s1_ua-1 | Vlan10 | 10.101.201.1 | C2:05:48:3C:00:00 |
---------------------------------------------------------------------
| 0.0 | c2_s1_ua-1 | Vlan10 | 10.101.201.2 | C2:07:61:70:00:00 |
---------------------------------------------------------------------
adrian@adrian-VirtualBox:~/netor/netor/salt$ sudo salt-run net.find to_inside
Pattern "to_inside" found in the description of the following interfaces
----------------------------------------------------------------------------------------------------------------------------
| Device | Interface | Interface Description | IP Addresses | Enabled | UP | MAC Address | Speed [Mbps] |
----------------------------------------------------------------------------------------------------------------------------
| c1_s1_cpe | FastEthernet0/1 | to_inside | 10.100.12.1/24 | True | True | C2:02:5D:80:00:01 | 10 |
----------------------------------------------------------------------------------------------------------------------------
Details for interface to_inside
Details for all interfaces on device to_inside
Pattern "to_inside" found in one of the following LLDP details
LLDP Neighbors for interface to_inside
LLDP Neighbors for all interfaces on device to_inside
MAC Address(es) on device to_inside
MAC Address(es) on interface to_inside
ARP Entries on device to_inside
ARP Entries on interface to_inside
None
adrian@adrian-VirtualBox:~/netor/netor/salt$ sudo salt-run net.find 10.100.12.1
Details for all interfaces that include network 10.100.12.1/32 - only best match returned
----------------------------------------------------------------------------------------------------------------------------
| Device | Interface | Interface Description | IP Addresses | Enabled | UP | MAC Address | Speed [Mbps] |
----------------------------------------------------------------------------------------------------------------------------
| c1_s1_cpe | FastEthernet0/1 | to_inside | 10.100.12.1/24 | True | True | C2:02:5D:80:00:01 | 10 |
----------------------------------------------------------------------------------------------------------------------------
ARP Entries for IP 10.100.12.1
-----------------------------------------------------------------------
| Age | Device | Interface | IP | MAC |
-----------------------------------------------------------------------
| 0.0 | c1_s1_cpe | FastEthernet0/1 | 10.100.12.1 | C2:02:5D:80:00:01 |
-----------------------------------------------------------------------
IP Address 10.100.12.1 is set for interface FastEthernet0/1, on c1_s1_cpe
----------------------------------------------------------------------------------------------------------------------------
| Device | Interface | Interface Description | IP Addresses | Enabled | UP | MAC Address | Speed [Mbps] |
----------------------------------------------------------------------------------------------------------------------------
| c1_s1_cpe | FastEthernet0/1 | to_inside | 10.100.12.1/24 | True | True | C2:02:5D:80:00:01 | 10 |
----------------------------------------------------------------------------------------------------------------------------
LLDP Neighbors for interface FastEthernet0/1 on device c1_s1_cpe
None
adrian@adrian-VirtualBox:~/netor/netor/salt$ sudo salt-run net.find C2:02:5D:80:00:01
MAC Address(es)
ARP Entries for MAC C2:02:5D:80:00:01
--------------------------------------------------------------------------
| Age | Device | Interface | IP | MAC |
--------------------------------------------------------------------------
| 114.0 | c1_s1_co-1 | FastEthernet0/0 | 10.100.12.1 | C2:02:5D:80:00:01 |
--------------------------------------------------------------------------
LLDP Neighbors for all interfaces having Chassis ID C2:02:5D:80:00:01
Interface FastEthernet0/1 on c1_s1_cpe has the physical address (C2:02:5D:80:00:01)
----------------------------------------------------------------------------------------------------------------------------
| Device | Interface | Interface Description | IP Addresses | Enabled | UP | MAC Address | Speed [Mbps] |
----------------------------------------------------------------------------------------------------------------------------
| c1_s1_cpe | FastEthernet0/1 | to_inside | 10.100.12.1/24 | True | True | C2:02:5D:80:00:01 | 10 |
----------------------------------------------------------------------------------------------------------------------------
LLDP Neighbors for interface FastEthernet0/1 on device c1_s1_cpe
None
States, great concept!
It is getting better…
Salt define a sate in a file in which you can define attributes (like ntp in this example), and later you can apply that state/attribute to any OS. Yes it will figure out what commands to execute depending on the OS.
Read about this state ntp.sls file at the netor/salt/config/pillar/states
folder.
adrian@adrian-VirtualBox:~/netor/netor/salt$ sudo salt 'c1_s1_cpe' state.apply ntp
c1_s1_cpe:
----------
ID: netntp
Function: netntp.managed
Result: True
Comment: Device configured properly.
Started: 23:44:39.097859
Duration: 1629.019 ms
Changes:
Summary for c1_s1_cpe
------------
Succeeded: 1
Failed: 0
------------
Total states run: 1
Total run time: 1.629 s
adrian@adrian-VirtualBox:~/netor/netor/salt$
adrian@adrian-VirtualBox:~/netor/netor/salt$ more ./config/pillar/states/ntp.sls
netntp:
netntp.managed:
- servers:
- 10.0.0.2
adrian@adrian-VirtualBox:~/netor/netor/salt$
this is how you can view the event bus
You will see what happens when you apply the state
adrian@adrian-VirtualBox:~/netor/netor/salt$ sudo salt-run state.event pretty=True
20191115234741088036 {
"_stamp": "2019-11-15T22:47:41.088306",
"minions": [
"c1_s1_cpe"
]
}
salt/job/20191115234741088036/new {
"_stamp": "2019-11-15T22:47:41.088725",
"arg": [
"ntp"
],
"fun": "state.apply",
"jid": "20191115234741088036",
"minions": [
"c1_s1_cpe"
],
"missing": [],
"tgt": "c1_s1_cpe",
"tgt_type": "glob",
"user": "sudo_adrian"
}
minion/refresh/c1_s1_cpe {
"Minion data cache refresh": "c1_s1_cpe",
"_stamp": "2019-11-15T22:47:41.300837"
}
salt/job/20191115234741088036/ret/c1_s1_cpe {
"_stamp": "2019-11-15T22:47:43.462567",
"cmd": "_return",
"fun": "state.apply",
"fun_args": [
"ntp"
],
"id": "c1_s1_cpe",
"jid": "20191115234741088036",
"out": "highstate",
"retcode": 0,
"return": {
"netntp_-netntp_-netntp_-managed": {
"__id__": "netntp",
"__run_num__": 0,
"__sls__": "ntp",
"changes": {},
"comment": "Device configured properly.",
"duration": 2026.341,
"name": "netntp",
"result": true,
"start_time": "23:47:41.424906"
}
},
"success": true
}
how to use the online help of the commands
In this case the mine function/module
adrian@lmint2:~$ sudo salt-run mine
mine.get:
Gathers the data from the specified minions' mine, pass in the target,
function to look up and the target type
CLI Example:
salt-run mine.get '*' network.interfaces
mine.update:
New in version 2017.7.0
Update the mine data on a certain group of minions.
tgt
Which minions to target for the execution.
tgt_type: ``glob``
The type of ``tgt``.
clear: ``False``
Boolean flag specifying whether updating will clear the existing
mines, or will update. Default: ``False`` (update).
mine_functions
Update the mine data on certain functions only.
This feature can be used when updating the mine for functions
that require refresh at different intervals than the rest of
the functions specified under ``mine_functions`` in the
minion/master config or pillar.
CLI Example:
salt-run mine.update '*'
salt-run mine.update 'juniper-edges' tgt_type='nodegroup'
... continue
wait you can do a simulation with the “test=True” option
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' state.apply sla test=True
c1_s1_cpe:
----------
ID: rpmprobes
Function: probes.managed
Result: None
Comment: Testing mode: configuration was not changed!
Started: 10:37:24.816077
Duration: 1648.158 ms
Changes:
----------
added:
----------
probe_name1:
----------
probe1_test1:
----------
probe_type:
icmp-ping
target:
10.0.12.1
probe1_test2:
----------
probe_count:
3
probe_type:
udp-ping
source:
10.100.12.1
target:
10.0.12.1
test_interval:
5
removed:
None
updated:
None
Summary for c1_s1_cpe
------------
Succeeded: 1 (unchanged=1, changed=1)
Failed: 0
------------
Total states run: 1
Total run time: 1.648 s
check a running configuration
This command will take 3 second since you can have a proxy minion with a session already established with the device
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.config source='running'
c1_s1_cpe:
----------
comment:
out:
----------
candidate:
running:
Building configuration...
Current configuration : 2202 bytes
!
version 12.4
no service pad
service tcp-keepalives-in
service tcp-keepalives-out
service timestamps debug datetime msec localtime show-timezone
service timestamps log datetime msec localtime show-timezone
service password-encryption
!
hostname r2
!
boot-start-marker
boot-end-marker
!
logging buffered 32000
no logging console
enable secret 5 $1$QAh2$FiUShFDsaikloAgWmKsW1.
!
aaa new-model
!
!
aaa authentication login default local-case
aaa authorization exec default local
!
!
aaa session-id common
memory-size iomem 5
no ip source-route
ip options drop
ip cef
!
!
ip dhcp bootp ignore
!
!
no ip domain lookup
ip domain name quadrant.edu
!
multilink bundle-name authenticated
... continue
of course you can add a simple ‘grep’
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.config source='running' | grep snmp
snmp-server community snmpCommunity RW
snmp-server community read_only RO
snmp-server community read_write RW
** do a simple ping from several devices to check for problems**
You could try this for ping from several countries/sites to 1 server/service inside/outside of the network.
adrian@adrian-VirtualBox:~$ sudo salt 'c1_s1_*' network.ping 10.0.12.2
c1_s1_ua-1:
PING 10.0.12.2 (10.0.12.2) 56(84) bytes of data.
64 bytes from 10.0.12.2: icmp_seq=1 ttl=253 time=31.9 ms
64 bytes from 10.0.12.2: icmp_seq=2 ttl=253 time=324 ms
64 bytes from 10.0.12.2: icmp_seq=3 ttl=253 time=21.4 ms
64 bytes from 10.0.12.2: icmp_seq=4 ttl=253 time=103 ms
--- 10.0.12.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 21.461/120.435/324.668/122.081 ms
c1_s1_cpe:
PING 10.0.12.2 (10.0.12.2) 56(84) bytes of data.
64 bytes from 10.0.12.2: icmp_seq=1 ttl=253 time=41.7 ms
64 bytes from 10.0.12.2: icmp_seq=2 ttl=253 time=344 ms
64 bytes from 10.0.12.2: icmp_seq=3 ttl=253 time=52.1 ms
64 bytes from 10.0.12.2: icmp_seq=4 ttl=253 time=124 ms
--- 10.0.12.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 41.770/140.752/344.745/121.997 ms
c1_s1_co-1:
PING 10.0.12.2 (10.0.12.2) 56(84) bytes of data.
64 bytes from 10.0.12.2: icmp_seq=1 ttl=253 time=44.9 ms
64 bytes from 10.0.12.2: icmp_seq=2 ttl=253 time=359 ms
64 bytes from 10.0.12.2: icmp_seq=3 ttl=253 time=66.6 ms
64 bytes from 10.0.12.2: icmp_seq=4 ttl=253 time=148 ms
--- 10.0.12.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 44.999/155.004/359.790/124.385 ms
if the have a route to a destination
adrian@lmint2:~$ sudo salt '*' route.show 192.168.201.3
c1_s1_co-1:
----------
comment:
out:
----------
192.168.201.3:
result:
True
c2_s1_ua-1:
----------
comment:
out:
----------
192.168.201.3:
result:
True
c1_s1_cpe:
----------
comment:
out:
----------
192.168.201.3:
result:
True
c2_s1_cpe:
----------
comment:
out:
----------
192.168.201.3:
result:
True
a simple ping with True or False if it was successful
adrian@lmint2:~$ sudo salt 'c1_s1*' net.ping 192.168.201.3
c1_s1_ua-1:
----------
comment:
out:
----------
result:
True
c1_s1_cpe:
----------
comment:
out:
----------
result:
True
a traceroute showing the latency
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.traceroute 192.168.201.3
c1_s1_cpe:
----------
comment:
out:
----------
success:
----------
0:
----------
probes:
----------
1:
----------
host_name:
10.0.12.1
ip_address:
10.0.12.1
rtt:
208.0
2:
----------
host_name:
10.0.12.1
ip_address:
10.0.12.1
rtt:
32.0
3:
----------
host_name:
10.0.12.1
ip_address:
10.0.12.1
rtt:
24.0
1:
----------
probes:
----------
1:
----------
host_name:
10.0.12.1
ip_address:
10.0.12.1
rtt:
28.0
2:
----------
host_name:
10.0.12.1
ip_address:
10.0.12.1
rtt:
32.0
3:
----------
host_name:
10.0.12.1
ip_address:
10.0.12.1
rtt:
32.0
2:
----------
probes:
----------
1:
----------
host_name:
10.0.0.1
ip_address:
10.0.0.1
rtt:
36.0
2:
----------
host_name:
10.0.0.1
ip_address:
10.0.0.1
rtt:
40.0
3:
----------
host_name:
10.0.0.1
ip_address:
10.0.0.1
rtt:
36.0
3:
----------
probes:
----------
1:
----------
host_name:
192.168.201.3
ip_address:
192.168.201.3
rtt:
40.0
2:
----------
host_name:
192.168.201.3
ip_address:
192.168.201.3
rtt:
36.0
3:
----------
host_name:
192.168.201.3
ip_address:
192.168.201.3
rtt:
40.0
result:
True
another kind ok ping
adrian@adrian-VirtualBox:~$ sudo salt 'c1_s1_cpe' net.ping 10.0.12.2
c1_s1_cpe:
----------
comment:
out:
----------
success:
----------
packet_loss:
0
probes_sent:
5
results:
|_
----------
ip_address:
10.0.12.2
rtt:
0.0
|_
----------
ip_address:
10.0.12.2
rtt:
0.0
|_
----------
ip_address:
10.0.12.2
rtt:
0.0
|_
----------
ip_address:
10.0.12.2
rtt:
0.0
|_
----------
ip_address:
10.0.12.2
rtt:
0.0
rtt_avg:
3.0
rtt_max:
4.0
rtt_min:
1.0
rtt_stddev:
0.0
result:
True
check the information about the devices
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.facts
c1_s1_cpe:
----------
comment:
out:
----------
fqdn:
r2.quadrant.edu
hostname:
r2
interface_list:
- FastEthernet0/0
- FastEthernet0/1
- FastEthernet1/0
model:
3725
os_version:
3700 Software (C3725-ADVENTERPRISEK9-M), Version 12.4(15)T13, RELEASE SOFTWARE (fc3)
serial_number:
FTX0945W0MY
uptime:
38160
vendor:
Cisco
result:
True
this is interesting, you can format the output
Salt has several out formatters, like table, json, etc
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.arp --out=table
c1_s1_cpe:
----------
comment:
----------
out:
----------
-------------------------------------------------------------
| Age | Interface | Ip | Mac |
-------------------------------------------------------------
| 126.0 | FastEthernet0/0 | 10.0.12.1 | C2:01:37:5C:00:01 |
-------------------------------------------------------------
| 0.0 | FastEthernet0/0 | 10.0.12.2 | C2:02:5D:80:00:00 |
-------------------------------------------------------------
| 0.0 | FastEthernet0/1 | 10.100.12.1 | C2:02:5D:80:00:01 |
-------------------------------------------------------------
| 149.0 | FastEthernet0/1 | 10.100.12.2 | C2:04:5F:8C:00:00 |
-------------------------------------------------------------
check arp entries
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.arp
c1_s1_cpe:
----------
comment:
out:
|_
----------
age:
126.0
interface:
FastEthernet0/0
ip:
10.0.12.1
mac:
C2:01:37:5C:00:01
|_
----------
age:
0.0
interface:
FastEthernet0/0
ip:
10.0.12.2
mac:
C2:02:5D:80:00:00
|_
----------
age:
0.0
interface:
FastEthernet0/1
ip:
10.100.12.1
mac:
C2:02:5D:80:00:01
|_
----------
age:
150.0
interface:
FastEthernet0/1
ip:
10.100.12.2
mac:
C2:04:5F:8C:00:00
result:
True
check interfaces
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.interfaces
c1_s1_cpe:
----------
comment:
out:
----------
FastEthernet0/0:
----------
description:
to_r1
is_enabled:
True
is_up:
True
last_flapped:
-1.0
mac_address:
C2:02:5D:80:00:00
mtu:
1500
speed:
10
FastEthernet0/1:
----------
description:
to_inside
is_enabled:
True
is_up:
True
last_flapped:
-1.0
mac_address:
C2:02:5D:80:00:01
mtu:
1500
speed:
10
FastEthernet1/0:
----------
description:
is_enabled:
False
is_up:
False
last_flapped:
-1.0
mac_address:
C2:02:5D:80:00:10
mtu:
1500
speed:
100
result:
True
check ip addresses of interfaces
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.ipaddrs
c1_s1_cpe:
----------
comment:
out:
----------
FastEthernet0/0:
----------
ipv4:
----------
10.0.12.2:
----------
prefix_length:
24
FastEthernet0/1:
----------
ipv4:
----------
10.100.12.1:
----------
prefix_length:
24
result:
True
check arp entries
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.arp
c1_s1_cpe:
----------
comment:
out:
|_
----------
age:
130.0
interface:
FastEthernet0/0
ip:
10.0.12.1
mac:
C2:01:37:5C:00:01
|_
----------
age:
0.0
interface:
FastEthernet0/0
ip:
10.0.12.2
mac:
C2:02:5D:80:00:00
|_
----------
age:
0.0
interface:
FastEthernet0/1
ip:
10.100.12.1
mac:
C2:02:5D:80:00:01
|_
----------
age:
153.0
interface:
FastEthernet0/1
ip:
10.100.12.2
mac:
C2:04:5F:8C:00:00
result:
True
check the same arp entries but with an “table” output formatter
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.arp --out=table
c1_s1_cpe:
----------
comment:
----------
out:
----------
-------------------------------------------------------------
| Age | Interface | Ip | Mac |
-------------------------------------------------------------
| 130.0 | FastEthernet0/0 | 10.0.12.1 | C2:01:37:5C:00:01 |
-------------------------------------------------------------
| 0.0 | FastEthernet0/0 | 10.0.12.2 | C2:02:5D:80:00:00 |
-------------------------------------------------------------
| 0.0 | FastEthernet0/1 | 10.100.12.1 | C2:02:5D:80:00:01 |
-------------------------------------------------------------
| 154.0 | FastEthernet0/1 | 10.100.12.2 | C2:04:5F:8C:00:00 |
-------------------------------------------------------------
result:
----------
or with json formatter
adrian@lmint2:~$ sudo salt 'c1_s1_cpe' net.arp --out=json
{
"c1_s1_cpe": {
"out": [
{
"interface": "FastEthernet0/0",
"mac": "C2:01:37:5C:00:01",
"ip": "10.0.12.1",
"age": 130.0
},
{
"interface": "FastEthernet0/0",
"mac": "C2:02:5D:80:00:00",
"ip": "10.0.12.2",
"age": 0.0
},
{
"interface": "FastEthernet0/1",
"mac": "C2:02:5D:80:00:01",
"ip": "10.100.12.1",
"age": 0.0
},
{
"interface": "FastEthernet0/1",
"mac": "C2:04:5F:8C:00:00",
"ip": "10.100.12.2",
"age": 154.0
}
],
"result": true,
"comment": ""
}
}
send messages with slack
Edit and try the playbook “backup-msg-slack.yml”. After the backup you will receive a message in Slack telling you so. This is just an example of what you can do with chatOps.
Finally, check the respective project pages because this is only an intro… there are thousands of cool stuff to do.