1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00

Add bridge-ports-condone-regex option (closes #117)

The bridge-ports-condone-regex option can be used to tell ifupdown2 to let
  some bridge member ports alone and do not remove them on ifreload runs.
  This might come in handy when running a KVM (or any other virtualization
  system) host with a bridged network setup.

  Before this option, ifupdown2 would either complain about not existing
  member ports when setting up the bridge (if all VM interfaces were to
  be specified in /etc/network/interfaces) or remove any VM interface
  from a bridge if it was not specified in /e/n/i.

Signed-off-by: Maximilian Wilhelm <max@rfc2324.org>
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
Co-authored-by: Julien Fortin <julien@cumulusnetworks.com>
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
This commit is contained in:
Maximilian Wilhelm
2016-09-27 11:26:52 +02:00
committed by Julien Fortin
parent c9091d7108
commit f5c97c0d6b

View File

@@ -76,6 +76,10 @@ class bridge(moduleBase):
'example' : ['bridge-ports swp1.100 swp2.100 swp3.100',
'bridge-ports glob swp1-3.100',
'bridge-ports regex (swp[1|2|3].100)']},
'bridge-ports-condone-regex' :
{'help' : 'bridge ports to ignore/condone when reloading config / removing interfaces',
'required' : False,
'example' : [ 'bridge-ports-condone-regex ^[a-zA-Z0-9]+_v[0-9]{1,4}$']},
'bridge-stp' :
{'help': 'bridge-stp yes/no',
'example' : ['bridge-stp no'],
@@ -901,6 +905,19 @@ class bridge(moduleBase):
ports = self._get_ifaceobj_bridge_ports(ifaceobj)
return self.parse_port_list(ifaceobj.name, ports) if ports else None
def _get_bridge_port_condone_regex(self, ifaceobj, get_string = False):
bridge_port_condone_regex = ifaceobj.get_attr_value_first('bridge-ports-condone-regex')
# If bridge-ports-ignore-regex is configured, do NOT use the parse_port_list()
# function to gather a list of ports matching the regex here and now but set
# up a compiled regex to be used in a match later. This way we try to avoid
# a race condition where an (possibly VM) interface is created after this
# function has been called but before the bridgeports are validated.
if bridge_port_condone_regex:
if get_string:
return bridge_port_condone_regex
return re.compile (r"%s" % bridge_port_condone_regex)
return None
def _process_bridge_waitport(self, ifaceobj, portlist):
waitport_value = ifaceobj.get_attr_value_first('bridge-waitport')
if not waitport_value: return
@@ -974,6 +991,7 @@ class bridge(moduleBase):
def _add_ports(self, ifaceobj, ifaceobj_getfunc):
bridgeports = self._get_bridge_port_list(ifaceobj)
bridgeportscondoneregex = self._get_bridge_port_condone_regex(ifaceobj)
runningbridgeports = []
self.ipcmd.batch_start()
@@ -985,6 +1003,9 @@ class bridge(moduleBase):
if runningbridgeports:
for bport in runningbridgeports:
if not bridgeports or bport not in bridgeports:
if bridgeportscondoneregex and bridgeportscondoneregex.match(bport):
self.logger.info("%s: port %s will stay enslaved as it matches with bridge-ports-condone-regex" % (ifaceobj.name, bport))
continue
self.ipcmd.link_set(bport, 'nomaster')
# set admin DOWN on all removed ports
# that don't have config outside bridge
@@ -2617,6 +2638,14 @@ class bridge(moduleBase):
self.query_check_bridge_ports(ifaceobj, ifaceobjcurr, runningattrs.get('ports', {}).keys(), ifaceobj_getfunc)
diff.remove('bridge-ports')
if "bridge-ports-condone-regex" in diff:
ifaceobjcurr.update_config_with_status(
"bridge-ports-condone-regex",
self._get_bridge_port_condone_regex(ifaceobj, True),
0
)
diff.remove("bridge-ports-condone-regex")
for k in diff:
# get the corresponding ifaceobj attr
v = ifaceobj.get_attr_value_first(k)
@@ -2740,8 +2769,6 @@ class bridge(moduleBase):
if not running_port_list and not bridge_all_ports:
return
ports_list_status = 0 if not set(running_port_list).symmetric_difference(bridge_all_ports) else 1
try:
port_list = self._get_ifaceobj_bridge_ports(ifaceobj).split()
# we want to display the same bridge-ports list as provided
@@ -2757,7 +2784,29 @@ class bridge(moduleBase):
port_list = ordered
except:
port_list = running_port_list
ifaceobjcurr.update_config_with_status('bridge-ports', (' '.join(port_list) if port_list else ''), ports_list_status)
difference = set(running_port_list).symmetric_difference(bridge_all_ports)
bridge_port_condone_regex = self._get_bridge_port_condone_regex(ifaceobj)
if bridge_port_condone_regex:
# Drop any condoned port from the difference set
condone_ports = [port for port in difference if bridge_port_condone_regex.match(port)]
for port in condone_ports:
try:
difference.remove(port)
except ValueError:
pass
# Tag all condoned ports in brackets in output
if port not in bridge_all_ports:
port_list.append("(%s)" % port)
ifaceobjcurr.update_config_with_status(
"bridge-ports",
" ".join(port_list) if port_list else "",
0 if not difference else 1
)
def get_ifaceobj_bridge_vids(self, ifaceobj):
vids = ('bridge-vids', ifaceobj.get_attr_value_first('bridge-vids'))