diff --git a/htools/Ganeti/Query/Node.hs b/htools/Ganeti/Query/Node.hs index d324c39f6b254c3d192ba6725a6643b8cad78753..de6ea1a93d39f0ce9c68f8dece20cc47ff6fe791 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 c0d0cb6bbfe905bbb856b33c82e55c550bc99273..284bb5ef75667a60da1f7fb11e200ac3c978c69e 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 eb9cb45717165aa81ec84283b18032ae745365a1..5b963c5fadd1a91ef3694e76e974e1b173a54a98 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 5f339b699ae0bd08b7c1c34ed809d98508e1ea9a..48cbd55ceef3c9b316f957477621ada1c5625217 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 b72ac23e98bb911e1ca43651c2dd5bd6c02cff87..0c4bad0792c7117c1c17879392f540e02042aa6a 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,