mirror of
https://github.com/CumulusNetworks/ifupdown2.git
synced 2024-05-06 15:54:50 +00:00
First phase checkin for new format for vlan aware bridge
Ticket: CM-3346 Reviewed By: Testing Done: Sanity test + test new bridge format There are a bunch of open issues with `vlan` interface handling. Below is the format. auto swp1 iface swp1 bridge-access 300 mstpctl-pathcost 0 mstpctl-adminedge yes mstpctl-autoedge yes mstpctl-p2p yes mstpctl-bpduguard yes mstpctl-treeprio 64 mstpctl-network yes mstpctl-bpdufilter yes auto swp2 iface swp2 bridge-vids 301 bridge-pvid 302 bridge-pathcost 10 bridge-priority 10 bridge-multicast-router 0 bridge-multicast-fast-leave 1 auto br0 iface br0 bridge-vlan-aware yes bridge-stp on bridge-ports swp1 swp2 bridge-vids 2001 auto br0.2001 iface br0.2001 address 10.0.14.2 hwaddress 00:03:00:00:00:12 address-virtual 00:00:5e:00:01:01 11.0.4.1/24 auto br0.2001 vlan br0.2001 bridge-igmp-querier-src 172.16.101.1
This commit is contained in:
@@ -265,7 +265,7 @@ class address(moduleBase):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run address configuration on the interface object passed as argument
|
||||
|
||||
Args:
|
||||
|
@@ -147,7 +147,7 @@ class addressvirtual(moduleBase):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run vlan configuration on the interface object passed as argument
|
||||
|
||||
Args:
|
||||
@@ -163,6 +163,8 @@ class addressvirtual(moduleBase):
|
||||
of interfaces. status is success if the running state is same
|
||||
as user required state in ifaceobj. error otherwise.
|
||||
"""
|
||||
if ifaceobj.type == ifaceType.BRIDGE_VLAN:
|
||||
return
|
||||
op_handler = self._run_ops.get(operation)
|
||||
if not op_handler:
|
||||
return
|
||||
|
462
addons/bridge.py
462
addons/bridge.py
@@ -18,6 +18,9 @@ class bridge(moduleBase):
|
||||
|
||||
_modinfo = { 'mhelp' : 'bridge configuration module',
|
||||
'attrs' : {
|
||||
'bridge-vlan-aware' :
|
||||
{'help' : 'bridge vlan aware',
|
||||
'example' : ['bridge-vlan-aware yes/no']},
|
||||
'bridge-ports' :
|
||||
{'help' : 'bridge ports',
|
||||
'required' : True,
|
||||
@@ -152,24 +155,52 @@ class bridge(moduleBase):
|
||||
'bridge-vids' :
|
||||
{ 'help' : 'bridge vlans',
|
||||
'example' : ['bridge-vids 4000']},
|
||||
'bridge-pvid' :
|
||||
{ 'help' : 'bridge vlans',
|
||||
'example' : ['bridge-pvid 1']},
|
||||
'bridge-access' :
|
||||
{ 'help' : 'bridge access vlans',
|
||||
'example' : ['bridge-access 300']},
|
||||
'bridge-port-vids' :
|
||||
{ 'help' : 'bridge vlans',
|
||||
'example' : ['bridge-port-vids bond0=1-1000,1010-1020']},
|
||||
'bridge-port-pvids' :
|
||||
{ 'help' : 'bridge port vlans',
|
||||
'example' : ['bridge-port-pvids bond0=100 bond1=200']},
|
||||
'bridge-pathcost' :
|
||||
{ 'help' : 'bridge port path cost',
|
||||
'example' : ['bridge-pathcost 10']},
|
||||
'bridge-priority' :
|
||||
{ 'help' : 'bridge port priority',
|
||||
'example' : ['bridge-priority 10']},
|
||||
'bridge-multicast-router' :
|
||||
{ 'help' : 'bridge multicast router',
|
||||
'example' : ['bridge-multicast-router 1']},
|
||||
'bridge-multicast-fast-leave' :
|
||||
{ 'help' : 'bridge multicast fast leave',
|
||||
'example' : ['bridge-multicast-fast-leave 1']},
|
||||
'bridge-igmp-querier-src' :
|
||||
{ 'help' : 'bridge igmp querier src',
|
||||
'example' : ['bridge-igmp-querier-src 172.16.101.1']},
|
||||
}}
|
||||
|
||||
def __init__(self, *args, **kargs):
|
||||
moduleBase.__init__(self, *args, **kargs)
|
||||
self.ipcmd = None
|
||||
self.brctlcmd = None
|
||||
self._running_vidinfo = {}
|
||||
self._running_vidinfo_valid = False
|
||||
|
||||
def _is_bridge(self, ifaceobj):
|
||||
if ifaceobj.get_attr_value_first('bridge-ports'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _is_bridge_port(self, ifaceobj):
|
||||
if self.brctlcmd.is_bridge_port(ifaceobj.name):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
|
||||
if not self._is_bridge(ifaceobj):
|
||||
return None
|
||||
@@ -332,7 +363,10 @@ class bridge(moduleBase):
|
||||
else:
|
||||
return True
|
||||
|
||||
def _set_bridge_mcqv4src(self, ifaceobj):
|
||||
def _set_bridge_mcqv4src_compat(self, ifaceobj):
|
||||
#
|
||||
# Sets old style igmp querier
|
||||
#
|
||||
attrval = ifaceobj.get_attr_value_first('bridge-mcqv4src')
|
||||
if attrval:
|
||||
running_mcqv4src = {}
|
||||
@@ -349,12 +383,52 @@ class bridge(moduleBase):
|
||||
self.brctlcmd.del_mcqv4src(ifaceobj.name, v)
|
||||
for v in mcqs.keys():
|
||||
self.brctlcmd.set_mcqv4src(ifaceobj.name, v, mcqs[v])
|
||||
|
||||
def _set_bridge_vidinfo(self, ifaceobj):
|
||||
# Handle bridge vlan attrs
|
||||
running_vidinfo = {}
|
||||
|
||||
def _get_running_vidinfo(self):
|
||||
if self._running_vidinfo_valid:
|
||||
return self._running_vidinfo
|
||||
self._running_vidinfo = {}
|
||||
if not self.PERFMODE:
|
||||
running_vidinfo = self.ipcmd.bridge_port_vids_get_all()
|
||||
self._running_vidinfo = self.ipcmd.bridge_port_vids_get_all()
|
||||
self._running_vidinfo_valid = True
|
||||
return self._running_vidinfo
|
||||
|
||||
def _flush_running_vidinfo(self):
|
||||
self._running_vidinfo = {}
|
||||
self._running_vidinfo_valid = False
|
||||
|
||||
def _set_bridge_vidinfo_compat(self, ifaceobj):
|
||||
#
|
||||
# Supports old style vlan vid info format
|
||||
# for compatibility
|
||||
#
|
||||
|
||||
# Handle bridge vlan attrs
|
||||
running_vidinfo = self._get_running_vidinfo()
|
||||
|
||||
# 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
|
||||
for p in portlist:
|
||||
try:
|
||||
(port, pvid) = p.split('=')
|
||||
running_pvid = running_vidinfo.get(port, {}).get('pvid')
|
||||
if running_pvid:
|
||||
if running_pvid == pvid:
|
||||
continue
|
||||
else:
|
||||
self.ipcmd.bridge_port_pvid_del(port, running_pvid)
|
||||
self.ipcmd.bridge_port_pvid_add(port, pvid)
|
||||
except Exception, e:
|
||||
self.log_warn('%s: failed to set pvid `%s` (%s)'
|
||||
%(ifaceobj.name, p, str(e)))
|
||||
|
||||
# install port vids
|
||||
attrval = ifaceobj.get_attr_value_first('bridge-port-vids')
|
||||
if attrval:
|
||||
portlist = self.parse_port_list(attrval)
|
||||
@@ -380,28 +454,7 @@ class bridge(moduleBase):
|
||||
self.log_warn('%s: failed to set vid `%s` (%s)'
|
||||
%(ifaceobj.name, p, str(e)))
|
||||
|
||||
# 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
|
||||
for p in portlist:
|
||||
try:
|
||||
(port, pvid) = p.split('=')
|
||||
running_pvid = running_vidinfo.get(port, {}).get('pvid')
|
||||
if running_pvid:
|
||||
if running_pvid == pvid:
|
||||
continue
|
||||
else:
|
||||
self.ipcmd.bridge_port_pvid_del(port, running_pvid)
|
||||
self.ipcmd.bridge_port_pvid_add(port, pvid)
|
||||
except Exception, e:
|
||||
self.log_warn('%s: failed to set pvid `%s` (%s)'
|
||||
%(ifaceobj.name, p, str(e)))
|
||||
|
||||
# install vids
|
||||
attrval = ifaceobj.get_attr_value_first('bridge-vids')
|
||||
if attrval:
|
||||
vids = re.split(r'[\s\t]\s*', attrval)
|
||||
@@ -501,16 +554,162 @@ class bridge(moduleBase):
|
||||
for port, attrdict in portattrs.iteritems():
|
||||
self.brctlcmd.set_bridgeport_attrs(ifaceobj.name, port,
|
||||
attrdict)
|
||||
self._set_bridge_vidinfo(ifaceobj)
|
||||
self._set_bridge_vidinfo_compat(ifaceobj)
|
||||
|
||||
self._set_bridge_mcqv4src(ifaceobj)
|
||||
self._set_bridge_mcqv4src_compat(ifaceobj)
|
||||
|
||||
self._process_bridge_maxwait(ifaceobj,
|
||||
self._get_bridge_port_list(ifaceobj))
|
||||
except Exception, e:
|
||||
self.log_warn(str(e))
|
||||
|
||||
def _up(self, ifaceobj):
|
||||
def _apply_bridge_vids(self, bportifaceobj, vids, running_vids, isbridge):
|
||||
try:
|
||||
if running_vids:
|
||||
(vids_to_del, vids_to_add) = \
|
||||
self._diff_vids(vids, running_vids)
|
||||
if vids_to_del:
|
||||
self.ipcmd.bridge_vids_del(bportifaceobj.name,
|
||||
vids_to_del, isbridge)
|
||||
if vids_to_add:
|
||||
self.ipcmd.bridge_vids_add(bportifaceobj.name,
|
||||
vids_to_add, isbridge)
|
||||
else:
|
||||
self.ipcmd.bridge_vids_add(bportifaceobj.name, vids, isbridge)
|
||||
except Exception, e:
|
||||
self.log_warn('%s: failed to set vid `%s` (%s)'
|
||||
%(bportifaceobj.name, str(vids), str(e)))
|
||||
|
||||
def _apply_bridge_port_pvids(self, bportifaceobj, pvid, running_pvid):
|
||||
# Install pvids
|
||||
try:
|
||||
if running_pvid:
|
||||
if running_pvid != pvid:
|
||||
self.ipcmd.bridge_port_pvid_del(bportifaceobj.name,
|
||||
running_pvid)
|
||||
self.ipcmd.bridge_port_pvid_add(bportifaceobj.name, pvid)
|
||||
except Exception, e:
|
||||
self.log_warn('%s: failed to set pvid `%s` (%s)'
|
||||
%(bportifaceobj.name, pvid, str(e)))
|
||||
|
||||
def _apply_bridge_vlan_aware_port_settings_all(self, bportifaceobj,
|
||||
bridge_vids):
|
||||
running_vidinfo = self._get_running_vidinfo()
|
||||
vids = None
|
||||
pvids = None
|
||||
bport_access = bportifaceobj.get_attr_value_first('bridge-access')
|
||||
if bport_access:
|
||||
vids = re.split(r'[\s\t]\s*', bport_access)
|
||||
pvids = vids
|
||||
|
||||
bport_vids = bportifaceobj.get_attr_value_first('bridge-vids')
|
||||
if bport_vids:
|
||||
vids = re.split(r'[\s\t]\s*', bport_vids)
|
||||
|
||||
bport_pvids = bportifaceobj.get_attr_value_first('bridge-pvid')
|
||||
if bport_pvids:
|
||||
pvids = re.split(r'[\s\t]\s*', bport_pvids)
|
||||
|
||||
if pvids:
|
||||
self._apply_bridge_port_pvids(bportifaceobj, pvids[0],
|
||||
running_vidinfo.get(bportifaceobj.name, {}).get('pvid'))
|
||||
else:
|
||||
self._apply_bridge_port_pvids(bportifaceobj,
|
||||
'1', running_vidinfo.get(bportifaceobj.name,
|
||||
{}).get('pvid'))
|
||||
|
||||
if vids:
|
||||
self._apply_bridge_vids(bportifaceobj, vids,
|
||||
running_vidinfo.get(bportifaceobj.name,
|
||||
{}).get('vlan'), False)
|
||||
elif bridge_vids:
|
||||
self._apply_bridge_vids(bportifaceobj,
|
||||
bridge_vids, running_vidinfo.get(
|
||||
bportifaceobj.name, {}).get('vlan'), False)
|
||||
|
||||
|
||||
def _apply_bridge_port_settings(self, bportifaceobj, bridgename=None,
|
||||
bridgeifaceobj=None):
|
||||
if not bridgename and bridgeifaceobj:
|
||||
bridgename = bridgeifaceobj.name
|
||||
# Set other stp and igmp attributes
|
||||
portattrs = {}
|
||||
for attrname, dstattrname in {
|
||||
'bridge-pathcost' : 'pathcost',
|
||||
'bridge-prio' : 'portprio',
|
||||
'bridge-priority' : 'portprio',
|
||||
'bridge-mcrouter' : 'portmcrouter',
|
||||
'bridge-multicast-router' : 'portmcrouter',
|
||||
'bridge-multicast-fast-leave' : 'portmcfl'}.items():
|
||||
attrval = bportifaceobj.get_attr_value_first(attrname)
|
||||
if not attrval:
|
||||
# Check if bridge has that attribute
|
||||
if bridgeifaceobj:
|
||||
attrval = bridgeifaceobj.get_attr_value_first(attrname)
|
||||
if not attrval:
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
portattrs[dstattrname] = attrval
|
||||
try:
|
||||
self.brctlcmd.set_bridgeport_attrs(bridgename,
|
||||
bportifaceobj.name, portattrs)
|
||||
except Exception, e:
|
||||
self.log_warn(str(e))
|
||||
|
||||
def _apply_bridge_port_settings_all(self, ifaceobj,
|
||||
ifaceobj_getfunc=None):
|
||||
bridge_vlan_aware = ifaceobj.get_attr_value_first(
|
||||
'bridge-vlan-aware')
|
||||
if bridge_vlan_aware and bridge_vlan_aware == 'yes':
|
||||
bridge_vlan_aware = True
|
||||
else:
|
||||
bridge_vlan_aware = False
|
||||
|
||||
if (ifaceobj.get_attr_value_first('bridge-port-vids') and
|
||||
ifaceobj.get_attr_value_first('bridge-port-pvids')):
|
||||
# Old style bridge port vid info
|
||||
# skip new style setting on ports
|
||||
return
|
||||
self.logger.info('%s: applying bridge configuration '
|
||||
%ifaceobj.name + 'specific to ports')
|
||||
|
||||
bridge_vids = ifaceobj.get_attr_value_first('bridge-vids')
|
||||
if bridge_vids:
|
||||
bridge_vids = re.split(r'[\s\t]\s*', bridge_vids)
|
||||
else:
|
||||
bridge_vids = None
|
||||
|
||||
bridgeports = self._get_bridge_port_list(ifaceobj)
|
||||
for bport in bridgeports:
|
||||
# Use the brctlcmd bulk set method: first build a dictionary
|
||||
# and then call set
|
||||
self.logger.info('%s: processing bridge config for port %s'
|
||||
%(ifaceobj.name, bport))
|
||||
bportifaceobjlist = ifaceobj_getfunc(bport)
|
||||
if not bportifaceobjlist:
|
||||
continue
|
||||
for bportifaceobj in bportifaceobjlist:
|
||||
# Add attributes specific to the vlan aware bridge
|
||||
if bridge_vlan_aware:
|
||||
self._apply_bridge_vlan_aware_port_settings_all(
|
||||
bportifaceobj, bridge_vids)
|
||||
self._apply_bridge_port_settings(
|
||||
bportifaceobj, bridgeifaceobj=ifaceobj)
|
||||
|
||||
def _up(self, ifaceobj, ifaceobj_getfunc=None):
|
||||
# Check if bridge port
|
||||
if self._is_bridge_port(ifaceobj):
|
||||
bridgename = ifaceobj.upperifaces[0]
|
||||
if not bridgename:
|
||||
self.logger.warn('%s: unable to determine bridge name'
|
||||
%ifaceobj.name)
|
||||
return
|
||||
self._apply_bridge_port_settings(ifaceobj, bridgename=bridgename)
|
||||
return
|
||||
|
||||
if not self._is_bridge(ifaceobj):
|
||||
return
|
||||
try:
|
||||
porterr = False
|
||||
porterrstr = ''
|
||||
@@ -529,12 +728,15 @@ class bridge(moduleBase):
|
||||
finally:
|
||||
self.ipcmd.batch_commit()
|
||||
self._apply_bridge_settings(ifaceobj)
|
||||
self._apply_bridge_port_settings_all(ifaceobj,
|
||||
ifaceobj_getfunc=ifaceobj_getfunc)
|
||||
self._flush_running_vidinfo()
|
||||
except Exception, e:
|
||||
self.log_error(str(e))
|
||||
if porterr:
|
||||
raise Exception(porterrstr)
|
||||
|
||||
def _down(self, ifaceobj):
|
||||
def _down(self, ifaceobj, ifaceobj_getfunc=None):
|
||||
try:
|
||||
if ifaceobj.get_attr_value_first('bridge-ports'):
|
||||
ports = self.brctlcmd.get_bridge_ports(ifaceobj.name)
|
||||
@@ -549,8 +751,7 @@ class bridge(moduleBase):
|
||||
|
||||
def _query_running_vidinfo(self, ifaceobjrunning, ports):
|
||||
running_attrs = {}
|
||||
running_vidinfo = self.ipcmd.bridge_port_vids_get_all()
|
||||
|
||||
running_vidinfo = self._get_running_vidinfo()
|
||||
if ports:
|
||||
running_bridge_port_vids = ''
|
||||
for p in ports:
|
||||
@@ -574,7 +775,8 @@ class bridge(moduleBase):
|
||||
pass
|
||||
running_attrs['bridge-port-pvids'] = running_bridge_port_pvids
|
||||
|
||||
running_bridge_vids = running_vidinfo.get(ifaceobjrunning.name, {}).get('vlan')
|
||||
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
|
||||
@@ -749,101 +951,103 @@ class bridge(moduleBase):
|
||||
ifaceobjcurr.update_config_with_status('bridge-vids', attrval,
|
||||
1)
|
||||
|
||||
def _query_check(self, ifaceobj, ifaceobjcurr):
|
||||
if not self.brctlcmd.bridge_exists(ifaceobj.name):
|
||||
self.logger.info('%s: bridge: does not exist' %(ifaceobj.name))
|
||||
ifaceobjcurr.status = ifaceStatus.NOTFOUND
|
||||
return
|
||||
ifaceattrs = self.dict_key_subset(ifaceobj.config,
|
||||
self.get_mod_attrs())
|
||||
if not ifaceattrs:
|
||||
return
|
||||
try:
|
||||
runningattrs = self.brctlcmd.get_bridge_attrs(ifaceobj.name)
|
||||
if not runningattrs:
|
||||
self.logger.debug('%s: bridge: unable to get bridge attrs'
|
||||
%ifaceobj.name)
|
||||
runningattrs = {}
|
||||
except Exception, e:
|
||||
self.logger.warn(str(e))
|
||||
runningattrs = {}
|
||||
filterattrs = ['bridge-vids', 'bridge-port-vids',
|
||||
'bridge-port-pvids']
|
||||
for k in Set(ifaceattrs).difference(filterattrs):
|
||||
# get the corresponding ifaceobj attr
|
||||
v = ifaceobj.get_attr_value_first(k)
|
||||
if not v:
|
||||
continue
|
||||
rv = runningattrs.get(k[7:])
|
||||
if k == 'bridge-mcqv4src':
|
||||
continue
|
||||
if k == 'bridge-stp':
|
||||
# special case stp compare because it may
|
||||
# contain more than one valid values
|
||||
stp_on_vals = ['on', 'yes']
|
||||
stp_off_vals = ['off']
|
||||
if ((v in stp_on_vals and rv in stp_on_vals) or
|
||||
(v in stp_off_vals and rv in stp_off_vals)):
|
||||
ifaceobjcurr.update_config_with_status('bridge-stp',
|
||||
v, 0)
|
||||
else:
|
||||
ifaceobjcurr.update_config_with_status('bridge-stp',
|
||||
def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):
|
||||
if not self._is_bridge(ifaceobj):
|
||||
return
|
||||
if not self.brctlcmd.bridge_exists(ifaceobj.name):
|
||||
self.logger.info('%s: bridge: does not exist' %(ifaceobj.name))
|
||||
ifaceobjcurr.status = ifaceStatus.NOTFOUND
|
||||
return
|
||||
ifaceattrs = self.dict_key_subset(ifaceobj.config,
|
||||
self.get_mod_attrs())
|
||||
if not ifaceattrs:
|
||||
return
|
||||
try:
|
||||
runningattrs = self.brctlcmd.get_bridge_attrs(ifaceobj.name)
|
||||
if not runningattrs:
|
||||
self.logger.debug('%s: bridge: unable to get bridge attrs'
|
||||
%ifaceobj.name)
|
||||
runningattrs = {}
|
||||
except Exception, e:
|
||||
self.logger.warn(str(e))
|
||||
runningattrs = {}
|
||||
filterattrs = ['bridge-vids', 'bridge-port-vids',
|
||||
'bridge-port-pvids']
|
||||
for k in Set(ifaceattrs).difference(filterattrs):
|
||||
# get the corresponding ifaceobj attr
|
||||
v = ifaceobj.get_attr_value_first(k)
|
||||
if not v:
|
||||
continue
|
||||
rv = runningattrs.get(k[7:])
|
||||
if k == 'bridge-mcqv4src':
|
||||
continue
|
||||
if k == 'bridge-stp':
|
||||
# special case stp compare because it may
|
||||
# contain more than one valid values
|
||||
stp_on_vals = ['on', 'yes']
|
||||
stp_off_vals = ['off']
|
||||
if ((v in stp_on_vals and rv in stp_on_vals) or
|
||||
(v in stp_off_vals and rv in stp_off_vals)):
|
||||
ifaceobjcurr.update_config_with_status('bridge-stp',
|
||||
v, 0)
|
||||
else:
|
||||
ifaceobjcurr.update_config_with_status('bridge-stp',
|
||||
v, 1)
|
||||
elif k == 'bridge-ports':
|
||||
# special case ports because it can contain regex or glob
|
||||
running_port_list = rv.keys() if rv else []
|
||||
bridge_port_list = self._get_bridge_port_list(ifaceobj)
|
||||
if not running_port_list and not bridge_port_list:
|
||||
continue
|
||||
portliststatus = 1
|
||||
if running_port_list and bridge_port_list:
|
||||
difference = set(running_port_list
|
||||
).symmetric_difference(bridge_port_list)
|
||||
if not difference:
|
||||
portliststatus = 0
|
||||
ifaceobjcurr.update_config_with_status('bridge-ports',
|
||||
' '.join(running_port_list)
|
||||
if running_port_list else '', portliststatus)
|
||||
elif (k == 'bridge-pathcosts' or
|
||||
k == 'bridge-portprios' or k == 'bridge-portmcrouter'
|
||||
or k == 'bridge-portmcfl'):
|
||||
brctlcmdattrname = k[11:].rstrip('s')
|
||||
# for port attributes, the attributes are in a list
|
||||
# <portname>=<portattrvalue>
|
||||
status = 0
|
||||
currstr = ''
|
||||
vlist = self.parse_port_list(v)
|
||||
if not vlist:
|
||||
continue
|
||||
for vlistitem in vlist:
|
||||
try:
|
||||
(p, v) = vlistitem.split('=')
|
||||
currv = self.brctlcmd.get_bridgeport_attr(
|
||||
ifaceobj.name, p,
|
||||
brctlcmdattrname)
|
||||
if currv:
|
||||
currstr += ' %s=%s' %(p, currv)
|
||||
else:
|
||||
currstr += ' %s=%s' %(p, 'None')
|
||||
if currv != v:
|
||||
status = 1
|
||||
except Exception, e:
|
||||
self.log_warn(str(e))
|
||||
pass
|
||||
ifaceobjcurr.update_config_with_status(k, currstr, status)
|
||||
elif not rv:
|
||||
ifaceobjcurr.update_config_with_status(k, 'notfound', 1)
|
||||
elif k == 'bridge-ports':
|
||||
# special case ports because it can contain regex or glob
|
||||
running_port_list = rv.keys() if rv else []
|
||||
bridge_port_list = self._get_bridge_port_list(ifaceobj)
|
||||
if not running_port_list and not bridge_port_list:
|
||||
continue
|
||||
elif v != rv:
|
||||
ifaceobjcurr.update_config_with_status(k, rv, 1)
|
||||
else:
|
||||
ifaceobjcurr.update_config_with_status(k, rv, 0)
|
||||
portliststatus = 1
|
||||
if running_port_list and bridge_port_list:
|
||||
difference = set(running_port_list
|
||||
).symmetric_difference(bridge_port_list)
|
||||
if not difference:
|
||||
portliststatus = 0
|
||||
ifaceobjcurr.update_config_with_status('bridge-ports',
|
||||
' '.join(running_port_list)
|
||||
if running_port_list else '', portliststatus)
|
||||
elif (k == 'bridge-pathcosts' or
|
||||
k == 'bridge-portprios' or k == 'bridge-portmcrouter'
|
||||
or k == 'bridge-portmcfl'):
|
||||
brctlcmdattrname = k[11:].rstrip('s')
|
||||
# for port attributes, the attributes are in a list
|
||||
# <portname>=<portattrvalue>
|
||||
status = 0
|
||||
currstr = ''
|
||||
vlist = self.parse_port_list(v)
|
||||
if not vlist:
|
||||
continue
|
||||
for vlistitem in vlist:
|
||||
try:
|
||||
(p, v) = vlistitem.split('=')
|
||||
currv = self.brctlcmd.get_bridgeport_attr(
|
||||
ifaceobj.name, p,
|
||||
brctlcmdattrname)
|
||||
if currv:
|
||||
currstr += ' %s=%s' %(p, currv)
|
||||
else:
|
||||
currstr += ' %s=%s' %(p, 'None')
|
||||
if currv != v:
|
||||
status = 1
|
||||
except Exception, e:
|
||||
self.log_warn(str(e))
|
||||
pass
|
||||
ifaceobjcurr.update_config_with_status(k, currstr, status)
|
||||
elif not rv:
|
||||
ifaceobjcurr.update_config_with_status(k, 'notfound', 1)
|
||||
continue
|
||||
elif v != rv:
|
||||
ifaceobjcurr.update_config_with_status(k, rv, 1)
|
||||
else:
|
||||
ifaceobjcurr.update_config_with_status(k, rv, 0)
|
||||
|
||||
self._query_check_vidinfo(ifaceobj, ifaceobjcurr)
|
||||
|
||||
self._query_check_mcqv4src(ifaceobj, ifaceobjcurr)
|
||||
|
||||
def _query_running(self, ifaceobjrunning):
|
||||
def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
|
||||
if not self.brctlcmd.bridge_exists(ifaceobjrunning.name):
|
||||
return
|
||||
ifaceobjrunning.update_config_dict(self._query_running_attrs(
|
||||
@@ -865,7 +1069,8 @@ class bridge(moduleBase):
|
||||
if not self.brctlcmd:
|
||||
self.brctlcmd = brctl(**flags)
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None,
|
||||
ifaceobj_getfunc=None):
|
||||
""" run bridge configuration on the interface object passed as
|
||||
argument. Can create bridge interfaces if they dont exist already
|
||||
|
||||
@@ -886,11 +1091,10 @@ class bridge(moduleBase):
|
||||
op_handler = self._run_ops.get(operation)
|
||||
if not op_handler:
|
||||
return
|
||||
if (operation != 'query-running' and
|
||||
not self._is_bridge(ifaceobj)):
|
||||
return
|
||||
self._init_command_handlers()
|
||||
self._flush_running_vidinfo()
|
||||
if operation == 'query-checkcurr':
|
||||
op_handler(self, ifaceobj, query_ifaceobj)
|
||||
op_handler(self, ifaceobj, query_ifaceobj,
|
||||
ifaceobj_getfunc=ifaceobj_getfunc)
|
||||
else:
|
||||
op_handler(self, ifaceobj)
|
||||
op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)
|
||||
|
153
addons/bridgevlan.py
Normal file
153
addons/bridgevlan.py
Normal file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
|
||||
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
|
||||
#
|
||||
|
||||
from ifupdown.iface import *
|
||||
from ifupdownaddons.modulebase import moduleBase
|
||||
from ifupdownaddons.iproute2 import iproute2
|
||||
from ifupdownaddons.bridgeutils import brctl
|
||||
import logging
|
||||
|
||||
class bridgevlan(moduleBase):
|
||||
""" ifupdown2 addon module to configure vlan attributes on a vlan
|
||||
aware bridge """
|
||||
|
||||
_modinfo = {'mhelp' : 'bridgevlan module configures vlan attributes ' +
|
||||
'on a vlan aware bridge. This module only ' +
|
||||
'understands vlan interface name ' +
|
||||
'with dot notations. eg br0.100. where br0 is the ' +
|
||||
'vlan aware bridge this config is for',
|
||||
'attrs' : {
|
||||
'bridge-igmp-querier-src' :
|
||||
{'help' : 'igmp querier src'}}}
|
||||
|
||||
def __init__(self, *args, **kargs):
|
||||
moduleBase.__init__(self, *args, **kargs)
|
||||
self.brctlcmd = None
|
||||
self.ipcmd = None
|
||||
|
||||
def _is_bridge_vlan_device(self, ifaceobj):
|
||||
if ifaceobj.type == ifaceType.BRIDGE_VLAN:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_bridge_n_vlan(self, ifaceobj):
|
||||
vlist = ifaceobj.name.split('.', 1)
|
||||
if len(vlist) == 2:
|
||||
return (vlist[0], vlist[1])
|
||||
return None
|
||||
|
||||
def _get_bridgename(self, ifaceobj):
|
||||
vlist = ifaceobj.name.split('.', 1)
|
||||
if len(vlist) == 2:
|
||||
return vlist[0]
|
||||
return None
|
||||
|
||||
def get_dependent_ifacenames(self, ifaceobj, ifaceobjs_all=None):
|
||||
if not self._is_bridge_vlan_device(ifaceobj):
|
||||
return None
|
||||
return [self._get_bridgename(ifaceobj)]
|
||||
|
||||
def _up(self, ifaceobj):
|
||||
try:
|
||||
(bridgename, vlan) = self._get_bridge_n_vlan(ifaceobj)
|
||||
vlanid = int(vlan, 10)
|
||||
except:
|
||||
self.logger.warn('%s: bridge vlan interface name ' %ifaceobj.name +
|
||||
'does not correspond to format (eg. br0.100)')
|
||||
raise
|
||||
|
||||
if not self.ipcmd.link_exists(bridgename):
|
||||
self.logger.warn('%s: bridge %s does not exist' %(ifaceobj.name,
|
||||
bridgename))
|
||||
return
|
||||
|
||||
running_mcqv4src = {}
|
||||
if not self.PERFMODE:
|
||||
running_mcqv4src = self.brctlcmd.get_mcqv4src(bridgename)
|
||||
if running_mcqv4src:
|
||||
r_mcqv4src = running_mcqv4src.get(vlan)
|
||||
else:
|
||||
r_mcqv4src = None
|
||||
mcqv4src = ifaceobj.get_attr_value_first('bridge-igmp-querier-src')
|
||||
if not mcqv4src:
|
||||
if r_mcqv4src:
|
||||
self.brctlcmd.del_mcqv4src(bridgename, vlanid)
|
||||
return
|
||||
|
||||
if r_mcqv4src and r_mcqv4src != mcqv4src:
|
||||
self.brctlcmd.del_mcqv4src(bridgename, vlanid)
|
||||
self.brctlcmd.set_mcqv4src(bridgename, vlanid, mcqv4src)
|
||||
else:
|
||||
self.brctlcmd.set_mcqv4src(bridgename, vlanid, mcqv4src)
|
||||
|
||||
def _down(self, ifaceobj):
|
||||
try:
|
||||
(bridgename, vlan) = self._get_bridge_n_vlan(ifaceobj)
|
||||
vlanid = int(vlan, 10)
|
||||
except:
|
||||
self.logger.warn('%s: bridge vlan interface name ' %ifaceobj.name +
|
||||
'does not correspond to format (eg. br0.100)')
|
||||
raise
|
||||
|
||||
if not self.ipcmd.link_exists(bridgename):
|
||||
self.logger.warn('%s: bridge %s does not exist' %(ifaceobj.name,
|
||||
bridgename))
|
||||
return
|
||||
|
||||
mcqv4src = ifaceobj.get_attr_value_first('bridge-igmp-querier-src')
|
||||
if mcqv4src:
|
||||
self.brctlcmd.del_mcqv4src(bridgename, vlanid)
|
||||
|
||||
def _query_check(self, ifaceobj, ifaceobjcurr):
|
||||
# XXX not supported
|
||||
return
|
||||
|
||||
def _query_running(self, ifaceobjrunning):
|
||||
# XXX not supported
|
||||
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):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
if not self.brctlcmd:
|
||||
self.brctlcmd = brctl(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run vlan configuration on the interface object passed as argument
|
||||
|
||||
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
|
||||
if (operation != 'query-running' and
|
||||
not self._is_bridge_vlan_device(ifaceobj)):
|
||||
return
|
||||
self._init_command_handlers()
|
||||
if operation == 'query-checkcurr':
|
||||
op_handler(self, ifaceobj, query_ifaceobj)
|
||||
else:
|
||||
op_handler(self, ifaceobj)
|
@@ -95,7 +95,7 @@ class dhcp(moduleBase):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run dhcp configuration on the interface object passed as argument
|
||||
|
||||
Args:
|
||||
|
@@ -106,7 +106,7 @@ class ethtool(moduleBase):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run ethtool configuration on the interface object passed as
|
||||
argument
|
||||
|
||||
|
@@ -351,7 +351,7 @@ class ifenslave(moduleBase):
|
||||
if not self.ifenslavecmd:
|
||||
self.ifenslavecmd = ifenslaveutil(**flags)
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run bond configuration on the interface object passed as argument
|
||||
|
||||
Args:
|
||||
|
@@ -50,7 +50,7 @@ class loopback(moduleBase):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
op_handler = self._run_ops.get(operation)
|
||||
if not op_handler:
|
||||
return
|
||||
|
@@ -211,8 +211,12 @@ class mstpctl(moduleBase):
|
||||
|
||||
def _is_bridge(self, ifaceobj):
|
||||
if (ifaceobj.get_attr_value_first('mstpctl-ports') or
|
||||
ifaceobj.get_attr_value_first('bridge-ports') or
|
||||
ifaceobj.type == ifaceType.BRIDGE):
|
||||
ifaceobj.get_attr_value_first('bridge-ports')):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _is_bridge_port(self, ifaceobj):
|
||||
if self.brctlcmd.is_bridge_port(ifaceobj.name):
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -344,35 +348,63 @@ class mstpctl(moduleBase):
|
||||
self.log_warn(str(e))
|
||||
pass
|
||||
|
||||
def _apply_bridge_port_settings(self, ifaceobj, bridge):
|
||||
def _apply_bridge_port_settings(self, ifaceobj, bridgename=None,
|
||||
bridgeifaceobj=None):
|
||||
check = False if self.PERFMODE else True
|
||||
try:
|
||||
# set bridge port attributes
|
||||
for attrname, dstattrname in self._port_attrs_map.items():
|
||||
attrval = ifaceobj.get_attr_value_first(attrname)
|
||||
if not attrval:
|
||||
continue
|
||||
if not bridgename and bridgeifaceobj:
|
||||
bridgename = bridgeifaceobj.name
|
||||
# set bridge port attributes
|
||||
for attrname, dstattrname in self._port_attrs_map.items():
|
||||
attrval = ifaceobj.get_attr_value_first(attrname)
|
||||
if not attrval:
|
||||
if bridgeifaceobj:
|
||||
# If bridge object available, check if the bridge
|
||||
# has the attribute set, in which case,
|
||||
# inherit it from the bridge
|
||||
attrval = bridgeifaceobj.get_attr_value_first(attrname)
|
||||
if not attrval:
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
try:
|
||||
self.mstpctlcmd.set_bridgeport_attr(bridgename,
|
||||
ifaceobj.name, dstattrname, attrval, check)
|
||||
except Exception, e:
|
||||
self.log_warn('%s: error setting %s (%s)'
|
||||
%(ifaceobj.name, attrname, str(e)))
|
||||
|
||||
def _apply_bridge_port_settings_all(self, ifaceobj,
|
||||
ifaceobj_getfunc=None):
|
||||
self.logger.info('%s: applying bridge configuration '
|
||||
%ifaceobj.name + 'specific to ports')
|
||||
|
||||
bridgeports = self._get_bridge_port_list(ifaceobj)
|
||||
for bport in bridgeports:
|
||||
self.logger.info('%s: processing bridge config for port %s'
|
||||
%(ifaceobj.name, bport))
|
||||
bportifaceobjlist = ifaceobj_getfunc(bport)
|
||||
if not bportifaceobjlist:
|
||||
continue
|
||||
for bportifaceobj in bportifaceobjlist:
|
||||
try:
|
||||
self.mstpctlcmd.set_bridgeport_attr(bridge,
|
||||
ifaceobj.name, dstattrname, attrval, check)
|
||||
self._apply_bridge_port_settings(bportifaceobj,
|
||||
ifaceobj.name, ifaceobj)
|
||||
except Exception, e:
|
||||
self.log_warn('%s: error setting %s (%s)'
|
||||
%(ifaceobj.name, attrname, str(e)))
|
||||
except Exception, e:
|
||||
self.log_warn(str(e))
|
||||
pass
|
||||
self.log_warn(str(e))
|
||||
|
||||
def _up(self, ifaceobj):
|
||||
def _up(self, ifaceobj, ifaceobj_getfunc=None):
|
||||
# Check if bridge port
|
||||
bridge = ifaceobj.get_attr_value_first('bridge')
|
||||
if bridge:
|
||||
if self._is_bridge_port(ifaceobj):
|
||||
if self.mstpctlcmd.is_mstpd_running():
|
||||
self._apply_bridge_port_settings(ifaceobj, bridge)
|
||||
bridgename = ifaceobj.upperifaces[0]
|
||||
if not bridgename:
|
||||
self.logger.warn('%s: unable to determine bridge name'
|
||||
%ifaceobj.name)
|
||||
return
|
||||
self._apply_bridge_port_settings(ifaceobj, bridgename)
|
||||
return
|
||||
|
||||
if not self._is_bridge(ifaceobj):
|
||||
return
|
||||
|
||||
stp = None
|
||||
try:
|
||||
porterr = False
|
||||
@@ -403,12 +435,16 @@ class mstpctl(moduleBase):
|
||||
if (self.mstpctlcmd.is_mstpd_running() and
|
||||
(stp == 'yes' or stp == 'on')):
|
||||
self._apply_bridge_settings(ifaceobj)
|
||||
self._apply_bridge_port_settings_all(ifaceobj,
|
||||
ifaceobj_getfunc=ifaceobj_getfunc)
|
||||
except Exception, e:
|
||||
self.log_error(str(e))
|
||||
if porterr:
|
||||
raise Exception(porterrstr)
|
||||
|
||||
def _down(self, ifaceobj):
|
||||
def _down(self, ifaceobj, ifaceobj_getfunc=None):
|
||||
if not self._is_bridge(ifaceobj):
|
||||
return
|
||||
try:
|
||||
if ifaceobj.get_attr_value_first('mstpctl-ports'):
|
||||
# If bridge ports specified with mstpctl attr, delete the
|
||||
@@ -599,7 +635,8 @@ class mstpctl(moduleBase):
|
||||
else:
|
||||
ifaceobjcurr.update_config_with_status(k, rv, 0)
|
||||
|
||||
def _query_check_bridge_port(self, ifaceobj, ifaceobjcurr, bridge):
|
||||
def _query_check_bridge_port(self, ifaceobj, ifaceobjcurr):
|
||||
bridge = ifaceobj.upperifaces[0]
|
||||
# list of attributes that are not supported currently
|
||||
blacklistedattrs = ['mstpctl-pathcost',
|
||||
'mstpctl-treeprio', 'mstpctl-treecost']
|
||||
@@ -633,15 +670,14 @@ class mstpctl(moduleBase):
|
||||
else:
|
||||
ifaceobjcurr.update_config_with_status(k, None, 1)
|
||||
|
||||
def _query_check(self, ifaceobj, ifaceobjcurr):
|
||||
def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):
|
||||
# Check if bridge port
|
||||
bridge = ifaceobj.get_attr_value_first('bridge')
|
||||
if bridge:
|
||||
self._query_check_bridge_port(ifaceobj, ifaceobjcurr, bridge)
|
||||
return
|
||||
self._query_check_bridge(ifaceobj, ifaceobjcurr)
|
||||
if self._is_bridge_port(ifaceobj):
|
||||
self._query_check_bridge_port(ifaceobj, ifaceobjcurr)
|
||||
elif self._is_bridge(ifaceobj):
|
||||
self._query_check_bridge(ifaceobj, ifaceobjcurr)
|
||||
|
||||
def _query_running(self, ifaceobjrunning):
|
||||
def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
|
||||
if not self.brctlcmd.bridge_exists(ifaceobjrunning.name):
|
||||
return
|
||||
if self.brctlcmd.get_stp(ifaceobjrunning.name) == 'no':
|
||||
@@ -674,7 +710,8 @@ class mstpctl(moduleBase):
|
||||
if not self.mstpctlcmd:
|
||||
self.mstpctlcmd = mstpctlutil(**flags)
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None,
|
||||
ifaceobj_getfunc=None, **extra_args):
|
||||
""" run mstp configuration on the interface object passed as argument
|
||||
|
||||
Args:
|
||||
@@ -695,6 +732,7 @@ class mstpctl(moduleBase):
|
||||
return
|
||||
self._init_command_handlers()
|
||||
if operation == 'query-checkcurr':
|
||||
op_handler(self, ifaceobj, query_ifaceobj)
|
||||
op_handler(self, ifaceobj, query_ifaceobj,
|
||||
ifaceobj_getfunc=ifaceobj_getfunc)
|
||||
else:
|
||||
op_handler(self, ifaceobj)
|
||||
op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)
|
||||
|
@@ -75,7 +75,7 @@ class usercmds(ifupdownaddons.modulebase.moduleBase):
|
||||
""" returns list of ops supported by this module """
|
||||
return self._run_ops.keys()
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run user commands
|
||||
|
||||
Args:
|
||||
|
@@ -98,8 +98,12 @@ class vlan(moduleBase):
|
||||
vlanrawdevice = self._get_vlan_raw_device(ifaceobj)
|
||||
if not vlanrawdevice:
|
||||
raise Exception('could not determine vlan raw device')
|
||||
if not self.ipcmd.link_exists(ifaceobj.name):
|
||||
rtnetlink_api.rtnl_api.create_vlan(vlanrawdevice,
|
||||
if not self.PERFMODE:
|
||||
if not self.ipcmd.link_exists(vlanrawdevice):
|
||||
raise Exception('rawdevice %s not present' %vlanrawdevice)
|
||||
if self.ipcmd.link_exists(ifaceobj.name):
|
||||
return
|
||||
rtnetlink_api.rtnl_api.create_vlan(vlanrawdevice,
|
||||
ifaceobj.name, vlanid)
|
||||
|
||||
def _down(self, ifaceobj):
|
||||
@@ -164,7 +168,7 @@ class vlan(moduleBase):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
""" run vlan configuration on the interface object passed as argument
|
||||
|
||||
Args:
|
||||
@@ -180,6 +184,8 @@ class vlan(moduleBase):
|
||||
of interfaces. status is success if the running state is same
|
||||
as user required state in ifaceobj. error otherwise.
|
||||
"""
|
||||
if ifaceobj.type == ifaceType.BRIDGE_VLAN:
|
||||
return
|
||||
op_handler = self._run_ops.get(operation)
|
||||
if not op_handler:
|
||||
return
|
||||
|
@@ -73,7 +73,7 @@ class vxlan(moduleBase):
|
||||
if not self.ipcmd:
|
||||
self.ipcmd = iproute2(**self.get_flags())
|
||||
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None):
|
||||
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
|
||||
op_handler = self._run_ops.get(operation)
|
||||
if not op_handler:
|
||||
return
|
||||
|
@@ -3,8 +3,8 @@ pre-up,vlan
|
||||
pre-up,vxlan
|
||||
pre-up,usercmds
|
||||
pre-up,loopback
|
||||
pre-up,bridgevlanaware
|
||||
pre-up,bridge
|
||||
pre-up,bridgevlan
|
||||
pre-up,mstpctl
|
||||
up,dhcp
|
||||
up,address
|
||||
@@ -19,7 +19,7 @@ down,addressvirtual
|
||||
down,address
|
||||
down,usercmds
|
||||
post-down,mstpctl
|
||||
post-down,bridgevlanaware
|
||||
post-down,bridgevlan
|
||||
post-down,bridge
|
||||
post-down,vxlan
|
||||
post-down,vlan
|
||||
|
@@ -351,6 +351,7 @@ class iface():
|
||||
Returns True if object self is same as dstiface and False otherwise """
|
||||
|
||||
if self.name != dstiface.name: return False
|
||||
if self.type != dstiface.type: return False
|
||||
if self.addr_family != dstiface.addr_family: return False
|
||||
if self.addr_method != dstiface.addr_method: return False
|
||||
if self.auto != dstiface.auto: return False
|
||||
|
0
ifupdown/iff.py
Executable file → Normal file
0
ifupdown/iff.py
Executable file → Normal file
@@ -37,6 +37,16 @@ _crossmark = u'\u2717'
|
||||
_success_sym = '(%s)' %_tickmark
|
||||
_error_sym = '(%s)' %_crossmark
|
||||
|
||||
class ifupdownFlags():
|
||||
FORCE = False
|
||||
DRYRUN = False
|
||||
NOWAIT = False
|
||||
PERFMODE = False
|
||||
CACHE = False
|
||||
|
||||
# Flags
|
||||
CACHE_FLAGS = 0x0
|
||||
|
||||
class ifupdownMain(ifupdownBase):
|
||||
""" ifupdown2 main class """
|
||||
|
||||
@@ -160,6 +170,14 @@ class ifupdownMain(ifupdownBase):
|
||||
self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
|
||||
self.ADDONS_ENABLE = addons_enable
|
||||
|
||||
# Copy flags into ifupdownFlags
|
||||
# XXX: before we transition fully to ifupdownFlags
|
||||
ifupdownFlags.FORCE = force
|
||||
ifupdownFlags.DRYRUN = dryrun
|
||||
ifupdownFlags.NOWAIT = nowait
|
||||
ifupdownFlags.PERFMODE = perfmode
|
||||
ifupdownFlags.CACHE = cache
|
||||
|
||||
self.ifaces = OrderedDict()
|
||||
self.njobs = njobs
|
||||
self.pp = pprint.PrettyPrinter(indent=4)
|
||||
@@ -351,7 +369,7 @@ class ifupdownMain(ifupdownBase):
|
||||
dlist = None
|
||||
pass
|
||||
if dlist: ret_dlist.extend(dlist)
|
||||
return ret_dlist
|
||||
return list(set(ret_dlist))
|
||||
|
||||
def populate_dependency_info(self, ops, ifacenames=None):
|
||||
""" recursive function to generate iface dependency info """
|
||||
|
@@ -266,17 +266,36 @@ class networkInterfaces():
|
||||
for v in range(range_val[1], range_val[2]):
|
||||
ifaceobj_new = copy.deepcopy(ifaceobj)
|
||||
ifaceobj_new.real_name = ifaceobj.name
|
||||
ifaceobj_new.name = "%s-%d" %(range_val[0], v)
|
||||
ifaceobj_new.name = "%s%d" %(range_val[0], v)
|
||||
self.callbacks.get('iface_found')(ifaceobj_new)
|
||||
else:
|
||||
self.callbacks.get('iface_found')(ifaceobj)
|
||||
|
||||
return lines_consumed # Return next index
|
||||
|
||||
def process_vlan(self, lines, cur_idx, lineno):
|
||||
ifaceobj = iface()
|
||||
lines_consumed = self.parse_iface(lines, cur_idx, lineno, ifaceobj)
|
||||
|
||||
range_val = utils.parse_iface_range(ifaceobj.name)
|
||||
if range_val:
|
||||
for v in range(range_val[1], range_val[2]):
|
||||
ifaceobj_new = copy.deepcopy(ifaceobj)
|
||||
ifaceobj_new.real_name = ifaceobj.name
|
||||
ifaceobj_new.name = "%s%d" %(range_val[0], v)
|
||||
ifaceobj_new.type = ifaceType.BRIDGE_VLAN
|
||||
self.callbacks.get('iface_found')(ifaceobj_new)
|
||||
else:
|
||||
ifaceobj.type = ifaceType.BRIDGE_VLAN
|
||||
self.callbacks.get('iface_found')(ifaceobj)
|
||||
|
||||
return lines_consumed # Return next index
|
||||
|
||||
network_elems = { 'source' : process_source,
|
||||
'allow' : process_allow,
|
||||
'auto' : process_auto,
|
||||
'iface' : process_iface}
|
||||
'iface' : process_iface,
|
||||
'vlan' : process_vlan}
|
||||
|
||||
def _is_keyword(self, str):
|
||||
# The additional split here is for allow- keyword
|
||||
|
@@ -11,6 +11,7 @@ from socket import AF_UNSPEC
|
||||
from iff import IFF_UP
|
||||
from rtnetlink import *
|
||||
import os
|
||||
import ifupdownmain
|
||||
|
||||
class rtnetlinkApi(RtNetlink):
|
||||
|
||||
@@ -39,13 +40,15 @@ class rtnetlinkApi(RtNetlink):
|
||||
return ifindex
|
||||
|
||||
def create_vlan(self, link, ifname, vlanid):
|
||||
|
||||
self.logger.info('rtnetlink: creating vlan %s' %ifname)
|
||||
if ifupdownmain.ifupdownFlags.DRYRUN:
|
||||
return
|
||||
try:
|
||||
ifindex = self.get_ifindex(link)
|
||||
except Exception, e:
|
||||
raise Exception('cannot determine ifindex for link %s (%s)' %(link, str(e)))
|
||||
raise Exception('cannot determine ifindex for link %s (%s)'
|
||||
%(link, str(e)))
|
||||
|
||||
self.logger.info('rtnetlink: creating vlan %s' %ifname)
|
||||
ifm = Ifinfomsg(AF_UNSPEC)
|
||||
rtas = {IFLA_IFNAME: ifname,
|
||||
IFLA_LINK : ifindex,
|
||||
@@ -56,17 +59,19 @@ class rtnetlinkApi(RtNetlink):
|
||||
}
|
||||
}
|
||||
}
|
||||
token = self.request(RTM_NEWLINK, NLM_F_CREATE | NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
||||
token = self.request(RTM_NEWLINK,
|
||||
NLM_F_CREATE | NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
||||
self.process_wait([token])
|
||||
|
||||
def create_macvlan(self, ifname, link, mode='private'):
|
||||
|
||||
self.logger.info('rtnetlink: creating macvlan %s' %ifname)
|
||||
if ifupdownmain.ifupdownFlags.DRYRUN:
|
||||
return
|
||||
try:
|
||||
ifindex = self.get_ifindex(link)
|
||||
except Exception, e:
|
||||
raise Exception('cannot determine ifindex for link %s (%s)' %(link, str(e)))
|
||||
|
||||
self.logger.info('rtnetlink: creating macvlan %s' %ifname)
|
||||
raise Exception('cannot determine ifindex for link %s (%s)'
|
||||
%(link, str(e)))
|
||||
|
||||
ifm = Ifinfomsg(AF_UNSPEC)
|
||||
rtas = {IFLA_IFNAME: ifname,
|
||||
@@ -78,14 +83,15 @@ class rtnetlinkApi(RtNetlink):
|
||||
}
|
||||
}
|
||||
}
|
||||
token = self.request(RTM_NEWLINK, NLM_F_CREATE | NLM_F_REQUEST | NLM_F_ACK,
|
||||
ifm, rtas)
|
||||
token = self.request(RTM_NEWLINK, NLM_F_CREATE | NLM_F_REQUEST |
|
||||
NLM_F_ACK, ifm, rtas)
|
||||
self.process_wait([token])
|
||||
|
||||
def link_set(self, ifname, state):
|
||||
flags = 0
|
||||
|
||||
self.logger.info('rtnetlink: setting link %s %s' %(ifname, state))
|
||||
if ifupdownmain.ifupdownFlags.DRYRUN:
|
||||
return
|
||||
|
||||
if state == "up":
|
||||
flags |= IFF_UP
|
||||
|
@@ -65,7 +65,7 @@ class ifaceScheduler():
|
||||
m.run(ifaceobj, op, query_ifaceobj)
|
||||
else:
|
||||
ifupdownobj.logger.debug(msg)
|
||||
m.run(ifaceobj, op)
|
||||
m.run(ifaceobj, op, ifaceobj_getfunc=ifupdownobj.get_ifaceobjs)
|
||||
except Exception, e:
|
||||
err = 1
|
||||
ifupdownobj.log_error(str(e))
|
||||
|
@@ -32,7 +32,7 @@ class utils():
|
||||
|
||||
@classmethod
|
||||
def parse_iface_range(cls, name):
|
||||
range_match = re.match("^([\w]+)-\[([\d]+)-([\d]+)\]", name)
|
||||
range_match = re.match("^([\w\.]+)\[([\d]+)-([\d]+)\]", name)
|
||||
if range_match:
|
||||
range_groups = range_match.groups()
|
||||
if range_groups[1] and range_groups[2]:
|
||||
|
@@ -484,6 +484,9 @@ class brctl(utilsBase):
|
||||
def bridge_exists(self, bridge):
|
||||
return os.path.exists('/sys/class/net/%s/bridge' %bridge)
|
||||
|
||||
def is_bridge_port(self, ifacename):
|
||||
return os.path.exists('/sys/class/net/%s/brport' %ifacename)
|
||||
|
||||
def bridge_port_exists(self, bridge, bridgeportname):
|
||||
try:
|
||||
return bridgeportname in os.listdir('/sys/class/net/%s/brif'
|
||||
|
@@ -486,6 +486,8 @@ class iproute2(utilsBase):
|
||||
self._cache_update([name], {})
|
||||
|
||||
def link_exists(self, ifacename):
|
||||
if self.DRYRUN:
|
||||
return True
|
||||
return os.path.exists('/sys/class/net/%s' %ifacename)
|
||||
|
||||
def is_vlan_device_by_name(self, ifacename):
|
||||
|
@@ -180,7 +180,11 @@ class moduleBase(object):
|
||||
if not port_expr:
|
||||
return None
|
||||
for expr in re.split(r'[\s\t]\s*', port_expr):
|
||||
if expr == 'regex':
|
||||
if expr == 'noregex':
|
||||
regex = 0
|
||||
elif expr == 'noglob':
|
||||
glob = 0
|
||||
elif expr == 'regex':
|
||||
regex = 1
|
||||
elif expr == 'glob':
|
||||
glob = 1
|
||||
|
Reference in New Issue
Block a user