Fix gnt-network info
[ganeti-local] / lib / rpc.py
index e85fa32..5ce530a 100644 (file)
@@ -592,47 +592,68 @@ def _EncodeBlockdevRename(value):
   return [(d.ToDict(), uid) for d, uid in value]
 
 
-def BuildVgInfoQuery(cfg):
-  """Build a query about the default VG for C{node_info}.
+def _AddSpindlesToLegacyNodeInfo(result, space_info):
+  """Extracts the spindle information from the space info and adds
+  it to the result dictionary.
+
+  @type result: dict of strings
+  @param result: dictionary holding the result of the legacy node info
+  @type space_info: list of dicts of strings
+  @param space_info: list, each row holding space information of one storage
+    unit
+  @rtype: None
+  @return: does not return anything, manipulates the C{result} variable
 
-  The result of the RPC can be parsed with L{MakeLegacyNodeInfo}.
+  """
+  lvm_pv_info = utils.storage.LookupSpaceInfoByStorageType(
+      space_info, constants.ST_LVM_PV)
+  if lvm_pv_info:
+    result["spindles_free"] = lvm_pv_info["storage_free"]
+    result["spindles_total"] = lvm_pv_info["storage_size"]
+  else:
+    raise errors.OpExecError("No spindle storage information available.")
 
-  @type cfg: L{config.ConfigWriter}
-  @param cfg: Cluster configuration
-  @rtype: list
-  @return: argument suitable for L{rpc.RpcRunner.call_node_info}
+
+def _AddDefaultStorageInfoToLegacyNodeInfo(result, space_info):
+  """Extracts the storage space information of the default storage type from
+  the space info and adds it to the result dictionary.
+
+  @see: C{_AddSpindlesToLegacyNodeInfo} for parameter information.
 
   """
-  vg_name = cfg.GetVGName()
-  if vg_name:
-    ret = [
-      (constants.ST_LVM_VG, vg_name),
-      (constants.ST_LVM_PV, vg_name),
-      ]
+  # Check if there is at least one row for non-spindle storage info.
+  no_defaults = (len(space_info) < 1) or \
+      (space_info[0]["type"] == constants.ST_LVM_PV and len(space_info) == 1)
+
+  default_space_info = None
+  if no_defaults:
+    logging.warning("No storage info provided for default storage type.")
   else:
-    ret = []
-  return ret
+    default_space_info = space_info[0]
 
+  if default_space_info:
+    result["name"] = default_space_info["name"]
+    result["storage_free"] = default_space_info["storage_free"]
+    result["storage_size"] = default_space_info["storage_size"]
 
-def MakeLegacyNodeInfo(data, require_vg_info=True):
+
+def MakeLegacyNodeInfo(data, require_spindles=False):
   """Formats the data returned by L{rpc.RpcRunner.call_node_info}.
 
   Converts the data into a single dictionary. This is fine for most use cases,
   but some require information from more than one volume group or hypervisor.
 
-  @param require_vg_info: raise an error if the returnd vg_info
-      doesn't have any values
+  @param require_spindles: add spindle storage information to the legacy node
+      info
 
   """
-  (bootid, vgs_info, (hv_info, )) = data
+  (bootid, space_info, (hv_info, )) = data
 
   ret = utils.JoinDisjointDicts(hv_info, {"bootid": bootid})
 
-  if require_vg_info or vgs_info:
-    (vg0_info, vg0_spindles) = vgs_info
-    ret = utils.JoinDisjointDicts(vg0_info, ret)
-    ret["spindles_free"] = vg0_spindles["vg_free"]
-    ret["spindles_total"] = vg0_spindles["vg_size"]
+  if require_spindles:
+    _AddSpindlesToLegacyNodeInfo(ret, space_info)
+  _AddDefaultStorageInfoToLegacyNodeInfo(ret, space_info)
 
   return ret
 
@@ -683,7 +704,7 @@ def AnnotateDiskParams(template, disks, disk_params):
   return [annotation_fn(disk.Copy(), ld_params) for disk in disks]
 
 
-def _GetESFlag(cfg, node_uuid):
+def _GetExclusiveStorageFlag(cfg, node_uuid):
   ni = cfg.GetNodeInfo(node_uuid)
   if ni is None:
     raise errors.OpPrereqError("Invalid node name %s" % node_uuid,
@@ -691,6 +712,31 @@ def _GetESFlag(cfg, node_uuid):
   return cfg.GetNdParams(ni)[constants.ND_EXCLUSIVE_STORAGE]
 
 
+def _AddExclusiveStorageFlagToLvmStorageUnits(storage_units, es_flag):
+  """Adds the exclusive storage flag to lvm units.
+
+  This function creates a copy of the storage_units lists, with the
+  es_flag being added to all lvm storage units.
+
+  @type storage_units: list of pairs (string, string)
+  @param storage_units: list of 'raw' storage units, consisting only of
+    (storage_type, storage_key)
+  @type es_flag: boolean
+  @param es_flag: exclusive storage flag
+  @rtype: list of tuples (string, string, list)
+  @return: list of storage units (storage_type, storage_key, params) with
+    the params containing the es_flag for lvm-vg storage units
+
+  """
+  result = []
+  for (storage_type, storage_key) in storage_units:
+    if storage_type == constants.ST_LVM_VG:
+      result.append((storage_type, storage_key, es_flag))
+    else:
+      result.append((storage_type, storage_key, []))
+  return result
+
+
 def GetExclusiveStorageForNodes(cfg, node_uuids):
   """Return the exclusive storage flag for all the given nodes.
 
