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:
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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':
|
||||
|
441
addons/bridge.py
441
addons/bridge.py
@@ -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)
|
||||
|
@@ -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):
|
||||
|
@@ -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 }
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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):
|
||||
|
@@ -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()
|
||||
|
141
addons/vrf.py
141
addons/vrf.py
@@ -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)
|
||||
|
@@ -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):
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user