Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 75cf411a

History | View | Annotate | Download (12.6 kB)

1 4ca96421 Michael Hanselmann
#
2 4ca96421 Michael Hanselmann
#
3 4ca96421 Michael Hanselmann
4 4ca96421 Michael Hanselmann
# Copyright (C) 2010 Google Inc.
5 4ca96421 Michael Hanselmann
#
6 4ca96421 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 4ca96421 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 4ca96421 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 4ca96421 Michael Hanselmann
# (at your option) any later version.
10 4ca96421 Michael Hanselmann
#
11 4ca96421 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 4ca96421 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 4ca96421 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4ca96421 Michael Hanselmann
# General Public License for more details.
15 4ca96421 Michael Hanselmann
#
16 4ca96421 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 4ca96421 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 4ca96421 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 4ca96421 Michael Hanselmann
# 02110-1301, USA.
20 4ca96421 Michael Hanselmann
21 4ca96421 Michael Hanselmann
22 4ca96421 Michael Hanselmann
"""Module for query operations"""
23 4ca96421 Michael Hanselmann
24 8235fe04 Michael Hanselmann
import logging
25 4ca96421 Michael Hanselmann
import operator
26 4ca96421 Michael Hanselmann
import re
27 4ca96421 Michael Hanselmann
28 4ca96421 Michael Hanselmann
from ganeti import constants
29 4ca96421 Michael Hanselmann
from ganeti import errors
30 4ca96421 Michael Hanselmann
from ganeti import utils
31 4ca96421 Michael Hanselmann
from ganeti import compat
32 4ca96421 Michael Hanselmann
from ganeti import objects
33 4ca96421 Michael Hanselmann
from ganeti import ht
34 4ca96421 Michael Hanselmann
35 4ca96421 Michael Hanselmann
36 8235fe04 Michael Hanselmann
(NQ_CONFIG,
37 8235fe04 Michael Hanselmann
 NQ_INST,
38 8235fe04 Michael Hanselmann
 NQ_LIVE,
39 8235fe04 Michael Hanselmann
 NQ_GROUP) = range(1, 5)
40 8235fe04 Michael Hanselmann
41 8235fe04 Michael Hanselmann
42 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
43 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
44 4ca96421 Michael Hanselmann
45 4ca96421 Michael Hanselmann
#: Verification function for each field type
46 4ca96421 Michael Hanselmann
_VERIFY_FN = {
47 4ca96421 Michael Hanselmann
  constants.QFT_UNKNOWN: ht.TNone,
48 4ca96421 Michael Hanselmann
  constants.QFT_TEXT: ht.TString,
49 4ca96421 Michael Hanselmann
  constants.QFT_BOOL: ht.TBool,
50 4ca96421 Michael Hanselmann
  constants.QFT_NUMBER: ht.TInt,
51 4ca96421 Michael Hanselmann
  constants.QFT_UNIT: ht.TInt,
52 4ca96421 Michael Hanselmann
  constants.QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat),
53 4ca96421 Michael Hanselmann
  constants.QFT_OTHER: lambda _: True,
54 4ca96421 Michael Hanselmann
  }
55 4ca96421 Michael Hanselmann
56 4ca96421 Michael Hanselmann
57 4ca96421 Michael Hanselmann
def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
58 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
59 4ca96421 Michael Hanselmann

60 4ca96421 Michael Hanselmann
  """
61 4ca96421 Michael Hanselmann
  return (constants.QRFS_UNKNOWN, None)
62 4ca96421 Michael Hanselmann
63 4ca96421 Michael Hanselmann
64 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
65 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
66 4ca96421 Michael Hanselmann

67 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
68 4ca96421 Michael Hanselmann

69 4ca96421 Michael Hanselmann
  @type fielddefs: dict
70 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
71 4ca96421 Michael Hanselmann
  @type selected: list of strings
72 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
73 4ca96421 Michael Hanselmann

74 4ca96421 Michael Hanselmann
  """
75 4ca96421 Michael Hanselmann
  result = []
76 4ca96421 Michael Hanselmann
77 4ca96421 Michael Hanselmann
  for name in selected:
78 4ca96421 Michael Hanselmann
    try:
