akarneliuk / pygnmi

The pure Python implementation of the gNMI client.
https://training.karneliuk.com
BSD 3-Clause "New" or "Revised" License
129 stars 44 forks source link

breaking change in 0.8 #83

Closed ksator closed 2 years ago

ksator commented 2 years ago

Hello @akarneliuk

arista@devbox:~$ cat t3.py 
"""
pygnmi script
"""
from pygnmi.client import gNMIclient

TELEMETRY_REQUEST = {
                         'subscription': [
                             {
                                 'path': '/inventory/state/device/device-id'
                             }
                         ],
                         'mode': 'once',
                         'encoding': 'json'
                     }

with open("token.tok") as f:
    TOKEN = f.read().strip('\n')

if __name__ == "__main__":
     with gNMIclient(target=('192.168.0.5', '443'), token=TOKEN, skip_verify=True) as gconn:
         inventory = gconn.subscribe2(subscribe=TELEMETRY_REQUEST)
         for device in inventory:
                print(device)
arista@devbox:~$ 

working

arista@devbox:~$ pip install pygnmi==0.7.5
arista@devbox:~$ python t3.py 
ssl_target_name_override is applied, should be used for testing only!
{'update': {'update': [{'path': 'inventory/state/device[device-id=leaf4]/device-id', 'val': 'leaf4'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=host2]/device-id', 'val': 'host2'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=spine1]/device-id', 'val': 'spine1'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=leaf2]/device-id', 'val': 'leaf2'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=leaf3]/device-id', 'val': 'leaf3'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=spine2]/device-id', 'val': 'spine2'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=host1]/device-id', 'val': 'host1'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=leaf1]/device-id', 'val': 'leaf1'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'update': {'update': [{'path': 'inventory/state/device[device-id=cvx01]/device-id', 'val': 'cvx01'}], 'timestamp': 1658653200000000000, 'prefix': ''}}
{'sync_response': True}

not working

arista@devbox:~$ pip install pygnmi==0.8.2
arista@devbox:~$ python t3.py 
ssl_target_name_override is applied, should be used for testing only!
Exception in thread Thread-5:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/home/arista/.local/lib/python3.9/site-packages/pygnmi/client.py", line 940, in enqueue_updates
    for update in subscription:
  File "/home/arista/.local/lib/python3.9/site-packages/grpc/_channel.py", line 426, in __next__
    return self._next()
  File "/home/arista/.local/lib/python3.9/site-packages/grpc/_channel.py", line 826, in _next
    raise self
grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
        status = StatusCode.UNIMPLEMENTED
        details = "Extension not supported"
        debug_error_string = "{"created":"@1658653512.927644730","description":"Error received from peer ipv4:192.168.0.5:443","file":"src/core/lib/surface/call.cc","file_line":966,"grpc_message":"Extension not supported","grpc_status":12}"
>
^CTraceback (most recent call last):
  File "/home/arista/t3.py", line 22, in <module>
    for device in inventory:
  File "/home/arista/.local/lib/python3.9/site-packages/pygnmi/client.py", line 1004, in __next__
    result = self.next()
  File "/home/arista/.local/lib/python3.9/site-packages/pygnmi/client.py", line 1016, in next
    return self._next_update(timeout=None)
  File "/home/arista/.local/lib/python3.9/site-packages/pygnmi/client.py", line 1090, in _next_update
    return self._get_one_update(timeout=timeout)
  File "/home/arista/.local/lib/python3.9/site-packages/pygnmi/client.py", line 969, in _get_one_update
    return telemetryParser(self._updates.get(block=True, timeout=timeout))
  File "/usr/local/lib/python3.9/queue.py", line 171, in get
    self.not_empty.wait()
  File "/usr/local/lib/python3.9/threading.py", line 312, in wait
    waiter.acquire()
KeyboardInterrupt
ksator commented 2 years ago

same issue with another script

arista@devbox:~$ cat t4.py 
"""
Go to **Devices > Inventory** and replace the target in this script with the `device ID` found in the CVP device inventory
The `device ID` is the device SN.  
"""

from pygnmi.client import gNMIclient

TELEMETRY_REQUEST = {
                         'subscription': [
                             {
                                #'path': 'openconfig:/network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state',
                                 'path': 'openconfig:/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=172.16.0.5]/state/session-state',
                                 'mode': 'target_defined'
                             }
                         ],
                         'mode': 'stream',
                         'encoding': 'json'
                     }

with open("token.tok") as f:
    TOKEN = f.read().strip('\n')

if __name__ == "__main__":
    with gNMIclient(target=('192.168.0.5', '443'), token=TOKEN, skip_verify=True) as gconn:
        gconn.capabilities()
        for item in gconn.subscribe2(subscribe=TELEMETRY_REQUEST, target="spine1"): 
                print(item)

working