@@ -699,16 +745,42 @@ def GetExclusiveStorageForNodes(cfg, node_uuids):
   @type node_uuids: list or tuple
   @param node_uuids: node UUIDs for which to read the flag
   @rtype: dict
-  @return: mapping from node names to exclusive storage flags
+  @return: mapping from node uuids to exclusive storage flags
   @raise errors.OpPrereqError: if any given node name has no corresponding
   node
 
   """
-  getflag = lambda n: _GetESFlag(cfg, n)
+  getflag = lambda n: _GetExclusiveStorageFlag(cfg, n)
   flags = map(getflag, node_uuids)
   return dict(zip(node_uuids, flags))
 
 
+def PrepareStorageUnitsForNodes(cfg, storage_units, node_uuids):
+  """Return the lvm storage unit for all the given nodes.
+
+  Main purpose of this function is to map the exclusive storage flag, which
+  can be different for each node, to the default LVM storage unit.
+
+  @type cfg: L{config.ConfigWriter}
+  @param cfg: cluster configuration
+  @type storage_units: list of pairs (string, string)
+  @param storage_units: list of 'raw' storage units, e.g. pairs of
+    (storage_type, storage_key)
+  @type node_uuids: list or tuple
+  @param node_uuids: node UUIDs for which to read the flag
+  @rtype: dict
+  @return: mapping from node uuids to a list of storage units which include
+    the exclusive storage flag for lvm storage
+  @raise errors.OpPrereqError: if any given node name has no corresponding
+  node
+
+  """
+  getunit = lambda n: _AddExclusiveStorageFlagToLvmStorageUnits(
+      storage_units, _GetExclusiveStorageFlag(cfg, n))
+  flags = map(getunit, node_uuids)
+  return dict(zip(node_uuids, flags))
+
+
 #: Generic encoders
 _ENCODERS = {
   rpc_defs.ED_OBJECT_DICT: _ObjectToDict,
@@ -751,6 +823,7 @@ class RpcRunner(_RpcClientBase,
 
       # Encoders annotating disk parameters
       rpc_defs.ED_DISKS_DICT_DP: self._DisksDictDP,
+      rpc_defs.ED_MULTI_DISKS_DICT_DP: self._MultiDiskDictDP,
       rpc_defs.ED_SINGLE_DISK_DICT_DP: self._SingleDiskDictDP,
 
       # Encoders with special requirements
@@ -849,6 +922,14 @@ class RpcRunner(_RpcClientBase,
             for disk in AnnotateDiskParams(instance.disk_template,
                                            disks, diskparams)]
 
+  def _MultiDiskDictDP(self, disks_insts):
+    """Wrapper for L{AnnotateDiskParams}.
+
+    Supports a list of (disk, instance) tuples.
+    """
+    return [disk for disk_inst in disks_insts
+            for disk in self._DisksDictDP(disk_inst)]
+
   def _SingleDiskDictDP(self, (disk, instance)):
     """Wrapper for L{AnnotateDiskParams}.