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

Misc fixes + ifreload new option + cleanups + more ifquery support etc

Ticket: CM-3346, CM-3784, CM-3841
Reviewed By:
Testing Done: various ifupdown2 tests
This commit is contained in:
Roopa Prabhu
2014-11-11 21:58:12 -08:00
parent 830c91d7e6
commit 2da58137d8
11 changed files with 245 additions and 943 deletions

View File

@@ -168,7 +168,8 @@ class bridge(moduleBase):
'If specified under the bridge the ports ' + 'If specified under the bridge the ports ' +
'inherit it unless overridden by a ' + 'inherit it unless overridden by a ' +
'bridge-vids attribuet under the port', 'bridge-vids attribuet under the port',
'example' : ['bridge-vids 4000']}, 'example' : ['bridge-vids 4000',
'bridge-vids 2000 2200-3000']},
'bridge-pvid' : 'bridge-pvid' :
{ 'help' : 'bridge port pvid. Must be specified under' + { 'help' : 'bridge port pvid. Must be specified under' +
' the bridge port', ' the bridge port',
@@ -198,6 +199,9 @@ class bridge(moduleBase):
self.brctlcmd = None self.brctlcmd = None
self._running_vidinfo = {} self._running_vidinfo = {}
self._running_vidinfo_valid = False self._running_vidinfo_valid = False
self._resv_vlan_range = self._get_reserved_vlan_range()
self.logger.debug('%s: using reserved vlan range %s'
%(self.__class__.__name__, str(self._resv_vlan_range)))
def _is_bridge(self, ifaceobj): def _is_bridge(self, ifaceobj):
if ifaceobj.get_attr_value_first('bridge-ports'): if ifaceobj.get_attr_value_first('bridge-ports'):
@@ -605,7 +609,8 @@ class bridge(moduleBase):
%(bportifaceobj.name, pvid, str(e))) %(bportifaceobj.name, pvid, str(e)))
def _apply_bridge_vlan_aware_port_settings_all(self, bportifaceobj, def _apply_bridge_vlan_aware_port_settings_all(self, bportifaceobj,
bridge_vids=None): bridge_vids=None,
bridge_pvid=None):
running_vidinfo = self._get_running_vidinfo() running_vidinfo = self._get_running_vidinfo()
vids = None vids = None
pvids = None pvids = None
@@ -613,22 +618,27 @@ class bridge(moduleBase):
if bport_access: if bport_access:
vids = re.split(r'[\s\t]\s*', bport_access) vids = re.split(r'[\s\t]\s*', bport_access)
pvids = vids pvids = vids
else:
bport_vids = bportifaceobj.get_attr_value_first('bridge-vids')
if bport_vids:
vids = re.split(r'[\s\t,]\s*', bport_vids)
bport_vids = bportifaceobj.get_attr_value_first('bridge-vids') bport_pvids = bportifaceobj.get_attr_value_first('bridge-pvid')
if bport_vids: if bport_pvids:
vids = re.split(r'[\s\t]\s*', bport_vids) pvids = re.split(r'[\s\t]\s*', bport_pvids)
bport_pvids = bportifaceobj.get_attr_value_first('bridge-pvid')
if bport_pvids:
pvids = re.split(r'[\s\t]\s*', bport_pvids)
if pvids: if pvids:
self._apply_bridge_port_pvids(bportifaceobj, pvids[0], self._apply_bridge_port_pvids(bportifaceobj, pvids[0],
running_vidinfo.get(bportifaceobj.name, {}).get('pvid')) running_vidinfo.get(bportifaceobj.name, {}).get('pvid'))
else: elif bridge_pvid:
self._apply_bridge_port_pvids(bportifaceobj, self._apply_bridge_port_pvids(bportifaceobj,
'1', running_vidinfo.get(bportifaceobj.name, bridge_pvid, running_vidinfo.get(bportifaceobj.name,
{}).get('pvid')) {}).get('pvid'))
# XXX: default pvid is already one
#else:
# self._apply_bridge_port_pvids(bportifaceobj,
# '1', running_vidinfo.get(bportifaceobj.name,
# {}).get('pvid'))
if vids: if vids:
self._apply_bridge_vids(bportifaceobj, vids, self._apply_bridge_vids(bportifaceobj, vids,
@@ -686,10 +696,16 @@ class bridge(moduleBase):
bridge_vids = ifaceobj.get_attr_value_first('bridge-vids') bridge_vids = ifaceobj.get_attr_value_first('bridge-vids')
if bridge_vids: if bridge_vids:
bridge_vids = re.split(r'[\s\t]\s*', bridge_vids) bridge_vids = re.split(r'[\s\t,]\s*', bridge_vids)
else: else:
bridge_vids = None bridge_vids = None
bridge_pvid = ifaceobj.get_attr_value_first('bridge-pvid')
if bridge_pvid:
bridge_pvid = re.split(r'[\s\t]\s*', bridge_pvid)
else:
bridge_pvid = None
bridgeports = self._get_bridge_port_list(ifaceobj) bridgeports = self._get_bridge_port_list(ifaceobj)
for bport in bridgeports: for bport in bridgeports:
# Use the brctlcmd bulk set method: first build a dictionary # Use the brctlcmd bulk set method: first build a dictionary
@@ -711,7 +727,7 @@ class bridge(moduleBase):
# Add attributes specific to the vlan aware bridge # Add attributes specific to the vlan aware bridge
if bridge_vlan_aware: if bridge_vlan_aware:
self._apply_bridge_vlan_aware_port_settings_all( self._apply_bridge_vlan_aware_port_settings_all(
bportifaceobj, bridge_vids) bportifaceobj, bridge_vids, bridge_pvid)
self._apply_bridge_port_settings(bportifaceobj, self._apply_bridge_port_settings(bportifaceobj,
bridgeifaceobj=ifaceobj) bridgeifaceobj=ifaceobj)
@@ -722,8 +738,11 @@ class bridge(moduleBase):
if self.ipcmd.bridge_is_vlan_aware(bridgename): if self.ipcmd.bridge_is_vlan_aware(bridgename):
bridge_vids = self._get_bridge_vids(bridgename, bridge_vids = self._get_bridge_vids(bridgename,
ifaceobj_getfunc) ifaceobj_getfunc)
bridge_pvid = self._get_bridge_pvid(bridgename,
ifaceobj_getfunc)
self._apply_bridge_vlan_aware_port_settings_all(ifaceobj, self._apply_bridge_vlan_aware_port_settings_all(ifaceobj,
bridge_vids) bridge_vids,
bridge_pvid)
self._apply_bridge_port_settings(ifaceobj, bridgename=bridgename) self._apply_bridge_port_settings(ifaceobj, bridgename=bridgename)
ifaceobj.priv_flags |= self._BRIDGE_PORT_PROCESSED ifaceobj.priv_flags |= self._BRIDGE_PORT_PROCESSED
return return
@@ -1096,9 +1115,16 @@ class bridge(moduleBase):
ifaceobjs = ifaceobj_getfunc(bridgename) ifaceobjs = ifaceobj_getfunc(bridgename)
for ifaceobj in ifaceobjs: for ifaceobj in ifaceobjs:
vids = ifaceobj.get_attr_value_first('bridge-vids') vids = ifaceobj.get_attr_value_first('bridge-vids')
if vids: return re.split(r'[\s\t]\s*', vids) if vids: return re.split(r'[\s\t,]\s*', vids)
return None return None
def _get_bridge_pvid(self, bridgename, ifaceobj_getfunc):
ifaceobjs = ifaceobj_getfunc(bridgename)
pvid = None
for ifaceobj in ifaceobjs:
pvid = ifaceobj.get_attr_value_first('bridge-pvid')
return pvid
def _get_bridge_name(self, ifaceobj): def _get_bridge_name(self, ifaceobj):
return self.ipcmd.bridge_port_get_bridge_name(ifaceobj.name) return self.ipcmd.bridge_port_get_bridge_name(ifaceobj.name)

View File

@@ -1,863 +0,0 @@
#!/usr/bin/python
#
# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
#
from sets import Set
from ifupdown.iface import *
from ifupdownaddons.modulebase import moduleBase
from ifupdownaddons.bridgeutils import brctl
from ifupdownaddons.iproute2 import iproute2
import itertools
import re
import os
class bridgevlanaware(moduleBase):
""" ifupdown2 addon module to configure linux bridges """
_modinfo = { 'mhelp' : 'bridge configuration module',
'attrs' : {
'bridge' :
{'help': 'bridge this interface is part of',
'example' : ['bridge br0']},
'bridge-vlan-aware' :
{'help': 'Is this a vlan aware bridge ?',
'default' : 'no',
'required' : False,
'example' : ['bridge-vlan-aware yes']},
'type' :
{'help': 'type of interface this module supports',
'example' : ['type bridge']},
'bridge-stp' :
{'help': 'bridge-stp yes/no',
'example' : ['bridge-stp no'],
'validvals' : ['yes', 'on', 'off', 'no'],
'default' : 'no'},
'bridge-bridgeprio' :
{'help': 'bridge priority',
'example' : ['bridge-bridgeprio 32768'],
'default' : '32768'},
'bridge-ageing' :
{'help': 'bridge ageing',
'example' : ['bridge-ageing 300'],
'default' : '300'},
'bridge-fd' :
{ 'help' : 'bridge forward delay',
'example' : ['bridge-fd 15'],
'default' : '15'},
'bridge-gcint' :
# XXX: recheck values
{ 'help' : 'bridge garbage collection interval in secs',
'example' : ['bridge-gcint 4'],
'default' : '4'},
'bridge-hello' :
{ 'help' : 'bridge set hello time',
'example' : ['bridge-hello 2'],
'default' : '2'},
'bridge-maxage' :
{ 'help' : 'bridge set maxage',
'example' : ['bridge-maxage 20'],
'default' : '20'},
'bridge-pathcosts' :
{ 'help' : 'bridge set port path costs',
'example' : ['bridge-pathcosts swp1=100 swp2=100'],
'default' : '100'},
'bridge-priority' :
{ 'help' : 'bridge port priority',
'example' : ['bridge-priority 32'],
'default' : '32'},
'bridge-mclmc' :
{ 'help' : 'set multicast last member count',
'example' : ['bridge-mclmc 2'],
'default' : '2'},
'bridge-mcrouter' :
{ 'help' : 'set multicast router',
'default' : '1',
'example' : ['bridge-mcrouter 1']},
'bridge-mcsnoop' :
{ 'help' : 'set multicast snooping',
'default' : '1',
'example' : ['bridge-mcsnoop 1']},
'bridge-mcsqc' :
{ 'help' : 'set multicast startup query count',
'default' : '2',
'example' : ['bridge-mcsqc 2']},
'bridge-mcqifaddr' :
{ 'help' : 'set multicast query to use ifaddr',
'default' : '0',
'example' : ['bridge-mcqifaddr 0']},
'bridge-mcquerier' :
{ 'help' : 'set multicast querier',
'default' : '0',
'example' : ['bridge-mcquerier 0']},
'bridge-hashel' :
{ 'help' : 'set hash elasticity',
'default' : '4096',
'example' : ['bridge-hashel 4096']},
'bridge-hashmax' :
{ 'help' : 'set hash max',
'default' : '4096',
'example' : ['bridge-hashmax 4096']},
'bridge-mclmi' :
{ 'help' : 'set multicast last member interval (in secs)',
'default' : '1',
'example' : ['bridge-mclmi 1']},
'bridge-mcmi' :
{ 'help' : 'set multicast membership interval (in secs)',
'default' : '260',
'example' : ['bridge-mcmi 260']},
'bridge-mcqpi' :
{ 'help' : 'set multicast querier interval (in secs)',
'default' : '255',
'example' : ['bridge-mcqpi 255']},
'bridge-mcqi' :
{ 'help' : 'set multicast query interval (in secs)',
'default' : '125',
'example' : ['bridge-mcqi 125']},
'bridge-mcqri' :
{ 'help' : 'set multicast query response interval (in secs)',
'default' : '10',
'example' : ['bridge-mcqri 10']},
'bridge-mcsqi' :
{ 'help' : 'set multicast startup query interval (in secs)',
'default' : '31',
'example' : ['bridge-mcsqi 31']},
'bridge-mcqv4src' :
{ 'help' : 'set per VLAN v4 multicast querier source address',
'compat' : True,
'example' : ['bridge-mcqv4src 172.16.100.1']},
'bridge-igmp-querier-src' :
{ 'help' : 'set per VLAN v4 multicast querier source address',
'example' : ['bridge-igmp-querier-src 172.16.100.1']},
'bridge-mcfl' :
{ 'help' : 'port multicast fast leave',
'default' : '0',
'example' : ['bridge-mcfl 0']},
'bridge-waitport' :
{ 'help' : 'wait for a max of time secs for the' +
' specified ports to become available,' +
'if no ports are specified then those' +
' specified on bridge-ports will be' +
' used here. Specifying no ports here ' +
'should not be used if we are using ' +
'regex or \"all\" on bridge_ports,' +
'as it wouldnt work.',
'default' : '0',
'example' : ['bridge-waitport 4 swp1 swp2']},
'bridge-maxwait' :
{ 'help' : 'forces to time seconds the maximum time ' +
'that the Debian bridge setup scripts will ' +
'wait for the bridge ports to get to the ' +
'forwarding status, doesn\'t allow factional ' +
'part. If it is equal to 0 then no waiting' +
' is done',
'default' : '0',
'example' : ['bridge-maxwait 3']},
'bridge-vlan' :
{ 'help' : 'bridge vlans',
'example' : ['bridge-vlan 4000']},
'bridge-vlan-native' :
{ 'compat' : True,
'help' : 'bridge port vlan',
'example' : ['bridge-vlan-native 1']},
}}
def __init__(self, *args, **kargs):
moduleBase.__init__(self, *args, **kargs)
self.ipcmd = None
self.brctlcmd = None
def _is_bridge_port(self, ifaceobj):
if ifaceobj.get_attr_value_first('bridge'):
return True
return False
def _is_bridge(self, ifaceobj):
if ifaceobj.type == ifaceType.BRIDGE:
return True
return False
def _is_bridge_vlan(self, ifaceobj):
if ifaceobj.type & ifaceType.BRIDGE_VLAN:
return True
return False
def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
bridge = ifaceobj.get_attr_value_first('bridge')
if bridge:
match = re.match("^%s-([\d]+)" %bridge, ifaceobj.name)
if match:
ifaceobj.priv_data = int(match.groups()[0], 10)
# XXX: mark this iface as a bridge_vlan iface
ifaceobj.type = ifaceType.BRIDGE_VLAN
return [bridge]
elif ifaceobj.get_attr_value_first('type') == 'bridge':
ifaceobj.type = ifaceType.BRIDGE
return None
def get_dependent_ifacenames_running(self, ifaceobj):
self._init_command_handlers()
if not self.brctlcmd.bridge_exists(ifaceobj.name):
return None
return self.brctlcmd.get_bridge_ports(ifaceobj.name)
def _process_bridge_waitport(self, ifaceobj, portlist):
waitport_value = ifaceobj.get_attr_value_first('bridge-waitport')
if not waitport_value: return
try:
waitportvals = re.split(r'[\s\t]\s*', waitport_value, 1)
if not waitportvals: return
try:
waitporttime = int(waitportvals[0])
except:
self.log_warn('%s: invalid waitport value \'%s\''
%(ifaceobj.name, waitporttime))
return
if waitporttime <= 0: return
try:
waitportlist = self.parse_port_list(waitportvals[1])
except IndexError, e:
# ignore error and use all bridge ports
waitportlist = portlist
pass
if not waitportlist: return
self.logger.info('%s: waiting for ports %s to exist ...'
%(ifaceobj.name, str(waitportlist)))
starttime = time.time()
while ((time.time() - starttime) < waitporttime):
if all([False for p in waitportlist
if not self.ipcmd.link_exists(p)]):
break;
time.sleep(1)
except Exception, e:
self.log_warn('%s: unable to process waitport: %s'
%(ifaceobj.name, str(e)))
def _add_ports(self, ifaceobj):
bridgeports = self._get_bridge_port_list(ifaceobj)
runningbridgeports = []
self._process_bridge_waitport(ifaceobj, bridgeports)
# Delete active ports not in the new port list
if not self.PERFMODE:
runningbridgeports = self.brctlcmd.get_bridge_ports(ifaceobj.name)
if runningbridgeports:
[self.ipcmd.link_set(bport, 'nomaster')
for bport in runningbridgeports
if not bridgeports or bport not in bridgeports]
else:
runningbridgeports = []
if not bridgeports:
return
err = 0
for bridgeport in Set(bridgeports).difference(Set(runningbridgeports)):
try:
if not self.DRYRUN and not self.ipcmd.link_exists(bridgeport):
self.log_warn('%s: bridge port %s does not exist'
%(ifaceobj.name, bridgeport))
err += 1
continue
self.ipcmd.link_set(bridgeport, 'master', ifaceobj.name)
self.write_file('/proc/sys/net/ipv6/conf/%s' %bridgeport +
'/disable_ipv6', '1')
self.ipcmd.addr_flush(bridgeport)
except Exception, e:
self.log_error(str(e))
if err:
self.log_error('bridge configuration failed (missing ports)')
def _process_bridge_maxwait(self, ifaceobj, portlist):
maxwait = ifaceobj.get_attr_value_first('bridge-maxwait')
if not maxwait: return
try:
maxwait = int(maxwait)
except:
self.log_warn('%s: invalid maxwait value \'%s\'' %(ifaceobj.name,
maxwait))
return
if not maxwait: return
self.logger.info('%s: waiting for ports to go to fowarding state ..'
%ifaceobj.name)
try:
starttime = time.time()
while ((time.time() - starttime) < maxwait):
if all([False for p in portlist
if self.read_file_oneline(
'/sys/class/net/%s/brif/%s/state'
%(ifaceobj.name, p)) != '3']):
break;
time.sleep(1)
except Exception, e:
self.log_warn('%s: unable to process maxwait: %s'
%(ifaceobj.name, str(e)))
def _ints_to_ranges(self, ints):
for a, b in itertools.groupby(enumerate(ints), lambda (x, y): y - x):
b = list(b)
yield b[0][1], b[-1][1]
def _ranges_to_ints(self, rangelist):
""" returns expanded list of integers given set of string ranges
example: ['1', '2-4', '6'] returns [1, 2, 3, 4, 6]
"""
result = []
for part in rangelist:
if '-' in part:
a, b = part.split('-')
a, b = int(a), int(b)
result.extend(range(a, b + 1))
else:
a = int(part)
result.append(a)
return result
def _diff_vids(self, vids1, vids2):
vids_to_add = None
vids_to_del = None
vids1_ints = self._ranges_to_ints(vids1)
vids2_ints = self._ranges_to_ints(vids2)
vids1_diff = Set(vids1_ints).difference(vids2_ints)
vids2_diff = Set(vids2_ints).difference(vids1_ints)
if vids1_diff:
vids_to_add = ['%d' %start if start == end else '%d-%d' %(start, end)
for start, end in self._ints_to_ranges(vids1_diff)]
if vids2_diff:
vids_to_del = ['%d' %start if start == end else '%d-%d' %(start, end)
for start, end in self._ints_to_ranges(vids2_diff)]
return (vids_to_del, vids_to_add)
def _compare_vids(self, vids1, vids2):
""" Returns true if the vids are same else return false """
vids1_ints = self._ranges_to_ints(vids1)
vids2_ints = self._ranges_to_ints(vids2)
if Set(vids1_ints).symmetric_difference(vids2_ints):
return False
else:
return True
def _set_bridge_mcqv4src(self, ifaceobj):
attrval = ifaceobj.get_attr_value_first('bridge-mcqv4src')
if attrval:
running_mcqv4src = {}
if not self.PERFMODE:
running_mcqv4src = self.brctlcmd.get_mcqv4src(ifaceobj.name)
mcqs = {}
srclist = attrval.split()
for s in srclist:
k, v = s.split('=')
mcqs[k] = v
k_to_del = Set(running_mcqv4src.keys()).difference(mcqs.keys())
for v in k_to_del:
self.brctlcmd.del_mcqv4src(ifaceobj.name, int(v, 10))
for v in mcqs.keys():
self.brctlcmd.set_mcqv4src(ifaceobj.name, int(v, 10), mcqs[v])
def _set_bridge_vidinfo(self, ifaceobj, isbridge=True):
# Handle bridge vlan attrs
running_vidinfo = {}
if not self.PERFMODE:
running_vidinfo = self.ipcmd.bridge_port_vids_get_all()
attrval = ifaceobj.get_attr_value_first('bridge-vlan')
if attrval:
vids = re.split(r'[\s\t]\s*', attrval)
#vids = attrval.split(',')
try:
if running_vidinfo.get(ifaceobj.name):
(vids_to_del, vids_to_add) = \
self._diff_vids(vids,
running_vidinfo.get(ifaceobj.name, {}).get('vlan'))
if vids_to_del:
self.ipcmd.bridge_vids_del(ifaceobj.name,
vids_to_del, isbridge)
if vids_to_add:
self.ipcmd.bridge_vids_add(ifaceobj.name,
vids_to_add, isbridge)
else:
self.ipcmd.bridge_vids_add(ifaceobj.name, vids,
isbridge)
except Exception, e:
self.log_warn('%s: failed to set vid `%s` (%s)'
%(ifaceobj.name, str(vids), str(e)))
else:
running_vids = running_vidinfo.get(ifaceobj.name, {}).get('vlan')
if running_vids:
self.ipcmd.bridge_vids_del(ifaceobj.name, running_vids)
# Install pvids
pvid = ifaceobj.get_attr_value_first('bridge-vlan-native')
if pvid:
try:
running_pvid = running_vidinfo.get(ifaceobj.name,
{}).get('pvid')
if running_pvid:
if running_pvid != pvid:
self.ipcmd.bridge_port_pvid_del(ifaceobj.name,
running_pvid)
self.ipcmd.bridge_port_pvid_add(ifaceobj.name, pvid)
else:
self.ipcmd.bridge_port_pvid_add(ifaceobj.name, pvid)
except Exception, e:
self.log_warn('%s: failed to set pvid `%s` (%s)'
%(ifaceobj.name, pvid, str(e)))
def _apply_bridge_settings(self, ifaceobj):
try:
stp = ifaceobj.get_attr_value_first('bridge-stp')
if stp:
self.brctlcmd.set_stp(ifaceobj.name, stp)
# Use the brctlcmd bulk set method: first build a dictionary
# and then call set
bridgeattrs = { k:v for k,v in
{'ageing' :
ifaceobj.get_attr_value_first('bridge-ageing'),
'bridgeprio' :
ifaceobj.get_attr_value_first(
'bridge-bridgeprio'),
'fd' :
ifaceobj.get_attr_value_first('bridge-fd'),
'gcint' :
ifaceobj.get_attr_value_first('bridge-gcint'),
'hello' :
ifaceobj.get_attr_value_first('bridge-hello'),
'maxage' :
ifaceobj.get_attr_value_first('bridge-maxage'),
'mclmc' :
ifaceobj.get_attr_value_first('bridge-mclmc'),
'mcrouter' :
ifaceobj.get_attr_value_first(
'bridge-mcrouter'),
'mcsnoop' :
ifaceobj.get_attr_value_first('bridge-mcsnoop'),
'mcsqc' :
ifaceobj.get_attr_value_first('bridge-mcsqc'),
'mcqifaddr' :
ifaceobj.get_attr_value_first(
'bridge-mcqifaddr'),
'mcquerier' :
ifaceobj.get_attr_value_first(
'bridge-mcquerier'),
'hashel' :
ifaceobj.get_attr_value_first('bridge-hashel'),
'hashmax' :
ifaceobj.get_attr_value_first('bridge-hashmax'),
'mclmi' :
ifaceobj.get_attr_value_first('bridge-mclmi'),
'mcmi' :
ifaceobj.get_attr_value_first('bridge-mcmi'),
'mcqpi' :
ifaceobj.get_attr_value_first('bridge-mcqpi'),
'mcqi' :
ifaceobj.get_attr_value_first('bridge-mcqi'),
'mcqri' :
ifaceobj.get_attr_value_first('bridge-mcqri'),
'mcsqi' :
ifaceobj.get_attr_value_first('bridge-mcsqi')
}.items()
if v }
if bridgeattrs:
self.brctlcmd.set_bridge_attrs(ifaceobj.name, bridgeattrs)
self._set_bridge_vidinfo(ifaceobj)
self._set_bridge_mcqv4src(ifaceobj)
#self._process_bridge_maxwait(ifaceobj,
# self._get_bridge_port_list(ifaceobj))
except Exception, e:
self.log_warn(str(e))
def _apply_bridge_port_settings(self, ifaceobj, bridge):
try:
# Use the brctlcmd bulk set method: first build a dictionary
# and then call set
portattrs = {}
for attrname, dstattrname in {'bridge-pathcost' : 'pathcost',
'bridge-prio' : 'portprio',
'bridge-mcrouter' : 'portmcrouter',
'bridge-mcfl' : 'portmcfl'}.items():
attrval = ifaceobj.get_attr_value_first(attrname)
if not attrval:
continue
portattrs[ifaceobj.name] = attrval
self.brctlcmd.set_bridgeport_attrs(bridge, ifaceobj.name, portattrs)
self._set_bridge_vidinfo(ifaceobj, isbridge=False)
except Exception, e:
self.log_warn(str(e))
def _apply_bridge_vlan_settings(self, ifaceobj, bridge):
mcq = ifaceobj.get_attrs_value_first(['bridge-mcqv4src',
'bridge-igmp-querier-src'])
if mcq:
running_mcq = None
if not self.PERFMODE:
running_mcq = self.brctlcmd.get_mcqv4src(bridge,
vlan=ifaceobj.priv_data)
if running_mcq != mcq:
self.brctlcmd.set_mcqv4src(bridge, ifaceobj.priv_data, mcq)
self.ipcmd.bridge_vids_add(bridge, [ifaceobj.priv_data], True)
def _delete_bridge_vlan_settings(self, ifaceobj, bridge):
# delete vlan from bridge
self.ipcmd.bridge_vids_del(bridge, [ifaceobj.priv_data], True)
mcq = ifaceobj.get_attr_value_first('bridge-mcqv4src')
if mcq:
self.brctlcmd.del_mcqv4src(bridge, ifaceobj.name)
def _up_bridge(self, ifaceobj):
try:
if not self.PERFMODE:
if not self.ipcmd.link_exists(ifaceobj.name):
self.ipcmd.link_create(ifaceobj.name, 'bridge')
else:
self.ipcmd.link_create(ifaceobj.name, 'bridge')
self._apply_bridge_settings(ifaceobj)
except Exception, e:
self.log_error(str(e))
def _up_bridge_port(self, ifaceobj, bridge):
try:
self.ipcmd.link_set(ifaceobj.name, 'master', bridge)
self._apply_bridge_port_settings(ifaceobj, bridge)
except Exception, e:
self.log_error(str(e))
def _up_bridge_vlan(self, ifaceobj, bridge):
purge_existing = False if self.PERFMODE else True
try:
address = ifaceobj.get_attr_value('address')
if address:
# Create a vlan device,
ifacename = '%s.%s' %(bridge, ifaceobj.priv_data)
if not self.ipcmd.link_exists(ifacename):
self.ipcmd.link_create_vlan(ifacename, bridge,
ifaceobj.priv_data)
purge_existing = False
hwaddress = ifaceobj.get_attr_value_first('hwaddress')
if hwaddress:
self.ipcmd.link_set_hwaddress(ifacename, hwaddress)
self.ipcmd.addr_add_multiple(ifacename, address, purge_existing)
self._apply_bridge_vlan_settings(ifaceobj, bridge)
except Exception, e:
self.log_error(str(e))
def _up(self, ifaceobj):
bridge = ifaceobj.get_attr_value_first('bridge')
if ifaceobj.type == ifaceType.BRIDGE_VLAN:
self._up_bridge_vlan(ifaceobj, bridge)
elif bridge:
self._up_bridge_port(ifaceobj, bridge)
elif self._is_bridge(ifaceobj):
self._up_bridge(ifaceobj)
else:
# Was this interface part of the bridge at some point and now
# got removed ?. If we attached it to the bridge last time
# we should release it
if os.path.exists('/sys/class/net/%s/brport' %ifaceobj.name):
bridgelink = os.readlink('/sys/class/net/%s/brport/bridge'
%ifaceobj.name)
if bridgelink:
bridge = os.path.basename(bridgelink)
if (not ifaceobj.upperifaces or
bridge not in ifaceobj.upperifaces):
# set nomaster
self.ipcmd.link_set(ifaceobj.name, 'nomaster')
def _down_bridge(self, ifaceobj):
try:
self.brctlcmd.delete_bridge(ifaceobj.name)
except Exception, e:
self.log_error(str(e))
def _down_bridge_port(self, ifaceobj):
self.ipcmd.link_set(ifaceobj.name, 'nomaster')
def _down_bridge_vlan(self, ifaceobj, bridge):
try:
address = ifaceobj.get_attr_value('address')
if address:
# Create a vlan device,
ifacename = '%s.%s' %(bridge, ifaceobj.priv_data)
self.ipcmd.link_delete(ifacename)
self._delete_bridge_vlan_settings(ifaceobj, bridge)
except Exception, e:
self.log_error(str(e))
def _down(self, ifaceobj):
bridge = ifaceobj.get_attr_value_first('bridge')
if ifaceobj.type == ifaceType.BRIDGE_VLAN:
self._down_bridge_vlan(ifaceobj, bridge)
elif bridge:
self._down_bridge_port(ifaceobj)
elif self._is_bridge(ifaceobj):
self._down_bridge(ifaceobj)
def _query_running_vidinfo(self, ifaceobjrunning, ports):
running_attrs = {}
running_vidinfo = self.ipcmd.bridge_port_vids_get_all()
if ports:
running_bridge_port_vids = ''
for p in ports:
try:
running_vids = running_vidinfo.get(p, {}).get('vlan')
if running_vids:
running_bridge_port_vids += ' %s=%s' %(p,
','.join(running_vids))
except Exception:
pass
running_attrs['bridge-port-vids'] = running_bridge_port_vids
running_bridge_port_pvids = ''
for p in ports:
try:
running_pvids = running_vidinfo.get(p, {}).get('pvid')
if running_pvids:
running_bridge_port_pvids += ' %s=%s' %(p,
running_pvids)
except Exception:
pass
running_attrs['bridge-port-pvids'] = running_bridge_port_pvids
running_bridge_vids = running_vidinfo.get(ifaceobjrunning.name, {}).get('vlan')
if running_bridge_vids:
running_attrs['bridge-vids'] = ','.join(running_bridge_vids)
return running_attrs
def _query_running_mcqv4src(self, ifaceobjrunning):
running_mcqv4src = self.brctlcmd.get_mcqv4src(ifaceobjrunning.name)
mcqs = ['%s=%s' %(v, i) for v, i in running_mcqv4src.items()]
mcqs.sort()
mcq = ' '.join(mcqs)
return mcq
def _query_running_attrs(self, ifaceobjrunning):
bridgeattrdict = {}
userspace_stp = 0
ports = None
skip_kernel_stp_attrs = 0
if self.sysctl_get('net.bridge.bridge-stp-user-space') == '1':
userspace_stp = 1
tmpbridgeattrdict = self.brctlcmd.get_bridge_attrs(ifaceobjrunning.name)
if not tmpbridgeattrdict:
self.logger.warn('%s: unable to get bridge attrs'
%ifaceobjrunning.name)
return bridgeattrdict
# Fill bridge_ports and bridge stp attributes first
ports = tmpbridgeattrdict.get('ports')
if ports:
bridgeattrdict['bridge-ports'] = [' '.join(ports.keys())]
stp = tmpbridgeattrdict.get('stp', 'no')
if stp != self.get_mod_subattr('bridge-stp', 'default'):
bridgeattrdict['bridge-stp'] = [stp]
if stp == 'yes' and userspace_stp:
skip_kernel_stp_attrs = 1
# pick all other attributes
for k,v in tmpbridgeattrdict.items():
if not v:
continue
if k == 'ports' or k == 'stp':
continue
if skip_kernel_stp_attrs and k[:2] != 'mc':
# only include igmp attributes if kernel stp is off
continue
attrname = 'bridge-' + k
if v != self.get_mod_subattr(attrname, 'default'):
bridgeattrdict[attrname] = [v]
bridgevidinfo = self._query_running_vidinfo(ifaceobjrunning, ports)
if bridgevidinfo:
bridgeattrdict.update({k : [v] for k, v in bridgevidinfo.items()
if v})
mcq = self._query_running_mcqv4src(ifaceobjrunning)
if mcq:
bridgeattrdict['bridge-mcqv4src'] = [mcq]
if skip_kernel_stp_attrs:
return bridgeattrdict
if ports:
portconfig = {'bridge-pathcosts' : '',
'bridge-portprios' : ''}
for p, v in ports.items():
v = self.brctlcmd.get_pathcost(ifaceobjrunning.name, p)
if v and v != self.get_mod_subattr('bridge-pathcosts',
'default'):
portconfig['bridge-pathcosts'] += ' %s=%s' %(p, v)
v = self.brctlcmd.get_portprio(ifaceobjrunning.name, p)
if v and v != self.get_mod_subattr('bridge-portprios',
'default'):
portconfig['bridge-portprios'] += ' %s=%s' %(p, v)
bridgeattrdict.update({k : [v] for k, v in portconfig.items()
if v})
return bridgeattrdict
def _query_check_mcqv4src(self, ifaceobj, ifaceobjcurr):
running_mcqs = self._query_running_mcqv4src(ifaceobj)
attrval = ifaceobj.get_attr_value_first('bridge-mcqv4src')
if attrval:
mcqs = attrval.split()
mcqs.sort()
mcqsout = ' '.join(mcqs)
ifaceobjcurr.update_config_with_status('bridge-mcqv4src',
running_mcqs, 1 if running_mcqs != mcqsout else 0)
def _query_check_vidinfo(self, ifaceobj, ifaceobjcurr):
err = 0
running_vidinfo = self.ipcmd.bridge_port_vids_get_all()
attrval = ifaceobj.get_attr_value_first('bridge-port-vids')
if attrval:
running_bridge_port_vids = ''
portlist = self.parse_port_list(attrval)
if not portlist:
self.log_warn('%s: could not parse \'%s %s\''
%(ifaceobj.name, attrname, attrval))
return
err = 0
for p in portlist:
try:
(port, val) = p.split('=')
vids = val.split(',')
running_vids = running_vidinfo.get(port, {}).get('vlan')
if running_vids:
if not self._compare_vids(vids, running_vids):
err += 1
running_bridge_port_vids += ' %s=%s' %(port,
','.join(running_vids))
else:
running_bridge_port_vids += ' %s' %p
else:
err += 1
except Exception, e:
self.log_warn('%s: failure checking vid %s (%s)'
%(ifaceobj.name, p, str(e)))
if err:
ifaceobjcurr.update_config_with_status('bridge-port-vids',
running_bridge_port_vids, 1)
else:
ifaceobjcurr.update_config_with_status('bridge-port-vids',
attrval, 0)
# Install pvids
attrval = ifaceobj.get_attr_value_first('bridge-port-pvids')
if attrval:
portlist = self.parse_port_list(attrval)
if not portlist:
self.log_warn('%s: could not parse \'%s %s\''
%(ifaceobj.name, attrname, attrval))
return
running_bridge_port_pvids = ''
err = 0
for p in portlist:
try:
(port, pvid) = p.split('=')
running_pvid = running_vidinfo.get(port, {}).get('pvid')
if running_pvid and running_pvid == pvid:
running_bridge_port_pvids += ' %s' %p
else:
err += 1
running_bridge_port_pvids += ' %s=%s' %(port,
running_pvid)
except Exception, e:
self.log_warn('%s: failure checking pvid %s (%s)'
%(ifaceobj.name, pvid, str(e)))
if err:
ifaceobjcurr.update_config_with_status('bridge-port-pvids',
running_bridge_port_pvids, 1)
else:
ifaceobjcurr.update_config_with_status('bridge-port-pvids',
running_bridge_port_pvids, 0)
attrval = ifaceobj.get_attr_value_first('bridge-vids')
if attrval:
vids = re.split(r'[\s\t]\s*', attrval)
running_vids = running_vidinfo.get(ifaceobj.name, {}).get('vlan')
if running_vids:
if self._compare_vids(vids, running_vids):
ifaceobjcurr.update_config_with_status('bridge-vids',
attrval, 0)
else:
ifaceobjcurr.update_config_with_status('bridge-vids',
','.join(running_vids), 1)
else:
ifaceobjcurr.update_config_with_status('bridge-vids', attrval,
1)
def _query_check_bridge(self, ifaceobj, ifaceobjcurr):
return
def _query_check_bridge_port(self, ifaceobj, bridge, ifaceobjcurr):
return
def _query_check_bridge_vlan(self, ifaceobj, bridge, ifaceobjcurr):
return
def _query_check(self, ifaceobj, ifaceobjcurr):
bridge = ifaceobj.get_attr_value_first('bridge')
if ifaceobj.type == ifaceType.BRIDGE_VLAN:
self._query_check_bridge_vlan(ifaceobj, bridge, ifaceobjcurr)
elif bridge:
self._query_check_bridge_port(ifaceobj, bridge, ifaceobjcurr)
elif self._is_bridge(ifaceobj):
self._query_check_bridge(ifaceobj, ifaceobjcurr)
def _query_running(self, ifaceobjrunning):
return
_run_ops = {'pre-up' : _up,
'post-down' : _down,
'query-checkcurr' : _query_check,
'query-running' : _query_running}
def get_ops(self):
""" returns list of ops supported by this module """
return self._run_ops.keys()
def _init_command_handlers(self):
flags = self.get_flags()
if not self.ipcmd:
self.ipcmd = iproute2(**flags)
if not self.brctlcmd:
self.brctlcmd = brctl(**flags)
def run(self, ifaceobj, operation, query_ifaceobj=None):
""" run bridge configuration on the interface object passed as
argument. Can create bridge interfaces if they dont exist already
Args:
**ifaceobj** (object): iface object
**operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
'query-running'
Kwargs:
**query_ifaceobj** (object): query check ifaceobject. This is only
valid when op is 'query-checkcurr'. It is an object same as
ifaceobj, but contains running attribute values and its config
status. The modules can use it to return queried running state
of interfaces. status is success if the running state is same
as user required state in ifaceobj. error otherwise.
"""
op_handler = self._run_ops.get(operation)
if not op_handler:
return
self._init_command_handlers()
if operation == 'query-checkcurr':
op_handler(self, ifaceobj, query_ifaceobj)
else:
op_handler(self, ifaceobj)

View File

@@ -321,6 +321,7 @@ class ifenslave(moduleBase):
self.ifenslavecmd.get_lacp_fallback_period(bondname), self.ifenslavecmd.get_lacp_fallback_period(bondname),
'bond-lacp-fallback-priority' : 'bond-lacp-fallback-priority' :
self.ifenslavecmd.get_lacp_fallback_priority(bondname)} self.ifenslavecmd.get_lacp_fallback_priority(bondname)}
slaves = self.ifenslavecmd.get_slaves(bondname) slaves = self.ifenslavecmd.get_slaves(bondname)
if slaves: if slaves:
bondattrs['bond-slaves'] = slaves bondattrs['bond-slaves'] = slaves

