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:
@@ -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)
|
||||||
|
|
||||||
|
@@ -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)
|
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
|
||||||
|
@@ -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:
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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):
|
||||||
|
Reference in New Issue
Block a user