I'm having issues with a custom TextFSM Template producing errors and I'm not sure what's wrong, because the RegEx works.
Here's the sample script:
from netmiko import ConnectHandler
import Seeker.helpers.constants
root = Seeker.helpers.constants.get_project_root()
show_mac_template = f'{root}/ntc_textfsm_templates/cisco_ios_show_mac_address-table.textfsm'
device = {
'host': 'r1.nunya.com',
'device_type': 'cisco_ios',
'username': 'cisco',
'password': 'password',
'secret': 'secret',
}
ssh = ConnectHandler(**device)
ssh.enable()
show_mac = ssh.send_command(
"show mac address-table dynamic",
use_textfsm=True,
textfsm_template=show_mac_template,
)
ssh.disconnect()
Here's the traceback I'm getting:
"C:\Program Files\Python310\python.exe" "C:/Scripts/Python/Seeker/test1.py"
Traceback (most recent call last):
File "C:\Scripts\Python\Seeker\test1.py", line 18, in <module>
show_mac = ssh.send_command(
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\netmiko\utilities.py", line 596, in wrapper_decorator
return func(self, *args, **kwargs)
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\netmiko\base_connection.py", line 1702, in send_command
return_val = structured_data_converter(
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\netmiko\utilities.py", line 560, in structured_data_converter
structured_output_tfsm = get_structured_data_textfsm(
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\netmiko\utilities.py", line 397, in get_structured_data_textfsm
return _textfsm_parse(
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\netmiko\utilities.py", line 345, in _textfsm_parse
tfsm_parse(raw_output, templates=template_file)
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\textfsm\clitable.py", line 282, in ParseCmd
self.table = self._ParseCmdItem(self.raw, template_file=template_files[0])
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\textfsm\clitable.py", line 315, in _ParseCmdItem
for record in fsm.ParseText(cmd_input):
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\textfsm\parser.py", line 897, in ParseText
self._CheckLine(line)
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\textfsm\parser.py", line 946, in _CheckLine
if self._Operations(rule, line):
File "C:\Users\nunya\AppData\Roaming\Python\Python310\site-packages\textfsm\parser.py", line 1026, in _Operations
raise TextFSMError('State Error raised. Rule Line: %s. Input Line: %s'
textfsm.parser.TextFSMError: State Error raised. Rule Line: 27. Input Line: 1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
Process finished with exit code 1
Here's the template, it should be using TYPE2:
Value VLAN (\S+)
Value MAC ([0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\.[0-9a-fA-F]{4})
Value TYPE (\S+)
Value PORT ([^,\s]+)
Start
^Vlan\s+Mac\s+Address\s+Type\s+Ports -> TYPE1
^\s*vlan\s+mac address\s+type\s+protocols\s+port -> TYPE2
TYPE1
^\s*Mac\sAddress\sTable
^-+
^\s*$$
^Vlan\s+Mac Address\s+Type\s+Ports
^-+\s+-+\s+-+\s+-+$$
^\s*${VLAN}\s+${MAC}\s+${TYPE}\s+${PORT}$$ -> Record
^Total\s+Mac\s+Addresses\s+for\s+this\s+criterion\:\s+\d+ -> End
^. -> Error
TYPE2
^Unicast\sEntries
^\s+vlan\s+mac address\s+type\s+protocols\s+port
^-+\+-+\+-+\+-+\+-+
^\s*${VLAN}\s+${MAC}\s+${TYPE}\s+\S+\s+${PORT}$$ -> Record
^\s*$$ -> End
^. -> Error
And finally here's an example output of the command ran directly on the device:
r1#show mac address-table dynamic
Unicast Entries
vlan mac address type protocols port
---------+---------------+--------+---------------------+-------------------------
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet4/10
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/8
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/5
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/5
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/1
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet10/4
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/5
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/9
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet4/10
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet10/5
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet10/5
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet4/9
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet10/6
1 0000.0000.0000 dynamic ip,ipx,assigned,other TenGigabitEthernet3/4
--More--
Any help would be appreciated.
Changing a line in TYPE2 from:
^\s*${VLAN}\s+${MAC}\s+${TYPE}\s+\S+\s+${PORT}$$ -> Record
to:
^\s*${VLAN}\s+${MAC}\s+${TYPE}\s+\S+\s+${PORT}\s*$$ -> Record
fixes the issue.