diff --git a/addons/bridge.py b/addons/bridge.py index ebc9fbf..8ee76a4 100644 --- a/addons/bridge.py +++ b/addons/bridge.py @@ -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) diff --git a/addons/ifenslave.py b/addons/ifenslave.py index 6c5bda3..671d725 100644 --- a/addons/ifenslave.py +++ b/addons/ifenslave.py @@ -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: diff --git a/ifupdown/iface.py b/ifupdown/iface.py index 7e3f849..216225e 100644 --- a/ifupdown/iface.py +++ b/ifupdown/iface.py @@ -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 = ' ' diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index f46d5b2..44a34fe 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -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 """