122 lines
4.0 KiB
Python
122 lines
4.0 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
import ipaddress
|
|
|
|
import pyroute2
|
|
from pyroute2.netlink.rtnl import ifinfmsg
|
|
import six
|
|
|
|
from kuryr.lib import constants
|
|
|
|
|
|
_IPDB_CACHE = None
|
|
_IPROUTE_CACHE = None
|
|
|
|
FIXED_IP_KEY = 'fixed_ips'
|
|
IP_ADDRESS_KEY = 'ip_address'
|
|
MAC_ADDRESS_KEY = 'mac_address'
|
|
SUBNET_ID_KEY = 'subnet_id'
|
|
|
|
|
|
def get_veth_pair_names(port_id):
|
|
ifname = constants.VETH_PREFIX + port_id
|
|
ifname = ifname[:constants.NIC_NAME_LEN]
|
|
peer_name = constants.CONTAINER_VETH_PREFIX + port_id
|
|
peer_name = peer_name[:constants.NIC_NAME_LEN]
|
|
return ifname, peer_name
|
|
|
|
|
|
def get_ipdb():
|
|
"""Returns the already cached or a newly created IPDB instance.
|
|
|
|
IPDB reads the Linux specific file when it's instantiated. This behaviour
|
|
prevents Mac OSX users from running unit tests. This function makes the
|
|
loading IPDB lazyily and therefore it can be mocked after the import of
|
|
modules that import this module.
|
|
|
|
:returns: The already cached or newly created ``pyroute2.IPDB`` instance
|
|
"""
|
|
global _IPDB_CACHE
|
|
if not _IPDB_CACHE:
|
|
_IPDB_CACHE = pyroute2.IPDB()
|
|
return _IPDB_CACHE
|
|
|
|
|
|
def get_iproute():
|
|
"""Returns the already cached or a newly created IPRoute instance.
|
|
|
|
IPRoute reads the Linux specific file when it's instantiated. This
|
|
behaviour prevents Mac OSX users from running unit tests. This function
|
|
makes the loading IPDB lazyily and therefore it can be mocked after the
|
|
import of modules that import this module.
|
|
|
|
:returns: The already cached or newly created ``pyroute2.IPRoute`` instance
|
|
"""
|
|
global _IPROUTE_CACHE
|
|
if not _IPROUTE_CACHE:
|
|
_IPROUTE_CACHE = pyroute2.IPRoute()
|
|
return _IPROUTE_CACHE
|
|
|
|
|
|
def remove_device(ifname):
|
|
"""Removes the device with name ifname.
|
|
|
|
:param ifname: the name of the device to remove
|
|
:returns: the index the device identified by ifname had if it
|
|
exists, otherwise None
|
|
:raises: pyroute2.NetlinkError
|
|
"""
|
|
ipr = get_iproute()
|
|
|
|
devices = ipr.link_lookup(ifname=ifname)
|
|
if devices:
|
|
dev_index = devices[0]
|
|
ipr.link_remove(dev_index)
|
|
return dev_index
|
|
else:
|
|
return None
|
|
|
|
|
|
def is_up(interface):
|
|
flags = interface['flags']
|
|
if not flags:
|
|
return False
|
|
return (flags & ifinfmsg.IFF_UP) == 1
|
|
|
|
|
|
def _configure_container_iface(iface, subnets, fixed_ips, mtu=None,
|
|
hwaddr=None):
|
|
"""Configures the interface that is placed in the container net ns
|
|
|
|
:param iface: the pyroute IPDB interface object to configure
|
|
:param subnets: an iterable of all the Neutron subnets which the
|
|
endpoint is trying to join
|
|
:param fixed_ips: an iterable of fixed IPs to be set for the iface
|
|
:param mtu: Maximum Transfer Unit to set for the iface
|
|
:param hwaddr: Hardware address to set for the iface
|
|
"""
|
|
subnets_dict = {subnet['id']: subnet for subnet in subnets}
|
|
# We assume containers always work with fixed ips, dhcp does not really
|
|
# make a lot of sense
|
|
for fixed_ip in fixed_ips:
|
|
if IP_ADDRESS_KEY in fixed_ip and (SUBNET_ID_KEY in fixed_ip):
|
|
subnet_id = fixed_ip[SUBNET_ID_KEY]
|
|
subnet = subnets_dict[subnet_id]
|
|
cidr = ipaddress.ip_network(six.text_type(subnet['cidr']))
|
|
iface.add_ip(fixed_ip[IP_ADDRESS_KEY], cidr.prefixlen)
|
|
if mtu is not None:
|
|
iface.set_mtu(mtu)
|
|
if hwaddr is not None:
|
|
iface.set_address(hwaddr)
|
|
if not is_up(iface):
|
|
iface.up()
|