Revision 05484a24

b/lib/cli.py
2868 2868

  
2869 2869

  
2870 2870
def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
2871
                   filter_master=False):
2871
                   filter_master=False, nodegroup=None):
2872 2872
  """Returns the names of online nodes.
2873 2873

  
2874 2874
  This function will also log a warning on stderr with the names of
......
2889 2889
  @param filter_master: if True, do not return the master node in the list
2890 2890
      (useful in coordination with secondary_ips where we cannot check our
2891 2891
      node name against the list)
2892
  @type nodegroup: string
2893
  @param nodegroup: If set, only return nodes in this node group
2892 2894

  
2893 2895
  """
2894 2896
  if cl is None:
2895 2897
    cl = GetClient()
2896 2898

  
2897
  if secondary_ips:
2898
    name_idx = 2
2899
  else:
2900
    name_idx = 0
2899
  filter_ = []
2900

  
2901
  if nodes:
2902
    filter_.append(qlang.MakeSimpleFilter("name", nodes))
2903

  
2904
  if nodegroup is not None:
2905
    filter_.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
2906
                                 [qlang.OP_EQUAL, "group.uuid", nodegroup]])
2901 2907

  
2902 2908
  if filter_master:
2903
    master_node = cl.QueryConfigValues(["master_node"])[0]
2904
    filter_fn = lambda x: x != master_node
2909
    filter_.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
2910

  
2911
  if filter_:
2912
    if len(filter_) > 1:
2913
      final_filter = [qlang.OP_AND] + filter_
2914
    else:
2915
      assert len(filter_) == 1
2916
      final_filter = filter_[0]
2905 2917
  else:
2906
    filter_fn = lambda _: True
2918
    final_filter = None
2919

  
2920
  result = cl.Query(constants.QR_NODE, ["name", "offline", "sip"], final_filter)
2921

  
2922
  def _IsOffline(row):
2923
    (_, (_, offline), _) = row
2924
    return offline
2925

  
2926
  def _GetName(row):
2927
    ((_, name), _, _) = row
2928
    return name
2929

  
2930
  def _GetSip(row):
2931
    (_, _, (_, sip)) = row
2932
    return sip
2933

  
2934
  (offline, online) = compat.partition(result.data, _IsOffline)
2907 2935

  
2908
  result = cl.QueryNodes(names=nodes, fields=["name", "offline", "sip"],
2909
                         use_locking=False)
2910
  offline = [row[0] for row in result if row[1]]
2911 2936
  if offline and not nowarn:
2912
    ToStderr("Note: skipping offline node(s): %s" % utils.CommaJoin(offline))
2913
  return [row[name_idx] for row in result if not row[1] and filter_fn(row[0])]
2937
    ToStderr("Note: skipping offline node(s): %s" %
2938
             utils.CommaJoin(map(_GetName, offline)))
2939

  
2940
  if secondary_ips:
2941
    fn = _GetSip
2942
  else:
2943
    fn = _GetName
2944

  
2945
  return map(fn, online)
2914 2946

  
2915 2947

  
2916 2948
def _ToStream(stream, txt, *args):
b/test/ganeti.cli_unittest.py
32 32
from ganeti import errors
33 33
from ganeti import utils
34 34
from ganeti import objects
35
from ganeti import qlang
35 36
from ganeti.errors import OpPrereqError, ParameterError
36 37

  
37 38

  
......
753 754
      self.assertTrue(result.endswith(")"))
754 755

  
755 756

  
757
class TestGetOnlineNodes(unittest.TestCase):
758
  class _FakeClient:
759
    def __init__(self):
760
      self._query = []
761

  
762
    def AddQueryResult(self, *args):
763
      self._query.append(args)
764

  
765
    def CountPending(self):
766
      return len(self._query)
767

  
768
    def Query(self, res, fields, filter_):
769
      if res != constants.QR_NODE:
770
        raise Exception("Querying wrong resource")
771

  
772
      (exp_fields, check_filter, result) = self._query.pop(0)
773

  
774
      if exp_fields != fields:
775
        raise Exception("Expected fields %s, got %s" % (exp_fields, fields))
776

  
777
      if not (filter_ is None or check_filter(filter_)):
778
        raise Exception("Filter doesn't match expectations")
779

  
780
      return objects.QueryResponse(fields=None, data=result)
781

  
782
  def testEmpty(self):
783
    cl = self._FakeClient()
784

  
785
    cl.AddQueryResult(["name", "offline", "sip"], None, [])
786
    self.assertEqual(cli.GetOnlineNodes(None, cl=cl), [])
787
    self.assertEqual(cl.CountPending(), 0)
788

  
789
  def testNoSpecialFilter(self):
790
    cl = self._FakeClient()
791

  
792
    cl.AddQueryResult(["name", "offline", "sip"], None, [
793
      [(constants.RS_NORMAL, "master.example.com"),
794
       (constants.RS_NORMAL, False),
795
       (constants.RS_NORMAL, "192.0.2.1")],
796
      [(constants.RS_NORMAL, "node2.example.com"),
797
       (constants.RS_NORMAL, False),
798
       (constants.RS_NORMAL, "192.0.2.2")],
799
      ])
