Merge "Nested CNI: Look for leftover ifaces to remove"
This commit is contained in:
@@ -34,6 +34,22 @@ LOG = logging.getLogger(__name__)
|
|||||||
class BaseBindingDriver(object):
|
class BaseBindingDriver(object):
|
||||||
"""Interface to attach ports to pods."""
|
"""Interface to attach ports to pods."""
|
||||||
|
|
||||||
|
def _remove_ifaces(self, ipdb, ifnames, netns='host'):
|
||||||
|
"""Check if any of `ifnames` exists and remove it.
|
||||||
|
|
||||||
|
:param ipdb: ipdb of the network namespace to check
|
||||||
|
:param ifnames: iterable of interface names to remove
|
||||||
|
:param netns: network namespace name (used for logging)
|
||||||
|
"""
|
||||||
|
for ifname in ifnames:
|
||||||
|
if ifname in ipdb.interfaces:
|
||||||
|
LOG.warning('Found hanging interface %(ifname)s inside '
|
||||||
|
'%(netns)s netns. Most likely it is a leftover '
|
||||||
|
'from a kuryr-daemon restart. Trying to delete '
|
||||||
|
'it.', {'ifname': ifname, 'netns': netns})
|
||||||
|
with ipdb.interfaces[ifname] as iface:
|
||||||
|
iface.remove()
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def connect(self, vif, ifname, netns, container_id):
|
def connect(self, vif, ifname, netns, container_id):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
@@ -32,16 +32,12 @@ class BaseBridgeDriver(health.HealthHandler, b_base.BaseBindingDriver):
|
|||||||
def connect(self, vif, ifname, netns, container_id):
|
def connect(self, vif, ifname, netns, container_id):
|
||||||
host_ifname = vif.vif_name
|
host_ifname = vif.vif_name
|
||||||
|
|
||||||
|
# NOTE(dulek): Check if we already run connect for this iface and if
|
||||||
|
# there's a leftover host-side vif. If so we need to
|
||||||
|
# remove it, its peer should get deleted automatically by
|
||||||
|
# the kernel.
|
||||||
with b_base.get_ipdb() as h_ipdb:
|
with b_base.get_ipdb() as h_ipdb:
|
||||||
if host_ifname in h_ipdb.interfaces:
|
self._remove_ifaces(h_ipdb, (host_ifname,))
|
||||||
# NOTE(dulek): This most likely means that we already run
|
|
||||||
# connect for this iface and there's a leftover
|
|
||||||
# host-side vif. Let's remove it, its peer should
|
|
||||||
# get deleted automatically by the kernel.
|
|
||||||
LOG.debug('Found leftover host vif %s. Removing it before '
|
|
||||||
'connecting.', host_ifname)
|
|
||||||
with h_ipdb.interfaces[host_ifname] as h_iface:
|
|
||||||
h_iface.remove()
|
|
||||||
|
|
||||||
if vif.network.mtu:
|
if vif.network.mtu:
|
||||||
interface_mtu = vif.network.mtu
|
interface_mtu = vif.network.mtu
|
||||||
|
@@ -15,6 +15,8 @@
|
|||||||
import abc
|
import abc
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from kuryr_kubernetes.cni.binding import base as b_base
|
from kuryr_kubernetes.cni.binding import base as b_base
|
||||||
from kuryr_kubernetes import config
|
from kuryr_kubernetes import config
|
||||||
from kuryr_kubernetes.handlers import health
|
from kuryr_kubernetes.handlers import health
|
||||||
@@ -24,6 +26,8 @@ VLAN_KIND = 'vlan'
|
|||||||
MACVLAN_KIND = 'macvlan'
|
MACVLAN_KIND = 'macvlan'
|
||||||
MACVLAN_MODE_BRIDGE = 'bridge'
|
MACVLAN_MODE_BRIDGE = 'bridge'
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class NestedDriver(health.HealthHandler, b_base.BaseBindingDriver):
|
class NestedDriver(health.HealthHandler, b_base.BaseBindingDriver):
|
||||||
@@ -36,19 +40,29 @@ class NestedDriver(health.HealthHandler, b_base.BaseBindingDriver):
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def connect(self, vif, ifname, netns, container_id):
|
def connect(self, vif, ifname, netns, container_id):
|
||||||
with b_base.get_ipdb() as h_ipdb:
|
# NOTE(vikasc): Ideally 'ifname' should be used here but instead a
|
||||||
# NOTE(vikasc): Ideally 'ifname' should be used here but instead a
|
# temporary name is being used while creating the device for
|
||||||
# temporary name is being used while creating the device for
|
# container in host network namespace. This is because cni expects
|
||||||
# container in host network namespace. This is because cni expects
|
# only 'eth0' as interface name and if host already has an
|
||||||
# only 'eth0' as interface name and if host already has an
|
# interface named 'eth0', device creation will fail with 'already
|
||||||
# interface named 'eth0', device creation will fail with 'already
|
# exists' error.
|
||||||
# exists' error.
|
temp_name = vif.vif_name
|
||||||
temp_name = vif.vif_name
|
|
||||||
|
|
||||||
|
# First let's take a peek into the pod namespace and try to remove any
|
||||||
|
# leftover interface in case we got restarted before CNI returned to
|
||||||
|
# kubelet.
|
||||||
|
with b_base.get_ipdb(netns) as c_ipdb:
|
||||||
|
self._remove_ifaces(c_ipdb, (temp_name, ifname), netns)
|
||||||
|
|
||||||
|
with b_base.get_ipdb() as h_ipdb:
|
||||||
# TODO(vikasc): evaluate whether we should have stevedore
|
# TODO(vikasc): evaluate whether we should have stevedore
|
||||||
# driver for getting the link device.
|
# driver for getting the link device.
|
||||||
vm_iface_name = config.CONF.binding.link_iface
|
vm_iface_name = config.CONF.binding.link_iface
|
||||||
|
|
||||||
|
# We might also have leftover interface in the host netns, let's
|
||||||
|
# try to remove it too.
|
||||||
|
self._remove_ifaces(h_ipdb, (temp_name,))
|
||||||
|
|
||||||
args = self._get_iface_create_args(vif)
|
args = self._get_iface_create_args(vif)
|
||||||
with h_ipdb.create(ifname=temp_name,
|
with h_ipdb.create(ifname=temp_name,
|
||||||
link=h_ipdb.interfaces[vm_iface_name],
|
link=h_ipdb.interfaces[vm_iface_name],
|
||||||
|
@@ -180,7 +180,7 @@ class TestNestedVlanDriver(TestDriverMixin, test_base.TestCase):
|
|||||||
self._test_connect()
|
self._test_connect()
|
||||||
|
|
||||||
self.assertEqual(1, self.h_ipdb_exit.call_count)
|
self.assertEqual(1, self.h_ipdb_exit.call_count)
|
||||||
self.assertEqual(2, self.c_ipdb_exit.call_count)
|
self.assertEqual(3, self.c_ipdb_exit.call_count)
|
||||||
|
|
||||||
self.assertEqual(self.ifname, self.m_h_iface.ifname)
|
self.assertEqual(self.ifname, self.m_h_iface.ifname)
|
||||||
self.assertEqual(1, self.m_h_iface.mtu)
|
self.assertEqual(1, self.m_h_iface.mtu)
|
||||||
@@ -202,7 +202,7 @@ class TestNestedMacvlanDriver(TestDriverMixin, test_base.TestCase):
|
|||||||
self._test_connect()
|
self._test_connect()
|
||||||
|
|
||||||
self.assertEqual(1, self.h_ipdb_exit.call_count)
|
self.assertEqual(1, self.h_ipdb_exit.call_count)
|
||||||
self.assertEqual(2, self.c_ipdb_exit.call_count)
|
self.assertEqual(3, self.c_ipdb_exit.call_count)
|
||||||
|
|
||||||
self.assertEqual(self.ifname, self.m_h_iface.ifname)
|
self.assertEqual(self.ifname, self.m_h_iface.ifname)
|
||||||
self.assertEqual(1, self.m_h_iface.mtu)
|
self.assertEqual(1, self.m_h_iface.mtu)
|
||||||
|
Reference in New Issue
Block a user