Skip to content

Commit 4852a18

Browse files
authored
Merge pull request #748 from netenglabs/minor-fixes-0.18
Minor fixes 0.18
2 parents 808aa24 + 6ac70f2 commit 4852a18

File tree

8 files changed

+119
-51
lines changed

8 files changed

+119
-51
lines changed

suzieq/cli/sqcmds/command.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ def _pager_print(self, df: pd.DataFrame) -> None:
274274
else:
275275
print(df)
276276

277+
# pylint: disable=too-many-statements
277278
def _gen_output(self, df: pd.DataFrame, json_orient: str = "records",
278279
dont_strip_cols: bool = False, sort: bool = True):
279280

@@ -291,6 +292,9 @@ def _gen_output(self, df: pd.DataFrame, json_orient: str = "records",
291292
cols = df.columns.tolist()
292293
is_error = False
293294

295+
max_rows = self.ctxt.max_rows
296+
all_columns = self.ctxt.all_columns
297+
294298
if dont_strip_cols or not all(item in df.columns for item in cols):
295299
cols = df.columns.tolist()
296300

@@ -317,9 +321,11 @@ def _gen_output(self, df: pd.DataFrame, json_orient: str = "records",
317321
'timestamp' not in self.columns and not dont_strip_cols and
318322
'timestamp' in df.columns and 'timestamp' in cols):
319323
cols.remove('timestamp')
320-
with pd.option_context('precision', 3,
321-
'display.max_colwidth', max_colwidth,
322-
'display.max_rows', 256):
324+
with pd.option_context(
325+
'precision', 3,
326+
'display.max_colwidth', max_colwidth,
327+
'display.max_rows', max_rows,
328+
'display.expand_frame_repr', not all_columns):
323329
df = self.sqobj.humanize_fields(df)
324330
if df.empty:
325331
print(df)

suzieq/cli/sqcmds/context_commands.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
@argument("pager", description="Enable pagination prompt on longer outputs",
2323
choices=['on', 'off'])
2424
@argument('col_width', description='Max Width of each column in table display')
25+
@argument('max_rows',
26+
description='Max rows to display before ellipsis is shown')
27+
@argument('all_columns',
28+
description='Display all columns wrapping around if necessary',
29+
choices=['yes', 'no'])
2530
@argument(
2631
"engine",
2732
choices=SUPPORTED_ENGINES,
@@ -57,6 +62,8 @@ def set_ctxt(
5762
datadir: str = "",
5863
debug: str = '',
5964
col_width: int = 50,
65+
max_rows: int = None,
66+
all_columns: str = None,
6067
rest_server_ip: str = "",
6168
rest_server_port: str = "",
6269
rest_api_key: str = "",
@@ -93,6 +100,15 @@ def set_ctxt(
93100
if col_width:
94101
ctxt.col_width = int(col_width)
95102

103+
if max_rows is not None:
104+
if max_rows == 0:
105+
ctxt.max_rows = None
106+
else:
107+
ctxt.max_rows = max_rows
108+
109+
if all_columns is not None:
110+
ctxt.all_columns = all_columns == "yes"
111+
96112
if pager == 'on':
97113
ctxt.pager = True
98114
elif pager == 'off':

suzieq/config/textfsm_templates/iosxe_show_mac.tfsm

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,21 @@ Value Required macaddr (\S+)
33
Value Required flags (\w+)
44
Value oif (\S+)
55
Value protocol (\S+)
6+
Value _learn (\w+)
7+
Value age (\d+|-)
8+
Value List _ports (\S+)
69

710
Start
11+
^\* -> WithStar
812
^\s+vlan.*protocol.* -> WithProtocol
913
^\s*${vlan}\s+${macaddr}\s+${flags}\s+${oif}.*$$ -> Record
1014

1115
WithProtocol
1216
^\s*${vlan}\s+${macaddr}\s+${flags}\s+${protocol}\s+${oif}.*$$ -> Record
1317
^Multicast\s+Entries -> Start
1418

15-
# Mac Address Table
16-
#-------------------------------------------
17-
#
18-
#Vlan Mac Address Type Ports
19-
#---- ----------- -------- -----
20-
# All 0100.0ccc.cccc STATIC CPU
21-
# All 0100.0ccc.cccd STATIC CPU
22-
# All 0180.c200.0000 STATIC CPU
23-
# All 0180.c200.0001 STATIC CPU
24-
# All 0180.c200.0002 STATIC CPU
25-
# All 0180.c200.0003 STATIC CPU
26-
# All 0180.c200.0004 STATIC CPU
27-
# All 0180.c200.0005 STATIC CPU
28-
# All 0180.c200.0006 STATIC CPU
29-
# All 0180.c200.0007 STATIC CPU
30-
# All 0180.c200.0008 STATIC CPU
31-
# All 0180.c200.0009 STATIC CPU
32-
# All 0180.c200.000a STATIC CPU
33-
# All 0180.c200.000b STATIC CPU
34-
# All 0180.c200.000c STATIC CPU
35-
# All 0180.c200.000d STATIC CPU
36-
# All 0180.c200.000e STATIC CPU
37-
# All 0180.c200.000f STATIC CPU
38-
# All 0180.c200.0010 STATIC CPU
39-
# All 0180.c200.0021 STATIC CPU
40-
# All ffff.ffff.ffff STATIC CPU
41-
# 1 780c.f0e1.1dc3 STATIC Vl1
42-
# 51 0000.1111.2222 STATIC Vl51
43-
# 51 780c.f0e1.1dc6 STATIC Vl51
44-
#1021 0000.0c9f.f45c STATIC Vl1021
45-
#1021 0002.02cc.0002 STATIC Gi6/0/2
46-
#1021 0002.02cc.0003 STATIC Gi6/0/3
47-
#1021 0002.02cc.0004 STATIC Gi6/0/4
48-
#1021 0002.02cc.0005 STATIC Gi6/0/5
49-
#1021 0002.02cc.0006 STATIC Gi6/0/6
50-
#1021 0002.02cc.0007 STATIC Gi6/0/7
51-
#1021 0002.02cc.0008 STATIC Gi6/0/8
52-
#1021 0002.02cc.0009 STATIC Gi6/0/9
53-
#1021 0002.02cc.000a STATIC Gi6/0/10
54-
#
19+
WithStar
20+
^\* -> Continue.Record
21+
^\*\s+${vlan}\s+${macaddr}\s+${flags}\s+${_learn}\s+${age}\s+${_ports}
22+
^\s+${_ports}
23+

suzieq/poller/worker/services/macs.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,26 @@ def _clean_iosxe_data(self, processed_data, _):
160160
for entry in processed_data:
161161
entry['macaddr'] = convert_macaddr_format_to_colon(
162162
entry.get('macaddr', '0000.0000.0000'))
163+
oiflist = []
163164
oifs = ''
164-
for oif in entry.get('oif', '').split(','):
165-
# Handle multicast entries
165+
oif = entry.get('oif', '').strip()
166+
if oif:
167+
oiflist = oif.split(',')
168+
if not oiflist:
169+
# Some versions of IOS/XE have a different output
170+
# format and we capture that in a different var
171+
oif = entry.get('_ports', '')
172+
if oif:
173+
for ele in oif:
174+
oiflist.extend(ele.split(','))
175+
for oif in oiflist:
176+
# Handles multicast entries
166177
oifs += f'{expand_ios_ifname(oif)} '
167178
if oifs:
168179
entry['oif'] = oifs.strip()
169180
else:
170-
entry['oif'] = expand_ios_ifname(entry['oif'])
181+
entry['oif'] = ''
182+
171183
entry['remoteVtepIp'] = ''
172184
if entry.get('vlan', ' ').strip() == "All":
173185
entry['vlan'] = 0

suzieq/poller/worker/services/vlan.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
class VlanService(Service):
77
"""Vlan service. Different class because Vlan is not right type for EOS"""
88

9+
def clean_json_input(self, data):
10+
"""evpnVni JSON output is busted across many NOS. Fix it"""
11+
12+
devtype = data.get("devtype", None)
13+
if devtype == 'junos-mx':
14+
data['data'] = data['data'].replace('}, \n }\n', '} \n }\n')
15+
16+
return data['data']
17+
918
def _clean_eos_data(self, processed_data, _):
1019
'''Massage the interface output'''
1120

suzieq/shared/context.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class SqContext:
1818
exec_time: str = ''
1919
engine: str = None
2020
col_width: int = 50
21+
max_rows: int = 256
22+
all_columns: bool = False
2123
debug: bool = False
2224
sort_fields: List[str] = field(default_factory=list)
2325
view: str = None

suzieq/shared/utils.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -452,19 +452,38 @@ def get_timestamp_from_junos_time(in_data, timestamp: int):
452452

453453

454454
def convert_macaddr_format_to_colon(macaddr: str) -> str:
455-
"""Convert NXOS/EOS . macaddr form to standard : format, lowecase
455+
"""Convert various macaddr forms to standard ':' format, lowecase
456+
457+
One unexpected side-effect, it'll convert the given string to lowercase
458+
even if it doesn't match a macaddr.
456459
457460
:param macaddr: str, the macaddr string to convert
458461
:returns: the converted macaddr string or all 0s string if arg not str
459462
:rtype: str
460463
461464
"""
462465
if isinstance(macaddr, str):
463-
if re.match(r'[0-9a-zA-Z]{4}.[0-9a-zA-Z]{4}.[0-9a-zA-Z]{4}', macaddr):
466+
macaddr = macaddr.lower()
467+
if re.match(r'[0-9a-f]{4}\.[0-9a-f]{4}\.[0-9a-f]{4}', macaddr):
464468
return (':'.join([f'{x[:2]}:{x[2:]}'
465-
for x in macaddr.split('.')])).lower()
466-
else:
467-
return macaddr.lower()
469+
for x in macaddr.split('.')]))
470+
if re.match(r'[0-9a-f]{2}-[0-9a-f]{2}-[0-9a-f]{2}-'
471+
r'[0-9a-f]{2}-[0-9a-f]{2}-[0-9a-f]{2}',
472+
macaddr):
473+
return macaddr.replace('-', ':')
474+
if re.match(r'[0-9a-f]{4}:[0-9a-f]{4}:[0-9a-f]{4}', macaddr):
475+
return (':'.join([f'{x[:2]}:{x[2:]}'
476+
for x in macaddr.split(':')]))
477+
if ':' not in macaddr and re.match(r'[0-9a-f]{12}', macaddr):
478+
newmac = ''
479+
for i in range(0, 12, 2):
480+
newmac += f'{macaddr[i:i+2]}:'
481+
newmac = newmac[:-1] # remove the trailing ':'
482+
return newmac
483+
if re.match(r'[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}', macaddr):
484+
return (':'.join([f'{x[:2]}:{x[2:]}'
485+
for x in macaddr.split('-')]))
486+
return macaddr
468487

469488
return '00:00:00:00:00:00'
470489

tests/unit/test_mac_convert.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from suzieq.shared.utils import convert_macaddr_format_to_colon
2+
3+
4+
def test_mac_convert():
5+
'''Test all formats of MAC formats being converted to std format'''
6+
result = '50:9a:4c:36:a1:df'
7+
nullmac = '00:00:00:00:00:00'
8+
9+
assert convert_macaddr_format_to_colon('509A:4C36:A1DF') == result, \
10+
'failed to convert 509A:4C36:A1DF'
11+
12+
assert convert_macaddr_format_to_colon('509A.4C36.A1DF') == result, \
13+
'failed to convert 509A.4C36.A1DF'
14+
15+
assert convert_macaddr_format_to_colon('509A-4C36-A1DF') == result, \
16+
'failed to convert 509A.4C36.A1DF'
17+
18+
assert convert_macaddr_format_to_colon('509A4C36A1DF') == result, \
19+
'failed to convert 509A4C36A1DF'
20+
21+
assert convert_macaddr_format_to_colon('50-9A-4C-36-A1-DF') == result, \
22+
'failed to convert 50-9A-4C-36-A1-DF'
23+
24+
assert convert_macaddr_format_to_colon(
25+
'50-9Z-4C-36-A1-DF') == '50-9z-4c-36-a1-df', \
26+
'Incorrect conversion of 50-9Z-4C-36-A1-DF'
27+
28+
assert convert_macaddr_format_to_colon(result) == result, \
29+
f'Failed to return {result} as is'
30+
31+
assert convert_macaddr_format_to_colon(1) == nullmac, \
32+
f'Incorrect handling when int is passed'
33+
34+
assert convert_macaddr_format_to_colon([1]) == nullmac, \
35+
f'Incorrect handling when list is passed'

0 commit comments

Comments
 (0)