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

Merge remote-tracking branch 'cumulus/dev'

Conflicts:
	config/ifupdown2.conf
	nlmanager/nllistener.py
This commit is contained in:
Roopa Prabhu
2016-09-02 15:45:58 -07:00
27 changed files with 1473 additions and 478 deletions

View File

@@ -17,6 +17,7 @@ try:
from ifupdown.netlink import netlink
import ifupdown.ifupdownconfig as ifupdownConfig
import ifupdown.ifupdownflags as ifupdownflags
import ifupdown.statemanager as statemanager
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
@@ -28,18 +29,17 @@ class address(moduleBase):
'attrs': {
'address' :
{'help' : 'ipv4 or ipv6 addresses',
'validvals' : [IPv4Network, IPv6Network],
'validvals' : ['<ipv4/prefixlen>', '<ipv6/prefixlen>'],
'multiline' : True,
'example' : ['address 10.0.12.3/24',
'address 2000:1000:1000:1000:3::5/128']},
'netmask' :
{'help': 'netmask',
'validvals' : [IPv4Address, ],
'example' : ['netmask 255.255.255.0'],
'compat' : True},
'broadcast' :
{'help': 'broadcast address',
'validvals' : [IPv4Address, ],
'validvals' : ['<ipv4>', ],
'example' : ['broadcast 10.0.1.255']},
'scope' :
{'help': 'scope',
@@ -52,7 +52,7 @@ class address(moduleBase):
'preferred-lifetime 10']},
'gateway' :
{'help': 'default gateway',
'validvals' : [IPv4Address, IPv6Address],
'validvals' : ['<ipv4>', '<ipv6>'],
'example' : ['gateway 255.255.255.0']},
'mtu' :
{ 'help': 'interface mtu',
@@ -79,7 +79,7 @@ class address(moduleBase):
'clagd-vxlan-anycast-ip' :
{ 'help' : 'Anycast local IP address for ' +
'dual connected VxLANs',
'validvals' : [IPv4Address, ],
'validvals' : ['<ipv4>', ],
'example' : ['clagd-vxlan-anycast-ip 36.0.0.11']}}}
def __init__(self, *args, **kargs):
@@ -260,6 +260,30 @@ class address(moduleBase):
return
self._inet_address_list_config(ifaceobj, newaddrs, newaddr_attrs)
def _add_delete_gateway(self, ifaceobj, gateways=[], prev_gw=[]):
vrf = ifaceobj.get_attr_value_first('vrf')
metric = ifaceobj.get_attr_value_first('metric')
for del_gw in list(set(prev_gw) - set(gateways)):
try:
self.ipcmd.route_del_gateway(ifaceobj.name, del_gw, vrf, metric)
except:
pass
for add_gw in list(set(gateways) - set(prev_gw)):
try:
self.ipcmd.route_add_gateway(ifaceobj.name, add_gw, vrf)
except:
pass
def _get_prev_gateway(self, ifaceobj, gateways):
ipv = []
saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name)
if not saved_ifaceobjs:
return ipv
prev_gateways = saved_ifaceobjs[0].get_attr_value('gateway')
if not prev_gateways:
return ipv
return prev_gateways
def _up(self, ifaceobj, ifaceobj_getfunc=None):
if not self.ipcmd.link_exists(ifaceobj.name):
return
@@ -290,7 +314,7 @@ class address(moduleBase):
mtu = ifaceobj.get_attr_value_first('mtu')
if mtu:
self.ipcmd.link_set(ifaceobj.name, 'mtu', mtu)
elif (not ifaceobj.link_kind and
elif (not (ifaceobj.name == 'lo') and not ifaceobj.link_kind and
not (ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) and
self.default_mtu):
# logical devices like bridges and vlan devices rely on mtu
@@ -308,7 +332,11 @@ class address(moduleBase):
alias = ifaceobj.get_attr_value_first('alias')
if alias:
self.ipcmd.link_set_alias(ifaceobj.name, alias)
self.ipcmd.batch_commit()
try:
self.ipcmd.batch_commit()
except Exception as e:
self.logger.error('%s: %s' % (ifaceobj.name, str(e)))
ifaceobj.set_status(ifaceStatus.ERROR)
hwaddress = self._get_hwaddress(ifaceobj)
if hwaddress:
@@ -340,9 +368,12 @@ class address(moduleBase):
pass
if addr_method != "dhcp":
self.ipcmd.route_add_gateway(ifaceobj.name,
ifaceobj.get_attr_value_first('gateway'),
ifaceobj.get_attr_value_first('vrf'))
gateways = ifaceobj.get_attr_value('gateway')
if not gateways:
gateways = []
prev_gw = self._get_prev_gateway(ifaceobj, gateways)
self._add_delete_gateway(ifaceobj, gateways, prev_gw)
return
def _down(self, ifaceobj, ifaceobj_getfunc=None):
try:
@@ -350,10 +381,6 @@ class address(moduleBase):
return
addr_method = ifaceobj.addr_method
if addr_method != "dhcp":
self.ipcmd.route_del_gateway(ifaceobj.name,
ifaceobj.get_attr_value_first('gateway'),
ifaceobj.get_attr_value_first('vrf'),
ifaceobj.get_attr_value_first('metric'))
if ifaceobj.get_attr_value_first('address-purge')=='no':
addrlist = ifaceobj.get_attr_value('address')
for addr in addrlist:

View File

@@ -25,8 +25,8 @@ class addressvirtual(moduleBase):
'every mac ip address-virtual line',
'attrs' : {
'address-virtual' :
{ 'help' : 'bridge router virtual mac and ip',
'validvals' : [('<mac>', IPv4Network), ],
{ 'help' : 'bridge router virtual mac and ips',
'validvals' : ['<mac-ip/prefixlen-list>',],
'example' : ['address-virtual 00:11:22:33:44:01 11.0.1.1/24 11.0.1.2/24']}
}}
@@ -125,6 +125,11 @@ class addressvirtual(moduleBase):
%str(e))
pass
def _handle_vrf_slaves(self, macvlan_ifacename, ifaceobj):
vrfname = self.ipcmd.link_get_master(ifaceobj.name)
if vrfname:
self.ipcmd.link_set(macvlan_ifacename, 'master', vrfname)
def _get_macs_from_old_config(self, ifaceobj=None):
""" This method returns a list of the mac addresses
in the address-virtual attribute for the bridge. """
@@ -196,6 +201,16 @@ class addressvirtual(moduleBase):
if lower_iface_mtu and lower_iface_mtu != self.ipcmd.link_get_mtu(macvlan_ifacename):
self.ipcmd.link_set_mtu(macvlan_ifacename, lower_iface_mtu)
# handle vrf slaves
if (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE):
self._handle_vrf_slaves(macvlan_ifacename, ifaceobj)
# Disable IPv6 duplicate address detection on VRR interfaces
for key, sysval in { 'accept_dad' : '0', 'dad_transmits' : '0' }.iteritems():
syskey = 'net.ipv6.conf.%s.%s' % (macvlan_ifacename, key)
if self.sysctl_get(syskey) != sysval:
self.sysctl_set(syskey, sysval)
av_idx += 1
self.ipcmd.batch_commit()
@@ -277,7 +292,8 @@ class addressvirtual(moduleBase):
self._remove_address_config(ifaceobj, address_virtual_list)
return
if ifaceobj.upperifaces:
if (ifaceobj.upperifaces and
not ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE):
self.log_error('%s: invalid placement of address-virtual lines (must be configured under an interface with no upper interfaces or parent interfaces)'
% (ifaceobj.name), ifaceobj)
return

View File

@@ -80,12 +80,14 @@ class bond(moduleBase):
'bond-ad-sys-mac-addr':
{'help' : '802.3ad system mac address',
'default' : '00:00:00:00:00:00',
'validvals': ['<mac>', ],
'example' : ['bond-ad-sys-mac-addr 00:00:00:00:00:00'],
'deprecated' : True,
'new-attribute' : 'bond-ad-actor-system'},
'bond-ad-actor-system':
{'help' : '802.3ad system mac address',
'default' : '00:00:00:00:00:00',
'validvals': ['<mac>', ],
'example' : ['bond-ad-actor-system 00:00:00:00:00:00'],},
'bond-lacp-bypass-allow':
{'help' : 'allow lacp bypass',
@@ -96,6 +98,7 @@ class bond(moduleBase):
{'help' : 'bond slaves',
'required' : True,
'multivalue' : True,
'validvals': ['<interface-list>'],
'example' : ['bond-slaves swp1 swp2',
'bond-slaves glob swp1-2',
'bond-slaves regex (swp[1|2)']}}}
@@ -188,20 +191,6 @@ class bond(moduleBase):
ifname=ifaceobj.name,
attr=attrname)
if attrval:
msg = ('%s: invalid value %s for attr %s.'
%(ifaceobj.name, attrval, attrname))
optiondict = self.get_mod_attr(attrname)
if not optiondict:
return None
validvals = optiondict.get('validvals')
if validvals and attrval not in validvals:
raise Exception(msg + ' Valid values are %s' %str(validvals))
validrange = optiondict.get('validrange')
if validrange:
if (int(attrval) < int(validrange[0]) or
int(attrval) > int(validrange[1])):
raise Exception(msg + ' Valid range is [%s,%s]'
%(validrange[0], validrange[1]))
if attrname == 'bond-mode':
attrval = bond._get_readable_bond_mode(attrval)
if attrval == '802.3ad':