View File

@@ -30,6 +30,9 @@ class vlan(moduleBase):
moduleBase.__init__(self, *args, **kargs) moduleBase.__init__(self, *args, **kargs)
self.ipcmd = None self.ipcmd = None
self._bridge_vids_query_cache = {} self._bridge_vids_query_cache = {}
self._resv_vlan_range = self._get_reserved_vlan_range()
self.logger.debug('%s: using reserved vlan range %s'
%(self.__class__.__name__, str(self._resv_vlan_range)))
def _is_vlan_device(self, ifaceobj): def _is_vlan_device(self, ifaceobj):
vlan_raw_device = ifaceobj.get_attr_value_first('vlan-raw-device') vlan_raw_device = ifaceobj.get_attr_value_first('vlan-raw-device')
@@ -197,6 +200,7 @@ class vlan(moduleBase):
def _init_command_handlers(self): def _init_command_handlers(self):
if not self.ipcmd: if not self.ipcmd:
self.ipcmd = iproute2(**self.get_flags()) self.ipcmd = iproute2(**self.get_flags())
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args): def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
""" run vlan configuration on the interface object passed as argument """ run vlan configuration on the interface object passed as argument

View File

@@ -13,12 +13,21 @@ template_lookuppath=/etc/network/ifupdown2/templates
# Support /etc/network/if-*/ scripts # Support /etc/network/if-*/ scripts
addon_scripts_support=0 addon_scripts_support=0
# By defauly ifupdown2 only supports a single vlan filtering bridge
# on the system. Set this flag to 1 to support multiple vlan
# filtering bridges
multiple_vlan_aware_bridge_support=0
# ifquery check status strings. # ifquery check status strings.
# By default `ifquery --check` prints the check and # By default `ifquery --check` prints the check and
# cross marks against interface attributes. # cross marks against interface attributes.
# Use the below strings to modify the default behaviour. # Use the below strings to modify the default behaviour.
#
# ifquery_check_success_str=
# ifquery_check_error_str=(x)
#
# check_success_str= # This attribute controls iface/vlan range expansions
# check_error_str=(x) # in ifquery default output.
ifquery_ifacename_expand_range=0
multiple_vlan_aware_bridge_support=0

