Skip to content

Commit aa5f8c8

Browse files
committed
Merge remote-tracking branch 'origin/develop'
2 parents f2c6fe6 + d4559d0 commit aa5f8c8

File tree

12 files changed

+81
-24
lines changed

12 files changed

+81
-24
lines changed

docs/release-notes.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Release Notes
22

3+
## 0.19.1 (Sep 6, 2022)
4+
5+
This patch release for the 0.19.0 release includes the following important fixes:
6+
7+
* Fixes bug in path whereby an address such as 10.1.1.110 was incorrectly matched with 10.1.1.1 causing path problems
8+
* Fixes inconsistent use of "!" in filtering by device version string
9+
* Fixes intermittent crashes in device show (or the status page in the GUI) when using columns=*
10+
* Fixes incorrect hostname setting on NXOS devices in some conditions when the hostname is a hostname that includes the domain name
11+
* Add missing keyword query-str to path commands
12+
313
## 0.19.0 (Aug 22, 2022)
414

515
The 19th release of SuzieQ contains bug fixes and improvements to key functionalities such as the REST API and endpoint tracker. Here's a detailed list of key features of this release:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "suzieq"
3-
version = "0.19.0"
3+
version = "0.19.1"
44
description = "A framework and application for network observability"
55
readme = 'README.md'
66
repository = 'https://github.com/netenglabs/suzieq'

suzieq/cli/sqcmds/PathCmd.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(
2525
src: str = "",
2626
dest: str = "",
2727
vrf: str = "",
28+
query_str: str = ' ',
2829
) -> None:
2930
super().__init__(
3031
engine=engine,
@@ -34,6 +35,7 @@ def __init__(
3435
view=view,
3536
namespace=namespace,
3637
columns=columns,
38+
query_str=query_str,
3739
format=format,
3840
sqobj=PathObj
3941
)

suzieq/engines/pandas/device.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def get(self, **kwargs):
8484
(df['status_y'] != 0) & (df['status_y'] != 200) &
8585
(df['status'] == "N/A"),
8686
'neverpoll', df['status'])
87+
8788
if 'version' in df.columns:
8889
df['version'] = np.where(df.status_y == 418, 'unsupported',
8990
df.version)
@@ -100,13 +101,13 @@ def get(self, **kwargs):
100101
df.address = np.where(df['address'] == 'N/A', df['hostname'],
101102
df['address'])
102103

103-
if 'uptime' in columns or columns == ['*']:
104-
uptime_cols = (df['timestamp'] -
105-
humanize_timestamp(df['bootupTimestamp']*1000,
106-
self.cfg.get('analyzer', {}).get('timezone',
107-
None)))
108-
uptime_cols = pd.to_timedelta(uptime_cols, unit='s')
109-
df.insert(len(df.columns)-1, 'uptime', uptime_cols)
104+
if 'uptime' in columns or columns == ['*']:
105+
uptime_cols = (df['timestamp'] -
106+
humanize_timestamp(df['bootupTimestamp']*1000,
107+
self.cfg.get('analyzer', {}).get('timezone',
108+
None)))
109+
uptime_cols = pd.to_timedelta(uptime_cols, unit='s')
110+
df.insert(len(df.columns)-1, 'uptime', uptime_cols)
110111

111112
if df.empty:
112113
return df[fields]
@@ -116,9 +117,11 @@ def get(self, **kwargs):
116117
df = df.loc[df.status.isin(status)]
117118
if os_version:
118119
opdict = {'>': operator.gt, '<': operator.lt, '>=': operator.ge,
119-
'<=': operator.le, '=': operator.eq, '!=': operator.ne}
120+
'<=': operator.le, '=': operator.eq, '!': operator.ne}
120121
op = operator.eq
121122
for osv in os_version:
123+
# Introduced in 0.19.1, we do this for backwards compatibility
124+
osv = osv.replace('!=', '!')
122125
for elem, val in opdict.items():
123126
if osv.startswith(elem):
124127
osv = osv.replace(elem, '')

suzieq/engines/pandas/path.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ def _init_dfs(self, ns, source, dest):
119119

120120
if ':' in source:
121121
self._src_df = self._if_df[self._if_df.ip6AddressList.astype(str)
122-
.str.contains(source + "/")]
122+
.str.startswith(source + "/")]
123123
else:
124124
self._src_df = self._if_df[self._if_df.ipAddressList.astype(str)
125-
.str.contains(source + "/")]
125+
.str.startswith(source + "/")]
126126

127127
if self._src_df.empty:
128128
# TODO: No host with this src addr. Is addr a local ARP entry?
@@ -147,10 +147,10 @@ def _init_dfs(self, ns, source, dest):
147147

