launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #12316
[Merge] lp:~gz/maas/populate_mem_and_cpu into lp:maas
Martin Packman has proposed merging lp:~gz/maas/populate_mem_and_cpu into lp:maas with lp:~gz/maas/store_lshw_in_node as a prerequisite.
Requested reviews:
MAAS Maintainers (maas-maintainers)
For more details, see:
https://code.launchpad.net/~gz/maas/populate_mem_and_cpu/+merge/125705
Updates cpu_count and memory fields on node when hardware_details gets set. This is much uglier than anticipated for a variety of reasons, mostly django related.
I tried and failed to get around django to just update the fields, so this does a bunch of extra steps. There may well be a better way, but unfortunatly just accessing sql functions does require raw sql.
Because proper reporting on objects other than node-sets from xpath wasn't implemented till postgres 9.2, I needed the following changes to the queries to do some operations in sql rather than in the query:
(xpath(%s, hardware_details))[1],
"count(//node[@id='core']/node[@class='processor'])"
->
array_length(xpath(%s, hardware_details), 1),
"//node[@id='core']/node[@class='processor']"
(xpath(%s, hardware_details))[1],
"/node[@id='memory']/size[@units='bytes'] div 107374182"
->
(xpath(%s, hardware_details))[1]::text::bigint / 1073741824",
"/node[@id='memory']/size[@units='bytes']/text()"
Fortunately this won't affect tags, which should just be able to use the simpler xpath_exists function.
--
https://code.launchpad.net/~gz/maas/populate_mem_and_cpu/+merge/125705
Your team MAAS Maintainers is requested to review the proposed merge of lp:~gz/maas/populate_mem_and_cpu into lp:maas.
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2012-09-21 13:12:23 +0000
+++ src/maasserver/models/node.py 2012-09-21 13:12:23 +0000
@@ -13,6 +13,7 @@
__all__ = [
"NODE_TRANSITIONS",
"Node",
+ "update_hardware_details",
]
import os
@@ -25,6 +26,9 @@
PermissionDenied,
ValidationError,
)
+from django.db import (
+ connection,
+ )
from django.db.models import (
BooleanField,
CharField,
@@ -318,6 +322,35 @@
return processed_nodes
+
+def update_hardware_details(node, xmlbytes):
+ """Set node hardware_details from lshw output and update related fields
+
+ There are a bunch of suboptimal things here:
+ * Is a function rather than method in hope south migration can reuse.
+ * Doing UPDATE then transaction.commit_unless_managed doesn't work?
+ * Scalar returns from xpath() work in postgres 9.2 or later only.
+ """
+ node.hardware_details = xmlbytes
+ node.save()
+ cursor = connection.cursor()
+ cursor.execute("SELECT"
+ " array_length(xpath(%s, hardware_details), 1) AS count"
+ ", (xpath(%s, hardware_details))[1]::text::bigint / 1073741824 AS mem"
+ " FROM maasserver_node"
+ " WHERE id = %s",
+ [
+ "//node[@id='core']/node[@class='processor']",
+ "//node[@id='memory']/size[@units='bytes']/text()",
+ node.id,
+ ])
+ cpu_count, memory = cursor.fetchone()
+ node.cpu_count = cpu_count or 0
+ node.memory = memory or 0
+ node.save()
+ # TODO: update node-tag links
+
+
class Node(CleanSave, TimestampedModel):
"""A `Node` represents a physical machine used by the MAAS Server.
@@ -635,5 +668,4 @@
def set_hardware_details(self, xmlbytes):
"""Set the `lshw -xml` output"""
- self.hardware_details = xmlbytes
- self.save()
+ update_hardware_details(self, xmlbytes)
=== modified file 'src/metadataserver/tests/test_api.py'
--- src/metadataserver/tests/test_api.py 2012-09-21 13:12:23 +0000
+++ src/metadataserver/tests/test_api.py 2012-09-21 13:12:23 +0000
@@ -503,6 +503,31 @@
node = reload_object(node)
self.assertEqual(xmlbytes, node.hardware_details)
+ def test_signal_stores_lshw_with_cpu_count(self):
+ node = factory.make_node(status=NODE_STATUS.COMMISSIONING)
+ client = self.make_node_client(node=node)
+ xmlbytes = (
+ '<node id="core">'
+ '<node id="cpu:0" class="processor"/>'
+ '<node id="cpu:1" class="processor"/>'
+ '</node>').encode("utf-8")
+ response = self.call_signal(client, files={'01-lshw.out': xmlbytes})
+ self.assertEqual(httplib.OK, response.status_code)
+ node = reload_object(node)
+ self.assertEqual(2, node.cpu_count)
+
+ def test_signal_stores_lshw_with_memory(self):
+ node = factory.make_node(status=NODE_STATUS.COMMISSIONING)
+ client = self.make_node_client(node=node)
+ xmlbytes = (
+ '<node id="memory">'
+ '<size units="bytes">4294967296</size>'
+ '</node>').encode("utf-8")
+ response = self.call_signal(client, files={'01-lshw.out': xmlbytes})
+ self.assertEqual(httplib.OK, response.status_code)
+ node = reload_object(node)
+ self.assertEqual(4, node.memory)
+
def test_api_retrieves_node_metadata_by_mac(self):
mac = factory.make_mac_address()
url = reverse(