b79842f289
Removed E125 (continuation line does not distinguish itself from next logical line) from the ignore list and fixed all the indentation issues. Didn't think it was going to be close to 100 files when I started. Change-Id: I0a6f5efec4b7d8d3632dd9dbb43e0ab58af9dff3
533 lines
22 KiB
Python
533 lines
22 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import mock
|
|
from neutron_lib import constants as lib_constants
|
|
from neutron_lib.exceptions import l3 as l3_exc
|
|
from oslo_utils import uuidutils
|
|
|
|
from neutron.agent.l3 import router_info
|
|
from neutron.agent.linux import ip_lib
|
|
from neutron.conf.agent import common as config
|
|
from neutron.conf.agent.l3 import config as l3_config
|
|
from neutron.tests import base
|
|
|
|
|
|
_uuid = uuidutils.generate_uuid
|
|
|
|
|
|
class TestRouterInfo(base.BaseTestCase):
|
|
def setUp(self):
|
|
super(TestRouterInfo, self).setUp()
|
|
|
|
conf = config.setup_conf()
|
|
l3_config.register_l3_agent_config_opts(l3_config.OPTS, conf)
|
|
|
|
self.ip_cls_p = mock.patch('neutron.agent.linux.ip_lib.IPWrapper')
|
|
ip_cls = self.ip_cls_p.start()
|
|
self.mock_ip = mock.MagicMock()
|
|
ip_cls.return_value = self.mock_ip
|
|
self.ri_kwargs = {'agent_conf': conf,
|
|
'interface_driver': mock.sentinel.interface_driver}
|
|
|
|
def _check_agent_method_called(self, calls):
|
|
self.mock_ip.netns.execute.assert_has_calls(
|
|
[mock.call(call, check_exit_code=False) for call in calls],
|
|
any_order=True)
|
|
|
|
def test_routing_table_update(self):
|
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
|
ri.router = {}
|
|
|
|
fake_route1 = {'destination': '135.207.0.0/16',
|
|
'nexthop': '1.2.3.4'}
|
|
fake_route2 = {'destination': '135.207.111.111/32',
|
|
'nexthop': '1.2.3.4'}
|
|
|
|
ri.update_routing_table('replace', fake_route1)
|
|
expected = [['ip', 'route', 'replace', 'to', '135.207.0.0/16',
|
|
'via', '1.2.3.4']]
|
|
self._check_agent_method_called(expected)
|
|
|
|
ri.update_routing_table('delete', fake_route1)
|
|
expected = [['ip', 'route', 'delete', 'to', '135.207.0.0/16',
|
|
'via', '1.2.3.4']]
|
|
self._check_agent_method_called(expected)
|
|
|
|
ri.update_routing_table('replace', fake_route2)
|
|
expected = [['ip', 'route', 'replace', 'to', '135.207.111.111/32',
|
|
'via', '1.2.3.4']]
|
|
self._check_agent_method_called(expected)
|
|
|
|
ri.update_routing_table('delete', fake_route2)
|
|
expected = [['ip', 'route', 'delete', 'to', '135.207.111.111/32',
|
|
'via', '1.2.3.4']]
|
|
self._check_agent_method_called(expected)
|
|
|
|
def test_update_routing_table(self):
|
|
# Just verify the correct namespace was used in the call
|
|
uuid = _uuid()
|
|
netns = 'qrouter-' + uuid
|
|
fake_route1 = {'destination': '135.207.0.0/16',
|
|
'nexthop': '1.2.3.4'}
|
|
|
|
ri = router_info.RouterInfo(mock.Mock(), uuid,
|
|
{'id': uuid}, **self.ri_kwargs)
|
|
ri._update_routing_table = mock.Mock()
|
|
|
|
ri.update_routing_table('replace', fake_route1)
|
|
ri._update_routing_table.assert_called_once_with('replace',
|
|
fake_route1,
|
|
netns)
|
|
|
|
def test_routes_updated(self):
|
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
|
ri.router = {}
|
|
|
|
fake_old_routes = []
|
|
fake_new_routes = [{'destination': "110.100.31.0/24",
|
|
'nexthop': "10.100.10.30"},
|
|
{'destination': "110.100.30.0/24",
|
|
'nexthop': "10.100.10.30"}]
|
|
ri.routes = fake_old_routes
|
|
ri.router['routes'] = fake_new_routes
|
|
ri.routes_updated(fake_old_routes, fake_new_routes)
|
|
|
|
expected = [['ip', 'route', 'replace', 'to', '110.100.30.0/24',
|
|
'via', '10.100.10.30'],
|
|
['ip', 'route', 'replace', 'to', '110.100.31.0/24',
|
|
'via', '10.100.10.30']]
|
|
|
|
self._check_agent_method_called(expected)
|
|
ri.routes = fake_new_routes
|
|
fake_new_routes = [{'destination': "110.100.30.0/24",
|
|
'nexthop': "10.100.10.30"}]
|
|
ri.router['routes'] = fake_new_routes
|
|
ri.routes_updated(ri.routes, fake_new_routes)
|
|
expected = [['ip', 'route', 'delete', 'to', '110.100.31.0/24',
|
|
'via', '10.100.10.30']]
|
|
|
|
self._check_agent_method_called(expected)
|
|
fake_new_routes = []
|
|
ri.router['routes'] = fake_new_routes
|
|
ri.routes_updated(ri.routes, fake_new_routes)
|
|
|
|
expected = [['ip', 'route', 'delete', 'to', '110.100.30.0/24',
|
|
'via', '10.100.10.30']]
|
|
self._check_agent_method_called(expected)
|
|
|
|
def test__process_pd_iptables_rules(self):
|
|
subnet_id = _uuid()
|
|
ex_gw_port = {'id': _uuid()}
|
|
prefix = '2001:db8:cafe::/64'
|
|
|
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
|
|
|
ipv6_mangle = ri.iptables_manager.ipv6['mangle'] = mock.MagicMock()
|
|
ri.get_ex_gw_port = mock.Mock(return_value=ex_gw_port)
|
|
ri.get_external_device_name = mock.Mock(return_value='fake_device')
|
|
ri.get_address_scope_mark_mask = mock.Mock(return_value='fake_mark')
|
|
|
|
ri._process_pd_iptables_rules(prefix, subnet_id)
|
|
|
|
mangle_rule = '-d %s ' % prefix
|
|
mangle_rule += ri.address_scope_mangle_rule('fake_device', 'fake_mark')
|
|
|
|
ipv6_mangle.add_rule.assert_called_once_with(
|
|
'scope',
|
|
mangle_rule,
|
|
tag='prefix_delegation_%s' % subnet_id)
|
|
|
|
def test_add_ports_address_scope_iptables(self):
|
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
|
port = {
|
|
'id': _uuid(),
|
|
'fixed_ips': [{'ip_address': '172.9.9.9'}],
|
|
'address_scopes': {lib_constants.IP_VERSION_4: '1234'}
|
|
}
|
|
ipv4_mangle = ri.iptables_manager.ipv4['mangle'] = mock.MagicMock()
|
|
ri.get_address_scope_mark_mask = mock.Mock(return_value='fake_mark')
|
|
ri.get_internal_device_name = mock.Mock(return_value='fake_device')
|
|
ri.rt_tables_manager = mock.MagicMock()
|
|
ri.process_external_port_address_scope_routing = mock.Mock()
|
|
ri.process_floating_ip_address_scope_rules = mock.Mock()
|
|
ri.iptables_manager._apply = mock.Mock()
|
|
|
|
ri.router[lib_constants.INTERFACE_KEY] = [port]
|
|
ri.process_address_scope()
|
|
|
|
ipv4_mangle.add_rule.assert_called_once_with(
|
|
'scope', ri.address_scope_mangle_rule('fake_device', 'fake_mark'))
|
|
|
|
def test_address_scope_mark_ids_handling(self):
|
|
mark_ids = set(range(router_info.ADDRESS_SCOPE_MARK_ID_MIN,
|
|
router_info.ADDRESS_SCOPE_MARK_ID_MAX))
|
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
|
# first mark id is used for the default address scope
|
|
scope_to_mark_id = {router_info.DEFAULT_ADDRESS_SCOPE: mark_ids.pop()}
|
|
self.assertEqual(scope_to_mark_id, ri._address_scope_to_mark_id)
|
|
self.assertEqual(mark_ids, ri.available_mark_ids)
|
|
|
|
# new id should be used for new address scope
|
|
ri.get_address_scope_mark_mask('new_scope')
|
|
scope_to_mark_id['new_scope'] = mark_ids.pop()
|
|
self.assertEqual(scope_to_mark_id, ri._address_scope_to_mark_id)
|
|
self.assertEqual(mark_ids, ri.available_mark_ids)
|
|
|
|
# new router should have it's own mark ids set
|
|
new_mark_ids = set(range(router_info.ADDRESS_SCOPE_MARK_ID_MIN,
|
|
router_info.ADDRESS_SCOPE_MARK_ID_MAX))
|
|
new_ri = router_info.RouterInfo(mock.Mock(), _uuid(),
|
|
{}, **self.ri_kwargs)
|
|
new_mark_ids.pop()
|
|
self.assertEqual(new_mark_ids, new_ri.available_mark_ids)
|
|
self.assertNotEqual(ri.available_mark_ids, new_ri.available_mark_ids)
|
|
|
|
def test_process_delete(self):
|
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
|
ri.router = {'id': _uuid()}
|
|
with mock.patch.object(ri, '_process_internal_ports') as p_i_p,\
|
|
mock.patch.object(ri,
|
|
'_process_external_on_delete') as p_e_o_d:
|
|
self.mock_ip.netns.exists.return_value = False
|
|
ri.process_delete()
|
|
self.assertFalse(p_i_p.called)
|
|
self.assertFalse(p_e_o_d.called)
|
|
|
|
p_i_p.reset_mock()
|
|
p_e_o_d.reset_mock()
|
|
self.mock_ip.netns.exists.return_value = True
|
|
ri.process_delete()
|
|
p_i_p.assert_called_once_with()
|
|
p_e_o_d.assert_called_once_with()
|
|
|
|
def test__update_internal_ports_cache(self):
|
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
|
ri.internal_ports = [
|
|
{'id': 'port-id-1', 'mtu': 1500},
|
|
{'id': 'port-id-2', 'mtu': 2000}]
|
|
initial_internal_ports = ri.internal_ports[:]
|
|
|
|
# Test add new element to the cache
|
|
new_port = {'id': 'new-port-id', 'mtu': 1500}
|
|
ri._update_internal_ports_cache(new_port)
|
|
self.assertEqual(
|
|
initial_internal_ports + [new_port],
|
|
ri.internal_ports)
|
|
|
|
# Test update existing port in cache
|
|
updated_port = new_port.copy()
|
|
updated_port['mtu'] = 2500
|
|
ri._update_internal_ports_cache(updated_port)
|
|
self.assertEqual(
|
|
initial_internal_ports + [updated_port],
|
|
ri.internal_ports)
|
|
|
|
|
|
class BasicRouterTestCaseFramework(base.BaseTestCase):
|
|
def _create_router(self, router=None, **kwargs):
|
|
if not router:
|
|
router = mock.MagicMock()
|
|
self.agent_conf = mock.Mock()
|
|
self.router_id = _uuid()
|
|
return router_info.RouterInfo(mock.Mock(),
|
|
self.router_id,
|
|
router,
|
|
self.agent_conf,
|
|
mock.sentinel.interface_driver,
|
|
**kwargs)
|
|
|
|
|
|
class TestBasicRouterOperations(BasicRouterTestCaseFramework):
|
|
|
|
def test_get_floating_ips(self):
|
|
router = mock.MagicMock()
|
|
router.get.return_value = [mock.sentinel.floating_ip]
|
|
ri = self._create_router(router)
|
|
|
|
fips = ri.get_floating_ips()
|
|
|
|
self.assertEqual([mock.sentinel.floating_ip], fips)
|
|
|
|
def test_process_floating_ip_nat_rules(self):
|
|
ri = self._create_router()
|
|
fips = [{'fixed_ip_address': mock.sentinel.ip,
|
|
'floating_ip_address': mock.sentinel.fip}]
|
|
ri.get_floating_ips = mock.Mock(return_value=fips)
|
|
ri.iptables_manager = mock.MagicMock()
|
|
ipv4_nat = ri.iptables_manager.ipv4['nat']
|
|
ri.floating_forward_rules = mock.Mock(
|
|
return_value=[(mock.sentinel.chain, mock.sentinel.rule)])
|
|
|
|
ri.process_floating_ip_nat_rules()
|
|
|
|
# Be sure that the rules are cleared first and apply is called last
|
|
self.assertEqual(mock.call.clear_rules_by_tag('floating_ip'),
|
|
ipv4_nat.mock_calls[0])
|
|
self.assertEqual(mock.call.apply(), ri.iptables_manager.mock_calls[-1])
|
|
|
|
# Be sure that add_rule is called somewhere in the middle
|
|
ipv4_nat.add_rule.assert_called_once_with(mock.sentinel.chain,
|
|
mock.sentinel.rule,
|
|
tag='floating_ip')
|
|
|
|
def test_process_floating_ip_nat_rules_removed(self):
|
|
ri = self._create_router()
|
|
ri.get_floating_ips = mock.Mock(return_value=[])
|
|
ri.iptables_manager = mock.MagicMock()
|
|
ipv4_nat = ri.iptables_manager.ipv4['nat']
|
|
|
|
ri.process_floating_ip_nat_rules()
|
|
|
|
# Be sure that the rules are cleared first and apply is called last
|
|
self.assertEqual(mock.call.clear_rules_by_tag('floating_ip'),
|
|
ipv4_nat.mock_calls[0])
|
|
self.assertEqual(mock.call.apply(), ri.iptables_manager.mock_calls[-1])
|
|
|
|
# Be sure that add_rule is called somewhere in the middle
|
|
self.assertFalse(ipv4_nat.add_rule.called)
|
|
|
|
def test_process_floating_ip_address_scope_rules_diff_scopes(self):
|
|
ri = self._create_router()
|
|
fips = [{'fixed_ip_address': mock.sentinel.ip,
|
|
'floating_ip_address': mock.sentinel.fip,
|
|
'fixed_ip_address_scope': 'scope1'}]
|
|
ri.get_floating_ips = mock.Mock(return_value=fips)
|
|
ri._get_external_address_scope = mock.Mock(return_value='scope2')
|
|
ipv4_mangle = ri.iptables_manager.ipv4['mangle'] = mock.MagicMock()
|
|
ri.floating_mangle_rules = mock.Mock(
|
|
return_value=[(mock.sentinel.chain1, mock.sentinel.rule1)])
|
|
ri.get_external_device_name = mock.Mock()
|
|
|
|
ri.process_floating_ip_address_scope_rules()
|
|
|
|
# Be sure that the rules are cleared first
|
|
self.assertEqual(mock.call.clear_rules_by_tag('floating_ip'),
|
|
ipv4_mangle.mock_calls[0])
|
|
# Be sure that add_rule is called somewhere in the middle
|
|
self.assertEqual(1, ipv4_mangle.add_rule.call_count)
|
|
self.assertEqual(mock.call.add_rule(mock.sentinel.chain1,
|
|
mock.sentinel.rule1,
|
|
tag='floating_ip'),
|
|
ipv4_mangle.mock_calls[1])
|
|
|
|
def test_process_floating_ip_address_scope_rules_same_scopes(self):
|
|
ri = self._create_router()
|
|
fips = [{'fixed_ip_address': mock.sentinel.ip,
|
|
'floating_ip_address': mock.sentinel.fip,
|
|
'fixed_ip_address_scope': 'scope1'}]
|
|
ri.get_floating_ips = mock.Mock(return_value=fips)
|
|
ri._get_external_address_scope = mock.Mock(return_value='scope1')
|
|
ipv4_mangle = ri.iptables_manager.ipv4['mangle'] = mock.MagicMock()
|
|
|
|
ri.process_floating_ip_address_scope_rules()
|
|
|
|
# Be sure that the rules are cleared first
|
|
self.assertEqual(mock.call.clear_rules_by_tag('floating_ip'),
|
|
ipv4_mangle.mock_calls[0])
|
|
# Be sure that add_rule is not called somewhere in the middle
|
|
self.assertFalse(ipv4_mangle.add_rule.called)
|
|
|
|
def test_process_floating_ip_mangle_rules_removed(self):
|
|
ri = self._create_router()
|
|
ri.get_floating_ips = mock.Mock(return_value=[])
|
|
ipv4_mangle = ri.iptables_manager.ipv4['mangle'] = mock.MagicMock()
|
|
|
|
ri.process_floating_ip_address_scope_rules()
|
|
|
|
# Be sure that the rules are cleared first
|
|
self.assertEqual(mock.call.clear_rules_by_tag('floating_ip'),
|
|
ipv4_mangle.mock_calls[0])
|
|
|
|
# Be sure that add_rule is not called somewhere in the middle
|
|
self.assertFalse(ipv4_mangle.add_rule.called)
|
|
|
|
def _test_add_fip_addr_to_device_error(self, device):
|
|
ri = self._create_router()
|
|
ip = '15.1.2.3'
|
|
|
|
result = ri._add_fip_addr_to_device(
|
|
{'id': mock.sentinel.id, 'floating_ip_address': ip}, device)
|
|
|
|
device.addr.add.assert_called_with(ip + '/32')
|
|
return result
|
|
|
|
def test__add_fip_addr_to_device(self):
|
|
result = self._test_add_fip_addr_to_device_error(mock.Mock())
|
|
self.assertTrue(result)
|
|
|
|
def test__add_fip_addr_to_device_error(self):
|
|
device = mock.Mock()
|
|
device.addr.add.side_effect = RuntimeError
|
|
result = self._test_add_fip_addr_to_device_error(device)
|
|
self.assertFalse(result)
|
|
|
|
def test_process_snat_dnat_for_fip(self):
|
|
ri = self._create_router()
|
|
ri.process_floating_ip_nat_rules = mock.Mock(side_effect=Exception)
|
|
|
|
self.assertRaises(l3_exc.FloatingIpSetupException,
|
|
ri.process_snat_dnat_for_fip)
|
|
|
|
ri.process_floating_ip_nat_rules.assert_called_once_with()
|
|
|
|
def test_put_fips_in_error_state(self):
|
|
ri = self._create_router()
|
|
ri.router = mock.Mock()
|
|
ri.router.get.return_value = [{'id': mock.sentinel.id1},
|
|
{'id': mock.sentinel.id2}]
|
|
|
|
statuses = ri.put_fips_in_error_state()
|
|
|
|
expected = [{mock.sentinel.id1: lib_constants.FLOATINGIP_STATUS_ERROR,
|
|
mock.sentinel.id2: lib_constants.FLOATINGIP_STATUS_ERROR}]
|
|
self.assertNotEqual(expected, statuses)
|
|
|
|
def test_configure_fip_addresses(self):
|
|
ri = self._create_router()
|
|
ri.process_floating_ip_addresses = mock.Mock(
|
|
side_effect=Exception)
|
|
|
|
self.assertRaises(l3_exc.FloatingIpSetupException,
|
|
ri.configure_fip_addresses,
|
|
mock.sentinel.interface_name)
|
|
|
|
ri.process_floating_ip_addresses.assert_called_once_with(
|
|
mock.sentinel.interface_name)
|
|
|
|
def test_get_router_cidrs_returns_cidrs(self):
|
|
ri = self._create_router()
|
|
addresses = ['15.1.2.2/24', '15.1.2.3/32']
|
|
device = mock.MagicMock()
|
|
device.addr.list.return_value = [{'cidr': addresses[0]},
|
|
{'cidr': addresses[1]}]
|
|
self.assertEqual(set(addresses), ri.get_router_cidrs(device))
|
|
|
|
|
|
@mock.patch.object(ip_lib, 'IPDevice')
|
|
class TestFloatingIpWithMockDevice(BasicRouterTestCaseFramework):
|
|
|
|
def test_process_floating_ip_addresses_remap(self, IPDevice):
|
|
fip_id = _uuid()
|
|
fip = {
|
|
'id': fip_id, 'port_id': _uuid(),
|
|
'floating_ip_address': '15.1.2.3',
|
|
'fixed_ip_address': '192.168.0.2',
|
|
'status': lib_constants.FLOATINGIP_STATUS_DOWN
|
|
}
|
|
|
|
IPDevice.return_value = device = mock.Mock()
|
|
device.addr.list.return_value = [{'cidr': '15.1.2.3/32'}]
|
|
ri = self._create_router()
|
|
ri.get_floating_ips = mock.Mock(return_value=[fip])
|
|
|
|
fip_statuses = ri.process_floating_ip_addresses(
|
|
mock.sentinel.interface_name)
|
|
self.assertEqual({fip_id: lib_constants.FLOATINGIP_STATUS_ACTIVE},
|
|
fip_statuses)
|
|
|
|
self.assertFalse(device.addr.add.called)
|
|
self.assertFalse(device.addr.delete.called)
|
|
|
|
def test_process_router_with_disabled_floating_ip(self, IPDevice):
|
|
fip_id = _uuid()
|
|
fip = {
|
|
'id': fip_id, 'port_id': _uuid(),
|
|
'floating_ip_address': '15.1.2.3',
|
|
'fixed_ip_address': '192.168.0.2'
|
|
}
|
|
|
|
ri = self._create_router()
|
|
ri.floating_ips = [fip]
|
|
ri.get_floating_ips = mock.Mock(return_value=[])
|
|
|
|
fip_statuses = ri.process_floating_ip_addresses(
|
|
mock.sentinel.interface_name)
|
|
|
|
self.assertIsNone(fip_statuses.get(fip_id))
|
|
|
|
def test_process_router_floating_ip_with_device_add_error(self, IPDevice):
|
|
IPDevice.return_value = device = mock.Mock(side_effect=RuntimeError)
|
|
device.addr.list.return_value = []
|
|
fip_id = _uuid()
|
|
fip = {
|
|
'id': fip_id, 'port_id': _uuid(),
|
|
'floating_ip_address': '15.1.2.3',
|
|
'fixed_ip_address': '192.168.0.2',
|
|
'status': 'DOWN'
|
|
}
|
|
ri = self._create_router()
|
|
ri.add_floating_ip = mock.Mock(
|
|
return_value=lib_constants.FLOATINGIP_STATUS_ERROR)
|
|
ri.get_floating_ips = mock.Mock(return_value=[fip])
|
|
|
|
fip_statuses = ri.process_floating_ip_addresses(
|
|
mock.sentinel.interface_name)
|
|
|
|
self.assertEqual({fip_id: lib_constants.FLOATINGIP_STATUS_ERROR},
|
|
fip_statuses)
|
|
|
|
# TODO(mrsmith): refactor for DVR cases
|
|
def test_process_floating_ip_addresses_remove(self, IPDevice):
|
|
IPDevice.return_value = device = mock.Mock()
|
|
device.addr.list.return_value = [{'cidr': '15.1.2.3/32'}]
|
|
|
|
ri = self._create_router()
|
|
ri.remove_floating_ip = mock.Mock()
|
|
ri.router.get = mock.Mock(return_value=[])
|
|
|
|
fip_statuses = ri.process_floating_ip_addresses(
|
|
mock.sentinel.interface_name)
|
|
self.assertEqual({}, fip_statuses)
|
|
ri.remove_floating_ip.assert_called_once_with(device, '15.1.2.3/32')
|
|
|
|
def test_process_floating_ip_reassignment(self, IPDevice):
|
|
IPDevice.return_value = device = mock.Mock()
|
|
device.addr.list.return_value = [{'cidr': '15.1.2.3/32'}]
|
|
|
|
fip_id = _uuid()
|
|
fip = {
|
|
'id': fip_id, 'port_id': _uuid(),
|
|
'floating_ip_address': '15.1.2.3',
|
|
'fixed_ip_address': '192.168.0.3',
|
|
'status': 'DOWN'
|
|
}
|
|
ri = self._create_router()
|
|
ri.get_floating_ips = mock.Mock(return_value=[fip])
|
|
ri.move_floating_ip = mock.Mock()
|
|
ri.fip_map = {'15.1.2.3': '192.168.0.2'}
|
|
|
|
ri.process_floating_ip_addresses(mock.sentinel.interface_name)
|
|
ri.move_floating_ip.assert_called_once_with(fip)
|
|
|
|
def test_process_floating_ip_addresses_gw_secondary_ip_not_removed(
|
|
self, IPDevice):
|
|
IPDevice.return_value = device = mock.Mock()
|
|
device.addr.list.return_value = [{'cidr': '1.1.1.1/16'},
|
|
{'cidr': '2.2.2.2/32'},
|
|
{'cidr': '3.3.3.3/32'},
|
|
{'cidr': '4.4.4.4/32'}]
|
|
ri = self._create_router()
|
|
|
|
ri.get_floating_ips = mock.Mock(return_value=[
|
|
{'id': _uuid(),
|
|
'floating_ip_address': '3.3.3.3',
|
|
'status': 'DOWN'}])
|
|
ri.add_floating_ip = mock.Mock()
|
|
ri.get_ex_gw_port = mock.Mock(return_value={
|
|
"fixed_ips": [{"ip_address": "1.1.1.1"},
|
|
{"ip_address": "2.2.2.2"}]})
|
|
ri.remove_floating_ip = mock.Mock()
|
|
|
|
ri.process_floating_ip_addresses("qg-fake-device")
|
|
ri.remove_floating_ip.assert_called_once_with(device, '4.4.4.4/32')
|