148148
if ':' in dest:
149149
self._dest_df = self._if_df[self._if_df.ip6AddressList.astype(str)
150-
.str.contains(dest + "/")]
150+
.str.startswith(dest + "/")]
151151
else:
152152
self._dest_df = self._if_df[self._if_df.ipAddressList.astype(str)
153-
.str.contains(dest + "/")]
153+
.str.startswith(dest + "/")]
154154

155155
if self._dest_df.empty:
156156
# Check if addr is in any switch's local ARP
@@ -752,6 +752,7 @@ def get(self, **kwargs) -> pd.DataFrame:
752752
src = kwargs.get("src", None)
753753
dest = kwargs.get("dest", None)
754754
dvrf = kwargs.get("vrf", "")
755+
query_str = kwargs.pop('query_str', "")
755756

756757
if not src or not dest:
757758
raise AttributeError("Must specify trace source and dest")
@@ -929,10 +930,10 @@ def get(self, **kwargs) -> pd.DataFrame:
929930
if not nhdf.empty:
930931
if srcvers == 4:
931932
nhdf = nhdf.query(
932-
f'ipAddressList.str.contains("{ndst}")')
933+
f'ipAddressList.str.startswith("{ndst}/")')
933934
else:
934935
nhdf = nhdf.query(
935-
f'ip6AddressList.str.contains("{ndst}")')
936+
f'ip6AddressList.str.startswith("{ndst}/")')
936937
if not nhdf.empty:
937938
ifmac = nhdf.macaddr.unique().tolist()
938939
if (not macaddr) or (macaddr in ifmac):
@@ -1120,7 +1121,9 @@ def get(self, **kwargs) -> pd.DataFrame:
11201121
# This occurs when a path traversal terminates due to an error such
11211122
# as loop detected
11221123
final_paths = paths
1123-
return self._path_cons_result(final_paths)
1124+
return self._handle_user_query_str(
1125+
self._path_cons_result(final_paths), query_str)\
1126+
.reset_index(drop=True)
11241127

11251128
def _path_cons_result(self, paths):
11261129
df_plist = []

suzieq/engines/pandas/topology.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
class TopologyObj(SqPandasEngine):
2424
'''Backend class to operate on virtual table, topology, with pandas'''
2525

26+
def __init__(self, baseobj):
27+
super().__init__(baseobj)
28+
self.lsdb = pd.DataFrame()
29+
self._a_df = pd.DataFrame()
30+
self._ip_table = pd.DataFrame()
31+
self.nses = []
32+
2633
@staticmethod
2734
def table_name():
2835
'''Table name'''
@@ -86,9 +93,6 @@ class Services:
8693
self._init_dfs(self._namespaces)
8794
if self._if_df.empty:
8895
return pd.DataFrame({'error': ['No interfaces data found']})
89-
self.lsdb = pd.DataFrame()
90-
self._a_df = pd.DataFrame()
91-
self._ip_table = pd.DataFrame()
9296

9397
fields = self.schema.get_display_fields(columns)
9498

suzieq/poller/worker/nodes/node.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,11 @@ async def _parse_device_type_hostname(self, output, _) -> None:
409409
f'Detected {devtype} for {self.address}:{self.port},'
410410
f' {hostname}')
411411
self._set_devtype(devtype, version_str)
412-
self._set_hostname(hostname)
412+
# We don't set the hostname here because the real hostname
413+
# is retrieved via a different command on some platforms
414+
# and can contain the FQDN. The hostname stored with a
415+
# record needs to be one that is also used in LLDP so that we
416+
# can find interface peers
413417
self.current_exception = None
414418

415419
async def _detect_node_type(self):

suzieq/poller/worker/services/service.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ async def commit_data(self, result: Dict, namespace: str, hostname: str):
628628
hostname=[hostname],
629629
namespace=[namespace]).query('active')
630630
prev_res = df.to_dict('records')
631+
self.previous_results[key] = prev_res
631632

632633
if result or prev_res:
633634
adds, dels = self.get_diff(prev_res, result)

suzieq/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"""Store the Suzieq version string."""
33

44

5-
SUZIEQ_VERSION = "0.19.0"
5+
SUZIEQ_VERSION = "0.19.1"
66

77
if __name__ == '__main__':
88
print(SUZIEQ_VERSION)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
description: Testing some common errors independent of NOS
2+
tests:
3+
- command: topology summarize --namespace=whatever --format=json
4+
data-directory: tests/data/parquet/
5+
marks: topology summarize
6+
output: '{}'

0 commit comments

Comments
 (0)