View File

@@ -18,10 +18,9 @@ import logging
import json import json
class ifaceType(): class ifaceType():
UNKNOWN = 0x1 UNKNOWN = 0x0
GENERIC = 0x2 IFACE = 0x1
BRIDGE = 0x3 BRIDGE_VLAN = 0x2
BRIDGE_VLAN = 0x4
class ifaceStatus(): class ifaceStatus():
"""Enumerates iface status """ """Enumerates iface status """
@@ -180,6 +179,8 @@ 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 HAS_SIBLINGS = 0x2
IFACERANGE_ENTRY = 0x3
IFACERANGE_START = 0x4
version = '0.1' version = '0.1'
@@ -214,7 +215,7 @@ class iface():
self.type = ifaceType.UNKNOWN self.type = ifaceType.UNKNOWN
"""interface type""" """interface type"""
self.priv_data = None self.priv_data = None
self.real_name = None self.realname = None
def _set_attrs_from_dict(self, attrdict): def _set_attrs_from_dict(self, attrdict):
self.auto = attrdict.get('auto', False) self.auto = attrdict.get('auto', False)
@@ -436,15 +437,20 @@ class iface():
logger.info('}') logger.info('}')
def dump_pretty(self, with_status=False, def dump_pretty(self, with_status=False,
successstr='success', errorstr='error'): successstr='success', errorstr='error',
use_realname=False):
indent = '\t' indent = '\t'
outbuf = '' outbuf = ''
if self.auto: if use_realname:
outbuf += 'auto %s\n' %self.name name = self.realname
if self.type == ifaceType.BRIDGE_VLAN:
outbuf += 'vlan %s' %self.name
else: else:
outbuf += 'iface %s' %self.name name = self.name
if self.auto:
outbuf += 'auto %s\n' %name
if self.type == ifaceType.BRIDGE_VLAN:
outbuf += 'vlan %s' %name
else:
outbuf += 'iface %s' %name
if self.addr_family: if self.addr_family:
outbuf += ' %s' %self.addr_family outbuf += ' %s' %self.addr_family
if self.addr_method: if self.addr_method:

