Initial formatting run with Black. Integration tests and unit tests pass before and after this change.
This commit is contained in:
@ -21,77 +21,78 @@ import config.address as address
|
||||
import config.mac as mac
|
||||
import config.tap as tap
|
||||
|
||||
|
||||
def get_qinx_parent_by_name(yaml, ifname):
|
||||
""" Returns the sub-interface which matches a QinAD or QinQ outer tag, or None,None
|
||||
if that sub-interface doesn't exist. """
|
||||
"""Returns the sub-interface which matches a QinAD or QinQ outer tag, or None,None
|
||||
if that sub-interface doesn't exist."""
|
||||
|
||||
if not is_qinx(yaml, ifname):
|
||||
return None, None
|
||||
qinx_ifname, qinx_iface = get_by_name(yaml, ifname)
|
||||
if not qinx_iface:
|
||||
return None,None
|
||||
return None, None
|
||||
|
||||
qinx_encap = get_encapsulation(yaml, ifname)
|
||||
if not qinx_encap:
|
||||
return None,None
|
||||
return None, None
|
||||
|
||||
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
|
||||
if not parent_iface:
|
||||
return None,None
|
||||
return None, None
|
||||
|
||||
for subid, sub_iface in parent_iface['sub-interfaces'].items():
|
||||
for subid, sub_iface in parent_iface["sub-interfaces"].items():
|
||||
sub_ifname = f"{parent_ifname}.{int(subid)}"
|
||||
sub_encap = get_encapsulation(yaml, sub_ifname)
|
||||
if not sub_encap:
|
||||
continue
|
||||
if qinx_encap['dot1q'] > 0 and sub_encap['dot1q'] == qinx_encap['dot1q']:
|
||||
if qinx_encap["dot1q"] > 0 and sub_encap["dot1q"] == qinx_encap["dot1q"]:
|
||||
return sub_ifname, sub_iface
|
||||
if qinx_encap['dot1ad'] > 0 and sub_encap['dot1ad'] == qinx_encap['dot1ad']:
|
||||
if qinx_encap["dot1ad"] > 0 and sub_encap["dot1ad"] == qinx_encap["dot1ad"]:
|
||||
return sub_ifname, sub_iface
|
||||
return None,None
|
||||
return None, None
|
||||
|
||||
|
||||
def get_parent_by_name(yaml, ifname):
|
||||
""" Returns the sub-interface's parent, or None,None if the sub-int doesn't exist. """
|
||||
"""Returns the sub-interface's parent, or None,None if the sub-int doesn't exist."""
|
||||
try:
|
||||
parent_ifname, subid = ifname.split('.')
|
||||
parent_ifname, subid = ifname.split(".")
|
||||
subid = int(subid)
|
||||
iface = yaml['interfaces'][parent_ifname]
|
||||
iface = yaml["interfaces"][parent_ifname]
|
||||
return parent_ifname, iface
|
||||
except:
|
||||
pass
|
||||
return None,None
|
||||
return None, None
|
||||
|
||||
|
||||
def get_by_lcp_name(yaml, lcpname):
|
||||
""" Returns the interface or sub-interface by a given lcp name, or None,None if it does not exist """
|
||||
if not 'interfaces' in yaml:
|
||||
return None,None
|
||||
for ifname, iface in yaml['interfaces'].items():
|
||||
if 'lcp' in iface and iface['lcp'] == lcpname:
|
||||
"""Returns the interface or sub-interface by a given lcp name, or None,None if it does not exist"""
|
||||
if not "interfaces" in yaml:
|
||||
return None, None
|
||||
for ifname, iface in yaml["interfaces"].items():
|
||||
if "lcp" in iface and iface["lcp"] == lcpname:
|
||||
return ifname, iface
|
||||
if not 'sub-interfaces' in iface:
|
||||
if not "sub-interfaces" in iface:
|
||||
continue
|
||||
for subid, sub_iface in yaml['interfaces'][ifname]['sub-interfaces'].items():
|
||||
for subid, sub_iface in yaml["interfaces"][ifname]["sub-interfaces"].items():
|
||||
sub_ifname = f"{ifname}.{int(subid)}"
|
||||
if 'lcp' in sub_iface and sub_iface['lcp'] == lcpname:
|
||||
if "lcp" in sub_iface and sub_iface["lcp"] == lcpname:
|
||||
return sub_ifname, sub_iface
|
||||
return None,None
|
||||
return None, None
|
||||
|
||||
|
||||
def get_by_name(yaml, ifname):
|
||||
""" Returns the interface or sub-interface by a given name, or None,None if it does not exist """
|
||||
if '.' in ifname:
|
||||
"""Returns the interface or sub-interface by a given name, or None,None if it does not exist"""
|
||||
if "." in ifname:
|
||||
try:
|
||||
phy_ifname, subid = ifname.split('.')
|
||||
phy_ifname, subid = ifname.split(".")
|
||||
subid = int(subid)
|
||||
iface = yaml['interfaces'][phy_ifname]['sub-interfaces'][subid]
|
||||
iface = yaml["interfaces"][phy_ifname]["sub-interfaces"][subid]
|
||||
return ifname, iface
|
||||
except:
|
||||
return None, None
|
||||
|
||||
try:
|
||||
iface = yaml['interfaces'][ifname]
|
||||
iface = yaml["interfaces"][ifname]
|
||||
return ifname, iface
|
||||
except:
|
||||
pass
|
||||
@ -99,121 +100,125 @@ def get_by_name(yaml, ifname):
|
||||
|
||||
|
||||
def is_sub(yaml, ifname):
|
||||
""" Returns True if this interface is a sub-interface """
|
||||
"""Returns True if this interface is a sub-interface"""
|
||||
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
|
||||
return isinstance(parent_iface, dict)
|
||||
|
||||
|
||||
def has_sub(yaml, ifname):
|
||||
""" Returns True if this interface has sub-interfaces """
|
||||
if not 'interfaces' in yaml:
|
||||
"""Returns True if this interface has sub-interfaces"""
|
||||
if not "interfaces" in yaml:
|
||||
return False
|
||||
|
||||
if ifname in yaml['interfaces']:
|
||||
iface = yaml['interfaces'][ifname]
|
||||
if 'sub-interfaces' in iface and len(iface['sub-interfaces']) > 0:
|
||||
if ifname in yaml["interfaces"]:
|
||||
iface = yaml["interfaces"][ifname]
|
||||
if "sub-interfaces" in iface and len(iface["sub-interfaces"]) > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def has_address(yaml, ifname):
|
||||
""" Returns True if this interface or sub-interface has one or more addresses"""
|
||||
"""Returns True if this interface or sub-interface has one or more addresses"""
|
||||
|
||||
ifname, iface = get_by_name(yaml, ifname)
|
||||
if not iface:
|
||||
return False
|
||||
return 'addresses' in iface
|
||||
return "addresses" in iface
|
||||
|
||||
|
||||
def get_l2xc_interfaces(yaml):
|
||||
""" Returns a list of all interfaces that have an L2 CrossConnect """
|
||||
"""Returns a list of all interfaces that have an L2 CrossConnect"""
|
||||
ret = []
|
||||
if not 'interfaces' in yaml:
|
||||
if not "interfaces" in yaml:
|
||||
return ret
|
||||
for ifname, iface in yaml['interfaces'].items():
|
||||
if 'l2xc' in iface:
|
||||
for ifname, iface in yaml["interfaces"].items():
|
||||
if "l2xc" in iface:
|
||||
ret.append(ifname)
|
||||
if 'sub-interfaces' in iface:
|
||||
for subid, sub_iface in iface['sub-interfaces'].items():
|
||||
if "sub-interfaces" in iface:
|
||||
for subid, sub_iface in iface["sub-interfaces"].items():
|
||||
sub_ifname = f"{ifname}.{int(subid)}"
|
||||
if 'l2xc' in sub_iface:
|
||||
if "l2xc" in sub_iface:
|
||||
ret.append(sub_ifname)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def is_l2xc_interface(yaml, ifname):
|
||||
""" Returns True if this interface has an L2 CrossConnect """
|
||||
"""Returns True if this interface has an L2 CrossConnect"""
|
||||
|
||||
return ifname in get_l2xc_interfaces(yaml)
|
||||
|
||||
|
||||
def get_l2xc_target_interfaces(yaml):
|
||||
""" Returns a list of all interfaces that are the target of an L2 CrossConnect """
|
||||
"""Returns a list of all interfaces that are the target of an L2 CrossConnect"""
|
||||
ret = []
|
||||
if 'interfaces' in yaml:
|
||||
for ifname, iface in yaml['interfaces'].items():
|
||||
if 'l2xc' in iface:
|
||||
ret.append(iface['l2xc'])
|
||||
if 'sub-interfaces' in iface:
|
||||
for subid, sub_iface in iface['sub-interfaces'].items():
|
||||
if 'l2xc' in sub_iface:
|
||||
ret.append(sub_iface['l2xc'])
|
||||
if "interfaces" in yaml:
|
||||
for ifname, iface in yaml["interfaces"].items():
|
||||
if "l2xc" in iface:
|
||||
ret.append(iface["l2xc"])
|
||||
if "sub-interfaces" in iface:
|
||||
for subid, sub_iface in iface["sub-interfaces"].items():
|
||||
if "l2xc" in sub_iface:
|
||||
ret.append(sub_iface["l2xc"])
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def is_l2xc_target_interface(yaml, ifname):
|
||||
""" Returns True if this interface is the target of an L2 CrossConnect """
|
||||
"""Returns True if this interface is the target of an L2 CrossConnect"""
|
||||
|
||||
return ifname in get_l2xc_target_interfaces(yaml)
|
||||
|
||||
|
||||
def is_l2xc_target_interface_unique(yaml, ifname):
|
||||
""" Returns True if this interface is referenced as an l2xc target zero or one times """
|
||||
"""Returns True if this interface is referenced as an l2xc target zero or one times"""
|
||||
|
||||
ifs = get_l2xc_target_interfaces(yaml)
|
||||
return ifs.count(ifname) < 2
|
||||
|
||||
|
||||
def has_lcp(yaml, ifname):
|
||||
""" Returns True if this interface or sub-interface has an LCP """
|
||||
"""Returns True if this interface or sub-interface has an LCP"""
|
||||
|
||||
ifname, iface = get_by_name(yaml, ifname)
|
||||
if not iface:
|
||||
return False
|
||||
return 'lcp' in iface
|
||||
return "lcp" in iface
|
||||
|
||||
|
||||
def valid_encapsulation(yaml, ifname):
|
||||
""" Returns True if the sub interface has a valid encapsulation, or
|
||||
none at all """
|
||||
"""Returns True if the sub interface has a valid encapsulation, or
|
||||
none at all"""
|
||||
ifname, iface = get_by_name(yaml, ifname)
|
||||
if not iface:
|
||||
return True
|
||||
if not 'encapsulation' in iface:
|
||||
if not "encapsulation" in iface:
|
||||
return True
|
||||
|
||||
encap = iface['encapsulation']
|
||||
if 'dot1ad' in encap and 'dot1q' in encap:
|
||||
encap = iface["encapsulation"]
|
||||
if "dot1ad" in encap and "dot1q" in encap:
|
||||
return False
|
||||
if 'inner-dot1q' in encap and not ('dot1ad' in encap or 'dot1q' in encap):
|
||||
if "inner-dot1q" in encap and not ("dot1ad" in encap or "dot1q" in encap):
|
||||
return False
|
||||
if 'exact-match' in encap and encap['exact-match'] == False and has_lcp(yaml, ifname):
|
||||
if (
|
||||
"exact-match" in encap
|
||||
and encap["exact-match"] == False
|
||||
and has_lcp(yaml, ifname)
|
||||
):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_encapsulation(yaml, ifname):
|
||||
""" Returns the encapsulation of an interface name as a fully formed dictionary:
|
||||
"""Returns the encapsulation of an interface name as a fully formed dictionary:
|
||||
|
||||
dot1q: int (default 0)
|
||||
dot1ad: int (default 0)
|
||||
inner-dot1q: int (default 0)
|
||||
exact-match: bool (default False)
|
||||
dot1q: int (default 0)
|
||||
dot1ad: int (default 0)
|
||||
inner-dot1q: int (default 0)
|
||||
exact-match: bool (default False)
|
||||
|
||||
If the interface is not a sub-int with valid encapsulation, None is returned.
|
||||
If the interface is not a sub-int with valid encapsulation, None is returned.
|
||||
"""
|
||||
if not valid_encapsulation(yaml, ifname):
|
||||
return None
|
||||
@ -225,49 +230,49 @@ def get_encapsulation(yaml, ifname):
|
||||
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
|
||||
if not iface or not parent_iface:
|
||||
return None
|
||||
parent_ifname, subid = ifname.split('.')
|
||||
parent_ifname, subid = ifname.split(".")
|
||||
|
||||
dot1q = 0
|
||||
dot1ad = 0
|
||||
inner_dot1q = 0
|
||||
exact_match = False
|
||||
if not 'encapsulation' in iface:
|
||||
if not "encapsulation" in iface:
|
||||
dot1q = int(subid)
|
||||
exact_match = True
|
||||
else:
|
||||
if 'dot1q' in iface['encapsulation']:
|
||||
dot1q = iface['encapsulation']['dot1q']
|
||||
elif 'dot1ad' in iface['encapsulation']:
|
||||
dot1ad = iface['encapsulation']['dot1ad']
|
||||
if 'inner-dot1q' in iface['encapsulation']:
|
||||
inner_dot1q = iface['encapsulation']['inner-dot1q']
|
||||
if 'exact-match' in iface['encapsulation']:
|
||||
exact_match = iface['encapsulation']['exact-match']
|
||||
if "dot1q" in iface["encapsulation"]:
|
||||
dot1q = iface["encapsulation"]["dot1q"]
|
||||
elif "dot1ad" in iface["encapsulation"]:
|
||||
dot1ad = iface["encapsulation"]["dot1ad"]
|
||||
if "inner-dot1q" in iface["encapsulation"]:
|
||||
inner_dot1q = iface["encapsulation"]["inner-dot1q"]
|
||||
if "exact-match" in iface["encapsulation"]:
|
||||
exact_match = iface["encapsulation"]["exact-match"]
|
||||
|
||||
return {
|
||||
"dot1q": int(dot1q),
|
||||
"dot1ad": int(dot1ad),
|
||||
"inner-dot1q": int(inner_dot1q),
|
||||
"exact-match": bool(exact_match)
|
||||
}
|
||||
"dot1q": int(dot1q),
|
||||
"dot1ad": int(dot1ad),
|
||||
"inner-dot1q": int(inner_dot1q),
|
||||
"exact-match": bool(exact_match),
|
||||
}
|
||||
|
||||
|
||||
def get_phys(yaml):
|
||||
""" Return a list of all toplevel (ie. non-sub) interfaces which are
|
||||
"""Return a list of all toplevel (ie. non-sub) interfaces which are
|
||||
assumed to be physical network cards, eg TenGigabitEthernet1/0/0. Note
|
||||
that derived/created interfaces such as Tunnels, BondEthernets and
|
||||
Loopbacks are not returned """
|
||||
Loopbacks are not returned"""
|
||||
ret = []
|
||||
if not 'interfaces' in yaml:
|
||||
if not "interfaces" in yaml:
|
||||
return ret
|
||||
for ifname, iface in yaml['interfaces'].items():
|
||||
for ifname, iface in yaml["interfaces"].items():
|
||||
if is_phy(yaml, ifname):
|
||||
ret.append(ifname)
|
||||
return ret
|
||||
|
||||
|
||||
def is_phy(yaml, ifname):
|
||||
""" Returns True if the ifname is the name of a physical network interface. """
|
||||
"""Returns True if the ifname is the name of a physical network interface."""
|
||||
|
||||
ifname, iface = get_by_name(yaml, ifname)
|
||||
if iface == None:
|
||||
@ -287,33 +292,34 @@ def is_phy(yaml, ifname):
|
||||
|
||||
|
||||
def get_interfaces(yaml):
|
||||
""" Return a list of all interface and sub-interface names """
|
||||
"""Return a list of all interface and sub-interface names"""
|
||||
ret = []
|
||||
if not 'interfaces' in yaml:
|
||||
if not "interfaces" in yaml:
|
||||
return ret
|
||||
for ifname, iface in yaml['interfaces'].items():
|
||||
for ifname, iface in yaml["interfaces"].items():
|
||||
ret.append(ifname)
|
||||
if not 'sub-interfaces' in iface:
|
||||
if not "sub-interfaces" in iface:
|
||||
continue
|
||||
for subid, sub_iface in iface['sub-interfaces'].items():
|
||||
for subid, sub_iface in iface["sub-interfaces"].items():
|
||||
ret.append(f"{ifname}.{int(subid)}")
|
||||
return ret
|
||||
|
||||
|
||||
def get_sub_interfaces(yaml):
|
||||
""" Return all interfaces which are a subinterface. """
|
||||
"""Return all interfaces which are a subinterface."""
|
||||
ret = []
|
||||
for ifname in get_interfaces(yaml):
|
||||
if is_sub(yaml, ifname):
|
||||
ret.append(ifname)
|
||||
return ret
|
||||
|
||||
def get_qinx_interfaces(yaml):
|
||||
""" Return all interfaces which are double-tagged, either QinAD or QinQ.
|
||||
These interfaces will always have a valid encapsulation with 'inner-dot1q'
|
||||
set to non-zero.
|
||||
|
||||
Note: this is always a strict subset of get_sub_interfaces()
|
||||
def get_qinx_interfaces(yaml):
|
||||
"""Return all interfaces which are double-tagged, either QinAD or QinQ.
|
||||
These interfaces will always have a valid encapsulation with 'inner-dot1q'
|
||||
set to non-zero.
|
||||
|
||||
Note: this is always a strict subset of get_sub_interfaces()
|
||||
"""
|
||||
ret = []
|
||||
for ifname in get_interfaces(yaml):
|
||||
@ -322,19 +328,19 @@ def get_qinx_interfaces(yaml):
|
||||
encap = get_encapsulation(yaml, ifname)
|
||||
if not encap:
|
||||
continue
|
||||
if encap['inner-dot1q'] > 0:
|
||||
if encap["inner-dot1q"] > 0:
|
||||
ret.append(ifname)
|
||||
return ret
|
||||
|
||||
|
||||
def is_qinx(yaml, ifname):
|
||||
""" Returns True if the interface is a double-tagged (QinQ or QinAD) interface """
|
||||
"""Returns True if the interface is a double-tagged (QinQ or QinAD) interface"""
|
||||
return ifname in get_qinx_interfaces(yaml)
|
||||
|
||||
|
||||
def unique_encapsulation(yaml, sub_ifname):
|
||||
""" Ensures that for the sub_ifname specified, there exist no other sub-ints on the
|
||||
parent with the same encapsulation. """
|
||||
"""Ensures that for the sub_ifname specified, there exist no other sub-ints on the
|
||||
parent with the same encapsulation."""
|
||||
new_ifname, iface = get_by_name(yaml, sub_ifname)
|
||||
parent_ifname, parent_iface = get_parent_by_name(yaml, new_ifname)
|
||||
if not iface or not parent_iface:
|
||||
@ -345,7 +351,7 @@ def unique_encapsulation(yaml, sub_ifname):
|
||||
return False
|
||||
|
||||
ncount = 0
|
||||
for subid, sibling_iface in parent_iface['sub-interfaces'].items():
|
||||
for subid, sibling_iface in parent_iface["sub-interfaces"].items():
|
||||
sibling_ifname = f"{parent_ifname}.{int(subid)}"
|
||||
sibling_encap = get_encapsulation(yaml, sibling_ifname)
|
||||
if sub_encap == sibling_encap and new_ifname != sibling_ifname:
|
||||
@ -355,7 +361,7 @@ def unique_encapsulation(yaml, sub_ifname):
|
||||
|
||||
|
||||
def is_l2(yaml, ifname):
|
||||
""" Returns True if the interface is an L2XC source, L2XC target or a member of a bridgedomain """
|
||||
"""Returns True if the interface is an L2XC source, L2XC target or a member of a bridgedomain"""
|
||||
if bridgedomain.is_bridge_interface(yaml, ifname):
|
||||
return True
|
||||
if is_l2xc_interface(yaml, ifname):
|
||||
@ -366,22 +372,23 @@ def is_l2(yaml, ifname):
|
||||
|
||||
|
||||
def is_l3(yaml, ifname):
|
||||
""" Returns True if the interface exists and is neither l2xc target nor bridgedomain """
|
||||
"""Returns True if the interface exists and is neither l2xc target nor bridgedomain"""
|
||||
return not is_l2(yaml, ifname)
|
||||
|
||||
|
||||
def get_lcp(yaml, ifname):
|
||||
""" Returns the LCP of the interface. If the interface is a sub-interface with L3
|
||||
"""Returns the LCP of the interface. If the interface is a sub-interface with L3
|
||||
enabled, synthesize it based on its parent, using smart QinQ syntax.
|
||||
Return None if no LCP can be found. """
|
||||
Return None if no LCP can be found."""
|
||||
|
||||
ifname, iface = get_by_name(yaml, ifname)
|
||||
if iface and 'lcp' in iface:
|
||||
return iface['lcp']
|
||||
if iface and "lcp" in iface:
|
||||
return iface["lcp"]
|
||||
return None
|
||||
|
||||
|
||||
def get_mtu(yaml, ifname):
|
||||
""" Returns MTU of the interface. If it's not set, return the parent's MTU, and
|
||||
"""Returns MTU of the interface. If it's not set, return the parent's MTU, and
|
||||
return 1500 if no MTU was set on the sub-int or the parent."""
|
||||
ifname, iface = get_by_name(yaml, ifname)
|
||||
if not iface:
|
||||
@ -390,61 +397,70 @@ def get_mtu(yaml, ifname):
|
||||
parent_ifname, parent_iface = get_parent_by_name(yaml, ifname)
|
||||
|
||||
try:
|
||||
return iface['mtu']
|
||||
return parent_iface['mtu']
|
||||
return iface["mtu"]
|
||||
return parent_iface["mtu"]
|
||||
except:
|
||||
pass
|
||||
return 1500
|
||||
|
||||
|
||||
def get_admin_state(yaml, ifname):
|
||||
""" Return True if the interface admin state should be 'up'. Return False
|
||||
if it does not exist, or if it's set to 'down'. """
|
||||
"""Return True if the interface admin state should be 'up'. Return False
|
||||
if it does not exist, or if it's set to 'down'."""
|
||||
ifname, iface = get_by_name(yaml, ifname)
|
||||
if not iface:
|
||||
return False
|
||||
if not 'state' in iface:
|
||||
if not "state" in iface:
|
||||
return True
|
||||
return iface['state'] == 'up'
|
||||
return iface["state"] == "up"
|
||||
|
||||
|
||||
def validate_interfaces(yaml):
|
||||
result = True
|
||||
msgs = []
|
||||
logger = logging.getLogger('vppcfg.config')
|
||||
logger = logging.getLogger("vppcfg.config")
|
||||
logger.addHandler(logging.NullHandler())
|
||||
|
||||
if not 'interfaces' in yaml:
|
||||
if not "interfaces" in yaml:
|
||||
return result, msgs
|
||||
|
||||
for ifname, iface in yaml['interfaces'].items():
|
||||
for ifname, iface in yaml["interfaces"].items():
|
||||
logger.debug(f"interface {iface}")
|
||||
if ifname.startswith("BondEthernet") and (None,None) == bondethernet.get_by_name(yaml, ifname):
|
||||
if ifname.startswith("BondEthernet") and (
|
||||
None,
|
||||
None,
|
||||
) == bondethernet.get_by_name(yaml, ifname):
|
||||
msgs.append(f"interface {ifname} does not exist in bondethernets")
|
||||
result = False
|
||||
if ifname.startswith("BondEthernet") and 'mac' in iface:
|
||||
msgs.append(f"interface {ifname} is a member of bondethernet, cannot set MAC")
|
||||
if ifname.startswith("BondEthernet") and "mac" in iface:
|
||||
msgs.append(
|
||||
f"interface {ifname} is a member of bondethernet, cannot set MAC"
|
||||
)
|
||||
result = False
|
||||
if not 'state' in iface:
|
||||
iface['state'] = 'up'
|
||||
if not "state" in iface:
|
||||
iface["state"] = "up"
|
||||
|
||||
if 'mac' in iface and mac.is_multicast(iface['mac']):
|
||||
msgs.append(f"interface {ifname} MAC address {iface['mac']} cannot be multicast")
|
||||
if "mac" in iface and mac.is_multicast(iface["mac"]):
|
||||
msgs.append(
|
||||
f"interface {ifname} MAC address {iface['mac']} cannot be multicast"
|
||||
)
|
||||
result = False
|
||||
|
||||
iface_mtu = get_mtu(yaml, ifname)
|
||||
iface_lcp = get_lcp(yaml, ifname)
|
||||
iface_address = has_address(yaml, ifname)
|
||||
|
||||
if ifname.startswith('tap'):
|
||||
if ifname.startswith("tap"):
|
||||
tap_ifname, tap_iface = tap.get_by_name(yaml, ifname)
|
||||
if not tap_iface:
|
||||
msgs.append(f"interface {ifname} is a TAP but does not exist in taps")
|
||||
result = False
|
||||
elif 'mtu' in tap_iface['host']:
|
||||
host_mtu = tap_iface['host']['mtu']
|
||||
elif "mtu" in tap_iface["host"]:
|
||||
host_mtu = tap_iface["host"]["mtu"]
|
||||
if host_mtu != iface_mtu:
|
||||
msgs.append(f"interface {ifname} is a TAP so its MTU {int(iface_mtu)} must match host MTU {int(host_mtu)}")
|
||||
msgs.append(
|
||||
f"interface {ifname} is a TAP so its MTU {int(iface_mtu)} must match host MTU {int(host_mtu)}"
|
||||
)
|
||||
result = False
|
||||
if iface_address:
|
||||
msgs.append(f"interface {ifname} is a TAP so it cannot have an address")
|
||||
@ -453,28 +469,38 @@ def validate_interfaces(yaml):
|
||||
msgs.append(f"interface {ifname} is a TAP so it cannot have an LCP")
|
||||
result = False
|
||||
if has_sub(yaml, ifname):
|
||||
msgs.append(f"interface {ifname} is a TAP so it cannot have sub-interfaces")
|
||||
msgs.append(
|
||||
f"interface {ifname} is a TAP so it cannot have sub-interfaces"
|
||||
)
|
||||
result = False
|
||||
|
||||
if is_l2(yaml, ifname) and iface_lcp:
|
||||
msgs.append(f"interface {ifname} is in L2 mode but has LCP name {iface_lcp}")
|
||||
msgs.append(
|
||||
f"interface {ifname} is in L2 mode but has LCP name {iface_lcp}"
|
||||
)
|
||||
result = False
|
||||
if is_l2(yaml, ifname) and iface_address:
|
||||
msgs.append(f"interface {ifname} is in L2 mode but has an address")
|
||||
result = False
|
||||
if iface_lcp and not lcp.is_unique(yaml, iface_lcp):
|
||||
msgs.append(f"interface {ifname} does not have a unique LCP name {iface_lcp}")
|
||||
msgs.append(
|
||||
f"interface {ifname} does not have a unique LCP name {iface_lcp}"
|
||||
)
|
||||
result = False
|
||||
|
||||
if 'addresses' in iface:
|
||||
for a in iface['addresses']:
|
||||
if not address.is_allowed(yaml, ifname, iface['addresses'], a):
|
||||
msgs.append(f"interface {ifname} IP address {a} conflicts with another")
|
||||
if "addresses" in iface:
|
||||
for a in iface["addresses"]:
|
||||
if not address.is_allowed(yaml, ifname, iface["addresses"], a):
|
||||
msgs.append(
|
||||
f"interface {ifname} IP address {a} conflicts with another"
|
||||
)
|
||||
result = False
|
||||
|
||||
if 'l2xc' in iface:
|
||||
if "l2xc" in iface:
|
||||
if has_sub(yaml, ifname):
|
||||
msgs.append(f"interface {ifname} has l2xc so it cannot have sub-interfaces")
|
||||
msgs.append(
|
||||
f"interface {ifname} has l2xc so it cannot have sub-interfaces"
|
||||
)
|
||||
result = False
|
||||
if iface_lcp:
|
||||
msgs.append(f"interface {ifname} has l2xc so it cannot have an LCP")
|
||||
@ -482,31 +508,45 @@ def validate_interfaces(yaml):
|
||||
if iface_address:
|
||||
msgs.append(f"interface {ifname} has l2xc so it cannot have an address")
|
||||
result = False
|
||||
if (None,None) == get_by_name(yaml, iface['l2xc']):
|
||||
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} does not exist")
|
||||
if (None, None) == get_by_name(yaml, iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"interface {ifname} l2xc target {iface['l2xc']} does not exist"
|
||||
)
|
||||
result = False
|
||||
if iface['l2xc'] == ifname:
|
||||
if iface["l2xc"] == ifname:
|
||||
msgs.append(f"interface {ifname} l2xc target cannot be itself")
|
||||
result = False
|
||||
target_mtu = get_mtu(yaml, iface['l2xc'])
|
||||
target_mtu = get_mtu(yaml, iface["l2xc"])
|
||||
if target_mtu != iface_mtu:
|
||||
msgs.append(f"interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(iface_mtu)}")
|
||||
msgs.append(
|
||||
f"interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(iface_mtu)}"
|
||||
)
|
||||
result = False
|
||||
if not is_l2xc_target_interface_unique(yaml, iface['l2xc']):
|
||||
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} is not unique")
|
||||
if not is_l2xc_target_interface_unique(yaml, iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"interface {ifname} l2xc target {iface['l2xc']} is not unique"
|
||||
)
|
||||
result = False
|
||||
if bridgedomain.is_bridge_interface(yaml, iface['l2xc']):
|
||||
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} is in a bridgedomain")
|
||||
if bridgedomain.is_bridge_interface(yaml, iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"interface {ifname} l2xc target {iface['l2xc']} is in a bridgedomain"
|
||||
)
|
||||
result = False
|
||||
if has_lcp(yaml, iface['l2xc']):
|
||||
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} cannot have an LCP")
|
||||
if has_lcp(yaml, iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"interface {ifname} l2xc target {iface['l2xc']} cannot have an LCP"
|
||||
)
|
||||
result = False
|
||||
if has_address(yaml, iface['l2xc']):
|
||||
msgs.append(f"interface {ifname} l2xc target {iface['l2xc']} cannot have an address")
|
||||
if has_address(yaml, iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"interface {ifname} l2xc target {iface['l2xc']} cannot have an address"
|
||||
)
|
||||
result = False
|
||||
|
||||
if has_sub(yaml, ifname):
|
||||
for sub_id, sub_iface in yaml['interfaces'][ifname]['sub-interfaces'].items():
|
||||
for sub_id, sub_iface in yaml["interfaces"][ifname][
|
||||
"sub-interfaces"
|
||||
].items():
|
||||
logger.debug(f"sub-interface {sub_iface}")
|
||||
sub_ifname = f"{ifname}.{int(sub_id)}"
|
||||
if not sub_iface:
|
||||
@ -514,93 +554,138 @@ def validate_interfaces(yaml):
|
||||
result = False
|
||||
continue
|
||||
|
||||
if not 'state' in sub_iface:
|
||||
sub_iface['state'] = 'up'
|
||||
if sub_iface['state'] == 'up' and iface['state'] == 'down':
|
||||
msgs.append(f"sub-interface {sub_ifname} cannot be up if parent {ifname} is down")
|
||||
if not "state" in sub_iface:
|
||||
sub_iface["state"] = "up"
|
||||
if sub_iface["state"] == "up" and iface["state"] == "down":
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} cannot be up if parent {ifname} is down"
|
||||
)
|
||||
result = False
|
||||
|
||||
sub_mtu = get_mtu(yaml, sub_ifname)
|
||||
if sub_mtu > iface_mtu:
|
||||
msgs.append(f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {ifname} MTU {int(iface_mtu)}")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {ifname} MTU {int(iface_mtu)}"
|
||||
)
|
||||
result = False
|
||||
if is_qinx(yaml, sub_ifname):
|
||||
mid_ifname, mid_iface = get_qinx_parent_by_name(yaml, sub_ifname)
|
||||
mid_mtu = get_mtu(yaml, mid_ifname)
|
||||
if sub_mtu > mid_mtu:
|
||||
msgs.append(f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {mid_ifname} MTU {int(mid_mtu)}")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} has MTU {int(sub_iface['mtu'])} higher than parent {mid_ifname} MTU {int(mid_mtu)}"
|
||||
)
|
||||
result = False
|
||||
|
||||
sub_lcp = get_lcp(yaml, sub_ifname)
|
||||
if is_l2(yaml, sub_ifname) and sub_lcp:
|
||||
msgs.append(f"sub-interface {sub_ifname} is in L2 mode but has LCP name {sub_lcp}")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} is in L2 mode but has LCP name {sub_lcp}"
|
||||
)
|
||||
result = False
|
||||
if sub_lcp and not lcp.is_unique(yaml, sub_lcp):
|
||||
msgs.append(f"sub-interface {sub_ifname} does not have a unique LCP name {sub_lcp}")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} does not have a unique LCP name {sub_lcp}"
|
||||
)
|
||||
result = False
|
||||
if sub_lcp and not iface_lcp:
|
||||
msgs.append(f"sub-interface {sub_ifname} has LCP name {sub_lcp} but {ifname} does not have an LCP")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} has LCP name {sub_lcp} but {ifname} does not have an LCP"
|
||||
)
|
||||
result = False
|
||||
if sub_lcp and is_qinx(yaml, sub_ifname):
|
||||
mid_ifname, mid_iface = get_qinx_parent_by_name(yaml, sub_ifname)
|
||||
if not mid_iface:
|
||||
msgs.append(f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} which requires a parent")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} which requires a parent"
|
||||
)
|
||||
result = False
|
||||
elif not get_lcp(yaml, mid_ifname):
|
||||
msgs.append(f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} but {mid_ifname} does not have an LCP")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} is QinX and has LCP name {sub_lcp} but {mid_ifname} does not have an LCP"
|
||||
)
|
||||
result = False
|
||||
|
||||
encap = get_encapsulation(yaml, sub_ifname)
|
||||
if sub_lcp and (not encap or not encap['exact-match']):
|
||||
msgs.append(f"sub-interface {sub_ifname} has LCP name {sub_lcp} but its encapsulation is not exact-match")
|
||||
if sub_lcp and (not encap or not encap["exact-match"]):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} has LCP name {sub_lcp} but its encapsulation is not exact-match"
|
||||
)
|
||||
result = False
|
||||
|
||||
if has_address(yaml, sub_ifname):
|
||||
if not encap or not encap['exact-match']:
|
||||
msgs.append(f"sub-interface {sub_ifname} has an address but its encapsulation is not exact-match")
|
||||
if not encap or not encap["exact-match"]:
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} has an address but its encapsulation is not exact-match"
|
||||
)
|
||||
result = False
|
||||
if is_l2(yaml, sub_ifname):
|
||||
msgs.append(f"sub-interface {sub_ifname} is in L2 mode but has an address")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} is in L2 mode but has an address"
|
||||
)
|
||||
result = False
|
||||
for a in sub_iface['addresses']:
|
||||
if not address.is_allowed(yaml, sub_ifname, sub_iface['addresses'], a):
|
||||
msgs.append(f"sub-interface {sub_ifname} IP address {a} conflicts with another")
|
||||
for a in sub_iface["addresses"]:
|
||||
if not address.is_allowed(
|
||||
yaml, sub_ifname, sub_iface["addresses"], a
|
||||
):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} IP address {a} conflicts with another"
|
||||
)
|
||||
result = False
|
||||
if not valid_encapsulation(yaml, sub_ifname):
|
||||
msgs.append(f"sub-interface {sub_ifname} has invalid encapsulation")
|
||||
result = False
|
||||
elif not unique_encapsulation(yaml, sub_ifname):
|
||||
msgs.append(f"sub-interface {sub_ifname} does not have unique encapsulation")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} does not have unique encapsulation"
|
||||
)
|
||||
result = False
|
||||
if 'l2xc' in sub_iface:
|
||||
if "l2xc" in sub_iface:
|
||||
if has_lcp(yaml, sub_ifname):
|
||||
msgs.append(f"sub-interface {sub_ifname} has l2xc so it cannot have an LCP")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} has l2xc so it cannot have an LCP"
|
||||
)
|
||||
result = False
|
||||
if has_address(yaml, sub_ifname):
|
||||
msgs.append(f"sub-interface {sub_ifname} has l2xc so it cannot have an address")
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} has l2xc so it cannot have an address"
|
||||
)
|
||||
result = False
|
||||
if (None, None) == get_by_name(yaml, sub_iface['l2xc']):
|
||||
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} does not exist")
|
||||
if (None, None) == get_by_name(yaml, sub_iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} does not exist"
|
||||
)
|
||||
result = False
|
||||
if sub_iface['l2xc'] == sub_ifname:
|
||||
msgs.append(f"sub-interface {sub_ifname} l2xc target cannot be itself")
|
||||
if sub_iface["l2xc"] == sub_ifname:
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} l2xc target cannot be itself"
|
||||
)
|
||||
result = False
|
||||
target_mtu = get_mtu(yaml, sub_iface['l2xc'])
|
||||
target_mtu = get_mtu(yaml, sub_iface["l2xc"])
|
||||
if target_mtu != sub_mtu:
|
||||
msgs.append(f"sub-interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(sub_mtu)}")
|
||||
msgs.append(
|
||||
f"sub-interface {ifname} l2xc target MTU {int(target_mtu)} does not match source MTU {int(sub_mtu)}"
|
||||
)
|
||||
result = False
|
||||
if not is_l2xc_target_interface_unique(yaml, sub_iface['l2xc']):
|
||||
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is not unique")
|
||||
if not is_l2xc_target_interface_unique(yaml, sub_iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is not unique"
|
||||
)
|
||||
result = False
|
||||
if bridgedomain.is_bridge_interface(yaml, sub_iface['l2xc']):
|
||||
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is in a bridgedomain")
|
||||
if bridgedomain.is_bridge_interface(yaml, sub_iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} is in a bridgedomain"
|
||||
)
|
||||
result = False
|
||||
if has_lcp(yaml, sub_iface['l2xc']):
|
||||
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an LCP")
|
||||
if has_lcp(yaml, sub_iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an LCP"
|
||||
)
|
||||
result = False
|
||||
if has_address(yaml, sub_iface['l2xc']):
|
||||
msgs.append(f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an address")
|
||||
if has_address(yaml, sub_iface["l2xc"]):
|
||||
msgs.append(
|
||||
f"sub-interface {sub_ifname} l2xc target {sub_iface['l2xc']} cannot have an address"
|
||||
)
|
||||
result = False
|
||||
|
||||
|
||||
return result, msgs
|
||||
|
Reference in New Issue
Block a user