View File

@@ -42,6 +42,7 @@ class bridge(moduleBase):
{'help' : 'bridge ports',
'multivalue' : True,
'required' : True,
'validvals': ['<interface-list>'],
'example' : ['bridge-ports swp1.100 swp2.100 swp3.100',
'bridge-ports glob swp1-3.100',
'bridge-ports regex (swp[1|2|3].100)']},
@@ -85,12 +86,14 @@ class bridge(moduleBase):
'default' : '20'},
'bridge-pathcosts' :
{ 'help' : 'bridge set port path costs',
'validvals': ['<interface-range-list>'],
'validrange' : ['0', '65535'],
'example' : ['under the bridge: bridge-pathcosts swp1=100 swp2=100',
'under the port (recommended): bridge-pathcosts 100'],
'default' : '100'},
'bridge-portprios' :
{ 'help' : 'bridge port prios',
'validvals': ['<interface-range-list>'],
'validrange' : ['0', '65535'],
'example' : ['under the bridge: bridge-portprios swp1=32 swp2=32',
'under the port (recommended): bridge-portprios 32'],
@@ -173,12 +176,13 @@ class bridge(moduleBase):
'example' : ['bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1']},
'bridge-portmcrouter' :
{ 'help' : 'set port multicast routers',
'validvals' : ['yes', 'no', '0', '1'],
'validvals' : ['<interface-yes-no-0-1-list>'],
'default' : 'yes',
'example' : ['under the bridge: bridge-portmcrouter swp1=yes swp2=yes',
'under the port (recommended): bridge-portmcrouter yes']},
'bridge-portmcfl' :
{ 'help' : 'port multicast fast leave.',
'validvals': ['<interface-range-list>'],
'validrange' : ['0', '65535'],
'default' : '0',
'example' : ['under the bridge: bridge-portmcfl swp1=0 swp2=0',
@@ -193,6 +197,7 @@ class bridge(moduleBase):
'regex or \"all\" on bridge_ports,' +
'as it wouldnt work.',
'default' : '0',
'validvals': ['<number-interface-list>'],
'example' : ['bridge-waitport 4 swp1 swp2']},
'bridge-maxwait' :
{ 'help' : 'forces to time seconds the maximum time ' +
@@ -210,6 +215,7 @@ class bridge(moduleBase):
'If specified under the bridge the ports ' +
'inherit it unless overridden by a ' +
'bridge-vids attribute under the port',
'validvals': ['<number-range-list>'],
'example' : ['bridge-vids 4000',
'bridge-vids 2000 2200-3000']},
'bridge-pvid' :
@@ -491,20 +497,14 @@ class bridge(moduleBase):
result.append(a)
return result
def _diff_vids(self, vids1, vids2):
vids_to_add = None
vids_to_del = None
def _compress_into_ranges(self, vids_ints):
return ['%d' %start if start == end else '%d-%d' %(start, end)
for start, end in self._ints_to_ranges(vids_ints)]
def _diff_vids(self, vids1_ints, vids2_ints):
vids_to_add = Set(vids1_ints).difference(vids2_ints)
vids_to_del = Set(vids2_ints).difference(vids1_ints)
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, pvid=None):
@@ -513,8 +513,8 @@ class bridge(moduleBase):
vids1_ints = self._ranges_to_ints(vids1)
vids2_ints = self._ranges_to_ints(vids2)
set_diff = Set(vids1_ints).symmetric_difference(vids2_ints)
if pvid:
set_diff = set_diff.remove(pvid)
if pvid and int(pvid) in set_diff:
set_diff.remove(int(pvid))
if set_diff:
return False
else:
@@ -548,7 +548,7 @@ class bridge(moduleBase):
# CM-8161. Removed check for PERFMODE. Need the get in all cases
# including reboot, so that we can configure the pvid correctly.
self._running_vidinfo = self.ipcmd.bridge_port_vids_get_all()
self._running_vidinfo = self.ipcmd.bridge_port_vids_get_all_json()
self._running_vidinfo_valid = True
return self._running_vidinfo
@@ -567,8 +567,6 @@ class bridge(moduleBase):
return
# Handle bridge vlan attrs
running_vidinfo = self._get_running_vidinfo()
# Install pvids
if bridge_port_pvids:
portlist = self.parse_port_list(ifaceobj.name, bridge_port_pvids)
@@ -580,7 +578,8 @@ class bridge(moduleBase):
for p in portlist:
try:
(port, pvid) = p.split('=')
running_pvid = running_vidinfo.get(port, {}).get('pvid')
pvid = int(pvid)
running_pvid = self._get_running_pvid(port)
if running_pvid:
if running_pvid == pvid:
continue
@@ -602,42 +601,23 @@ class bridge(moduleBase):
try:
(port, val) = p.split('=')
vids = val.split(',')
if running_vidinfo.get(port):
vids_int = self._ranges_to_ints(vids)
running_vids = self._get_running_vids(port)
if running_vids:
(vids_to_del, vids_to_add) = \
self._diff_vids(vids,
running_vidinfo.get(port).get('vlan'))
self._diff_vids(vids_int, running_vids)
if vids_to_del:
self.ipcmd.bridge_port_vids_del(port, vids_to_del)
self.ipcmd.bridge_port_vids_del(port,
self._compress_into_ranges(vids_to_del))
if vids_to_add:
self.ipcmd.bridge_port_vids_add(port, vids_to_add)
self.ipcmd.bridge_port_vids_add(port,
self._compress_into_ranges(vids_to_add))
else:
self.ipcmd.bridge_port_vids_add(port, vids)
self.ipcmd.bridge_port_vids_add(port, vids_int)
except Exception, e:
self.log_warn('%s: failed to set vid `%s` (%s)'
%(ifaceobj.name, p, str(e)))
# install vids
# XXX: Commenting out this code for now because it was decided
# that this is not needed
#attrval = ifaceobj.get_attr_value_first('bridge-vids')
#if attrval:
# vids = re.split(r'[\s\t]\s*', attrval)
# 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)
# if vids_to_add:
# self.ipcmd.bridge_vids_add(ifaceobj.name, vids_to_add)
# else:
# self.ipcmd.bridge_vids_add(ifaceobj.name, vids)
#else:
# running_vids = running_vidinfo.get(ifaceobj.name)
# if running_vids:
# self.ipcmd.bridge_vids_del(ifaceobj.name, running_vids)
def _is_running_stp_state_on(self, bridgename):
""" Returns True if running stp state is on, else False """
@@ -784,26 +764,6 @@ class bridge(moduleBase):
ret = False
return ret
def _apply_bridge_vids(self, bportifaceobj, vids, running_vids, isbridge):
try:
if not self._check_vids(bportifaceobj, vids):
return
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_error('%s: failed to set vid `%s` (%s)'
%(bportifaceobj.name, str(vids), str(e)),
bportifaceobj)
def _apply_bridge_port_pvids(self, bportifaceobj, pvid, running_pvid):
# Install pvids
try:
@@ -818,8 +778,88 @@ class bridge(moduleBase):
self.log_error('%s: failed to set pvid `%s` (%s)'
%(bportifaceobj.name, pvid, str(e)), bportifaceobj)
def _apply_bridge_vids_and_pvid(self, bportifaceobj, vids, running_vids,
pvid, running_pvid, isbridge):
def _get_running_pvid(self, ifacename):
pvid = 0
running_vidinfo = self._get_running_vidinfo()
for vinfo in running_vidinfo.get(ifacename, {}):
v = vinfo.get('vlan')
pvid = v if 'PVID' in vinfo.get('flags', []) else 0
if pvid:
return pvid
return pvid
def _get_running_vids(self, ifacename):
vids = []
running_vidinfo = self._get_running_vidinfo()
for vinfo in running_vidinfo.get(ifacename, {}):
v = vinfo.get('vlan')
ispvid = True if 'PVID' in vinfo.get('flags', []) else False
if ispvid:
pvid = v if 'PVID' in vinfo.get('flags', []) else 0
if pvid == 1:
continue
vEnd = vinfo.get('vlanEnd')
if vEnd:
vids.extend(range(v, vEnd + 1))
else:
vids.append(v)
return vids
def _get_running_vids_n_pvid(self, ifacename):
vids = []
pvid = 0
running_vidinfo = self._get_running_vidinfo()
for vinfo in running_vidinfo.get(ifacename, {}):
v = vinfo.get('vlan')
ispvid = True if 'PVID' in vinfo.get('flags', []) else False
if ispvid:
pvid = v if 'PVID' in vinfo.get('flags', []) else 0
vEnd = vinfo.get('vlanEnd')
if vEnd:
vids.extend(range(v, vEnd + 1))
else:
vids.append(v)
return (vids, pvid)
def _get_running_vids_n_pvid_str(self, ifacename):
vids = []
pvid = None
(vids, pvid) = self._get_running_vids_n_pvid(ifacename)
if vids:
ret_vids = self._compress_into_ranges(vids)
else:
ret_vids = None
if pvid:
ret_pvid = '%s' %pvid
else:
ret_pvid = None
return (ret_vids, ret_pvid)
def _get_running_vids_n_pvid_str2(self, ifacename):
vids = []
pvid = None
running_vidinfo = self._get_running_vidinfo()
for vinfo in running_vidinfo.get(ifacename, {}):
v = vinfo.get('vlan')
if not pvid:
pvid = '%s' %v if 'PVID' in vinfo.get('flags', []) else None
vEnd = vinfo.get('vlanEnd')
if vEnd:
vids.append('%s-%s' %(v, vEnd))
else:
vids.append('%s' %v)
return (vids, pvid)
def _apply_bridge_vids_and_pvid(self, bportifaceobj, vids, pvid,
isbridge):
""" This method is a combination of methods _apply_bridge_vids and
_apply_bridge_port_pvids above. A combined function is
found necessary to do the deletes first and the adds later
@@ -827,24 +867,42 @@ class bridge(moduleBase):
"""
vids_int = self._ranges_to_ints(vids)
pvid_int = int(pvid) if pvid else 0
vids_to_del = []
vids_to_add = vids_int
pvid_to_del = None
pvid_to_add = pvid_int
try:
if not self._check_vids(bportifaceobj, vids):
return
vids_to_del = []
vids_to_add = vids
pvid_to_del = None
pvid_to_add = pvid
(running_vids, running_pvid) = self._get_running_vids_n_pvid(
bportifaceobj.name)
if not running_vids and not running_pvid:
# There cannot be a no running pvid.
# It might just not be in our cache:
# this can happen if at the time we were
# creating the bridge vlan cache, the port
# was not part of the bridge. And we need
# to make sure both vids and pvid is not in
# the cache, to declare that our cache may
# be stale.
running_pvid = 1
running_vids = [1]
if running_vids:
(vids_to_del, vids_to_add) = \
self._diff_vids(vids, running_vids)
self._diff_vids(vids_to_add, running_vids)
if running_pvid:
if running_pvid != pvid and running_pvid != '0':
if running_pvid != pvid_int and running_pvid != 0:
pvid_to_del = running_pvid
if (pvid_to_del and (pvid_to_del in vids) and
if (pvid_to_del and (pvid_to_del in vids_int) and
(pvid_to_del not in vids_to_add)):
# kernel deletes dont take into account
# bridge vid flags and its possible that
@@ -859,7 +917,7 @@ class bridge(moduleBase):
# - new change is going to move the state to
# pvid 101
# vid 100 102
vids_to_add.append(pvid_to_del)
vids_to_add.add(pvid_to_del)
except Exception, e:
self.log_error('%s: failed to process vids/pvids'
%bportifaceobj.name + ' vids = %s' %str(vids) +
@@ -867,8 +925,11 @@ class bridge(moduleBase):
bportifaceobj, raise_error=False)
try:
if vids_to_del:
if pvid_to_add in vids_to_del:
vids_to_del.remove(pvid_to_add)
self.ipcmd.bridge_vids_del(bportifaceobj.name,
vids_to_del, isbridge)
self._compress_into_ranges(
vids_to_del), isbridge)
except Exception, e:
self.log_warn('%s: failed to del vid `%s` (%s)'
%(bportifaceobj.name, str(vids_to_del), str(e)))
@@ -884,15 +945,17 @@ class bridge(moduleBase):
try:
if vids_to_add:
self.ipcmd.bridge_vids_add(bportifaceobj.name,
vids_to_add, isbridge)
self._compress_into_ranges(
vids_to_add), isbridge)
except Exception, e:
self.log_error('%s: failed to set vid `%s` (%s)'
%(bportifaceobj.name, str(vids_to_add), str(e)),
bportifaceobj, raise_error=False)
%(bportifaceobj.name, str(vids_to_add),
str(e)), bportifaceobj, raise_error=False)
try:
if pvid_to_add:
self.ipcmd.bridge_port_pvid_add(bportifaceobj.name, pvid_to_add)
if pvid_to_add and pvid_to_add != running_pvid:
self.ipcmd.bridge_port_pvid_add(bportifaceobj.name,
pvid_to_add)
except Exception, e:
self.log_error('%s: failed to set pvid `%s` (%s)'
%(bportifaceobj.name, pvid_to_add, str(e)),
@@ -901,7 +964,6 @@ class bridge(moduleBase):
def _apply_bridge_vlan_aware_port_settings_all(self, bportifaceobj,
bridge_vids=None,
bridge_pvid=None):
running_vidinfo = self._get_running_vidinfo()
vids = None
pvids = None
vids_final = []
@@ -938,10 +1000,7 @@ class bridge(moduleBase):
pvid_final = None
self._apply_bridge_vids_and_pvid(bportifaceobj, vids_final,
running_vidinfo.get(bportifaceobj.name, {}).get('vlan'),
pvid_final,
running_vidinfo.get(bportifaceobj.name, {}).get('pvid'),
False)
pvid_final, False)
def _apply_bridge_port_settings(self, bportifaceobj, bridgename=None,
bridgeifaceobj=None):
@@ -971,9 +1030,9 @@ class bridge(moduleBase):
self.log_error(str(e), bportifaceobj)
def _apply_bridge_port_settings_all(self, ifaceobj,
ifaceobj_getfunc=None):
ifaceobj_getfunc=None,
bridge_vlan_aware=False):
err = False
bridge_vlan_aware = ifaceobj.get_attr_value_first('bridge-vlan-aware') == 'yes'
if (ifaceobj.get_attr_value_first('bridge-port-vids') and
ifaceobj.get_attr_value_first('bridge-port-pvids')):
@@ -1005,6 +1064,7 @@ class bridge(moduleBase):
if not bridgeports:
self.logger.debug('%s: cannot find bridgeports' %ifaceobj.name)
return
self.ipcmd.batch_start()
for bport in bridgeports:
# Use the brctlcmd bulk set method: first build a dictionary
# and then call set
@@ -1037,6 +1097,7 @@ class bridge(moduleBase):
err = True
self.logger.warn('%s: %s' %(ifaceobj.name, str(e)))
pass
self.ipcmd.bridge_batch_commit()
if err:
raise Exception('%s: errors applying port settings' %ifaceobj.name)
@@ -1097,14 +1158,21 @@ class bridge(moduleBase):
raise Exception(str(e))
try:
bridge_vlan_aware = False
if ifaceobj.get_attr_value_first('bridge-vlan-aware') == 'yes':
bridge_vlan_aware = True
if (bridge_just_created or
not self.ipcmd.bridge_is_vlan_aware(ifaceobj.name)):
self.ipcmd.link_set(ifaceobj.name, 'vlan_filtering', '1',
False, "bridge")
if not bridge_just_created:
ifaceobj.module_flags[self.name] = ifaceobj.module_flags.setdefault(self.name,0) | bridgeFlags.PORT_PROCESSED_OVERRIDE
elif (not bridge_just_created and
ifaceobj.get_attr_value_first('bridge-vlan-aware') == 'no'
and self.ipcmd.bridge_is_vlan_aware(ifaceobj.name)):
self.ipcmd.link_set(ifaceobj.name, 'vlan_filtering', '0',
False, "bridge")
bridge_vlan_aware = False
except Exception, e:
raise Exception(str(e))
@@ -1129,12 +1197,12 @@ class bridge(moduleBase):
# disable ipv6 for ports that were added to bridge
self.handle_ipv6(running_ports, '1', ifaceobj=ifaceobj)
self._apply_bridge_port_settings_all(ifaceobj,
ifaceobj_getfunc=ifaceobj_getfunc)
ifaceobj_getfunc=ifaceobj_getfunc,
bridge_vlan_aware=bridge_vlan_aware)
except Exception, e:
err = True
errstr = str(e)
pass
#self._flush_running_vidinfo()
finally:
if ifaceobj.link_type != ifaceLinkType.LINK_NA:
for p in running_ports:
@@ -1165,12 +1233,11 @@ class bridge(moduleBase):
def _query_running_vidinfo_compat(self, ifaceobjrunning, ports):
running_attrs = {}
running_vidinfo = self._get_running_vidinfo()
if ports:
running_bridge_port_vids = ''
for p in ports:
try:
running_vids = running_vidinfo.get(p, {}).get('vlan')
running_vids = self._get_runing_vids(p)
if running_vids:
running_bridge_port_vids += ' %s=%s' %(p,
','.join(running_vids))
@@ -1178,41 +1245,36 @@ class bridge(moduleBase):
pass
running_attrs['bridge-port-vids'] = running_bridge_port_vids
running_bridge_port_pvids = ''
running_bridge_port_pvid = ''
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)
running_pvid = self._get_runing_pvid(p)
if running_pvid:
running_bridge_port_pvid += ' %s=%s' %(p,
running_pvid)
except Exception:
pass
running_attrs['bridge-port-pvids'] = running_bridge_port_pvids
running_attrs['bridge-port-pvids'] = running_bridge_port_pvid
running_bridge_vids = running_vidinfo.get(ifaceobjrunning.name,
{}).get('vlan')
running_bridge_vids = self._get_running_vids(ifaceobjrunning.name)
if running_bridge_vids:
running_attrs['bridge-vids'] = ','.join(running_bridge_vids)
running_attrs['bridge-vids'] = ','.join(self._compress_into_ranges(running_bridge_vids))
return running_attrs
def _query_running_vidinfo(self, ifaceobjrunning, ifaceobj_getfunc,
bridgeports=None):
running_attrs = {}
running_vidinfo = self._get_running_vidinfo()
if not running_vidinfo:
return running_attrs
# 'bridge-vids' under the bridge is all about 'vids' on the port.
# so query the ports
running_bridgeport_vids = []
running_bridgeport_pvids = []
for bport in bridgeports:
vids = running_vidinfo.get(bport, {}).get('vlan')
(vids, pvid) = self._get_running_vids_n_pvid_str(bport)
if vids:
running_bridgeport_vids.append(' '.join(vids))
pvids = running_vidinfo.get(bport, {}).get('pvid')
if pvids:
running_bridgeport_pvids.append(pvids)
if pvid:
running_bridgeport_pvids.append(pvid)
bridge_vids = None
if running_bridgeport_vids:
@@ -1226,26 +1288,29 @@ class bridge(moduleBase):
(vidval, freq) = Counter(running_bridgeport_pvids).most_common()[0]
if freq == len(bridgeports) and vidval != '1':
running_attrs['bridge-pvid'] = vidval
bridge_pvid = vidval.split()
bridge_pvid = vidval.split()[0]
# Go through all bridge ports and find their vids
for bport in bridgeports:
bportifaceobj = ifaceobj_getfunc(bport)
if not bportifaceobj:
continue
bport_vids = None
bport_pvids = None
vids = running_vidinfo.get(bport, {}).get('vlan')
bport_vids = []
bport_pvid = None
(vids, pvid) = self._get_running_vids_n_pvid_str(bport)
if vids and vids != bridge_vids:
bport_vids = vids
pvids = running_vidinfo.get(bport, {}).get('pvid')
if pvids and pvids[0] != bridge_pvid:
bport_pvids = pvids
if not bport_vids and bport_pvids and bport_pvids[0] != '1':
bportifaceobj[0].replace_config('bridge-access', bport_pvids[0])
if pvid and pvid != bridge_pvid:
bport_pvid = pvid
if bport_vids and bport_pvid in bport_vids:
bport_vids.remove(bport_pvid)
if (not bport_vids and bport_pvid and bport_pvid != '1'):
bportifaceobj[0].replace_config('bridge-access', bport_pvid)
bportifaceobj[0].delete_config('bridge-pvid')
bportifaceobj[0].delete_config('bridge-vids')
else:
if bport_pvids and bport_pvids[0] != '1':
bportifaceobj[0].replace_config('bridge-pvid', bport_pvids[0])
if bport_pvid and bport_pvid != '1':
bportifaceobj[0].replace_config('bridge-pvid', bport_pvid)
else:
# delete any stale bridge-vids under ports
bportifaceobj[0].delete_config('bridge-pvid')
@@ -1291,6 +1356,7 @@ class bridge(moduleBase):
if stp == 'yes' and userspace_stp:
skip_kernel_stp_attrs = 1
bool2str = {'0': 'no', '1': 'yes'}
# pick all other attributes
for k,v in tmpbridgeattrdict.items():
if not v:
@@ -1302,7 +1368,11 @@ class bridge(moduleBase):
# only include igmp attributes if kernel stp is off
continue
attrname = 'bridge-' + k
if v != self.get_mod_subattr(attrname, 'default'):
mod_default = self.get_mod_subattr(attrname, 'default')
if v != mod_default:
# convert '0|1' running values to 'no|yes'
if v in bool2str.keys() and bool2str[v] == mod_default:
continue
bridgeattrdict[attrname] = [v]
if bridge_vlan_aware:
@@ -1323,7 +1393,8 @@ class bridge(moduleBase):
if skip_kernel_stp_attrs:
return bridgeattrdict
if ports:
# Do this only for vlan-UNAWARE-bridge
if ports and not bridge_vlan_aware:
portconfig = {'bridge-pathcosts' : '',
'bridge-portprios' : ''}
for p, v in ports.items():
@@ -1354,7 +1425,6 @@ class bridge(moduleBase):
def _query_check_bridge_vidinfo(self, ifaceobj, ifaceobjcurr):
err = 0
running_vidinfo = self._get_running_vidinfo()
attrval = ifaceobj.get_attr_value_first('bridge-port-vids')
if attrval:
running_bridge_port_vids = ''
@@ -1368,7 +1438,7 @@ class bridge(moduleBase):
try:
(port, val) = p.split('=')
vids = val.split(',')
running_vids = running_vidinfo.get(port, {}).get('vlan')
running_vids = self._get_running_vids(port)
if running_vids:
if not self._compare_vids(vids, running_vids):
err += 1
@@ -1400,7 +1470,7 @@ class bridge(moduleBase):
for p in portlist:
try:
(port, pvid) = p.split('=')
running_pvid = running_vidinfo.get(port, {}).get('pvid')
running_pvid = self._get_running_vids(port)
if running_pvid and running_pvid == pvid:
running_bridge_port_pvids += ' %s' %p
else:
@@ -1417,24 +1487,7 @@ class bridge(moduleBase):
ifaceobjcurr.update_config_with_status('bridge-port-pvids',
running_bridge_port_pvids, 0)
# XXX: No need to check for bridge-vids on the bridge
# This is used by the ports. The vids on the bridge
# come from the vlan interfaces on the bridge.
#
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)
if attrval:
ifaceobjcurr.update_config_with_status('bridge-vids', attrval, -1)
@@ -1588,57 +1641,67 @@ class bridge(moduleBase):
def _query_check_bridge_port_vidinfo(self, ifaceobj, ifaceobjcurr,
ifaceobj_getfunc, bridgename):
running_vidinfo = self._get_running_vidinfo()
attr_name = 'bridge-access'
vids = ifaceobj.get_attr_value_first(attr_name)
if vids:
running_pvids = running_vidinfo.get(ifaceobj.name,
{}).get('pvid')
running_vids = running_vidinfo.get(ifaceobj.name,
{}).get('vlan')
if (not running_pvids or running_pvids != vids or
running_vids):
vid = ifaceobj.get_attr_value_first(attr_name)
if vid:
(running_vids, running_pvid) = self._get_running_vids_n_pvid_str(
ifaceobj.name)
if (not running_pvid or running_pvid != vid or
(running_vids and running_vids[0] != vid)):
ifaceobjcurr.update_config_with_status(attr_name,
running_pvids, 1)
else:
ifaceobjcurr.update_config_with_status(attr_name, vids, 0)
return
running_pvid, 1)
else:
ifaceobjcurr.update_config_with_status(attr_name, vid, 0)
return
running_pvid = running_vidinfo.get(ifaceobj.name,
{}).get('pvid')
(running_vids, running_pvid) = self._get_running_vids_n_pvid_str(
ifaceobj.name)
attr_name = 'bridge-pvid'
pvid = self._get_bridge_pvid(bridgename, ifaceobj_getfunc)
pvid = ifaceobj.get_attr_value_first('bridge-pvid')
if pvid:
if running_pvid and running_pvid == pvid:
ifaceobjcurr.update_config_with_status(attr_name,
running_pvid, 0)
else:
ifaceobjcurr.update_config_with_status(attr_name,
running_pvid, 1)
elif not running_pvid or running_pvid != '1':
ifaceobjcurr.status = ifaceStatus.ERROR
ifaceobjcurr.status_str = 'bridge pvid error'
if running_pvid and running_pvid == pvid:
ifaceobjcurr.update_config_with_status(attr_name,
running_pvid, 0)
else:
ifaceobjcurr.update_config_with_status(attr_name,
running_pvid, 1)
elif (not (ifaceobj.flags & iface.HAS_SIBLINGS) or
((ifaceobj.flags & iface.HAS_SIBLINGS) and
(ifaceobj.flags & iface.OLDEST_SIBLING))):
# if the interface has multiple iface sections,
# we check the below only for the oldest sibling
# or the last iface section
pvid = self._get_bridge_pvid(bridgename, ifaceobj_getfunc)
if pvid:
if not running_pvid or running_pvid != pvid:
ifaceobjcurr.status = ifaceStatus.ERROR
ifaceobjcurr.status_str = 'bridge pvid error'
elif not running_pvid or running_pvid != '1':
ifaceobjcurr.status = ifaceStatus.ERROR
ifaceobjcurr.status_str = 'bridge pvid error'
attr_name = 'bridge-vids'
vids = ifaceobj.get_attr_value_first(attr_name)
if vids:
vids = re.split(r'[\s\t]\s*', vids)
running_vids = running_vidinfo.get(ifaceobj.name,
{}).get('vlan')
if not running_vids or not self._compare_vids(vids, running_vids):
if not running_vids or not self._compare_vids(vids, running_vids,
running_pvid):
ifaceobjcurr.update_config_with_status(attr_name,
' '.join(running_vids), 1)
' '.join(running_vids), 1)
else:
ifaceobjcurr.update_config_with_status(attr_name,
' '.join(running_vids), 0)
else:
' '.join(vids), 0)
elif (not (ifaceobj.flags & iface.HAS_SIBLINGS) or
((ifaceobj.flags & iface.HAS_SIBLINGS) and
(ifaceobj.flags & iface.OLDEST_SIBLING))):
# if the interface has multiple iface sections,
# we check the below only for the oldest sibling
# or the last iface section
# check if it matches the bridge vids
bridge_vids = self._get_bridge_vids(bridgename, ifaceobj_getfunc)
running_vids = running_vidinfo.get(ifaceobj.name,
{}).get('vlan')
if (bridge_vids and (not running_vids or
not self._compare_vids(bridge_vids, running_vids, pvid))):
not self._compare_vids(bridge_vids, running_vids, running_pvid))):
ifaceobjcurr.status = ifaceStatus.ERROR
ifaceobjcurr.status_str = 'bridge vid error'
@@ -1663,9 +1726,9 @@ class bridge(moduleBase):
ifaceobj_getfunc,
bridgename)
for attr, dstattr in {'bridge-pathcosts' : 'pathcost',
'bridge-portprios' : 'priority',
'bridge-portmcrouter' : 'mcrouter',
'bridge-portmcfl' : 'mcfl' }.items():
'bridge-portprios' : 'portprio',
'bridge-portmcrouter' : 'portmcrouter',
'bridge-portmcfl' : 'portmcfl' }.items():
attrval = ifaceobj.get_attr_value_first(attr)
if not attrval:
continue
@@ -1674,7 +1737,7 @@ class bridge(moduleBase):
running_attrval = self.brctlcmd.get_bridgeport_attr(
bridgename, ifaceobj.name, dstattr)
if dstattr == 'mcrouter':
if dstattr == 'portmcrouter':
if not utils.is_binary_bool(attrval) and running_attrval:
running_attrval = utils.get_yesno_boolean(
utils.get_boolean_from_string(running_attrval))
@@ -1720,6 +1783,7 @@ class bridge(moduleBase):
def _query_running_bridge_port(self, ifaceobjrunning,
ifaceobj_getfunc=None):
bridgename = self.ipcmd.bridge_port_get_bridge_name(
ifaceobjrunning.name)
bridge_vids = None
@@ -1731,11 +1795,8 @@ class bridge(moduleBase):
if not self.ipcmd.bridge_is_vlan_aware(bridgename):
return
running_vidinfo = self._get_running_vidinfo()
bridge_port_vids = running_vidinfo.get(ifaceobjrunning.name,
{}).get('vlan')
bridge_port_pvid = running_vidinfo.get(ifaceobjrunning.name,
{}).get('pvid')
(bridge_port_vids, bridge_port_pvid) = self._get_running_vids_n_pvid_str(
ifaceobjrunning.name)
bridgeifaceobjlist = ifaceobj_getfunc(bridgename)
if bridgeifaceobjlist:
@@ -1834,7 +1895,7 @@ class bridge(moduleBase):
if not op_handler:
return
self._init_command_handlers()
self._flush_running_vidinfo()
#self._flush_running_vidinfo()
if operation == 'query-checkcurr':
op_handler(self, ifaceobj, query_ifaceobj,
ifaceobj_getfunc=ifaceobj_getfunc)

