latency_collect.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """Ping every collected switch's management IP in parallel.
  4. Zabbix host -> switch latency is the only latency that can be measured without
  5. touching device config, so this is what drives the node latency colouring.
  6. Writes /tmp/latency.tsv -> <ip>\\t<avg_ms or empty>
  7. """
  8. import json
  9. import re
  10. import subprocess
  11. import concurrent.futures as cf
  12. import urllib.request
  13. import l2cfg
  14. TOK = 'd3abb125eb301a021ef80a2847a803a7cd2d0b1d3c8337a14d09db9d571369b5'
  15. API = 'http://192.168.87.20:8080/api_jsonrpc.php'
  16. OUT = '/tmp/latency.tsv'
  17. def call(m, p):
  18. d = json.dumps({"jsonrpc": "2.0", "method": m, "params": p, "id": 1}).encode()
  19. q = urllib.request.Request(API, data=d, headers={'Content-Type': 'application/json', 'Authorization': 'Bearer ' + TOK})
  20. return json.loads(urllib.request.urlopen(q, timeout=60).read().decode())
  21. def ping(ip):
  22. try:
  23. r = subprocess.run(['ping', '-c', '3', '-W', '1', '-q', ip],
  24. capture_output=True, text=True, timeout=10)
  25. m = re.search(r'=\s*[\d.]+/([\d.]+)/', r.stdout)
  26. if m:
  27. return ip, float(m.group(1))
  28. m = re.search(r'time=([\d.]+)\s*ms', r.stdout)
  29. if m:
  30. return ip, float(m.group(1))
  31. except Exception:
  32. pass
  33. return ip, None
  34. def main():
  35. hs = l2cfg.hosts(call)
  36. ips = sorted({i['ip'] for h in hs for i in (h.get('interfaces') or [])
  37. if i.get('ip') and i.get('type') == '2'})
  38. if not ips:
  39. ips = sorted({i['ip'] for h in hs for i in (h.get('interfaces') or []) if i.get('ip')})
  40. res = {}
  41. with cf.ThreadPoolExecutor(max_workers=40) as ex:
  42. for ip, v in ex.map(ping, ips):
  43. res[ip] = v
  44. with open(OUT, 'w', encoding='utf-8') as f:
  45. for ip in ips:
  46. v = res.get(ip)
  47. f.write('%s\t%s\n' % (ip, '' if v is None else '%.3f' % v))
  48. ok = sum(1 for v in res.values() if v is not None)
  49. print('latency: %d/%d reachable' % (ok, len(ips)))
  50. if __name__ == '__main__':
  51. main()