Merge ~newell-jensen/maas:lxd-commissioning-hooks-memory into maas:master
- Git
- lp:~newell-jensen/maas
- lxd-commissioning-hooks-memory
- Merge into master
Proposed by
Newell Jensen
Status: | Merged |
---|---|
Approved by: | Newell Jensen |
Approved revision: | 0e10985bdf6ece6075af36e6695bec2e32855a37 |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~newell-jensen/maas:lxd-commissioning-hooks-memory |
Merge into: | maas:master |
Diff against target: |
468 lines (+245/-98) 2 files modified
src/metadataserver/builtin_scripts/hooks.py (+20/-35) src/metadataserver/builtin_scripts/tests/test_hooks.py (+225/-63) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Lee Trager (community) | Needs Fixing | ||
MAAS Lander | Needs Fixing | ||
Review via email: mp+372503@code.launchpad.net |
Commit message
Use LXD commissioning memory output instead of lshw memory output when post processing the script result hooks. Update cpu_speed to iterate over the sockets to take average frequency.
Description of the change
To post a comment you must log in.
Revision history for this message
Lee Trager (ltrager) wrote : | # |
When the CPU frequency isn't found in the CPU model name its value should be the maximum value, not the average.
review:
Needs Fixing
- 24c6cac... by Newell Jensen
-
Review updates.
- 0e10985... by Newell Jensen
-
Update current average frequency when there is no max.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/src/metadataserver/builtin_scripts/hooks.py b/src/metadataserver/builtin_scripts/hooks.py |
2 | index 75928e2..e488e44 100644 |
3 | --- a/src/metadataserver/builtin_scripts/hooks.py |
4 | +++ b/src/metadataserver/builtin_scripts/hooks.py |
5 | @@ -7,13 +7,11 @@ __all__ = [ |
6 | 'NODE_INFO_SCRIPTS', |
7 | 'parse_lshw_nic_info', |
8 | 'update_node_network_information', |
9 | - 'lxd_update_cpu_details', |
10 | ] |
11 | |
12 | import fnmatch |
13 | import json |
14 | import logging |
15 | -import math |
16 | import re |
17 | |
18 | from lxml import etree |
19 | @@ -298,8 +296,8 @@ def get_xml_field_value(evaluator, expression): |
20 | def update_hardware_details(node, output, exit_status): |
21 | """Process the results of `LSHW_SCRIPT`. |
22 | |
23 | - Updates `node.memory`, and `node.storage` fields, and also |
24 | - evaluates all tag expressions against the given ``lshw`` XML. |
25 | + Updates `node.storage` fields, and also evaluates all tag |
26 | + expressions against the given ``lshw`` XML. |
27 | |
28 | If `exit_status` is non-zero, this function returns without doing |
29 | anything. |
30 | @@ -318,20 +316,6 @@ def update_hardware_details(node, output, exit_status): |
31 | # Same document, many queries: use XPathEvaluator. |
32 | evaluator = etree.XPathEvaluator(doc) |
33 | |
34 | - # Some machines have a <size> element in their memory <node> with the |
35 | - # total amount of memory, and other machines declare the size of the |
36 | - # memory in individual memory banks. This expression is mean to cope |
37 | - # with both. |
38 | - memory = evaluator("""\ |
39 | - sum(//node[@id='memory']/size[@units='bytes'] | |
40 | - //node[starts-with(@id, 'memory:')] |
41 | - /node[starts-with(@id, 'bank:')]/size[@units='bytes']) |
42 | - div 1024 div 1024 |
43 | - """) |
44 | - if not memory or math.isnan(memory): |
45 | - memory = 0 |
46 | - node.memory = memory |
47 | - |
48 | # Only one hardware UUID should be provided but lxml always returns a |
49 | # list. |
50 | for e in evaluator('//node/configuration/setting[@id="uuid"]'): |
51 | @@ -339,7 +323,7 @@ def update_hardware_details(node, output, exit_status): |
52 | if value: |
53 | node.hardware_uuid = value |
54 | |
55 | - node.save(update_fields=['memory', 'hardware_uuid']) |
56 | + node.save(update_fields=['hardware_uuid']) |
57 | |
58 | # This gathers the system vendor, product, version, and serial. Custom |
59 | # built machines and some Supermicro servers do not provide this |
60 | @@ -389,15 +373,9 @@ def process_lxd_results(node, output, exit_status): |
61 | raise ValueError(e.message + ': ' + output) |
62 | |
63 | # Update CPU details. |
64 | - lxd_update_cpu_details(node, data) |
65 | - |
66 | - |
67 | -def lxd_update_cpu_details(node, data): |
68 | - """Updates `node.cpu_count`, `node.cpu_speed`, `node.cpu_model`""" |
69 | - # cpu_count, cpu_speed, cpu_model. |
70 | node.cpu_count, node.cpu_speed, cpu_model = _parse_lxd_cpuinfo(data) |
71 | - # memory. |
72 | - node.memory = data.get('memory', {}).get('total', 0) |
73 | + # Update memory. |
74 | + node.memory = data.get('memory', {}).get('total', 0) / 1024 / 1024 |
75 | |
76 | if cpu_model: |
77 | NodeMetadata.objects.update_or_create( |
78 | @@ -435,19 +413,26 @@ def _parse_lxd_cpuinfo(data): |
79 | if m is not None: |
80 | cpu_speed = int(float(m.group('ghz')) * 1000) |
81 | # When socket names don't match or cpu_speed couldn't be retrieved, |
82 | - # use the max frequency if available before resulting to current |
83 | - # frequency average. |
84 | + # use the max frequency among all the sockets if before |
85 | + # resulting to average current frequency of all the sockets. |
86 | if not cpu_speed: |
87 | - frequency_turbo = socket.get('frequency_turbo') |
88 | - if frequency_turbo is not None: |
89 | - cpu_speed = frequency_turbo |
90 | + max_frequency = 0 |
91 | + for socket in sockets: |
92 | + frequency_turbo = socket.get('frequency_turbo', 0) |
93 | + if frequency_turbo > max_frequency: |
94 | + max_frequency = frequency_turbo |
95 | + if max_frequency: |
96 | + cpu_speed = max_frequency |
97 | else: |
98 | - frequency_current_average = socket.get('frequency') |
99 | - if frequency_current_average is not None: |
100 | + current_average = 0 |
101 | + for socket in sockets: |
102 | + current_average += socket.get('frequency', 0) |
103 | + current_average /= len(sockets) |
104 | + if current_average: |
105 | # Fall back on the current speed, round it to |
106 | # the nearest hundredth as the number may be |
107 | # effected by CPU scaling. |
108 | - cpu_speed = round(frequency_current_average / 100) * 100 |
109 | + cpu_speed = round(current_average / 100) * 100 |
110 | |
111 | return cpu_count, cpu_speed, cpu_model |
112 | |
113 | diff --git a/src/metadataserver/builtin_scripts/tests/test_hooks.py b/src/metadataserver/builtin_scripts/tests/test_hooks.py |
114 | index bb68e1a..870c351 100644 |
115 | --- a/src/metadataserver/builtin_scripts/tests/test_hooks.py |
116 | +++ b/src/metadataserver/builtin_scripts/tests/test_hooks.py |
117 | @@ -41,7 +41,7 @@ from metadataserver.builtin_scripts.hooks import ( |
118 | extract_router_mac_addresses, |
119 | filter_modaliases, |
120 | get_dmi_data, |
121 | - lxd_update_cpu_details, |
122 | + process_lxd_results, |
123 | retag_node_for_hardware_by_modalias, |
124 | set_virtual_tag, |
125 | SWITCH_OPENBMC_MAC, |
126 | @@ -88,7 +88,7 @@ lldp_output_interface_template = """ |
127 | """ |
128 | |
129 | |
130 | -SAMPLE_JSON_CPUINFO = { |
131 | +SAMPLE_LXD_JSON = { |
132 | "cpu": { |
133 | "architecture": "x86_64", |
134 | "sockets": [ |
135 | @@ -135,14 +135,212 @@ SAMPLE_JSON_CPUINFO = { |
136 | } |
137 | ], |
138 | "frequency": 3247 |
139 | + }, |
140 | + { |
141 | + "core": 1, |
142 | + "numa_node": 0, |
143 | + "threads": [ |
144 | + { |
145 | + "id": 2, |
146 | + "thread": 0, |
147 | + "online": True |
148 | + }, |
149 | + { |
150 | + "id": 3, |
151 | + "thread": 1, |
152 | + "online": True |
153 | + } |
154 | + ], |
155 | + "frequency": 3192 |
156 | + }, |
157 | + { |
158 | + "core": 2, |
159 | + "numa_node": 0, |
160 | + "threads": [ |
161 | + { |
162 | + "id": 4, |
163 | + "thread": 0, |
164 | + "online": True |
165 | + }, |
166 | + { |
167 | + "id": 5, |
168 | + "thread": 1, |
169 | + "online": True |
170 | + } |
171 | + ], |
172 | + "frequency": 3241 |
173 | + }, |
174 | + { |
175 | + "core": 3, |
176 | + "numa_node": 0, |
177 | + "threads": [ |
178 | + { |
179 | + "id": 6, |
180 | + "thread": 0, |
181 | + "online": True |
182 | + }, |
183 | + { |
184 | + "id": 7, |
185 | + "thread": 1, |
186 | + "online": True |
187 | + } |
188 | + ], |
189 | + "frequency": 3247 |
190 | } |
191 | ], |
192 | - "frequency": 3247, |
193 | + "frequency": 3231, |
194 | "frequency_minimum": 800, |
195 | "frequency_turbo": 3400 |
196 | } |
197 | ], |
198 | "total": 8 |
199 | + }, |
200 | + "memory": { |
201 | + "nodes": [ |
202 | + { |
203 | + "numa_node": 0, |
204 | + "hugepages_used": 0, |
205 | + "hugepages_total": 0, |
206 | + "used": 16430092288, |
207 | + "total": 16691519488 |
208 | + } |
209 | + ], |
210 | + "hugepages_total": 0, |
211 | + "hugepages_used": 0, |
212 | + "hugepages_size": 2097152, |
213 | + "used": 12116492288, |
214 | + "total": 16691519488 |
215 | + }, |
216 | + "gpu": { |
217 | + "cards": [ |
218 | + { |
219 | + "driver": "i915", |
220 | + "driver_version": "4.15.0-58-generic", |
221 | + "drm": { |
222 | + "id": 0, |
223 | + "card_name": "card0", |
224 | + "card_device": "226:0", |
225 | + "control_name": "controlD64", |
226 | + "control_device": "226:0", |
227 | + "render_name": "renderD128", |
228 | + "render_device": "226:128" |
229 | + }, |
230 | + "numa_node": 0, |
231 | + "pci_address": "0000:00:02.0", |
232 | + "vendor": "Intel Corporation", |
233 | + "vendor_id": "8086", |
234 | + "product": ( |
235 | + "4th Gen Core Processor Integrated Graphics Controller"), |
236 | + "product_id": "0416" |
237 | + } |
238 | + ], |
239 | + "total": 1 |
240 | + }, |
241 | + "network": { |
242 | + "cards": [ |
243 | + { |
244 | + "driver": "e1000e", |
245 | + "driver_version": "3.2.6-k", |
246 | + "ports": [ |
247 | + { |
248 | + "id": "enp0s25", |
249 | + "address": "54:ee:75:13:aa:52", |
250 | + "port": 0, |
251 | + "protocol": "ethernet", |
252 | + "supported_modes": [ |
253 | + "10baseT/Half", |
254 | + "10baseT/Full", |
255 | + "100baseT/Half", |
256 | + "100baseT/Full", |
257 | + "1000baseT/Full" |
258 | + ], |
259 | + "supported_ports": [ |
260 | + "twisted pair" |
261 | + ], |
262 | + "port_type": "twisted pair", |
263 | + "transceiver_type": "internal", |
264 | + "auto_negotiation": True, |
265 | + "link_detected": False |
266 | + } |
267 | + ], |
268 | + "numa_node": 0, |
269 | + "pci_address": "0000:00:19.0", |
270 | + "vendor": "Intel Corporation", |
271 | + "vendor_id": "8086", |
272 | + "product": "Ethernet Connection I217-LM", |
273 | + "product_id": "153a" |
274 | + }, |
275 | + { |
276 | + "driver": "iwlwifi", |
277 | + "driver_version": "4.15.0-58-generic", |
278 | + "ports": [ |
279 | + { |
280 | + "id": "wlp4s0", |
281 | + "address": "e8:2a:ea:22:0b:d2", |
282 | + "port": 0, |
283 | + "protocol": "ethernet", |
284 | + "auto_negotiation": False, |
285 | + "link_detected": True |
286 | + } |
287 | + ], |
288 | + "numa_node": 0, |
289 | + "pci_address": "0000:04:00.0", |
290 | + "vendor": "Intel Corporation", |
291 | + "vendor_id": "8086", |
292 | + "product": "Wireless 7260", |
293 | + "product_id": "08b2" |
294 | + } |
295 | + ], |
296 | + "total": 2 |
297 | + }, |
298 | + "storage": { |
299 | + "disks": [ |
300 | + { |
301 | + "id": "sda", |
302 | + "device": "8:0", |
303 | + "model": "Crucial_CT512M55", |
304 | + "type": "scsi", |
305 | + "read_only": False, |
306 | + "size": 512110190592, |
307 | + "removable": False, |
308 | + "numa_node": 0, |
309 | + "partitions": [ |
310 | + { |
311 | + "id": "sda1", |
312 | + "device": "8:1", |
313 | + "read_only": False, |
314 | + "size": 536870912, |
315 | + "partition": 1 |
316 | + }, |
317 | + { |
318 | + "id": "sda2", |
319 | + "device": "8:2", |
320 | + "read_only": False, |
321 | + "size": 511705088, |
322 | + "partition": 2 |
323 | + }, |
324 | + { |
325 | + "id": "sda3", |
326 | + "device": "8:3", |
327 | + "read_only": False, |
328 | + "size": 511060213760, |
329 | + "partition": 3 |
330 | + } |
331 | + ] |
332 | + }, |
333 | + { |
334 | + "id": "sr0", |
335 | + "device": "11:0", |
336 | + "model": "DVD-RAM UJ8E2", |
337 | + "type": "scsi", |
338 | + "read_only": False, |
339 | + "size": 1073741312, |
340 | + "removable": True, |
341 | + "numa_node": 0, |
342 | + "partitions": [] |
343 | + } |
344 | + ], |
345 | + "total": 5 |
346 | } |
347 | } |
348 | |
349 | @@ -726,43 +924,6 @@ class TestUpdateHardwareDetails(MAASServerTestCase): |
350 | |
351 | doctest_flags = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
352 | |
353 | - def test_hardware_updates_memory(self): |
354 | - node = factory.make_Node() |
355 | - xmlbytes = dedent("""\ |
356 | - <node id="memory"> |
357 | - <size units="bytes">4294967296</size> |
358 | - </node> |
359 | - """).encode("utf-8") |
360 | - update_hardware_details(node, xmlbytes, 0) |
361 | - node = reload_object(node) |
362 | - self.assertEqual(4096, node.memory) |
363 | - |
364 | - def test_hardware_updates_memory_lenovo(self): |
365 | - node = factory.make_Node() |
366 | - xmlbytes = dedent("""\ |
367 | - <node> |
368 | - <node id="memory:0" class="memory"> |
369 | - <node id="bank:0" class="memory" handle="DMI:002D"> |
370 | - <size units="bytes">4294967296</size> |
371 | - </node> |
372 | - <node id="bank:1" class="memory" handle="DMI:002E"> |
373 | - <size units="bytes">3221225472</size> |
374 | - </node> |
375 | - </node> |
376 | - <node id="memory:1" class="memory"> |
377 | - <node id="bank:0" class="memory" handle="DMI:002F"> |
378 | - <size units="bytes">536870912</size> |
379 | - </node> |
380 | - </node> |
381 | - <node id="memory:2" class="memory"></node> |
382 | - </node> |
383 | - """).encode("utf-8") |
384 | - update_hardware_details(node, xmlbytes, 0) |
385 | - node = reload_object(node) |
386 | - mega = 2 ** 20 |
387 | - expected = (4294967296 + 3221225472 + 536879812) // mega |
388 | - self.assertEqual(expected, node.memory) |
389 | - |
390 | def test_hardware_updates_hardware_uuid(self): |
391 | node = factory.make_Node() |
392 | hardware_uuid = factory.make_UUID() |
393 | @@ -882,53 +1043,54 @@ class TestUpdateHardwareDetails(MAASServerTestCase): |
394 | self.assertIsNone(NodeMetadata.objects.get(node=node, key=key)) |
395 | |
396 | |
397 | -class TestLXDUpdateCPUDetails(MAASServerTestCase): |
398 | +class TestProcessLXDResults(MAASServerTestCase): |
399 | |
400 | - doctest_flags = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
401 | + def test__updates_memory(self): |
402 | + node = factory.make_Node() |
403 | + node.memory = random.randint(4096, 8192) |
404 | + node.save() |
405 | + |
406 | + process_lxd_results( |
407 | + node, json.dumps(SAMPLE_LXD_JSON).encode('utf-8'), 0) |
408 | + node = reload_object(node) |
409 | + self.assertEqual(round(16691519488 / 1024 / 1024), node.memory) |
410 | |
411 | - def test__speed_in_name(self): |
412 | + def test__updates_model_and_cpu_speed_from_name(self): |
413 | node = factory.make_Node() |
414 | - node.cpu_count = 2 |
415 | node.cpu_speed = 9999 |
416 | node.save() |
417 | |
418 | - lxd_update_cpu_details(node, SAMPLE_JSON_CPUINFO) |
419 | + process_lxd_results( |
420 | + node, json.dumps(SAMPLE_LXD_JSON).encode('utf-8'), 0) |
421 | node = reload_object(node) |
422 | - self.assertEqual(8, node.cpu_count) |
423 | self.assertEqual(2400, node.cpu_speed) |
424 | nmd = NodeMetadata.objects.get(node=node, key='cpu_model') |
425 | self.assertEqual('Intel(R) Core(TM) i7-4700MQ CPU', nmd.value) |
426 | |
427 | - def test__max_speed(self): |
428 | + def test__updates_cpu_speed_with_max_frequency_when_not_in_name(self): |
429 | node = factory.make_Node() |
430 | - node.cpu_count = 2 |
431 | node.cpu_speed = 9999 |
432 | node.save() |
433 | |
434 | - SAMPLE_JSON_CPUINFO_NO_SPEED_IN_NAME = deepcopy(SAMPLE_JSON_CPUINFO) |
435 | - SAMPLE_JSON_CPUINFO_NO_SPEED_IN_NAME['cpu']['sockets'][0]['name'] = ( |
436 | + NO_SPEED_IN_NAME = deepcopy(SAMPLE_LXD_JSON) |
437 | + NO_SPEED_IN_NAME['cpu']['sockets'][0]['name'] = ( |
438 | 'Intel(R) Core(TM) i7-4700MQ CPU') |
439 | - lxd_update_cpu_details(node, SAMPLE_JSON_CPUINFO_NO_SPEED_IN_NAME) |
440 | + process_lxd_results( |
441 | + node, json.dumps(NO_SPEED_IN_NAME).encode('utf-8'), 0) |
442 | node = reload_object(node) |
443 | - self.assertEqual(8, node.cpu_count) |
444 | self.assertEqual(3400, node.cpu_speed) |
445 | - nmd = NodeMetadata.objects.get(node=node, key='cpu_model') |
446 | - self.assertEqual('Intel(R) Core(TM) i7-4700MQ CPU', nmd.value) |
447 | |
448 | - def test__current_speed(self): |
449 | + def test__updates_cpu_speed_with_current_frequency_when_not_in_name(self): |
450 | node = factory.make_Node() |
451 | - node.cpu_count = 2 |
452 | node.cpu_speed = 9999 |
453 | node.save() |
454 | |
455 | - SAMPLE_JSON_CPUINFO_NO_NAME_OR_MAX_FREQ = deepcopy(SAMPLE_JSON_CPUINFO) |
456 | - del SAMPLE_JSON_CPUINFO_NO_NAME_OR_MAX_FREQ[ |
457 | - 'cpu']['sockets'][0]['name'] |
458 | - del SAMPLE_JSON_CPUINFO_NO_NAME_OR_MAX_FREQ[ |
459 | - 'cpu']['sockets'][0]['frequency_turbo'] |
460 | - lxd_update_cpu_details(node, SAMPLE_JSON_CPUINFO_NO_NAME_OR_MAX_FREQ) |
461 | + NO_NAME_OR_MAX_FREQ = deepcopy(SAMPLE_LXD_JSON) |
462 | + del NO_NAME_OR_MAX_FREQ['cpu']['sockets'][0]['name'] |
463 | + del NO_NAME_OR_MAX_FREQ['cpu']['sockets'][0]['frequency_turbo'] |
464 | + process_lxd_results( |
465 | + node, json.dumps(NO_NAME_OR_MAX_FREQ).encode('utf-8'), 0) |
466 | node = reload_object(node) |
467 | - self.assertEqual(8, node.cpu_count) |
468 | self.assertEqual(3200, node.cpu_speed) |
469 | |
470 |
UNIT TESTS ng-hooks- memory lp:~newell-jensen/maas/+git/maas into -b master lp:~maas-committers/maas
-b lxd-commissioni
STATUS: FAILED maas-ci- jenkins. internal: 8080/job/ maas/job/ branch- tester/ 6371/console c50c200870ffa91 4d6e5a51fb
LOG: http://
COMMIT: c9db21b36a34b48