The Cisco ASAv has a command show interface summary
, this command output has a lot of information, these are the interesting information I need from this command:
- Interface id including the sub interface if available
- nameif, which is the name interface which must be configured
- administrative status
- protocol status
- vlan id if available
- ip address if available
- subnet mask
- description if available
- mac address
Sample output from cisco asa
fw02# sh int summary Interface GigabitEthernet0/0 "", is up, line protocol is up Hardware is i82540EM rev03, BW 1000 Mbps, DLY 10 usec Auto-Duplex(Full-duplex), Auto-Speed(1000 Mbps) Input flow control is unsupported, output flow control is off Available but not configured via nameif MAC address 5000.0002.0001, MTU not set IP address unassigned 0 packets input, 0 bytes, 0 no buffer Received 0 broadcasts, 0 runts, 0 giants 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort 0 pause input, 0 resume input 0 L2 decode drops 2 packets output, 0 bytes, 0 underruns 0 pause output, 0 resume output 0 output errors, 0 collisions, 2 interface resets 0 late collisions, 0 deferred 0 input reset drops, 0 output reset drops input queue (blocks free curr/low): hardware (511/511) output queue (blocks free curr/low): hardware (511/510) Interface GigabitEthernet0/0.100 "dmz_net100", is up, line protocol is up Hardware is i82540EM rev03, BW 1000 Mbps, DLY 10 usec VLAN identifier 100 MAC address 5000.0002.0001, MTU 1500 IP address 10.0.100.1, subnet mask 255.255.255.0 Interface GigabitEthernet0/0.101 "dmz_secondary_net101", is up, line protocol is up Hardware is i82540EM rev03, BW 1000 Mbps, DLY 10 usec VLAN identifier 101 MAC address 5000.0002.0001, MTU 1500 IP address 10.0.101.1, subnet mask 255.255.255.0
TextFSM to match the interesting data
Value Required interface ([0-9A-Za-z/.]+) Value nameif (\S*) Value a_state (up|down|administratively down) Value p_state (up|down) Value vlan (\d+) Value ip_address (\d+.\d+.\d+.\d+) Value mask (\d+.\d+.\d+.\d+) Value description ([\w\s\-]+) Value mac_address (\S+) Start # detects if there is a word Interface after show int summary # if there is on next line start recording. ^Interface -> Continue.Record ^Interface\s+${interface}\s+"${nameif}",\s*is\s+${a_state},\s*line\s+protocol\s+is\s+${p_state} ^\s*VLAN\s+identifier\s+${vlan} ^\s*Description:\s*${description} ^\s*MAC\s+address\s+${mac_address},\s+MTU\s+(\d+) ^\s*IP\s+address\s+${ip_address},\s*subnet\s+mask\s+${mask}
The Continue
line action is ignoring the match row, and go to the next.
Code to test
For testing I am using nornir framework to call netmiko.
from network.ciscoasa import connect_asa_host from nornir.plugins.tasks.networking import netmiko_send_command from textfsm import TextFSM from pathlib import Path from os.path import join from pprint import pprint filename = "show_int_summary.textfsm" file_path = join(Path(__file__).parent.parent.absolute(), "network", "templates", filename) hostname = "fw02" asa = connect_asa_host(hostname=hostname) response = asa.run(task=netmiko_send_command, command_string="show interface summary") result = response[hostname][0].result with open(file_path, "r") as tp: template = TextFSM(tp) processed_result = template.ParseTextToDicts(result) pprint(processed_result)
from network.ciscoasa import connect_asa_host
is my personal code that does the InitNornir
and filter the host in the hosts.yaml file.
from nornir.plugins.tasks.networking import netmiko_send_command
this imports the netmiko_send_command function, this is similar to below when calling netmiko directly without Nornir:
cmd = "show interface summary" with ConnectHandler(**config) as task: try: collect_results.append(task.send_command(cmd)) except Exceptions as e: print(e)
To send single command use netmiko_send_command
, to send configuration set use netmiko_send_config
. Single command has one index in AggregatedResult, hence the result can be obtained from result = response[hostname][0].result
, to check for failure use result = response[hostname][0].failed
which is a boolean.
If you use netmiko_send_config
then the result is in the second index of AggregatedResult i.e. result = response[hostname][1].result
, to refer to the failure state use the first index result = response[hostname][0].failed
TextFSM has a ParseTextToDicts
which helps to combine the header with the result and output as a dictionary, I did not know this previously and hence I was re-inventing the wheel by using zip and dict to get the dictionary.
Result
[{'a_state': 'up', 'description': '', 'interface': 'GigabitEthernet0/0', 'ip_address': '', 'mac_address': '', 'mask': '', 'nameif': '', 'p_state': 'up', 'vlan': ''}, {'a_state': 'up', 'description': '', 'interface': 'GigabitEthernet0/0.100', 'ip_address': '10.0.100.1', 'mac_address': '5000.0002.0001', 'mask': '255.255.255.0', 'nameif': 'dmz_net100', 'p_state': 'up', 'vlan': '100'}, {'a_state': 'up', 'description': '', 'interface': 'GigabitEthernet0/0.101', 'ip_address': '10.0.101.1', 'mac_address': '5000.0002.0001', 'mask': '255.255.255.0', 'nameif': 'dmz_secondary_net101', 'p_state': 'up', 'vlan': '101'}, {'a_state': 'up', 'description': '', 'interface': 'GigabitEthernet0/1', 'ip_address': '', 'mac_address': '', 'mask': '', 'nameif': '', 'p_state': 'up', 'vlan': ''}, {'a_state': 'up', 'description': '', 'interface': 'GigabitEthernet0/1.90', 'ip_address': '10.0.90.1', 'mac_address': '5000.0002.0002', 'mask': '255.255.255.0', 'nameif': 'reserved_net90', 'p_state': 'up', 'vlan': '90'}, {'a_state': 'up', 'description': '', 'interface': 'GigabitEthernet0/2', 'ip_address': '', 'mac_address': '', 'mask': '', 'nameif': '', 'p_state': 'up', 'vlan': ''}, {'a_state': 'up', 'description': 'This is a description test ', 'interface': 'GigabitEthernet0/2.20', 'ip_address': '10.0.20.1', 'mac_address': '5000.0002.0003', 'mask': '255.255.255.0', 'nameif': 'user_space_net20', 'p_state': 'up', 'vlan': '20'}, {'a_state': 'administratively down', 'description': '', 'interface': 'GigabitEthernet0/3', 'ip_address': '', 'mac_address': '', 'mask': '', 'nameif': '', 'p_state': 'up', 'vlan': ''}, {'a_state': 'administratively down', 'description': '', 'interface': 'GigabitEthernet0/4', 'ip_address': '', 'mac_address': '', 'mask': '', 'nameif': '', 'p_state': 'up', 'vlan': ''}, {'a_state': 'administratively down', 'description': '', 'interface': 'GigabitEthernet0/5', 'ip_address': '', 'mac_address': '', 'mask': '', 'nameif': '', 'p_state': 'up', 'vlan': ''}, {'a_state': 'administratively down', 'description': '', 'interface': 'GigabitEthernet0/6', 'ip_address': '', 'mac_address': '', 'mask': '', 'nameif': '', 'p_state': 'up', 'vlan': ''}, {'a_state': 'up', 'description': '', 'interface': 'Management0/0', 'ip_address': '192.168.100.30', 'mac_address': '5000.0002.0000', 'mask': '255.255.255.0', 'nameif': 'management', 'p_state': 'up', 'vlan': ''}]