Merge "Fix ipv6 interface configuration"

This commit is contained in:
Zuul 2022-02-22 09:19:16 +00:00 committed by Gerrit Code Review
commit 1bc108b19f
3 changed files with 79 additions and 2 deletions

View File

@ -22,6 +22,8 @@ import time
from oslo_config import cfg
from oslo_log import log as logging
import pyroute2
# pylint: disable=no-name-in-module
from pyroute2.netlink.rtnl import ifaddrmsg
from octavia.amphorae.backends.utils import interface_file
from octavia.common import constants as consts
@ -37,6 +39,9 @@ class InterfaceController(object):
DELETE = 'delete'
SET = 'set'
TENTATIVE_WAIT_INTERVAL = .2
TENTATIVE_WAIT_TIMEOUT = 30
def interface_file_list(self):
net_dir = interface_file.InterfaceFile.get_directory()
@ -134,6 +139,21 @@ class InterfaceController(object):
LOG.debug("Running '%s'", cmd)
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
def _wait_tentative(self, ipr, idx):
start = time.time()
while time.time() - start < self.TENTATIVE_WAIT_TIMEOUT:
addrs = ipr.get_addr(idx)
has_tentative = [
True
for addr in addrs
if (addr['family'] == socket.AF_INET6 and
addr['flags'] & ifaddrmsg.IFA_F_TENTATIVE)]
if not has_tentative:
return
time.sleep(self.TENTATIVE_WAIT_INTERVAL)
LOG.warning("Some IPV6 addresses remain still in 'tentative' state "
"after %d seconds.", self.TENTATIVE_WAIT_TIMEOUT)
def up(self, interface):
LOG.info("Setting interface %s up", interface.name)
@ -158,6 +178,8 @@ class InterfaceController(object):
LOG.debug("%s: Adding address %s", interface.name, address)
self._ipr_command(ipr.addr, self.ADD, index=idx, **address)
self._wait_tentative(ipr, idx)
for route in interface.routes:
route[consts.FAMILY] = self._family(route[consts.DST])
LOG.debug("%s: Adding route %s", interface.name, route)

View File

@ -446,8 +446,11 @@ class TestInterface(base.TestCase):
@mock.patch('pyroute2.IPRoute.link')
@mock.patch('pyroute2.IPRoute.link_lookup')
@mock.patch('subprocess.check_output')
def test_up_auto(self, mock_check_output, mock_link_lookup, mock_link,
mock_addr, mock_route, mock_rule):
@mock.patch('octavia.amphorae.backends.utils.interface.'
'InterfaceController._wait_tentative')
def test_up_auto(self, mock_wait_tentative, mock_check_output,
mock_link_lookup, mock_link, mock_addr, mock_route,
mock_rule):
iface = interface_file.InterfaceFile(
name="eth1",
mtu=1450,
@ -900,3 +903,50 @@ class TestInterface(base.TestCase):
stderr=-2),
mock.call(["post-down", iface.name])
])
@mock.patch("time.time")
@mock.patch("time.sleep")
def test__wait_tentative(self, mock_time_sleep, mock_time_time):
mock_ipr = mock.MagicMock()
mock_ipr.get_addr.side_effect = [
({'family': socket.AF_INET,
'flags': 0},
{'family': socket.AF_INET6,
'flags': 0x40}, # tentative
{'family': socket.AF_INET6,
'flags': 0}),
({'family': socket.AF_INET,
'flags': 0},
{'family': socket.AF_INET6,
'flags': 0},
{'family': socket.AF_INET6,
'flags': 0})
]
mock_time_time.return_value = 0
controller = interface.InterfaceController()
idx = 4
controller._wait_tentative(mock_ipr, idx)
mock_time_sleep.assert_called_once()
@mock.patch("time.time")
@mock.patch("time.sleep")
def test__wait_tentative_timeout(self, mock_time_sleep,
mock_time_time):
mock_ipr = mock.MagicMock()
mock_ipr.get_addr.return_value = (
{'family': socket.AF_INET6,
'flags': 0x40}, # tentative
{'family': socket.AF_INET6,
'flags': 0}
)
mock_time_time.side_effect = [0, 0, 1, 2, 29, 30, 31]
controller = interface.InterfaceController()
idx = 4
controller._wait_tentative(mock_ipr, idx)
self.assertEqual(4, len(mock_time_sleep.mock_calls))

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fix an issue with IPv6 members that could have been set in operating_status
``ERROR`` just after being added.