original commit ported to the python3 branch:
commit
bffa619b11ae7aa9e567c26c255c17ac6df2c495
Author: Maximilian Wilhelm <max@rfc2324.org>
Date: Sat Jan 14 19:08:01 2017 +0100
Add option 'veth-peer-name' to veth links and ensure proper configuration.
The option »veth-peer-name« forces an veth peer link to be created with
a specific interface name. As the interface name of the "local" part of
the veth link pair already is defined by the name of the interface stanza
this option is added to, now both sides are clearly named.
As there is a bidirectional dependency of both link pairs - both cannot
exist without the other - this presents a problem when setting up all
interfaces. Depending on which interface is set up first there might be
a problem when only on dependency is specified. Therefore adding the
»veth-peer-name« option to both interface of the veth link pair ensures
that regardless of which side is configured first the peer name will be
set correctly. This intentionally creates a circular dependency which is
handled accordingly.
Fixing the config check for veth link-type while at it :)
Signed-off-by: Maximilian Wilhelm <max@rfc2324.org>
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
* New: bridge-always-up attribute
* New: set bridge mtu with policy default
* New: ES bond with "es-sys-mac" attribute
+ * New: support for "veth-peer-name" attribute
* New: dhcp policy: dhclient_retry_on_failure
* New: support for marking interfaces as mgmt interfaces
* New: bridge-vlan-vni-map attribute (single vxlan device)
"example": ["link-down yes/no"],
"default": "no",
"validvals": ["yes", "no"]
+ },
+ "veth-peer-name": {
+ "help": "Name of the veth peer interface.",
+ "validvals": "<interface>",
+ "example": ["veth-peer-name veth_ext2int"]
}
}
}
if ifaceobj.get_attr_value_first('link-type'):
ifaceobj.link_kind = ifaceLinkKind.OTHER
+ link_type = ifaceobj.get_attr_value_first("link-type")
+ # If this interface is one side of a veth link pair and a name for
+ # the peer interface if given, pass it to the link_create call.
+ if link_type == "veth" and ifaceobj.get_attr_value_first("veth-peer-name"):
+ return [ifaceobj.get_attr_value_first("veth-peer-name")]
+
+ return None
+
def _up(self, ifaceobj):
- link_type = ifaceobj.get_attr_value_first('link-type')
- if link_type:
+ link_type = ifaceobj.get_attr_value_first("link-type")
+
+ # If this interface is one side of a veth link pair and a name for
+ # the peer interface if given, pass it to the link_create call.
+ if link_type == "veth":
+ peer_name = ifaceobj.get_attr_value_first("veth-peer-name")
+
+ if peer_name and not self.cache.link_exists(ifaceobj.name):
+ self.iproute2.link_add_veth(ifaceobj.name, peer_name)
+
+ elif link_type:
self.netlink.link_add(ifname=ifaceobj.name, kind=link_type)
def _down(self, ifaceobj):
if ulist: ret_ulist.extend(ulist)
return list(set(ret_ulist))
+ def _remove_circular_veth_dependencies(self, ifaceobj, dlist):
+ # if ifaceobj isn't a veth link, ignore it.
+ if ifaceobj.get_attr_value_first('link-type') != "veth":
+ return
+
+ for diface in dlist:
+ difaceobj = self.get_ifaceobj_first(diface)
+ # If the dependent iface isn't a veth link - which shouldn't
+ # happen - ignore it to be save.
+ if difaceobj and difaceobj.get_attr_value_first('link-type') != "veth":
+ continue
+
+ # If the peer has a desired peer name set and this is us,
+ # see if the peer has a dependency to us too and remove our
+ # redundant dependency to the peer.
+ diface_peer_name = difaceobj.get_attr_value_first('veth-peer-name')
+ if diface_peer_name and diface_peer_name == ifaceobj.name:
+ peer_dlist = difaceobj.lowerifaces
+ if not peer_dlist:
+ # Not list of dependent interface on the peer.
+ continue
+
+ # We aleady are in the peers dlist, don't add dependcy from us to peer
+ if ifaceobj.name in peer_dlist:
+ dlist.remove(difaceobj.name)
+
def populate_dependency_info(self, ops, ifacenames=None):
""" recursive function to generate iface dependency info """
if dependents_processed:
continue
if dlist:
+ self._remove_circular_veth_dependencies(ifaceobj, dlist)
self.preprocess_dependency_list(ifaceobj,
dlist, ops)
ifaceobj.lowerifaces = dlist
###
+ def link_add_veth(self, ifname, peer_name):
+ utils.exec_command(
+ "%s link add %s type veth peer name %s"
+ % (utils.ip_cmd, ifname, peer_name)
+ )
+
+ ###
+
def link_add_single_vxlan(self, ifname, ip, port):
self.logger.info("creating single vxlan device: %s" % ifname)