Revision 8930b0f0

b/lib/query.py
1 1
#
2 2
#
3 3

  
4
# Copyright (C) 2010, 2011 Google Inc.
4
# Copyright (C) 2010, 2011, 2012 Google Inc.
5 5
#
6 6
# This program is free software; you can redistribute it and/or modify
7 7
# it under the terms of the GNU General Public License as published by
......
136 136

  
137 137
_SERIAL_NO_DOC = "%s object serial number, incremented on each modification"
138 138

  
139
# TODO: Consider moving titles closer to constants
140
NDP_TITLE = {
141
  constants.ND_OOB_PROGRAM: "OutOfBandProgram",
142
  constants.ND_SPINDLE_COUNT: "SpindleCount",
143
  }
144

  
139 145

  
140 146
def _GetUnknownField(ctx, item): # pylint: disable=W0613
141 147
  """Gets the contents of an unknown field.
......
899 905
  return lambda _, item: getter(item)
900 906

  
901 907

  
908
def _GetNDParam(name):
909
  """Return a field function to return an ND parameter out of the context.
910

  
911
  """
912
  def _helper(ctx, _):
913
    if ctx.ndparams is None:
914
      return _FS_UNAVAIL
915
    else:
916
      return ctx.ndparams.get(name, None)
917
  return _helper
918

  
919

  
920
def _BuildNDFields(is_group):
921
  """Builds all the ndparam fields.
922

  
923
  @param is_group: whether this is called at group or node level
924

  
925
  """
926
  if is_group:
927
    field_kind = GQ_CONFIG
928
  else:
929
    field_kind = NQ_GROUP
930
  return [(_MakeField("ndp/%s" % name, NDP_TITLE.get(name, "ndp/%s" % name),
931
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
932
           field_kind, 0, _GetNDParam(name))
933
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
934

  
935

  
902 936
def _ConvWrapInner(convert, fn, ctx, item):
903 937
  """Wrapper for converting values.
904 938

  
......
982 1016

  
983 1017
    # Used for individual rows
984 1018
    self.curlive_data = None
1019
    self.ndparams = None
985 1020

  
986 1021
  def __iter__(self):
987 1022
    """Iterate over all nodes.
......
991 1026

  
992 1027
    """
993 1028
    for node in self.nodes:
1029
      group = self.groups.get(node.group, None)
1030
      if group is None:
1031
        self.ndparams = None
1032
      else:
1033
        self.ndparams = self.cluster.FillND(node, group)
994 1034
      if self.live_data:
995 1035
        self.curlive_data = self.live_data.get(node.name, None)
996 1036
      else:
......
1198 1238
     NQ_CONFIG, 0, _GetNodeDiskState),
1199 1239
    ]
1200 1240

  
1241
  fields.extend(_BuildNDFields(False))
1242

  
1201 1243
  # Node role
1202 1244
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1203 1245
                 constants.NR_REGULAR, constants.NR_DRAINED,
......
1959 2001

  
1960 2002
    # Used for individual rows
1961 2003
    self.group_ipolicy = None
2004
    self.ndparams = None
1962 2005

  
1963 2006
  def __iter__(self):
1964 2007
    """Iterate over all node groups.
......
1969 2012
    """
1970 2013
    for group in self.groups:
1971 2014
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2015
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
1972 2016
      yield group
1973 2017

  
1974 2018

  
......
1977 2021
  "name": ("Group", QFT_TEXT, "Group name"),
1978 2022
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
1979 2023
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
1980
  "ndparams": ("NDParams", QFT_OTHER, "Node parameters"),
1981 2024
  }
1982 2025

  
1983 2026

  
......
2027 2070
    (_MakeField("custom_ipolicy", "CustomInstancePolicy", QFT_OTHER,
2028 2071
                "Custom instance policy limitations"),
2029 2072
     GQ_CONFIG, 0, _GetItemAttr("ipolicy")),
2073
    (_MakeField("custom_ndparams", "CustomNDParams", QFT_OTHER,
2074
                "Custom node parameters"),
2075
     GQ_CONFIG, 0, _GetItemAttr("ndparams")),
2076
    (_MakeField("ndparams", "NDParams", QFT_OTHER,
2077
                "Node parameters"),
2078
     GQ_CONFIG, 0, lambda ctx, _: ctx.ndparams),
2030 2079
    ])
2031 2080

  
2081
  # ND parameters