View File

@@ -165,6 +165,8 @@ class ifupdownMain(ifupdownBase):
self.config = config self.config = config
self.logger.debug(self.config) self.logger.debug(self.config)
self.type = ifaceType.UNKNOWN
# Can be used to provide hints for caching # Can be used to provide hints for caching
self.CACHE_FLAGS = 0x0 self.CACHE_FLAGS = 0x0
self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
@@ -348,7 +350,7 @@ class ifupdownMain(ifupdownBase):
for d in del_list: for d in del_list:
dlist.remove(d) dlist.remove(d)
def query_dependents(self, ifaceobj, ops, ifacenames): def query_dependents(self, ifaceobj, ops, ifacenames, type=None):
""" Gets iface dependents by calling into respective modules """ """ Gets iface dependents by calling into respective modules """
ret_dlist = [] ret_dlist = []
@@ -742,8 +744,17 @@ class ifupdownMain(ifupdownBase):
traceback.print_tb(t) traceback.print_tb(t)
self.logger.warning('error saving state (%s)' %str(e)) self.logger.warning('error saving state (%s)' %str(e))
def set_type(self, type):
if type == 'iface':
self.type = ifaceType.IFACE
elif type == 'vlan':
self.type = ifaceType.BRIDGE_VLAN
else:
self.type = ifaceType.UNKNOWN
def up(self, ops, auto=False, allow_classes=None, ifacenames=None, def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
excludepats=None, printdependency=None, syntaxcheck=False): excludepats=None, printdependency=None, syntaxcheck=False,
type=None):
"""This brings the interface(s) up """This brings the interface(s) up
Args: Args:
@@ -758,6 +769,8 @@ class ifupdownMain(ifupdownBase):
syntaxcheck (bool): only perform syntax check syntaxcheck (bool): only perform syntax check
""" """
self.set_type(type)
if allow_classes: if allow_classes:
self.IFACE_CLASS = True self.IFACE_CLASS = True
if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
@@ -800,9 +813,12 @@ class ifupdownMain(ifupdownBase):
self._save_state() self._save_state()
def down(self, ops, auto=False, allow_classes=None, ifacenames=None, def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
excludepats=None, printdependency=None, usecurrentconfig=False): excludepats=None, printdependency=None, usecurrentconfig=False,
type=None):
""" down an interface """ """ down an interface """
self.set_type(type)
if allow_classes: if allow_classes:
self.IFACE_CLASS = True self.IFACE_CLASS = True
if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
@@ -858,9 +874,11 @@ class ifupdownMain(ifupdownBase):
def query(self, ops, auto=False, allow_classes=None, ifacenames=None, def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
excludepats=None, printdependency=None, excludepats=None, printdependency=None,
format='native'): format='native', type=None):
""" query an interface """ """ query an interface """
self.set_type(type)
if allow_classes: if allow_classes:
self.IFACE_CLASS = True self.IFACE_CLASS = True
if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate': if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
@@ -902,8 +920,6 @@ class ifupdownMain(ifupdownBase):
raise Exception('no ifaces found matching ' + raise Exception('no ifaces found matching ' +
'given allow lists') 'given allow lists')
# Roopa
#self.populate_dependency_info(ops, filtered_ifacenames)
self.populate_dependency_info(ops) self.populate_dependency_info(ops)
if ops[0] == 'query-dependency' and printdependency: if ops[0] == 'query-dependency' and printdependency:
self.print_dependency(filtered_ifacenames, printdependency) self.print_dependency(filtered_ifacenames, printdependency)
@@ -925,16 +941,87 @@ class ifupdownMain(ifupdownBase):
self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format) self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
return return
def reload(self, upops, downops, auto=False, allow=None, def _reload_currentlyup(self, upops, downops, auto=True, allow=None,
ifacenames=None, excludepats=None, usecurrentconfig=False): ifacenames=None, excludepats=None, usecurrentconfig=False,
""" reload interface config """ **extra_args):
""" reload currently up interfaces """
allow_classes = [] allow_classes = []
new_ifaceobjdict = {} new_ifaceobjdict = {}
self.logger.debug('reloading interface config ..') # Override auto to true
if auto: auto = True
self.ALL = True
self.WITH_DEPENDS = True try:
self.read_iface_config()
except:
raise
if not self.ifaceobjdict:
self.logger.warn("nothing to reload ..exiting.")
return
already_up_ifacenames = []
# generate dependency graph of interfaces
self.populate_dependency_info(upops)
if (not usecurrentconfig and self.STATEMANAGER_ENABLE
and self.statemanager.ifaceobjdict):
already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
if not ifacenames: ifacenames = self.ifaceobjdict.keys()
filtered_ifacenames = [i for i in ifacenames
if self._iface_whitelisted(auto, allow_classes,
excludepats, i)]
# Get already up interfaces that still exist in the interfaces file
already_up_ifacenames_not_present = Set(
already_up_ifacenames).difference(ifacenames)
already_up_ifacenames_still_present = Set(
already_up_ifacenames).difference(
already_up_ifacenames_not_present)
interfaces_to_up = Set(already_up_ifacenames_still_present).union(
filtered_ifacenames)
if (already_up_ifacenames_not_present and
self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
self.logger.info('reload: schedule down on interfaces: %s'
%str(already_up_ifacenames_not_present))
# Save a copy of new iface objects and dependency_graph
new_ifaceobjdict = dict(self.ifaceobjdict)
new_dependency_graph = dict(self.dependency_graph)
# old interface config is read into self.ifaceobjdict
self.read_old_iface_config()
# reinitialize dependency graph
self.dependency_graph = OrderedDict({})
self.populate_dependency_info(downops,
already_up_ifacenames_not_present)
self._sched_ifaces(already_up_ifacenames_not_present, downops)
else:
self.logger.debug('no interfaces to down ..')
# Now, run 'up' with new config dict
# reset statemanager update flag to default
if new_ifaceobjdict:
self.ifaceobjdict = new_ifaceobjdict
self.dependency_graph = new_dependency_graph
if not self.ifaceobjdict:
return
self.logger.info('reload: scheduling up on interfaces: %s'
%str(interfaces_to_up))
self._sched_ifaces(interfaces_to_up, upops)
if self.DRYRUN:
return
self._save_state()
def _reload_default(self, upops, downops, auto=False, allow=None,
ifacenames=None, excludepats=None, usecurrentconfig=False,
**extra_args):
""" reload interface config """
allow_classes = []
new_ifaceobjdict = {}
try: try:
self.read_iface_config() self.read_iface_config()
@@ -975,7 +1062,8 @@ class ifupdownMain(ifupdownBase):
# config # config
# #
ifacedownlist = [] ifacedownlist = []
for ifname, lastifaceobjlist in self.ifaceobjdict.items(): for ifname in filtered_ifacenames:
lastifaceobjlist = self.ifaceobjdict.get(ifname)
objidx = 0 objidx = 0
# If interface is not present in the new file # If interface is not present in the new file
# append it to the down list # append it to the down list
@@ -997,7 +1085,7 @@ class ifupdownMain(ifupdownBase):
continue continue
if ifacedownlist: if ifacedownlist:
self.logger.info('Executing down on interfaces: %s' self.logger.info('reload: scheduling down on interfaces: %s'
%str(ifacedownlist)) %str(ifacedownlist))
# reinitialize dependency graph # reinitialize dependency graph
self.dependency_graph = OrderedDict({}) self.dependency_graph = OrderedDict({})
@@ -1018,13 +1106,25 @@ class ifupdownMain(ifupdownBase):
if self._iface_whitelisted(auto, allow_classes, if self._iface_whitelisted(auto, allow_classes,
excludepats, i)] excludepats, i)]
self.logger.info('Scheduling up on interfaces: %s' self.logger.info('reload: scheduling up on interfaces: %s'
%str(filtered_ifacenames)) %str(filtered_ifacenames))
self._sched_ifaces(filtered_ifacenames, upops) self._sched_ifaces(filtered_ifacenames, upops)
if self.DRYRUN: if self.DRYRUN:
return return
self._save_state() self._save_state()
def reload(self, *args, **kargs):
""" reload interface config """
if kargs.get('auto', False):
self.ALL = True
self.WITH_DEPENDS = True
self.logger.debug('reloading interface config ..')
if kargs.get('currentlyup', False):
self._reload_currentlyup(*args, **kargs)
else:
self._reload_default(*args, **kargs)
def _pretty_print_ordered_dict(self, prefix, argdict): def _pretty_print_ordered_dict(self, prefix, argdict):
outbuf = prefix + ' {\n' outbuf = prefix + ' {\n'
for k, vlist in argdict.items(): for k, vlist in argdict.items():
@@ -1085,7 +1185,14 @@ class ifupdownMain(ifupdownBase):
print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
indent=4, separators=(',', ': ')) indent=4, separators=(',', ': '))
else: else:
map(lambda i: i.dump_pretty(), ifaceobjs) expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
for i in ifaceobjs:
if not expand and (i.flags & iface.IFACERANGE_ENTRY):
# print only the first one
if i.flags & iface.IFACERANGE_START:
i.dump_pretty(use_realname=True)
else:
i.dump_pretty()
def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs): def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
ret = 0 ret = 0
@@ -1122,9 +1229,9 @@ class ifupdownMain(ifupdownBase):
separators=(',', ': ')) separators=(',', ': '))
else: else:
map(lambda i: i.dump_pretty(with_status=True, map(lambda i: i.dump_pretty(with_status=True,
successstr=self.config.get('check_success_str', successstr=self.config.get('ifquery_check_success_str',
_success_sym), _success_sym),
errorstr=self.config.get('check_error_str', _error_sym)), errorstr=self.config.get('ifquery_check_error_str', _error_sym)),
ifaceobjs) ifaceobjs)
return ret return ret

