Merge ~newell-jensen/maas:no-arch-and-mac-address-validation-with-ipmi-power-parameters into maas:master
- Git
- lp:~newell-jensen/maas
- no-arch-and-mac-address-validation-with-ipmi-power-parameters
- Merge into master
Status: | Rejected |
---|---|
Rejected by: | Newell Jensen |
Proposed branch: | ~newell-jensen/maas:no-arch-and-mac-address-validation-with-ipmi-power-parameters |
Merge into: | maas:master |
Diff against target: |
490 lines (+100/-135) 11 files modified
src/maasserver/api/machines.py (+6/-0) src/maasserver/api/tests/test_machines.py (+27/-0) src/maasserver/forms/__init__.py (+28/-13) src/maasserver/forms/tests/test_machine.py (+1/-1) src/maasserver/forms/tests/test_machinewithmacaddresses.py (+19/-1) src/maasserver/models/node.py (+1/-13) src/maasserver/models/tests/test_node.py (+0/-23) src/maasserver/static/js/angular/controllers/add_hardware.js (+11/-28) src/maasserver/static/js/angular/controllers/tests/test_add_hardware.js (+6/-24) src/maasserver/static/partials/nodes-list.html (+1/-1) src/maasserver/websockets/handlers/tests/test_machine.py (+0/-31) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
MAAS Lander | Approve | ||
Lee Trager (community) | Needs Fixing | ||
Review via email: mp+347649@code.launchpad.net |
Commit message
LP: #1707216 - No validation for architecture or mac addresses is required for IPMI power types.
Description of the change
- 7b0fdba... by Newell Jensen
-
Clean some tests.
Lee Trager (ltrager) wrote : | # |
I'm not sure clearing the errors after they occur is the best path. If I add form.save() to your unit test an exception is raised about the architecture missing. I think MAAS should be smart enough to know when to avoid the errors.
On Django forms whether or not a field is required is controlled by the optional field argument required. On the mac_addresses field this is not set so Django is assuming it always is, you can turn it off by modifying WithMACAddresse
self.fields[
If you look at MachineForm.
- a12d6d7... by Newell Jensen
-
Move validation for architecture to forms. Review fixes and updated unit tests.
- 18315b3... by Newell Jensen
-
Merge with master.
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b no-arch-
STATUS: SUCCESS
COMMIT: a12d6d70413c1cd
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b no-arch-
STATUS: SUCCESS
COMMIT: 18315b3cef069a5
- 97fb812... by Newell Jensen
-
Set mac_addresses to empty list when no architecture is given for IPMI power types. This will force the machine to enlist if no architecture is supplied.
- f2e44fa... by Newell Jensen
-
Fix failing unit tests by adding an explicit check for ipmi power type when setting mac addresses to an empty list when no architecture is set.
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b no-arch-
STATUS: FAILED
LOG: http://
COMMIT: 97fb812e49d1a49
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b no-arch-
STATUS: SUCCESS
COMMIT: f2e44fad675b05b
Lee Trager (ltrager) wrote : | # |
If MAC addresses are added and an architecture isn't specified in the UI MAC addresses shouldn't be added for the machine. You stopped adding them only over the API, this should be done in the form. A few other comments below but I think this is close.
- 94cf8d4... by Newell Jensen
-
Review fixes.
Newell Jensen (newell-jensen) wrote : | # |
I updated the branch with the review fixes. Thanks for the review Lee.
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b no-arch-
STATUS: SUCCESS
COMMIT: 94cf8d46212d747
Newell Jensen (newell-jensen) wrote : | # |
Rejecting this branch as my changes were used in https:/
Unmerged commits
- 94cf8d4... by Newell Jensen
-
Review fixes.
- f2e44fa... by Newell Jensen
-
Fix failing unit tests by adding an explicit check for ipmi power type when setting mac addresses to an empty list when no architecture is set.
- 97fb812... by Newell Jensen
-
Set mac_addresses to empty list when no architecture is given for IPMI power types. This will force the machine to enlist if no architecture is supplied.
- 18315b3... by Newell Jensen
-
Merge with master.
- a12d6d7... by Newell Jensen
-
Move validation for architecture to forms. Review fixes and updated unit tests.
- 7b0fdba... by Newell Jensen
-
Clean some tests.
- ea5199b... by Newell Jensen
-
Fix lint.
- cf4c545... by Newell Jensen
-
Drive by clean up.
- fb59a9e... by Newell Jensen
-
LP: #1707216 - No validation for architecture or mac addresses is required for IPMI power types.
- dc3931c... by Newell Jensen
-
Add unit tests.
Preview Diff
1 | diff --git a/src/maasserver/api/machines.py b/src/maasserver/api/machines.py |
2 | index a02cbe2..61e3ec0 100644 |
3 | --- a/src/maasserver/api/machines.py |
4 | +++ b/src/maasserver/api/machines.py |
5 | @@ -1200,6 +1200,7 @@ class AnonMachinesHandler(AnonNodesHandler): |
6 | # BMC enlistment is currently only done for IPMI. |
7 | # First, check if there is a pre-existing machine within MAAS that |
8 | # matches the request. |
9 | + architecture = request.data.get('architecture', None) |
10 | power_type = request.data.get('power_type', None) |
11 | power_parameters = request.data.get('power_parameters', None) |
12 | machine = None |
13 | @@ -1209,6 +1210,11 @@ class AnonMachinesHandler(AnonNodesHandler): |
14 | status__in=[NODE_STATUS.NEW, NODE_STATUS.COMMISSIONING], |
15 | bmc__power_parameters__power_address=( |
16 | params['power_address'])).first() |
17 | + # Update architecture if it is not already set. |
18 | + if machine is not None and architecture is not None: |
19 | + if machine.architecture != architecture: |
20 | + machine.architecture = architecture |
21 | + machine.save() |
22 | if machine is None: |
23 | machine = create_machine(request) |
24 | if machine.status == NODE_STATUS.NEW: |
25 | diff --git a/src/maasserver/api/tests/test_machines.py b/src/maasserver/api/tests/test_machines.py |
26 | index c96eaa0..fc44545 100644 |
27 | --- a/src/maasserver/api/tests/test_machines.py |
28 | +++ b/src/maasserver/api/tests/test_machines.py |
29 | @@ -173,6 +173,33 @@ class TestMachinesAPI(APITestCase.ForUser): |
30 | {nic.mac_address for nic in machine.interface_set.all()}, |
31 | Equals(macs)) |
32 | |
33 | + def test_POST_creates_ipmi_machine_sets_mac_addresses_empty_no_arch(self): |
34 | + make_usable_architecture(self) |
35 | + hostname = factory.make_name('host') |
36 | + macs = { |
37 | + factory.make_mac_address() |
38 | + for _ in range(random.randint(1, 2)) |
39 | + } |
40 | + power_address = factory.make_ip_address() |
41 | + response = self.client.post( |
42 | + reverse('machines_handler'), |
43 | + { |
44 | + 'hostname': hostname, |
45 | + 'mac_addresses': macs, |
46 | + 'power_type': 'ipmi', |
47 | + 'power_parameters_power_address': power_address, |
48 | + }) |
49 | + self.assertEqual(http.client.OK, response.status_code) |
50 | + system_id = json.loads( |
51 | + response.content.decode(settings.DEFAULT_CHARSET))['system_id'] |
52 | + machine = Machine.objects.get(system_id=system_id) |
53 | + self.expectThat(machine.hostname, Equals(hostname)) |
54 | + self.expectThat( |
55 | + {nic.mac_address for nic in machine.interface_set.all()}, |
56 | + Equals(set())) |
57 | + self.assertEqual( |
58 | + power_address, machine.power_parameters['power_address']) |
59 | + |
60 | def test_POST_when_logged_in_creates_machine_in_declared_state(self): |
61 | # When a user enlists a machine, it goes into the New state. |
62 | # This will change once we start doing proper commissioning. |
63 | diff --git a/src/maasserver/forms/__init__.py b/src/maasserver/forms/__init__.py |
64 | index 970e6a3..44c392d 100644 |
65 | --- a/src/maasserver/forms/__init__.py |
66 | +++ b/src/maasserver/forms/__init__.py |
67 | @@ -673,6 +673,9 @@ class MachineForm(NodeForm): |
68 | # Even though it doesn't need it and doesn't use it, this form accepts |
69 | # a parameter named 'request' because it is used interchangingly |
70 | # with AdminMachineForm which actually uses this parameter. |
71 | + request = kwargs.get('request') |
72 | + if request is not None: |
73 | + self.data = request.data |
74 | instance = kwargs.get('instance') |
75 | |
76 | self.set_up_architecture_field() |
77 | @@ -702,9 +705,11 @@ class MachineForm(NodeForm): |
78 | choices = list_architecture_choices(architectures) |
79 | invalid_arch_message = compose_invalid_choice_text( |
80 | 'architecture', choices) |
81 | + power_type = self.data.get('power_type', None) |
82 | self.fields['architecture'] = forms.ChoiceField( |
83 | - choices=choices, required=False, initial=default_arch, |
84 | - error_messages={'invalid_choice': invalid_arch_message}) |
85 | + choices=choices, required=(power_type != 'ipmi'), |
86 | + initial=default_arch, error_messages={ |
87 | + 'invalid_choice': invalid_arch_message}) |
88 | |
89 | def set_up_osystem_and_distro_series_fields(self, instance): |
90 | """Create the `osystem` and `distro_series` fields. |
91 | @@ -1205,7 +1210,8 @@ class WithMACAddressesMixin: |
92 | |
93 | def set_up_mac_addresses_field(self): |
94 | macs = [mac for mac in self.data.getlist('mac_addresses') if mac] |
95 | - self.fields['mac_addresses'] = MultipleMACAddressField(len(macs)) |
96 | + self.fields['mac_addresses'] = MultipleMACAddressField( |
97 | + len(macs), required=(self.data.get('power_type') != 'ipmi')) |
98 | self.data = self.data.copy() |
99 | self.data['mac_addresses'] = macs |
100 | |
101 | @@ -1255,16 +1261,25 @@ class WithMACAddressesMixin: |
102 | This implementation of `save` does not support the `commit` argument. |
103 | """ |
104 | node = super(WithMACAddressesMixin, self).save() |
105 | - for mac in self.cleaned_data['mac_addresses']: |
106 | - mac_addresses_errors = [] |
107 | - try: |
108 | - node.add_physical_interface(mac) |
109 | - except ValidationError as e: |
110 | - mac_addresses_errors.append(e.message) |
111 | - if mac_addresses_errors: |
112 | - raise ValidationError({ |
113 | - "mac_addresses": mac_addresses_errors |
114 | - }) |
115 | + architecture = self.cleaned_data.get('architecture') |
116 | + power_type = self.cleaned_data.get('power_type') |
117 | + # BMC enlistment - if no achitecture is set for IPMI power type, |
118 | + # force mac_addressesto be empty. |
119 | + if not architecture and power_type == 'ipmi': |
120 | + mac_addresses = [] |
121 | + else: |
122 | + mac_addresses = self.cleaned_data.get('mac_addresses') |
123 | + if mac_addresses: |
124 | + for mac in mac_addresses: |
125 | + mac_addresses_errors = [] |
126 | + try: |
127 | + node.add_physical_interface(mac) |
128 | + except ValidationError as e: |
129 | + mac_addresses_errors.append(e.message) |
130 | + if mac_addresses_errors: |
131 | + raise ValidationError({ |
132 | + "mac_addresses": mac_addresses_errors |
133 | + }) |
134 | # Generate a hostname for this node if the provided hostname is |
135 | # IP-based (because this means that this name comes from a DNS |
136 | # reverse query to the MAAS DNS). If the provided hostname was empty, |
137 | diff --git a/src/maasserver/forms/tests/test_machine.py b/src/maasserver/forms/tests/test_machine.py |
138 | index f284136..4bca075 100644 |
139 | --- a/src/maasserver/forms/tests/test_machine.py |
140 | +++ b/src/maasserver/forms/tests/test_machine.py |
141 | @@ -369,8 +369,8 @@ class TestAdminMachineForm(MAASServerTestCase): |
142 | 'cpu_count', |
143 | 'memory', |
144 | 'zone', |
145 | - 'power_type', |
146 | 'power_parameters', |
147 | + 'power_type', |
148 | 'pool', |
149 | ], |
150 | list(form.fields)) |
151 | diff --git a/src/maasserver/forms/tests/test_machinewithmacaddresses.py b/src/maasserver/forms/tests/test_machinewithmacaddresses.py |
152 | index 5e6b703..fefaaf9 100644 |
153 | --- a/src/maasserver/forms/tests/test_machinewithmacaddresses.py |
154 | +++ b/src/maasserver/forms/tests/test_machinewithmacaddresses.py |
155 | @@ -1,4 +1,4 @@ |
156 | -# Copyright 2014-2016 Canonical Ltd. This software is licensed under the |
157 | +# Copyright 2014-2018 Canonical Ltd. This software is licensed under the |
158 | # GNU Affero General Public License version 3 (see the file LICENSE). |
159 | |
160 | """Tests for `MachineWithMACAddressesForm`.""" |
161 | @@ -138,6 +138,24 @@ class MachineWithMACAddressesFormTest(MAASServerTestCase): |
162 | |
163 | self.assertTrue(form.is_valid()) |
164 | |
165 | + def test__mac_address_is_required(self): |
166 | + form = MachineWithMACAddressesForm( |
167 | + data=self.make_params(mac_addresses=[])) |
168 | + |
169 | + self.assertFalse(form.is_valid()) |
170 | + self.assertEqual(['mac_addresses'], list(form.errors)) |
171 | + self.assertEqual( |
172 | + ["This field is required."], |
173 | + form.errors['mac_addresses']) |
174 | + |
175 | + def test__no_architecture_or_mac_addresses_is_ok_for_ipmi(self): |
176 | + # No architecture or MAC addresses is okay for IPMI power types. |
177 | + params = self.make_params(mac_addresses=[]) |
178 | + params['architecture'] = None |
179 | + params['power_type'] = 'ipmi' |
180 | + form = MachineWithMACAddressesForm(data=params) |
181 | + self.assertTrue(form.is_valid()) |
182 | + |
183 | def test__save(self): |
184 | macs = ['aa:bb:cc:dd:ee:ff', '9a:bb:c3:33:e5:7f'] |
185 | form = MachineWithMACAddressesForm( |
186 | diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py |
187 | index 2599a6e..6b4b39f 100644 |
188 | --- a/src/maasserver/models/node.py |
189 | +++ b/src/maasserver/models/node.py |
190 | @@ -1563,12 +1563,6 @@ class Node(CleanSave, TimestampedModel): |
191 | ) |
192 | raise NodeStateViolation(error_text) |
193 | |
194 | - def clean_architecture(self): |
195 | - if self.architecture == '': |
196 | - raise ValidationError( |
197 | - {'architecture': |
198 | - ["Architecture must be defined for installable nodes."]}) |
199 | - |
200 | def clean_hostname_domain(self): |
201 | # If you set the hostname to a name with dots, that you mean for that |
202 | # to be the FQDN of the host. Se we check that a domain exists for |
203 | @@ -1607,8 +1601,6 @@ class Node(CleanSave, TimestampedModel): |
204 | self.clean_pool() |
205 | if self._state.has_changed('status'): |
206 | self.clean_status(self._state.get_old_value('status')) |
207 | - if self._state.has_changed('architecture'): |
208 | - self.clean_architecture() |
209 | if self._state.has_changed('boot_disk_id'): |
210 | self.clean_boot_disk() |
211 | if self._state.has_changed('boot_interface_id'): |
212 | @@ -2984,7 +2976,7 @@ class Node(CleanSave, TimestampedModel): |
213 | |
214 | def split_arch(self): |
215 | """Return architecture and subarchitecture, as a tuple.""" |
216 | - if self.architecture is None: |
217 | + if self.architecture is None or self.architecture == '': |
218 | return ("", "") |
219 | arch, subarch = self.architecture.split('/') |
220 | return (arch, subarch) |
221 | @@ -5464,10 +5456,6 @@ class Device(Node): |
222 | super(Device, self).__init__( |
223 | node_type=NODE_TYPE.DEVICE, *args, **kwargs) |
224 | |
225 | - def clean_architecture(self): |
226 | - # Devices aren't required to have a defined architecture |
227 | - pass |
228 | - |
229 | |
230 | class NodeGroupToRackController(CleanSave, Model): |
231 | """Store some of the old NodeGroup data so we can migrate it when a rack |
232 | diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py |
233 | index d15ba32..0b5694c 100644 |
234 | --- a/src/maasserver/models/tests/test_node.py |
235 | +++ b/src/maasserver/models/tests/test_node.py |
236 | @@ -1004,17 +1004,6 @@ class TestNode(MAASServerTestCase): |
237 | node = factory.make_Node() |
238 | self.assertThat(node.system_id, HasLength(6)) |
239 | |
240 | - def test_empty_architecture_rejected_for_type_node(self): |
241 | - self.assertRaises( |
242 | - ValidationError, |
243 | - factory.make_Node, node_type=NODE_TYPE.MACHINE, architecture='') |
244 | - |
245 | - def test_empty_architecture_rejected_for_type_rack_controller(self): |
246 | - self.assertRaises( |
247 | - ValidationError, |
248 | - factory.make_Node, node_type=NODE_TYPE.RACK_CONTROLLER, |
249 | - architecture='') |
250 | - |
251 | def test__set_zone(self): |
252 | zone = factory.make_Zone() |
253 | node = factory.make_Node() |
254 | @@ -3429,18 +3418,6 @@ class TestNode(MAASServerTestCase): |
255 | node = reload_object(node) |
256 | self.assertIsNone(node.status_expires) |
257 | |
258 | - def test_save_checks_architecture_for_installable_nodes(self): |
259 | - device = factory.make_Device(architecture='') |
260 | - device.node_type = factory.pick_enum( |
261 | - NODE_TYPE, but_not=[NODE_TYPE.DEVICE]) |
262 | - device._state._changed_fields['architecture'] = None |
263 | - exception = self.assertRaises( |
264 | - ValidationError, device.as_node().save) |
265 | - self.assertEqual( |
266 | - exception.message_dict, |
267 | - {'architecture': |
268 | - ['Architecture must be defined for installable nodes.']}) |
269 | - |
270 | def test_netboot_defaults_to_True(self): |
271 | node = Node() |
272 | self.assertTrue(node.netboot) |
273 | diff --git a/src/maasserver/static/js/angular/controllers/add_hardware.js b/src/maasserver/static/js/angular/controllers/add_hardware.js |
274 | index 5e1b0d8..7d4d7f0 100644 |
275 | --- a/src/maasserver/static/js/angular/controllers/add_hardware.js |
276 | +++ b/src/maasserver/static/js/angular/controllers/add_hardware.js |
277 | @@ -25,6 +25,7 @@ angular.module('MAAS').controller('AddHardwareController', [ |
278 | $scope.pools = ResourcePoolsManager.getItems(); |
279 | $scope.domains = DomainsManager.getItems(); |
280 | $scope.architectures = GeneralManager.getData("architectures"); |
281 | + $scope.architectures.push("Choose an architecture"); |
282 | $scope.hwe_kernels = GeneralManager.getData("hwe_kernels"); |
283 | $scope.default_min_hwe_kernel = GeneralManager.getData( |
284 | "default_min_hwe_kernel"); |
285 | @@ -274,22 +275,6 @@ angular.module('MAAS').controller('AddHardwareController', [ |
286 | } |
287 | } |
288 | |
289 | - // Get the default architecture from the loaded architectures. |
290 | - function defaultArchitecture() { |
291 | - if($scope.architectures.length === 0) { |
292 | - return ''; |
293 | - } else { |
294 | - // Return amd64/generic first if available. |
295 | - var i; |
296 | - for(i = 0; i < $scope.architectures.length; i++) { |
297 | - if($scope.architectures[i] === "amd64/generic") { |
298 | - return $scope.architectures[i]; |
299 | - } |
300 | - } |
301 | - return $scope.architectures[0]; |
302 | - } |
303 | - } |
304 | - |
305 | // Return a new MAC address object. |
306 | function newMAC() { |
307 | return { |
308 | @@ -326,7 +311,7 @@ angular.module('MAAS').controller('AddHardwareController', [ |
309 | macs: [newMAC()], |
310 | zone: defaultZone(), |
311 | pool: defaultResourcePool(), |
312 | - architecture: defaultArchitecture(), |
313 | + architecture: '', |
314 | min_hwe_kernel: $scope.default_min_hwe_kernel.text, |
315 | power: { |
316 | type: null, |
317 | @@ -419,15 +404,6 @@ angular.module('MAAS').controller('AddHardwareController', [ |
318 | $scope.machine = newMachine($scope.machine); |
319 | $scope.chassis = newChassis($scope.chassis); |
320 | $scope.error = null; |
321 | - |
322 | - // If the machine doesn't have an architecture |
323 | - // set then it was created before all of the |
324 | - // architectures were loaded. Set the default |
325 | - // architecture for that machine. |
326 | - if(angular.isObject($scope.machine) && |
327 | - $scope.machine.architecture === '') { |
328 | - $scope.machine.architecture = defaultArchitecture(); |
329 | - } |
330 | $scope.viewable = true; |
331 | }); |
332 | |
333 | @@ -518,7 +494,8 @@ angular.module('MAAS').controller('AddHardwareController', [ |
334 | $scope.machine === null || |
335 | $scope.machine.zone === null || |
336 | $scope.machine.pool === null || |
337 | - $scope.machine.architecture === '' || |
338 | + ($scope.machine.architecture === 'Choose an architecture' && |
339 | + $scope.machine.power.type.name !== 'ipmi') || |
340 | $scope.machine.power.type === null || |
341 | $scope.invalidName($scope.machine)); |
342 | if(in_error) { |
343 | @@ -527,7 +504,8 @@ angular.module('MAAS').controller('AddHardwareController', [ |
344 | |
345 | // Make sure none of the mac addresses are in error. The first one |
346 | // cannot be blank the remaining are allowed to be empty. |
347 | - if($scope.machine.macs[0].mac === '' || |
348 | + if(($scope.machine.macs[0].mac === '' && |
349 | + $scope.machine.power.type.name !== 'ipmi') || |
350 | $scope.machine.macs[0].error) { |
351 | return true; |
352 | } |
353 | @@ -575,6 +553,11 @@ angular.module('MAAS').controller('AddHardwareController', [ |
354 | // the device. |
355 | $scope.error = null; |
356 | |
357 | + // Set the architecture to empty string if none was chosen. |
358 | + if($scope.machine.architecture === "Choose an architecture") { |
359 | + $scope.machine.architecture = ''; |
360 | + } |
361 | + |
362 | // Add the machine. |
363 | MachinesManager.create( |
364 | convertMachineToProtocol($scope.machine)).then( |
365 | diff --git a/src/maasserver/static/js/angular/controllers/tests/test_add_hardware.js b/src/maasserver/static/js/angular/controllers/tests/test_add_hardware.js |
366 | index 4f097c4..48f8783 100644 |
367 | --- a/src/maasserver/static/js/angular/controllers/tests/test_add_hardware.js |
368 | +++ b/src/maasserver/static/js/angular/controllers/tests/test_add_hardware.js |
369 | @@ -105,7 +105,7 @@ describe("AddHardwareController", function() { |
370 | expect($scope.zones).toBe(ZonesManager.getItems()); |
371 | expect($scope.pools).toBe(ResourcePoolsManager.getItems()); |
372 | expect($scope.domains).toBe(DomainsManager.getItems()); |
373 | - expect($scope.architectures).toEqual([]); |
374 | + expect($scope.architectures).toEqual(['Choose an architecture']); |
375 | expect($scope.hwe_kernels).toEqual([]); |
376 | expect($scope.power_types).toEqual([]); |
377 | expect($scope.error).toBeNull(); |
378 | @@ -121,32 +121,14 @@ describe("AddHardwareController", function() { |
379 | expect(ManagerHelperService.loadManagers).not.toHaveBeenCalled(); |
380 | }); |
381 | |
382 | - it("initializes machine architecture with first arch", function() { |
383 | - var loadManagers_defer = $q.defer(); |
384 | - var loadItems_defer = $q.defer(); |
385 | - var controller = makeController(loadManagers_defer, loadItems_defer); |
386 | - var arch = makeName("arch"); |
387 | - $scope.architectures = [arch]; |
388 | - $scope.machine = { |
389 | - architecture: '', |
390 | - power: {type: makeName("power_type")} |
391 | - }; |
392 | - $scope.show(); |
393 | - |
394 | - loadManagers_defer.resolve(); |
395 | - loadItems_defer.resolve(); |
396 | - $scope.$digest(); |
397 | - expect($scope.machine.architecture).toEqual(arch); |
398 | - }); |
399 | - |
400 | - it("initializes machine architecture with amd64 arch", function() { |
401 | + it("initializes machine arch with 'Choose an architecture'", function() { |
402 | var loadManagers_defer = $q.defer(); |
403 | var loadItems_defer = $q.defer(); |
404 | var controller = makeController(loadManagers_defer, loadItems_defer); |
405 | var arch = makeName("arch"); |
406 | $scope.architectures = [arch, "amd64/generic"]; |
407 | $scope.machine = { |
408 | - architecture: '', |
409 | + architecture: 'Choose an architecture', |
410 | power: {type: makeName("power_type")} |
411 | }; |
412 | $scope.show(); |
413 | @@ -154,7 +136,7 @@ describe("AddHardwareController", function() { |
414 | loadManagers_defer.resolve(); |
415 | loadItems_defer.resolve(); |
416 | $scope.$digest(); |
417 | - expect($scope.machine.architecture).toEqual("amd64/generic"); |
418 | + expect($scope.machine.architecture).toEqual("Choose an architecture"); |
419 | }); |
420 | |
421 | it("doesnt initializes machine architecture if set", function() { |
422 | @@ -383,11 +365,11 @@ describe("AddHardwareController", function() { |
423 | expect($scope.machineHasError()).toBe(true); |
424 | }); |
425 | |
426 | - it("returns true if architecture is empty", function() { |
427 | + it("returns true if architecture is not chosen", function() { |
428 | var controller = makeControllerWithMachine(); |
429 | $scope.machine.zone = {}; |
430 | $scope.machine.pool = {}; |
431 | - $scope.machine.architecture = ''; |
432 | + $scope.machine.architecture = 'Choose an architecture'; |
433 | $scope.machine.power.type = {}; |
434 | $scope.machine.macs[0].mac = '00:11:22:33:44:55'; |
435 | $scope.machine.macs[0].error = false; |
436 | diff --git a/src/maasserver/static/partials/nodes-list.html b/src/maasserver/static/partials/nodes-list.html |
437 | index 8310b39..d318cab 100644 |
438 | --- a/src/maasserver/static/partials/nodes-list.html |
439 | +++ b/src/maasserver/static/partials/nodes-list.html |
440 | @@ -382,7 +382,7 @@ |
441 | <select name="architecture" id="architecture" |
442 | data-ng-model="machine.architecture" |
443 | data-ng-options="arch for arch in architectures"> |
444 | - <option value="" disabled>Choose an architecture</option> |
445 | + <option value="">Choose an architecture</option> |
446 | </select> |
447 | </div> |
448 | </div> |
449 | diff --git a/src/maasserver/websockets/handlers/tests/test_machine.py b/src/maasserver/websockets/handlers/tests/test_machine.py |
450 | index 72fd395..183d74f 100644 |
451 | --- a/src/maasserver/websockets/handlers/tests/test_machine.py |
452 | +++ b/src/maasserver/websockets/handlers/tests/test_machine.py |
453 | @@ -1778,37 +1778,6 @@ class TestMachineHandler(MAASServerTestCase): |
454 | HandlerPermissionError, |
455 | handler.create, {}) |
456 | |
457 | - def test_create_raises_validation_error_for_missing_pxe_mac(self): |
458 | - user = factory.make_admin() |
459 | - handler = MachineHandler(user, {}) |
460 | - zone = factory.make_Zone() |
461 | - params = { |
462 | - "architecture": make_usable_architecture(self), |
463 | - "zone": { |
464 | - "name": zone.name, |
465 | - }, |
466 | - } |
467 | - error = self.assertRaises( |
468 | - HandlerValidationError, handler.create, params) |
469 | - self.assertThat(error.message_dict, Equals( |
470 | - {'mac_addresses': ['This field is required.']})) |
471 | - |
472 | - def test_create_raises_validation_error_for_missing_architecture(self): |
473 | - user = factory.make_admin() |
474 | - handler = MachineHandler(user, {}) |
475 | - zone = factory.make_Zone() |
476 | - params = { |
477 | - "pxe_mac": factory.make_mac_address(), |
478 | - "zone": { |
479 | - "name": zone.name, |
480 | - }, |
481 | - } |
482 | - error = self.assertRaises( |
483 | - HandlerValidationError, handler.create, params) |
484 | - self.assertThat(error.message_dict, Equals( |
485 | - {'architecture': [ |
486 | - 'Architecture must be defined for installable nodes.']})) |
487 | - |
488 | def test_create_creates_node(self): |
489 | user = factory.make_admin() |
490 | handler = MachineHandler(user, {}) |
UNIT TESTS and-mac- address- validation- with-ipmi- power-parameter s lp:~newell-jensen/maas/+git/maas into -b master lp:~maas-committers/maas
-b no-arch-
STATUS: SUCCESS b4818b6cc6b3300 c454d5de48
COMMIT: 7b0fdba3debce6f