Merge "Deletes floating ip related connection states" into stable/icehouse

This commit is contained in:
Jenkins 2014-09-29 22:11:31 +00:00 committed by Gerrit Code Review
commit 2e9756c7f1
9 changed files with 69 additions and 7 deletions

View File

@ -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

View File

@ -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):

View File

@ -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):

View File

@ -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'])

View File

@ -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:

View File

@ -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()

View File

@ -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'])

View File

@ -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()

View File

@ -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):