Merge ~r00ta/maas:lp-2027621 into maas:master

Proposed by Jacopo Rota
Status: Merged
Approved by: Jacopo Rota
Approved revision: 983c55ba1a9b58c2f7a5cb6b0838eb0db27eddd8
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~r00ta/maas:lp-2027621
Merge into: maas:master
Diff against target: 286 lines (+123/-21)
2 files modified
src/maasserver/dhcp.py (+15/-9)
src/maasserver/tests/test_dhcp.py (+108/-12)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Anton Troyanov Approve
Review via email: mp+446748@code.launchpad.net

Commit message

fix dhcp make_failover_peer_config mixing ipv4 and ipv6 addresses

Description of the change

This MP aims to fix https://bugs.launchpad.net/maas/+bug/2027621.

The function make_failover_peer_config is mixing ipv4 and ipv6 addresses when the configuration is rendered.

The fix is
1) pass the `ip_version` to this function
2) select the interfaces of the rack controller that are on the vlan and that match the `ip_version`
3) select the best interface according to a specific logic already implemented
4) get an ip from that interface that is on the vlan and that matches the `ip_version`

A test to verify this scenario has been added.

To post a comment you must log in.
Revision history for this message
Anton Troyanov (troyanov) wrote :

LGTM!

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp-2027621 lp:~r00ta/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/3016/console
COMMIT: 04242f723144301e93011ac95a79a2f947b33fca

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp-2027621 lp:~r00ta/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 983c55ba1a9b58c2f7a5cb6b0838eb0db27eddd8

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/maasserver/dhcp.py b/src/maasserver/dhcp.py
index 32ad98a..8f51cbf 100644
--- a/src/maasserver/dhcp.py
+++ b/src/maasserver/dhcp.py
@@ -227,15 +227,17 @@ def ip_is_on_vlan(ip_address, vlan):
227 )227 )
228228
229229
230def get_ip_address_for_interface(interface, vlan):230def get_ip_address_for_interface(interface, vlan, ip_version: int):
231 """Return the IP address for `interface` on `vlan`."""231 """Return the IP address for `interface` on `vlan`."""
232 for ip_address in interface.ip_addresses.all():232 for ip_address in interface.ip_addresses.all():
233 if ip_is_on_vlan(ip_address, vlan):233 if ip_is_version(ip_address, ip_version) and ip_is_on_vlan(
234 ip_address, vlan
235 ):
234 return ip_address236 return ip_address
235 return None237 return None
236238
237239
238def get_ip_address_for_rack_controller(rack_controller, vlan):240def get_ip_address_for_rack_controller(rack_controller, vlan, ip_version: int):
239 """Return the IP address for `rack_controller` on `vlan`."""241 """Return the IP address for `rack_controller` on `vlan`."""
240 # First we build a list of all interfaces that have an IP address242 # First we build a list of all interfaces that have an IP address
241 # on that vlan. Then we pick the best interface for that vlan243 # on that vlan. Then we pick the best interface for that vlan
@@ -248,10 +250,12 @@ def get_ip_address_for_rack_controller(rack_controller, vlan):
248 matching_interfaces = set()250 matching_interfaces = set()
249 for interface in interfaces:251 for interface in interfaces:
250 for ip_address in interface.ip_addresses.all():252 for ip_address in interface.ip_addresses.all():
251 if ip_is_on_vlan(ip_address, vlan):253 if ip_is_version(ip_address, ip_version) and ip_is_on_vlan(
254 ip_address, vlan
255 ):
252 matching_interfaces.add(interface)256 matching_interfaces.add(interface)
253 interface = get_best_interface(matching_interfaces)257 interface = get_best_interface(matching_interfaces)
254 return get_ip_address_for_interface(interface, vlan)258 return get_ip_address_for_interface(interface, vlan, ip_version)
255259
256260
257def get_ntp_server_addresses_for_rack(rack: RackController) -> dict:261def get_ntp_server_addresses_for_rack(rack: RackController) -> dict:
@@ -498,17 +502,19 @@ def make_subnet_config(
498 return subnet_config502 return subnet_config
499503
500504
501def make_failover_peer_config(vlan, rack_controller):505def make_failover_peer_config(vlan, rack_controller, ip_version: int):
502 """Return DHCP failover peer configuration dict for a rack controller."""506 """Return DHCP failover peer configuration dict for a rack controller."""
503 is_primary = vlan.primary_rack_id == rack_controller.id507 is_primary = vlan.primary_rack_id == rack_controller.id
504 interface_ip_address = get_ip_address_for_rack_controller(508 interface_ip_address = get_ip_address_for_rack_controller(
505 rack_controller, vlan509 rack_controller, vlan, ip_version
506 )510 )
507 if is_primary:511 if is_primary:
508 peer_rack = vlan.secondary_rack512 peer_rack = vlan.secondary_rack
509 else:513 else:
510 peer_rack = vlan.primary_rack514 peer_rack = vlan.primary_rack
511 peer_address = get_ip_address_for_rack_controller(peer_rack, vlan)515 peer_address = get_ip_address_for_rack_controller(
516 peer_rack, vlan, ip_version
517 )
512 name = "failover-vlan-%d" % vlan.id518 name = "failover-vlan-%d" % vlan.id
513 return (519 return (
514 name,520 name,
@@ -631,7 +637,7 @@ def get_dhcp_configure_for(
631 if has_secondary:637 if has_secondary:
632 # Generate the failover peer for this VLAN.638 # Generate the failover peer for this VLAN.
633 peer_name, peer_config, peer_rack = make_failover_peer_config(639 peer_name, peer_config, peer_rack = make_failover_peer_config(
634 vlan, rack_controller640 vlan, rack_controller, ip_version
635 )641 )
636 else:642 else:
637 peer_name, peer_config, peer_rack = None, None, None643 peer_name, peer_config, peer_rack = None, None, None
diff --git a/src/maasserver/tests/test_dhcp.py b/src/maasserver/tests/test_dhcp.py
index e9d0cfa..04d15dc 100644
--- a/src/maasserver/tests/test_dhcp.py
+++ b/src/maasserver/tests/test_dhcp.py
@@ -815,10 +815,16 @@ class TestGetIPAddressForInterface(MAASServerTestCase):
815 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan)815 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan)
816 subnet = factory.make_Subnet(vlan=vlan)816 subnet = factory.make_Subnet(vlan=vlan)
817 ip_address = factory.make_StaticIPAddress(817 ip_address = factory.make_StaticIPAddress(
818 alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface818 ip=factory.pick_ip_in_Subnet(subnet),
819 alloc_type=IPADDRESS_TYPE.AUTO,
820 subnet=subnet,
821 interface=interface,
819 )822 )
820 self.assertEqual(823 self.assertEqual(
821 ip_address, dhcp.get_ip_address_for_interface(interface, vlan)824 ip_address,
825 dhcp.get_ip_address_for_interface(
826 interface, vlan, subnet.get_ip_version()
827 ),
822 )828 )
823829
824 def test_returns_None(self):830 def test_returns_None(self):
@@ -826,10 +832,15 @@ class TestGetIPAddressForInterface(MAASServerTestCase):
826 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan)832 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan)
827 subnet = factory.make_Subnet(vlan=vlan)833 subnet = factory.make_Subnet(vlan=vlan)
828 factory.make_StaticIPAddress(834 factory.make_StaticIPAddress(
829 alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface835 ip=factory.pick_ip_in_Subnet(subnet),
836 alloc_type=IPADDRESS_TYPE.AUTO,
837 subnet=subnet,
838 interface=interface,
830 )839 )
831 self.assertIsNone(840 self.assertIsNone(
832 dhcp.get_ip_address_for_interface(interface, factory.make_VLAN())841 dhcp.get_ip_address_for_interface(
842 interface, factory.make_VLAN(), subnet.get_ip_version()
843 )
833 )844 )
834845
835846
@@ -844,11 +855,16 @@ class TestGetIPAddressForRackController(MAASServerTestCase):
844 )855 )
845 subnet = factory.make_Subnet(vlan=vlan)856 subnet = factory.make_Subnet(vlan=vlan)
846 ip_address = factory.make_StaticIPAddress(857 ip_address = factory.make_StaticIPAddress(
847 alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface858 ip=factory.pick_ip_in_Subnet(subnet),
859 alloc_type=IPADDRESS_TYPE.AUTO,
860 subnet=subnet,
861 interface=interface,
848 )862 )
849 self.assertEqual(863 self.assertEqual(
850 ip_address,864 ip_address,
851 dhcp.get_ip_address_for_rack_controller(rack_controller, vlan),865 dhcp.get_ip_address_for_rack_controller(
866 rack_controller, vlan, subnet.get_ip_version()
867 ),
852 )868 )
853869
854 def test_returns_ip_address_from_best_interface_on_rack_controller(self):870 def test_returns_ip_address_from_best_interface_on_rack_controller(self):
@@ -868,7 +884,10 @@ class TestGetIPAddressForRackController(MAASServerTestCase):
868 )884 )
869 subnet = factory.make_Subnet(vlan=vlan)885 subnet = factory.make_Subnet(vlan=vlan)
870 factory.make_StaticIPAddress(886 factory.make_StaticIPAddress(
871 alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface887 ip=factory.pick_ip_in_Subnet(subnet),
888 alloc_type=IPADDRESS_TYPE.AUTO,
889 subnet=subnet,
890 interface=interface,
872 )891 )
873 bond_ip_address = factory.make_StaticIPAddress(892 bond_ip_address = factory.make_StaticIPAddress(
874 alloc_type=IPADDRESS_TYPE.AUTO,893 alloc_type=IPADDRESS_TYPE.AUTO,
@@ -877,7 +896,9 @@ class TestGetIPAddressForRackController(MAASServerTestCase):
877 )896 )
878 self.assertEqual(897 self.assertEqual(
879 bond_ip_address,898 bond_ip_address,
880 dhcp.get_ip_address_for_rack_controller(rack_controller, vlan),899 dhcp.get_ip_address_for_rack_controller(
900 rack_controller, vlan, subnet.get_ip_version()
901 ),
881 )902 )
882903
883904
@@ -2121,11 +2142,12 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
2121 primary_rack=primary_rack,2142 primary_rack=primary_rack,
2122 secondary_rack=secondary_rack,2143 secondary_rack=secondary_rack,
2123 )2144 )
2124 subnet = factory.make_Subnet(vlan=vlan)2145 subnet = factory.make_Subnet(vlan=vlan, version=4)
2125 primary_interface = factory.make_Interface(2146 primary_interface = factory.make_Interface(
2126 INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan2147 INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan
2127 )2148 )
2128 primary_ip = factory.make_StaticIPAddress(2149 primary_ip = factory.make_StaticIPAddress(
2150 ip=factory.pick_ip_in_Subnet(subnet),
2129 alloc_type=IPADDRESS_TYPE.AUTO,2151 alloc_type=IPADDRESS_TYPE.AUTO,
2130 subnet=subnet,2152 subnet=subnet,
2131 interface=primary_interface,2153 interface=primary_interface,
@@ -2134,6 +2156,7 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
2134 INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan2156 INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan
2135 )2157 )
2136 secondary_ip = factory.make_StaticIPAddress(2158 secondary_ip = factory.make_StaticIPAddress(
2159 ip=factory.pick_ip_in_Subnet(subnet),
2137 alloc_type=IPADDRESS_TYPE.AUTO,2160 alloc_type=IPADDRESS_TYPE.AUTO,
2138 subnet=subnet,2161 subnet=subnet,
2139 interface=secondary_interface,2162 interface=secondary_interface,
@@ -2150,7 +2173,7 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
2150 },2173 },
2151 secondary_rack,2174 secondary_rack,
2152 ),2175 ),
2153 dhcp.make_failover_peer_config(vlan, primary_rack),2176 dhcp.make_failover_peer_config(vlan, primary_rack, 4),
2154 )2177 )
21552178
2156 def test_renders_config_for_secondary(self):2179 def test_renders_config_for_secondary(self):
@@ -2161,11 +2184,12 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
2161 primary_rack=primary_rack,2184 primary_rack=primary_rack,
2162 secondary_rack=secondary_rack,2185 secondary_rack=secondary_rack,
2163 )2186 )
2164 subnet = factory.make_Subnet(vlan=vlan)2187 subnet = factory.make_Subnet(vlan=vlan, version=4)
2165 primary_interface = factory.make_Interface(2188 primary_interface = factory.make_Interface(
2166 INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan2189 INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan
2167 )2190 )
2168 primary_ip = factory.make_StaticIPAddress(2191 primary_ip = factory.make_StaticIPAddress(
2192 ip=factory.pick_ip_in_Subnet(subnet),
2169 alloc_type=IPADDRESS_TYPE.AUTO,2193 alloc_type=IPADDRESS_TYPE.AUTO,
2170 subnet=subnet,2194 subnet=subnet,
2171 interface=primary_interface,2195 interface=primary_interface,
@@ -2174,6 +2198,7 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
2174 INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan2198 INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan
2175 )2199 )
2176 secondary_ip = factory.make_StaticIPAddress(2200 secondary_ip = factory.make_StaticIPAddress(
2201 ip=factory.pick_ip_in_Subnet(subnet),
2177 alloc_type=IPADDRESS_TYPE.AUTO,2202 alloc_type=IPADDRESS_TYPE.AUTO,
2178 subnet=subnet,2203 subnet=subnet,
2179 interface=secondary_interface,2204 interface=secondary_interface,
@@ -2190,7 +2215,78 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
2190 },2215 },
2191 primary_rack,2216 primary_rack,
2192 ),2217 ),
2193 dhcp.make_failover_peer_config(vlan, secondary_rack),2218 dhcp.make_failover_peer_config(vlan, secondary_rack, 4),
2219 )
2220
2221 # See https://bugs.launchpad.net/maas/+bug/2027621
2222 def test_renders_config_for_secondary_should_not_mix_v4_and_v6_addresses(
2223 self,
2224 ):
2225 primary_rack = factory.make_RackController()
2226 secondary_rack = factory.make_RackController()
2227 vlan = factory.make_VLAN(
2228 dhcp_on=True,
2229 primary_rack=primary_rack,
2230 secondary_rack=secondary_rack,
2231 )
2232 subnet_v4 = factory.make_Subnet(vlan=vlan, version=4)
2233 subnet_v6 = factory.make_Subnet(vlan=vlan, version=6)
2234 primary_interface = factory.make_Interface(
2235 INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan
2236 )
2237 primary_ip_v4 = factory.make_StaticIPAddress(
2238 ip=factory.pick_ip_in_Subnet(subnet_v4),
2239 alloc_type=IPADDRESS_TYPE.AUTO,
2240 subnet=subnet_v4,
2241 interface=primary_interface,
2242 )
2243 primary_ip_v6 = factory.make_StaticIPAddress(
2244 ip=factory.pick_ip_in_Subnet(subnet_v6),
2245 alloc_type=IPADDRESS_TYPE.AUTO,
2246 subnet=subnet_v6,
2247 interface=primary_interface,
2248 )
2249 secondary_interface = factory.make_Interface(
2250 INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan
2251 )
2252 secondary_ip_v4 = factory.make_StaticIPAddress(
2253 ip=factory.pick_ip_in_Subnet(subnet_v4),
2254 alloc_type=IPADDRESS_TYPE.AUTO,
2255 subnet=subnet_v4,
2256 interface=secondary_interface,
2257 )
2258 secondary_ip_v6 = factory.make_StaticIPAddress(
2259 ip=factory.pick_ip_in_Subnet(subnet_v6),
2260 alloc_type=IPADDRESS_TYPE.AUTO,
2261 subnet=subnet_v6,
2262 interface=secondary_interface,
2263 )
2264 failover_peer_name = "failover-vlan-%d" % vlan.id
2265 self.assertEqual(
2266 (
2267 failover_peer_name,
2268 {
2269 "name": failover_peer_name,
2270 "mode": "secondary",
2271 "address": str(secondary_ip_v4.ip),
2272 "peer_address": str(primary_ip_v4.ip),
2273 },
2274 primary_rack,
2275 ),
2276 dhcp.make_failover_peer_config(vlan, secondary_rack, 4),
2277 )
2278 self.assertEqual(
2279 (
2280 failover_peer_name,
2281 {
2282 "name": failover_peer_name,
2283 "mode": "secondary",
2284 "address": str(secondary_ip_v6.ip),
2285 "peer_address": str(primary_ip_v6.ip),
2286 },
2287 primary_rack,
2288 ),
2289 dhcp.make_failover_peer_config(vlan, secondary_rack, 6),
2194 )2290 )
21952291
21962292

Subscribers

People subscribed via source and target branches