79 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
80 4ca96421 Michael Hanselmann
    except KeyError:
81 4ca96421 Michael Hanselmann
      fdef = (_MakeField(name, name, constants.QFT_UNKNOWN),
82 4ca96421 Michael Hanselmann
              None, _GetUnknownField)
83 4ca96421 Michael Hanselmann
84 4ca96421 Michael Hanselmann
    assert len(fdef) == 3
85 4ca96421 Michael Hanselmann
86 4ca96421 Michael Hanselmann
    result.append(fdef)
87 4ca96421 Michael Hanselmann
88 4ca96421 Michael Hanselmann
  return result
89 4ca96421 Michael Hanselmann
90 4ca96421 Michael Hanselmann
91 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
92 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
93 4ca96421 Michael Hanselmann

94 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
95 4ca96421 Michael Hanselmann

96 4ca96421 Michael Hanselmann
  """
97 4ca96421 Michael Hanselmann
  return [fdef for (fdef, _, _) in fielddefs]
98 4ca96421 Michael Hanselmann
99 4ca96421 Michael Hanselmann
100 4ca96421 Michael Hanselmann
class Query:
101 4ca96421 Michael Hanselmann
  def __init__(self, fieldlist, selected):
102 4ca96421 Michael Hanselmann
    """Initializes this class.
103 4ca96421 Michael Hanselmann

104 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
105 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
106 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
107 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
108 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
109 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
110 4ca96421 Michael Hanselmann

111 4ca96421 Michael Hanselmann
    Users of this class can call L{RequestedData} before preparing the data
112 4ca96421 Michael Hanselmann
    container to determine what data is needed.
113 4ca96421 Michael Hanselmann

114 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
115 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
116 4ca96421 Michael Hanselmann
    @type selected: list of strings
117 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
118 4ca96421 Michael Hanselmann

119 4ca96421 Michael Hanselmann
    """
120 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
121 4ca96421 Michael Hanselmann
122 4ca96421 Michael Hanselmann
  def RequestedData(self):
123 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
124 4ca96421 Michael Hanselmann

125 4ca96421 Michael Hanselmann
    @rtype: frozenset
126 4ca96421 Michael Hanselmann

127 4ca96421 Michael Hanselmann
    """
128 4ca96421 Michael Hanselmann
    return frozenset(datakind
129 4ca96421 Michael Hanselmann
                     for (_, datakind, _) in self._fields
130 4ca96421 Michael Hanselmann
                     if datakind is not None)
131 4ca96421 Michael Hanselmann
132 4ca96421 Michael Hanselmann
  def GetFields(self):
133 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
134 4ca96421 Michael Hanselmann

135 4ca96421 Michael Hanselmann
    Includes unknown fields.
136 4ca96421 Michael Hanselmann

137 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
138 4ca96421 Michael Hanselmann

139 4ca96421 Michael Hanselmann
    """
140 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
141 4ca96421 Michael Hanselmann
142 4ca96421 Michael Hanselmann
  def Query(self, ctx):
143 4ca96421 Michael Hanselmann
    """Execute a query.
144 4ca96421 Michael Hanselmann

145 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
146 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
147 4ca96421 Michael Hanselmann

148 4ca96421 Michael Hanselmann
    """
149 4ca96421 Michael Hanselmann
    result = [[fn(ctx, item) for (_, _, fn) in self._fields]
150 4ca96421 Michael Hanselmann
              for item in ctx]
151 4ca96421 Michael Hanselmann
152 4ca96421 Michael Hanselmann
    # Verify result
153 4ca96421 Michael Hanselmann
    if __debug__:
154 4ca96421 Michael Hanselmann
      for (idx, row) in enumerate(result):
155 4ca96421 Michael Hanselmann
        assert _VerifyResultRow(self._fields, row), \
156 4ca96421 Michael Hanselmann
               ("Inconsistent result for fields %s in row %s: %r" %
157 89ce4acc Michael Hanselmann
                (GetAllFields(self._fields), idx, row))
158 4ca96421 Michael Hanselmann
159 4ca96421 Michael Hanselmann
    return result
160 4ca96421 Michael Hanselmann
161 4ca96421 Michael Hanselmann
  def OldStyleQuery(self, ctx):
162 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
163 4ca96421 Michael Hanselmann

164 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
165 4ca96421 Michael Hanselmann

166 4ca96421 Michael Hanselmann
    """
