def _CollectDiskInfo(self, node_uuids, node_image, instanceinfo):
    node_disks = {}
    node_disks_dev_inst_only = {}
    diskless_instances = set()
    nodisk_instances = set()

    for nuuid in node_uuids:
      node_inst_uuids = list(itertools.chain(node_image[nuuid].pinst,
                                             node_image[nuuid].sinst))
      diskless_instances.update(uuid for uuid in node_inst_uuids
                                if not instanceinfo[uuid].disks)
      disks = [(inst_uuid, disk)
               for inst_uuid in node_inst_uuids
               for disk in self.cfg.GetInstanceDisks(inst_uuid)]

      if not disks:
        nodisk_instances.update(uuid for uuid in node_inst_uuids
                                if instanceinfo[uuid].disks)
        # No need to collect data
        continue

      node_disks[nuuid] = disks

      # _AnnotateDiskParams makes already copies of the disks
      dev_inst_only = []
      for (inst_uuid, dev) in disks:
        (anno_disk,) = AnnotateDiskParams(instanceinfo[inst_uuid], [dev],
                                          self.cfg)
        dev_inst_only.append((anno_disk, instanceinfo[inst_uuid]))

      node_disks_dev_inst_only[nuuid] = dev_inst_only

    assert len(node_disks) == len(node_disks_dev_inst_only)

    # Collect data from all nodes with disks
    result = self.rpc.call_blockdev_getmirrorstatus_multi(
               node_disks.keys(), node_disks_dev_inst_only)

    assert len(result) == len(node_disks)

    instdisk = {}

    for (nuuid, nres) in result.items():
      node = self.cfg.GetNodeInfo(nuuid)
      disks = node_disks[node.uuid]

      if nres.offline:
        # No data from this node
        data = len(disks) * [(False, "node offline")]
      else:
        msg = nres.fail_msg
        self._ErrorIf(msg, constants.CV_ENODERPC, node.name,
                      "while getting disk information: %s", msg)
        if msg:
          # No data from this node
          data = len(disks) * [(False, msg)]
        else:
          data = []
          for idx, i in enumerate(nres.payload):
            if isinstance(i, (tuple, list)) and len(i) == 2:
              data.append(i)
            else:
              logging.warning("Invalid result from node %s, entry %d: %s",
                              node.name, idx, i)
              data.append((False, "Invalid result from the remote node"))

      for ((inst_uuid, _), status) in zip(disks, data):
        instdisk.setdefault(inst_uuid, {}).setdefault(node.uuid, []) \
          .append(status)

    # Add empty entries for diskless instances.
    for inst_uuid in diskless_instances:
      assert inst_uuid not in instdisk
      instdisk[inst_uuid] = {}
    # ...and disk-full instances that happen to have no disks
    for inst_uuid in nodisk_instances:
      assert inst_uuid not in instdisk
      instdisk[inst_uuid] = {}

    assert compat.all(len(statuses) == len(instanceinfo[inst].disks) and
                      len(nuuids) <= len(
                        self.cfg.GetInstanceNodes(instanceinfo[inst].uuid)) and
                      compat.all(isinstance(s, (tuple, list)) and
                                 len(s) == 2 for s in statuses)
                      for inst, nuuids in instdisk.items()
                      for nuuid, statuses in nuuids.items())
    if __debug__:
      instdisk_keys = set(instdisk)
      instanceinfo_keys = set(instanceinfo)
      assert instdisk_keys == instanceinfo_keys, \
        ("instdisk keys (%s) do not match instanceinfo keys (%s)" %
         (instdisk_keys, instanceinfo_keys))

    return instdisk
Gets per-disk status information for all instances.
dataset/ETHPy150Open ganeti/ganeti/lib/cmdlib/cluster/verify.py/LUClusterVerifyGroup._CollectDiskInfo