mirror of
https://github.com/CumulusNetworks/ifupdown2.git
synced 2024-05-06 15:54:50 +00:00
Add check for shared dependents during building dependency list
Ticket: CM-5373 Reviewed By: sam Testing Done: Tested with shared slaves in bridge and bonds
This commit is contained in:
@@ -221,6 +221,7 @@ class bridge(moduleBase):
|
||||
if ifaceobj.link_type != ifaceLinkType.LINK_NA:
|
||||
ifaceobj.link_type = ifaceLinkType.LINK_MASTER
|
||||
ifaceobj.link_kind = ifaceLinkKind.BRIDGE
|
||||
ifaceobj.dependency_type = ifaceDependencyType.MASTER_SLAVE
|
||||
return self.parse_port_list(ifaceobj.get_attr_value_first(
|
||||
'bridge-ports'), ifacenames_all)
|
||||
|
||||
|
@@ -118,7 +118,7 @@ class ifenslave(moduleBase):
|
||||
return None
|
||||
slave_list = self.parse_port_list(ifaceobj.get_attr_value_first(
|
||||
'bond-slaves'), ifacenames_all)
|
||||
|
||||
ifaceobj.dependency_type = ifaceDependencyType.MASTER_SLAVE
|
||||
# Also save a copy for future use
|
||||
ifaceobj.priv_data = list(slave_list)
|
||||
if ifaceobj.link_type != ifaceLinkType.LINK_NA:
|
||||
|
@@ -33,6 +33,36 @@ class ifaceLinkType():
|
||||
LINK_MASTER = 0x2
|
||||
LINK_NA = 0x3
|
||||
|
||||
class ifaceDependencyType():
|
||||
""" Indicates type of dependency.
|
||||
|
||||
This class enumerates types of dependency relationships
|
||||
between interfaces.
|
||||
|
||||
iface dependency relationships can be classified
|
||||
into:
|
||||
- link
|
||||
- master/slave
|
||||
|
||||
In a 'link' dependency relationship, dependency can be shared
|
||||
between interfaces. example: swp1.100 and
|
||||
swp1.200 can both have 'link' swp1. swp1 is also a dependency
|
||||
of swp1.100 and swp1.200. As you can see dependency
|
||||
swp1 is shared between swp1.100 and swp1.200.
|
||||
|
||||
In a master/slave relationship like bridge and
|
||||
its ports: eg: bridge br0 and its ports swp1 and swp2.
|
||||
dependency swp1 and swp2 cannot be shared with any other
|
||||
interface with the same dependency relationship.
|
||||
ie, swp1 and swp2 cannot be in a slave relationship
|
||||
with another interface. Understanding the dependency type is
|
||||
required for any semantic checks between dependencies.
|
||||
|
||||
"""
|
||||
UNKNOWN = 0x0
|
||||
LINK = 0x1
|
||||
MASTER_SLAVE = 0x2
|
||||
|
||||
class ifaceStatus():
|
||||
"""Enumerates iface status """
|
||||
|
||||
@@ -230,6 +260,10 @@ class iface():
|
||||
self.link_type = ifaceLinkType.LINK_UNKNOWN
|
||||
self.link_kind = ifaceLinkKind.UNKNOWN
|
||||
|
||||
# The below attribute is used to disambiguate between various
|
||||
# types of dependencies
|
||||
self.dependency_type = ifaceDependencyType.UNKNOWN
|
||||
|
||||
def _set_attrs_from_dict(self, attrdict):
|
||||
self.auto = attrdict.get('auto', False)
|
||||
self.name = attrdict.get('name')
|
||||
@@ -416,6 +450,7 @@ class iface():
|
||||
del odict['env']
|
||||
del odict['link_type']
|
||||
del odict['link_kind']
|
||||
del odict['dependency_type']
|
||||
return odict
|
||||
|
||||
def __setstate__(self, dict):
|
||||
@@ -434,6 +469,7 @@ class iface():
|
||||
self.flags |= self._PICKLED
|
||||
self.link_type = ifaceLinkType.LINK_NA
|
||||
self.link_kind = ifaceLinkKind.UNKNOWN
|
||||
self.dependency_type = ifaceDependencyType.UNKNOWN
|
||||
|
||||
def dump_raw(self, logger):
|
||||
indent = ' '
|
||||
|
@@ -384,6 +384,27 @@ class ifupdownMain(ifupdownBase):
|
||||
if not ifaceobj: return True
|
||||
return self.is_ifaceobj_noconfig(ifaceobj)
|
||||
|
||||
def check_shared_dependents(self, ifaceobj, dlist):
|
||||
""" Check if dlist intersects with any other
|
||||
interface with slave dependents.
|
||||
example: bond and bridges.
|
||||
This function logs such errors """
|
||||
setdlist = Set(dlist)
|
||||
for ifacename, ifacedlist in self.dependency_graph.items():
|
||||
if not ifacedlist:
|
||||
continue
|
||||
check_depends = False
|
||||
iobjs = self.get_ifaceobjs(ifacename)
|
||||
for i in iobjs:
|
||||
if (i.dependency_type == ifaceDependencyType.MASTER_SLAVE):
|
||||
check_depends = True
|
||||
if check_depends:
|
||||
common = Set(ifacedlist).intersection(setdlist)
|
||||
if common:
|
||||
self.logger.error('iface %s and %s '
|
||||
%(ifaceobj.name, ifacename) +
|
||||
'have common dependents %s' %str(list(common)))
|
||||
|
||||
def preprocess_dependency_list(self, upperifaceobj, dlist, ops):
|
||||
""" We go through the dependency list and
|
||||
delete or add interfaces from the interfaces dict by
|
||||
@@ -401,6 +422,10 @@ class ifupdownMain(ifupdownBase):
|
||||
"""
|
||||
del_list = []
|
||||
|
||||
if (upperifaceobj.dependency_type ==
|
||||
ifaceDependencyType.MASTER_SLAVE):
|
||||
self.check_shared_dependents(upperifaceobj, dlist)
|
||||
|
||||
for d in dlist:
|
||||
dilist = self.get_ifaceobjs(d)
|
||||
if not dilist:
|
||||
@@ -451,6 +476,7 @@ class ifupdownMain(ifupdownBase):
|
||||
if dlist: ret_dlist.extend(dlist)
|
||||
return list(set(ret_dlist))
|
||||
|
||||
|
||||
def populate_dependency_info(self, ops, ifacenames=None):
|
||||
""" recursive function to generate iface dependency info """
|
||||
|
||||
|
Reference in New Issue
Block a user