View File

@@ -266,8 +266,11 @@ class networkInterfaces():
if range_val: if range_val:
for v in range(range_val[1], range_val[2]): for v in range(range_val[1], range_val[2]):
ifaceobj_new = copy.deepcopy(ifaceobj) ifaceobj_new = copy.deepcopy(ifaceobj)
ifaceobj_new.real_name = ifaceobj.name ifaceobj_new.realname = ifaceobj.name
ifaceobj_new.name = "%s%d" %(range_val[0], v) ifaceobj_new.name = "%s%d" %(range_val[0], v)
ifaceobj_new.flags |= iface.IFACERANGE_ENTRY
if v == range_val[1]:
ifaceobj_new.flags |= iface.IFACERANGE_START
self.callbacks.get('iface_found')(ifaceobj_new) self.callbacks.get('iface_found')(ifaceobj_new)
else: else:
self.callbacks.get('iface_found')(ifaceobj) self.callbacks.get('iface_found')(ifaceobj)
@@ -282,9 +285,12 @@ class networkInterfaces():
if range_val: if range_val:
for v in range(range_val[1], range_val[2]): for v in range(range_val[1], range_val[2]):
ifaceobj_new = copy.deepcopy(ifaceobj) ifaceobj_new = copy.deepcopy(ifaceobj)
ifaceobj_new.real_name = ifaceobj.name ifaceobj_new.realname = ifaceobj.name
ifaceobj_new.name = "%s%d" %(range_val[0], v) ifaceobj_new.name = "%s%d" %(range_val[0], v)
ifaceobj_new.type = ifaceType.BRIDGE_VLAN ifaceobj_new.type = ifaceType.BRIDGE_VLAN
ifaceobj_new.flags |= iface.IFACERANGE_ENTRY
if v == range_val[1]:
ifaceobj_new.flags |= iface.IFACERANGE_START
self.callbacks.get('iface_found')(ifaceobj_new) self.callbacks.get('iface_found')(ifaceobj_new)
else: else:
ifaceobj.type = ifaceType.BRIDGE_VLAN ifaceobj.type = ifaceType.BRIDGE_VLAN

