raise NotImplementedError()
def remove_floating_ip(self, device, ip_cidr):
- device.addr.delete(ip_cidr)
- self.driver.delete_conntrack_state(namespace=self.ns_name, ip=ip_cidr)
+ device.delete_addr_and_conntrack_state(ip_cidr)
def get_router_cidrs(self, device):
return set([addr['cidr'] for addr in device.addr.list()])
# clean up any old addresses
for ip_cidr in previous:
if ip_cidr not in preserve_ips:
- device.addr.delete(ip_cidr)
- self.delete_conntrack_state(namespace=namespace, ip=ip_cidr)
+ device.delete_addr_and_conntrack_state(ip_cidr)
for gateway_ip in gateway_ips or []:
device.route.add_gateway(gateway_ip)
for route in existing_onlink_routes - new_onlink_routes:
device.route.delete_onlink_route(route)
- def delete_conntrack_state(self, 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.
-
- 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(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(_LE("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(_LE("Failed deleting egress connection state of"
- " floatingip %s"), ip_str)
-
def check_bridge_exists(self, bridge):
if not ip_lib.device_exists(bridge):
raise exceptions.BridgeDoesNotExist(bridge=bridge)
def __str__(self):
return self.name
+ def delete_addr_and_conntrack_state(self, cidr):
+ """Delete an address along with its conntrack state
+
+ This terminates any active connections through an IP.
+
+ cidr: 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.
+ """
+ self.addr.delete(cidr)
+
+ ip_str = str(netaddr.IPNetwork(cidr).ip)
+ ip_wrapper = IPWrapper(namespace=self.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(_LE("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(_LE("Failed deleting egress connection state of"
+ " floatingip %s"), ip_str)
+
class IpCommandBase(object):
COMMAND = ''
ri.remove_floating_ip(device, cidr)
- device.addr.delete.assert_called_once_with(cidr)
- self.driver.delete_conntrack_state.assert_called_once_with(
- ip=cidr,
- namespace=ri.ns_name)
+ device.delete_addr_and_conntrack_state.assert_called_once_with(cidr)
@mock.patch.object(ip_lib, 'send_gratuitous_arp')
[mock.call('tap0', namespace=ns),
mock.call().addr.list(filters=['permanent']),
mock.call().addr.add('192.168.1.2/24'),
- mock.call().addr.delete('172.16.77.240/24'),
+ mock.call().delete_addr_and_conntrack_state('172.16.77.240/24'),
mock.call().route.list_onlink_routes(constants.IP_VERSION_4),
mock.call().route.list_onlink_routes(constants.IP_VERSION_6),
mock.call().route.add_onlink_route('172.20.0.0/24')])
mock.call().addr.list(filters=['permanent']),
mock.call().addr.add('192.168.1.2/24')])
self.assertFalse(self.ip_dev().addr.delete.called)
+ self.assertFalse(self.ip_dev().delete_addr_and_conntrack_state.called)
def _test_l3_init_with_ipv6(self, include_gw_ip):
addresses = [dict(scope='global',
[mock.call('tap0', namespace=ns),
mock.call().addr.list(filters=['permanent']),
mock.call().addr.add('2001:db8:a::124/64'),
- mock.call().addr.delete('2001:db8:a::123/64')])
+ mock.call().delete_addr_and_conntrack_state(
+ '2001:db8:a::123/64')])
if include_gw_ip:
expected_calls += (
[mock.call().route.add_gateway('2001:db8:a::1')])
mock.call().addr.list(filters=['permanent']),
mock.call().addr.add('192.168.1.2/24'),
mock.call().addr.add('2001:db8:a::124/64'),
- mock.call().addr.delete('172.16.77.240/24'),
- mock.call().addr.delete('2001:db8:a::123/64'),
+ mock.call().delete_addr_and_conntrack_state('172.16.77.240/24'),
+ mock.call().delete_addr_and_conntrack_state('2001:db8:a::123/64'),
mock.call().route.list_onlink_routes(constants.IP_VERSION_4),
mock.call().route.list_onlink_routes(constants.IP_VERSION_6),
mock.call().route.add_onlink_route('172.20.0.0/24')],