167 4ca96421 Michael Hanselmann
    unknown = set(fdef.name
168 4ca96421 Michael Hanselmann
                  for (fdef, _, _) in self._fields
169 4ca96421 Michael Hanselmann
                  if fdef.kind == constants.QFT_UNKNOWN)
170 4ca96421 Michael Hanselmann
    if unknown:
171 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
172 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
173 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
174 4ca96421 Michael Hanselmann
175 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
176 4ca96421 Michael Hanselmann
            for row in self.Query(ctx)]
177 4ca96421 Michael Hanselmann
178 4ca96421 Michael Hanselmann
179 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
180 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
181 4ca96421 Michael Hanselmann

182 4ca96421 Michael Hanselmann
  @type fields: list
183 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
184 4ca96421 Michael Hanselmann
  @type row: list of tuples
185 4ca96421 Michael Hanselmann
  @param row: Row data
186 4ca96421 Michael Hanselmann

187 4ca96421 Michael Hanselmann
  """
188 4ca96421 Michael Hanselmann
  return (len(row) == len(fields) and
189 4ca96421 Michael Hanselmann
          compat.all((status == constants.QRFS_NORMAL and
190 4ca96421 Michael Hanselmann
                      _VERIFY_FN[fdef.kind](value)) or
191 4ca96421 Michael Hanselmann
                     # Value for an abnormal status must be None
192 4ca96421 Michael Hanselmann
                     (status != constants.QRFS_NORMAL and value is None)
193 4ca96421 Michael Hanselmann
                     for ((status, value), (fdef, _, _)) in zip(row, fields)))
194 4ca96421 Michael Hanselmann
195 4ca96421 Michael Hanselmann
196 4ca96421 Michael Hanselmann
def _PrepareFieldList(fields):
197 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
198 4ca96421 Michael Hanselmann

199 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
200 4ca96421 Michael Hanselmann

201 4ca96421 Michael Hanselmann
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data kind,
202 4ca96421 Michael Hanselmann
    retrieval function)
203 4ca96421 Michael Hanselmann
  @param fields: List of fields
204 4ca96421 Michael Hanselmann
  @rtype: dict
205 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
206 4ca96421 Michael Hanselmann

207 4ca96421 Michael Hanselmann
  """
208 89ce4acc Michael Hanselmann
  if __debug__:
209 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
210 89ce4acc Michael Hanselmann
                                      for (fdef, _, _) in fields)
211 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
212 4ca96421 Michael Hanselmann
213 4ca96421 Michael Hanselmann
  result = {}
214 4ca96421 Michael Hanselmann
215 4ca96421 Michael Hanselmann
  for field in fields:
216 4ca96421 Michael Hanselmann
    (fdef, _, fn) = field
217 4ca96421 Michael Hanselmann
218 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
219 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
220 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
221 4ca96421 Michael Hanselmann
    assert callable(fn)
222 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
223 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
224 4ca96421 Michael Hanselmann
225 4ca96421 Michael Hanselmann
    result[fdef.name] = field
226 4ca96421 Michael Hanselmann
227 4ca96421 Michael Hanselmann
  assert len(result) == len(fields)
228 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
229 4ca96421 Michael Hanselmann
                    for (name, (fdef, _, _)) in result.items())
230 4ca96421 Michael Hanselmann
231 4ca96421 Michael Hanselmann
  return result
232 4ca96421 Michael Hanselmann
233 4ca96421 Michael Hanselmann
234 4ca96421 Michael Hanselmann
def _MakeField(name, title, kind):
235 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
236 4ca96421 Michael Hanselmann

237 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
238 4ca96421 Michael Hanselmann
  @param title: Human-readable title
239 4ca96421 Michael Hanselmann
  @param kind: Field type
240 4ca96421 Michael Hanselmann

241 4ca96421 Michael Hanselmann
  """
242 4ca96421 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind)
243 8235fe04 Michael Hanselmann
244 8235fe04 Michael Hanselmann
245 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
246 8235fe04 Michael Hanselmann
  """Determine node role.
