mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-28 03:33:01 +02:00
121 lines
3.8 KiB
Python
121 lines
3.8 KiB
Python
"""
|
|
Fetch interface status from remote device.
|
|
"""
|
|
|
|
|
|
def get_xpath(iface, path=None):
|
|
"""Compose complete XPath to a YANG node in /ietf-interfaces"""
|
|
xpath = f"/ietf-interfaces:interfaces/interface[name='{iface}']"
|
|
if path is not None:
|
|
xpath = f"{xpath}/{path}"
|
|
return xpath
|
|
|
|
|
|
def _extract_param(json_content, param):
|
|
"""Returns (extracted) value for parameter 'param'"""
|
|
interfaces = json_content.get('interfaces')
|
|
if not interfaces:
|
|
return None
|
|
|
|
for interface in interfaces.get('interface'):
|
|
if param not in interface:
|
|
continue
|
|
return interface[param]
|
|
|
|
return None
|
|
|
|
|
|
def get_param(target, iface, param=None):
|
|
"""Fetch target dict for iface and extract param from JSON"""
|
|
content = target.get_data(get_xpath(iface, param))
|
|
if content is None:
|
|
return None
|
|
return _extract_param(content, param)
|
|
|
|
|
|
def exist(target, iface):
|
|
"""Verify that the target interface exists"""
|
|
return get_param(target, iface, "name") is not None
|
|
|
|
|
|
def address_exist(target, iface, address, prefix_length=None, proto="dhcp"):
|
|
"""Check if 'address' is set on iface"""
|
|
if not prefix_length:
|
|
if ':' in address:
|
|
prefix_length = 64
|
|
else:
|
|
prefix_length = 24
|
|
|
|
addrs = get_ipv4_address(target, iface)
|
|
if addrs:
|
|
for addr in addrs:
|
|
if addr['origin'] == proto and addr['ip'] == address and\
|
|
addr['prefix-length'] == prefix_length:
|
|
return True
|
|
|
|
addrs = get_ipv6_address(target, iface)
|
|
if addrs:
|
|
for addr in addrs:
|
|
if addr['origin'] == proto and addr['ip'] == address and\
|
|
addr['prefix-length'] == prefix_length:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def get_ipv4_address(target, iface):
|
|
"""Fetch interface IPv4 addresses from operational"""
|
|
# The interface array is different in restconf/netconf, netconf has
|
|
# a keyed list but restconf has a numbered list, i think i read that
|
|
# this was a bug in rousette, but have not found it.
|
|
interface = target.get_iface(iface)
|
|
if interface is None:
|
|
raise "Interface not found"
|
|
|
|
ip = interface.get("ipv4") or interface.get("ietf-ip:ipv4")
|
|
if ip is None or 'address' not in ip:
|
|
return None
|
|
return ip['address']
|
|
|
|
|
|
def get_ipv6_address(target, iface):
|
|
"""Fetch interface IPv6 addresses from operational"""
|
|
# The interface array is different in restconf/netconf, netconf has
|
|
# a keyed list but restconf has a numbered list, i think i read that
|
|
# this was a bug in rousette, but have not found it.
|
|
interface = target.get_iface(iface)
|
|
if interface is None:
|
|
raise "Interface not found"
|
|
|
|
ip = interface.get("ipv6") or interface.get("ietf-ip:ipv6")
|
|
if ip is None or 'address' not in ip:
|
|
return None
|
|
return ip['address']
|
|
|
|
|
|
def get_phys_address(target, iface):
|
|
"""Fetch interface MAC address (operational status)"""
|
|
return get_param(target, iface, "phys-address")
|
|
|
|
|
|
def exist_bridge_multicast_filter(target, group, iface, bridge):
|
|
"""Check if a bridge has a multicast filter for group with iface"""
|
|
# The interface array is different in restconf/netconf, netconf has
|
|
# a keyed list but restconf has a numbered list, i think i read that
|
|
# this was a bug in rousette, but have not found it.
|
|
interface = target.get_iface(bridge)
|
|
if interface is None:
|
|
raise "Interface not found"
|
|
|
|
brif = interface.get("bridge") or interface.get("infix-interfaces:bridge")
|
|
if brif is None:
|
|
return False
|
|
|
|
for f in brif.get("multicast-filters", {}).get("multicast-filter", {}):
|
|
if f.get("group") == group:
|
|
for p in f.get("ports"):
|
|
if p["port"] == iface:
|
|
return True
|
|
|
|
return False
|