'dual connected VxLANs',
'validvals' : ['<ipv4>', ],
'example' : ['clagd-vxlan-anycast-ip 36.0.0.11']},
+ 'arp-accept' :
+ { 'help': 'Allow gratuitous arp to update arp table',
+ 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
+ 'default' : 'off',
+ 'example' : ['arp-accept on']},
'ip-forward' :
{ 'help': 'ip forwarding flag',
'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
def _process_bridge(self, ifaceobj, up):
hwaddress = self._get_hwaddress(ifaceobj)
addrs = ifaceobj.get_attr_value_first('address')
+ arp_accept = ifaceobj.get_attr_value_first('arp-accept')
+ arp_accept = utils.boolean_support_binary(arp_accept)
is_vlan_dev_on_vlan_aware_bridge = False
is_bridge = self.ipcmd.is_bridge(ifaceobj.name)
if not is_bridge:
self.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj.name +
'/arp_accept', '0')
else:
- self.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj.name, '0')
+ self.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj.name, arp_accept)
if hwaddress and is_vlan_dev_on_vlan_aware_bridge:
- if up:
- self.ipcmd.bridge_fdb_add(bridgename, hwaddress, vlan)
- else:
- self.ipcmd.bridge_fdb_del(bridgename, hwaddress, vlan)
+ if up:
+ # check statemanager to delete the old entry if necessary
+ try:
+ for old_obj in statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name) or []:
+ old_hwaddress = old_obj.get_attr_value_first("hwaddress")
+ if old_hwaddress and self.ipcmd.mac_str_to_int(old_hwaddress) != self.ipcmd.mac_str_to_int(hwaddress):
+ self.ipcmd.bridge_fdb_del(bridgename, old_hwaddress, vlan)
+ break
+ except:
+ pass
+ self.ipcmd.bridge_fdb_add(bridgename, hwaddress, vlan)
+ else:
+ self.ipcmd.bridge_fdb_del(bridgename, hwaddress, vlan)
def _get_anycast_addr(self, ifaceobjlist):
for ifaceobj in ifaceobjlist:
if addr_method not in ["dhcp", "ppp"]:
self._inet_address_config(ifaceobj, ifaceobj_getfunc,
force_reapply)
+ else:
+ # remove old addresses added by ifupdown2
+ # (if intf was moved from static config to dhcp)
+ for old_ifaceobj in statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name) or []:
+ for addr in old_ifaceobj.get_attr_value("address") or []:
+ self.ipcmd.addr_del(ifaceobj.name, addr)
self.process_mtu(ifaceobj, ifaceobj_getfunc)
else:
return None
+ def enable_ipv6_if_prev_brport(self, ifname):
+ """
+ If the intf was previously enslaved to a bridge it is possible ipv6 is still disabled.
+ """
+ try:
+ if os.path.exists("/sys/class/net/%s/brport" % ifname):
+ self.write_file("/proc/sys/net/ipv6/conf/%s/disable_ipv6" % ifname, "0")
+ except Exception, e:
+ self.logger.info(str(e))
+
def _is_clag_bond(self, ifaceobj):
if self.get_bond_slaves(ifaceobj):
attrval = ifaceobj.get_attr_value_first('clag-id')
netlink.link_set_protodown(slave, "on")
except Exception, e:
self.logger.error('%s: %s' % (ifaceobj.name, str(e)))
+ self.enable_ipv6_if_prev_brport(slave)
netlink.link_set_master(slave, ifaceobj.name)
if link_up or ifaceobj.link_type != ifaceLinkType.LINK_NA:
try:
try:
import ifupdown2.ifupdown.policymanager as policymanager
import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
+ from ifupdown2.ifupdown.statemanager import statemanager_api as statemanager
from ifupdown2.ifupdown.iface import *
from ifupdown2.ifupdown.utils import utils
except ImportError:
import ifupdown.policymanager as policymanager
import ifupdown.ifupdownflags as ifupdownflags
+ from ifupdown.statemanager import statemanager_api as statemanager
from ifupdown.iface import *
from ifupdown.utils import utils
raise
break
self._handle_existing_connections(ifaceobj, vrfname)
+ self.enable_ipv6_if_prev_brport(ifacename)
self.ipcmd.link_set(ifacename, 'master', vrfname)
return
+ def enable_ipv6_if_prev_brport(self, ifname):
+ """
+ If the intf was previously enslaved to a bridge it is possible ipv6 is still disabled.
+ """
+ try:
+ if os.path.exists("/sys/class/net/%s/brport" % ifname):
+ self.write_file("/proc/sys/net/ipv6/conf/%s/disable_ipv6" % ifname, "0")
+ except Exception, e:
+ self.logger.info(str(e))
+
def _down_dhcp_slave(self, ifaceobj, vrfname):
try:
dhclient_cmd_prefix = None
uppers = self.ipcmd.link_get_uppers(ifacename)
if not uppers or vrfname not in uppers:
self._handle_existing_connections(ifaceobj, vrfname)
+ self.enable_ipv6_if_prev_brport(ifacename)
self.ipcmd.link_set(ifacename, 'master', vrfname)
elif ifaceobj:
vrf_master_objs = ifaceobj_getfunc(vrfname)
if self.flags.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
return self.statemanager.dump_pretty(ifacenames)
self.flags.STATEMANAGER_UPDATE = False
+
+ iface_read_ret = True
+
if auto:
self.logger.debug('setting flag ALL')
ifupdownflags.flags.ALL = True
ifacePrivFlags(False, True)), ifacenames)
else:
try:
- self.read_iface_config()
+ iface_read_ret = self.read_iface_config()
except Exception:
raise
if ops[0] == 'query' and ifupdownflags.flags.WITHDEFAULTS:
return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
elif ops[0] == 'query-checkcurr':
- ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
- if ret != 0:
+ if self.print_ifaceobjscurr_pretty(filtered_ifacenames, format):
# if any of the object has an error, signal that silently
raise Exception('')
elif ops[0] == 'query-running':
self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
return
+ if not iface_read_ret or not ret:
+ raise Exception()
+
def _reload_currentlyup(self, upops, downops, auto=False, allow=None,
ifacenames=None, excludepats=None, usecurrentconfig=False,
syntaxcheck=False, **extra_args):
not self.is_ifaceobj_builtin(newifaceobjlist[0]) and
lastifaceobjlist[0].is_config_present() and
lastifaceobjlist[0].link_kind):
- self.logger.warn('%s: misconfig ? removed but still exists '
- 'as a dependency of %s.\nPlease remove '
- 'the dependency manually `ifdown %s` if '
- 'it is being picked up as part of a regex'
- % (newifaceobjlist[objidx].name,
- str(newifaceobjlist[objidx].upperifaces),
- newifaceobjlist[objidx].name))
- if (lastifaceobjlist[0].link_kind and
+
+ # Check if interface is picked up by a regex in the upperifaces.
+ print_warning = True
+
+ for upper in newifaceobjlist[objidx].upperifaces or []:
+ slaves = []
+ for upper_ifaceobj in self.ifaceobjdict.get(upper):
+ slaves.extend(upper_ifaceobj.get_attr_value("bond-slaves") or [])
+ slaves.extend(upper_ifaceobj.get_attr_value("bridge-ports") or [])
+ slaves_string = " ".join(slaves)
+ if newifaceobjlist[objidx].name not in slaves_string:
+ print_warning = "regex" not in slaves_string
+ if not print_warning:
+ break
+ ###############################################################
+
+ warning_no_config_regex = (
+ "%s: misconfig ? removed but still exists as a dependency of %s.\n"
+ "Please remove the dependency manually `ifdown %s` if it is being "
+ "picked up as part of a regex" % (
+ newifaceobjlist[objidx].name,
+ str(newifaceobjlist[objidx].upperifaces),
+ newifaceobjlist[objidx].name
+ )
+ )
+
+ if print_warning:
+ self.logger.warn(warning_no_config_regex)
+ else:
+ # The warning shouldn't be printed because we've detected that this
+ # interface was pick up as part of a regex but the config doesn't
+ # exist anymore. It was most likely removed from the config file itself
+ # We should down this interface and remove it from the ifaceobjdict
+ # and dependency graph used for the following ifreload.
+ ifname_to_remove = newifaceobjlist[objidx].name
+ ifacedownlist.append(ifname_to_remove)
+
+ try:
+ if new_ifaceobjdict:
+ del new_ifaceobjdict[ifname_to_remove]
+
+ for k, v in new_dependency_graph.iteritems():
+ if ifname_to_remove in v:
+ v.remove(ifname_to_remove)
+ del new_dependency_graph[ifname_to_remove]
+ except Exception as e:
+ self.logger.warning(warning_no_config_regex)
+ self.logger.warning("while trying to fix this situation "
+ "we ran into the following issues: %s" % str(e))
+
+ elif (lastifaceobjlist[0].link_kind and
not newifaceobjlist[0].link_kind):
self.logger.warn('%s: moved from being a %s to a'
' physical interface (non-logical interface).'
log = Log()
-
-
-"""
-
-#logging.basicConfig( format="%(filename)s: %(username)s says '%(message)s' in %(funcname)s" )
-
-Logger.debug(msg, *args, **kwargs)
-Logs a message with level DEBUG on this logger. The msg is the message format string, and the args are the arguments which are merged into msg using the string formatting operator. (Note that this means that you can use keywords in the format string, together with a single dictionary argument.)
-
-There are two keyword arguments in kwargs which are inspected: exc_info which, if it does not evaluate as false, causes exception information to be added to the logging message. If an exception tuple (in the format returned by sys.exc_info()) is provided, it is used; otherwise, sys.exc_info() is called to get the exception information.
-
-"""
-
-"""
-USE FILTER TO IGNORE "EXITS" MESSAGES
-Now that you know the basic plot, let me introduce one more character - the Filter.
-Filter as the name suggests, allows you to filter a message before you log it. Yes, messages are filtered based on the level setting, but adding a Filter gives you more fine grained control of messages you log.
-Both Loggers and Handlers can have multiple Filters. You can add Filters using addFilter and removeFilter methods.
-When a Logger/Handler receives a message, it consults all of its filters. If the filter(record) method on any of the Filters attached returns False (or 0) the message is dropped.
-The official documentation, though detailed, is actually pretty confusing about the role of Filters. This is a pity; because Filters can be handy when you want to drop a message based on a regular expression, error code, contextual information and pretty much anything else. The default Filter is pretty much useless (and the doc string is very confusing too). Just inherit from the default filter and override the filter method according to what you want to filter out. (Be sure to download the source for logging module and check out the unit tests which have some good examples. See the references at the end of this post.)"""
obj = IPNetwork(ip)
if type(obj) == IPv6Network:
- ip6.append(obj)
+ ip6.append(str(obj))
else:
- ip4.append(obj)
+ ip4.append(str(obj))
running_ipobj = []
for ip in running_addrs or []:
- running_ipobj.append(IPNetwork(ip))
+ running_ipobj.append(str(IPNetwork(ip)))
return running_ipobj == (ip4 + ip6)
The TX socket is used for install requests, sending RTM_GETXXXX
requests, etc
"""
- self.tx_socket = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, 0)
- self.tx_socket.bind((self.pid, 0))
+ try:
+ self.tx_socket = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, 0)
+
+ # bind retry mechanism:
+ # in some cases we are running into weird issues... Address already in use
+ # to counter this problem, we will retry up to NLMANAGER_BIND_RETRY times to
+ # bind our socket, every time increasing the address (or pid) that we bind it
+ # to. NLMANAGER_BIND_RETRY default to 4242
+ for i in xrange(0, int(os.getenv("NLMANAGER_BIND_RETRY", 4242))):
+ try:
+ self.tx_socket.bind((self.pid + i, 0))
+ # the bind call succeeded, we need to update self.pid
+ # to reflect the correct value we are binded to. If we
+ # couldn't bind to our real pid (os.getpid()) warn user
+ # to avoid confusion (via debug logs).
+ if i != 0:
+ log.debug(
+ "nlmanager: pid %s already in use - binding netlink socket to pid %s"
+ % (self.pid, self.pid + i)
+ )
+ self.pid = self.pid + i
+ return
+ except:
+ pass
+ # if we reach this code it means all our bind calls failed. We are trying to
+ # bind the socket one last time on the original parameters if not we will not
+ # be catching the exception
+ self.tx_socket.bind((self.pid, 0))
+ except:
+ if self.tx_socket:
+ self.tx_socket.close()
+ self.tx_socket = None
+ raise
def tx_nlpacket_raw(self, message):
"""