247 8235fe04 Michael Hanselmann

248 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
249 8235fe04 Michael Hanselmann
  @param node: Node object
250 8235fe04 Michael Hanselmann
  @type master_name: string
251 8235fe04 Michael Hanselmann
  @param master_name: Master node name
252 8235fe04 Michael Hanselmann

253 8235fe04 Michael Hanselmann
  """
254 8235fe04 Michael Hanselmann
  if node.name == master_name:
255 8235fe04 Michael Hanselmann
    return "M"
256 8235fe04 Michael Hanselmann
  elif node.master_candidate:
257 8235fe04 Michael Hanselmann
    return "C"
258 8235fe04 Michael Hanselmann
  elif node.drained:
259 8235fe04 Michael Hanselmann
    return "D"
260 8235fe04 Michael Hanselmann
  elif node.offline:
261 8235fe04 Michael Hanselmann
    return "O"
262 8235fe04 Michael Hanselmann
  else:
263 8235fe04 Michael Hanselmann
    return "R"
264 8235fe04 Michael Hanselmann
265 8235fe04 Michael Hanselmann
266 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
267 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
268 8235fe04 Michael Hanselmann

269 8235fe04 Michael Hanselmann
  @param attr: Attribute name
270 8235fe04 Michael Hanselmann

271 8235fe04 Michael Hanselmann
  """
272 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
273 8235fe04 Michael Hanselmann
  return lambda _, item: (constants.QRFS_NORMAL, getter(item))
274 8235fe04 Michael Hanselmann
275 8235fe04 Michael Hanselmann
276 8235fe04 Michael Hanselmann
class NodeQueryData:
277 8235fe04 Michael Hanselmann
  """Data container for node data queries.
278 8235fe04 Michael Hanselmann

279 8235fe04 Michael Hanselmann
  """
280 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
281 8235fe04 Michael Hanselmann
               node_to_secondary, groups):
282 8235fe04 Michael Hanselmann
    """Initializes this class.
283 8235fe04 Michael Hanselmann

284 8235fe04 Michael Hanselmann
    """
285 8235fe04 Michael Hanselmann
    self.nodes = nodes
286 8235fe04 Michael Hanselmann
    self.live_data = live_data
287 8235fe04 Michael Hanselmann
    self.master_name = master_name
288 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
289 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
290 8235fe04 Michael Hanselmann
    self.groups = groups
291 8235fe04 Michael Hanselmann
292 8235fe04 Michael Hanselmann
    # Used for individual rows
293 8235fe04 Michael Hanselmann
    self.curlive_data = None
294 8235fe04 Michael Hanselmann
295 8235fe04 Michael Hanselmann
  def __iter__(self):
296 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
297 8235fe04 Michael Hanselmann

298 8235fe04 Michael Hanselmann
    This function has side-effects and only one instance of the resulting
299 8235fe04 Michael Hanselmann
    generator should be used at a time.
300 8235fe04 Michael Hanselmann

