mirror of
https://github.com/CumulusNetworks/ifupdown2.git
synced 2024-05-06 15:54:50 +00:00
Fix bug during handling multiple iface sections for same interface
Ticket: CM-1438 Reviewed By: Testing Done: Tested ifupdown2 sanity + multiple iface sections for an interface - This patch fixes a few shortcomings in the multiple iface sections for same interface (partly because i was only covering backward compatibility cases earlier) - Since this is a very common configuration pattern, this patch cleans it up - also restructures some code - main change is: before: for iface in ifaces: for op in ops: run op on iface after: for op in ops: for iface in ifaces: run op on iface
This commit is contained in:
@@ -169,6 +169,7 @@ class iface():
|
|||||||
|
|
||||||
# flag to indicate that the object was created from pickled state
|
# flag to indicate that the object was created from pickled state
|
||||||
_PICKLED = 0x1
|
_PICKLED = 0x1
|
||||||
|
HAS_SIBLINGS = 0x2
|
||||||
|
|
||||||
version = '0.1'
|
version = '0.1'
|
||||||
|
|
||||||
|
@@ -188,21 +188,26 @@ class ifupdownMain(ifupdownBase):
|
|||||||
return ifaceobj
|
return ifaceobj
|
||||||
|
|
||||||
def create_n_save_ifaceobjcurr(self, ifaceobj):
|
def create_n_save_ifaceobjcurr(self, ifaceobj):
|
||||||
""" creates a copy of iface object and adds it to the iface dict containing current iface objects
|
""" creates a copy of iface object and adds it to the iface
|
||||||
|
dict containing current iface objects
|
||||||
"""
|
"""
|
||||||
ifaceobjcurr = self.get_ifaceobjcurr(ifaceobj.name)
|
|
||||||
if ifaceobjcurr:
|
|
||||||
return ifaceobjcurr
|
|
||||||
ifaceobjcurr = iface()
|
ifaceobjcurr = iface()
|
||||||
ifaceobjcurr.name = ifaceobj.name
|
ifaceobjcurr.name = ifaceobj.name
|
||||||
ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
|
ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
|
||||||
ifaceobjcurr.priv_flags = ifaceobj.priv_flags
|
ifaceobjcurr.priv_flags = ifaceobj.priv_flags
|
||||||
ifaceobjcurr.auto = ifaceobj.auto
|
ifaceobjcurr.auto = ifaceobj.auto
|
||||||
self.ifaceobjcurrdict[ifaceobj.name] = ifaceobjcurr
|
self.ifaceobjcurrdict.setdefault(ifaceobj.name,
|
||||||
|
[]).append(ifaceobjcurr)
|
||||||
return ifaceobjcurr
|
return ifaceobjcurr
|
||||||
|
|
||||||
def get_ifaceobjcurr(self, ifacename):
|
def get_ifaceobjcurr(self, ifacename, idx=0):
|
||||||
return self.ifaceobjcurrdict.get(ifacename)
|
ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
|
||||||
|
if not ifaceobjlist:
|
||||||
|
return None
|
||||||
|
if not idx:
|
||||||
|
return ifaceobjlist
|
||||||
|
else:
|
||||||
|
return ifaceobjlist[idx]
|
||||||
|
|
||||||
def get_ifaceobjrunning(self, ifacename):
|
def get_ifaceobjrunning(self, ifacename):
|
||||||
return self.ifaceobjrunningdict.get(ifacename)
|
return self.ifaceobjrunningdict.get(ifacename)
|
||||||
@@ -349,6 +354,8 @@ class ifupdownMain(ifupdownBase):
|
|||||||
if ifaceobj.compare(currentifaceobjlist[0]):
|
if ifaceobj.compare(currentifaceobjlist[0]):
|
||||||
self.logger.warn('duplicate interface %s found' %ifaceobj.name)
|
self.logger.warn('duplicate interface %s found' %ifaceobj.name)
|
||||||
return
|
return
|
||||||
|
currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS
|
||||||
|
ifaceobj.flags |= iface.HAS_SIBLINGS
|
||||||
self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
|
self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
|
||||||
|
|
||||||
def _iface_configattr_syntax_checker(self, attrname, attrval):
|
def _iface_configattr_syntax_checker(self, attrname, attrval):
|
||||||
@@ -938,19 +945,20 @@ class ifupdownMain(ifupdownBase):
|
|||||||
def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
|
def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
|
||||||
ret = 0
|
ret = 0
|
||||||
for i in ifacenames:
|
for i in ifacenames:
|
||||||
ifaceobj = self.get_ifaceobjcurr(i)
|
ifaceobjscurr = self.get_ifaceobjcurr(i)
|
||||||
if not ifaceobj: continue
|
if not ifaceobjscurr: continue
|
||||||
if (ifaceobj.status == ifaceStatus.NOTFOUND or
|
for ifaceobj in ifaceobjscurr:
|
||||||
ifaceobj.status == ifaceStatus.ERROR):
|
if (ifaceobj.status == ifaceStatus.NOTFOUND or
|
||||||
ret = 1
|
ifaceobj.status == ifaceStatus.ERROR):
|
||||||
if self.is_ifaceobj_noconfig(ifaceobj):
|
ret = 1
|
||||||
continue
|
if self.is_ifaceobj_noconfig(ifaceobj):
|
||||||
ifaceobjs.append(ifaceobj)
|
continue
|
||||||
if self.WITH_DEPENDS and not self.ALL:
|
ifaceobjs.append(ifaceobj)
|
||||||
dlist = ifaceobj.lowerifaces
|
if self.WITH_DEPENDS and not self.ALL:
|
||||||
if not dlist: continue
|
dlist = ifaceobj.lowerifaces
|
||||||
dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
|
if not dlist: continue
|
||||||
if dret: ret = 1
|
dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
|
||||||
|
if dret: ret = 1
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
|
def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
|
||||||
|
@@ -49,7 +49,8 @@ class ifaceScheduler():
|
|||||||
_STATE_CHECK = True
|
_STATE_CHECK = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_iface_op(cls, ifupdownobj, ifaceobj, op, cenv):
|
def run_iface_op(cls, ifupdownobj, ifaceobj, op, query_ifaceobj=None,
|
||||||
|
cenv=None):
|
||||||
""" Runs sub operation on an interface """
|
""" Runs sub operation on an interface """
|
||||||
ifacename = ifaceobj.name
|
ifacename = ifaceobj.name
|
||||||
|
|
||||||
@@ -58,16 +59,7 @@ class ifaceScheduler():
|
|||||||
(ifaceobj.status == ifaceStatus.SUCCESS)):
|
(ifaceobj.status == ifaceStatus.SUCCESS)):
|
||||||
ifupdownobj.logger.debug('%s: already in state %s' %(ifacename, op))
|
ifupdownobj.logger.debug('%s: already in state %s' %(ifacename, op))
|
||||||
return
|
return
|
||||||
|
|
||||||
# first run ifupdownobj handlers
|
|
||||||
handler = ifupdownobj.ops_handlers.get(op)
|
|
||||||
if handler:
|
|
||||||
if not ifaceobj.addr_method or (ifaceobj.addr_method and
|
|
||||||
ifaceobj.addr_method != 'manual'):
|
|
||||||
handler(ifupdownobj, ifaceobj)
|
|
||||||
|
|
||||||
if not ifupdownobj.ADDONS_ENABLE: return
|
if not ifupdownobj.ADDONS_ENABLE: return
|
||||||
|
|
||||||
for mname in ifupdownobj.module_ops.get(op):
|
for mname in ifupdownobj.module_ops.get(op):
|
||||||
m = ifupdownobj.modules.get(mname)
|
m = ifupdownobj.modules.get(mname)
|
||||||
err = 0
|
err = 0
|
||||||
@@ -81,7 +73,7 @@ class ifaceScheduler():
|
|||||||
continue
|
continue
|
||||||
ifupdownobj.logger.debug(msg)
|
ifupdownobj.logger.debug(msg)
|
||||||
m.run(ifaceobj, op,
|
m.run(ifaceobj, op,
|
||||||
query_ifaceobj=ifupdownobj.create_n_save_ifaceobjcurr(ifaceobj))
|
query_ifaceobj)
|
||||||
else:
|
else:
|
||||||
ifupdownobj.logger.debug(msg)
|
ifupdownobj.logger.debug(msg)
|
||||||
m.run(ifaceobj, op)
|
m.run(ifaceobj, op)
|
||||||
@@ -107,23 +99,42 @@ class ifaceScheduler():
|
|||||||
ifupdownobj.log_error(str(e))
|
ifupdownobj.log_error(str(e))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_iface_ops(cls, ifupdownobj, ifaceobj, ops):
|
def run_iface_list_ops(cls, ifupdownobj, ifaceobjs, ops):
|
||||||
""" Runs all operations on an interface """
|
""" Runs all operations on a list of interface
|
||||||
ifacename = ifaceobj.name
|
configurations for the same interface
|
||||||
|
"""
|
||||||
# minor optimization. If operation is 'down', proceed only
|
# minor optimization. If operation is 'down', proceed only
|
||||||
# if interface exists in the system
|
# if interface exists in the system
|
||||||
if 'down' in ops[0] and not ifupdownobj.link_exists(ifacename):
|
ifacename = ifaceobjs[0].name
|
||||||
|
if ('down' in ops[0] and
|
||||||
|
not ifupdownobj.link_exists(ifacename)):
|
||||||
ifupdownobj.logger.debug('%s: does not exist' %ifacename)
|
ifupdownobj.logger.debug('%s: does not exist' %ifacename)
|
||||||
|
# run posthook before you get out of here, so that
|
||||||
|
# appropriate cleanup is done
|
||||||
|
posthookfunc = ifupdownobj.sched_hooks.get('posthook')
|
||||||
|
if posthookfunc:
|
||||||
|
for ifaceobj in ifaceobjs:
|
||||||
|
ifaceobj.status = ifaceStatus.SUCCESS
|
||||||
|
posthookfunc(ifupdownobj, ifaceobj, 'down')
|
||||||
return
|
return
|
||||||
cenv=None
|
for op in ops:
|
||||||
if ifupdownobj.COMPAT_EXEC_SCRIPTS:
|
# first run ifupdownobj handlers. This is good enough
|
||||||
# For backward compatibility generate env variables
|
# for the first object in the list
|
||||||
# for attributes
|
handler = ifupdownobj.ops_handlers.get(op)
|
||||||
cenv = ifupdownobj.generate_running_env(ifaceobj, ops[0])
|
if handler:
|
||||||
map(lambda op: cls.run_iface_op(ifupdownobj, ifaceobj, op, cenv), ops)
|
if (not ifaceobjs[0].addr_method or
|
||||||
posthookfunc = ifupdownobj.sched_hooks.get('posthook')
|
(ifaceobjs[0].addr_method and
|
||||||
if posthookfunc:
|
ifaceobjs[0].addr_method != 'manual')):
|
||||||
posthookfunc(ifupdownobj, ifaceobj, ops[0])
|
handler(ifupdownobj, ifaceobjs[0])
|
||||||
|
for ifaceobj in ifaceobjs:
|
||||||
|
cls.run_iface_op(ifupdownobj, ifaceobj, op,
|
||||||
|
query_ifaceobj=ifupdownobj.create_n_save_ifaceobjcurr(
|
||||||
|
ifaceobj) if op == 'query-checkcurr' else None,
|
||||||
|
cenv=ifupdownobj.generate_running_env(ifaceobj, op)
|
||||||
|
if ifupdownobj.COMPAT_EXEC_SCRIPTS else None)
|
||||||
|
posthookfunc = ifupdownobj.sched_hooks.get('posthook')
|
||||||
|
if posthookfunc:
|
||||||
|
posthookfunc(ifupdownobj, ifaceobj, op)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _check_upperifaces(cls, ifupdownobj, ifaceobj, ops, parent,
|
def _check_upperifaces(cls, ifupdownobj, ifaceobj, ops, parent,
|
||||||
@@ -182,10 +193,12 @@ class ifaceScheduler():
|
|||||||
if not cls._check_upperifaces(ifupdownobj, ifaceobj,
|
if not cls._check_upperifaces(ifupdownobj, ifaceobj,
|
||||||
ops, parent, followdependents):
|
ops, parent, followdependents):
|
||||||
return
|
return
|
||||||
if order == ifaceSchedulerFlags.INORDER:
|
|
||||||
# If inorder, run the iface first and then its dependents
|
|
||||||
cls.run_iface_ops(ifupdownobj, ifaceobj, ops)
|
|
||||||
|
|
||||||
|
# If inorder, run the iface first and then its dependents
|
||||||
|
if order == ifaceSchedulerFlags.INORDER:
|
||||||
|
cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops)
|
||||||
|
|
||||||
|
for ifaceobj in ifaceobjs:
|
||||||
# Run lowerifaces or dependents
|
# Run lowerifaces or dependents
|
||||||
dlist = ifaceobj.lowerifaces
|
dlist = ifaceobj.lowerifaces
|
||||||
if dlist:
|
if dlist:
|
||||||
@@ -199,12 +212,11 @@ class ifaceScheduler():
|
|||||||
# not follow dependents, we must follow the ones
|
# not follow dependents, we must follow the ones
|
||||||
# that dont have user given config. Because we own them
|
# that dont have user given config. Because we own them
|
||||||
new_dlist = [d for d in dlist
|
new_dlist = [d for d in dlist
|
||||||
if ifupdownobj.is_iface_noconfig(d)]
|
if ifupdownobj.is_iface_noconfig(d)]
|
||||||
if new_dlist:
|
if new_dlist:
|
||||||
cls.run_iface_list(ifupdownobj, new_dlist, ops,
|
cls.run_iface_list(ifupdownobj, new_dlist, ops,
|
||||||
ifacename, order,
|
ifacename, order, followdependents,
|
||||||
followdependents,
|
continueonfailure=False)
|
||||||
continueonfailure=False)
|
|
||||||
else:
|
else:
|
||||||
cls.run_iface_list(ifupdownobj, dlist, ops,
|
cls.run_iface_list(ifupdownobj, dlist, ops,
|
||||||
ifacename, order,
|
ifacename, order,
|
||||||
@@ -216,10 +228,10 @@ class ifaceScheduler():
|
|||||||
else:
|
else:
|
||||||
# Dont bring the iface up if children did not come up
|
# Dont bring the iface up if children did not come up
|
||||||
ifaceobj.set_state_n_status(ifaceState.NEW,
|
ifaceobj.set_state_n_status(ifaceState.NEW,
|
||||||
ifaceStatus.ERROR)
|
ifaceStatus.ERROR)
|
||||||
raise
|
raise
|
||||||
if order == ifaceSchedulerFlags.POSTORDER:
|
if order == ifaceSchedulerFlags.POSTORDER:
|
||||||
cls.run_iface_ops(ifupdownobj, ifaceobj, ops)
|
cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_iface_list(cls, ifupdownobj, ifacenames,
|
def run_iface_list(cls, ifupdownobj, ifacenames,
|
||||||
@@ -253,11 +265,10 @@ class ifaceScheduler():
|
|||||||
if not ifaceobjs:
|
if not ifaceobjs:
|
||||||
raise Exception('%s: not found' %ifacename)
|
raise Exception('%s: not found' %ifacename)
|
||||||
|
|
||||||
|
if not skip_root:
|
||||||
|
# run the iface first and then its upperifaces
|
||||||
|
cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops)
|
||||||
for ifaceobj in ifaceobjs:
|
for ifaceobj in ifaceobjs:
|
||||||
if not skip_root:
|
|
||||||
# run the iface first and then its upperifaces
|
|
||||||
cls.run_iface_ops(ifupdownobj, ifaceobj, ops)
|
|
||||||
|
|
||||||
# Run upperifaces
|
# Run upperifaces
|
||||||
ulist = ifaceobj.upperifaces
|
ulist = ifaceobj.upperifaces
|
||||||
if ulist:
|
if ulist:
|
||||||
@@ -320,13 +331,14 @@ class ifaceScheduler():
|
|||||||
# logical interface and we have to followupperifaces
|
# logical interface and we have to followupperifaces
|
||||||
followupperifaces = (True if
|
followupperifaces = (True if
|
||||||
[i for i in ifacenames
|
[i for i in ifacenames
|
||||||
if not ifupdownobj.link_exists(i)]
|
if not ifupdownobj.link_exists(i)]
|
||||||
else False)
|
else False)
|
||||||
cls.run_iface_list(ifupdownobj, ifacenames, ops,
|
cls.run_iface_list(ifupdownobj, ifacenames, ops,
|
||||||
parent=None,order=order,
|
parent=None,order=order,
|
||||||
followdependents=followdependents)
|
followdependents=followdependents)
|
||||||
if (not ifupdownobj.ALL and
|
if (not ifupdownobj.ALL and
|
||||||
(followdependents or followupperifaces) and 'up' in ops[0]):
|
(followdependents or followupperifaces) and
|
||||||
|
'up' in ops[0]):
|
||||||
# If user had given a set of interfaces to bring up
|
# If user had given a set of interfaces to bring up
|
||||||
# try and execute 'up' on the upperifaces
|
# try and execute 'up' on the upperifaces
|
||||||
ifupdownobj.logger.info('running upperifaces if available')
|
ifupdownobj.logger.info('running upperifaces if available')
|
||||||
|
Reference in New Issue
Block a user