View File

@@ -43,6 +43,9 @@ class ifaceScheduler():
""" Runs sub operation on an interface """ """ Runs sub operation on an interface """
ifacename = ifaceobj.name ifacename = ifaceobj.name
if ifupdownobj.type and ifupdownobj.type != ifaceobj.Type:
return
if (cls._STATE_CHECK and if (cls._STATE_CHECK and
(ifaceobj.state >= ifaceState.from_str(op))): (ifaceobj.state >= ifaceState.from_str(op))):
ifupdownobj.logger.debug('%s: already in state %s' %(ifacename, op)) ifupdownobj.logger.debug('%s: already in state %s' %(ifacename, op))
@@ -151,27 +154,6 @@ class ifaceScheduler():
not ifupdownobj.ALL)): not ifupdownobj.ALL)):
return True return True
if ifaceobj.type == ifaceType.BRIDGE:
#
# XXX: This function's job is to return True for
# logical devices when any of the upperifaces are still around.
# In the new model, where bridge is represented as a dependency
# for a bridge port, bridge becomes a lowerdevice of a bridge port,
# which is not really true. To handle this case, add a special
# check for bridge device. Will figure out a better way to handle
# this.
# Long term this function should be replaced by
# walking the sysfs links to upper and lower device available in
# latest kernels.
try:
if os.listdir('/sys/class/net/%s/brif' %ifaceobj.name):
return False
else:
return True
except Exception:
pass
return True
ulist = ifaceobj.upperifaces ulist = ifaceobj.upperifaces
if not ulist: if not ulist:
return True return True