301 8235fe04 Michael Hanselmann
    """
302 8235fe04 Michael Hanselmann
    for node in self.nodes:
303 8235fe04 Michael Hanselmann
      if self.live_data:
304 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
305 8235fe04 Michael Hanselmann
      else:
306 8235fe04 Michael Hanselmann
        self.curlive_data = None
307 8235fe04 Michael Hanselmann
      yield node
308 8235fe04 Michael Hanselmann
309 8235fe04 Michael Hanselmann
310 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
311 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
312 8235fe04 Michael Hanselmann
  "ctime": ("CTime", constants.QFT_TIMESTAMP),
313 8235fe04 Michael Hanselmann
  "drained": ("Drained", constants.QFT_BOOL),
314 8235fe04 Michael Hanselmann
  "master_candidate": ("MasterC", constants.QFT_BOOL),
315 8235fe04 Michael Hanselmann
  "master_capable": ("MasterCapable", constants.QFT_BOOL),
316 8235fe04 Michael Hanselmann
  "mtime": ("MTime", constants.QFT_TIMESTAMP),
317 8235fe04 Michael Hanselmann
  "name": ("Node", constants.QFT_TEXT),
318 8235fe04 Michael Hanselmann
  "offline": ("Offline", constants.QFT_BOOL),
319 8235fe04 Michael Hanselmann
  "serial_no": ("SerialNo", constants.QFT_NUMBER),
320 8235fe04 Michael Hanselmann
  "uuid": ("UUID", constants.QFT_TEXT),
321 8235fe04 Michael Hanselmann
  "vm_capable": ("VMCapable", constants.QFT_BOOL),
322 8235fe04 Michael Hanselmann
  }
323 8235fe04 Michael Hanselmann
324 8235fe04 Michael Hanselmann
325 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
326 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
327 8235fe04 Michael Hanselmann
  "bootid": ("BootID", constants.QFT_TEXT, "bootid"),
328 8235fe04 Michael Hanselmann
  "cnodes": ("CNodes", constants.QFT_NUMBER, "cpu_nodes"),
329 8235fe04 Michael Hanselmann
  "csockets": ("CSockets", constants.QFT_NUMBER, "cpu_sockets"),
330 8235fe04 Michael Hanselmann
  "ctotal": ("CTotal", constants.QFT_NUMBER, "cpu_total"),
331 8235fe04 Michael Hanselmann
  "dfree": ("DFree", constants.QFT_UNIT, "vg_free"),
332 8235fe04 Michael Hanselmann
  "dtotal": ("DTotal", constants.QFT_UNIT, "vg_size"),
333 8235fe04 Michael Hanselmann
  "mfree": ("MFree", constants.QFT_UNIT, "memory_free"),
334 8235fe04 Michael Hanselmann
  "mnode": ("MNode", constants.QFT_UNIT, "memory_dom0"),
335 8235fe04 Michael Hanselmann
  "mtotal": ("MTotal", constants.QFT_UNIT, "memory_total"),
336 8235fe04 Michael Hanselmann
  }
337 8235fe04 Michael Hanselmann
338 8235fe04 Michael Hanselmann
339 8235fe04 Michael Hanselmann
def _GetNodeGroup(ctx, node):
340 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
341 8235fe04 Michael Hanselmann

342 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
343 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
344 8235fe04 Michael Hanselmann
  @param node: Node object
345 8235fe04 Michael Hanselmann

346 8235fe04 Michael Hanselmann
  """
347 8235fe04 Michael Hanselmann
  ng = ctx.groups.get(node.group, None)
348 8235fe04 Michael Hanselmann
  if ng is None:
349 8235fe04 Michael Hanselmann
    # Nodes always have a group, or the configuration is corrupt
350 8235fe04 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
351 8235fe04 Michael Hanselmann
352 8235fe04 Michael Hanselmann
  return (constants.QRFS_NORMAL, ng.name)
353 8235fe04 Michael Hanselmann
354 8235fe04 Michael Hanselmann
355 8235fe04 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, _):
356 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
357 8235fe04 Michael Hanselmann

358 8235fe04 Michael Hanselmann
  @param field: Live field name
359 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
360 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
361 8235fe04 Michael Hanselmann

362 8235fe04 Michael Hanselmann
  """
363 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
364 8235fe04 Michael Hanselmann
    return (constants.QRFS_NODATA, None)
365 8235fe04 Michael Hanselmann
366 8235fe04 Michael Hanselmann
  try:
367 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
368 8235fe04 Michael Hanselmann
  except KeyError:
369 8235fe04 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
370 8235fe04 Michael Hanselmann
371 8235fe04 Michael Hanselmann
  if kind == constants.QFT_TEXT:
372 8235fe04 Michael Hanselmann
    return (constants.QRFS_NORMAL, value)
373 8235fe04 Michael Hanselmann
374 8235fe04 Michael Hanselmann
  assert kind in (constants.QFT_NUMBER, constants.QFT_UNIT)
375 8235fe04 Michael Hanselmann
376 8235fe04 Michael Hanselmann
  # Try to convert into number
377 8235fe04 Michael Hanselmann
  try:
378 8235fe04 Michael Hanselmann
    return (constants.QRFS_NORMAL, int(value))
379 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
380 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
381 8235fe04 Michael Hanselmann
                      value, field)
382 8235fe04 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
383 8235fe04 Michael Hanselmann
384 8235fe04 Michael Hanselmann
385 8235fe04 Michael Hanselmann
def _BuildNodeFields():
386 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
387 8235fe04 Michael Hanselmann

388 8235fe04 Michael Hanselmann
  """
