pygnmi
pygnmi copied to clipboard
_merge_updates() does not handle case where new_resp is None
Crash seen when connecting to a Juniper box running Junos: 21.4R2-S1.12-EVO
# Modules
from pygnmi.client import gNMIclient, telemetryParser
# Variables
host = ('1.1.1.1', '50051')
# Body
subscribe = {
'subscription': [
{
'path': '/components/component',
'mode': 'sample',
'sample_interval': 10000000000
},
],
'use_aliases': False,
'mode': 'stream',
'encoding': 'json'
}
if __name__ == '__main__':
with gNMIclient(target=host, username='foo', password='lab123', insecure=True) as gc:
telemetry_stream = gc.subscribe_stream(subscribe=subscribe)
for telemetry_entry in telemetry_stream:
print(telemetry_entry)
resulted in an unhandled exception:
Parsing of telemetry information is failed.
Traceback (most recent call last):
File "/Users/foo/scripts/foo/gnmi-scripts/subscribe.py", line 25, in <module>
Exception in thread Thread-5:
Traceback (most recent call last):
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
for telemetry_entry in telemetry_stream:
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/pygnmi/client.py", line 973, in __next__
self.run()
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/threading.py", line 910, in run
result = self.next()
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/pygnmi/client.py", line 985, in next
self._target(*self._args, **self._kwargs)
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/pygnmi/client.py", line 908, in enqueue_updates
return self._next_update(timeout=None)
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/pygnmi/client.py", line 1036, in _next_update
for update in subscription:
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/grpc/_channel.py", line 426, in __next__
return self._get_updates_till_sync(timeout=timeout)
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/pygnmi/client.py", line 949, in _get_updates_till_sync
return self._next()
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/grpc/_channel.py", line 809, in _next
self._merge_updates(resp, new_resp)
File "/Users/foo/scripts/foo/gnmi-scripts/venv/lib/python3.9/site-packages/pygnmi/client.py", line 954, in _merge_updates
if 'update' in new_resp:
TypeError: argument of type 'NoneType' is not iterable
raise self
grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
status = StatusCode.CANCELLED
details = "Channel closed!"
debug_error_string = "UNKNOWN:Error received from peer 1.1.1.1:50051 {grpc_message:"Channel closed!", grpc_status:1, created_time:"2022-10-25T18:22:42.347026+11:00"}"
workaround was to add a line to client.py in _merge_updates()
def _merge_updates(self, resp, new_resp):
if new_resp is not None: ### adding this line
if 'update' in new_resp:
for key in new_resp['update']:
if key.upper() in UpdateResult.Operation.keys():
if key not in resp['update']:
resp['update'][key] = []
resp['update'][key] += new_resp['update'][key]
else:
resp['update'][key] = new_resp['update'][key]
if 'sync_response' in new_resp:
resp['sync_response'] = new_resp['sync_response']