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
1diff --git a/src/maasserver/dhcp.py b/src/maasserver/dhcp.py
2index 32ad98a..8f51cbf 100644
3--- a/src/maasserver/dhcp.py
4+++ b/src/maasserver/dhcp.py
5@@ -227,15 +227,17 @@ def ip_is_on_vlan(ip_address, vlan):
6 )
7
8
9-def get_ip_address_for_interface(interface, vlan):
10+def get_ip_address_for_interface(interface, vlan, ip_version: int):
11 """Return the IP address for `interface` on `vlan`."""
12 for ip_address in interface.ip_addresses.all():
13- if ip_is_on_vlan(ip_address, vlan):
14+ if ip_is_version(ip_address, ip_version) and ip_is_on_vlan(
15+ ip_address, vlan
16+ ):
17 return ip_address
18 return None
19
20
21-def get_ip_address_for_rack_controller(rack_controller, vlan):
22+def get_ip_address_for_rack_controller(rack_controller, vlan, ip_version: int):
23 """Return the IP address for `rack_controller` on `vlan`."""
24 # First we build a list of all interfaces that have an IP address
25 # on that vlan. Then we pick the best interface for that vlan
26@@ -248,10 +250,12 @@ def get_ip_address_for_rack_controller(rack_controller, vlan):
27 matching_interfaces = set()
28 for interface in interfaces:
29 for ip_address in interface.ip_addresses.all():
30- if ip_is_on_vlan(ip_address, vlan):
31+ if ip_is_version(ip_address, ip_version) and ip_is_on_vlan(
32+ ip_address, vlan
33+ ):
34 matching_interfaces.add(interface)
35 interface = get_best_interface(matching_interfaces)
36- return get_ip_address_for_interface(interface, vlan)
37+ return get_ip_address_for_interface(interface, vlan, ip_version)
38
39
40 def get_ntp_server_addresses_for_rack(rack: RackController) -> dict:
41@@ -498,17 +502,19 @@ def make_subnet_config(
42 return subnet_config
43
44
45-def make_failover_peer_config(vlan, rack_controller):
46+def make_failover_peer_config(vlan, rack_controller, ip_version: int):
47 """Return DHCP failover peer configuration dict for a rack controller."""
48 is_primary = vlan.primary_rack_id == rack_controller.id
49 interface_ip_address = get_ip_address_for_rack_controller(
50- rack_controller, vlan
51+ rack_controller, vlan, ip_version
52 )
53 if is_primary:
54 peer_rack = vlan.secondary_rack
55 else:
56 peer_rack = vlan.primary_rack
57- peer_address = get_ip_address_for_rack_controller(peer_rack, vlan)
58+ peer_address = get_ip_address_for_rack_controller(
59+ peer_rack, vlan, ip_version
60+ )
61 name = "failover-vlan-%d" % vlan.id
62 return (
63 name,
64@@ -631,7 +637,7 @@ def get_dhcp_configure_for(
65 if has_secondary:
66 # Generate the failover peer for this VLAN.
67 peer_name, peer_config, peer_rack = make_failover_peer_config(
68- vlan, rack_controller
69+ vlan, rack_controller, ip_version
70 )
71 else:
72 peer_name, peer_config, peer_rack = None, None, None
73diff --git a/src/maasserver/tests/test_dhcp.py b/src/maasserver/tests/test_dhcp.py
74index e9d0cfa..04d15dc 100644
75--- a/src/maasserver/tests/test_dhcp.py
76+++ b/src/maasserver/tests/test_dhcp.py
77@@ -815,10 +815,16 @@ class TestGetIPAddressForInterface(MAASServerTestCase):
78 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan)
79 subnet = factory.make_Subnet(vlan=vlan)
80 ip_address = factory.make_StaticIPAddress(
81- alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface
82+ ip=factory.pick_ip_in_Subnet(subnet),
83+ alloc_type=IPADDRESS_TYPE.AUTO,
84+ subnet=subnet,
85+ interface=interface,
86 )
87 self.assertEqual(
88- ip_address, dhcp.get_ip_address_for_interface(interface, vlan)
89+ ip_address,
90+ dhcp.get_ip_address_for_interface(
91+ interface, vlan, subnet.get_ip_version()
92+ ),
93 )
94
95 def test_returns_None(self):
96@@ -826,10 +832,15 @@ class TestGetIPAddressForInterface(MAASServerTestCase):
97 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan)
98 subnet = factory.make_Subnet(vlan=vlan)
99 factory.make_StaticIPAddress(
100- alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface
101+ ip=factory.pick_ip_in_Subnet(subnet),
102+ alloc_type=IPADDRESS_TYPE.AUTO,
103+ subnet=subnet,
104+ interface=interface,
105 )
106 self.assertIsNone(
107- dhcp.get_ip_address_for_interface(interface, factory.make_VLAN())
108+ dhcp.get_ip_address_for_interface(
109+ interface, factory.make_VLAN(), subnet.get_ip_version()
110+ )
111 )
112
113
114@@ -844,11 +855,16 @@ class TestGetIPAddressForRackController(MAASServerTestCase):
115 )
116 subnet = factory.make_Subnet(vlan=vlan)
117 ip_address = factory.make_StaticIPAddress(
118- alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface
119+ ip=factory.pick_ip_in_Subnet(subnet),
120+ alloc_type=IPADDRESS_TYPE.AUTO,
121+ subnet=subnet,
122+ interface=interface,
123 )
124 self.assertEqual(
125 ip_address,
126- dhcp.get_ip_address_for_rack_controller(rack_controller, vlan),
127+ dhcp.get_ip_address_for_rack_controller(
128+ rack_controller, vlan, subnet.get_ip_version()
129+ ),
130 )
131
132 def test_returns_ip_address_from_best_interface_on_rack_controller(self):
133@@ -868,7 +884,10 @@ class TestGetIPAddressForRackController(MAASServerTestCase):
134 )
135 subnet = factory.make_Subnet(vlan=vlan)
136 factory.make_StaticIPAddress(
137- alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet, interface=interface
138+ ip=factory.pick_ip_in_Subnet(subnet),
139+ alloc_type=IPADDRESS_TYPE.AUTO,
140+ subnet=subnet,
141+ interface=interface,
142 )
143 bond_ip_address = factory.make_StaticIPAddress(
144 alloc_type=IPADDRESS_TYPE.AUTO,
145@@ -877,7 +896,9 @@ class TestGetIPAddressForRackController(MAASServerTestCase):
146 )
147 self.assertEqual(
148 bond_ip_address,
149- dhcp.get_ip_address_for_rack_controller(rack_controller, vlan),
150+ dhcp.get_ip_address_for_rack_controller(
151+ rack_controller, vlan, subnet.get_ip_version()
152+ ),
153 )
154
155
156@@ -2121,11 +2142,12 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
157 primary_rack=primary_rack,
158 secondary_rack=secondary_rack,
159 )
160- subnet = factory.make_Subnet(vlan=vlan)
161+ subnet = factory.make_Subnet(vlan=vlan, version=4)
162 primary_interface = factory.make_Interface(
163 INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan
164 )
165 primary_ip = factory.make_StaticIPAddress(
166+ ip=factory.pick_ip_in_Subnet(subnet),
167 alloc_type=IPADDRESS_TYPE.AUTO,
168 subnet=subnet,
169 interface=primary_interface,
170@@ -2134,6 +2156,7 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
171 INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan
172 )
173 secondary_ip = factory.make_StaticIPAddress(
174+ ip=factory.pick_ip_in_Subnet(subnet),
175 alloc_type=IPADDRESS_TYPE.AUTO,
176 subnet=subnet,
177 interface=secondary_interface,
178@@ -2150,7 +2173,7 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
179 },
180 secondary_rack,
181 ),
182- dhcp.make_failover_peer_config(vlan, primary_rack),
183+ dhcp.make_failover_peer_config(vlan, primary_rack, 4),
184 )
185
186 def test_renders_config_for_secondary(self):
187@@ -2161,11 +2184,12 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
188 primary_rack=primary_rack,
189 secondary_rack=secondary_rack,
190 )
191- subnet = factory.make_Subnet(vlan=vlan)
192+ subnet = factory.make_Subnet(vlan=vlan, version=4)
193 primary_interface = factory.make_Interface(
194 INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan
195 )
196 primary_ip = factory.make_StaticIPAddress(
197+ ip=factory.pick_ip_in_Subnet(subnet),
198 alloc_type=IPADDRESS_TYPE.AUTO,
199 subnet=subnet,
200 interface=primary_interface,
201@@ -2174,6 +2198,7 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
202 INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan
203 )
204 secondary_ip = factory.make_StaticIPAddress(
205+ ip=factory.pick_ip_in_Subnet(subnet),
206 alloc_type=IPADDRESS_TYPE.AUTO,
207 subnet=subnet,
208 interface=secondary_interface,
209@@ -2190,7 +2215,78 @@ class TestMakeFailoverPeerConfig(MAASServerTestCase):
210 },
211 primary_rack,
212 ),
213- dhcp.make_failover_peer_config(vlan, secondary_rack),
214+ dhcp.make_failover_peer_config(vlan, secondary_rack, 4),
215+ )
216+
217+ # See https://bugs.launchpad.net/maas/+bug/2027621
218+ def test_renders_config_for_secondary_should_not_mix_v4_and_v6_addresses(
219+ self,
220+ ):
221+ primary_rack = factory.make_RackController()
222+ secondary_rack = factory.make_RackController()
223+ vlan = factory.make_VLAN(
224+ dhcp_on=True,
225+ primary_rack=primary_rack,
226+ secondary_rack=secondary_rack,
227+ )
228+ subnet_v4 = factory.make_Subnet(vlan=vlan, version=4)
229+ subnet_v6 = factory.make_Subnet(vlan=vlan, version=6)
230+ primary_interface = factory.make_Interface(
231+ INTERFACE_TYPE.PHYSICAL, node=primary_rack, vlan=vlan
232+ )
233+ primary_ip_v4 = factory.make_StaticIPAddress(
234+ ip=factory.pick_ip_in_Subnet(subnet_v4),
235+ alloc_type=IPADDRESS_TYPE.AUTO,
236+ subnet=subnet_v4,
237+ interface=primary_interface,
238+ )
239+ primary_ip_v6 = factory.make_StaticIPAddress(
240+ ip=factory.pick_ip_in_Subnet(subnet_v6),
241+ alloc_type=IPADDRESS_TYPE.AUTO,
242+ subnet=subnet_v6,
243+ interface=primary_interface,
244+ )
245+ secondary_interface = factory.make_Interface(
246+ INTERFACE_TYPE.PHYSICAL, node=secondary_rack, vlan=vlan
247+ )
248+ secondary_ip_v4 = factory.make_StaticIPAddress(
249+ ip=factory.pick_ip_in_Subnet(subnet_v4),
250+ alloc_type=IPADDRESS_TYPE.AUTO,
251+ subnet=subnet_v4,
252+ interface=secondary_interface,
253+ )
254+ secondary_ip_v6 = factory.make_StaticIPAddress(
255+ ip=factory.pick_ip_in_Subnet(subnet_v6),
256+ alloc_type=IPADDRESS_TYPE.AUTO,
257+ subnet=subnet_v6,
258+ interface=secondary_interface,
259+ )
260+ failover_peer_name = "failover-vlan-%d" % vlan.id
261+ self.assertEqual(
262+ (
263+ failover_peer_name,
264+ {
265+ "name": failover_peer_name,
266+ "mode": "secondary",
267+ "address": str(secondary_ip_v4.ip),
268+ "peer_address": str(primary_ip_v4.ip),
269+ },
270+ primary_rack,
271+ ),
272+ dhcp.make_failover_peer_config(vlan, secondary_rack, 4),
273+ )
274+ self.assertEqual(
275+ (
276+ failover_peer_name,
277+ {
278+ "name": failover_peer_name,
279+ "mode": "secondary",
280+ "address": str(secondary_ip_v6.ip),
281+ "peer_address": str(primary_ip_v6.ip),
282+ },
283+ primary_rack,
284+ ),
285+ dhcp.make_failover_peer_config(vlan, secondary_rack, 6),
286 )
287
288

Subscribers

People subscribed via source and target branches