This replaces the field 'vg_names' in the RPC call of 'node info' by
'storage_units'. Storage units are a list of tuples <storage_type,key>
and an abstraction of the old vg_names. It will be used to report
storage space for more than just lvm volume groups. What the 'key' is
depends on the storage type. For storage type lvm-vg, the key is the
volume group name. To keep backward compatibility, all functions that
use the old vg_names, convert them to a list where every volume group
is mapped to a tuple [('lvm-vg',volume_group)] before making the call.

Signed-off-by: Helga Velroyen <[email protected]>
---
 lib/backend.py           | 37 ++++++++++++++++++++++++++++++++-----
 lib/cmdlib.py            | 15 ++++++++++++---
 lib/rpc_defs.py          |  5 +++--
 lib/server/noded.py      |  4 ++--
 src/Ganeti/Query/Node.hs |  5 ++++-
 src/Ganeti/Rpc.hs        |  4 ++--
 6 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/lib/backend.py b/lib/backend.py
index dc13b02..7930089 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -620,11 +620,13 @@ def _GetNamedNodeInfo(names, fn):
     return map(fn, names)
 
 
-def GetNodeInfo(vg_names, hv_names, excl_stor):
+def GetNodeInfo(storage_units, hv_names, excl_stor):
   """Gives back a hash with different information about the node.
 
-  @type vg_names: list of string
-  @param vg_names: Names of the volume groups to ask for disk space information
+  @type storage_units: list of pairs (string, string)
+  @param storage_units: List of pairs of storage units and storage unit
+                        identifiers to ask for disk space information. In
+                        case of lvm-vg, the identifier is the vg name.
   @type hv_names: list of string
   @param hv_names: Names of the hypervisors to ask for node information
   @type excl_stor: boolean
@@ -634,11 +636,36 @@ def GetNodeInfo(vg_names, hv_names, excl_stor):
     information
 
   """
+  # TODO: This implicitely assumes that only lvm storage units are present
   bootid = utils.ReadFile(_BOOT_ID_PATH, size=128).rstrip("\n")
-  vg_info = _GetNamedNodeInfo(vg_names, (lambda vg: _GetVgInfo(vg, excl_stor)))
+  storage_info = _GetNamedNodeInfo(
+    storage_units,
+    (lambda storage_unit: _GetVgInfo(storage_unit[1], excl_stor)))
   hv_info = _GetNamedNodeInfo(hv_names, _GetHvInfo)
 
-  return (bootid, vg_info, hv_info)
+  return (bootid, storage_info, hv_info)
+
+
+# FIXME: implement storage reporting for all missing storage types.
+_STORAGE_TYPE_INFO_FN = {
+  constants.ST_BLOCK: _GetVgInfo,
+  constants.ST_DISKLESS: _GetVgInfo,
+  constants.ST_EXT: _GetVgInfo,
+  constants.ST_FILE: _GetVgInfo,
+  constants.ST_LVM_VG: _GetVgInfo,
+  constants.ST_RADOS: _GetVgInfo,
+}
+
+
+def _GetStorageInfoFunction(storage_type, *args):
+  """Looks up the correct function to calculate free and total storage for the
+  given storage type.
+
+  @type storage_type: string
+  @param storage_type: the storage type for which the storage shall be 
reported.
+
+  """
+  return _STORAGE_TYPE_INFO_FN[storage_type](*args)
 
 
 def _CheckExclusivePvs(pvi_list):
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 4dfd668..296372b 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -5670,7 +5670,10 @@ class _NodeQuery(_QueryBase):
       toquery_nodes = [name for name in nodenames if all_info[name].vm_capable]
 
       es_flags = rpc.GetExclusiveStorageForNodeNames(lu.cfg, toquery_nodes)
