From b48ff1a9838a7edcf024ff0ec73f2f404f2fe404 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Mon, 8 Dec 2014 17:15:57 -0800 Subject: [PATCH] This patch moves bond slave link ownership to the bond module and makes sure that slaves can never be brought admin up on their own when they are not in the bond Ticket: CM-4408 Reviewed By: CCR-2323 Testing Done: Tested ifup/ifdown of bond slaves and bond interface This patch introduces: - introduces 2 interface flags, LINK_MASTER and LINK_SLAVE. - The bond module will set LINK_MASTER on the bond iface object indicating that the bond module owns the link. - Which means that all lower devices /slaves of the bond get their link when the bond (aka LINK_MASTER) is processed in the bond module - The module that queries dependencies propagates the LINK_SLAVE flags on the dependents of LINK_MASTER. - The scheduler now acts on the LINK_SLAVE flag. If LINK_SLAVE is set, it skips setting admin 'up' on that interface. It also makes sure the interface is not already in the bond. ie if an interface is a LINK_SLAVE (bond slave in this case), admin up will not be executed when the interface is not inside the bond. (cherry picked from commit 84b5a07a4f7685c7ae2eac5892889d6c0e08b2eb) --- addons/ifenslave.py | 6 ++-- ifupdown/iface.py | 8 +++-- ifupdown/ifupdownmain.py | 69 +++++++++++++++++++--------------------- 3 files changed, 40 insertions(+), 43 deletions(-) diff --git a/addons/ifenslave.py b/addons/ifenslave.py index a4dbf0d..7189cd4 100644 --- a/addons/ifenslave.py +++ b/addons/ifenslave.py @@ -105,6 +105,7 @@ class ifenslave(moduleBase): # Also save a copy for future use ifaceobj.priv_data = list(slave_list) + ifaceobj.flags |= iface.LINK_MASTER return slave_list def get_dependent_ifacenames_running(self, ifaceobj): @@ -200,9 +201,8 @@ class ifenslave(moduleBase): self.log_warn('%s: skipping slave %s, does not exist' %(ifaceobj.name, slave)) continue - self.ifenslavecmd.enslave_slave(ifaceobj.name, slave, - prehook=self.ipcmd.link_down, - posthook=self.ipcmd.link_up) + self.ipcmd.link_set(slave, 'master', ifaceobj.name) + rtnetlink_api.rtnl_api.link_set(slave, "up") def _apply_slaves_lacp_fallback_prio(self, ifaceobj): slaves = self.ifenslavecmd.get_slaves(ifaceobj.name) diff --git a/ifupdown/iface.py b/ifupdown/iface.py index 5365eca..3e9d81a 100644 --- a/ifupdown/iface.py +++ b/ifupdown/iface.py @@ -181,6 +181,8 @@ class iface(): HAS_SIBLINGS = 0x2 IFACERANGE_ENTRY = 0x3 IFACERANGE_START = 0x4 + LINK_MASTER = 0x5 + LINK_SLAVE = 0x6 version = '0.1' @@ -452,10 +454,10 @@ class iface(): unknownstr='unknown', use_realname=False): indent = '\t' outbuf = '' - if use_realname: - name = self.realname + if use_realname and self.realname: + name = '%s' %self.realname else: - name = self.name + name = '%s' %self.name if self.auto: outbuf += 'auto %s\n' %name ifaceline = '' diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index e807267..5443b20 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -108,14 +108,26 @@ class ifupdownMain(ifupdownBase): # Handlers for ops that ifupdown2 owns def run_up(self, ifaceobj): - ifacename = ifaceobj.name - if self.link_exists(ifacename): - self.link_up(ifacename) + # If this object is a link slave, ie its link is controlled + # by its link master interface, then dont set the link state. + # But do allow user to change state of the link if the interface + # is already with its link master (hence the master check). + if ((ifaceobj.flags & iface.LINK_SLAVE) and + not os.path.exists('/sys/class/net/%s/master' %ifaceobj.name)): + return + if self.link_exists(ifaceobj.name): + self.link_up(ifaceobj.name) def run_down(self, ifaceobj): - ifacename = ifaceobj.name - if self.link_exists(ifacename): - self.link_down(ifacename) + # If this object is a link slave, ie its link is controlled + # by its link master interface, then dont set the link state. + # But do allow user to change state of the link if the interface + # is already with its link master (hence the master check). + if ((ifaceobj.flags & iface.LINK_SLAVE) and + not os.path.exists('/sys/class/net/%s/master' %ifaceobj.name)): + return + if self.link_exists(ifaceobj.name): + self.link_down(ifaceobj.name) # ifupdown object interface operation handlers ops_handlers = OrderedDict([('up', run_up), @@ -314,7 +326,7 @@ class ifupdownMain(ifupdownBase): if not ifaceobj: return True return self.is_ifaceobj_noconfig(ifaceobj) - def preprocess_dependency_list(self, upperifacename, dlist, ops): + def preprocess_dependency_list(self, upperifaceobj, dlist, ops): """ We go through the dependency list and delete or add interfaces from the interfaces dict by applying the following rules: @@ -334,18 +346,25 @@ class ifupdownMain(ifupdownBase): for d in dlist: dilist = self.get_ifaceobjs(d) if not dilist: + ni = None if self.is_iface_builtin_byname(d): - self.create_n_save_ifaceobj(d, self.BUILTIN | self.NOCONFIG, - True).add_to_upperifaces(upperifacename) + ni = self.create_n_save_ifaceobj(d, self.BUILTIN | self.NOCONFIG, + True) elif not self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG: - self.create_n_save_ifaceobj(d, self.NOCONFIG, - True).add_to_upperifaces(upperifacename) + ni = self.create_n_save_ifaceobj(d, self.NOCONFIG, + True) else: del_list.append(d) + if ni: + ni.add_to_upperifaces(upperifaceobj.name) + if (upperifaceobj.flags & iface.LINK_MASTER): + ni.flags |= iface.LINK_SLAVE else: for di in dilist: di.inc_refcnt() - di.add_to_upperifaces(upperifacename) + di.add_to_upperifaces(upperifaceobj.name) + if (upperifaceobj.flags & iface.LINK_MASTER): + di.flags |= iface.LINK_SLAVE for d in del_list: dlist.remove(d) @@ -375,30 +394,6 @@ class ifupdownMain(ifupdownBase): if dlist: ret_dlist.extend(dlist) return list(set(ret_dlist)) - def populate_dependency_info_old(self, ops, ifacenames=None): - """ recursive function to generate iface dependency info """ - - if not ifacenames: - ifacenames = self.ifaceobjdict.keys() - - iqueue = deque(ifacenames) - while iqueue: - i = iqueue.popleft() - # Go through all modules and find dependent ifaces - dlist = None - ifaceobj = self.get_ifaceobj_first(i) - if not ifaceobj: - continue - dlist = self.query_dependents(ifaceobj, ops, ifacenames) - if dlist and dlist != ifaceobj.lowerifaces: - self.preprocess_dependency_list(ifaceobj.name, - dlist, ops) - [iqueue.append(d) for d in dlist] - self.dependency_graph.setdefault(i, []).extend(dlist) - ifaceobj.lowerifaces = self.dependency_graph.get(i) - else: - self.dependency_graph[i] = dlist - def populate_dependency_info(self, ops, ifacenames=None): """ recursive function to generate iface dependency info """ @@ -419,7 +414,7 @@ class ifupdownMain(ifupdownBase): else: continue if dlist: - self.preprocess_dependency_list(ifaceobj.name, + self.preprocess_dependency_list(ifaceobj, dlist, ops) ifaceobj.lowerifaces = dlist [iqueue.append(d) for d in dlist]