From 6e16e5ae90f2fac021db3985415938aefd61d4bf Mon Sep 17 00:00:00 2001 From: Nikhil Date: Wed, 20 Apr 2016 03:02:26 -0700 Subject: [PATCH] addons,ifupdown,sbin: adding ifquery --with-defaults option Ticket: CM-7840 Reviewed By: Roopa Prabhu Testing Done: yes, by installing ifupdown .deb file onto dell-s3000-02 This patch adds a new argument '--with-defaults' to 'ifquery' when 'ifquery --with-defaults' is executed, running states of all interface attributes are compared against respective configured attributes from /etc/network/interfaces file, if configured. Otherwise, compared against default attributes from policy file This patch also: (1) fixes ifquery check failure for bridge-* stp attributes. (2) removes vrf-default-route and vrf-cgroup attributes from ifupdown2 policy and just have the vrf-helper attribute Signed-off-by: Nikhil --- addons/address.py | 3 +-- addons/bridge.py | 30 +++++++++++---------- addons/ethtool.py | 9 +++---- addons/vrf.py | 50 +++++++++++++++-------------------- ifupdown/ifupdownflags.py | 1 + ifupdown/ifupdownmain.py | 14 +++++----- ifupdown/scheduler.py | 40 ++++++++++++++-------------- ifupdownaddons/bridgeutils.py | 14 +++++++--- sbin/ifupdown2 | 8 +++--- 9 files changed, 84 insertions(+), 85 deletions(-) diff --git a/addons/address.py b/addons/address.py index 812aefe..b35206e 100644 --- a/addons/address.py +++ b/addons/address.py @@ -500,8 +500,7 @@ class address(moduleBase): if not self.ipcmd: self.ipcmd = iproute2() - def run(self, ifaceobj, operation, query_ifaceobj=None, - ifaceobj_getfunc=None, **extra_args): + def run(self, ifaceobj, operation, query_ifaceobj=None, ifaceobj_getfunc=None): """ run address configuration on the interface object passed as argument Args: diff --git a/addons/bridge.py b/addons/bridge.py index 9c184d6..646d3c2 100644 --- a/addons/bridge.py +++ b/addons/bridge.py @@ -1369,7 +1369,8 @@ class bridge(moduleBase): if attrval: ifaceobjcurr.update_config_with_status('bridge-vids', attrval, -1) - def _query_check_bridge(self, ifaceobj, ifaceobjcurr, withdefaults): + def _query_check_bridge(self, ifaceobj, ifaceobjcurr, + ifaceobj_getfunc=None): if not self._is_bridge(ifaceobj): return if not self.brctlcmd.bridge_exists(ifaceobj.name): @@ -1379,7 +1380,7 @@ class bridge(moduleBase): ifaceattrs = self.dict_key_subset(ifaceobj.config, self.get_mod_attrs()) #Add default attributes if --with-defaults is set - if withdefaults and 'bridge-stp' not in ifaceattrs: + if ifupdownflags.flags.WITHDEFAULTS and 'bridge-stp' not in ifaceattrs: ifaceattrs.append('bridge-stp') if not ifaceattrs: return @@ -1398,13 +1399,16 @@ class bridge(moduleBase): # get the corresponding ifaceobj attr v = ifaceobj.get_attr_value_first(k) if not v: - if withdefaults and k == 'bridge-stp': - v = 'on' if self.default_stp_on else 'off' - else: - continue + if ifupdownflags.flags.WITHDEFAULTS and k == 'bridge-stp': + v = 'on' if self.default_stp_on else 'off' + else: + continue rv = runningattrs.get(k[7:]) if k == 'bridge-mcqv4src': continue + if k == 'bridge-maxwait' or k == 'bridge-waitport': + ifaceobjcurr.update_config_with_status(k, v, 0) + continue if k == 'bridge-vlan-aware': rv = self.ipcmd.bridge_is_vlan_aware(ifaceobj.name) if (rv and v == 'yes') or (not rv and v == 'no'): @@ -1424,7 +1428,7 @@ class bridge(moduleBase): rv, 0) else: ifaceobjcurr.update_config_with_status('bridge-stp', - rv, 1) + rv, 1) elif k == 'bridge-ports': # special case ports because it can contain regex or glob running_port_list = rv.keys() if rv else [] @@ -1443,7 +1447,7 @@ class bridge(moduleBase): elif (k == 'bridge-pathcosts' or k == 'bridge-portprios' or k == 'bridge-portmcrouter' or k == 'bridge-portmcfl'): - brctlcmdattrname = k[11:].rstrip('s') + brctlcmdattrname = k[7:].rstrip('s') # for port attributes, the attributes are in a list # = status = 0 @@ -1468,7 +1472,7 @@ class bridge(moduleBase): pass ifaceobjcurr.update_config_with_status(k, currstr, status) elif not rv: - if k == 'bridge-pvid' or k == 'bridge-vids': + if k == 'bridge-pvid' or k == 'bridge-vids' or k == 'bridge-allow-untagged': # bridge-pvid and bridge-vids on a bridge does # not correspond directly to a running config # on the bridge. They correspond to default @@ -1606,10 +1610,9 @@ class bridge(moduleBase): except Exception, e: self.log_warn('%s: %s' %(ifaceobj.name, str(e))) - def _query_check(self, ifaceobj, ifaceobjcurr, withdefaults, - ifaceobj_getfunc=None): + def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None): if self._is_bridge(ifaceobj): - self._query_check_bridge(ifaceobj, ifaceobjcurr, withdefaults) + self._query_check_bridge(ifaceobj, ifaceobjcurr) else: self._query_check_bridge_port(ifaceobj, ifaceobjcurr, ifaceobj_getfunc) @@ -1699,7 +1702,7 @@ class bridge(moduleBase): self.brctlcmd = brctl() def run(self, ifaceobj, operation, query_ifaceobj=None, - ifaceobj_getfunc=None, **extra_args): + ifaceobj_getfunc=None): """ run bridge configuration on the interface object passed as argument. Can create bridge interfaces if they dont exist already @@ -1724,7 +1727,6 @@ class bridge(moduleBase): self._flush_running_vidinfo() if operation == 'query-checkcurr': op_handler(self, ifaceobj, query_ifaceobj, - extra_args['withdefaults'] if 'withdefaults' in extra_args else False, ifaceobj_getfunc=ifaceobj_getfunc) else: op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc) diff --git a/addons/ethtool.py b/addons/ethtool.py index 32939e4..c7a4850 100644 --- a/addons/ethtool.py +++ b/addons/ethtool.py @@ -13,6 +13,7 @@ try: from ifupdownaddons.utilsbase import * from ifupdownaddons.modulebase import moduleBase from ifupdownaddons.iproute2 import iproute2 + import ifupdown.ifupdownflags as ifupdownflags except ImportError, e: raise ImportError (str(e) + "- required module not found") @@ -123,7 +124,7 @@ class ethtool(moduleBase,utilsBase): def _pre_down(self, ifaceobj): pass #self._post_up(ifaceobj,operation="_pre_down") - def _query_check(self, ifaceobj, ifaceobjcurr, withdefaults): + def _query_check(self, ifaceobj, ifaceobjcurr): """ _query_check() needs to compare the configured (or running) attribute with the running attribute. @@ -133,12 +134,11 @@ class ethtool(moduleBase,utilsBase): This is because a reboot will lose their running attribute (the default will get set). """ - # Add default attributes if --with-defaults is set for attr in ['speed', 'duplex', 'autoneg']: configured = ifaceobj.get_attr_value_first('link-%s'%attr) # if there is nothing configured, do not check if not configured: - if not withdefaults: + if not ifupdownflags.flags.WITHDEFAULTS: continue default = policymanager.policymanager_api.get_iface_default( module_name='ethtool', @@ -268,7 +268,6 @@ class ethtool(moduleBase,utilsBase): self._init_command_handlers() if operation == 'query-checkcurr': - op_handler(self, ifaceobj, query_ifaceobj, - extra_args['withdefaults'] if 'withdefaults' in extra_args else False) + op_handler(self, ifaceobj, query_ifaceobj) else: op_handler(self, ifaceobj) diff --git a/addons/vrf.py b/addons/vrf.py index bb2b212..1ff21f3 100644 --- a/addons/vrf.py +++ b/addons/vrf.py @@ -30,10 +30,6 @@ class vrf(moduleBase): {'help' : 'vrf device table id. key to ' + 'creating a vrf device', 'example': ['vrf-table-id 1']}, - 'vrf-default-route': - {'help' : 'vrf device default route ' + - 'to avoid communication outside the vrf device', - 'example': ['vrf-default-route yes/no']}, 'vrf': {'help' : 'vrf the interface is part of.', 'example': ['vrf blue']}}} @@ -97,14 +93,6 @@ class vrf(moduleBase): self.vrf_fix_local_table = True self.vrf_count = 0 - self.vrf_cgroup_create = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-cgroup-create') - - if not self.vrf_cgroup_create: - self.vrf_cgroup_create = False - elif self.vrf_cgroup_create == 'yes': - self.vrf_cgroup_create = True - else: - self.vrf_cgroup_create = False self.vrf_mgmt_devname = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-mgmt-devname') self.vrf_helper = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-helper') @@ -744,8 +732,7 @@ class vrf(moduleBase): except Exception, e: self.log_warn(str(e)) - def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table, - withdefaults): + def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table): try: if not self.ipcmd.link_exists(ifaceobj.name): self.logger.info('%s: vrf: does not exist' %(ifaceobj.name)) @@ -768,28 +755,34 @@ class vrf(moduleBase): else: ifaceobjcurr.update_config_with_status('vrf-table', running_table, 0) - if not withdefaults: + if not ifupdownflags.flags.WITHDEFAULTS: return if self.vrf_helper: - ret_vrfhelper = self.exec_command('%s verify %s %s' - %(self.vrf_helper, - ifaceobj.name, vrf_table)) - if 'default routes are installed' not in ret_vrfhelper: - ifaceobjcurr.update_config_with_status('vrf-default-route', - 'no', 1) - else: - ifaceobjcurr.update_config_with_status('vrf-default-route', - 'yes',0) + try: + self.exec_command('%s verify %s %s' + %(self.vrf_helper, + ifaceobj.name, config_table)) + ifaceobjcurr.update_config_with_status('vrf-helper', + '%s create %s %s' + %(self.vrf_helper, + ifaceobj.name, + config_table), 0) + except Exception, e: + ifaceobjcurr.update_config_with_status('vrf-helper', + '%s create %s %s' + %(self.vrf_helper, + ifaceobj.name, + config_table), 1) + pass except Exception, e: self.log_warn(str(e)) - def _query_check(self, ifaceobj, ifaceobjcurr, withdefaults): + def _query_check(self, ifaceobj, ifaceobjcurr): try: vrf_table = ifaceobj.get_attr_value_first('vrf-table') if vrf_table: self._iproute2_vrf_map_initialize() - self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table, - withdefaults) + self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table) else: vrf = ifaceobj.get_attr_value_first('vrf') if vrf: @@ -855,7 +848,6 @@ class vrf(moduleBase): return self._init_command_handlers() if operation == 'query-checkcurr': - op_handler(self, ifaceobj, query_ifaceobj, - extra_args['withdefaults'] if 'withdefaults' in extra_args else False) + op_handler(self, ifaceobj, query_ifaceobj) else: op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc) diff --git a/ifupdown/ifupdownflags.py b/ifupdown/ifupdownflags.py index 5b7c386..08ad3ec 100644 --- a/ifupdown/ifupdownflags.py +++ b/ifupdown/ifupdownflags.py @@ -14,6 +14,7 @@ class ifupdownFlags(): self.NOWAIT = False self.PERFMODE = False self.CACHE = False + self.WITHDEFAULTS = False # Flags self.CACHE_FLAGS = 0x0 diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index b4c3440..de6b28c 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -171,7 +171,8 @@ class ifupdownMain(ifupdownBase): cache=False, addons_enable=True, statemanager_enable=True, interfacesfile='/etc/network/interfaces', interfacesfileiobuf=None, - interfacesfileformat='native'): + interfacesfileformat='native', + withdefaults=False): """This member function initializes the ifupdownmain object. Kwargs: @@ -188,6 +189,7 @@ class ifupdownMain(ifupdownBase): self.logger = logging.getLogger('ifupdown') ifupdownflags.flags.FORCE = force ifupdownflags.flags.DRYRUN = dryrun + ifupdownflags.flags.WITHDEFAULTS = withdefaults ifupdownflags.flags.NOWAIT = nowait ifupdownflags.flags.PERFMODE = perfmode ifupdownflags.flags.CACHE = cache @@ -895,13 +897,13 @@ class ifupdownMain(ifupdownBase): # continue reading pass - def _sched_ifaces(self, ifacenames, ops, withdefaults=False, - skipupperifaces=False, followdependents=True, sort=False): + def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False, + followdependents=True, sort=False): self.logger.debug('scheduling \'%s\' for %s' %(str(ops), str(ifacenames))) self._pretty_print_ordered_dict('dependency graph', self.dependency_graph) - ifaceScheduler.sched_ifaces(self, ifacenames, ops, withdefaults, + ifaceScheduler.sched_ifaces(self, ifacenames, ops, dependency_graph=self.dependency_graph, order=ifaceSchedulerFlags.INORDER if 'down' in ops[0] @@ -1209,7 +1211,7 @@ class ifupdownMain(ifupdownBase): def query(self, ops, auto=False, format_list=False, allow_classes=None, ifacenames=None, excludepats=None, printdependency=None, - format='native', type=None, withdefaults=False): + format='native', type=None): """ query an interface """ self.set_type(type) @@ -1273,7 +1275,7 @@ class ifupdownMain(ifupdownBase): elif ops[0] == 'query-raw': return self.print_ifaceobjs_raw(filtered_ifacenames) - ret = self._sched_ifaces(filtered_ifacenames, ops, withdefaults, + ret = self._sched_ifaces(filtered_ifacenames, ops, followdependents=True if self.flags.WITH_DEPENDS else False) diff --git a/ifupdown/scheduler.py b/ifupdown/scheduler.py index cbcfeb8..3202f9b 100644 --- a/ifupdown/scheduler.py +++ b/ifupdown/scheduler.py @@ -49,7 +49,7 @@ class ifaceScheduler(): cls._SCHED_STATUS = state @classmethod - def run_iface_op(cls, ifupdownobj, ifaceobj, op, withdefaults=False, cenv=None): + def run_iface_op(cls, ifupdownobj, ifaceobj, op, cenv=None): """ Runs sub operation on an interface """ ifacename = ifaceobj.name @@ -80,11 +80,11 @@ class ifaceScheduler(): continue ifupdownobj.logger.debug(msg) m.run(ifaceobj, op, query_ifaceobj, - ifaceobj_getfunc=ifupdownobj.get_ifaceobjs, withdefaults=withdefaults) + ifaceobj_getfunc=ifupdownobj.get_ifaceobjs) else: ifupdownobj.logger.debug(msg) m.run(ifaceobj, op, - ifaceobj_getfunc=ifupdownobj.get_ifaceobjs, withdefaults=withdefaults) + ifaceobj_getfunc=ifupdownobj.get_ifaceobjs) except Exception, e: if not ifupdownobj.ignore_error(str(e)): err = 1 @@ -117,7 +117,7 @@ class ifaceScheduler(): ifupdownobj.log_error(str(e)) @classmethod - def run_iface_list_ops(cls, ifupdownobj, ifaceobjs, ops, withdefaults=False): + def run_iface_list_ops(cls, ifupdownobj, ifaceobjs, ops): """ Runs all operations on a list of interface configurations for the same interface """ @@ -151,7 +151,7 @@ class ifaceScheduler(): %(ifaceobjs[0].name, str(e))) pass for ifaceobj in ifaceobjs: - cls.run_iface_op(ifupdownobj, ifaceobj, op, withdefaults, + cls.run_iface_op(ifupdownobj, ifaceobj, op, cenv=ifupdownobj.generate_running_env(ifaceobj, op) if ifupdownobj.config.get('addon_scripts_support', '0') == '1' else None) @@ -212,8 +212,8 @@ class ifaceScheduler(): return True @classmethod - def run_iface_graph(cls, ifupdownobj, ifacename, ops, withdefaults=False, - parent=None, order=ifaceSchedulerFlags.POSTORDER, + def run_iface_graph(cls, ifupdownobj, ifacename, ops, parent=None, + order=ifaceSchedulerFlags.POSTORDER, followdependents=True): """ runs interface by traversing all nodes rooted at itself """ @@ -235,7 +235,7 @@ class ifaceScheduler(): # If inorder, run the iface first and then its dependents if order == ifaceSchedulerFlags.INORDER: - cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, False) + cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops) for ifaceobj in ifaceobjs: # Run lowerifaces or dependents @@ -254,12 +254,11 @@ class ifaceScheduler(): if ifupdownobj.is_iface_noconfig(d)] if new_dlist: cls.run_iface_list(ifupdownobj, new_dlist, ops, - withdefaults, ifacename, order, - followdependents, + ifacename, order, followdependents, continueonfailure=False) else: cls.run_iface_list(ifupdownobj, dlist, ops, - withdefaults, ifacename, order, + ifacename, order, followdependents, continueonfailure=False) except Exception, e: @@ -271,17 +270,18 @@ class ifaceScheduler(): ifaceStatus.ERROR) raise if order == ifaceSchedulerFlags.POSTORDER: - cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, withdefaults) + cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops) @classmethod - def run_iface_list(cls, ifupdownobj, ifacenames, ops, withdefaults=False, - parent=None, order=ifaceSchedulerFlags.POSTORDER, + def run_iface_list(cls, ifupdownobj, ifacenames, + ops, parent=None, order=ifaceSchedulerFlags.POSTORDER, followdependents=True, continueonfailure=True): """ Runs interface list """ + for ifacename in ifacenames: try: - cls.run_iface_graph(ifupdownobj, ifacename, ops, withdefaults, - parent, order, followdependents) + cls.run_iface_graph(ifupdownobj, ifacename, ops, parent, + order, followdependents) except Exception, e: if continueonfailure: if ifupdownobj.logger.isEnabledFor(logging.DEBUG): @@ -311,7 +311,7 @@ class ifaceScheduler(): if not skip_root: # run the iface first and then its upperifaces - cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, False) + cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops) for ifaceobj in ifaceobjs: # Run upperifaces ulist = ifaceobj.upperifaces @@ -405,7 +405,7 @@ class ifaceScheduler(): ifaceobjs = ifupdownobj.get_ifaceobjs(u) if not ifaceobjs: continue - cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, False) + cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops) except Exception, e: if continueonfailure: self.logger.warn('%s' %str(e)) @@ -434,7 +434,7 @@ class ifaceScheduler(): return ifacenames_sorted @classmethod - def sched_ifaces(cls, ifupdownobj, ifacenames, ops, withdefaults=False, + def sched_ifaces(cls, ifupdownobj, ifacenames, ops, dependency_graph=None, indegrees=None, order=ifaceSchedulerFlags.POSTORDER, followdependents=True, skipupperifaces=False, sort=False): @@ -529,7 +529,7 @@ class ifaceScheduler(): run_queue.reverse() # run interface list - cls.run_iface_list(ifupdownobj, run_queue, ops, withdefaults, + cls.run_iface_list(ifupdownobj, run_queue, ops, parent=None, order=order, followdependents=followdependents) if not cls.get_sched_status(): diff --git a/ifupdownaddons/bridgeutils.py b/ifupdownaddons/bridgeutils.py index 962f98d..39640df 100644 --- a/ifupdownaddons/bridgeutils.py +++ b/ifupdownaddons/bridgeutils.py @@ -78,6 +78,12 @@ class brctl(utilsBase): battrs['fd'] = broutlines[6].split( 'bridge forward delay')[1].strip( ).replace('.00', '') + battrs['ageing'] = broutlines[7].split( + 'ageing time')[1].strip().replace('.00', '') + battrs['mcrouter'] = broutlines[12].split( + 'mc router')[1].strip().split('\t\t\t')[0] + battrs['bridgeprio'] = self.read_file_oneline( + '/sys/class/net/%s/bridge/priority' %bridgename) battrs.update(self._bridge_get_mcattrs_from_sysfs(bridgename)) # XXX: comment this out until mc attributes become available @@ -94,7 +100,6 @@ class brctl(utilsBase): pass linkCache.update_attrdict([bridgename, 'linkinfo'], battrs) - for cidx in range(1, len(chunks)): bpout = chunks[cidx].lstrip('\n') if not bpout or bpout[0] == ' ': @@ -107,11 +112,12 @@ class brctl(utilsBase): 'path cost')[1].strip() bportattrs['fdelay'] = bplines[4].split( 'forward delay timer')[1].strip() - bportattrs['mcrouter'] = self.read_file_oneline( + bportattrs['portmcrouter'] = self.read_file_oneline( '/sys/class/net/%s/brport/multicast_router' %pname) - bportattrs['mcfl'] = self.read_file_oneline( + bportattrs['portmcfl'] = self.read_file_oneline( '/sys/class/net/%s/brport/multicast_fast_leave' %pname) - + bportattrs['portprio'] = self.read_file_oneline( + '/sys/class/net/%s/brport/priority' %pname) #bportattrs['mcrouters'] = bplines[6].split('mc router')[1].split()[0].strip() #bportattrs['mc fast leave'] = bplines[6].split('mc fast leave')[1].strip() except Exception, e: diff --git a/sbin/ifupdown2 b/sbin/ifupdown2 index 289080e..140202d 100755 --- a/sbin/ifupdown2 +++ b/sbin/ifupdown2 @@ -107,8 +107,6 @@ def run_query(args): qop = 'query-dependency' elif args.printsavedstate: qop = 'query-savedstate' - elif args.withdefaults: - qop = 'query-withdefaults' else: qop='query' cachearg=(False if (iflist or args.nocache or @@ -125,15 +123,15 @@ def run_query(args): cache=cachearg, interfacesfile=interfacesfilename, interfacesfileiobuf=interfacesfileiobuf, - interfacesfileformat=args.interfacesfileformat) + interfacesfileformat=args.interfacesfileformat, + withdefaults=args.withdefaults) # list implies all auto interfaces (this is how ifupdown behaves) if args.list: args.all = True ifupdown_handle.query([qop], args.all, args.list, args.CLASS, iflist, excludepats=args.excludepats, printdependency=args.printdependency, - format=args.format, type=args.type, - withdefaults=args.withdefaults) + format=args.format, type=args.type) except: raise