Revision b8d26c6e

b/daemons/ganeti-noded
272 272
            for status in backend.BlockdevGetmirrorstatus(disks)]
273 273

  
274 274
  @staticmethod
275
  def perspective_blockdev_getmirrorstatus_multi(params):
276
    """Return the mirror status for a list of disks.
277

  
278
    """
279
    (node_disks, ) = params
280

  
281
    node_name = netutils.Hostname.GetSysName()
282

  
283
    disks = [objects.Disk.FromDict(dsk_s)
284
             for dsk_s in node_disks.get(node_name, [])]
285

  
286
    return [status.ToDict()
287
            for status in backend.BlockdevGetmirrorstatus(disks)]
288

  
289
  @staticmethod
275 290
  def perspective_blockdev_find(params):
276 291
    """Expose the FindBlockDevice functionality for a disk.
277 292

  
b/lib/cmdlib.py
1168 1168
  EINSTANCEDOWN = (TINSTANCE, "EINSTANCEDOWN")
1169 1169
  EINSTANCELAYOUT = (TINSTANCE, "EINSTANCELAYOUT")
1170 1170
  EINSTANCEMISSINGDISK = (TINSTANCE, "EINSTANCEMISSINGDISK")
1171
  EINSTANCEMISSINGDISK = (TINSTANCE, "EINSTANCEMISSINGDISK")
1171
  EINSTANCEFAULTYDISK = (TINSTANCE, "EINSTANCEFAULTYDISK")
1172 1172
  EINSTANCEWRONGNODE = (TINSTANCE, "EINSTANCEWRONGNODE")
1173 1173
  ENODEDRBD = (TNODE, "ENODEDRBD")
1174 1174
  ENODEDRBDHELPER = (TNODE, "ENODEDRBDHELPER")
......
1341 1341
        _ErrorIf(test, self.ENODEHV, node,
1342 1342
                 "hypervisor %s verify failure: '%s'", hv_name, hv_result)
1343 1343

  
1344

  
1345 1344
    test = nresult.get(constants.NV_NODESETUP,
1346 1345
                           ["Missing NODESETUP results"])
1347 1346
    _ErrorIf(test, self.ENODESETUP, node, "node setup error: %s",
......
1460 1459
          msg = "cannot reach the master IP"
1461 1460
        _ErrorIf(True, self.ENODENET, node, msg)
1462 1461

  
1463

  
1464
  def _VerifyInstance(self, instance, instanceconfig, node_image):
1462
  def _VerifyInstance(self, instance, instanceconfig, node_image,
1463
                      diskstatus):
1465 1464
    """Verify an instance.
1466 1465

  
1467 1466
    This function checks to see if the required block devices are
......
1497 1496
        _ErrorIf(test, self.EINSTANCEWRONGNODE, instance,
1498 1497
                 "instance should not run on node %s", node)
1499 1498

  
1499
    diskdata = [(nname, disk, idx)
1500
                for (nname, disks) in diskstatus.items()
1501
                for idx, disk in enumerate(disks)]
1502

  
1503
    for nname, bdev_status, idx in diskdata:
1504
      _ErrorIf(not bdev_status,
1505
               self.EINSTANCEFAULTYDISK, instance,
1506
               "couldn't retrieve status for disk/%s on %s", idx, nname)
1507
      _ErrorIf(bdev_status and bdev_status.ldisk_status == constants.LDS_FAULTY,
1508
               self.EINSTANCEFAULTYDISK, instance,
1509
               "disk/%s on %s is faulty", idx, nname)
1510

  
1500 1511
  def _VerifyOrphanVolumes(self, node_vol_should, node_image, reserved):
1501 1512
    """Verify if there are any unknown volumes in the cluster.
1502 1513

  
......
1847 1858
          _ErrorIf(True, self.ENODERPC, node,
1848 1859
                   "node returned invalid LVM info, check LVM status")
1849 1860

  
1861
  def _CollectDiskInfo(self, nodelist, node_image, instanceinfo):
1862
    """Gets per-disk status information for all instances.
1863

  
1864
    @type nodelist: list of strings
1865
    @param nodelist: Node names
1866
    @type node_image: dict of (name, L{objects.Node})
1867
    @param node_image: Node objects
1868
    @type instanceinfo: dict of (name, L{objects.Instance})
1869
    @param instanceinfo: Instance objects
