commit 11aa3ca5078eed640e5037276cd387f3c3b63f43
Author: Helga Velroyen <helgav@google.com>
Date:   Fri Jun 21 13:54:06 2013 +0200

    iallocator: extract storage info directly from node info
    
    So far, the iallocator made a node info RPC call, converted
    the result into a legacy node info format and then extracted
    the storage information from that. This patch removes the
    middle step of this procedure, skipping the legacy node info
    usage.
    
    In later patches, we will completely eliminate the need for
    the legacy node info in iallocator.
    
    Signed-off-by: Helga Velroyen <helgav@google.com>
    Reviewed-by: Thomas Thrainer <thomasth@google.com>

diff --git a/lib/masterd/iallocator.py b/lib/masterd/iallocator.py
index c8fc127..8b02f1c 100644
--- a/lib/masterd/iallocator.py
+++ b/lib/masterd/iallocator.py
@@ -544,30 +544,37 @@ class IAllocator(object):
     return value
 
   @staticmethod
-  def _ComputeStorageData(node_info, node_name, has_lvm):
-    """Extract storage data from the node info.
+  def _ComputeStorageDataFromNodeInfo(node_info, node_name, has_lvm):
+    """Extract storage data from node info (_not_ legacy node info).
 
-    @type node_info: see result of RPC call 'node info'
-    @param node_info: the node's live information
+    @type node_info: see result of the RPC call node info
+    @param node_info: the result of the RPC call node info
     @type node_name: string
     @param node_name: the node's name
     @type has_lvm: boolean
-    @param has_lvm: whether or not lvm storage info was requested
+    @param has_lvm: whether or not LVM storage information is requested
     @rtype: 4-tuple of integers
     @return: tuple of storage info (total_disk, free_disk, total_spindles,
        free_spindles)
 
     """
+    (_, space_info, _) = node_info
     # TODO: replace this with proper storage reporting
     if has_lvm:
-      total_disk = IAllocator._GetAttributeFromNodeData(node_info, node_name,
-                                                        "storage_size")
-      free_disk = IAllocator._GetAttributeFromNodeData(node_info, node_name,
-                                                       "storage_free")
-      total_spindles = IAllocator._GetAttributeFromNodeData(
-          node_info, node_name, "spindles_total")
-      free_spindles = IAllocator._GetAttributeFromNodeData(
-          node_info, node_name, "spindles_free")
+      lvm_vg_info = utils.storage.LookupSpaceInfoByStorageType(
+         space_info, constants.ST_LVM_VG)
+      if not lvm_vg_info:
+        raise errors.OpExecError("Node '%s' didn't return LVM vg space info."
+                                 % (node_name))
+      total_disk = lvm_vg_info["storage_size"]
+      free_disk = lvm_vg_info["storage_free"]
+      lvm_pv_info = utils.storage.LookupSpaceInfoByStorageType(
+         space_info, constants.ST_LVM_PV)
+      if not lvm_vg_info:
+        raise errors.OpExecError("Node '%s' didn't return LVM pv space info."
+                                 % (node_name))
+      total_spindles = lvm_pv_info["storage_size"]
+      free_spindles = lvm_pv_info["storage_free"]
     else:
       # we didn't even ask the node for VG status, so use zeros
       total_disk = free_disk = 0
@@ -615,7 +622,8 @@ class IAllocator(object):
               i_p_up_mem += beinfo[constants.BE_MAXMEM]
 
         (total_disk, free_disk, total_spindles, free_spindles) = \
-            self._ComputeStorageData(remote_info, ninfo.name, has_lvm)
+            self._ComputeStorageDataFromNodeInfo(nresult.payload, ninfo.name,
+                                                 has_lvm)
 
         # compute memory used by instances
         pnr_dyn = {
diff --git a/test/py/ganeti.masterd.iallocator_unittest.py b/test/py/ganeti.masterd.iallocator_unittest.py
index e77c8a1..ce23ea6 100755
--- a/test/py/ganeti.masterd.iallocator_unittest.py
+++ b/test/py/ganeti.masterd.iallocator_unittest.py
@@ -22,14 +22,12 @@
 """Script for testing ganeti.masterd.iallocator"""
 
 import unittest
-import mock
 
 from ganeti import compat
 from ganeti import constants
 from ganeti import errors
 from ganeti import objects
 from ganeti import ht
-from ganeti import rpc
 from ganeti.masterd import iallocator
 
 import testutils
@@ -200,28 +198,26 @@ class TestProcessStorageInfo(unittest.TestCase):
                        "storage_size": 44}]
     self.node_info = ("123", self.space_info, ({},))
 
-  def testComputeStorageDataLvm(self):
-    has_lvm = True
-    node_name = "mynode"
-    remote_info = rpc.MakeLegacyNodeInfo(self.node_info,
-                                         require_vg_info=has_lvm)
-    (total_disk, free_disk, total_spindles, free_spindles) = \
-      iallocator.IAllocator._ComputeStorageData(remote_info, node_name, has_lvm)
-    self.assertEqual(self.free_storage_lvm, free_disk)
-    self.assertEqual(self.total_storage_lvm, total_disk)
-
-  def testComputeStorageDataDefault(self):
+  def testComputeStorageDataFromNodeInfoDefault(self):
     has_lvm = False
     node_name = "mynode"
-    remote_info = rpc.MakeLegacyNodeInfo(self.node_info,
-                                         require_vg_info=has_lvm)
     (total_disk, free_disk, total_spindles, free_spindles) = \
-      iallocator.IAllocator._ComputeStorageData(remote_info, node_name, has_lvm)
+        iallocator.IAllocator._ComputeStorageDataFromNodeInfo(
+            self.node_info, node_name, has_lvm)
     # FIXME: right now, iallocator ignores anything else than LVM, adjust
     # this test once that arbitrary storage is supported
     self.assertEqual(0, free_disk)
     self.assertEqual(0, total_disk)
 
+  def testComputeStorageDataFromNodeInfoLvm(self):
+    has_lvm = True
+    node_name = "mynode"
+    (total_disk, free_disk, total_spindles, free_spindles) = \
+        iallocator.IAllocator._ComputeStorageDataFromNodeInfo(
+            self.node_info, node_name, has_lvm)
+    self.assertEqual(self.free_storage_lvm, free_disk)
+    self.assertEqual(self.total_storage_lvm, total_disk)
+
 
 if __name__ == "__main__":
   testutils.GanetiTestProgram()
