Merge lp:~mpontillo/maas/allow-physical-interfaces-on-vlans-with-known-tag--bug-1678339 into lp:~maas-committers/maas/trunk
- allow-physical-interfaces-on-vlans-with-known-tag--bug-1678339
- Merge into trunk
Proposed by
Mike Pontillo
Status: | Merged |
---|---|
Approved by: | Mike Pontillo |
Approved revision: | no longer in the source branch. |
Merged at revision: | 6087 |
Proposed branch: | lp:~mpontillo/maas/allow-physical-interfaces-on-vlans-with-known-tag--bug-1678339 |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
764 lines (+103/-161) 4 files modified
src/maasserver/api/tests/test_interfaces.py (+13/-22) src/maasserver/forms/interface.py (+2/-21) src/maasserver/forms/tests/test_interface.py (+65/-94) src/maasserver/websockets/handlers/tests/test_machine.py (+23/-24) |
To merge this branch: | bzr merge lp:~mpontillo/maas/allow-physical-interfaces-on-vlans-with-known-tag--bug-1678339 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andres Rodriguez (community) | Approve | ||
Review via email: mp+325774@code.launchpad.net |
Commit message
Allow physical (and bond) interfaces to be placed on VLANs with a known 802.1q tag.
Description of the change
This was preventing users with moderately complex networks from using the MAAS 2.2 release with DHCP relay, since nodes on the relay VLANs by definition are not "untagged" from the rack controller's point of view.
(The bug also occurs in situations without DHCP relay, as the linked bug description shows.)
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/maasserver/api/tests/test_interfaces.py' |
2 | --- src/maasserver/api/tests/test_interfaces.py 2017-04-20 22:41:52 +0000 |
3 | +++ src/maasserver/api/tests/test_interfaces.py 2017-06-15 21:08:15 +0000 |
4 | @@ -79,14 +79,14 @@ |
5 | def make_complex_interface(node, name=None): |
6 | """Makes interface with parents and children.""" |
7 | fabric = factory.make_Fabric() |
8 | - untagged = fabric.get_default_vlan() |
9 | + vlan_5 = factory.make_VLAN(vid=5, fabric=fabric) |
10 | nic_0 = factory.make_Interface( |
11 | - INTERFACE_TYPE.PHYSICAL, vlan=untagged, node=node) |
12 | + INTERFACE_TYPE.PHYSICAL, vlan=vlan_5, node=node) |
13 | nic_1 = factory.make_Interface( |
14 | - INTERFACE_TYPE.PHYSICAL, vlan=untagged, node=node) |
15 | + INTERFACE_TYPE.PHYSICAL, vlan=vlan_5, node=node) |
16 | parents = [nic_0, nic_1] |
17 | bond_interface = factory.make_Interface( |
18 | - INTERFACE_TYPE.BOND, mac_address=nic_0.mac_address, vlan=untagged, |
19 | + INTERFACE_TYPE.BOND, mac_address=nic_0.mac_address, vlan=vlan_5, |
20 | parents=parents, name=name) |
21 | vlan_10 = factory.make_VLAN(vid=10, fabric=fabric) |
22 | vlan_nic_10 = factory.make_Interface( |
23 | @@ -179,8 +179,7 @@ |
24 | node = factory.make_Node(status=status) |
25 | mac = factory.make_mac_address() |
26 | name = factory.make_name("eth") |
27 | - fabric = factory.make_Fabric() |
28 | - vlan = fabric.get_default_vlan() |
29 | + vlan = factory.make_VLAN() |
30 | tags = [ |
31 | factory.make_name("tag") |
32 | for _ in range(3) |
33 | @@ -213,8 +212,7 @@ |
34 | owner=self.user, parent=parent) |
35 | mac = factory.make_mac_address() |
36 | name = factory.make_name("eth") |
37 | - fabric = factory.make_Fabric() |
38 | - vlan = fabric.get_default_vlan() |
39 | + vlan = factory.make_VLAN() |
40 | tags = [ |
41 | factory.make_name("tag") |
42 | for _ in range(3) |
43 | @@ -247,8 +245,7 @@ |
44 | node = factory.make_Node(status=status) |
45 | mac = factory.make_mac_address() |
46 | name = factory.make_name("eth") |
47 | - fabric = factory.make_Fabric() |
48 | - vlan = fabric.get_default_vlan() |
49 | + vlan = factory.make_VLAN() |
50 | tags = [ |
51 | factory.make_name("tag") |
52 | for _ in range(3) |
53 | @@ -327,8 +324,7 @@ |
54 | interface_on_other_node = factory.make_Interface( |
55 | INTERFACE_TYPE.PHYSICAL) |
56 | name = factory.make_name("eth") |
57 | - fabric = factory.make_Fabric() |
58 | - vlan = fabric.get_default_vlan() |
59 | + vlan = factory.make_VLAN() |
60 | uri = get_interfaces_uri(node) |
61 | response = self.client.post(uri, { |
62 | "op": "create_physical", |
63 | @@ -348,8 +344,7 @@ |
64 | self.become_admin() |
65 | for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
66 | node = factory.make_Node(status=status) |
67 | - fabric = factory.make_Fabric() |
68 | - vlan = fabric.get_default_vlan() |
69 | + vlan = factory.make_VLAN() |
70 | parent_1_iface = factory.make_Interface( |
71 | INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=node) |
72 | parent_2_iface = factory.make_Interface( |
73 | @@ -438,7 +433,7 @@ |
74 | self.assertEqual( |
75 | http.client.CONFLICT, response.status_code, response.content) |
76 | |
77 | - def test_create_bond_requires_name_and_parents(self): |
78 | + def test_create_bond_requires_name_vlan_and_parents(self): |
79 | self.become_admin() |
80 | node = factory.make_Node(status=NODE_STATUS.READY) |
81 | uri = get_interfaces_uri(node) |
82 | @@ -941,8 +936,7 @@ |
83 | interface = factory.make_Interface( |
84 | INTERFACE_TYPE.PHYSICAL, node=node) |
85 | new_name = factory.make_name("name") |
86 | - new_fabric = factory.make_Fabric() |
87 | - new_vlan = new_fabric.get_default_vlan() |
88 | + new_vlan = factory.make_VLAN() |
89 | uri = get_interface_uri(interface) |
90 | response = self.client.put(uri, { |
91 | "name": new_name, |
92 | @@ -961,8 +955,7 @@ |
93 | interface = factory.make_Interface( |
94 | INTERFACE_TYPE.PHYSICAL, node=device) |
95 | new_name = factory.make_name("name") |
96 | - new_fabric = factory.make_Fabric() |
97 | - new_vlan = new_fabric.get_default_vlan() |
98 | + new_vlan = factory.make_VLAN() |
99 | uri = get_interface_uri(interface) |
100 | response = self.client.put(uri, { |
101 | "name": new_name, |
102 | @@ -996,12 +989,10 @@ |
103 | bond, [nic_0, nic_1], [vlan_10, vlan_11] = make_complex_interface( |
104 | node) |
105 | physical_interface = factory.make_Interface( |
106 | - INTERFACE_TYPE.PHYSICAL, node=node) |
107 | - new_vlan = factory.make_VLAN(fabric=physical_interface.vlan.fabric) |
108 | + INTERFACE_TYPE.PHYSICAL, node=node, vlan=nic_0.vlan) |
109 | uri = get_interface_uri(vlan_10) |
110 | response = self.client.put(uri, { |
111 | "parent": physical_interface.id, |
112 | - "vlan": new_vlan.id, |
113 | }) |
114 | self.assertEqual( |
115 | http.client.OK, response.status_code, response.content) |
116 | |
117 | === modified file 'src/maasserver/forms/interface.py' |
118 | --- src/maasserver/forms/interface.py 2017-04-05 22:50:03 +0000 |
119 | +++ src/maasserver/forms/interface.py 2017-06-15 21:08:15 +0000 |
120 | @@ -252,18 +252,6 @@ |
121 | if len(parents) > 0: |
122 | raise ValidationError("A physical interface cannot have parents.") |
123 | |
124 | - def clean_vlan(self): |
125 | - new_vlan = self.cleaned_data.get('vlan') |
126 | - if new_vlan and new_vlan.fabric.get_default_vlan() != new_vlan: |
127 | - # A device's physical interface can be connected to a tagged VLAN. |
128 | - # This is because a container or VM could be bridged on the machine |
129 | - # to a tagged VLAN interface. See lp:1572070 for details. |
130 | - if self.node.node_type != NODE_TYPE.DEVICE: |
131 | - raise ValidationError( |
132 | - "A physical interface can only belong to an " |
133 | - "untagged VLAN.") |
134 | - return new_vlan |
135 | - |
136 | def clean(self): |
137 | cleaned_data = super(PhysicalInterfaceForm, self).clean() |
138 | new_name = cleaned_data.get('name') |
139 | @@ -313,7 +301,7 @@ |
140 | not created and new_vlan is None and vlan_was_set): |
141 | raise ValidationError( |
142 | "A VLAN interface must be connected to a tagged VLAN.") |
143 | - if new_vlan and new_vlan.fabric.get_default_vlan() == new_vlan: |
144 | + if new_vlan and new_vlan.vid == 0: |
145 | raise ValidationError( |
146 | "A VLAN interface can only belong to a tagged VLAN.") |
147 | return new_vlan |
148 | @@ -455,16 +443,9 @@ |
149 | 'name', |
150 | ) |
151 | |
152 | - def clean_vlan(self): |
153 | - new_vlan = self.cleaned_data.get('vlan') |
154 | - if new_vlan and new_vlan.fabric.get_default_vlan() != new_vlan: |
155 | - raise ValidationError( |
156 | - "A bond interface can only belong to an untagged VLAN.") |
157 | - return new_vlan |
158 | - |
159 | def clean(self): |
160 | cleaned_data = super().clean() |
161 | - if self.fields_ok(['vlan', 'parents']): |
162 | + if self.fields_ok(['parents']): |
163 | parents = self.cleaned_data.get('parents') |
164 | # Set the mac_address if its missing and the interface is being |
165 | # created. |
166 | |
167 | === modified file 'src/maasserver/forms/tests/test_interface.py' |
168 | --- src/maasserver/forms/tests/test_interface.py 2017-04-05 23:39:23 +0000 |
169 | +++ src/maasserver/forms/tests/test_interface.py 2017-06-15 21:08:15 +0000 |
170 | @@ -30,7 +30,6 @@ |
171 | from maasserver.testing.factory import factory |
172 | from maasserver.testing.testcase import MAASServerTestCase |
173 | from maasserver.utils.forms import compose_invalid_choice_text |
174 | -from maasserver.utils.orm import reload_object |
175 | from testtools import ExpectedException |
176 | from testtools.matchers import MatchesStructure |
177 | |
178 | @@ -133,8 +132,7 @@ |
179 | node = factory.make_Node() |
180 | mac_address = factory.make_mac_address() |
181 | interface_name = 'eth0' |
182 | - fabric = factory.make_Fabric() |
183 | - vlan = fabric.get_default_vlan() |
184 | + vlan = factory.make_VLAN() |
185 | tags = [ |
186 | factory.make_name("tag") |
187 | for _ in range(3) |
188 | @@ -211,8 +209,7 @@ |
189 | node = factory.make_Node() |
190 | mac_address = factory.make_mac_address() |
191 | interface_name = 'eth0' |
192 | - fabric = factory.make_Fabric() |
193 | - vlan = fabric.get_default_vlan() |
194 | + vlan = factory.make_VLAN() |
195 | tags = [ |
196 | factory.make_name("tag") |
197 | for _ in range(3) |
198 | @@ -232,8 +229,7 @@ |
199 | |
200 | def test__requires_mac_address(self): |
201 | interface_name = 'eth0' |
202 | - fabric = factory.make_Fabric() |
203 | - vlan = fabric.get_default_vlan() |
204 | + vlan = factory.make_VLAN() |
205 | form = PhysicalInterfaceForm( |
206 | node=factory.make_Node(), |
207 | data={ |
208 | @@ -248,9 +244,7 @@ |
209 | form.errors['mac_address'][0]) |
210 | |
211 | def test_rejects_interface_with_duplicate_name(self): |
212 | - fabric = factory.make_Fabric() |
213 | - vlan = fabric.get_default_vlan() |
214 | - interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
215 | + interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
216 | mac_address = factory.make_mac_address() |
217 | form = PhysicalInterfaceForm( |
218 | node=interface.node, |
219 | @@ -266,26 +260,6 @@ |
220 | "already has an interface named '%s'." % interface.name, |
221 | form.errors['name'][0]) |
222 | |
223 | - def test_rejects_interface_on_tagged_vlan(self): |
224 | - fabric = factory.make_Fabric() |
225 | - interface = factory.make_Interface( |
226 | - INTERFACE_TYPE.PHYSICAL, vlan=fabric.get_default_vlan()) |
227 | - vlan = factory.make_VLAN(fabric=fabric) |
228 | - mac_address = factory.make_mac_address() |
229 | - form = PhysicalInterfaceForm( |
230 | - node=interface.node, |
231 | - data={ |
232 | - 'name': factory.make_name("eth"), |
233 | - 'mac_address': mac_address, |
234 | - 'vlan': vlan.id, |
235 | - }) |
236 | - self.assertFalse(form.is_valid(), dict(form.errors)) |
237 | - self.assertItemsEqual( |
238 | - ['vlan'], form.errors.keys(), form.errors) |
239 | - self.assertIn( |
240 | - "A physical interface can only belong to an untagged VLAN.", |
241 | - form.errors['vlan'][0]) |
242 | - |
243 | def test_allows_interface_on_tagged_vlan_for_device(self): |
244 | device = factory.make_Device() |
245 | fabric = factory.make_Fabric() |
246 | @@ -307,8 +281,7 @@ |
247 | |
248 | def test__rejects_parents(self): |
249 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
250 | - fabric = factory.make_Fabric() |
251 | - vlan = fabric.get_default_vlan() |
252 | + vlan = factory.make_VLAN() |
253 | form = PhysicalInterfaceForm( |
254 | node=parent.node, |
255 | data={ |
256 | @@ -328,8 +301,7 @@ |
257 | interface = factory.make_Interface( |
258 | INTERFACE_TYPE.PHYSICAL, name='eth0') |
259 | new_name = 'eth1' |
260 | - new_fabric = factory.make_Fabric() |
261 | - new_vlan = new_fabric.get_default_vlan() |
262 | + new_vlan = factory.make_VLAN(vid=33) |
263 | form = PhysicalInterfaceForm( |
264 | instance=interface, |
265 | data={ |
266 | @@ -390,8 +362,7 @@ |
267 | node = factory.make_Node() |
268 | mac_address = factory.make_mac_address() |
269 | interface_name = 'eth0' |
270 | - fabric = factory.make_Fabric() |
271 | - vlan = fabric.get_default_vlan() |
272 | + vlan = factory.make_VLAN() |
273 | tags = [ |
274 | factory.make_name("tag") |
275 | for _ in range(3) |
276 | @@ -430,8 +401,7 @@ |
277 | "autoconf": autoconf, |
278 | } |
279 | new_name = 'eth1' |
280 | - new_fabric = factory.make_Fabric() |
281 | - new_vlan = new_fabric.get_default_vlan() |
282 | + new_vlan = factory.make_VLAN(vid=33) |
283 | form = PhysicalInterfaceForm( |
284 | instance=interface, |
285 | data={ |
286 | @@ -503,8 +473,8 @@ |
287 | class VLANInterfaceFormTest(MAASServerTestCase): |
288 | |
289 | def test__creates_vlan_interface(self): |
290 | - parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
291 | - vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) |
292 | + vlan = factory.make_VLAN(vid=10) |
293 | + parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
294 | form = VLANInterfaceForm( |
295 | node=parent.node, |
296 | data={ |
297 | @@ -521,8 +491,8 @@ |
298 | self.assertItemsEqual([parent], interface.parents.all()) |
299 | |
300 | def test__create_ensures_link_up(self): |
301 | - parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
302 | - vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) |
303 | + vlan = factory.make_VLAN(vid=10) |
304 | + parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
305 | form = VLANInterfaceForm( |
306 | node=parent.node, |
307 | data={ |
308 | @@ -549,10 +519,13 @@ |
309 | form.errors['vlan'][0]) |
310 | |
311 | def test_rejects_interface_with_duplicate_name(self): |
312 | - parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
313 | - vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) |
314 | + vlan = factory.make_VLAN(vid=10) |
315 | + parent = factory.make_Interface( |
316 | + INTERFACE_TYPE.PHYSICAL, |
317 | + vlan=vlan) |
318 | interface = factory.make_Interface( |
319 | - INTERFACE_TYPE.VLAN, vlan=vlan, parents=[parent]) |
320 | + INTERFACE_TYPE.VLAN, |
321 | + vlan=vlan, parents=[parent]) |
322 | form = VLANInterfaceForm( |
323 | node=parent.node, |
324 | data={ |
325 | @@ -597,14 +570,13 @@ |
326 | |
327 | def test__rejects_vlan_parent(self): |
328 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
329 | - vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) |
330 | vlan_parent = factory.make_Interface( |
331 | - INTERFACE_TYPE.VLAN, vlan=vlan, parents=[parent]) |
332 | - other_vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=11) |
333 | + INTERFACE_TYPE.VLAN, parents=[parent]) |
334 | + vlan = factory.make_VLAN(vid=10) |
335 | form = VLANInterfaceForm( |
336 | node=parent.node, |
337 | data={ |
338 | - 'vlan': other_vlan.id, |
339 | + 'vlan': vlan.id, |
340 | 'parents': [vlan_parent.id], |
341 | }) |
342 | self.assertFalse(form.is_valid(), dict(form.errors)) |
343 | @@ -646,8 +618,8 @@ |
344 | |
345 | def test__rejects_parent_on_bond(self): |
346 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
347 | - bond = factory.make_Interface(INTERFACE_TYPE.BOND, parents=[parent]) |
348 | - vlan = factory.make_VLAN(fabric=bond.vlan.fabric, vid=10) |
349 | + factory.make_Interface(INTERFACE_TYPE.BOND, parents=[parent]) |
350 | + vlan = factory.make_VLAN(vid=10) |
351 | form = VLANInterfaceForm( |
352 | node=parent.node, |
353 | data={ |
354 | @@ -682,7 +654,7 @@ |
355 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
356 | interface = factory.make_Interface( |
357 | INTERFACE_TYPE.VLAN, parents=[parent]) |
358 | - new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric, vid=33) |
359 | + new_vlan = factory.make_VLAN(vid=33) |
360 | form = VLANInterfaceForm( |
361 | instance=interface, |
362 | data={ |
363 | @@ -701,15 +673,17 @@ |
364 | class BondInterfaceFormTest(MAASServerTestCase): |
365 | |
366 | def test__error_with_invalid_bond_mode(self): |
367 | - parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
368 | + vlan = factory.make_VLAN(vid=10) |
369 | + parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
370 | parent2 = factory.make_Interface( |
371 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
372 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
373 | interface_name = factory.make_name() |
374 | bond_mode = factory.make_name("bond_mode") |
375 | form = BondInterfaceForm( |
376 | node=parent1.node, |
377 | data={ |
378 | 'name': interface_name, |
379 | + 'vlan': vlan.id, |
380 | 'parents': [parent1.id, parent2.id], |
381 | 'bond_mode': bond_mode, |
382 | }) |
383 | @@ -721,14 +695,16 @@ |
384 | }, form.errors) |
385 | |
386 | def test__creates_bond_interface(self): |
387 | - parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
388 | + vlan = factory.make_VLAN(vid=10) |
389 | + parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
390 | parent2 = factory.make_Interface( |
391 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
392 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
393 | interface_name = factory.make_name() |
394 | form = BondInterfaceForm( |
395 | node=parent1.node, |
396 | data={ |
397 | 'name': interface_name, |
398 | + 'vlan': vlan.id, |
399 | 'parents': [parent1.id, parent2.id], |
400 | }) |
401 | self.assertTrue(form.is_valid(), dict(form.errors)) |
402 | @@ -743,16 +719,18 @@ |
403 | self.assertItemsEqual([parent1, parent2], interface.parents.all()) |
404 | |
405 | def test__create_removes_parent_links_and_sets_link_up_on_bond(self): |
406 | - parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
407 | + vlan = factory.make_VLAN(vid=10) |
408 | + parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
409 | parent1.ensure_link_up() |
410 | parent2 = factory.make_Interface( |
411 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
412 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
413 | parent2.ensure_link_up() |
414 | interface_name = factory.make_name() |
415 | form = BondInterfaceForm( |
416 | node=parent1.node, |
417 | data={ |
418 | 'name': interface_name, |
419 | + 'vlan': vlan.id, |
420 | 'parents': [parent1.id, parent2.id], |
421 | }) |
422 | self.assertTrue(form.is_valid(), dict(form.errors)) |
423 | @@ -769,14 +747,16 @@ |
424 | interface.ip_addresses.filter(alloc_type=IPADDRESS_TYPE.STICKY)) |
425 | |
426 | def test__creates_bond_interface_with_parent_mac_address(self): |
427 | - parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
428 | + vlan = factory.make_VLAN(vid=10) |
429 | + parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
430 | parent2 = factory.make_Interface( |
431 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
432 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
433 | interface_name = factory.make_name() |
434 | form = BondInterfaceForm( |
435 | node=parent1.node, |
436 | data={ |
437 | 'name': interface_name, |
438 | + 'vlan': vlan.id, |
439 | 'parents': [parent1.id, parent2.id], |
440 | 'mac_address': parent1.mac_address, |
441 | }) |
442 | @@ -790,14 +770,16 @@ |
443 | self.assertItemsEqual([parent1, parent2], interface.parents.all()) |
444 | |
445 | def test__creates_bond_interface_with_default_bond_params(self): |
446 | - parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
447 | + vlan = factory.make_VLAN(vid=10) |
448 | + parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
449 | parent2 = factory.make_Interface( |
450 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
451 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
452 | interface_name = factory.make_name() |
453 | form = BondInterfaceForm( |
454 | node=parent1.node, |
455 | data={ |
456 | 'name': interface_name, |
457 | + 'vlan': vlan.id, |
458 | 'parents': [parent1.id, parent2.id], |
459 | }) |
460 | self.assertTrue(form.is_valid(), dict(form.errors)) |
461 | @@ -812,9 +794,10 @@ |
462 | }, interface.params) |
463 | |
464 | def test__creates_bond_interface_with_bond_params(self): |
465 | - parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
466 | + vlan = factory.make_VLAN(vid=10) |
467 | + parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
468 | parent2 = factory.make_Interface( |
469 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
470 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
471 | interface_name = factory.make_name() |
472 | bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
473 | bond_miimon = random.randint(0, 1000) |
474 | @@ -827,6 +810,7 @@ |
475 | node=parent1.node, |
476 | data={ |
477 | 'name': interface_name, |
478 | + 'vlan': vlan.id, |
479 | 'parents': [parent1.id, parent2.id], |
480 | 'bond_mode': bond_mode, |
481 | 'bond_miimon': bond_miimon, |
482 | @@ -847,11 +831,13 @@ |
483 | }, interface.params) |
484 | |
485 | def test__rejects_no_parents(self): |
486 | + vlan = factory.make_VLAN(vid=10) |
487 | interface_name = factory.make_name() |
488 | form = BondInterfaceForm( |
489 | node=factory.make_Node(), |
490 | data={ |
491 | 'name': interface_name, |
492 | + 'vlan': vlan.id, |
493 | }) |
494 | self.assertFalse(form.is_valid(), dict(form.errors)) |
495 | self.assertItemsEqual(['parents', 'mac_address'], form.errors.keys()) |
496 | @@ -859,37 +845,21 @@ |
497 | "A bond interface must have one or more parents.", |
498 | form.errors['parents'][0]) |
499 | |
500 | - def test__rejects_when_vlan_not_untagged(self): |
501 | - interface_name = factory.make_name() |
502 | - parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
503 | - vlan = factory.make_VLAN(fabric=parent.vlan.fabric) |
504 | - form = BondInterfaceForm( |
505 | - node=parent.node, |
506 | - data={ |
507 | - 'name': interface_name, |
508 | - 'parents': [parent.id], |
509 | - 'mac_address': parent.mac_address, |
510 | - 'vlan': vlan.id, |
511 | - }) |
512 | - self.assertFalse(form.is_valid(), dict(form.errors)) |
513 | - self.assertItemsEqual(['vlan'], form.errors.keys()) |
514 | - self.assertIn( |
515 | - "A bond interface can only belong to an untagged VLAN.", |
516 | - form.errors['vlan'][0]) |
517 | - |
518 | def test__rejects_when_parents_already_have_children(self): |
519 | node = factory.make_Node() |
520 | parent1 = factory.make_Interface( |
521 | INTERFACE_TYPE.PHYSICAL, node=node, name="eth0") |
522 | factory.make_Interface(INTERFACE_TYPE.VLAN, parents=[parent1]) |
523 | parent2 = factory.make_Interface( |
524 | - INTERFACE_TYPE.PHYSICAL, node=node, name="eth1", vlan=parent1.vlan) |
525 | + INTERFACE_TYPE.PHYSICAL, node=node, name="eth1") |
526 | factory.make_Interface(INTERFACE_TYPE.VLAN, parents=[parent2]) |
527 | + vlan = factory.make_VLAN(vid=10) |
528 | interface_name = factory.make_name() |
529 | form = BondInterfaceForm( |
530 | node=node, |
531 | data={ |
532 | 'name': interface_name, |
533 | + 'vlan': vlan.id, |
534 | 'parents': [parent1.id, parent2.id] |
535 | }) |
536 | self.assertFalse(form.is_valid(), dict(form.errors)) |
537 | @@ -918,15 +888,14 @@ |
538 | def test__edits_interface(self): |
539 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
540 | parent2 = factory.make_Interface( |
541 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
542 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
543 | interface = factory.make_Interface( |
544 | INTERFACE_TYPE.BOND, |
545 | parents=[parent1, parent2]) |
546 | - new_fabric = factory.make_Fabric() |
547 | - new_vlan = new_fabric.get_default_vlan() |
548 | + new_vlan = factory.make_VLAN(vid=33) |
549 | new_name = factory.make_name() |
550 | new_parent = factory.make_Interface( |
551 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
552 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
553 | form = BondInterfaceForm( |
554 | instance=interface, |
555 | data={ |
556 | @@ -943,10 +912,6 @@ |
557 | vlan=new_vlan, type=INTERFACE_TYPE.BOND)) |
558 | self.assertItemsEqual( |
559 | [parent1, parent2, new_parent], interface.parents.all()) |
560 | - self.assertItemsEqual([new_vlan], set( |
561 | - reload_object(parent).vlan |
562 | - for parent in [parent1, parent2, new_parent] |
563 | - )) |
564 | |
565 | def test__edits_interface_allows_disconnected(self): |
566 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
567 | @@ -1023,7 +988,7 @@ |
568 | def test__edit_doesnt_overwrite_params(self): |
569 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
570 | parent2 = factory.make_Interface( |
571 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
572 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
573 | interface = factory.make_Interface( |
574 | INTERFACE_TYPE.BOND, |
575 | parents=[parent1, parent2]) |
576 | @@ -1043,10 +1008,12 @@ |
577 | "bond_xmit_hash_policy": bond_xmit_hash_policy, |
578 | } |
579 | interface.save() |
580 | + new_vlan = factory.make_VLAN(vid=33) |
581 | new_name = factory.make_name() |
582 | form = BondInterfaceForm( |
583 | instance=interface, |
584 | data={ |
585 | + 'vlan': new_vlan.id, |
586 | 'name': new_name, |
587 | }) |
588 | self.assertTrue(form.is_valid(), dict(form.errors)) |
589 | @@ -1063,7 +1030,7 @@ |
590 | def test__edit_does_overwrite_params(self): |
591 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
592 | parent2 = factory.make_Interface( |
593 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
594 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
595 | interface = factory.make_Interface( |
596 | INTERFACE_TYPE.BOND, |
597 | parents=[parent1, parent2]) |
598 | @@ -1083,6 +1050,7 @@ |
599 | "bond_xmit_hash_policy": bond_xmit_hash_policy, |
600 | } |
601 | interface.save() |
602 | + new_vlan = factory.make_VLAN(vid=33) |
603 | new_name = factory.make_name() |
604 | new_bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
605 | new_bond_miimon = random.randint(0, 1000) |
606 | @@ -1094,6 +1062,7 @@ |
607 | form = BondInterfaceForm( |
608 | instance=interface, |
609 | data={ |
610 | + 'vlan': new_vlan.id, |
611 | 'name': new_name, |
612 | 'bond_mode': new_bond_mode, |
613 | 'bond_miimon': new_bond_miimon, |
614 | @@ -1116,7 +1085,7 @@ |
615 | def test__edit_allows_zero_params(self): |
616 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
617 | parent2 = factory.make_Interface( |
618 | - INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) |
619 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
620 | interface = factory.make_Interface( |
621 | INTERFACE_TYPE.BOND, |
622 | parents=[parent1, parent2]) |
623 | @@ -1136,6 +1105,7 @@ |
624 | "bond_xmit_hash_policy": bond_xmit_hash_policy, |
625 | } |
626 | interface.save() |
627 | + new_vlan = factory.make_VLAN(vid=33) |
628 | new_name = factory.make_name() |
629 | new_bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
630 | new_bond_miimon = 0 |
631 | @@ -1147,6 +1117,7 @@ |
632 | form = BondInterfaceForm( |
633 | instance=interface, |
634 | data={ |
635 | + 'vlan': new_vlan.id, |
636 | 'name': new_name, |
637 | 'bond_mode': new_bond_mode, |
638 | 'bond_miimon': new_bond_miimon, |
639 | |
640 | === modified file 'src/maasserver/websockets/handlers/tests/test_machine.py' |
641 | --- src/maasserver/websockets/handlers/tests/test_machine.py 2017-04-20 08:58:42 +0000 |
642 | +++ src/maasserver/websockets/handlers/tests/test_machine.py 2017-06-15 21:08:15 +0000 |
643 | @@ -2079,8 +2079,7 @@ |
644 | handler = MachineHandler(user, {}) |
645 | name = factory.make_name("eth") |
646 | mac_address = factory.make_mac_address() |
647 | - fabric = factory.make_Fabric() |
648 | - vlan = fabric.get_default_vlan() |
649 | + vlan = factory.make_VLAN() |
650 | handler.create_physical({ |
651 | "system_id": node.system_id, |
652 | "name": name, |
653 | @@ -2097,8 +2096,7 @@ |
654 | handler = MachineHandler(user, {}) |
655 | name = factory.make_name("eth") |
656 | mac_address = factory.make_mac_address() |
657 | - fabric = factory.make_Fabric() |
658 | - vlan = fabric.get_default_vlan() |
659 | + vlan = factory.make_VLAN() |
660 | subnet = factory.make_Subnet(vlan=vlan) |
661 | handler.create_physical({ |
662 | "system_id": node.system_id, |
663 | @@ -2120,8 +2118,7 @@ |
664 | handler = MachineHandler(user, {}) |
665 | name = factory.make_name("eth") |
666 | mac_address = factory.make_mac_address() |
667 | - fabric = factory.make_Fabric() |
668 | - vlan = fabric.get_default_vlan() |
669 | + vlan = factory.make_VLAN() |
670 | handler.create_physical({ |
671 | "system_id": node.system_id, |
672 | "name": name, |
673 | @@ -2141,8 +2138,7 @@ |
674 | handler = MachineHandler(user, {}) |
675 | name = factory.make_name("eth") |
676 | mac_address = factory.make_mac_address() |
677 | - fabric = factory.make_Fabric() |
678 | - vlan = fabric.get_default_vlan() |
679 | + vlan = factory.make_VLAN() |
680 | subnet = factory.make_Subnet(vlan=vlan) |
681 | handler.create_physical({ |
682 | "system_id": node.system_id, |
683 | @@ -2162,12 +2158,13 @@ |
684 | user = factory.make_admin() |
685 | node = factory.make_Node() |
686 | handler = MachineHandler(user, {}) |
687 | - interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
688 | - new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) |
689 | + vlan = factory.make_VLAN() |
690 | + interface = factory.make_Interface( |
691 | + INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) |
692 | handler.create_vlan({ |
693 | "system_id": node.system_id, |
694 | "parent": interface.id, |
695 | - "vlan": new_vlan.id, |
696 | + "vlan": vlan.id, |
697 | }) |
698 | vlan_interface = get_one( |
699 | Interface.objects.filter( |
700 | @@ -2178,13 +2175,14 @@ |
701 | user = factory.make_admin() |
702 | node = factory.make_Node() |
703 | handler = MachineHandler(user, {}) |
704 | - interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
705 | - new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) |
706 | - new_subnet = factory.make_Subnet(vlan=new_vlan) |
707 | + vlan = factory.make_VLAN() |
708 | + interface = factory.make_Interface( |
709 | + INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) |
710 | + new_subnet = factory.make_Subnet(vlan=vlan) |
711 | handler.create_vlan({ |
712 | "system_id": node.system_id, |
713 | "parent": interface.id, |
714 | - "vlan": new_vlan.id, |
715 | + "vlan": vlan.id, |
716 | "mode": INTERFACE_LINK_TYPE.AUTO, |
717 | "subnet": new_subnet.id, |
718 | }) |
719 | @@ -2200,12 +2198,13 @@ |
720 | user = factory.make_admin() |
721 | node = factory.make_Node() |
722 | handler = MachineHandler(user, {}) |
723 | - interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
724 | - new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) |
725 | + vlan = factory.make_VLAN() |
726 | + interface = factory.make_Interface( |
727 | + INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) |
728 | handler.create_vlan({ |
729 | "system_id": node.system_id, |
730 | "parent": interface.id, |
731 | - "vlan": new_vlan.id, |
732 | + "vlan": vlan.id, |
733 | "mode": INTERFACE_LINK_TYPE.LINK_UP, |
734 | }) |
735 | vlan_interface = get_one( |
736 | @@ -2220,13 +2219,14 @@ |
737 | user = factory.make_admin() |
738 | node = factory.make_Node() |
739 | handler = MachineHandler(user, {}) |
740 | - interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
741 | - new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) |
742 | - new_subnet = factory.make_Subnet(vlan=new_vlan) |
743 | + vlan = factory.make_VLAN() |
744 | + interface = factory.make_Interface( |
745 | + INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) |
746 | + new_subnet = factory.make_Subnet(vlan=vlan) |
747 | handler.create_vlan({ |
748 | "system_id": node.system_id, |
749 | "parent": interface.id, |
750 | - "vlan": new_vlan.id, |
751 | + "vlan": vlan.id, |
752 | "mode": INTERFACE_LINK_TYPE.LINK_UP, |
753 | "subnet": new_subnet.id, |
754 | }) |
755 | @@ -2317,8 +2317,7 @@ |
756 | handler = MachineHandler(user, {}) |
757 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
758 | new_name = factory.make_name("name") |
759 | - new_fabric = factory.make_Fabric() |
760 | - new_vlan = new_fabric.get_default_vlan() |
761 | + new_vlan = factory.make_VLAN() |
762 | handler.update_interface({ |
763 | "system_id": node.system_id, |
764 | "interface_id": interface.id, |
lgtm!