View File

@@ -25,7 +25,7 @@ class bridgevlan(moduleBase):
'bridge-igmp-querier-src' :
{ 'help' : 'bridge igmp querier src. Must be ' +
'specified under the vlan interface',
'validvals' : [IPv4Address, ],
'validvals' : ['<ipv4>', ],
'example' : ['bridge-igmp-querier-src 172.16.101.1']}}}
def __init__(self, *args, **kargs):

View File

@@ -13,6 +13,9 @@ try:
from ifupdownaddons.dhclient import dhclient
from ifupdownaddons.iproute2 import iproute2
import ifupdown.ifupdownflags as ifupdownflags
from ifupdown.utils import utils
import time
from ifupdown.netlink import netlink
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
@@ -65,6 +68,9 @@ class dhcp(moduleBase):
self.dhclientcmd.stop6(ifaceobj.name)
except:
pass
#add delay before starting IPv6 dhclient to
#make sure the configured interface/link is up.
time.sleep(2)
self.dhclientcmd.start6(ifaceobj.name, wait=wait,
cmd_prefix=dhclient_cmd_prefix)
except Exception, e:
@@ -76,7 +82,10 @@ class dhcp(moduleBase):
if (vrf and self.vrf_exec_cmd_prefix and
self.ipcmd.link_exists(vrf)):
dhclient_cmd_prefix = '%s %s' %(self.vrf_exec_cmd_prefix, vrf)
self.dhclientcmd.release(ifaceobj.name, dhclient_cmd_prefix)
if ifaceobj.addr_family == 'inet6':
self.dhclientcmd.release6(ifaceobj.name, dhclient_cmd_prefix)
else:
self.dhclientcmd.release(ifaceobj.name, dhclient_cmd_prefix)
self.ipcmd.link_down(ifaceobj.name)
def _query_check(self, ifaceobj, ifaceobjcurr):
@@ -108,6 +117,7 @@ class dhcp(moduleBase):
_run_ops = {'up' : _up,
'down' : _down,
'pre-down' : _down,
'query-checkcurr' : _query_check,
'query-running' : _query_running }