View File

@@ -320,3 +320,13 @@ class moduleBase(object):
return dict(force=self.FORCE, dryrun=self.DRYRUN, nowait=self.NOWAIT, return dict(force=self.FORCE, dryrun=self.DRYRUN, nowait=self.NOWAIT,
perfmode=self.PERFMODE, cache=self.CACHE, perfmode=self.PERFMODE, cache=self.CACHE,
cacheflags=self.CACHE_FLAGS) cacheflags=self.CACHE_FLAGS)
def _get_reserved_vlan_range(self):
start = end = 0
get_resvvlan = '/usr/share/python-ifupdown2/get_reserved_vlan_range.sh'
try:
(start, end) = self.exec_command(get_resvvlan).split('-')
except:
# ignore errors
pass
return (start, end)

View File

@@ -51,13 +51,13 @@ def run_up(args):
ifupdown_handle.up(['up'], args.all, args.CLASS, iflist, ifupdown_handle.up(['up'], args.all, args.CLASS, iflist,
excludepats=args.excludepats, excludepats=args.excludepats,
printdependency=args.printdependency, printdependency=args.printdependency,
syntaxcheck=args.syntaxcheck) syntaxcheck=args.syntaxcheck, type=args.type)
else: else:
ifupdown_handle.up(['pre-up', 'up', 'post-up'], ifupdown_handle.up(['pre-up', 'up', 'post-up'],
args.all, args.CLASS, iflist, args.all, args.CLASS, iflist,
excludepats=args.excludepats, excludepats=args.excludepats,
printdependency=args.printdependency, printdependency=args.printdependency,
syntaxcheck=args.syntaxcheck) syntaxcheck=args.syntaxcheck, type=args.type)
except: except:
raise raise
@@ -81,7 +81,8 @@ def run_down(args):
args.all, args.CLASS, iflist, args.all, args.CLASS, iflist,
excludepats=args.excludepats, excludepats=args.excludepats,
printdependency=args.printdependency, printdependency=args.printdependency,
usecurrentconfig=args.usecurrentconfig) usecurrentconfig=args.usecurrentconfig,
type=args.type)
except: except:
raise raise
@@ -123,7 +124,7 @@ def run_query(args):
ifupdown_handle.query([qop], args.all, args.CLASS, iflist, ifupdown_handle.query([qop], args.all, args.CLASS, iflist,
excludepats=args.excludepats, excludepats=args.excludepats,
printdependency=args.printdependency, printdependency=args.printdependency,
format=args.format) format=args.format, type=args.type)
except: except:
raise raise
@@ -139,7 +140,8 @@ def run_reload(args):
['pre-down', 'down', 'post-down'], ['pre-down', 'down', 'post-down'],
args.all, None, None, args.all, None, None,
excludepats=args.excludepats, excludepats=args.excludepats,
usecurrentconfig=args.usecurrentconfig) usecurrentconfig=args.usecurrentconfig,
currentlyup=args.currentlyup)
except: except:
raise raise
@@ -226,6 +228,13 @@ def update_argparser(argparser):
default='native', default='native',
choices=['native', 'json'], choices=['native', 'json'],
help='interfaces file format') help='interfaces file format')
argparser.add_argument('-T', '--type',
dest='type',
default=None,
choices=['iface', 'vlan'],
help='type of interface entry (iface or vlan).' +
'This option can be used in case of ambiguity between ' +
'a vlan interface and an iface interface of the same name')
def update_ifupdown_argparser(argparser): def update_ifupdown_argparser(argparser):
""" common arg parser for ifup and ifdown """ """ common arg parser for ifup and ifdown """
@@ -294,8 +303,13 @@ def update_ifquery_argparser(argparser):
def update_ifreload_argparser(argparser): def update_ifreload_argparser(argparser):
""" parser for ifreload """ """ parser for ifreload """
argparser.add_argument('-a', '--all', action='store_true', required=True, group = argparser.add_mutually_exclusive_group(required=True)
group.add_argument('-a', '--all', action='store_true',
help='process all interfaces marked \"auto\"') help='process all interfaces marked \"auto\"')
group.add_argument('-c', '--currently-up', dest='currentlyup',
action='store_true',
help='only reload auto and other interfaces that are ' +
'currently up')
argparser.add_argument('iflist', metavar='IFACE', argparser.add_argument('iflist', metavar='IFACE',
nargs='*', help=argparse.SUPPRESS) nargs='*', help=argparse.SUPPRESS)
argparser.add_argument('-n', '--no-act', dest='noact', argparser.add_argument('-n', '--no-act', dest='noact',
@@ -367,8 +381,8 @@ def validate_args(op, args):
if op == 'query' and args.syntaxhelp: if op == 'query' and args.syntaxhelp:
return True return True
if op == 'reload': if op == 'reload':
if not args.all: if not args.all and not args.currentlyup:
print '\'-a\' option is required' print '\'-a\' or \'-c\' option is required'
return False return False
elif (not args.iflist and elif (not args.iflist and
not args.all and not args.CLASS): not args.all and not args.CLASS):