arista@devbox:~$ pip install pygnmi==0.7.5
arista@devbox:~$ python t4.py 
ssl_target_name_override is applied, should be used for testing only!
{'update': {'update': [{'path': 'network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=172.16.0.5]/state/session-state', 'val': 'ACTIVE'}], 'timestamp': 1658062041738667978, 'prefix': ''}, 'sync_response': True}

Not working

arista@devbox:~$ pip install pygnmi==0.8.2
arista@devbox:~$ python t4.py 
ssl_target_name_override is applied, should be used for testing only!
Exception in thread Thread-6:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/home/arista/.local/lib/python3.9/site-packages/pygnmi/client.py", line 940, in enqueue_updates
    for update in subscription:
  File "/home/arista/.local/lib/python3.9/site-packages/grpc/_channel.py", line 426, in __next__
    return self._next()
  File "/home/arista/.local/lib/python3.9/site-packages/grpc/_channel.py", line 826, in _next
    raise self
grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
        status = StatusCode.UNIMPLEMENTED
        details = "Extension not supported"
        debug_error_string = "{"created":"@1658654037.738152994","description":"Error received from peer ipv4:192.168.0.5:443","file":"src/core/lib/surface/call.cc","file_line":966,"grpc_message":"Extension not supported","grpc_status":12}"
ksator commented 2 years ago

same issue with this one as well

arista@devbox:~$ cat t5.py 
"""
pygnmi script
"""

from pygnmi.client import gNMIclient

TELEMETRY_REQUEST = {
                         'subscription': [
                             {
                                 'path': '/inventory/state/device/device-id',
                                 'mode': 'target_defined'
                             }
                         ],
                         'mode': 'stream',
                         'encoding': 'json'
                     }

with open("token.tok") as f:
    TOKEN = f.read().strip('\n')

if __name__ == "__main__":
    with gNMIclient(target=('192.168.0.5', '443'), token=TOKEN, skip_verify=True) as gconn:
        inventory = gconn.subscribe2(subscribe=TELEMETRY_REQUEST)
        for device in inventory:
            print(device)

working

arista@devbox:~$ pip install pygnmi==0.7.5
arista@devbox:~$ python t5.py 
ssl_target_name_override is applied, should be used for testing only!
{'update': {'update': [{'path': 'inventory/state/device[device-id=host2]/device-id', 'val': 'host2'}, {'path': 'inventory/state/device[device-id=cvx01]/device-id', 'val': 'cvx01'}, {'path': 'inventory/state/device[device-id=spine1]/device-id', 'val': 'spine1'}, {'path': 'inventory/state/device[device-id=spine2]/device-id', 'val': 'spine2'}, {'path': 'inventory/state/device[device-id=leaf2]/device-id', 'val': 'leaf2'}, {'path': 'inventory/state/device[device-id=leaf3]/device-id', 'val': 'leaf3'}, {'path': 'inventory/state/device[device-id=leaf1]/device-id', 'val': 'leaf1'}, {'path': 'inventory/state/device[device-id=leaf4]/device-id', 'val': 'leaf4'}, {'path': 'inventory/state/device[device-id=host1]/device-id', 'val': 'host1'}], 'timestamp': 1658653200000000000, 'prefix': ''}, 'sync_response': True}

Not working

arista@devbox:~$ pip install pygnmi==0.8.2
arista@devbox:~$ python t5.py 
ssl_target_name_override is applied, should be used for testing only!
Exception in thread Thread-5:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/home/arista/.local/lib/python3.9/site-packages/pygnmi/client.py", line 940, in enqueue_updates
    for update in subscription:
  File "/home/arista/.local/lib/python3.9/site-packages/grpc/_channel.py", line 426, in __next__
    return self._next()
  File "/home/arista/.local/lib/python3.9/site-packages/grpc/_channel.py", line 826, in _next
    raise self
grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
        status = StatusCode.UNIMPLEMENTED
        details = "Extension not supported"
        debug_error_string = "{"created":"@1658654407.820868393","description":"Error received from peer ipv4:192.168.0.5:443","file":"src/core/lib/surface/call.cc","file_line":966,"grpc_message":"Extension not supported","grpc_status":12}"
>
akarneliuk commented 2 years ago

Thanks @ksator ,

I've looked through the error messages, it suggests Extension not supported, which is interesting as it sends an empty extension field. We run unit tests against Arista EOS and it ignores that field, so it looks in CVP you have a different implementation of gNMI server. I will amend the code a bit.

Best, Anton

akarneliuk commented 2 years ago

Hey @ksator,

fixed by #84 and in published release pygnmi==0.8.3

Best, Anton

ksator commented 2 years ago

all good using 0.8.3 Thank you! you can close this issue.
just a comment: I dont see onthe repo the tag/release 0.8.3 (but I was able to pip install pygnmi==0.8.3)

akarneliuk commented 2 years ago

Thanks @ksator, fixed it

ksator commented 2 years ago

@akarneliuk fyi CVP has a TSDB and we can use the history gNMI extension with CVP but there is no TSDB on the devices. Maybe this explained the behavior regarding the gNMI Extensions handling.