Merge "Deletes floating ip related connection states" into stable/icehouse
This commit is contained in:
commit
2e9756c7f1
|
@ -39,3 +39,6 @@ iptables-save: CommandFilter, iptables-save, root
|
|||
iptables-restore: CommandFilter, iptables-restore, root
|
||||
ip6tables-save: CommandFilter, ip6tables-save, root
|
||||
ip6tables-restore: CommandFilter, ip6tables-restore, root
|
||||
|
||||
# l3 agent to delete floatingip's conntrack state
|
||||
conntrack: CommandFilter, conntrack, root
|
||||
|
|
|
@ -612,6 +612,10 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
|||
if ip_cidr.endswith(FLOATING_IP_CIDR_SUFFIX):
|
||||
net = netaddr.IPNetwork(ip_cidr)
|
||||
device.addr.delete(net.version, ip_cidr)
|
||||
self.driver.delete_conntrack_state(
|
||||
root_helper=self.root_helper,
|
||||
namespace=ri.ns_name,
|
||||
ip=ip_cidr)
|
||||
return fip_statuses
|
||||
|
||||
def _get_ex_gw_port(self, ri):
|
||||
|
|
|
@ -100,6 +100,46 @@ class LinuxInterfaceDriver(object):
|
|||
for ip_cidr, ip_version in previous.items():
|
||||
if ip_cidr not in preserve_ips:
|
||||
device.addr.delete(ip_version, ip_cidr)
|
||||
self.delete_conntrack_state(root_helper=self.root_helper,
|
||||
namespace=namespace,
|
||||
ip=ip_cidr)
|
||||
|
||||
def delete_conntrack_state(self, root_helper, namespace, ip):
|
||||
"""Delete conntrack state associated with an IP address.
|
||||
|
||||
This terminates any active connections through an IP. Call this soon
|
||||
after removing the IP address from an interface so that new connections
|
||||
cannot be created before the IP address is gone.
|
||||
|
||||
root_helper: root_helper to gain root access to call conntrack
|
||||
namespace: the name of the namespace where the IP has been configured
|
||||
ip: the IP address for which state should be removed. This can be
|
||||
passed as a string with or without /NN. A netaddr.IPAddress or
|
||||
netaddr.Network representing the IP address can also be passed.
|
||||
"""
|
||||
ip_str = str(netaddr.IPNetwork(ip).ip)
|
||||
ip_wrapper = ip_lib.IPWrapper(root_helper, namespace=namespace)
|
||||
|
||||
# Delete conntrack state for ingress traffic
|
||||
# If 0 flow entries have been deleted
|
||||
# conntrack -D will return 1
|
||||
try:
|
||||
ip_wrapper.netns.execute(["conntrack", "-D", "-d", ip_str],
|
||||
check_exit_code=True,
|
||||
extra_ok_codes=[1])
|
||||
|
||||
except RuntimeError:
|
||||
LOG.exception(_("Failed deleting ingress connection state of"
|
||||
" floatingip %s"), ip_str)
|
||||
|
||||
# Delete conntrack state for egress traffic
|
||||
try:
|
||||
ip_wrapper.netns.execute(["conntrack", "-D", "-q", ip_str],
|
||||
check_exit_code=True,
|
||||
extra_ok_codes=[1])
|
||||
except RuntimeError:
|
||||
LOG.exception(_("Failed deleting egress connection state of"
|
||||
" floatingip %s"), ip_str)
|
||||
|
||||
def check_bridge_exists(self, bridge):
|
||||
if not ip_lib.device_exists(bridge):
|
||||
|
|
|
@ -450,7 +450,8 @@ class IpNetnsCommand(IpCommandBase):
|
|||
def delete(self, name):
|
||||
self._as_root('delete', name, use_root_namespace=True)
|
||||
|
||||
def execute(self, cmds, addl_env={}, check_exit_code=True):
|
||||
def execute(self, cmds, addl_env={}, check_exit_code=True,
|
||||
extra_ok_codes=None):
|
||||
if not self._parent.root_helper:
|
||||
raise exceptions.SudoRequired()
|
||||
ns_params = []
|
||||
|
@ -464,7 +465,7 @@ class IpNetnsCommand(IpCommandBase):
|
|||
return utils.execute(
|
||||
ns_params + env_params + list(cmds),
|
||||
root_helper=self._parent.root_helper,
|
||||
check_exit_code=check_exit_code)
|
||||
check_exit_code=check_exit_code, extra_ok_codes=extra_ok_codes)
|
||||
|
||||
def exists(self, name):
|
||||
output = self._parent._execute('o', 'netns', ['list'])
|
||||
|
|
|
@ -60,7 +60,7 @@ def create_process(cmd, root_helper=None, addl_env=None):
|
|||
|
||||
|
||||
def execute(cmd, root_helper=None, process_input=None, addl_env=None,
|
||||
check_exit_code=True, return_stderr=False):
|
||||
check_exit_code=True, return_stderr=False, extra_ok_codes=None):
|
||||
try:
|
||||
obj, cmd = create_process(cmd, root_helper=root_helper,
|
||||
addl_env=addl_env)
|
||||
|
@ -71,7 +71,13 @@ def execute(cmd, root_helper=None, process_input=None, addl_env=None,
|
|||
m = _("\nCommand: %(cmd)s\nExit code: %(code)s\nStdout: %(stdout)r\n"
|
||||
"Stderr: %(stderr)r") % {'cmd': cmd, 'code': obj.returncode,
|
||||
'stdout': _stdout, 'stderr': _stderr}
|
||||
|
||||
LOG.debug(m)
|
||||
|
||||
extra_ok_codes = extra_ok_codes or []
|
||||
if obj.returncode and obj.returncode in extra_ok_codes:
|
||||
obj.returncode = None
|
||||
|
||||
if obj.returncode and check_exit_code:
|
||||
raise RuntimeError(m)
|
||||
finally:
|
||||
|
|
|
@ -495,6 +495,10 @@ class TestBasicRouterOperations(base.BaseTestCase):
|
|||
ri, {'id': _uuid()})
|
||||
self.assertEqual({}, fip_statuses)
|
||||
device.addr.delete.assert_called_once_with(4, '15.1.2.3/32')
|
||||
self.mock_driver.delete_conntrack_state.assert_called_once_with(
|
||||
root_helper=self.conf.root_helper,
|
||||
namespace=ri.ns_name,
|
||||
ip='15.1.2.3/32')
|
||||
|
||||
def test_process_router_floating_ip_nat_rules_remove(self):
|
||||
ri = mock.MagicMock()
|
||||
|
|
|
@ -706,7 +706,8 @@ class TestDnsmasq(TestBase):
|
|||
self.assertTrue(mocks['_output_opts_file'].called)
|
||||
self.execute.assert_called_once_with(expected,
|
||||
root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
check_exit_code=True,
|
||||
extra_ok_codes=None)
|
||||
|
||||
def test_spawn(self):
|
||||
self._test_spawn(['--conf-file=', '--domain=openstacklocal'])
|
||||
|
|
|
@ -46,7 +46,8 @@ class TestProcessManager(base.BaseTestCase):
|
|||
name.assert_called_once_with(ensure_pids_dir=True)
|
||||
self.execute.assert_called_once_with(['the', 'cmd'],
|
||||
root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
check_exit_code=True,
|
||||
extra_ok_codes=None)
|
||||
|
||||
def test_enable_with_namespace(self):
|
||||
callback = mock.Mock()
|
||||
|
|
|
@ -766,7 +766,8 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
|||
execute.assert_called_once_with(['ip', 'netns', 'exec', 'ns', 'ip',
|
||||
'link', 'list'],
|
||||
root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
check_exit_code=True,
|
||||
extra_ok_codes=None)
|
||||
|
||||
def test_execute_env_var_prepend(self):
|
||||
self.parent.namespace = 'ns'
|
||||
|
@ -776,7 +777,8 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
|||
execute.assert_called_once_with(
|
||||
['ip', 'netns', 'exec', 'ns', 'env', 'FOO=1', 'BAR=2',
|
||||
'ip', 'link', 'list'],
|
||||
root_helper='sudo', check_exit_code=True)
|
||||
root_helper='sudo', check_exit_code=True,
|
||||
extra_ok_codes=None)
|
||||
|
||||
|
||||
class TestDeviceExists(base.BaseTestCase):
|
||||
|
|
Loading…
Reference in New Issue