+ def _GetAttributeFromHypervisorNodeData(hv_info, node_name, attr):
+ """Extract an attribute from the hypervisor's node information.
+
+ This is a helper function to extract data from the hypervisor's information
+ about the node, as part of the result of a node_info query.
+
+ @type hv_info: dict of strings
+ @param hv_info: dictionary of node information from the hypervisor
+ @type node_name: string
+ @param node_name: name of the node
+ @type attr: string
+ @param attr: key of the attribute in the hv_info dictionary
+ @rtype: integer
+ @return: the value of the attribute
+ @raises errors.OpExecError: if key not in dictionary or value not
+ integer
+
+ """
+ if attr not in hv_info:
+ raise errors.OpExecError("Node '%s' didn't return attribute"
+ " '%s'" % (node_name, attr))
+ value = hv_info[attr]
+ if not isinstance(value, int):
+ raise errors.OpExecError("Node '%s' returned invalid value"
+ " for '%s': %s" %
+ (node_name, attr, value))
+ return value
+
+ @staticmethod
+ def _ComputeStorageDataFromSpaceInfo(space_info, node_name, has_lvm):
+ """Extract storage data from node info.
+
+ @type space_info: see result of the RPC call node info
+ @param space_info: the storage reporting part of 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 information is requested
+ @rtype: 4-tuple of integers
+ @return: tuple of storage info (total_disk, free_disk, total_spindles,
+ free_spindles)
+
+ """
+ # TODO: replace this with proper storage reporting
+ if has_lvm:
+ 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
+ total_spindles = free_spindles = 0
+ return (total_disk, free_disk, total_spindles, free_spindles)
+
+ @staticmethod
+ def _ComputeInstanceMemory(instance_list, node_instances_info, node_uuid,
+ input_mem_free):
+ """Compute memory used by primary instances.
+
+ @rtype: tuple (int, int, int)
+ @returns: A tuple of three integers: 1. the sum of memory used by primary
+ instances on the node (including the ones that are currently down), 2.
+ the sum of memory used by primary instances of the node that are up, 3.
+ the amount of memory that is free on the node considering the current
+ usage of the instances.
+
+ """
+ i_p_mem = i_p_up_mem = 0
+ mem_free = input_mem_free
+ for iinfo, beinfo in instance_list:
+ if iinfo.primary_node == node_uuid:
+ i_p_mem += beinfo[constants.BE_MAXMEM]
+ if iinfo.name not in node_instances_info[node_uuid].payload:
+ i_used_mem = 0
+ else:
+ i_used_mem = int(node_instances_info[node_uuid]
+ .payload[iinfo.name]["memory"])
+ i_mem_diff = beinfo[constants.BE_MAXMEM] - i_used_mem
+ mem_free -= max(0, i_mem_diff)
+
+ if iinfo.admin_state == constants.ADMINST_UP:
+ i_p_up_mem += beinfo[constants.BE_MAXMEM]
+ return (i_p_mem, i_p_up_mem, mem_free)
+
+ def _ComputeDynamicNodeData(self, node_cfg, node_data, node_iinfo, i_list,