2082
  fields.extend(_BuildNDFields(True))
2083

  
2032 2084
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
2033 2085

  
2034 2086
  return _PrepareFieldList(fields, [])
b/test/ganeti.query_unittest.py
1 1
#!/usr/bin/python
2 2
#
3 3

  
4
# Copyright (C) 2010, 2011 Google Inc.
4
# Copyright (C) 2010, 2011, 2012 Google Inc.
5 5
#
6 6
# This program is free software; you can redistribute it and/or modify
7 7
# it under the terms of the GNU General Public License as published by
......
322 322
    return query.Query(query.NODE_FIELDS, selected)
323 323

  
324 324
  def testSimple(self):
325
    cluster = objects.Cluster(cluster_name="testcluster",
326
                              ndparams=constants.NDC_DEFAULTS.copy())
327
    grp1 = objects.NodeGroup(name="default",
328
                             uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
329
                             alloc_policy=constants.ALLOC_POLICY_PREFERRED,
330
                             ipolicy=objects.MakeEmptyIPolicy(),
331
                             ndparams={},
332
                             )
333
    grp2 = objects.NodeGroup(name="group2",
334
                             uuid="c0e89160-18e7-11e0-a46e-001d0904babe",
335
                             alloc_policy=constants.ALLOC_POLICY_PREFERRED,
336
                             ipolicy=objects.MakeEmptyIPolicy(),
337
                             ndparams={constants.ND_SPINDLE_COUNT: 2},
338
                             )
339
    groups = {grp1.uuid: grp1, grp2.uuid: grp2}
325 340
    nodes = [
326
      objects.Node(name="node1", drained=False),
327
      objects.Node(name="node2", drained=True),
328
      objects.Node(name="node3", drained=False),
341
      objects.Node(name="node1", drained=False, group=grp1.uuid, ndparams={}),
342
      objects.Node(name="node2", drained=True, group=grp2.uuid, ndparams={}),
343
      objects.Node(name="node3", drained=False, group=grp1.uuid,
344
                   ndparams={constants.ND_SPINDLE_COUNT: 4}),
329 345
      ]
330 346
    for live_data in [None, dict.fromkeys([node.name for node in nodes], {})]:
331
      nqd = query.NodeQueryData(nodes, live_data, None, None, None, None, None,
332
                                None)
347
      nqd = query.NodeQueryData(nodes, live_data, None, None, None,
348
                                groups, None, cluster)
333 349

  
334 350
      q = self._Create(["name", "drained"])
335 351
      self.assertEqual(q.RequestedData(), set([query.NQ_CONFIG]))
......
345 361
                       [["node1", False],
346 362
                        ["node2", True],
347 363
                        ["node3", False]])
364
      q = self._Create(["ndp/spindle_count"])
365
      self.assertEqual(q.RequestedData(), set([query.NQ_GROUP]))
366
      self.assertEqual(q.Query(nqd),
367
                       [[(constants.RS_NORMAL,
368
                          constants.NDC_DEFAULTS[constants.ND_SPINDLE_COUNT])],
369
                        [(constants.RS_NORMAL,
370
                          grp2.ndparams[constants.ND_SPINDLE_COUNT])],
371
                        [(constants.RS_NORMAL,
372
                          nodes[2].ndparams[constants.ND_SPINDLE_COUNT])],
373
                       ])
348 374

  
349 375
  def test(self):
350 376
    selected = query.NODE_FIELDS.keys()
......
933 959
      objects.NodeGroup(name="default",
934 960
                        uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
935 961
                        alloc_policy=constants.ALLOC_POLICY_PREFERRED,
936
                        ipolicy=objects.MakeEmptyIPolicy()),
962
                        ipolicy=objects.MakeEmptyIPolicy(),
963
                        ndparams={},
964
                        ),
937 965
      objects.NodeGroup(name="restricted",
938 966
                        uuid="d2a40a74-18e7-11e0-9143-001d0904baeb",
939 967
                        alloc_policy=constants.ALLOC_POLICY_LAST_RESORT,
940
                        ipolicy=objects.MakeEmptyIPolicy()),
968
                        ipolicy=objects.MakeEmptyIPolicy(),
969
                        ndparams={}
970
                        ),
941 971
      ]
942 972
    self.cluster = objects.Cluster(cluster_name="testcluster",
943 973
      hvparams=constants.HVC_DEFAULTS,

Also available in: Unified diff