diff --git a/ifupdown/iface.py b/ifupdown/iface.py index cfdfe66..b0efbd3 100644 --- a/ifupdown/iface.py +++ b/ifupdown/iface.py @@ -19,7 +19,7 @@ import json class ifaceType(): UNKNOWN = 0x1 - BRIDGE = 0x2 + GENERIC = 0x2 BRIDGE_VLAN = 0x3 class ifaceStatus(): @@ -275,6 +275,17 @@ class iface(): return attr_value_list[0] return None + def get_attrs_value_first(self, attrs): + """ get first value of the first attr in the list. + Useful when you have multiple attrs representing the + same thing. + """ + for attr in attrs: + attr_value_list = self.config.get(attr) + if attr_value_list: + return attr_value_list[0] + return None + def get_attr_value_n(self, attr_name, attr_index): """ get n'th value of the specified attr name """ attr_value_list = self.config.get(attr_name) diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index 5125352..28b9eeb 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -376,29 +376,16 @@ class ifupdownMain(ifupdownBase): self.ifaceobjdict[ifaceobj.name].append(ifaceobj) def _save_iface(self, ifaceobj): - # - # Special 'iface vlan-' interface handling. - # If `iface vlan-` and belongs to a bridge - # mark interface type. - # - if ifaceobj.get_attr_value_first('bridge'): - vlan_match = re.match("^vlan-([\d]+)-([\d]+)|^vlan-([\d]+)", - ifaceobj.name) - if vlan_match: - vlan_groups = vlan_match.groups() - if vlan_groups[0] and vlan_groups[1]: - for v in range(int(vlan_groups[0]), int(vlan_groups[1])+1): - ifaceobj_vlan = copy.deepcopy(ifaceobj) - ifaceobj_vlan.real_name = ifaceobj.name - ifaceobj_vlan.name = "vlan-%d" %v - ifaceobj_vlan.priv_data = v - ifaceobj_vlan.type = ifaceType.BRIDGE_VLAN - self._add_ifaceobj(ifaceobj_vlan) - return - elif vlan_groups[2]: - ifaceobj.priv_data = int(vlan_groups[2]) - ifaceobj.type = ifaceType.BRIDGE_VLAN - self._add_ifaceobj(ifaceobj) + currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name) + if not currentifaceobjlist: + self.ifaceobjdict[ifaceobj.name]= [ifaceobj] + return + if ifaceobj.compare(currentifaceobjlist[0]): + self.logger.warn('duplicate interface %s found' %ifaceobj.name) + return + currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS + ifaceobj.flags |= iface.HAS_SIBLINGS + self.ifaceobjdict[ifaceobj.name].append(ifaceobj) def _iface_configattr_syntax_checker(self, attrname, attrval): for m, mdict in self.module_attrs.items(): @@ -582,11 +569,11 @@ class ifupdownMain(ifupdownBase): def _render_ifacename(self, ifacename): new_ifacenames = [] - vlan_match = re.match("^vlan-([\d]+)-([\d]+)", ifacename) + vlan_match = re.match("^([\d]+)-([\d]+)", ifacename) if vlan_match: vlan_groups = vlan_match.groups() if vlan_groups[0] and vlan_groups[1]: - [new_ifacenames.append('vlan-%d' %v) + [new_ifacenames.append('%d' %v) for v in range(int(vlan_groups[0]), int(vlan_groups[1])+1)] return new_ifacenames @@ -603,7 +590,7 @@ class ifupdownMain(ifupdownBase): ifaceobjs = self.get_ifaceobjs(i) if not ifaceobjs: # if name not available, render interface name and check again - rendered_ifacenames = self._render_ifacename(i) + rendered_ifacenames = utils.expand_iface_range(i) if rendered_ifacenames: for ri in rendered_ifacenames: ifaceobjs = self.get_ifaceobjs(ri) @@ -625,7 +612,6 @@ class ifupdownMain(ifupdownBase): interfaces are checked against the allow_classes and auto lists. """ - if excludepats: for e in excludepats: if re.search(e, ifacename): diff --git a/ifupdown/networkinterfaces.py b/ifupdown/networkinterfaces.py index 46f9053..d59b56b 100644 --- a/ifupdown/networkinterfaces.py +++ b/ifupdown/networkinterfaces.py @@ -12,6 +12,8 @@ import logging import glob import re import os +import copy +from utils import utils from iface import * from template import templateEngine @@ -23,6 +25,7 @@ class networkInterfaces(): hotplugs = {} auto_ifaces = [] callbacks = {} + auto_all = False _addrfams = {'inet' : ['static', 'manual', 'loopback', 'dhcp', 'dhcp6'], 'inet6' : ['static', 'manual', 'loopback', 'dhcp', 'dhcp6']} @@ -151,7 +154,15 @@ class networkInterfaces(): self._parse_error(self._currentfile, lineno, 'invalid auto line \'%s\''%lines[cur_idx]) return 0 - [self.auto_ifaces.append(a) for a in auto_ifaces] + for a in auto_ifaces: + if a == 'all': + self.auto_all = True + break + r = utils.parse_iface_range(a) + if r: + for i in range(r[1], r[2]): + self.auto_ifaces.append('%s-%d' %(r[0], i)) + self.auto_ifaces.append(a) return 0 def _add_to_iface_config(self, ifacename, iface_config, attrname, @@ -188,11 +199,10 @@ class networkInterfaces(): else: iface_config[newattrname].append(attrval) - def process_iface(self, lines, cur_idx, lineno): + def parse_iface(self, lines, cur_idx, lineno, ifaceobj): lines_consumed = 0 line_idx = cur_idx - ifaceobj = iface() iface_line = lines[cur_idx].strip(whitespaces) iface_attrs = re.split(self._ws_split_regex, iface_line) ifacename = iface_attrs[1] @@ -238,17 +248,30 @@ class networkInterfaces(): pass self._validate_addr_family(ifaceobj, lineno) - if ifaceobj.name in self.auto_ifaces: + if self.auto_all or (ifaceobj.name in self.auto_ifaces): ifaceobj.auto = True classes = self.get_allow_classes_for_iface(ifaceobj.name) if classes: [ifaceobj.set_class(c) for c in classes] - - # Call iface found callback - self.callbacks.get('iface_found')(ifaceobj) + return lines_consumed # Return next index + def process_iface(self, lines, cur_idx, lineno): + ifaceobj = iface() + lines_consumed = self.parse_iface(lines, cur_idx, lineno, ifaceobj) + + range_val = utils.parse_iface_range(ifaceobj.name) + if range_val: + for v in range(range_val[1], range_val[2]): + ifaceobj_new = copy.deepcopy(ifaceobj) + ifaceobj_new.real_name = ifaceobj.name + ifaceobj_new.name = "%s-%d" %(range_val[0], v) + self.callbacks.get('iface_found')(ifaceobj_new) + else: + self.callbacks.get('iface_found')(ifaceobj) + + return lines_consumed # Return next index network_elems = { 'source' : process_source, 'allow' : process_allow, diff --git a/ifupdown/utils.py b/ifupdown/utils.py index 9dd6910..409c690 100644 --- a/ifupdown/utils.py +++ b/ifupdown/utils.py @@ -8,6 +8,7 @@ # import os import fcntl +import re class utils(): @@ -29,4 +30,23 @@ class utils(): return False return True + @classmethod + def parse_iface_range(cls, name): + range_match = re.match("^([\w]+)-\[([\d]+)-([\d]+)\]", name) + if range_match: + range_groups = range_match.groups() + if range_groups[1] and range_groups[2]: + return (range_groups[0], int(range_groups[1], 10), + int(range_groups[2], 10)) + return None + + @classmethod + def expand_iface_range(cls, name): + ifacenames = [] + iface_range = cls.parse_iface_range(name) + if iface_range: + for i in range(iface_range[1], iface_range[2]): + ifacenames.append('%s-%d' %(iface_range[0], i)) + return ifacenames +