From 319322a735753064fdc2d31f1d683cd534a3c6cd Mon Sep 17 00:00:00 2001
From: Bernardo Dal Seno <bdalseno@google.com>
Date: Mon, 10 Dec 2012 23:27:03 +0100
Subject: [PATCH] Call node_info RPCs with the exclusive_storage flag

The flag is read from the configuration and passed to the RPC.

Signed-off-by: Bernardo Dal Seno <bdalseno@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>
---
 htools/Ganeti/Query/Node.hs | 12 +++++++++++-
 htools/Ganeti/Rpc.hs        |  9 +++++++--
 lib/cmdlib.py               |  6 ++++--
 lib/masterd/iallocator.py   |  3 ++-
 lib/rpc.py                  | 25 +++++++++++++++++++++++++
 5 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/htools/Ganeti/Query/Node.hs b/htools/Ganeti/Query/Node.hs
index d324c39f6..de6ea1a93 100644
--- a/htools/Ganeti/Query/Node.hs
+++ b/htools/Ganeti/Query/Node.hs
@@ -223,4 +223,14 @@ maybeCollectLiveData False _ nodes =
 maybeCollectLiveData True cfg nodes = do
   let vgs = [clusterVolumeGroupName $ configCluster cfg]
       hvs = [getDefaultHypervisor cfg]
-  executeRpcCall nodes (RpcCallNodeInfo vgs hvs)
+      step n (bn, gn, em) =
+        let ndp' = getNodeNdParams cfg n
+        in case ndp' of
+             Just ndp -> (bn, n : gn,
+                          (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))
+  -- 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/htools/Ganeti/Rpc.hs b/htools/Ganeti/Rpc.hs
index c0d0cb6bb..284bb5ef7 100644
--- a/htools/Ganeti/Rpc.hs
+++ b/htools/Ganeti/Rpc.hs
@@ -70,6 +70,8 @@ module Ganeti.Rpc
   ) where
 
 import Control.Arrow (second)
+import qualified Data.Map as Map
+import Data.Maybe (fromMaybe)
 import qualified Text.JSON as J
 import Text.JSON.Pretty (pp_value)
 
@@ -343,6 +345,7 @@ instance Rpc RpcCallInstanceList RpcResultInstanceList where
 $(buildObject "RpcCallNodeInfo" "rpcCallNodeInfo"
   [ simpleField "volume_groups" [t| [String] |]
   , simpleField "hypervisors" [t| [Hypervisor] |]
+  , simpleField "exclusive_storage" [t| Map.Map String Bool |]
   ])
 
 $(buildObject "VgInfo" "vgInfo"
@@ -371,10 +374,12 @@ instance RpcCall RpcCallNodeInfo where
   rpcCallName _          = "node_info"
   rpcCallTimeout _       = rpcTimeoutToRaw Urgent
   rpcCallAcceptOffline _ = False
-  rpcCallData _ call     = J.encode
+  rpcCallData n call     = J.encode
     ( rpcCallNodeInfoVolumeGroups call
     , rpcCallNodeInfoHypervisors call
-    , False
+    , fromMaybe (error $ "Programmer error: missing parameter for node named "
+                         ++ nodeName n)
+                $ Map.lookup (nodeName n) (rpcCallNodeInfoExclusiveStorage call)
     )
 
 instance Rpc RpcCallNodeInfo RpcResultNodeInfo where
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index eb9cb4571..5b963c5fa 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -5288,8 +5288,9 @@ class _NodeQuery(_QueryBase):
       # filter out non-vm_capable nodes
       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()],
-                                        [lu.cfg.GetHypervisorType()], False)
+                                        [lu.cfg.GetHypervisorType()], es_flags)
       live_data = dict((name, rpc.MakeLegacyNodeInfo(nresult.payload))
                        for (name, nresult) in node_data.items()
                        if not nresult.fail_msg and nresult.payload)
@@ -6888,7 +6889,8 @@ def _CheckNodesFreeDiskOnVG(lu, nodenames, vg, requested):
       or we cannot check the node
 
   """
-  nodeinfo = lu.rpc.call_node_info(nodenames, [vg], None, False)
+  es_flags = rpc.GetExclusiveStorageForNodeNames(lu.cfg, nodenames)
+  nodeinfo = lu.rpc.call_node_info(nodenames, [vg], None, es_flags)
   for node in nodenames:
     info = nodeinfo[node]
     info.Raise("Cannot get current information from node %s" % node,
diff --git a/lib/masterd/iallocator.py b/lib/masterd/iallocator.py
index 5f339b699..48cbd55ce 100644
--- a/lib/masterd/iallocator.py
+++ b/lib/masterd/iallocator.py
@@ -430,8 +430,9 @@ class IAllocator(object):
       hypervisor_name = cluster_info.primary_hypervisor
       node_whitelist = None
 
+    es_flags = rpc.GetExclusiveStorageForNodeNames(cfg, node_list)
     node_data = self.rpc.call_node_info(node_list, [cfg.GetVGName()],
-                                        [hypervisor_name], False)
+                                        [hypervisor_name], es_flags)
     node_iinfo = \
       self.rpc.call_all_instances_info(node_list,
                                        cluster_info.enabled_hypervisors)
diff --git a/lib/rpc.py b/lib/rpc.py
index b72ac23e9..0c4bad079 100644
--- a/lib/rpc.py
+++ b/lib/rpc.py
@@ -631,6 +631,31 @@ def AnnotateDiskParams(template, disks, disk_params):
   return [annotation_fn(disk.Copy(), ld_params) for disk in disks]
 
 
+def _GetESFlag(cfg, nodename):
+  ni = cfg.GetNodeInfo(nodename)
+  if ni is None:
+    raise errors.OpPrereqError("Invalid node name %s" % nodename,
+                               errors.ECODE_NOENT)
+  return cfg.GetNdParams(ni)[constants.ND_EXCLUSIVE_STORAGE]
+
+
+def GetExclusiveStorageForNodeNames(cfg, nodelist):
+  """Return the exclusive storage flag for all the given nodes.
+
+  @type cfg: L{config.ConfigWriter}
+  @param cfg: cluster configuration
+  @type nodelist: list or tuple
+  @param nodelist: node names for which to read the flag
+  @rtype: dict
+  @return: mapping from node names to exclusive storage flags
+  @raise errors.OpPrereqError: if any given node name has no corresponding node
+
+  """
+  getflag = lambda n: _GetESFlag(cfg, n)
+  flags = map(getflag, nodelist)
+  return dict(zip(nodelist, flags))
+
+
 #: Generic encoders
 _ENCODERS = {
   rpc_defs.ED_OBJECT_DICT: _ObjectToDict,
-- 
GitLab