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 | 79 | def make_complex_interface(node, name=None): | 79 | def make_complex_interface(node, name=None): |
6 | 80 | """Makes interface with parents and children.""" | 80 | """Makes interface with parents and children.""" |
7 | 81 | fabric = factory.make_Fabric() | 81 | fabric = factory.make_Fabric() |
9 | 82 | untagged = fabric.get_default_vlan() | 82 | vlan_5 = factory.make_VLAN(vid=5, fabric=fabric) |
10 | 83 | nic_0 = factory.make_Interface( | 83 | nic_0 = factory.make_Interface( |
12 | 84 | INTERFACE_TYPE.PHYSICAL, vlan=untagged, node=node) | 84 | INTERFACE_TYPE.PHYSICAL, vlan=vlan_5, node=node) |
13 | 85 | nic_1 = factory.make_Interface( | 85 | nic_1 = factory.make_Interface( |
15 | 86 | INTERFACE_TYPE.PHYSICAL, vlan=untagged, node=node) | 86 | INTERFACE_TYPE.PHYSICAL, vlan=vlan_5, node=node) |
16 | 87 | parents = [nic_0, nic_1] | 87 | parents = [nic_0, nic_1] |
17 | 88 | bond_interface = factory.make_Interface( | 88 | bond_interface = factory.make_Interface( |
19 | 89 | INTERFACE_TYPE.BOND, mac_address=nic_0.mac_address, vlan=untagged, | 89 | INTERFACE_TYPE.BOND, mac_address=nic_0.mac_address, vlan=vlan_5, |
20 | 90 | parents=parents, name=name) | 90 | parents=parents, name=name) |
21 | 91 | vlan_10 = factory.make_VLAN(vid=10, fabric=fabric) | 91 | vlan_10 = factory.make_VLAN(vid=10, fabric=fabric) |
22 | 92 | vlan_nic_10 = factory.make_Interface( | 92 | vlan_nic_10 = factory.make_Interface( |
23 | @@ -179,8 +179,7 @@ | |||
24 | 179 | node = factory.make_Node(status=status) | 179 | node = factory.make_Node(status=status) |
25 | 180 | mac = factory.make_mac_address() | 180 | mac = factory.make_mac_address() |
26 | 181 | name = factory.make_name("eth") | 181 | name = factory.make_name("eth") |
29 | 182 | fabric = factory.make_Fabric() | 182 | vlan = factory.make_VLAN() |
28 | 183 | vlan = fabric.get_default_vlan() | ||
30 | 184 | tags = [ | 183 | tags = [ |
31 | 185 | factory.make_name("tag") | 184 | factory.make_name("tag") |
32 | 186 | for _ in range(3) | 185 | for _ in range(3) |
33 | @@ -213,8 +212,7 @@ | |||
34 | 213 | owner=self.user, parent=parent) | 212 | owner=self.user, parent=parent) |
35 | 214 | mac = factory.make_mac_address() | 213 | mac = factory.make_mac_address() |
36 | 215 | name = factory.make_name("eth") | 214 | name = factory.make_name("eth") |
39 | 216 | fabric = factory.make_Fabric() | 215 | vlan = factory.make_VLAN() |
38 | 217 | vlan = fabric.get_default_vlan() | ||
40 | 218 | tags = [ | 216 | tags = [ |
41 | 219 | factory.make_name("tag") | 217 | factory.make_name("tag") |
42 | 220 | for _ in range(3) | 218 | for _ in range(3) |
43 | @@ -247,8 +245,7 @@ | |||
44 | 247 | node = factory.make_Node(status=status) | 245 | node = factory.make_Node(status=status) |
45 | 248 | mac = factory.make_mac_address() | 246 | mac = factory.make_mac_address() |
46 | 249 | name = factory.make_name("eth") | 247 | name = factory.make_name("eth") |
49 | 250 | fabric = factory.make_Fabric() | 248 | vlan = factory.make_VLAN() |
48 | 251 | vlan = fabric.get_default_vlan() | ||
50 | 252 | tags = [ | 249 | tags = [ |
51 | 253 | factory.make_name("tag") | 250 | factory.make_name("tag") |
52 | 254 | for _ in range(3) | 251 | for _ in range(3) |
53 | @@ -327,8 +324,7 @@ | |||
54 | 327 | interface_on_other_node = factory.make_Interface( | 324 | interface_on_other_node = factory.make_Interface( |
55 | 328 | INTERFACE_TYPE.PHYSICAL) | 325 | INTERFACE_TYPE.PHYSICAL) |
56 | 329 | name = factory.make_name("eth") | 326 | name = factory.make_name("eth") |
59 | 330 | fabric = factory.make_Fabric() | 327 | vlan = factory.make_VLAN() |
58 | 331 | vlan = fabric.get_default_vlan() | ||
60 | 332 | uri = get_interfaces_uri(node) | 328 | uri = get_interfaces_uri(node) |
61 | 333 | response = self.client.post(uri, { | 329 | response = self.client.post(uri, { |
62 | 334 | "op": "create_physical", | 330 | "op": "create_physical", |
63 | @@ -348,8 +344,7 @@ | |||
64 | 348 | self.become_admin() | 344 | self.become_admin() |
65 | 349 | for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): | 345 | for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN): |
66 | 350 | node = factory.make_Node(status=status) | 346 | node = factory.make_Node(status=status) |
69 | 351 | fabric = factory.make_Fabric() | 347 | vlan = factory.make_VLAN() |
68 | 352 | vlan = fabric.get_default_vlan() | ||
70 | 353 | parent_1_iface = factory.make_Interface( | 348 | parent_1_iface = factory.make_Interface( |
71 | 354 | INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=node) | 349 | INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=node) |
72 | 355 | parent_2_iface = factory.make_Interface( | 350 | parent_2_iface = factory.make_Interface( |
73 | @@ -438,7 +433,7 @@ | |||
74 | 438 | self.assertEqual( | 433 | self.assertEqual( |
75 | 439 | http.client.CONFLICT, response.status_code, response.content) | 434 | http.client.CONFLICT, response.status_code, response.content) |
76 | 440 | 435 | ||
78 | 441 | def test_create_bond_requires_name_and_parents(self): | 436 | def test_create_bond_requires_name_vlan_and_parents(self): |
79 | 442 | self.become_admin() | 437 | self.become_admin() |
80 | 443 | node = factory.make_Node(status=NODE_STATUS.READY) | 438 | node = factory.make_Node(status=NODE_STATUS.READY) |
81 | 444 | uri = get_interfaces_uri(node) | 439 | uri = get_interfaces_uri(node) |
82 | @@ -941,8 +936,7 @@ | |||
83 | 941 | interface = factory.make_Interface( | 936 | interface = factory.make_Interface( |
84 | 942 | INTERFACE_TYPE.PHYSICAL, node=node) | 937 | INTERFACE_TYPE.PHYSICAL, node=node) |
85 | 943 | new_name = factory.make_name("name") | 938 | new_name = factory.make_name("name") |
88 | 944 | new_fabric = factory.make_Fabric() | 939 | new_vlan = factory.make_VLAN() |
87 | 945 | new_vlan = new_fabric.get_default_vlan() | ||
89 | 946 | uri = get_interface_uri(interface) | 940 | uri = get_interface_uri(interface) |
90 | 947 | response = self.client.put(uri, { | 941 | response = self.client.put(uri, { |
91 | 948 | "name": new_name, | 942 | "name": new_name, |
92 | @@ -961,8 +955,7 @@ | |||
93 | 961 | interface = factory.make_Interface( | 955 | interface = factory.make_Interface( |
94 | 962 | INTERFACE_TYPE.PHYSICAL, node=device) | 956 | INTERFACE_TYPE.PHYSICAL, node=device) |
95 | 963 | new_name = factory.make_name("name") | 957 | new_name = factory.make_name("name") |
98 | 964 | new_fabric = factory.make_Fabric() | 958 | new_vlan = factory.make_VLAN() |
97 | 965 | new_vlan = new_fabric.get_default_vlan() | ||
99 | 966 | uri = get_interface_uri(interface) | 959 | uri = get_interface_uri(interface) |
100 | 967 | response = self.client.put(uri, { | 960 | response = self.client.put(uri, { |
101 | 968 | "name": new_name, | 961 | "name": new_name, |
102 | @@ -996,12 +989,10 @@ | |||
103 | 996 | bond, [nic_0, nic_1], [vlan_10, vlan_11] = make_complex_interface( | 989 | bond, [nic_0, nic_1], [vlan_10, vlan_11] = make_complex_interface( |
104 | 997 | node) | 990 | node) |
105 | 998 | physical_interface = factory.make_Interface( | 991 | physical_interface = factory.make_Interface( |
108 | 999 | INTERFACE_TYPE.PHYSICAL, node=node) | 992 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=nic_0.vlan) |
107 | 1000 | new_vlan = factory.make_VLAN(fabric=physical_interface.vlan.fabric) | ||
109 | 1001 | uri = get_interface_uri(vlan_10) | 993 | uri = get_interface_uri(vlan_10) |
110 | 1002 | response = self.client.put(uri, { | 994 | response = self.client.put(uri, { |
111 | 1003 | "parent": physical_interface.id, | 995 | "parent": physical_interface.id, |
112 | 1004 | "vlan": new_vlan.id, | ||
113 | 1005 | }) | 996 | }) |
114 | 1006 | self.assertEqual( | 997 | self.assertEqual( |
115 | 1007 | http.client.OK, response.status_code, response.content) | 998 | http.client.OK, response.status_code, response.content) |
116 | 1008 | 999 | ||
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 | 252 | if len(parents) > 0: | 252 | if len(parents) > 0: |
122 | 253 | raise ValidationError("A physical interface cannot have parents.") | 253 | raise ValidationError("A physical interface cannot have parents.") |
123 | 254 | 254 | ||
124 | 255 | def clean_vlan(self): | ||
125 | 256 | new_vlan = self.cleaned_data.get('vlan') | ||
126 | 257 | if new_vlan and new_vlan.fabric.get_default_vlan() != new_vlan: | ||
127 | 258 | # A device's physical interface can be connected to a tagged VLAN. | ||
128 | 259 | # This is because a container or VM could be bridged on the machine | ||
129 | 260 | # to a tagged VLAN interface. See lp:1572070 for details. | ||
130 | 261 | if self.node.node_type != NODE_TYPE.DEVICE: | ||
131 | 262 | raise ValidationError( | ||
132 | 263 | "A physical interface can only belong to an " | ||
133 | 264 | "untagged VLAN.") | ||
134 | 265 | return new_vlan | ||
135 | 266 | |||
136 | 267 | def clean(self): | 255 | def clean(self): |
137 | 268 | cleaned_data = super(PhysicalInterfaceForm, self).clean() | 256 | cleaned_data = super(PhysicalInterfaceForm, self).clean() |
138 | 269 | new_name = cleaned_data.get('name') | 257 | new_name = cleaned_data.get('name') |
139 | @@ -313,7 +301,7 @@ | |||
140 | 313 | not created and new_vlan is None and vlan_was_set): | 301 | not created and new_vlan is None and vlan_was_set): |
141 | 314 | raise ValidationError( | 302 | raise ValidationError( |
142 | 315 | "A VLAN interface must be connected to a tagged VLAN.") | 303 | "A VLAN interface must be connected to a tagged VLAN.") |
144 | 316 | if new_vlan and new_vlan.fabric.get_default_vlan() == new_vlan: | 304 | if new_vlan and new_vlan.vid == 0: |
145 | 317 | raise ValidationError( | 305 | raise ValidationError( |
146 | 318 | "A VLAN interface can only belong to a tagged VLAN.") | 306 | "A VLAN interface can only belong to a tagged VLAN.") |
147 | 319 | return new_vlan | 307 | return new_vlan |
148 | @@ -455,16 +443,9 @@ | |||
149 | 455 | 'name', | 443 | 'name', |
150 | 456 | ) | 444 | ) |
151 | 457 | 445 | ||
152 | 458 | def clean_vlan(self): | ||
153 | 459 | new_vlan = self.cleaned_data.get('vlan') | ||
154 | 460 | if new_vlan and new_vlan.fabric.get_default_vlan() != new_vlan: | ||
155 | 461 | raise ValidationError( | ||
156 | 462 | "A bond interface can only belong to an untagged VLAN.") | ||
157 | 463 | return new_vlan | ||
158 | 464 | |||
159 | 465 | def clean(self): | 446 | def clean(self): |
160 | 466 | cleaned_data = super().clean() | 447 | cleaned_data = super().clean() |
162 | 467 | if self.fields_ok(['vlan', 'parents']): | 448 | if self.fields_ok(['parents']): |
163 | 468 | parents = self.cleaned_data.get('parents') | 449 | parents = self.cleaned_data.get('parents') |
164 | 469 | # Set the mac_address if its missing and the interface is being | 450 | # Set the mac_address if its missing and the interface is being |
165 | 470 | # created. | 451 | # created. |
166 | 471 | 452 | ||
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 | 30 | from maasserver.testing.factory import factory | 30 | from maasserver.testing.factory import factory |
172 | 31 | from maasserver.testing.testcase import MAASServerTestCase | 31 | from maasserver.testing.testcase import MAASServerTestCase |
173 | 32 | from maasserver.utils.forms import compose_invalid_choice_text | 32 | from maasserver.utils.forms import compose_invalid_choice_text |
174 | 33 | from maasserver.utils.orm import reload_object | ||
175 | 34 | from testtools import ExpectedException | 33 | from testtools import ExpectedException |
176 | 35 | from testtools.matchers import MatchesStructure | 34 | from testtools.matchers import MatchesStructure |
177 | 36 | 35 | ||
178 | @@ -133,8 +132,7 @@ | |||
179 | 133 | node = factory.make_Node() | 132 | node = factory.make_Node() |
180 | 134 | mac_address = factory.make_mac_address() | 133 | mac_address = factory.make_mac_address() |
181 | 135 | interface_name = 'eth0' | 134 | interface_name = 'eth0' |
184 | 136 | fabric = factory.make_Fabric() | 135 | vlan = factory.make_VLAN() |
183 | 137 | vlan = fabric.get_default_vlan() | ||
185 | 138 | tags = [ | 136 | tags = [ |
186 | 139 | factory.make_name("tag") | 137 | factory.make_name("tag") |
187 | 140 | for _ in range(3) | 138 | for _ in range(3) |
188 | @@ -211,8 +209,7 @@ | |||
189 | 211 | node = factory.make_Node() | 209 | node = factory.make_Node() |
190 | 212 | mac_address = factory.make_mac_address() | 210 | mac_address = factory.make_mac_address() |
191 | 213 | interface_name = 'eth0' | 211 | interface_name = 'eth0' |
194 | 214 | fabric = factory.make_Fabric() | 212 | vlan = factory.make_VLAN() |
193 | 215 | vlan = fabric.get_default_vlan() | ||
195 | 216 | tags = [ | 213 | tags = [ |
196 | 217 | factory.make_name("tag") | 214 | factory.make_name("tag") |
197 | 218 | for _ in range(3) | 215 | for _ in range(3) |
198 | @@ -232,8 +229,7 @@ | |||
199 | 232 | 229 | ||
200 | 233 | def test__requires_mac_address(self): | 230 | def test__requires_mac_address(self): |
201 | 234 | interface_name = 'eth0' | 231 | interface_name = 'eth0' |
204 | 235 | fabric = factory.make_Fabric() | 232 | vlan = factory.make_VLAN() |
203 | 236 | vlan = fabric.get_default_vlan() | ||
205 | 237 | form = PhysicalInterfaceForm( | 233 | form = PhysicalInterfaceForm( |
206 | 238 | node=factory.make_Node(), | 234 | node=factory.make_Node(), |
207 | 239 | data={ | 235 | data={ |
208 | @@ -248,9 +244,7 @@ | |||
209 | 248 | form.errors['mac_address'][0]) | 244 | form.errors['mac_address'][0]) |
210 | 249 | 245 | ||
211 | 250 | def test_rejects_interface_with_duplicate_name(self): | 246 | def test_rejects_interface_with_duplicate_name(self): |
215 | 251 | fabric = factory.make_Fabric() | 247 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
213 | 252 | vlan = fabric.get_default_vlan() | ||
214 | 253 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) | ||
216 | 254 | mac_address = factory.make_mac_address() | 248 | mac_address = factory.make_mac_address() |
217 | 255 | form = PhysicalInterfaceForm( | 249 | form = PhysicalInterfaceForm( |
218 | 256 | node=interface.node, | 250 | node=interface.node, |
219 | @@ -266,26 +260,6 @@ | |||
220 | 266 | "already has an interface named '%s'." % interface.name, | 260 | "already has an interface named '%s'." % interface.name, |
221 | 267 | form.errors['name'][0]) | 261 | form.errors['name'][0]) |
222 | 268 | 262 | ||
223 | 269 | def test_rejects_interface_on_tagged_vlan(self): | ||
224 | 270 | fabric = factory.make_Fabric() | ||
225 | 271 | interface = factory.make_Interface( | ||
226 | 272 | INTERFACE_TYPE.PHYSICAL, vlan=fabric.get_default_vlan()) | ||
227 | 273 | vlan = factory.make_VLAN(fabric=fabric) | ||
228 | 274 | mac_address = factory.make_mac_address() | ||
229 | 275 | form = PhysicalInterfaceForm( | ||
230 | 276 | node=interface.node, | ||
231 | 277 | data={ | ||
232 | 278 | 'name': factory.make_name("eth"), | ||
233 | 279 | 'mac_address': mac_address, | ||
234 | 280 | 'vlan': vlan.id, | ||
235 | 281 | }) | ||
236 | 282 | self.assertFalse(form.is_valid(), dict(form.errors)) | ||
237 | 283 | self.assertItemsEqual( | ||
238 | 284 | ['vlan'], form.errors.keys(), form.errors) | ||
239 | 285 | self.assertIn( | ||
240 | 286 | "A physical interface can only belong to an untagged VLAN.", | ||
241 | 287 | form.errors['vlan'][0]) | ||
242 | 288 | |||
243 | 289 | def test_allows_interface_on_tagged_vlan_for_device(self): | 263 | def test_allows_interface_on_tagged_vlan_for_device(self): |
244 | 290 | device = factory.make_Device() | 264 | device = factory.make_Device() |
245 | 291 | fabric = factory.make_Fabric() | 265 | fabric = factory.make_Fabric() |
246 | @@ -307,8 +281,7 @@ | |||
247 | 307 | 281 | ||
248 | 308 | def test__rejects_parents(self): | 282 | def test__rejects_parents(self): |
249 | 309 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 283 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
252 | 310 | fabric = factory.make_Fabric() | 284 | vlan = factory.make_VLAN() |
251 | 311 | vlan = fabric.get_default_vlan() | ||
253 | 312 | form = PhysicalInterfaceForm( | 285 | form = PhysicalInterfaceForm( |
254 | 313 | node=parent.node, | 286 | node=parent.node, |
255 | 314 | data={ | 287 | data={ |
256 | @@ -328,8 +301,7 @@ | |||
257 | 328 | interface = factory.make_Interface( | 301 | interface = factory.make_Interface( |
258 | 329 | INTERFACE_TYPE.PHYSICAL, name='eth0') | 302 | INTERFACE_TYPE.PHYSICAL, name='eth0') |
259 | 330 | new_name = 'eth1' | 303 | new_name = 'eth1' |
262 | 331 | new_fabric = factory.make_Fabric() | 304 | new_vlan = factory.make_VLAN(vid=33) |
261 | 332 | new_vlan = new_fabric.get_default_vlan() | ||
263 | 333 | form = PhysicalInterfaceForm( | 305 | form = PhysicalInterfaceForm( |
264 | 334 | instance=interface, | 306 | instance=interface, |
265 | 335 | data={ | 307 | data={ |
266 | @@ -390,8 +362,7 @@ | |||
267 | 390 | node = factory.make_Node() | 362 | node = factory.make_Node() |
268 | 391 | mac_address = factory.make_mac_address() | 363 | mac_address = factory.make_mac_address() |
269 | 392 | interface_name = 'eth0' | 364 | interface_name = 'eth0' |
272 | 393 | fabric = factory.make_Fabric() | 365 | vlan = factory.make_VLAN() |
271 | 394 | vlan = fabric.get_default_vlan() | ||
273 | 395 | tags = [ | 366 | tags = [ |
274 | 396 | factory.make_name("tag") | 367 | factory.make_name("tag") |
275 | 397 | for _ in range(3) | 368 | for _ in range(3) |
276 | @@ -430,8 +401,7 @@ | |||
277 | 430 | "autoconf": autoconf, | 401 | "autoconf": autoconf, |
278 | 431 | } | 402 | } |
279 | 432 | new_name = 'eth1' | 403 | new_name = 'eth1' |
282 | 433 | new_fabric = factory.make_Fabric() | 404 | new_vlan = factory.make_VLAN(vid=33) |
281 | 434 | new_vlan = new_fabric.get_default_vlan() | ||
283 | 435 | form = PhysicalInterfaceForm( | 405 | form = PhysicalInterfaceForm( |
284 | 436 | instance=interface, | 406 | instance=interface, |
285 | 437 | data={ | 407 | data={ |
286 | @@ -503,8 +473,8 @@ | |||
287 | 503 | class VLANInterfaceFormTest(MAASServerTestCase): | 473 | class VLANInterfaceFormTest(MAASServerTestCase): |
288 | 504 | 474 | ||
289 | 505 | def test__creates_vlan_interface(self): | 475 | def test__creates_vlan_interface(self): |
292 | 506 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 476 | vlan = factory.make_VLAN(vid=10) |
293 | 507 | vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) | 477 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
294 | 508 | form = VLANInterfaceForm( | 478 | form = VLANInterfaceForm( |
295 | 509 | node=parent.node, | 479 | node=parent.node, |
296 | 510 | data={ | 480 | data={ |
297 | @@ -521,8 +491,8 @@ | |||
298 | 521 | self.assertItemsEqual([parent], interface.parents.all()) | 491 | self.assertItemsEqual([parent], interface.parents.all()) |
299 | 522 | 492 | ||
300 | 523 | def test__create_ensures_link_up(self): | 493 | def test__create_ensures_link_up(self): |
303 | 524 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 494 | vlan = factory.make_VLAN(vid=10) |
304 | 525 | vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) | 495 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) |
305 | 526 | form = VLANInterfaceForm( | 496 | form = VLANInterfaceForm( |
306 | 527 | node=parent.node, | 497 | node=parent.node, |
307 | 528 | data={ | 498 | data={ |
308 | @@ -549,10 +519,13 @@ | |||
309 | 549 | form.errors['vlan'][0]) | 519 | form.errors['vlan'][0]) |
310 | 550 | 520 | ||
311 | 551 | def test_rejects_interface_with_duplicate_name(self): | 521 | def test_rejects_interface_with_duplicate_name(self): |
314 | 552 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 522 | vlan = factory.make_VLAN(vid=10) |
315 | 553 | vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) | 523 | parent = factory.make_Interface( |
316 | 524 | INTERFACE_TYPE.PHYSICAL, | ||
317 | 525 | vlan=vlan) | ||
318 | 554 | interface = factory.make_Interface( | 526 | interface = factory.make_Interface( |
320 | 555 | INTERFACE_TYPE.VLAN, vlan=vlan, parents=[parent]) | 527 | INTERFACE_TYPE.VLAN, |
321 | 528 | vlan=vlan, parents=[parent]) | ||
322 | 556 | form = VLANInterfaceForm( | 529 | form = VLANInterfaceForm( |
323 | 557 | node=parent.node, | 530 | node=parent.node, |
324 | 558 | data={ | 531 | data={ |
325 | @@ -597,14 +570,13 @@ | |||
326 | 597 | 570 | ||
327 | 598 | def test__rejects_vlan_parent(self): | 571 | def test__rejects_vlan_parent(self): |
328 | 599 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 572 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
329 | 600 | vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=10) | ||
330 | 601 | vlan_parent = factory.make_Interface( | 573 | vlan_parent = factory.make_Interface( |
333 | 602 | INTERFACE_TYPE.VLAN, vlan=vlan, parents=[parent]) | 574 | INTERFACE_TYPE.VLAN, parents=[parent]) |
334 | 603 | other_vlan = factory.make_VLAN(fabric=parent.vlan.fabric, vid=11) | 575 | vlan = factory.make_VLAN(vid=10) |
335 | 604 | form = VLANInterfaceForm( | 576 | form = VLANInterfaceForm( |
336 | 605 | node=parent.node, | 577 | node=parent.node, |
337 | 606 | data={ | 578 | data={ |
339 | 607 | 'vlan': other_vlan.id, | 579 | 'vlan': vlan.id, |
340 | 608 | 'parents': [vlan_parent.id], | 580 | 'parents': [vlan_parent.id], |
341 | 609 | }) | 581 | }) |
342 | 610 | self.assertFalse(form.is_valid(), dict(form.errors)) | 582 | self.assertFalse(form.is_valid(), dict(form.errors)) |
343 | @@ -646,8 +618,8 @@ | |||
344 | 646 | 618 | ||
345 | 647 | def test__rejects_parent_on_bond(self): | 619 | def test__rejects_parent_on_bond(self): |
346 | 648 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 620 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
349 | 649 | bond = factory.make_Interface(INTERFACE_TYPE.BOND, parents=[parent]) | 621 | factory.make_Interface(INTERFACE_TYPE.BOND, parents=[parent]) |
350 | 650 | vlan = factory.make_VLAN(fabric=bond.vlan.fabric, vid=10) | 622 | vlan = factory.make_VLAN(vid=10) |
351 | 651 | form = VLANInterfaceForm( | 623 | form = VLANInterfaceForm( |
352 | 652 | node=parent.node, | 624 | node=parent.node, |
353 | 653 | data={ | 625 | data={ |
354 | @@ -682,7 +654,7 @@ | |||
355 | 682 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 654 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
356 | 683 | interface = factory.make_Interface( | 655 | interface = factory.make_Interface( |
357 | 684 | INTERFACE_TYPE.VLAN, parents=[parent]) | 656 | INTERFACE_TYPE.VLAN, parents=[parent]) |
359 | 685 | new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric, vid=33) | 657 | new_vlan = factory.make_VLAN(vid=33) |
360 | 686 | form = VLANInterfaceForm( | 658 | form = VLANInterfaceForm( |
361 | 687 | instance=interface, | 659 | instance=interface, |
362 | 688 | data={ | 660 | data={ |
363 | @@ -701,15 +673,17 @@ | |||
364 | 701 | class BondInterfaceFormTest(MAASServerTestCase): | 673 | class BondInterfaceFormTest(MAASServerTestCase): |
365 | 702 | 674 | ||
366 | 703 | def test__error_with_invalid_bond_mode(self): | 675 | def test__error_with_invalid_bond_mode(self): |
368 | 704 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 676 | vlan = factory.make_VLAN(vid=10) |
369 | 677 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) | ||
370 | 705 | parent2 = factory.make_Interface( | 678 | parent2 = factory.make_Interface( |
372 | 706 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 679 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
373 | 707 | interface_name = factory.make_name() | 680 | interface_name = factory.make_name() |
374 | 708 | bond_mode = factory.make_name("bond_mode") | 681 | bond_mode = factory.make_name("bond_mode") |
375 | 709 | form = BondInterfaceForm( | 682 | form = BondInterfaceForm( |
376 | 710 | node=parent1.node, | 683 | node=parent1.node, |
377 | 711 | data={ | 684 | data={ |
378 | 712 | 'name': interface_name, | 685 | 'name': interface_name, |
379 | 686 | 'vlan': vlan.id, | ||
380 | 713 | 'parents': [parent1.id, parent2.id], | 687 | 'parents': [parent1.id, parent2.id], |
381 | 714 | 'bond_mode': bond_mode, | 688 | 'bond_mode': bond_mode, |
382 | 715 | }) | 689 | }) |
383 | @@ -721,14 +695,16 @@ | |||
384 | 721 | }, form.errors) | 695 | }, form.errors) |
385 | 722 | 696 | ||
386 | 723 | def test__creates_bond_interface(self): | 697 | def test__creates_bond_interface(self): |
388 | 724 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 698 | vlan = factory.make_VLAN(vid=10) |
389 | 699 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) | ||
390 | 725 | parent2 = factory.make_Interface( | 700 | parent2 = factory.make_Interface( |
392 | 726 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 701 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
393 | 727 | interface_name = factory.make_name() | 702 | interface_name = factory.make_name() |
394 | 728 | form = BondInterfaceForm( | 703 | form = BondInterfaceForm( |
395 | 729 | node=parent1.node, | 704 | node=parent1.node, |
396 | 730 | data={ | 705 | data={ |
397 | 731 | 'name': interface_name, | 706 | 'name': interface_name, |
398 | 707 | 'vlan': vlan.id, | ||
399 | 732 | 'parents': [parent1.id, parent2.id], | 708 | 'parents': [parent1.id, parent2.id], |
400 | 733 | }) | 709 | }) |
401 | 734 | self.assertTrue(form.is_valid(), dict(form.errors)) | 710 | self.assertTrue(form.is_valid(), dict(form.errors)) |
402 | @@ -743,16 +719,18 @@ | |||
403 | 743 | self.assertItemsEqual([parent1, parent2], interface.parents.all()) | 719 | self.assertItemsEqual([parent1, parent2], interface.parents.all()) |
404 | 744 | 720 | ||
405 | 745 | def test__create_removes_parent_links_and_sets_link_up_on_bond(self): | 721 | def test__create_removes_parent_links_and_sets_link_up_on_bond(self): |
407 | 746 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 722 | vlan = factory.make_VLAN(vid=10) |
408 | 723 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) | ||
409 | 747 | parent1.ensure_link_up() | 724 | parent1.ensure_link_up() |
410 | 748 | parent2 = factory.make_Interface( | 725 | parent2 = factory.make_Interface( |
412 | 749 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 726 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
413 | 750 | parent2.ensure_link_up() | 727 | parent2.ensure_link_up() |
414 | 751 | interface_name = factory.make_name() | 728 | interface_name = factory.make_name() |
415 | 752 | form = BondInterfaceForm( | 729 | form = BondInterfaceForm( |
416 | 753 | node=parent1.node, | 730 | node=parent1.node, |
417 | 754 | data={ | 731 | data={ |
418 | 755 | 'name': interface_name, | 732 | 'name': interface_name, |
419 | 733 | 'vlan': vlan.id, | ||
420 | 756 | 'parents': [parent1.id, parent2.id], | 734 | 'parents': [parent1.id, parent2.id], |
421 | 757 | }) | 735 | }) |
422 | 758 | self.assertTrue(form.is_valid(), dict(form.errors)) | 736 | self.assertTrue(form.is_valid(), dict(form.errors)) |
423 | @@ -769,14 +747,16 @@ | |||
424 | 769 | interface.ip_addresses.filter(alloc_type=IPADDRESS_TYPE.STICKY)) | 747 | interface.ip_addresses.filter(alloc_type=IPADDRESS_TYPE.STICKY)) |
425 | 770 | 748 | ||
426 | 771 | def test__creates_bond_interface_with_parent_mac_address(self): | 749 | def test__creates_bond_interface_with_parent_mac_address(self): |
428 | 772 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 750 | vlan = factory.make_VLAN(vid=10) |
429 | 751 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) | ||
430 | 773 | parent2 = factory.make_Interface( | 752 | parent2 = factory.make_Interface( |
432 | 774 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 753 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
433 | 775 | interface_name = factory.make_name() | 754 | interface_name = factory.make_name() |
434 | 776 | form = BondInterfaceForm( | 755 | form = BondInterfaceForm( |
435 | 777 | node=parent1.node, | 756 | node=parent1.node, |
436 | 778 | data={ | 757 | data={ |
437 | 779 | 'name': interface_name, | 758 | 'name': interface_name, |
438 | 759 | 'vlan': vlan.id, | ||
439 | 780 | 'parents': [parent1.id, parent2.id], | 760 | 'parents': [parent1.id, parent2.id], |
440 | 781 | 'mac_address': parent1.mac_address, | 761 | 'mac_address': parent1.mac_address, |
441 | 782 | }) | 762 | }) |
442 | @@ -790,14 +770,16 @@ | |||
443 | 790 | self.assertItemsEqual([parent1, parent2], interface.parents.all()) | 770 | self.assertItemsEqual([parent1, parent2], interface.parents.all()) |
444 | 791 | 771 | ||
445 | 792 | def test__creates_bond_interface_with_default_bond_params(self): | 772 | def test__creates_bond_interface_with_default_bond_params(self): |
447 | 793 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 773 | vlan = factory.make_VLAN(vid=10) |
448 | 774 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) | ||
449 | 794 | parent2 = factory.make_Interface( | 775 | parent2 = factory.make_Interface( |
451 | 795 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 776 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
452 | 796 | interface_name = factory.make_name() | 777 | interface_name = factory.make_name() |
453 | 797 | form = BondInterfaceForm( | 778 | form = BondInterfaceForm( |
454 | 798 | node=parent1.node, | 779 | node=parent1.node, |
455 | 799 | data={ | 780 | data={ |
456 | 800 | 'name': interface_name, | 781 | 'name': interface_name, |
457 | 782 | 'vlan': vlan.id, | ||
458 | 801 | 'parents': [parent1.id, parent2.id], | 783 | 'parents': [parent1.id, parent2.id], |
459 | 802 | }) | 784 | }) |
460 | 803 | self.assertTrue(form.is_valid(), dict(form.errors)) | 785 | self.assertTrue(form.is_valid(), dict(form.errors)) |
461 | @@ -812,9 +794,10 @@ | |||
462 | 812 | }, interface.params) | 794 | }, interface.params) |
463 | 813 | 795 | ||
464 | 814 | def test__creates_bond_interface_with_bond_params(self): | 796 | def test__creates_bond_interface_with_bond_params(self): |
466 | 815 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 797 | vlan = factory.make_VLAN(vid=10) |
467 | 798 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, vlan=vlan) | ||
468 | 816 | parent2 = factory.make_Interface( | 799 | parent2 = factory.make_Interface( |
470 | 817 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 800 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=vlan) |
471 | 818 | interface_name = factory.make_name() | 801 | interface_name = factory.make_name() |
472 | 819 | bond_mode = factory.pick_choice(BOND_MODE_CHOICES) | 802 | bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
473 | 820 | bond_miimon = random.randint(0, 1000) | 803 | bond_miimon = random.randint(0, 1000) |
474 | @@ -827,6 +810,7 @@ | |||
475 | 827 | node=parent1.node, | 810 | node=parent1.node, |
476 | 828 | data={ | 811 | data={ |
477 | 829 | 'name': interface_name, | 812 | 'name': interface_name, |
478 | 813 | 'vlan': vlan.id, | ||
479 | 830 | 'parents': [parent1.id, parent2.id], | 814 | 'parents': [parent1.id, parent2.id], |
480 | 831 | 'bond_mode': bond_mode, | 815 | 'bond_mode': bond_mode, |
481 | 832 | 'bond_miimon': bond_miimon, | 816 | 'bond_miimon': bond_miimon, |
482 | @@ -847,11 +831,13 @@ | |||
483 | 847 | }, interface.params) | 831 | }, interface.params) |
484 | 848 | 832 | ||
485 | 849 | def test__rejects_no_parents(self): | 833 | def test__rejects_no_parents(self): |
486 | 834 | vlan = factory.make_VLAN(vid=10) | ||
487 | 850 | interface_name = factory.make_name() | 835 | interface_name = factory.make_name() |
488 | 851 | form = BondInterfaceForm( | 836 | form = BondInterfaceForm( |
489 | 852 | node=factory.make_Node(), | 837 | node=factory.make_Node(), |
490 | 853 | data={ | 838 | data={ |
491 | 854 | 'name': interface_name, | 839 | 'name': interface_name, |
492 | 840 | 'vlan': vlan.id, | ||
493 | 855 | }) | 841 | }) |
494 | 856 | self.assertFalse(form.is_valid(), dict(form.errors)) | 842 | self.assertFalse(form.is_valid(), dict(form.errors)) |
495 | 857 | self.assertItemsEqual(['parents', 'mac_address'], form.errors.keys()) | 843 | self.assertItemsEqual(['parents', 'mac_address'], form.errors.keys()) |
496 | @@ -859,37 +845,21 @@ | |||
497 | 859 | "A bond interface must have one or more parents.", | 845 | "A bond interface must have one or more parents.", |
498 | 860 | form.errors['parents'][0]) | 846 | form.errors['parents'][0]) |
499 | 861 | 847 | ||
500 | 862 | def test__rejects_when_vlan_not_untagged(self): | ||
501 | 863 | interface_name = factory.make_name() | ||
502 | 864 | parent = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | ||
503 | 865 | vlan = factory.make_VLAN(fabric=parent.vlan.fabric) | ||
504 | 866 | form = BondInterfaceForm( | ||
505 | 867 | node=parent.node, | ||
506 | 868 | data={ | ||
507 | 869 | 'name': interface_name, | ||
508 | 870 | 'parents': [parent.id], | ||
509 | 871 | 'mac_address': parent.mac_address, | ||
510 | 872 | 'vlan': vlan.id, | ||
511 | 873 | }) | ||
512 | 874 | self.assertFalse(form.is_valid(), dict(form.errors)) | ||
513 | 875 | self.assertItemsEqual(['vlan'], form.errors.keys()) | ||
514 | 876 | self.assertIn( | ||
515 | 877 | "A bond interface can only belong to an untagged VLAN.", | ||
516 | 878 | form.errors['vlan'][0]) | ||
517 | 879 | |||
518 | 880 | def test__rejects_when_parents_already_have_children(self): | 848 | def test__rejects_when_parents_already_have_children(self): |
519 | 881 | node = factory.make_Node() | 849 | node = factory.make_Node() |
520 | 882 | parent1 = factory.make_Interface( | 850 | parent1 = factory.make_Interface( |
521 | 883 | INTERFACE_TYPE.PHYSICAL, node=node, name="eth0") | 851 | INTERFACE_TYPE.PHYSICAL, node=node, name="eth0") |
522 | 884 | factory.make_Interface(INTERFACE_TYPE.VLAN, parents=[parent1]) | 852 | factory.make_Interface(INTERFACE_TYPE.VLAN, parents=[parent1]) |
523 | 885 | parent2 = factory.make_Interface( | 853 | parent2 = factory.make_Interface( |
525 | 886 | INTERFACE_TYPE.PHYSICAL, node=node, name="eth1", vlan=parent1.vlan) | 854 | INTERFACE_TYPE.PHYSICAL, node=node, name="eth1") |
526 | 887 | factory.make_Interface(INTERFACE_TYPE.VLAN, parents=[parent2]) | 855 | factory.make_Interface(INTERFACE_TYPE.VLAN, parents=[parent2]) |
527 | 856 | vlan = factory.make_VLAN(vid=10) | ||
528 | 888 | interface_name = factory.make_name() | 857 | interface_name = factory.make_name() |
529 | 889 | form = BondInterfaceForm( | 858 | form = BondInterfaceForm( |
530 | 890 | node=node, | 859 | node=node, |
531 | 891 | data={ | 860 | data={ |
532 | 892 | 'name': interface_name, | 861 | 'name': interface_name, |
533 | 862 | 'vlan': vlan.id, | ||
534 | 893 | 'parents': [parent1.id, parent2.id] | 863 | 'parents': [parent1.id, parent2.id] |
535 | 894 | }) | 864 | }) |
536 | 895 | self.assertFalse(form.is_valid(), dict(form.errors)) | 865 | self.assertFalse(form.is_valid(), dict(form.errors)) |
537 | @@ -918,15 +888,14 @@ | |||
538 | 918 | def test__edits_interface(self): | 888 | def test__edits_interface(self): |
539 | 919 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 889 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
540 | 920 | parent2 = factory.make_Interface( | 890 | parent2 = factory.make_Interface( |
542 | 921 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 891 | INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
543 | 922 | interface = factory.make_Interface( | 892 | interface = factory.make_Interface( |
544 | 923 | INTERFACE_TYPE.BOND, | 893 | INTERFACE_TYPE.BOND, |
545 | 924 | parents=[parent1, parent2]) | 894 | parents=[parent1, parent2]) |
548 | 925 | new_fabric = factory.make_Fabric() | 895 | new_vlan = factory.make_VLAN(vid=33) |
547 | 926 | new_vlan = new_fabric.get_default_vlan() | ||
549 | 927 | new_name = factory.make_name() | 896 | new_name = factory.make_name() |
550 | 928 | new_parent = factory.make_Interface( | 897 | new_parent = factory.make_Interface( |
552 | 929 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 898 | INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
553 | 930 | form = BondInterfaceForm( | 899 | form = BondInterfaceForm( |
554 | 931 | instance=interface, | 900 | instance=interface, |
555 | 932 | data={ | 901 | data={ |
556 | @@ -943,10 +912,6 @@ | |||
557 | 943 | vlan=new_vlan, type=INTERFACE_TYPE.BOND)) | 912 | vlan=new_vlan, type=INTERFACE_TYPE.BOND)) |
558 | 944 | self.assertItemsEqual( | 913 | self.assertItemsEqual( |
559 | 945 | [parent1, parent2, new_parent], interface.parents.all()) | 914 | [parent1, parent2, new_parent], interface.parents.all()) |
560 | 946 | self.assertItemsEqual([new_vlan], set( | ||
561 | 947 | reload_object(parent).vlan | ||
562 | 948 | for parent in [parent1, parent2, new_parent] | ||
563 | 949 | )) | ||
564 | 950 | 915 | ||
565 | 951 | def test__edits_interface_allows_disconnected(self): | 916 | def test__edits_interface_allows_disconnected(self): |
566 | 952 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 917 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
567 | @@ -1023,7 +988,7 @@ | |||
568 | 1023 | def test__edit_doesnt_overwrite_params(self): | 988 | def test__edit_doesnt_overwrite_params(self): |
569 | 1024 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 989 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
570 | 1025 | parent2 = factory.make_Interface( | 990 | parent2 = factory.make_Interface( |
572 | 1026 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 991 | INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
573 | 1027 | interface = factory.make_Interface( | 992 | interface = factory.make_Interface( |
574 | 1028 | INTERFACE_TYPE.BOND, | 993 | INTERFACE_TYPE.BOND, |
575 | 1029 | parents=[parent1, parent2]) | 994 | parents=[parent1, parent2]) |
576 | @@ -1043,10 +1008,12 @@ | |||
577 | 1043 | "bond_xmit_hash_policy": bond_xmit_hash_policy, | 1008 | "bond_xmit_hash_policy": bond_xmit_hash_policy, |
578 | 1044 | } | 1009 | } |
579 | 1045 | interface.save() | 1010 | interface.save() |
580 | 1011 | new_vlan = factory.make_VLAN(vid=33) | ||
581 | 1046 | new_name = factory.make_name() | 1012 | new_name = factory.make_name() |
582 | 1047 | form = BondInterfaceForm( | 1013 | form = BondInterfaceForm( |
583 | 1048 | instance=interface, | 1014 | instance=interface, |
584 | 1049 | data={ | 1015 | data={ |
585 | 1016 | 'vlan': new_vlan.id, | ||
586 | 1050 | 'name': new_name, | 1017 | 'name': new_name, |
587 | 1051 | }) | 1018 | }) |
588 | 1052 | self.assertTrue(form.is_valid(), dict(form.errors)) | 1019 | self.assertTrue(form.is_valid(), dict(form.errors)) |
589 | @@ -1063,7 +1030,7 @@ | |||
590 | 1063 | def test__edit_does_overwrite_params(self): | 1030 | def test__edit_does_overwrite_params(self): |
591 | 1064 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 1031 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
592 | 1065 | parent2 = factory.make_Interface( | 1032 | parent2 = factory.make_Interface( |
594 | 1066 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 1033 | INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
595 | 1067 | interface = factory.make_Interface( | 1034 | interface = factory.make_Interface( |
596 | 1068 | INTERFACE_TYPE.BOND, | 1035 | INTERFACE_TYPE.BOND, |
597 | 1069 | parents=[parent1, parent2]) | 1036 | parents=[parent1, parent2]) |
598 | @@ -1083,6 +1050,7 @@ | |||
599 | 1083 | "bond_xmit_hash_policy": bond_xmit_hash_policy, | 1050 | "bond_xmit_hash_policy": bond_xmit_hash_policy, |
600 | 1084 | } | 1051 | } |
601 | 1085 | interface.save() | 1052 | interface.save() |
602 | 1053 | new_vlan = factory.make_VLAN(vid=33) | ||
603 | 1086 | new_name = factory.make_name() | 1054 | new_name = factory.make_name() |
604 | 1087 | new_bond_mode = factory.pick_choice(BOND_MODE_CHOICES) | 1055 | new_bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
605 | 1088 | new_bond_miimon = random.randint(0, 1000) | 1056 | new_bond_miimon = random.randint(0, 1000) |
606 | @@ -1094,6 +1062,7 @@ | |||
607 | 1094 | form = BondInterfaceForm( | 1062 | form = BondInterfaceForm( |
608 | 1095 | instance=interface, | 1063 | instance=interface, |
609 | 1096 | data={ | 1064 | data={ |
610 | 1065 | 'vlan': new_vlan.id, | ||
611 | 1097 | 'name': new_name, | 1066 | 'name': new_name, |
612 | 1098 | 'bond_mode': new_bond_mode, | 1067 | 'bond_mode': new_bond_mode, |
613 | 1099 | 'bond_miimon': new_bond_miimon, | 1068 | 'bond_miimon': new_bond_miimon, |
614 | @@ -1116,7 +1085,7 @@ | |||
615 | 1116 | def test__edit_allows_zero_params(self): | 1085 | def test__edit_allows_zero_params(self): |
616 | 1117 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) | 1086 | parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
617 | 1118 | parent2 = factory.make_Interface( | 1087 | parent2 = factory.make_Interface( |
619 | 1119 | INTERFACE_TYPE.PHYSICAL, node=parent1.node, vlan=parent1.vlan) | 1088 | INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
620 | 1120 | interface = factory.make_Interface( | 1089 | interface = factory.make_Interface( |
621 | 1121 | INTERFACE_TYPE.BOND, | 1090 | INTERFACE_TYPE.BOND, |
622 | 1122 | parents=[parent1, parent2]) | 1091 | parents=[parent1, parent2]) |
623 | @@ -1136,6 +1105,7 @@ | |||
624 | 1136 | "bond_xmit_hash_policy": bond_xmit_hash_policy, | 1105 | "bond_xmit_hash_policy": bond_xmit_hash_policy, |
625 | 1137 | } | 1106 | } |
626 | 1138 | interface.save() | 1107 | interface.save() |
627 | 1108 | new_vlan = factory.make_VLAN(vid=33) | ||
628 | 1139 | new_name = factory.make_name() | 1109 | new_name = factory.make_name() |
629 | 1140 | new_bond_mode = factory.pick_choice(BOND_MODE_CHOICES) | 1110 | new_bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
630 | 1141 | new_bond_miimon = 0 | 1111 | new_bond_miimon = 0 |
631 | @@ -1147,6 +1117,7 @@ | |||
632 | 1147 | form = BondInterfaceForm( | 1117 | form = BondInterfaceForm( |
633 | 1148 | instance=interface, | 1118 | instance=interface, |
634 | 1149 | data={ | 1119 | data={ |
635 | 1120 | 'vlan': new_vlan.id, | ||
636 | 1150 | 'name': new_name, | 1121 | 'name': new_name, |
637 | 1151 | 'bond_mode': new_bond_mode, | 1122 | 'bond_mode': new_bond_mode, |
638 | 1152 | 'bond_miimon': new_bond_miimon, | 1123 | 'bond_miimon': new_bond_miimon, |
639 | 1153 | 1124 | ||
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 | 2079 | handler = MachineHandler(user, {}) | 2079 | handler = MachineHandler(user, {}) |
645 | 2080 | name = factory.make_name("eth") | 2080 | name = factory.make_name("eth") |
646 | 2081 | mac_address = factory.make_mac_address() | 2081 | mac_address = factory.make_mac_address() |
649 | 2082 | fabric = factory.make_Fabric() | 2082 | vlan = factory.make_VLAN() |
648 | 2083 | vlan = fabric.get_default_vlan() | ||
650 | 2084 | handler.create_physical({ | 2083 | handler.create_physical({ |
651 | 2085 | "system_id": node.system_id, | 2084 | "system_id": node.system_id, |
652 | 2086 | "name": name, | 2085 | "name": name, |
653 | @@ -2097,8 +2096,7 @@ | |||
654 | 2097 | handler = MachineHandler(user, {}) | 2096 | handler = MachineHandler(user, {}) |
655 | 2098 | name = factory.make_name("eth") | 2097 | name = factory.make_name("eth") |
656 | 2099 | mac_address = factory.make_mac_address() | 2098 | mac_address = factory.make_mac_address() |
659 | 2100 | fabric = factory.make_Fabric() | 2099 | vlan = factory.make_VLAN() |
658 | 2101 | vlan = fabric.get_default_vlan() | ||
660 | 2102 | subnet = factory.make_Subnet(vlan=vlan) | 2100 | subnet = factory.make_Subnet(vlan=vlan) |
661 | 2103 | handler.create_physical({ | 2101 | handler.create_physical({ |
662 | 2104 | "system_id": node.system_id, | 2102 | "system_id": node.system_id, |
663 | @@ -2120,8 +2118,7 @@ | |||
664 | 2120 | handler = MachineHandler(user, {}) | 2118 | handler = MachineHandler(user, {}) |
665 | 2121 | name = factory.make_name("eth") | 2119 | name = factory.make_name("eth") |
666 | 2122 | mac_address = factory.make_mac_address() | 2120 | mac_address = factory.make_mac_address() |
669 | 2123 | fabric = factory.make_Fabric() | 2121 | vlan = factory.make_VLAN() |
668 | 2124 | vlan = fabric.get_default_vlan() | ||
670 | 2125 | handler.create_physical({ | 2122 | handler.create_physical({ |
671 | 2126 | "system_id": node.system_id, | 2123 | "system_id": node.system_id, |
672 | 2127 | "name": name, | 2124 | "name": name, |
673 | @@ -2141,8 +2138,7 @@ | |||
674 | 2141 | handler = MachineHandler(user, {}) | 2138 | handler = MachineHandler(user, {}) |
675 | 2142 | name = factory.make_name("eth") | 2139 | name = factory.make_name("eth") |
676 | 2143 | mac_address = factory.make_mac_address() | 2140 | mac_address = factory.make_mac_address() |
679 | 2144 | fabric = factory.make_Fabric() | 2141 | vlan = factory.make_VLAN() |
678 | 2145 | vlan = fabric.get_default_vlan() | ||
680 | 2146 | subnet = factory.make_Subnet(vlan=vlan) | 2142 | subnet = factory.make_Subnet(vlan=vlan) |
681 | 2147 | handler.create_physical({ | 2143 | handler.create_physical({ |
682 | 2148 | "system_id": node.system_id, | 2144 | "system_id": node.system_id, |
683 | @@ -2162,12 +2158,13 @@ | |||
684 | 2162 | user = factory.make_admin() | 2158 | user = factory.make_admin() |
685 | 2163 | node = factory.make_Node() | 2159 | node = factory.make_Node() |
686 | 2164 | handler = MachineHandler(user, {}) | 2160 | handler = MachineHandler(user, {}) |
689 | 2165 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | 2161 | vlan = factory.make_VLAN() |
690 | 2166 | new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) | 2162 | interface = factory.make_Interface( |
691 | 2163 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) | ||
692 | 2167 | handler.create_vlan({ | 2164 | handler.create_vlan({ |
693 | 2168 | "system_id": node.system_id, | 2165 | "system_id": node.system_id, |
694 | 2169 | "parent": interface.id, | 2166 | "parent": interface.id, |
696 | 2170 | "vlan": new_vlan.id, | 2167 | "vlan": vlan.id, |
697 | 2171 | }) | 2168 | }) |
698 | 2172 | vlan_interface = get_one( | 2169 | vlan_interface = get_one( |
699 | 2173 | Interface.objects.filter( | 2170 | Interface.objects.filter( |
700 | @@ -2178,13 +2175,14 @@ | |||
701 | 2178 | user = factory.make_admin() | 2175 | user = factory.make_admin() |
702 | 2179 | node = factory.make_Node() | 2176 | node = factory.make_Node() |
703 | 2180 | handler = MachineHandler(user, {}) | 2177 | handler = MachineHandler(user, {}) |
707 | 2181 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | 2178 | vlan = factory.make_VLAN() |
708 | 2182 | new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) | 2179 | interface = factory.make_Interface( |
709 | 2183 | new_subnet = factory.make_Subnet(vlan=new_vlan) | 2180 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) |
710 | 2181 | new_subnet = factory.make_Subnet(vlan=vlan) | ||
711 | 2184 | handler.create_vlan({ | 2182 | handler.create_vlan({ |
712 | 2185 | "system_id": node.system_id, | 2183 | "system_id": node.system_id, |
713 | 2186 | "parent": interface.id, | 2184 | "parent": interface.id, |
715 | 2187 | "vlan": new_vlan.id, | 2185 | "vlan": vlan.id, |
716 | 2188 | "mode": INTERFACE_LINK_TYPE.AUTO, | 2186 | "mode": INTERFACE_LINK_TYPE.AUTO, |
717 | 2189 | "subnet": new_subnet.id, | 2187 | "subnet": new_subnet.id, |
718 | 2190 | }) | 2188 | }) |
719 | @@ -2200,12 +2198,13 @@ | |||
720 | 2200 | user = factory.make_admin() | 2198 | user = factory.make_admin() |
721 | 2201 | node = factory.make_Node() | 2199 | node = factory.make_Node() |
722 | 2202 | handler = MachineHandler(user, {}) | 2200 | handler = MachineHandler(user, {}) |
725 | 2203 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | 2201 | vlan = factory.make_VLAN() |
726 | 2204 | new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) | 2202 | interface = factory.make_Interface( |
727 | 2203 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) | ||
728 | 2205 | handler.create_vlan({ | 2204 | handler.create_vlan({ |
729 | 2206 | "system_id": node.system_id, | 2205 | "system_id": node.system_id, |
730 | 2207 | "parent": interface.id, | 2206 | "parent": interface.id, |
732 | 2208 | "vlan": new_vlan.id, | 2207 | "vlan": vlan.id, |
733 | 2209 | "mode": INTERFACE_LINK_TYPE.LINK_UP, | 2208 | "mode": INTERFACE_LINK_TYPE.LINK_UP, |
734 | 2210 | }) | 2209 | }) |
735 | 2211 | vlan_interface = get_one( | 2210 | vlan_interface = get_one( |
736 | @@ -2220,13 +2219,14 @@ | |||
737 | 2220 | user = factory.make_admin() | 2219 | user = factory.make_admin() |
738 | 2221 | node = factory.make_Node() | 2220 | node = factory.make_Node() |
739 | 2222 | handler = MachineHandler(user, {}) | 2221 | handler = MachineHandler(user, {}) |
743 | 2223 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | 2222 | vlan = factory.make_VLAN() |
744 | 2224 | new_vlan = factory.make_VLAN(fabric=interface.vlan.fabric) | 2223 | interface = factory.make_Interface( |
745 | 2225 | new_subnet = factory.make_Subnet(vlan=new_vlan) | 2224 | INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan) |
746 | 2225 | new_subnet = factory.make_Subnet(vlan=vlan) | ||
747 | 2226 | handler.create_vlan({ | 2226 | handler.create_vlan({ |
748 | 2227 | "system_id": node.system_id, | 2227 | "system_id": node.system_id, |
749 | 2228 | "parent": interface.id, | 2228 | "parent": interface.id, |
751 | 2229 | "vlan": new_vlan.id, | 2229 | "vlan": vlan.id, |
752 | 2230 | "mode": INTERFACE_LINK_TYPE.LINK_UP, | 2230 | "mode": INTERFACE_LINK_TYPE.LINK_UP, |
753 | 2231 | "subnet": new_subnet.id, | 2231 | "subnet": new_subnet.id, |
754 | 2232 | }) | 2232 | }) |
755 | @@ -2317,8 +2317,7 @@ | |||
756 | 2317 | handler = MachineHandler(user, {}) | 2317 | handler = MachineHandler(user, {}) |
757 | 2318 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) | 2318 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
758 | 2319 | new_name = factory.make_name("name") | 2319 | new_name = factory.make_name("name") |
761 | 2320 | new_fabric = factory.make_Fabric() | 2320 | new_vlan = factory.make_VLAN() |
760 | 2321 | new_vlan = new_fabric.get_default_vlan() | ||
762 | 2322 | handler.update_interface({ | 2321 | handler.update_interface({ |
763 | 2323 | "system_id": node.system_id, | 2322 | "system_id": node.system_id, |
764 | 2324 | "interface_id": interface.id, | 2323 | "interface_id": interface.id, |
lgtm!