-      node_data = lu.rpc.call_node_info(toquery_nodes, [lu.cfg.GetVGName()],
+      # FIXME: This currently maps everything to lvm, this should be more
+      # flexible
+      storage_units = [(constants.ST_LVM_VG, lu.cfg.GetVGName())]
+      node_data = lu.rpc.call_node_info(toquery_nodes, storage_units,
                                         [lu.cfg.GetHypervisorType()], es_flags)
       live_data = dict((name, rpc.MakeLegacyNodeInfo(nresult.payload))
                        for (name, nresult) in node_data.items()
@@ -7301,7 +7304,10 @@ def _CheckNodesFreeDiskOnVG(lu, nodenames, vg, 
requested):
 
   """
   es_flags = rpc.GetExclusiveStorageForNodeNames(lu.cfg, nodenames)
-  nodeinfo = lu.rpc.call_node_info(nodenames, [vg], None, es_flags)
+  # FIXME: This maps everything to storage type 'lvm-vg' to maintain
+  # the current functionality. Refactor to make it more flexible.
+  nodeinfo = lu.rpc.call_node_info(nodenames, [(constants.ST_LVM_VG, vg)], 
None,
+                                   es_flags)
   for node in nodenames:
     info = nodeinfo[node]
     info.Raise("Cannot get current information from node %s" % node,
@@ -11004,10 +11010,13 @@ class LUInstanceCreate(LogicalUnit):
       elif self.op.disk_template == constants.DT_EXT:
         # FIXME: Function that checks prereqs if needed
         pass
-      else:
+      elif self.op.disk_template in utils.GetLvmDiskTemplates():
         # Check lv size requirements, if not adopting
         req_sizes = _ComputeDiskSizePerVG(self.op.disk_template, self.disks)
         _CheckNodesFreeDiskPerVG(self, nodenames, req_sizes)
+      else:
+        # FIXME: add checks for other, non-adopting, non-lvm disk templates
+        pass
 
     elif self.op.disk_template == constants.DT_PLAIN: # Check the adoption data
       all_lvs = set(["%s/%s" % (disk[constants.IDISK_VG],
diff --git a/lib/rpc_defs.py b/lib/rpc_defs.py
index c6f9a09..360c19e 100644
--- a/lib/rpc_defs.py
+++ b/lib/rpc_defs.py
@@ -464,8 +464,9 @@ _NODE_CALLS = [
     ("address", None, "IP address"),
     ], None, None, "Checks if a node has the given IP address"),
   ("node_info", MULTI, None, constants.RPC_TMO_URGENT, [
-    ("vg_names", None,
-     "Names of the volume groups to ask for disk space information"),
+    ("storage_units", None,
+     "List of tuples '<storage_type>,<key>' to ask for disk space"
+     " information"),
     ("hv_names", None,
      "Names of the hypervisors to ask for node information"),
     ("exclusive_storage", None,
diff --git a/lib/server/noded.py b/lib/server/noded.py
index a7d7a88..0aff6c1 100644
--- a/lib/server/noded.py
+++ b/lib/server/noded.py
@@ -720,8 +720,8 @@ class NodeRequestHandler(http.server.HttpServerHandler):
     """Query node information.
 
     """
-    (vg_names, hv_names, excl_stor) = params
-    return backend.GetNodeInfo(vg_names, hv_names, excl_stor)
+    (storage_units, hv_names, excl_stor) = params
+    return backend.GetNodeInfo(storage_units, hv_names, excl_stor)
 
   @staticmethod
   def perspective_etc_hosts_modify(params):
diff --git a/src/Ganeti/Query/Node.hs b/src/Ganeti/Query/Node.hs
index 293ceb7..a8d821f 100644
--- a/src/Ganeti/Query/Node.hs
+++ b/src/Ganeti/Query/Node.hs
@@ -42,6 +42,7 @@ import Ganeti.Rpc
 import Ganeti.Query.Language
 import Ganeti.Query.Common
 import Ganeti.Query.Types
+import qualified Ganeti.Types as T
 import Ganeti.Utils (niceSort)
 
 -- | Runtime is the resulting type for NodeInfo call.
@@ -224,6 +225,7 @@ collectLiveData False _ nodes =
   return $ zip nodes (repeat $ Left (RpcResultError "Live data disabled"))
 collectLiveData True cfg nodes = do
   let vgs = maybeToList . clusterVolumeGroupName $ configCluster cfg
+      storage_units = zip (repeat T.StorageLvmVg) vgs
       hvs = [getDefaultHypervisor cfg]
       step n (bn, gn, em) =
         let ndp' = getNodeNdParams cfg n
@@ -232,7 +234,8 @@ collectLiveData True cfg nodes = do
                           (nodeName n, ndpExclusiveStorage ndp) : em)
              Nothing -> (n : bn, gn, em)
       (bnodes, gnodes, emap) = foldr step ([], [], []) nodes
-  rpcres <- executeRpcCall gnodes (RpcCallNodeInfo vgs hvs (Map.fromList emap))
+  rpcres <- executeRpcCall gnodes (RpcCallNodeInfo storage_units hvs
+    (Map.fromList emap))
   -- FIXME: The order of nodes in the result could be different from the input
   return $ zip bnodes (repeat $ Left (RpcResultError "Broken configuration"))
            ++ rpcres
diff --git a/src/Ganeti/Rpc.hs b/src/Ganeti/Rpc.hs
index 73d22ca..906a3a0 100644
--- a/src/Ganeti/Rpc.hs
+++ b/src/Ganeti/Rpc.hs
@@ -337,7 +337,7 @@ instance Rpc RpcCallInstanceList RpcResultInstanceList where
 -- | NodeInfo
 -- Return node information.
 $(buildObject "RpcCallNodeInfo" "rpcCallNodeInfo"
-  [ simpleField "volume_groups" [t| [String] |]
+  [ simpleField "storage_units" [t| [ (StorageType,String) ] |]
   , simpleField "hypervisors" [t| [Hypervisor] |]
   , simpleField "exclusive_storage" [t| Map.Map String Bool |]
   ])
@@ -369,7 +369,7 @@ instance RpcCall RpcCallNodeInfo where
   rpcCallTimeout _       = rpcTimeoutToRaw Urgent
   rpcCallAcceptOffline _ = False
   rpcCallData n call     = J.encode
-    ( rpcCallNodeInfoVolumeGroups call
+    ( rpcCallNodeInfoStorageUnits call
     , rpcCallNodeInfoHypervisors call
     , fromMaybe (error $ "Programmer error: missing parameter for node named "
                          ++ nodeName n)
-- 
1.8.2.1

Reply via email to