389 8235fe04 Michael Hanselmann
  fields = [
390 8235fe04 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", constants.QFT_TEXT), NQ_CONFIG,
391 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.primary_ip)),
392 8235fe04 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", constants.QFT_TEXT), NQ_CONFIG,
393 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.secondary_ip)),
394 8235fe04 Michael Hanselmann
    (_MakeField("tags", "Tags", constants.QFT_OTHER), NQ_CONFIG,
395 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, list(node.GetTags()))),
396 8235fe04 Michael Hanselmann
    (_MakeField("master", "IsMaster", constants.QFT_BOOL), NQ_CONFIG,
397 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.name == ctx.master_name)),
398 8235fe04 Michael Hanselmann
    (_MakeField("role", "Role", constants.QFT_TEXT), NQ_CONFIG,
399 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL,
400 8235fe04 Michael Hanselmann
                        _GetNodeRole(node, ctx.master_name))),
401 8235fe04 Michael Hanselmann
    (_MakeField("group", "Group", constants.QFT_TEXT), NQ_GROUP, _GetNodeGroup),
402 8235fe04 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", constants.QFT_TEXT),
403 8235fe04 Michael Hanselmann
     NQ_CONFIG, lambda ctx, node: (constants.QRFS_NORMAL, node.group)),
404 8235fe04 Michael Hanselmann
    ]
405 8235fe04 Michael Hanselmann
406 8235fe04 Michael Hanselmann
  def _GetLength(getter):
407 8235fe04 Michael Hanselmann
    return lambda ctx, node: (constants.QRFS_NORMAL,
408 8235fe04 Michael Hanselmann
                              len(getter(ctx)[node.name]))
409 8235fe04 Michael Hanselmann
410 8235fe04 Michael Hanselmann
  def _GetList(getter):
411 8235fe04 Michael Hanselmann
    return lambda ctx, node: (constants.QRFS_NORMAL,
412 8235fe04 Michael Hanselmann
                              list(getter(ctx)[node.name]))
413 8235fe04 Michael Hanselmann
414 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
415 8235fe04 Michael Hanselmann
  for prefix, titleprefix, getter in \
416 8235fe04 Michael Hanselmann
      [("p", "Pri", operator.attrgetter("node_to_primary")),
417 8235fe04 Michael Hanselmann
       ("s", "Sec", operator.attrgetter("node_to_secondary"))]:
418 8235fe04 Michael Hanselmann
    fields.extend([
419 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(),
420 8235fe04 Michael Hanselmann
                  constants.QFT_NUMBER),
421 8235fe04 Michael Hanselmann
       NQ_INST, _GetLength(getter)),
422 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
423 8235fe04 Michael Hanselmann
                  constants.QFT_OTHER),
424 8235fe04 Michael Hanselmann
       NQ_INST, _GetList(getter)),
425 8235fe04 Michael Hanselmann
      ])
426 8235fe04 Michael Hanselmann
427 8235fe04 Michael Hanselmann
  # Add simple fields
428 8235fe04 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), NQ_CONFIG, _GetItemAttr(name))
429 8235fe04 Michael Hanselmann
                 for (name, (title, kind)) in _NODE_SIMPLE_FIELDS.items()])
430 8235fe04 Michael Hanselmann
431 8235fe04 Michael Hanselmann
  # Add fields requiring live data
432 8235fe04 Michael Hanselmann
  fields.extend([
433 8235fe04 Michael Hanselmann
    (_MakeField(name, title, kind), NQ_LIVE,
434 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
435 8235fe04 Michael Hanselmann
    for (name, (title, kind, nfield)) in _NODE_LIVE_FIELDS.items()
436 8235fe04 Michael Hanselmann
    ])
437 8235fe04 Michael Hanselmann
438 8235fe04 Michael Hanselmann
  return _PrepareFieldList(fields)
439 8235fe04 Michael Hanselmann
440 8235fe04 Michael Hanselmann
441 8235fe04 Michael Hanselmann
#: Fields available for node queries
442 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()