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