800
    self.assertEqual(cli.GetOnlineNodes(None, cl=cl),
801
                     ["master.example.com", "node2.example.com"])
802
    self.assertEqual(cl.CountPending(), 0)
803

  
804
  def testNoMaster(self):
805
    cl = self._FakeClient()
806

  
807
    def _CheckFilter(filter_):
808
      self.assertEqual(filter_, [qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
809
      return True
810

  
811
    cl.AddQueryResult(["name", "offline", "sip"], _CheckFilter, [
812
      [(constants.RS_NORMAL, "node2.example.com"),
813
       (constants.RS_NORMAL, False),
814
       (constants.RS_NORMAL, "192.0.2.2")],
815
      ])
816
    self.assertEqual(cli.GetOnlineNodes(None, cl=cl, filter_master=True),
817
                     ["node2.example.com"])
818
    self.assertEqual(cl.CountPending(), 0)
819

  
820
  def testSecondaryIpAddress(self):
821
    cl = self._FakeClient()
822

  
823
    cl.AddQueryResult(["name", "offline", "sip"], None, [
824
      [(constants.RS_NORMAL, "master.example.com"),
825
       (constants.RS_NORMAL, False),
826
       (constants.RS_NORMAL, "192.0.2.1")],
827
      [(constants.RS_NORMAL, "node2.example.com"),
828
       (constants.RS_NORMAL, False),
829
       (constants.RS_NORMAL, "192.0.2.2")],
830
      ])
831
    self.assertEqual(cli.GetOnlineNodes(None, cl=cl, secondary_ips=True),
832
                     ["192.0.2.1", "192.0.2.2"])
833
    self.assertEqual(cl.CountPending(), 0)
834

  
835
  def testNoMasterFilterNodeName(self):
836
    cl = self._FakeClient()
837

  
838
    def _CheckFilter(filter_):
839
      self.assertEqual(filter_,
840
        [qlang.OP_AND,
841
         [qlang.OP_OR] + [[qlang.OP_EQUAL, "name", name]
842
                          for name in ["node2", "node3"]],
843
         [qlang.OP_NOT, [qlang.OP_TRUE, "master"]]])
844
      return True
845

  
846
    cl.AddQueryResult(["name", "offline", "sip"], _CheckFilter, [
847
      [(constants.RS_NORMAL, "node2.example.com"),
848
       (constants.RS_NORMAL, False),
849
       (constants.RS_NORMAL, "192.0.2.12")],
850
      [(constants.RS_NORMAL, "node3.example.com"),
851
       (constants.RS_NORMAL, False),
852
       (constants.RS_NORMAL, "192.0.2.13")],
853
      ])
854
    self.assertEqual(cli.GetOnlineNodes(["node2", "node3"], cl=cl,
855
                                        secondary_ips=True, filter_master=True),
856
                     ["192.0.2.12", "192.0.2.13"])
857
    self.assertEqual(cl.CountPending(), 0)
858

  
859
  def testOfflineNodes(self):
860
    cl = self._FakeClient()
861

  
862
    cl.AddQueryResult(["name", "offline", "sip"], None, [
863
      [(constants.RS_NORMAL, "master.example.com"),
864
       (constants.RS_NORMAL, False),
865
       (constants.RS_NORMAL, "192.0.2.1")],
866
      [(constants.RS_NORMAL, "node2.example.com"),
867
       (constants.RS_NORMAL, True),
868
       (constants.RS_NORMAL, "192.0.2.2")],
869
      [(constants.RS_NORMAL, "node3.example.com"),
870
       (constants.RS_NORMAL, True),
871
       (constants.RS_NORMAL, "192.0.2.3")],
872
      ])
873
    self.assertEqual(cli.GetOnlineNodes(None, cl=cl, nowarn=True),
874
                     ["master.example.com"])
875
    self.assertEqual(cl.CountPending(), 0)
876

  
877
  def testNodeGroup(self):
878
    cl = self._FakeClient()
879

  
880
    def _CheckFilter(filter_):
881
      self.assertEqual(filter_,
882
        [qlang.OP_OR, [qlang.OP_EQUAL, "group", "foobar"],
883
                      [qlang.OP_EQUAL, "group.uuid", "foobar"]])
884
      return True
885

  
886
    cl.AddQueryResult(["name", "offline", "sip"], _CheckFilter, [
887
      [(constants.RS_NORMAL, "master.example.com"),
888
       (constants.RS_NORMAL, False),
889
       (constants.RS_NORMAL, "192.0.2.1")],
890
      [(constants.RS_NORMAL, "node3.example.com"),
891
       (constants.RS_NORMAL, False),
892
       (constants.RS_NORMAL, "192.0.2.3")],
893
      ])
894
    self.assertEqual(cli.GetOnlineNodes(None, cl=cl, nodegroup="foobar"),
895
                     ["master.example.com", "node3.example.com"])
896
    self.assertEqual(cl.CountPending(), 0)
897

  
898

  
756 899
if __name__ == '__main__':
757 900
  testutils.GanetiTestProgram()

Also available in: Unified diff