Revision 25361b9a

b/lib/backend.py
350 350
  """
351 351
  result = {}
352 352

  
353
  if 'hypervisor' in what:
354
    result['hypervisor'] = my_dict = {}
355
    for hv_name in what['hypervisor']:
356
      my_dict[hv_name] = hypervisor.GetHypervisor(hv_name).Verify()
357

  
358
  if 'filelist' in what:
359
    result['filelist'] = utils.FingerprintFiles(what['filelist'])
360

  
361
  if 'nodelist' in what:
362
    result['nodelist'] = {}
363
    random.shuffle(what['nodelist'])
364
    for node in what['nodelist']:
353
  if constants.NV_HYPERVISOR in what:
354
    result[constants.NV_HYPERVISOR] = tmp = {}
355
    for hv_name in what[constants.NV_HYPERVISOR]:
356
      tmp[hv_name] = hypervisor.GetHypervisor(hv_name).Verify()
357

  
358
  if constants.NV_FILELIST in what:
359
    result[constants.NV_FILELIST] = utils.FingerprintFiles(
360
      what[constants.NV_FILELIST])
361

  
362
  if constants.NV_NODELIST in what:
363
    result[constants.NV_NODELIST] = tmp = {}
364
    random.shuffle(what[constants.NV_NODELIST])
365
    for node in what[constants.NV_NODELIST]:
365 366
      success, message = _GetSshRunner(cluster_name).VerifyNodeHostname(node)
366 367
      if not success:
367
        result['nodelist'][node] = message
368
  if 'node-net-test' in what:
369
    result['node-net-test'] = {}
368
        tmp[node] = message
369

  
370
  if constants.NV_NODENETTEST in what:
371
    result[constants.NV_NODENETTEST] = tmp = {}
370 372
    my_name = utils.HostInfo().name
371 373
    my_pip = my_sip = None
372
    for name, pip, sip in what['node-net-test']:
374
    for name, pip, sip in what[constants.NV_NODENETTEST]:
373 375
      if name == my_name:
374 376
        my_pip = pip
375 377
        my_sip = sip
376 378
        break
377 379
    if not my_pip:
378
      result['node-net-test'][my_name] = ("Can't find my own"
379
                                          " primary/secondary IP"
380
                                          " in the node list")
380
      tmp[my_name] = ("Can't find my own primary/secondary IP"
381
                      " in the node list")
381 382
    else:
382 383
      port = utils.GetNodeDaemonPort()
383
      for name, pip, sip in what['node-net-test']:
384
      for name, pip, sip in what[constants.NV_NODENETTEST]:
384 385
        fail = []
385 386
        if not utils.TcpPing(pip, port, source=my_pip):
386 387
          fail.append("primary")
......
388 389
          if not utils.TcpPing(sip, port, source=my_sip):
389 390
            fail.append("secondary")
390 391
        if fail:
391
          result['node-net-test'][name] = ("failure using the %s"
392
                                           " interface(s)" %
393
                                           " and ".join(fail))
392
          tmp[name] = ("failure using the %s interface(s)" %
393
                       " and ".join(fail))
394

  
395
  if constants.NV_LVLIST in what:
396
    result[constants.NV_LVLIST] = GetVolumeList(what[constants.NV_LVLIST])
397

  
398
  if constants.NV_INSTANCELIST in what:
399
    result[constants.NV_INSTANCELIST] = GetInstanceList(
400
      what[constants.NV_INSTANCELIST])
401

  
402
  if constants.NV_VGLIST in what:
403
    result[constants.NV_VGLIST] = ListVolumeGroups()
404

  
405
  if constants.NV_VERSION in what:
406
    result[constants.NV_VERSION] = constants.PROTOCOL_VERSION
407

  
408
  if constants.NV_HVINFO in what:
409
    hyper = hypervisor.GetHypervisor(what[constants.NV_HVINFO])
410
    result[constants.NV_HVINFO] = hyper.GetNodeInfo()
394 411

  
395 412
  return result
396 413

  
b/lib/cmdlib.py
570 570
    }
571 571
    self.share_locks = dict(((i, 1) for i in locking.LEVELS))
572 572

  
573
  def _VerifyNode(self, nodeinfo, file_list, local_cksum, vglist, node_result,
574
                  remote_version, feedback_fn, master_files):
573
  def _VerifyNode(self, nodeinfo, file_list, local_cksum,
574
                  node_result, feedback_fn, master_files):
575 575
    """Run multiple tests against a node.