1870

  
1871
    """
1872
    _ErrorIf = self._ErrorIf # pylint: disable-msg=C0103
1873

  
1874
    node_disks = {}
1875
    node_disks_devonly = {}
1876

  
1877
    for nname in nodelist:
1878
      disks = [(inst, disk)
1879
               for instlist in [node_image[nname].pinst,
1880
                                node_image[nname].sinst]
1881
               for inst in instlist
1882
               for disk in instanceinfo[inst].disks]
1883

  
1884
      if not disks:
1885
        # No need to collect data
1886
        continue
1887

  
1888
      node_disks[nname] = disks
1889

  
1890
      # Creating copies as SetDiskID below will modify the objects and that can
1891
      # lead to incorrect data returned from nodes
1892
      devonly = [dev.Copy() for (_, dev) in disks]
1893

  
1894
      for dev in devonly:
1895
        self.cfg.SetDiskID(dev, nname)
1896

  
1897
      node_disks_devonly[nname] = devonly
1898

  
1899
    assert len(node_disks) == len(node_disks_devonly)
1900

  
1901
    # Collect data from all nodes with disks
1902
    result = self.rpc.call_blockdev_getmirrorstatus_multi(node_disks.keys(),
1903
                                                          node_disks_devonly)
1904

  
1905
    assert len(result) == len(node_disks)
1906

  
1907
    instdisk = {}
1908

  
1909
    for (nname, nres) in result.items():
1910
      if nres.offline:
1911
        # Ignore offline node
1912
        continue
1913

  
1914
      disks = node_disks[nname]
1915

  
1916
      msg = nres.fail_msg
1917
      _ErrorIf(msg, self.ENODERPC, nname,
1918
               "while getting disk information: %s", nres.fail_msg)
1919
      if msg:
1920
        # No data from this node
1921
        data = len(disks) * [None]
1922
      else:
1923
        data = nres.payload
1924

  
1925
      for ((inst, _), status) in zip(disks, data):
1926
        instdisk.setdefault(inst, {}).setdefault(nname, []).append(status)
1927

  
1928
    assert compat.all(len(statuses) == len(instanceinfo[inst].disks) and
1929
                      len(nnames) <= len(instanceinfo[inst].all_nodes)
1930
                      for inst, nnames in instdisk.items()
1931
                      for nname, statuses in nnames.items())
1932

  
1933
    return instdisk
1934

  
1850 1935
  def BuildHooksEnv(self):
1851 1936
    """Build hooks env.
1852 1937

  
......
1977 2062

  
1978 2063
    all_drbd_map = self.cfg.ComputeDRBDMap()
1979 2064

  
2065
    feedback_fn("* Gathering disk information (%s nodes)" % len(nodelist))
2066
    instdisk = self._CollectDiskInfo(nodelist, node_image, instanceinfo)
2067

  
1980 2068
    feedback_fn("* Verifying node status")
1981 2069

  
1982 2070
    refos_img = None
......
2034 2122
      if verbose:
2035 2123
        feedback_fn("* Verifying instance %s" % instance)
2036 2124
      inst_config = instanceinfo[instance]
2037
      self._VerifyInstance(instance, inst_config, node_image)
2125
      self._VerifyInstance(instance, inst_config, node_image,
2126
                           instdisk[instance])
2038 2127
      inst_nodes_offline = []
2039 2128

  
2040 2129
      pnode = inst_config.primary_node
b/lib/rpc.py
1047 1047
    return result
1048 1048

  
1049 1049
  @_RpcTimeout(_TMO_NORMAL)
1050
  def call_blockdev_getmirrorstatus_multi(self, node_list, node_disks):
1051
    """Request status of (mirroring) devices from multiple nodes.
1052

  
1053
    This is a multi-node call.
1054

  
1055
    """
1056
    result = self._MultiNodeCall(node_list, "blockdev_getmirrorstatus_multi",
1057
                                 [dict((name, [dsk.ToDict() for dsk in disks])
1058
                                       for name, disks in node_disks.items())])
1059
    for nres in result.values():
1060
      if not nres.fail_msg:
1061
        nres.payload = [objects.BlockDevStatus.FromDict(i)
1062
                        for i in nres.payload]
1063
    return result
1064

  
1065
  @_RpcTimeout(_TMO_NORMAL)
1050 1066
  def call_blockdev_find(self, node, disk):
1051 1067
    """Request identification of a given block device.
1052 1068

  

Also available in: Unified diff