summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2017-06-15 06:56:37 +0000
committerGerrit Code Review <review@openstack.org>2017-06-15 06:56:37 +0000
commitaad90b005c270adfe83d81973d42e30498711db6 (patch)
treebd18e1281fa591b0b48d7ff536213f14990212ff
parent76d95b8b9cce8fdf6676f346d64ec6d98c62caa6 (diff)
parentafdc38f7c68228a7aaa6e5f2eb0871073f306722 (diff)
Merge "Add IPv6 default route to DHCP namespace" into stable/newton
-rw-r--r--neutron/agent/linux/dhcp.py55
-rw-r--r--neutron/tests/functional/agent/test_dhcp_agent.py6
-rw-r--r--neutron/tests/unit/agent/dhcp/test_agent.py155
3 files changed, 157 insertions, 59 deletions
diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py
index 28566b5..0fef935 100644
--- a/neutron/agent/linux/dhcp.py
+++ b/neutron/agent/linux/dhcp.py
@@ -1109,31 +1109,39 @@ class DeviceManager(object):
1109 return common_utils.get_dhcp_agent_device_id(network.id, 1109 return common_utils.get_dhcp_agent_device_id(network.id,
1110 self.conf.host) 1110 self.conf.host)
1111 1111
1112 def _set_default_route(self, network, device_name): 1112 def _set_default_route_ip_version(self, network, device_name, ip_version):
1113 """Sets the default gateway for this dhcp namespace.
1114
1115 This method is idempotent and will only adjust the route if adjusting
1116 it would change it from what it already is. This makes it safe to call
1117 and avoids unnecessary perturbation of the system.
1118 """
1119 device = ip_lib.IPDevice(device_name, namespace=network.namespace) 1113 device = ip_lib.IPDevice(device_name, namespace=network.namespace)
1120 gateway = device.route.get_gateway() 1114 gateway = device.route.get_gateway(ip_version=ip_version)
1121 if gateway: 1115 if gateway:
1122 gateway = gateway.get('gateway') 1116 gateway = gateway.get('gateway')
1123 1117
1124 for subnet in network.subnets: 1118 for subnet in network.subnets:
1125 skip_subnet = ( 1119 skip_subnet = (
1126 subnet.ip_version != 4 1120 subnet.ip_version != ip_version
1127 or not subnet.enable_dhcp 1121 or not subnet.enable_dhcp
1128 or subnet.gateway_ip is None) 1122 or subnet.gateway_ip is None)
1129 1123
1130 if skip_subnet: 1124 if skip_subnet:
1131 continue 1125 continue
1132 1126
1127 if subnet.ip_version == constants.IP_VERSION_6:
1128 # This is duplicating some of the API checks already done,
1129 # but some of the functional tests call directly
1130 prefixlen = netaddr.IPNetwork(subnet.cidr).prefixlen
1131 if prefixlen == 0 or prefixlen > 126:
1132 continue
1133 modes = [constants.IPV6_SLAAC, constants.DHCPV6_STATELESS]
1134 addr_mode = getattr(subnet, 'ipv6_address_mode', None)
1135 ra_mode = getattr(subnet, 'ipv6_ra_mode', None)
1136 if (prefixlen != 64 and
1137 (addr_mode in modes or ra_mode in modes)):
1138 continue
1139
1133 if gateway != subnet.gateway_ip: 1140 if gateway != subnet.gateway_ip:
1134 LOG.debug('Setting gateway for dhcp netns on net %(n)s to ' 1141 LOG.debug('Setting IPv%(version)s gateway for dhcp netns '
1135 '%(ip)s', 1142 'on net %(n)s to %(ip)s',
1136 {'n': network.id, 'ip': subnet.gateway_ip}) 1143 {'n': network.id, 'ip': subnet.gateway_ip,
1144 'version': ip_version})
1137 1145
1138 # Check for and remove the on-link route for the old 1146 # Check for and remove the on-link route for the old
1139 # gateway being replaced, if it is outside the subnet 1147 # gateway being replaced, if it is outside the subnet
@@ -1141,12 +1149,8 @@ class DeviceManager(object):
1141 not ipam_utils.check_subnet_ip( 1149 not ipam_utils.check_subnet_ip(
1142 subnet.cidr, gateway)) 1150 subnet.cidr, gateway))
1143 if is_old_gateway_not_in_subnet: 1151 if is_old_gateway_not_in_subnet:
1144 v4_onlink = device.route.list_onlink_routes( 1152 onlink = device.route.list_onlink_routes(ip_version)
1145 constants.IP_VERSION_4) 1153 existing_onlink_routes = set(r['cidr'] for r in onlink)
1146 v6_onlink = device.route.list_onlink_routes(
1147 constants.IP_VERSION_6)
1148 existing_onlink_routes = set(
1149 r['cidr'] for r in v4_onlink + v6_onlink)
1150 if gateway in existing_onlink_routes: 1154 if gateway in existing_onlink_routes:
1151 device.route.delete_route(gateway, scope='link') 1155 device.route.delete_route(gateway, scope='link')
1152 1156
@@ -1163,10 +1167,23 @@ class DeviceManager(object):
1163 # No subnets on the network have a valid gateway. Clean it up to avoid 1167 # No subnets on the network have a valid gateway. Clean it up to avoid
1164 # confusion from seeing an invalid gateway here. 1168 # confusion from seeing an invalid gateway here.
1165 if gateway is not None: 1169 if gateway is not None:
1166 LOG.debug('Removing gateway for dhcp netns on net %s', network.id) 1170 LOG.debug('Removing IPv%(version)s gateway for dhcp netns on '
1171 'net %(n)s',
1172 {'n': network.id, 'version': ip_version})
1167 1173
1168 device.route.delete_gateway(gateway) 1174 device.route.delete_gateway(gateway)
1169 1175
1176 def _set_default_route(self, network, device_name):
1177 """Sets the default gateway for this dhcp namespace.
1178
1179 This method is idempotent and will only adjust the route if adjusting
1180 it would change it from what it already is. This makes it safe to call
1181 and avoids unnecessary perturbation of the system.
1182 """
1183 for ip_version in (constants.IP_VERSION_4, constants.IP_VERSION_6):
1184 self._set_default_route_ip_version(network, device_name,
1185 ip_version)
1186
1170 def _setup_existing_dhcp_port(self, network, device_id, dhcp_subnets): 1187 def _setup_existing_dhcp_port(self, network, device_id, dhcp_subnets):
1171 """Set up the existing DHCP port, if there is one.""" 1188 """Set up the existing DHCP port, if there is one."""
1172 1189
diff --git a/neutron/tests/functional/agent/test_dhcp_agent.py b/neutron/tests/functional/agent/test_dhcp_agent.py
index 848d1c9..4ad1412 100644
--- a/neutron/tests/functional/agent/test_dhcp_agent.py
+++ b/neutron/tests/functional/agent/test_dhcp_agent.py
@@ -50,9 +50,9 @@ class DHCPAgentOVSTestFramework(base.BaseSudoTestCase):
50 4: {'addr': '192.168.10.11', 50 4: {'addr': '192.168.10.11',
51 'cidr': '192.168.10.0/24', 51 'cidr': '192.168.10.0/24',
52 'gateway': '192.168.10.1'}, 52 'gateway': '192.168.10.1'},
53 6: {'addr': '0:0:0:0:0:ffff:c0a8:a0b', 53 6: {'addr': '2001:db8:0:1::c0a8:a0b',
54 'cidr': '0:0:0:0:0:ffff:c0a8:a00/120', 54 'cidr': '2001:db8:0:1::c0a8:a00/120',
55 'gateway': '0:0:0:0:0:ffff:c0a8:a01'}, } 55 'gateway': '2001:db8:0:1::c0a8:a01'}, }
56 56
57 def setUp(self): 57 def setUp(self):
58 super(DHCPAgentOVSTestFramework, self).setUp() 58 super(DHCPAgentOVSTestFramework, self).setUp()
diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py
index c83b261..accbc14 100644
--- a/neutron/tests/unit/agent/dhcp/test_agent.py
+++ b/neutron/tests/unit/agent/dhcp/test_agent.py
@@ -1342,6 +1342,11 @@ class FakePort1(object):
1342 self.id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee' 1342 self.id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
1343 1343
1344 1344
1345class FakePort2(object):
1346 def __init__(self):
1347 self.id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
1348
1349
1345class FakeV4Subnet(object): 1350class FakeV4Subnet(object):
1346 def __init__(self): 1351 def __init__(self):
1347 self.id = 'dddddddd-dddd-dddd-dddd-dddddddddddd' 1352 self.id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
@@ -1351,12 +1356,27 @@ class FakeV4Subnet(object):
1351 self.enable_dhcp = True 1356 self.enable_dhcp = True
1352 1357
1353 1358
1359class FakeV6Subnet(object):
1360 def __init__(self):
1361 self.id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
1362 self.ip_version = 6
1363 self.cidr = '2001:db8:0:1::/64'
1364 self.gateway_ip = '2001:db8:0:1::1'
1365 self.enable_dhcp = True
1366
1367
1354class FakeV4SubnetOutsideGateway(FakeV4Subnet): 1368class FakeV4SubnetOutsideGateway(FakeV4Subnet):
1355 def __init__(self): 1369 def __init__(self):
1356 super(FakeV4SubnetOutsideGateway, self).__init__() 1370 super(FakeV4SubnetOutsideGateway, self).__init__()
1357 self.gateway_ip = '192.168.1.1' 1371 self.gateway_ip = '192.168.1.1'
1358 1372
1359 1373
1374class FakeV6SubnetOutsideGateway(FakeV6Subnet):
1375 def __init__(self):
1376 super(FakeV6SubnetOutsideGateway, self).__init__()
1377 self.gateway_ip = '2001:db8:1:1::1'
1378
1379
1360class FakeV4SubnetNoGateway(object): 1380class FakeV4SubnetNoGateway(object):
1361 def __init__(self): 1381 def __init__(self):
1362 self.id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee' 1382 self.id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
@@ -1366,6 +1386,15 @@ class FakeV4SubnetNoGateway(object):
1366 self.enable_dhcp = True 1386 self.enable_dhcp = True
1367 1387
1368 1388
1389class FakeV6SubnetNoGateway(object):
1390 def __init__(self):
1391 self.id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
1392 self.ip_version = 6
1393 self.cidr = '2001:db8:1:0::/64'
1394 self.gateway_ip = None
1395 self.enable_dhcp = True
1396
1397
1369class FakeV4Network(object): 1398class FakeV4Network(object):
1370 def __init__(self): 1399 def __init__(self):
1371 self.id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' 1400 self.id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
@@ -1374,24 +1403,39 @@ class FakeV4Network(object):
1374 self.namespace = 'qdhcp-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' 1403 self.namespace = 'qdhcp-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
1375 1404
1376 1405
1406class FakeDualNetwork(object):
1407 def __init__(self):
1408 self.id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
1409 self.subnets = [FakeV4Subnet(), FakeV6Subnet()]
1410 self.ports = [FakePort1(), FakePort2()]
1411 self.namespace = 'qdhcp-dddddddd-dddd-dddd-dddd-dddddddddddd'
1412
1413
1377class FakeV4NetworkOutsideGateway(FakeV4Network): 1414class FakeV4NetworkOutsideGateway(FakeV4Network):
1378 def __init__(self): 1415 def __init__(self):
1379 super(FakeV4NetworkOutsideGateway, self).__init__() 1416 super(FakeV4NetworkOutsideGateway, self).__init__()
1380 self.subnets = [FakeV4SubnetOutsideGateway()] 1417 self.subnets = [FakeV4SubnetOutsideGateway()]
1381 1418
1382 1419
1383class FakeV4NetworkNoSubnet(object): 1420class FakeDualNetworkOutsideGateway(FakeDualNetwork):
1421 def __init__(self):
1422 super(FakeDualNetworkOutsideGateway, self).__init__()
1423 self.subnets = [FakeV4SubnetOutsideGateway(),
1424 FakeV6SubnetOutsideGateway()]
1425
1426
1427class FakeDualNetworkNoSubnet(object):
1384 def __init__(self): 1428 def __init__(self):
1385 self.id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' 1429 self.id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
1386 self.subnets = [] 1430 self.subnets = []
1387 self.ports = [] 1431 self.ports = []
1388 1432
1389 1433
1390class FakeV4NetworkNoGateway(object): 1434class FakeDualNetworkNoGateway(object):
1391 def __init__(self): 1435 def __init__(self):
1392 self.id = 'cccccccc-cccc-cccc-cccc-cccccccccccc' 1436 self.id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
1393 self.subnets = [FakeV4SubnetNoGateway()] 1437 self.subnets = [FakeV4SubnetNoGateway(), FakeV6SubnetNoGateway()]
1394 self.ports = [FakePort1()] 1438 self.ports = [FakePort1(), FakePort2()]
1395 1439
1396 1440
1397class TestDeviceManager(base.BaseTestCase): 1441class TestDeviceManager(base.BaseTestCase):
@@ -1744,7 +1788,7 @@ class TestDeviceManager(base.BaseTestCase):
1744 network = FakeV4Network() 1788 network = FakeV4Network()
1745 dh._set_default_route(network, 'tap-name') 1789 dh._set_default_route(network, 'tap-name')
1746 1790
1747 self.assertEqual(1, device.route.get_gateway.call_count) 1791 self.assertEqual(2, device.route.get_gateway.call_count)
1748 self.assertFalse(device.route.delete_gateway.called) 1792 self.assertFalse(device.route.delete_gateway.called)
1749 device.route.add_gateway.assert_called_once_with('192.168.0.1') 1793 device.route.add_gateway.assert_called_once_with('192.168.0.1')
1750 1794
@@ -1758,7 +1802,7 @@ class TestDeviceManager(base.BaseTestCase):
1758 network = FakeV4NetworkOutsideGateway() 1802 network = FakeV4NetworkOutsideGateway()
1759 dh._set_default_route(network, 'tap-name') 1803 dh._set_default_route(network, 'tap-name')
1760 1804
1761 self.assertEqual(1, device.route.get_gateway.call_count) 1805 self.assertEqual(2, device.route.get_gateway.call_count)
1762 self.assertFalse(device.route.delete_gateway.called) 1806 self.assertFalse(device.route.delete_gateway.called)
1763 device.route.add_route.assert_called_once_with('192.168.1.1', 1807 device.route.add_route.assert_called_once_with('192.168.1.1',
1764 scope='link') 1808 scope='link')
@@ -1770,104 +1814,141 @@ class TestDeviceManager(base.BaseTestCase):
1770 device = mock.Mock() 1814 device = mock.Mock()
1771 mock_IPDevice.return_value = device 1815 mock_IPDevice.return_value = device
1772 device.route.get_gateway.return_value = None 1816 device.route.get_gateway.return_value = None
1773 network = FakeV4NetworkNoSubnet() 1817 network = FakeDualNetworkNoSubnet()
1774 network.namespace = 'qdhcp-1234' 1818 network.namespace = 'qdhcp-1234'
1775 dh._set_default_route(network, 'tap-name') 1819 dh._set_default_route(network, 'tap-name')
1776 1820
1777 self.assertEqual(1, device.route.get_gateway.call_count) 1821 self.assertEqual(2, device.route.get_gateway.call_count)
1778 self.assertFalse(device.route.delete_gateway.called) 1822 self.assertFalse(device.route.delete_gateway.called)
1779 self.assertFalse(device.route.add_gateway.called) 1823 self.assertFalse(device.route.add_gateway.called)
1780 1824
1781 def test_set_default_route_no_subnet_delete_gateway(self): 1825 def test_set_default_route_no_subnet_delete_gateway(self):
1782 dh = dhcp.DeviceManager(cfg.CONF, None) 1826 dh = dhcp.DeviceManager(cfg.CONF, None)
1827 v4_gateway = '192.168.0.1'
1828 v6_gateway = '2001:db8:0:1::1'
1829 expected = [mock.call(v4_gateway),
1830 mock.call(v6_gateway)]
1783 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice: 1831 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice:
1784 device = mock.Mock() 1832 device = mock.Mock()
1785 mock_IPDevice.return_value = device 1833 mock_IPDevice.return_value = device
1786 device.route.get_gateway.return_value = dict(gateway='192.168.0.1') 1834 device.route.get_gateway.side_effect = [
1787 network = FakeV4NetworkNoSubnet() 1835 dict(gateway=v4_gateway), dict(gateway=v6_gateway)]
1836 network = FakeDualNetworkNoSubnet()
1788 network.namespace = 'qdhcp-1234' 1837 network.namespace = 'qdhcp-1234'
1789 dh._set_default_route(network, 'tap-name') 1838 dh._set_default_route(network, 'tap-name')
1790 1839
1791 self.assertEqual(1, device.route.get_gateway.call_count) 1840 self.assertEqual(2, device.route.get_gateway.call_count)
1792 device.route.delete_gateway.assert_called_once_with('192.168.0.1') 1841 self.assertEqual(2, device.route.delete_gateway.call_count)
1842 device.route.delete_gateway.assert_has_calls(expected)
1793 self.assertFalse(device.route.add_gateway.called) 1843 self.assertFalse(device.route.add_gateway.called)
1794 1844
1795 def test_set_default_route_no_gateway(self): 1845 def test_set_default_route_no_gateway(self):
1796 dh = dhcp.DeviceManager(cfg.CONF, None) 1846 dh = dhcp.DeviceManager(cfg.CONF, None)
1847 v4_gateway = '192.168.0.1'
1848 v6_gateway = '2001:db8:0:1::1'
1849 expected = [mock.call(v4_gateway),
1850 mock.call(v6_gateway)]
1797 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice: 1851 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice:
1798 device = mock.Mock() 1852 device = mock.Mock()
1799 mock_IPDevice.return_value = device 1853 mock_IPDevice.return_value = device
1800 device.route.get_gateway.return_value = dict(gateway='192.168.0.1') 1854 device.route.get_gateway.side_effect = [
1801 network = FakeV4NetworkNoGateway() 1855 dict(gateway=v4_gateway), dict(gateway=v6_gateway)]
1856 network = FakeDualNetworkNoGateway()
1802 network.namespace = 'qdhcp-1234' 1857 network.namespace = 'qdhcp-1234'
1803 dh._set_default_route(network, 'tap-name') 1858 dh._set_default_route(network, 'tap-name')
1804 1859
1805 self.assertEqual(1, device.route.get_gateway.call_count) 1860 self.assertEqual(2, device.route.get_gateway.call_count)
1806 device.route.delete_gateway.assert_called_once_with('192.168.0.1') 1861 self.assertEqual(2, device.route.delete_gateway.call_count)
1862 device.route.delete_gateway.assert_has_calls(expected)
1807 self.assertFalse(device.route.add_gateway.called) 1863 self.assertFalse(device.route.add_gateway.called)
1808 1864
1809 def test_set_default_route_do_nothing(self): 1865 def test_set_default_route_do_nothing(self):
1810 dh = dhcp.DeviceManager(cfg.CONF, None) 1866 dh = dhcp.DeviceManager(cfg.CONF, None)
1867 v4_gateway = '192.168.0.1'
1868 v6_gateway = '2001:db8:0:1::1'
1811 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice: 1869 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice:
1812 device = mock.Mock() 1870 device = mock.Mock()
1813 mock_IPDevice.return_value = device 1871 mock_IPDevice.return_value = device
1814 device.route.get_gateway.return_value = dict(gateway='192.168.0.1') 1872 device.route.get_gateway.side_effect = [
1815 network = FakeV4Network() 1873 dict(gateway=v4_gateway), dict(gateway=v6_gateway)]
1874 network = FakeDualNetwork()
1816 dh._set_default_route(network, 'tap-name') 1875 dh._set_default_route(network, 'tap-name')
1817 1876
1818 self.assertEqual(1, device.route.get_gateway.call_count) 1877 self.assertEqual(2, device.route.get_gateway.call_count)
1819 self.assertFalse(device.route.delete_gateway.called) 1878 self.assertFalse(device.route.delete_gateway.called)
1820 self.assertFalse(device.route.add_gateway.called) 1879 self.assertFalse(device.route.add_gateway.called)
1821 1880
1822 def test_set_default_route_change_gateway(self): 1881 def test_set_default_route_change_gateway(self):
1823 dh = dhcp.DeviceManager(cfg.CONF, None) 1882 dh = dhcp.DeviceManager(cfg.CONF, None)
1883 v4_gateway = '192.168.0.1'
1884 old_v4_gateway = '192.168.0.2'
1885 v6_gateway = '2001:db8:0:1::1'
1886 old_v6_gateway = '2001:db8:0:1::2'
1887 expected = [mock.call(v4_gateway),
1888 mock.call(v6_gateway)]
1824 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice: 1889 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice:
1825 device = mock.Mock() 1890 device = mock.Mock()
1826 mock_IPDevice.return_value = device 1891 mock_IPDevice.return_value = device
1827 device.route.get_gateway.return_value = dict(gateway='192.168.0.2') 1892 device.route.get_gateway.side_effect = [
1828 network = FakeV4Network() 1893 dict(gateway=old_v4_gateway), dict(gateway=old_v6_gateway)]
1894 network = FakeDualNetwork()
1829 dh._set_default_route(network, 'tap-name') 1895 dh._set_default_route(network, 'tap-name')
1830 1896
1831 self.assertEqual(1, device.route.get_gateway.call_count) 1897 self.assertEqual(2, device.route.get_gateway.call_count)
1832 self.assertFalse(device.route.delete_gateway.called) 1898 self.assertFalse(device.route.delete_gateway.called)
1833 device.route.add_gateway.assert_called_once_with('192.168.0.1') 1899 device.route.add_gateway.assert_has_calls(expected)
1834 1900
1835 def test_set_default_route_change_gateway_outside_subnet(self): 1901 def test_set_default_route_change_gateway_outside_subnet(self):
1836 dh = dhcp.DeviceManager(cfg.CONF, None) 1902 dh = dhcp.DeviceManager(cfg.CONF, None)
1903 v4_gateway = '192.168.1.1'
1904 old_v4_gateway = '192.168.2.1'
1905 v6_gateway = '2001:db8:1:1::1'
1906 old_v6_gateway = '2001:db8:2:0::1'
1907 add_route_expected = [mock.call(v4_gateway, scope='link'),
1908 mock.call(v6_gateway, scope='link')]
1909 add_gw_expected = [mock.call(v4_gateway),
1910 mock.call(v6_gateway)]
1837 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice: 1911 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice:
1838 device = mock.Mock() 1912 device = mock.Mock()
1839 mock_IPDevice.return_value = device 1913 mock_IPDevice.return_value = device
1840 device.route.list_onlink_routes.return_value = ( 1914 device.route.list_onlink_routes.side_effect = [
1841 [{'cidr': '192.168.2.1'}]) 1915 [{'cidr': old_v4_gateway}], []]
1842 device.route.get_gateway.return_value = dict(gateway='192.168.2.1') 1916 device.route.get_gateway.side_effect = [
1843 network = FakeV4NetworkOutsideGateway() 1917 dict(gateway=old_v4_gateway), dict(gateway=old_v6_gateway)]
1918 network = FakeDualNetworkOutsideGateway()
1844 dh._set_default_route(network, 'tap-name') 1919 dh._set_default_route(network, 'tap-name')
1845 1920
1846 self.assertEqual(1, device.route.get_gateway.call_count) 1921 self.assertEqual(2, device.route.get_gateway.call_count)
1847 self.assertEqual(2, device.route.list_onlink_routes.call_count) 1922 self.assertEqual(2, device.route.list_onlink_routes.call_count)
1848 self.assertFalse(device.route.delete_gateway.called) 1923 self.assertFalse(device.route.delete_gateway.called)
1849 device.route.delete_route.assert_called_once_with('192.168.2.1', 1924 device.route.delete_route.assert_called_once_with(old_v4_gateway,
1850 scope='link')
1851 device.route.add_route.assert_called_once_with('192.168.1.1',
1852 scope='link') 1925 scope='link')
1853 device.route.add_gateway.assert_called_once_with('192.168.1.1') 1926 device.route.add_route.assert_has_calls(add_route_expected)
1927 device.route.add_gateway.assert_has_calls(add_gw_expected)
1854 1928
1855 def test_set_default_route_two_subnets(self): 1929 def test_set_default_route_two_subnets(self):
1856 # Try two subnets. Should set gateway from the first. 1930 # Try two subnets. Should set gateway from the first.
1857 dh = dhcp.DeviceManager(cfg.CONF, None) 1931 dh = dhcp.DeviceManager(cfg.CONF, None)
1932 v4_gateway = '192.168.1.1'
1933 v6_gateway = '2001:db8:1:1::1'
1934 expected = [mock.call(v4_gateway),
1935 mock.call(v6_gateway)]
1858 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice: 1936 with mock.patch.object(dhcp.ip_lib, 'IPDevice') as mock_IPDevice:
1859 device = mock.Mock() 1937 device = mock.Mock()
1860 mock_IPDevice.return_value = device 1938 mock_IPDevice.return_value = device
1861 device.route.get_gateway.return_value = None 1939 device.route.get_gateway.return_value = None
1862 network = FakeV4Network() 1940 network = FakeDualNetwork()
1863 subnet2 = FakeV4Subnet() 1941 subnet2 = FakeV4Subnet()
1864 subnet2.gateway_ip = '192.168.1.1' 1942 subnet2.gateway_ip = v4_gateway
1865 network.subnets = [subnet2, FakeV4Subnet()] 1943 subnet3 = FakeV6Subnet()
1944 subnet3.gateway_ip = v6_gateway
1945 network.subnets = [subnet2, FakeV4Subnet(),
1946 subnet3, FakeV6Subnet()]
1866 dh._set_default_route(network, 'tap-name') 1947 dh._set_default_route(network, 'tap-name')
1867 1948
1868 self.assertEqual(1, device.route.get_gateway.call_count) 1949 self.assertEqual(2, device.route.get_gateway.call_count)
1869 self.assertFalse(device.route.delete_gateway.called) 1950 self.assertFalse(device.route.delete_gateway.called)
1870 device.route.add_gateway.assert_called_once_with('192.168.1.1') 1951 device.route.add_gateway.assert_has_calls(expected)
1871 1952
1872 1953
1873class TestDictModel(base.BaseTestCase): 1954class TestDictModel(base.BaseTestCase):