576 576

  
577 577
    Test list:
......
585 585
    @param nodeinfo: the node to check
586 586
    @param file_list: required list of files
587 587
    @param local_cksum: dictionary of local files and their checksums
588
    @type vglist: dict
589
    @param vglist: dictionary of volume group names and their size
590 588
    @param node_result: the results from the node
591
    @param remote_version: the RPC version from the remote node
592 589
    @param feedback_fn: function used to accumulate results
593 590
    @param master_files: list of files that only masters should have
594 591

  
595 592
    """
596 593
    node = nodeinfo.name
594

  
595
    # main result, node_result should be a non-empty dict
596
    if not node_result or not isinstance(node_result, dict):
597
      feedback_fn("  - ERROR: unable to verify node %s." % (node,))
598
      return True
599

  
597 600
    # compares ganeti version
598 601
    local_version = constants.PROTOCOL_VERSION
602
    remote_version = node_result.get('version', None)
599 603
    if not remote_version:
600 604
      feedback_fn("  - ERROR: connection to %s failed" % (node))
601 605
      return True
......
608 612
    # checks vg existance and size > 20G
609 613

  
610 614
    bad = False
615
    vglist = node_result.get(constants.NV_VGLIST, None)
611 616
    if not vglist:
612 617
      feedback_fn("  - ERROR: unable to check volume groups on node %s." %
613 618
                      (node,))
......
619 624
        feedback_fn("  - ERROR: %s on node %s" % (vgstatus, node))
620 625
        bad = True
621 626

  
622
    if not node_result:
623
      feedback_fn("  - ERROR: unable to verify node %s." % (node,))
624
      return True
625

  
626 627
    # checks config file checksum
627
    # checks ssh to any
628 628

  
629
    if 'filelist' not in node_result:
629
    remote_cksum = node_result.get(constants.NV_FILELIST, None)
630
    if not isinstance(remote_cksum, dict):
630 631
      bad = True
631 632
      feedback_fn("  - ERROR: node hasn't returned file checksum data")
632 633
    else:
633
      remote_cksum = node_result['filelist']
634 634
      for file_name in file_list:
635 635
        node_is_mc = nodeinfo.master_candidate
636 636
        must_have_file = file_name not in master_files
......
653 653
            feedback_fn("  - ERROR: file '%s' should not exist on non master"
654 654
                        " candidates" % file_name)
655 655

  
656
    if 'nodelist' not in node_result:
656
    # checks ssh to any
657

  
658
    if constants.NV_NODELIST not in node_result:
657 659
      bad = True
658 660
      feedback_fn("  - ERROR: node hasn't returned node ssh connectivity data")
659 661
    else:
660
      if node_result['nodelist']:
662
      if node_result[constants.NV_NODELIST]:
661 663
        bad = True
662
        for node in node_result['nodelist']:
664
        for node in node_result[constants.NV_NODELIST]:
663 665
          feedback_fn("  - ERROR: ssh communication with node '%s': %s" %
664
                          (node, node_result['nodelist'][node]))
665
    if 'node-net-test' not in node_result:
666
                          (node, node_result[constants.NV_NODELIST][node]))
667

  
668
    if constants.NV_NODENETTEST not in node_result:
666 669
      bad = True
667 670
      feedback_fn("  - ERROR: node hasn't returned node tcp connectivity data")
668 671
    else:
669
      if node_result['node-net-test']:
672
      if node_result[constants.NV_NODENETTEST]:
670 673
        bad = True
671
        nlist = utils.NiceSort(node_result['node-net-test'].keys())
674
        nlist = utils.NiceSort(node_result[constants.NV_NODENETTEST].keys())
672 675
        for node in nlist:
673 676
          feedback_fn("  - ERROR: tcp communication with node '%s': %s" %
674
                          (node, node_result['node-net-test'][node]))
677
                          (node, node_result[constants.NV_NODENETTEST][node]))
675 678

  
676
    hyp_result = node_result.get('hypervisor', None)
679
    hyp_result = node_result.get(constants.NV_HYPERVISOR, None)
677 680
    if isinstance(hyp_result, dict):
678 681
      for hv_name, hv_result in hyp_result.iteritems():
679 682
        if hv_result is not None:
......
836 839
    local_checksums = utils.FingerprintFiles(file_names)
837 840

  
838 841
    feedback_fn("* Gathering data (%d nodes)" % len(nodelist))
839
    all_volumeinfo = self.rpc.call_volume_list(nodelist, vg_name)
840
    all_instanceinfo = self.rpc.call_instance_list(nodelist, hypervisors)
841
    all_vglist = self.rpc.call_vg_list(nodelist)
842 842
    node_verify_param = {
843
      'filelist': file_names,
844
      'nodelist': nodelist,
845
      'hypervisor': hypervisors,
846
      'node-net-test': [(node.name, node.primary_ip, node.secondary_ip)
847
                        for node in nodeinfo]
843
      constants.NV_FILELIST: file_names,
844
      constants.NV_NODELIST: nodelist,
845
      constants.NV_HYPERVISOR: hypervisors,
846
      constants.NV_NODENETTEST: [(node.name, node.primary_ip,
847
                                  node.secondary_ip) for node in nodeinfo],
848
      constants.NV_LVLIST: vg_name,
849
      constants.NV_INSTANCELIST: hypervisors,
850
      constants.NV_VGLIST: None,
851
      constants.NV_VERSION: None,
852
      constants.NV_HVINFO: self.cfg.GetHypervisorType(),
848 853
      }
849 854
    all_nvinfo = self.rpc.call_node_verify(nodelist, node_verify_param,
850 855
                                           self.cfg.GetClusterName())
851
    all_rversion = self.rpc.call_version(nodelist)
852
    all_ninfo = self.rpc.call_node_info(nodelist, self.cfg.GetVGName(),
853
                                        self.cfg.GetHypervisorType())
854 856

  
855 857
    cluster = self.cfg.GetClusterInfo()
856 858
    master_node = self.cfg.GetMasterNode()
857 859
    for node_i in nodeinfo:
858 860
      node = node_i.name
861
      nresult = all_nvinfo[node].data
862

  
859 863
      if node == master_node:
860
        ntype="master"
864
        ntype = "master"
861 865
      elif node_i.master_candidate:
862
        ntype="master candidate"
866
        ntype = "master candidate"
863 867
      else:
864
        ntype="regular"
868
        ntype = "regular"
865 869
      feedback_fn("* Verifying node %s (%s)" % (node, ntype))
870

  
871
      if all_nvinfo[node].failed or not isinstance(nresult, dict):
872
        feedback_fn("  - ERROR: connection to %s failed" % (node,))
873
        bad = True
874
        continue
875

  
866 876
      result = self._VerifyNode(node_i, file_names, local_checksums,
867
                                all_vglist[node], all_nvinfo[node],
868
                                all_rversion[node], feedback_fn, master_files)
877
                                nresult, feedback_fn, master_files)
869 878
      bad = bad or result
870 879

  
871
      # node_volume
872
      volumeinfo = all_volumeinfo[node]
873

  
874
      if isinstance(volumeinfo, basestring):
880
      lvdata = nresult.get(constants.NV_LVLIST, "Missing LV data")
881
      if isinstance(lvdata, basestring):
875 882
        feedback_fn("  - ERROR: LVM problem on node %s: %s" %
876
                    (node, volumeinfo[-400:].encode('string_escape')))
883
                    (node, lvdata.encode('string_escape')))
877 884
        bad = True
878 885
        node_volume[node] = {}
879
      elif not isinstance(volumeinfo, dict):
880
        feedback_fn("  - ERROR: connection to %s failed" % (node,))
886
      elif not isinstance(lvdata, dict):
887
        feedback_fn("  - ERROR: connection to %s failed (lvlist)" % (node,))
881 888
        bad = True
882 889
        continue
883 890
      else:
884
        node_volume[node] = volumeinfo
891
        node_volume[node] = lvdata
885 892

  
886 893
      # node_instance
887
      nodeinstance = all_instanceinfo[node]
888
      if type(nodeinstance) != list:
889
        feedback_fn("  - ERROR: connection to %s failed" % (node,))
894
      idata = nresult.get(constants.NV_INSTANCELIST, None)
895
      if not isinstance(idata, list):
896
        feedback_fn("  - ERROR: connection to %s failed (instancelist)" %
897
                    (node,))
890 898
        bad = True
891 899
        continue
892 900

  
893
      node_instance[node] = nodeinstance
901
      node_instance[node] = idata
894 902

  
895 903
      # node_info
896
      nodeinfo = all_ninfo[node]
904
      nodeinfo = nresult.get(constants.NV_HVINFO, None)
897 905
      if not isinstance(nodeinfo, dict):
898
        feedback_fn("  - ERROR: connection to %s failed" % (node,))
906
        feedback_fn("  - ERROR: connection to %s failed (hvinfo)" % (node,))
899 907
        bad = True
900 908
        continue
901 909

  
902 910
      try:
903 911
        node_info[node] = {
904 912
          "mfree": int(nodeinfo['memory_free']),
905
          "dfree": int(nodeinfo['vg_free']),
913
          "dfree": int(nresult[constants.NV_VGLIST][vg_name]),
906 914
          "pinst": [],
907 915
          "sinst": [],
908 916
          # dictionary holding all instances this node is secondary for,
......
1017 1025
        for node_name in hooks_results:
1018 1026
          show_node_header = True
1019 1027
          res = hooks_results[node_name]
1020
          if res is False or not isinstance(res, list):
1021
            feedback_fn("    Communication failure")
1028
          if res.failed or res.data is False or not isinstance(res.data, list):
1029
            feedback_fn("    Communication failure in hooks execution")
1022 1030
            lu_result = 1
1023 1031
            continue
1024
          for script, hkr, output in res:
1032
          for script, hkr, output in res.data:
1025 1033
            if hkr == constants.HKR_FAIL:
1026 1034
              # The node header is only shown once, if there are
1027 1035
              # failing hooks on that node
......
5500 5508
    found = False
5501 5509
    for node in exportlist:
5502 5510
      if exportlist[node].failed:
5503
        self.Warning("Failed to query node %s, continuing" % node)
5511
        self.LogWarning("Failed to query node %s, continuing" % node)
5504 5512
        continue
5505 5513
      if instance_name in exportlist[node].data:
5506 5514
        found = True
b/lib/constants.py
333 333
VERIFY_NPLUSONE_MEM = 'nplusone_mem'
334 334
VERIFY_OPTIONAL_CHECKS = frozenset([VERIFY_NPLUSONE_MEM])
335 335

  
336
# Node verify constants
337
NV_FILELIST = "filelist"
338
NV_HVINFO = "hvinfo"
339
NV_HYPERVISOR = "hypervisor"
340
NV_INSTANCELIST = "instancelist"
341
NV_LVLIST = "lvlist"
342
NV_NODELIST = "nodelist"
343
NV_NODENETTEST = "node-net-test"
344
NV_VERSION = "version"
345
NV_VGLIST = "vglist"
346

  
336 347
# Allocator framework constants
337 348
IALLOCATOR_DIR_IN = "in"
338 349
IALLOCATOR_DIR_OUT = "out"

Also available in: Unified diff