View File

@@ -97,11 +97,12 @@ class ethtool(moduleBase,utilsBase):
(ifaceobj.name in self.ifaceobjs_modified_configs)):
continue
# if we are not the oldest and we have no configs, do not change anything
# the only way a non-oldest sibling would change values is if it
# had configured settings
if (not ((ifaceobj.flags & iface.HAS_SIBLINGS) and
(ifaceobj.flags & iface.OLDEST_SIBLING)) and
# If we have siblings AND are not the oldest AND we have no configs,
# do not change anything. The only way a non-oldest sibling would
# change values is if it had configured settings. iface stanzas may
# not be squashed if addr_config_squash is not set so we still need this.
if ((ifaceobj.flags & iface.HAS_SIBLINGS) and
not (ifaceobj.flags & iface.OLDEST_SIBLING) and
not config_val):
continue
@@ -242,6 +243,10 @@ class ethtool(moduleBase,utilsBase):
# to see the defaults, we should implement another flag (--with-defaults)
if default_val == running_attr:
continue
# do not proceed if speed = 0
if attr == 'speed' and running_attr and running_attr == '0':
return
if running_attr:
ifaceobj.update_config('link-%s'%attr, running_attr)
@@ -249,8 +254,6 @@ class ethtool(moduleBase,utilsBase):
def _query(self, ifaceobj, **kwargs):
""" add default policy attributes supported by the module """
if ifaceobj.link_kind:
return
for attr in ['speed', 'duplex', 'autoneg']:
if ifaceobj.get_attr_value_first('link-%s'%attr):
continue
@@ -293,6 +296,8 @@ class ethtool(moduleBase,utilsBase):
of interfaces. status is success if the running state is same
as user required state in ifaceobj. error otherwise.
"""
if ifaceobj.link_kind:
return
op_handler = self._run_ops.get(operation)
if not op_handler:
return

View File

@@ -30,7 +30,7 @@ class mstpctl(moduleBase):
'new-attribute': 'bridge-ports'},
'mstpctl-stp' :
{'help': 'bridge stp yes/no',
'validvals' : ['yes', 'no'],
'validvals' : ['yes', 'no', 'on', 'off'],
'compat' : True,
'default' : 'no',
'deprecated': True,
@@ -79,6 +79,7 @@ class mstpctl(moduleBase):
'example' : ['mstpctl-forcevers rstp']},
'mstpctl-portpathcost' :
{ 'help' : 'bridge port path cost',
'validvals': ['<interface-range-list>'],
'validrange' : ['0', '65535'],
'default' : '0',
'jsonAttr' : 'adminExtPortCost',
@@ -89,7 +90,7 @@ class mstpctl(moduleBase):
{ 'help' : 'bridge port p2p detection mode',
'default' : 'auto',
'jsonAttr' : 'adminPointToPoint',
'validvals' : ['yes', 'no', 'auto'],
'validvals' : ['<interface-yes-no-auto-list>'],
'required' : False,
'example' : ['under the bridge: mstpctl-portp2p swp1=yes swp2=no',
'under the port (recommended): mstpctl-portp2p yes']},
@@ -98,7 +99,7 @@ class mstpctl(moduleBase):
'enable/disable port ability to take root role of the port',
'default' : 'no',
'jsonAttr' : 'restrictedRole',
'validvals' : ['yes', 'no'],
'validvals' : ['<interface-yes-no-list>'],
'required' : False,
'example' : ['under the bridge: mstpctl-portrestrrole swp1=yes swp2=no',
'under the port (recommended): mstpctl-portrestrrole yes']},
@@ -107,7 +108,7 @@ class mstpctl(moduleBase):
'enable/disable port ability to propagate received topology change notification of the port',
'default' : 'no',
'jsonAttr' : 'restrictedTcn',
'validvals' : ['yes', 'no'],
'validvals' : ['<interface-yes-no-list>'],
'required' : False,
'example' : ['under the bridge: mstpctl-portrestrtcn swp1=yes swp2=no',
'under the port (recommended): mstpctl-portrestrtcn yes']},
@@ -116,7 +117,7 @@ class mstpctl(moduleBase):
'enable/disable bpduguard',
'default' : 'no',
'jsonAttr' : 'bpduGuardPort',
'validvals' : ['yes', 'no'],
'validvals' : ['<interface-yes-no-list>'],
'required' : False,
'example' : ['under the bridge: mstpctl-bpduguard swp1=yes swp2=no',
'under the port (recommended): mstpctl-bpduguard yes']},
@@ -124,6 +125,7 @@ class mstpctl(moduleBase):
{ 'help' :
'port priority for MSTI instance',
'default' : '128',
'validvals': ['<interface-range-list>'],
'validrange' : ['0', '240'],
'required' : False,
'example' : ['under the bridge: mstpctl-treeportprio swp1=128 swp2=128',
@@ -136,7 +138,7 @@ class mstpctl(moduleBase):
'example' : ['mstpctl-hello 2']},
'mstpctl-portnetwork' :
{ 'help' : 'enable/disable bridge assurance capability for a port',
'validvals' : ['yes', 'no'],
'validvals' : ['<interface-yes-no-list>'],
'default' : 'no',
'jsonAttr' : 'networkPort',
'required' : False,
@@ -144,7 +146,7 @@ class mstpctl(moduleBase):
'under the port (recommended): mstpctl-portnetwork yes']},
'mstpctl-portadminedge' :
{ 'help' : 'enable/disable initial edge state of the port',
'validvals' : ['yes', 'no'],
'validvals' : ['<interface-yes-no-list>'],
'default' : 'no',
'jsonAttr' : 'adminEdgePort',
'required' : False,
@@ -152,7 +154,7 @@ class mstpctl(moduleBase):
'under the port (recommended): mstpctl-portadminedge yes']},
'mstpctl-portautoedge' :
{ 'help' : 'enable/disable auto transition to/from edge state of the port',
'validvals' : ['yes', 'no'],
'validvals' : ['<interface-yes-no-list>'],
'default' : 'yes',
'jsonAttr' : 'autoEdgePort',
'required' : False,
@@ -166,7 +168,7 @@ class mstpctl(moduleBase):
{ 'help' : 'enable/disable bpdu filter on a port. ' +
'syntax varies when defined under a bridge ' +
'vs under a port',
'validvals' : ['yes', 'no'],
'validvals' : ['<interface-yes-no-list>'],
'jsonAttr' : 'bpduFilterPort',
'default' : 'no',
'required' : False,
@@ -312,6 +314,8 @@ class mstpctl(moduleBase):
self.logger.warn('%s' %str(e))
pass
if self.ipcmd.bridge_is_vlan_aware(ifaceobj.name):
return
# set bridge port attributes
for attrname, dstattrname in self._port_attrs_map.items():
config_val = ifaceobj.get_attr_value_first(attrname)
@@ -560,7 +564,7 @@ class mstpctl(moduleBase):
except Exception, e:
self.log_error(str(e), ifaceobj)
def _query_running_attrs(self, ifaceobjrunning):
def _query_running_attrs(self, ifaceobjrunning, bridge_vlan_aware=False):
bridgeattrdict = {}
tmpbridgeattrdict = self.mstpctlcmd.get_bridge_attrs(ifaceobjrunning.name)
@@ -574,12 +578,16 @@ class mstpctl(moduleBase):
ports = v.keys()
continue
attrname = 'mstpctl-' + k
if v and v != self.get_mod_subattr(attrname, 'default'):
if (v and v != self.get_mod_subattr(attrname, 'default')
and attrname != 'mstpctl-maxhops'):
bridgeattrdict[attrname] = [v]
ports = self.brctlcmd.get_bridge_ports(ifaceobjrunning.name)
if ports:
portconfig = {'mstpctl-portnetwork' : '',
# Do this only for vlan-UNAWARE-bridge
if ports and not bridge_vlan_aware:
portconfig = {'mstpctl-portautoedge' : '',
'mstpctl-portbpdufilter' : '',
'mstpctl-portnetwork' : '',
'mstpctl-portpathcost' : '',
'mstpctl-portadminedge' : '',
'mstpctl-portautoedge' : '',
@@ -591,6 +599,16 @@ class mstpctl(moduleBase):
'mstpctl-treeportcost' : ''}
for p in ports:
v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
p, 'portautoedge')
if v and v != 'no':
portconfig['mstpctl-portautoedge'] += ' %s=%s' %(p, v)
v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
p, 'portbpdufilter')
if v and v != 'no':
portconfig['mstpctl-portbpdufilter'] += ' %s=%s' %(p, v)
v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
p, 'portnetwork')
if v and v != 'no':
@@ -634,11 +652,17 @@ class mstpctl(moduleBase):
# 'default'):
# portconfig['mstpctl-treeportprio'] += ' %s=%s' %(p, v)
#v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
# p, 'treecost')
#if v and v != self.get_mod_subattr('mstpctl-treeportcost',
# 'default'):
# portconfig['mstpctl-treeportcost'] += ' %s=%s' %(p, v)
v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
p, 'portpathcost')
if v and v != self.get_mod_subattr('mstpctl-portpathcost',
'default'):
portconfig['mstpctl-portpathcost'] += ' %s=%s' %(p, v)
v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
p, 'treeportcost')
if v and v != self.get_mod_subattr('mstpctl-treeportcost',
'default'):
portconfig['mstpctl-treeportcost'] += ' %s=%s' %(p, v)
bridgeattrdict.update({k : [v] for k, v in portconfig.items()
if v})
@@ -893,11 +917,25 @@ class mstpctl(moduleBase):
# if userspace stp not set, return
if self.sysctl_get('net.bridge.bridge-stp-user-space') != '1':
return
v = self.mstpctlcmd.get_bridgeport_attr(bridgename,
ifaceobjrunning.name,
'portautoedge')
if v and v != self.get_mod_subattr('mstpctl-portautoedge',
'default'):
ifaceobjrunning.update_config('mstpctl-portautoedge', v)
v = self.mstpctlcmd.get_bridgeport_attr(bridgename,
ifaceobjrunning.name,
'portbpdufilter')
if v and v != 'no':
ifaceobjrunning.update_config('mstpctl-portbpdufilter', v)
v = self.mstpctlcmd.get_bridgeport_attr(bridgename,
ifaceobjrunning.name,
'portnetwork')
if v and v != 'no':
ifaceobjrunning.update_config('mstpctl-network', v)
ifaceobjrunning.update_config('mstpctl-portnetwork', v)
# XXX: Can we really get path cost of a port ???
#v = self.mstpctlcmd.get_portpathcost(ifaceobjrunning.name, p)
@@ -921,7 +959,7 @@ class mstpctl(moduleBase):
ifaceobjrunning.update_config('mstpctl-portrestrrole', v)
v = self.mstpctlcmd.get_bridgeport_attr(bridgename,
ifaceobjrunning.name, 'restrtcn')
ifaceobjrunning.name, 'portrestrtcn')
if v and v != 'no':
ifaceobjrunning.update_config('mstpctl-portrestrtcn', v)
@@ -953,8 +991,12 @@ class mstpctl(moduleBase):
# Check if mstp really knows about this bridge
if not self.mstpctlcmd.mstpbridge_exists(ifaceobjrunning.name):
return
bridge_vlan_aware = False
if ifaceobjrunning.get_attr_value_first('bridge-vlan-aware') == 'yes':
bridge_vlan_aware = True
ifaceobjrunning.update_config_dict(self._query_running_attrs(
ifaceobjrunning))
ifaceobjrunning,
bridge_vlan_aware))
def _query_running(self, ifaceobjrunning, **extra_args):
if self.brctlcmd.bridge_exists(ifaceobjrunning.name):

View File

@@ -25,7 +25,7 @@ class vlan(moduleBase):
'attrs' : {
'vlan-raw-device' :
{'help' : 'vlan raw device',
'validvals' : ['<interface>' ,]},
'validvals': ['<interface>']},
'vlan-id' :
{'help' : 'vlan id',
'validrange' : ['0', '4096']}}}
@@ -176,22 +176,24 @@ class vlan(moduleBase):
else:
ifaceobjcurr.update_config_with_status('vlan-raw-device',
vlanrawdev, 0)
if vlanid != ifaceobj.get_attr_value_first('vlan-id'):
vlanid_config = ifaceobj.get_attr_value_first('vlan-id')
if not vlanid_config:
vlanid_config = str(self._get_vlan_id(ifaceobj))
if vlanid != vlanid_config:
ifaceobjcurr.update_config_with_status('vlan-id', vlanid, 1)
else:
ifaceobjcurr.update_config_with_status('vlan-id',
vlanid, 0)
ifaceobjcurr.update_config_with_status('vlan-id', vlanid, 0)
self._bridge_vid_check(ifaceobj, ifaceobjcurr, vlanrawdev, vlanid)
def _query_running(self, ifaceobjrunning):
if not self.ipcmd.link_exists(ifaceobjrunning.name):
return
if not self.ipcmd.get_vlandev_attrs(ifaceobjrunning.name):
(vlanrawdev, vlanid) = self.ipcmd.get_vlandev_attrs(ifaceobjrunning.name)
if not vlanid:
return
# If vlan name is not in the dot format, get the
# vlan dev and vlan id
if not '.' in ifaceobjrunning.name:
(vlanrawdev, vlanid) = self.ipcmd.get_vlandev_attrs(ifaceobjrunning.name)
ifaceobjrunning.update_config_dict({(k, v) for k, v in
{'vlan-raw-device' : vlanrawdev,
'vlan-id' : vlanid}.items()

View File

@@ -9,6 +9,8 @@ import signal
import errno
import fcntl
import atexit
import re
from sets import Set
from ifupdown.iface import *
from ifupdown.utils import utils
import ifupdown.policymanager as policymanager
@@ -33,9 +35,11 @@ class vrf(moduleBase):
'creating a vrf device. ' +
'Table id is either \'auto\' or '+
'\'valid routing table id\'',
'validvals': ['auto', '<number>'],
'example': ['vrf-table auto', 'vrf-table 1001']},
'vrf':
{'help' : 'vrf the interface is part of.',
'validvals': ['<text>'],
'example': ['vrf blue']}}}
iproute2_vrf_filename = '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
@@ -54,9 +58,18 @@ class vrf(moduleBase):
self.bondcmd = None
self.dhclientcmd = None
self.name = self.__class__.__name__
if ifupdownflags.flags.PERFMODE:
# if perf mode is set, remove vrf map file.
# start afresh. PERFMODE is set at boot
self.vrf_mgmt_devname = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-mgmt-devname')
if (ifupdownflags.flags.PERFMODE and
not (self.vrf_mgmt_devname and os.path.exists('/sys/class/net/%s'
%self.vrf_mgmt_devname))):
# if perf mode is set (PERFMODE is set at boot), and this is the first
# time we are calling ifup at boot (check for mgmt vrf existance at
# boot, make sure this is really the first invocation at boot.
# ifup is called with PERFMODE at boot multiple times (once for mgmt vrf
# and the second time with all auto interfaces). We want to delete
# the map file only the first time. This is to avoid accidently
# deleting map file with a valid mgmt vrf entry
if os.path.exists(self.iproute2_vrf_filename):
try:
self.logger.info('vrf: removing file %s'
@@ -85,6 +98,15 @@ class vrf(moduleBase):
#self.logger.info("vrf: ip -6 rule cache")
#self.logger.info(self.ip6_rule_cache)
self.l3mdev_checked = False
self.l3mdev4_rule = False
if self._l3mdev_rule(self.ip_rule_cache):
self.l3mdev4_rule = True
self.l3mdev_checked = True
self.l3mdev6_rule = False
if self._l3mdev_rule(self.ip6_rule_cache):
self.l3mdev6_rule = True
self.l3mdev_checked = True
self._iproute2_vrf_map_initialized = False
self.iproute2_vrf_map = {}
self.iproute2_vrf_map_fd = None
@@ -100,9 +122,10 @@ class vrf(moduleBase):
self.vrf_fix_local_table = True
self.vrf_count = 0
self.vrf_mgmt_devname = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-mgmt-devname')
self.vrf_helper = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-helper')
self.warn_on_vrf_map_write_err = True
def _iproute2_vrf_map_initialize(self, writetodisk=True):
if self._iproute2_vrf_map_initialized:
return
@@ -168,18 +191,35 @@ class vrf(moduleBase):
self._iproute2_vrf_map_initialized = True
self.vrf_count = len(self.iproute2_vrf_map)
def _iproute2_map_warn(self, errstr):
if self.warn_on_vrf_map_write_err:
if not os.path.exists('/etc/iproute2/rt_tables.d/'):
self.logger.info('unable to save iproute2 vrf to table ' +
'map (%s)\n' %errstr)
self.logger.info('cannot find /etc/iproute2/rt_tables.d.' +
' pls check if your iproute2 version' +
' supports rt_tables.d')
else:
self.logger.warn('unable to open iproute2 vrf to table ' +
'map (%s)\n' %errstr)
self.warn_on_vrf_map_write_err = False
def _iproute2_vrf_map_sync_to_disk(self):
if (ifupdownflags.flags.DRYRUN or
not self.iproute2_vrf_map_sync_to_disk):
return
self.logger.info('vrf: syncing table map to %s'
%self.iproute2_vrf_filename)
with open(self.iproute2_vrf_filename, 'w') as f:
f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
self.vrf_table_id_end))
for t, v in self.iproute2_vrf_map.iteritems():
f.write('%s %s\n' %(t, v))
f.flush()
try:
with open(self.iproute2_vrf_filename, 'w') as f:
f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
self.vrf_table_id_end))
for t, v in self.iproute2_vrf_map.iteritems():
f.write('%s %s\n' %(t, v))
f.flush()
except Exception, e:
self._iproute2_map_warn(str(e))
pass
def _iproute2_vrf_map_open(self, sync_vrfs=False, append=False):
self.logger.info('vrf: syncing table map to %s'
@@ -192,8 +232,7 @@ class vrf(moduleBase):
'%s' %fmode)
fcntl.fcntl(self.iproute2_vrf_map_fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
except Exception, e:
self.log_warn('vrf: error opening %s (%s)'
%(self.iproute2_vrf_filename, str(e)))
self._iproute2_map_warn(str(e))
return
if not append:
@@ -294,7 +333,7 @@ class vrf(moduleBase):
return True
def _up_vrf_slave_without_master(self, ifacename, vrfname, ifaceobj,
ifaceobj_getfunc):
vrf_master_objs):
""" If we have a vrf slave that has dhcp configured, bring up the
vrf master now. This is needed because vrf has special handling
in dhclient hook which requires the vrf master to be present """
@@ -307,10 +346,6 @@ class vrf(moduleBase):
self.logger.info('%s: vrf master %s exists returning'
%(ifacename, vrf_master))
return
vrf_master_objs = ifaceobj_getfunc(vrf_master)
if not vrf_master_objs:
self.logger.warn('%s: vrf master ifaceobj not found' %ifacename)
return
self.logger.info('%s: bringing up vrf master %s'
%(ifacename, vrf_master))
for mobj in vrf_master_objs:
@@ -362,14 +397,31 @@ class vrf(moduleBase):
if not upper or upper != vrfname:
self._handle_existing_connections(ifaceobj, vrfname)
self.ipcmd.link_set(ifacename, 'master', vrfname)
elif ifupdownflags.flags.ALL and ifaceobj:
self._up_vrf_slave_without_master(ifacename, vrfname, ifaceobj,
ifaceobj_getfunc)
elif ifaceobj:
vrf_master_objs = ifaceobj_getfunc(vrfname)
if not vrf_master_objs:
# this is the case where vrf is assigned to an interface
# but user has not provided a vrf interface.
# people expect you to warn them but go ahead with the
# rest of the config on that interface
netlink.link_set_updown(ifacename, "up")
self.log_error('vrf master ifaceobj %s not found'
%vrfname)
return
if (ifupdownflags.flags.ALL or
(ifupdownflags.flags.CLASS and
ifaceobj.classes and vrf_master_objs[0].classes and
Set(ifaceobj.classes).intersection(vrf_master_objs[0].classes))):
self._up_vrf_slave_without_master(ifacename, vrfname,
ifaceobj,
vrf_master_objs)
else:
master_exists = False
else:
master_exists = False
if master_exists:
netlink.link_set_updown(ifacename, "up")
elif ifupdownflags.flags.ALL:
else:
self.log_error('vrf %s not around, skipping vrf config'
%(vrfname), ifaceobj)
except Exception, e:
@@ -404,6 +456,22 @@ class vrf(moduleBase):
vrf_dev_name)
utils.exec_command(rule_cmd)
def _l3mdev_rule(self, ip_rules):
for rule in ip_rules:
if not re.search(r"\d.*from\s+all\s+lookup\s+\W?l3mdev-table\W?",
rule):
continue
return True
return False
def _rule_cache_fill(self):
ip_rules = utils.exec_command('/sbin/ip rule show').splitlines()
self.ip_rule_cache = [' '.join(r.split()) for r in ip_rules]
self.l3mdev4_rule = self._l3mdev_rule(self.ip_rule_cache)
ip_rules = utils.exec_command('/sbin/ip -6 rule show').splitlines()
self.ip6_rule_cache = [' '.join(r.split()) for r in ip_rules]
self.l3mdev6_rule = self._l3mdev_rule(self.ip6_rule_cache)
def _add_vrf_rules(self, vrf_dev_name, vrf_table):
pref = 200
ip_rule_out_format = '%s: from all %s %s lookup %s'
@@ -426,34 +494,54 @@ class vrf(moduleBase):
self.logger.info('%s: %s' % (vrf_dev_name, str(e)))
pass
if not self.l3mdev_checked:
self._rule_cache_fill()
self.l3mdev_checked = True
#Example ip rule
#200: from all oif blue lookup blue
#200: from all iif blue lookup blue
rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
if rule not in self.ip_rule_cache:
if not self.l3mdev4_rule and rule not in self.ip_rule_cache:
rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name,
vrf_dev_name)
utils.exec_command(rule_cmd)
rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
if rule not in self.ip_rule_cache:
if not self.l3mdev4_rule and rule not in self.ip_rule_cache:
rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name,
vrf_dev_name)
utils.exec_command(rule_cmd)
rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
if rule not in self.ip6_rule_cache:
if not self.l3mdev6_rule and rule not in self.ip6_rule_cache:
rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name,
vrf_dev_name)
utils.exec_command(rule_cmd)
rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
if rule not in self.ip6_rule_cache:
if not self.l3mdev6_rule and rule not in self.ip6_rule_cache:
rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
vrf_dev_name)
utils.exec_command(rule_cmd)
def _is_address_virtual_slaves(self, vrfobj, config_vrfslaves,
vrfslave):
# Address virtual lines on a vrf slave will create
# macvlan devices on the vrf slave and enslave them
# to the vrf master. This function checks if the
# vrf slave is such a macvlan interface.
# XXX: additional possible checks that can be done here
# are:
# - check if it is also a macvlan device of the
# format <vrf_slave>-v<int> created by the
# address virtual module
vrfslave_lowers = self.ipcmd.link_get_lowers(vrfslave)
if vrfslave_lowers:
if vrfslave_lowers[0] in config_vrfslaves:
return True
return False
def _add_vrf_slaves(self, ifaceobj, ifaceobj_getfunc=None):
running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
config_slaves = ifaceobj.lowerifaces
@@ -481,6 +569,9 @@ class vrf(moduleBase):
if del_slaves:
for s in del_slaves:
try:
if self._is_address_virtual_slaves(ifaceobj,
config_slaves, s):
continue
sobj = None
if ifaceobj_getfunc:
sobj = ifaceobj_getfunc(s)

View File

@@ -35,7 +35,7 @@ class vrrpd(moduleBase):
'example' : ['vrrp-priority 20']},
'vrrp-virtual-ip' :
{'help': 'set vrrp virtual ip',
'validvals' : [IPv4Address, ],
'validvals' : ['<ipv4>', ],
'example' : ['vrrp-virtual-ip 10.0.1.254']}}}
def __init__(self, *args, **kargs):

View File

@@ -17,20 +17,20 @@ class vxlan(moduleBase):
'attrs' : {
'vxlan-id' :
{'help' : 'vxlan id',
'validrange' : ['0', '4096'],
'validrange' : ['1', '16777214'],
'required' : True,
'example': ['vxlan-id 100']},
'vxlan-local-tunnelip' :
{'help' : 'vxlan local tunnel ip',
'validvals' : [IPv4Address, ],
'validvals' : ['<ipv4>', '<ipv6>'],
'example': ['vxlan-local-tunnelip 172.16.20.103']},
'vxlan-svcnodeip' :
{'help' : 'vxlan id',
'validvals' : [IPv4Address, ],
'validvals' : ['<ipv4>', '<ipv6>'],
'example': ['vxlan-svcnodeip 172.16.22.125']},
'vxlan-remoteip' :
{'help' : 'vxlan remote ip',
'validvals' : [IPv4Address, ],
'validvals' : ['<ipv4>', '<ipv6>'],
'example': ['vxlan-remoteip 172.16.22.127']},
'vxlan-learning' :
{'help' : 'vxlan learning yes/no',
@@ -66,19 +66,66 @@ class vxlan(moduleBase):
return True
return False
def _up(self, ifaceobj):
def _vxlan_create(self, ifaceobj):
vxlanid = ifaceobj.get_attr_value_first('vxlan-id')
if vxlanid:
self.ipcmd.link_create_vxlan(ifaceobj.name, vxlanid,
localtunnelip=ifaceobj.get_attr_value_first('vxlan-local-tunnelip'),
svcnodeip=ifaceobj.get_attr_value_first('vxlan-svcnodeip'),
remoteips=ifaceobj.get_attr_value('vxlan-remoteip'),
learning=utils.get_onoff_bool(ifaceobj.get_attr_value_first('vxlan-learning')),
ageing=ifaceobj.get_attr_value_first('vxlan-ageing'),
anycastip=self._clagd_vxlan_anycast_ip)
anycastip = self._clagd_vxlan_anycast_ip
group = ifaceobj.get_attr_value_first('vxlan-svcnodeip')
local = ifaceobj.get_attr_value_first('vxlan-local-tunnelip')
ageing = ifaceobj.get_attr_value_first('vxlan-ageing')
learning = utils.get_onoff_bool(ifaceobj.get_attr_value_first('vxlan-learning'))
if self.ipcmd.link_exists(ifaceobj.name):
vxlanattrs = self.ipcmd.get_vxlandev_attrs(ifaceobj.name)
# on ifreload do not overwrite anycast_ip to individual ip
# if clagd has modified
if vxlanattrs:
running_localtunnelip = vxlanattrs.get('local')
if (anycastip and running_localtunnelip and
anycastip == running_localtunnelip):
local = running_localtunnelip
netlink.link_add_vxlan(ifaceobj.name, vxlanid,
local=local,
learning=learning,
ageing=ageing,
group=group)
remoteips = ifaceobj.get_attr_value('vxlan-remoteip')
if not systemUtils.is_service_running(None, '/var/run/vxrd.pid'):
# figure out the diff for remotes and do the bridge fdb updates
# only if provisioned by user and not by vxrd
cur_peers = set(self.ipcmd.get_vxlan_peers(ifaceobj.name, group))
if remoteips:
new_peers = set(remoteips)
del_list = cur_peers.difference(new_peers)
add_list = new_peers.difference(cur_peers)
else:
del_list = cur_peers
add_list = []
try:
for addr in del_list:
self.ipcmd.bridge_fdb_del(ifaceobj.name,
'00:00:00:00:00:00',
None, True, addr)
except:
pass
try:
for addr in add_list:
self.ipcmd.bridge_fdb_append(ifaceobj.name,
'00:00:00:00:00:00',
None, True, addr)
except:
pass
if ifaceobj.addr_method == 'manual':
netlink.link_set_updown(ifaceobj.name, "up")
def _up(self, ifaceobj):
self._vxlan_create(ifaceobj)
def _down(self, ifaceobj):
try:
self.ipcmd.link_delete(ifaceobj.name)
@@ -167,6 +214,9 @@ class vxlan(moduleBase):
attrval = vxlanattrs.get('vxlanid')
if attrval:
ifaceobjrunning.update_config('vxlan-id', vxlanattrs.get('vxlanid'))
else:
# if there is no vxlan id, this is not a vxlan port
return
attrval = vxlanattrs.get('local')
if attrval:
ifaceobjrunning.update_config('vxlan-local-tunnelip', attrval)