Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 8572f1fe

History | View | Annotate | Download (34.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 52b5d286 René Nussbaumer
 NQ_GROUP,
40 52b5d286 René Nussbaumer
 NQ_OOB) = range(1, 6)
41 8235fe04 Michael Hanselmann
42 1c8addc6 Michael Hanselmann
(IQ_CONFIG,
43 1c8addc6 Michael Hanselmann
 IQ_LIVE,
44 1c8addc6 Michael Hanselmann
 IQ_DISKUSAGE) = range(100, 103)
45 1c8addc6 Michael Hanselmann
46 24d16f76 Michael Hanselmann
(LQ_MODE,
47 24d16f76 Michael Hanselmann
 LQ_OWNER,
48 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
49 8235fe04 Michael Hanselmann
50 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
51 8e21cfc0 Adeodato Simo
 GQ_NODE,
52 8e21cfc0 Adeodato Simo
 GQ_INST) = range(200, 203)
53 8e21cfc0 Adeodato Simo
54 8e21cfc0 Adeodato Simo
55 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
56 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
57 4ca96421 Michael Hanselmann
58 4ca96421 Michael Hanselmann
#: Verification function for each field type
59 4ca96421 Michael Hanselmann
_VERIFY_FN = {
60 4ca96421 Michael Hanselmann
  constants.QFT_UNKNOWN: ht.TNone,
61 4ca96421 Michael Hanselmann
  constants.QFT_TEXT: ht.TString,
62 4ca96421 Michael Hanselmann
  constants.QFT_BOOL: ht.TBool,
63 4ca96421 Michael Hanselmann
  constants.QFT_NUMBER: ht.TInt,
64 4ca96421 Michael Hanselmann
  constants.QFT_UNIT: ht.TInt,
65 4ca96421 Michael Hanselmann
  constants.QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat),
66 4ca96421 Michael Hanselmann
  constants.QFT_OTHER: lambda _: True,
67 4ca96421 Michael Hanselmann
  }
68 4ca96421 Michael Hanselmann
69 4ca96421 Michael Hanselmann
70 4ca96421 Michael Hanselmann
def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
71 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
72 4ca96421 Michael Hanselmann

73 4ca96421 Michael Hanselmann
  """
74 4ca96421 Michael Hanselmann
  return (constants.QRFS_UNKNOWN, None)
75 4ca96421 Michael Hanselmann
76 4ca96421 Michael Hanselmann
77 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
78 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
79 4ca96421 Michael Hanselmann

80 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
81 4ca96421 Michael Hanselmann

82 4ca96421 Michael Hanselmann
  @type fielddefs: dict
83 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
84 4ca96421 Michael Hanselmann
  @type selected: list of strings
85 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
86 4ca96421 Michael Hanselmann

87 4ca96421 Michael Hanselmann
  """
88 4ca96421 Michael Hanselmann
  result = []
89 4ca96421 Michael Hanselmann
90 4ca96421 Michael Hanselmann
  for name in selected:
91 4ca96421 Michael Hanselmann
    try:
92 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
93 4ca96421 Michael Hanselmann
    except KeyError:
94 4ca96421 Michael Hanselmann
      fdef = (_MakeField(name, name, constants.QFT_UNKNOWN),
95 4ca96421 Michael Hanselmann
              None, _GetUnknownField)
96 4ca96421 Michael Hanselmann
97 4ca96421 Michael Hanselmann
    assert len(fdef) == 3
98 4ca96421 Michael Hanselmann
99 4ca96421 Michael Hanselmann
    result.append(fdef)
100 4ca96421 Michael Hanselmann
101 4ca96421 Michael Hanselmann
  return result
102 4ca96421 Michael Hanselmann
103 4ca96421 Michael Hanselmann
104 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
105 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
106 4ca96421 Michael Hanselmann

107 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
108 4ca96421 Michael Hanselmann

109 4ca96421 Michael Hanselmann
  """
110 4ca96421 Michael Hanselmann
  return [fdef for (fdef, _, _) in fielddefs]
111 4ca96421 Michael Hanselmann
112 4ca96421 Michael Hanselmann
113 4ca96421 Michael Hanselmann
class Query:
114 4ca96421 Michael Hanselmann
  def __init__(self, fieldlist, selected):
115 4ca96421 Michael Hanselmann
    """Initializes this class.
116 4ca96421 Michael Hanselmann

117 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
118 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
119 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
120 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
121 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
122 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
123 4ca96421 Michael Hanselmann

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

127 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
128 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
129 4ca96421 Michael Hanselmann
    @type selected: list of strings
130 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
131 4ca96421 Michael Hanselmann

132 4ca96421 Michael Hanselmann
    """
133 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
134 4ca96421 Michael Hanselmann
135 4ca96421 Michael Hanselmann
  def RequestedData(self):
136 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
137 4ca96421 Michael Hanselmann

138 4ca96421 Michael Hanselmann
    @rtype: frozenset
139 4ca96421 Michael Hanselmann

140 4ca96421 Michael Hanselmann
    """
141 4ca96421 Michael Hanselmann
    return frozenset(datakind
142 4ca96421 Michael Hanselmann
                     for (_, datakind, _) in self._fields
143 4ca96421 Michael Hanselmann
                     if datakind is not None)
144 4ca96421 Michael Hanselmann
145 4ca96421 Michael Hanselmann
  def GetFields(self):
146 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
147 4ca96421 Michael Hanselmann

148 4ca96421 Michael Hanselmann
    Includes unknown fields.
149 4ca96421 Michael Hanselmann

150 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
151 4ca96421 Michael Hanselmann

152 4ca96421 Michael Hanselmann
    """
153 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
154 4ca96421 Michael Hanselmann
155 4ca96421 Michael Hanselmann
  def Query(self, ctx):
156 4ca96421 Michael Hanselmann
    """Execute a query.
157 4ca96421 Michael Hanselmann

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

161 4ca96421 Michael Hanselmann
    """
162 4ca96421 Michael Hanselmann
    result = [[fn(ctx, item) for (_, _, fn) in self._fields]
163 4ca96421 Michael Hanselmann
              for item in ctx]
164 4ca96421 Michael Hanselmann
165 4ca96421 Michael Hanselmann
    # Verify result
166 4ca96421 Michael Hanselmann
    if __debug__:
167 4ca96421 Michael Hanselmann
      for (idx, row) in enumerate(result):
168 4ca96421 Michael Hanselmann
        assert _VerifyResultRow(self._fields, row), \
169 4ca96421 Michael Hanselmann
               ("Inconsistent result for fields %s in row %s: %r" %
170 89ce4acc Michael Hanselmann
                (GetAllFields(self._fields), idx, row))
171 4ca96421 Michael Hanselmann
172 4ca96421 Michael Hanselmann
    return result
173 4ca96421 Michael Hanselmann
174 4ca96421 Michael Hanselmann
  def OldStyleQuery(self, ctx):
175 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
176 4ca96421 Michael Hanselmann

177 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
178 4ca96421 Michael Hanselmann

179 4ca96421 Michael Hanselmann
    """
180 4ca96421 Michael Hanselmann
    unknown = set(fdef.name
181 4ca96421 Michael Hanselmann
                  for (fdef, _, _) in self._fields
182 4ca96421 Michael Hanselmann
                  if fdef.kind == constants.QFT_UNKNOWN)
183 4ca96421 Michael Hanselmann
    if unknown:
184 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
185 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
186 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
187 4ca96421 Michael Hanselmann
188 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
189 4ca96421 Michael Hanselmann
            for row in self.Query(ctx)]
190 4ca96421 Michael Hanselmann
191 4ca96421 Michael Hanselmann
192 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
193 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
194 4ca96421 Michael Hanselmann

195 4ca96421 Michael Hanselmann
  @type fields: list
196 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
197 4ca96421 Michael Hanselmann
  @type row: list of tuples
198 4ca96421 Michael Hanselmann
  @param row: Row data
199 4ca96421 Michael Hanselmann

200 4ca96421 Michael Hanselmann
  """
201 4ca96421 Michael Hanselmann
  return (len(row) == len(fields) and
202 4ca96421 Michael Hanselmann
          compat.all((status == constants.QRFS_NORMAL and
203 4ca96421 Michael Hanselmann
                      _VERIFY_FN[fdef.kind](value)) or
204 4ca96421 Michael Hanselmann
                     # Value for an abnormal status must be None
205 4ca96421 Michael Hanselmann
                     (status != constants.QRFS_NORMAL and value is None)
206 4ca96421 Michael Hanselmann
                     for ((status, value), (fdef, _, _)) in zip(row, fields)))
207 4ca96421 Michael Hanselmann
208 4ca96421 Michael Hanselmann
209 4ca96421 Michael Hanselmann
def _PrepareFieldList(fields):
210 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
211 4ca96421 Michael Hanselmann

212 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
213 4ca96421 Michael Hanselmann

214 4ca96421 Michael Hanselmann
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data kind,
215 4ca96421 Michael Hanselmann
    retrieval function)
216 4ca96421 Michael Hanselmann
  @param fields: List of fields
217 4ca96421 Michael Hanselmann
  @rtype: dict
218 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
219 4ca96421 Michael Hanselmann

220 4ca96421 Michael Hanselmann
  """
221 89ce4acc Michael Hanselmann
  if __debug__:
222 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
223 89ce4acc Michael Hanselmann
                                      for (fdef, _, _) in fields)
224 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
225 4ca96421 Michael Hanselmann
226 4ca96421 Michael Hanselmann
  result = {}
227 4ca96421 Michael Hanselmann
228 4ca96421 Michael Hanselmann
  for field in fields:
229 4ca96421 Michael Hanselmann
    (fdef, _, fn) = field
230 4ca96421 Michael Hanselmann
231 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
232 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
233 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
234 4ca96421 Michael Hanselmann
    assert callable(fn)
235 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
236 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
237 4ca96421 Michael Hanselmann
238 4ca96421 Michael Hanselmann
    result[fdef.name] = field
239 4ca96421 Michael Hanselmann
240 4ca96421 Michael Hanselmann
  assert len(result) == len(fields)
241 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
242 4ca96421 Michael Hanselmann
                    for (name, (fdef, _, _)) in result.items())
243 4ca96421 Michael Hanselmann
244 4ca96421 Michael Hanselmann
  return result
245 4ca96421 Michael Hanselmann
246 4ca96421 Michael Hanselmann
247 b60fcb6f Michael Hanselmann
def GetQueryResponse(query, ctx):
248 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
249 b60fcb6f Michael Hanselmann

250 b60fcb6f Michael Hanselmann
  @type query: L{Query}
251 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
252 b60fcb6f Michael Hanselmann

253 b60fcb6f Michael Hanselmann
  """
254 b60fcb6f Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx),
255 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
256 b60fcb6f Michael Hanselmann
257 b60fcb6f Michael Hanselmann
258 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
259 aa29e95f Michael Hanselmann
  """Returns list of available fields.
260 aa29e95f Michael Hanselmann

261 aa29e95f Michael Hanselmann
  @type fielddefs: dict
262 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
263 aa29e95f Michael Hanselmann
  @type selected: list of strings
264 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
265 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
266 aa29e95f Michael Hanselmann

267 aa29e95f Michael Hanselmann
  """
268 aa29e95f Michael Hanselmann
  if selected is None:
269 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
270 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
271 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
272 aa29e95f Michael Hanselmann
  else:
273 aa29e95f Michael Hanselmann
    # Keep order as requested by client
274 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
275 aa29e95f Michael Hanselmann
276 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
277 aa29e95f Michael Hanselmann
278 aa29e95f Michael Hanselmann
279 4ca96421 Michael Hanselmann
def _MakeField(name, title, kind):
280 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
281 4ca96421 Michael Hanselmann

282 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
283 4ca96421 Michael Hanselmann
  @param title: Human-readable title
284 4ca96421 Michael Hanselmann
  @param kind: Field type
285 4ca96421 Michael Hanselmann

286 4ca96421 Michael Hanselmann
  """
287 4ca96421 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind)
288 8235fe04 Michael Hanselmann
289 8235fe04 Michael Hanselmann
290 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
291 8235fe04 Michael Hanselmann
  """Determine node role.
292 8235fe04 Michael Hanselmann

293 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
294 8235fe04 Michael Hanselmann
  @param node: Node object
295 8235fe04 Michael Hanselmann
  @type master_name: string
296 8235fe04 Michael Hanselmann
  @param master_name: Master node name
297 8235fe04 Michael Hanselmann

298 8235fe04 Michael Hanselmann
  """
299 8235fe04 Michael Hanselmann
  if node.name == master_name:
300 8235fe04 Michael Hanselmann
    return "M"
301 8235fe04 Michael Hanselmann
  elif node.master_candidate:
302 8235fe04 Michael Hanselmann
    return "C"
303 8235fe04 Michael Hanselmann
  elif node.drained:
304 8235fe04 Michael Hanselmann
    return "D"
305 8235fe04 Michael Hanselmann
  elif node.offline:
306 8235fe04 Michael Hanselmann
    return "O"
307 8235fe04 Michael Hanselmann
  else:
308 8235fe04 Michael Hanselmann
    return "R"
309 8235fe04 Michael Hanselmann
310 8235fe04 Michael Hanselmann
311 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
312 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
313 8235fe04 Michael Hanselmann

314 8235fe04 Michael Hanselmann
  @param attr: Attribute name
315 8235fe04 Michael Hanselmann

316 8235fe04 Michael Hanselmann
  """
317 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
318 8235fe04 Michael Hanselmann
  return lambda _, item: (constants.QRFS_NORMAL, getter(item))
319 8235fe04 Michael Hanselmann
320 8235fe04 Michael Hanselmann
321 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
322 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
323 145bea54 Michael Hanselmann

324 145bea54 Michael Hanselmann
  @type getter: callable
325 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
326 145bea54 Michael Hanselmann

327 145bea54 Michael Hanselmann
  """
328 145bea54 Michael Hanselmann
  def fn(_, item):
329 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
330 145bea54 Michael Hanselmann

331 145bea54 Michael Hanselmann
    """
332 145bea54 Michael Hanselmann
    timestamp = getter(item)
333 145bea54 Michael Hanselmann
    if timestamp is None:
334 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
335 145bea54 Michael Hanselmann
      return (constants.QRFS_UNAVAIL, None)
336 145bea54 Michael Hanselmann
    else:
337 145bea54 Michael Hanselmann
      return (constants.QRFS_NORMAL, timestamp)
338 145bea54 Michael Hanselmann
339 145bea54 Michael Hanselmann
  return fn
340 145bea54 Michael Hanselmann
341 145bea54 Michael Hanselmann
342 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
343 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
344 145bea54 Michael Hanselmann

345 145bea54 Michael Hanselmann
  @param datatype: Field data type for use by L{Query.RequestedData}
346 145bea54 Michael Hanselmann

347 145bea54 Michael Hanselmann
  """
348 145bea54 Michael Hanselmann
  return [
349 145bea54 Michael Hanselmann
    (_MakeField("ctime", "CTime", constants.QFT_TIMESTAMP), datatype,
350 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("ctime"))),
351 145bea54 Michael Hanselmann
    (_MakeField("mtime", "MTime", constants.QFT_TIMESTAMP), datatype,
352 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("mtime"))),
353 145bea54 Michael Hanselmann
    ]
354 145bea54 Michael Hanselmann
355 145bea54 Michael Hanselmann
356 8235fe04 Michael Hanselmann
class NodeQueryData:
357 8235fe04 Michael Hanselmann
  """Data container for node data queries.
358 8235fe04 Michael Hanselmann

359 8235fe04 Michael Hanselmann
  """
360 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
361 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
362 8235fe04 Michael Hanselmann
    """Initializes this class.
363 8235fe04 Michael Hanselmann

364 8235fe04 Michael Hanselmann
    """
365 8235fe04 Michael Hanselmann
    self.nodes = nodes
366 8235fe04 Michael Hanselmann
    self.live_data = live_data
367 8235fe04 Michael Hanselmann
    self.master_name = master_name
368 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
369 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
370 8235fe04 Michael Hanselmann
    self.groups = groups
371 52b5d286 René Nussbaumer
    self.oob_support = oob_support
372 8572f1fe René Nussbaumer
    self.cluster = cluster
373 8235fe04 Michael Hanselmann
374 8235fe04 Michael Hanselmann
    # Used for individual rows
375 8235fe04 Michael Hanselmann
    self.curlive_data = None
376 8235fe04 Michael Hanselmann
377 8235fe04 Michael Hanselmann
  def __iter__(self):
378 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
379 8235fe04 Michael Hanselmann

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

383 8235fe04 Michael Hanselmann
    """
384 8235fe04 Michael Hanselmann
    for node in self.nodes:
385 8235fe04 Michael Hanselmann
      if self.live_data:
386 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
387 8235fe04 Michael Hanselmann
      else:
388 8235fe04 Michael Hanselmann
        self.curlive_data = None
389 8235fe04 Michael Hanselmann
      yield node
390 8235fe04 Michael Hanselmann
391 8235fe04 Michael Hanselmann
392 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
393 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
394 8235fe04 Michael Hanselmann
  "drained": ("Drained", constants.QFT_BOOL),
395 8235fe04 Michael Hanselmann
  "master_candidate": ("MasterC", constants.QFT_BOOL),
396 8235fe04 Michael Hanselmann
  "master_capable": ("MasterCapable", constants.QFT_BOOL),
397 8235fe04 Michael Hanselmann
  "name": ("Node", constants.QFT_TEXT),
398 8235fe04 Michael Hanselmann
  "offline": ("Offline", constants.QFT_BOOL),
399 8235fe04 Michael Hanselmann
  "serial_no": ("SerialNo", constants.QFT_NUMBER),
400 8235fe04 Michael Hanselmann
  "uuid": ("UUID", constants.QFT_TEXT),
401 8235fe04 Michael Hanselmann
  "vm_capable": ("VMCapable", constants.QFT_BOOL),
402 8235fe04 Michael Hanselmann
  }
403 8235fe04 Michael Hanselmann
404 8235fe04 Michael Hanselmann
405 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
406 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
407 8235fe04 Michael Hanselmann
  "bootid": ("BootID", constants.QFT_TEXT, "bootid"),
408 8235fe04 Michael Hanselmann
  "cnodes": ("CNodes", constants.QFT_NUMBER, "cpu_nodes"),
409 8235fe04 Michael Hanselmann
  "csockets": ("CSockets", constants.QFT_NUMBER, "cpu_sockets"),
410 8235fe04 Michael Hanselmann
  "ctotal": ("CTotal", constants.QFT_NUMBER, "cpu_total"),
411 8235fe04 Michael Hanselmann
  "dfree": ("DFree", constants.QFT_UNIT, "vg_free"),
412 8235fe04 Michael Hanselmann
  "dtotal": ("DTotal", constants.QFT_UNIT, "vg_size"),
413 8235fe04 Michael Hanselmann
  "mfree": ("MFree", constants.QFT_UNIT, "memory_free"),
414 8235fe04 Michael Hanselmann
  "mnode": ("MNode", constants.QFT_UNIT, "memory_dom0"),
415 8235fe04 Michael Hanselmann
  "mtotal": ("MTotal", constants.QFT_UNIT, "memory_total"),
416 8235fe04 Michael Hanselmann
  }
417 8235fe04 Michael Hanselmann
418 8235fe04 Michael Hanselmann
419 8572f1fe René Nussbaumer
def _GetGroup(cb):
420 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
421 8572f1fe René Nussbaumer

422 8572f1fe René Nussbaumer
  @param cb: The callback to be called with the nodegroup
423 8572f1fe René Nussbaumer

424 8572f1fe René Nussbaumer
  """
425 8572f1fe René Nussbaumer
  def fn(ctx, node):
426 8572f1fe René Nussbaumer
    """Get group data for a node.
427 8572f1fe René Nussbaumer

428 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
429 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
430 8572f1fe René Nussbaumer
    @param inst: Node object
431 8572f1fe René Nussbaumer

432 8572f1fe René Nussbaumer
    """
433 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
434 8572f1fe René Nussbaumer
    if ng is None:
435 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
436 8572f1fe René Nussbaumer
      return (constants.QRFS_UNAVAIL, None)
437 8572f1fe René Nussbaumer
438 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
439 8572f1fe René Nussbaumer
440 8572f1fe René Nussbaumer
  return fn
441 8572f1fe René Nussbaumer
442 8572f1fe René Nussbaumer
443 8572f1fe René Nussbaumer
def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613
444 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
445 8235fe04 Michael Hanselmann

446 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
447 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
448 8235fe04 Michael Hanselmann
  @param node: Node object
449 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
450 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
451 8235fe04 Michael Hanselmann

452 8235fe04 Michael Hanselmann
  """
453 8235fe04 Michael Hanselmann
  return (constants.QRFS_NORMAL, ng.name)
454 8235fe04 Michael Hanselmann
455 8235fe04 Michael Hanselmann
456 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
457 52b5d286 René Nussbaumer
  """Returns the node powered state
458 52b5d286 René Nussbaumer

459 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
460 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
461 52b5d286 René Nussbaumer
  @param node: Node object
462 52b5d286 René Nussbaumer

463 52b5d286 René Nussbaumer
  """
464 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
465 52b5d286 René Nussbaumer
    return (constants.QRFS_NORMAL, node.powered)
466 52b5d286 René Nussbaumer
467 52b5d286 René Nussbaumer
  return (constants.QRFS_UNAVAIL, None)
468 52b5d286 René Nussbaumer
469 52b5d286 René Nussbaumer
470 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
471 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
472 8572f1fe René Nussbaumer

473 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
474 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
475 8572f1fe René Nussbaumer
  @param node: Node object
476 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
477 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
478 8572f1fe René Nussbaumer

479 8572f1fe René Nussbaumer
  """
480 8572f1fe René Nussbaumer
  return (constants.QRFS_NORMAL, ctx.cluster.SimpleFillND(ng.FillND(node)))
481 8572f1fe René Nussbaumer
482 8572f1fe René Nussbaumer
483 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
484 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
485 8235fe04 Michael Hanselmann

486 8235fe04 Michael Hanselmann
  @param field: Live field name
487 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
488 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
489 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
490 a6070ef7 Michael Hanselmann
  @param node: Node object
491 8235fe04 Michael Hanselmann

492 8235fe04 Michael Hanselmann
  """
493 a6070ef7 Michael Hanselmann
  if node.offline:
494 a6070ef7 Michael Hanselmann
    return (constants.QRFS_OFFLINE, None)
495 a6070ef7 Michael Hanselmann
496 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
497 8235fe04 Michael Hanselmann
    return (constants.QRFS_NODATA, None)
498 8235fe04 Michael Hanselmann
499 8235fe04 Michael Hanselmann
  try:
500 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
501 8235fe04 Michael Hanselmann
  except KeyError:
502 8235fe04 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
503 8235fe04 Michael Hanselmann
504 8235fe04 Michael Hanselmann
  if kind == constants.QFT_TEXT:
505 8235fe04 Michael Hanselmann
    return (constants.QRFS_NORMAL, value)
506 8235fe04 Michael Hanselmann
507 8235fe04 Michael Hanselmann
  assert kind in (constants.QFT_NUMBER, constants.QFT_UNIT)
508 8235fe04 Michael Hanselmann
509 8235fe04 Michael Hanselmann
  # Try to convert into number
510 8235fe04 Michael Hanselmann
  try:
511 8235fe04 Michael Hanselmann
    return (constants.QRFS_NORMAL, int(value))
512 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
513 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
514 8235fe04 Michael Hanselmann
                      value, field)
515 8235fe04 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
516 8235fe04 Michael Hanselmann
517 8235fe04 Michael Hanselmann
518 8235fe04 Michael Hanselmann
def _BuildNodeFields():
519 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
520 8235fe04 Michael Hanselmann

521 8235fe04 Michael Hanselmann
  """
522 8235fe04 Michael Hanselmann
  fields = [
523 8235fe04 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", constants.QFT_TEXT), NQ_CONFIG,
524 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.primary_ip)),
525 8235fe04 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", constants.QFT_TEXT), NQ_CONFIG,
526 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.secondary_ip)),
527 8235fe04 Michael Hanselmann
    (_MakeField("tags", "Tags", constants.QFT_OTHER), NQ_CONFIG,
528 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, list(node.GetTags()))),
529 8235fe04 Michael Hanselmann
    (_MakeField("master", "IsMaster", constants.QFT_BOOL), NQ_CONFIG,
530 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.name == ctx.master_name)),
531 8235fe04 Michael Hanselmann
    (_MakeField("role", "Role", constants.QFT_TEXT), NQ_CONFIG,
532 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL,
533 8235fe04 Michael Hanselmann
                        _GetNodeRole(node, ctx.master_name))),
534 8572f1fe René Nussbaumer
    (_MakeField("group", "Group", constants.QFT_TEXT), NQ_GROUP,
535 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
536 8235fe04 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", constants.QFT_TEXT),
537 8235fe04 Michael Hanselmann
     NQ_CONFIG, lambda ctx, node: (constants.QRFS_NORMAL, node.group)),
538 52b5d286 René Nussbaumer
    (_MakeField("powered", "Powered", constants.QFT_BOOL), NQ_OOB,
539 52b5d286 René Nussbaumer
      _GetNodePower),
540 8572f1fe René Nussbaumer
    (_MakeField("ndparams", "NodeParameters", constants.QFT_OTHER), NQ_GROUP,
541 8572f1fe René Nussbaumer
      _GetGroup(_GetNdParams)),
542 8572f1fe René Nussbaumer
    (_MakeField("custom_ndparams", "CustomNodeParameters", constants.QFT_OTHER),
543 8572f1fe René Nussbaumer
      NQ_GROUP, lambda ctx, node: (constants.QRFS_NORMAL, node.ndparams)),
544 8235fe04 Michael Hanselmann
    ]
545 8235fe04 Michael Hanselmann
546 8235fe04 Michael Hanselmann
  def _GetLength(getter):
547 8235fe04 Michael Hanselmann
    return lambda ctx, node: (constants.QRFS_NORMAL,
548 8235fe04 Michael Hanselmann
                              len(getter(ctx)[node.name]))
549 8235fe04 Michael Hanselmann
550 8235fe04 Michael Hanselmann
  def _GetList(getter):
551 8235fe04 Michael Hanselmann
    return lambda ctx, node: (constants.QRFS_NORMAL,
552 8235fe04 Michael Hanselmann
                              list(getter(ctx)[node.name]))
553 8235fe04 Michael Hanselmann
554 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
555 8235fe04 Michael Hanselmann
  for prefix, titleprefix, getter in \
556 8235fe04 Michael Hanselmann
      [("p", "Pri", operator.attrgetter("node_to_primary")),
557 8235fe04 Michael Hanselmann
       ("s", "Sec", operator.attrgetter("node_to_secondary"))]:
558 8235fe04 Michael Hanselmann
    fields.extend([
559 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(),
560 8235fe04 Michael Hanselmann
                  constants.QFT_NUMBER),
561 8235fe04 Michael Hanselmann
       NQ_INST, _GetLength(getter)),
562 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
563 8235fe04 Michael Hanselmann
                  constants.QFT_OTHER),
564 8235fe04 Michael Hanselmann
       NQ_INST, _GetList(getter)),
565 8235fe04 Michael Hanselmann
      ])
566 8235fe04 Michael Hanselmann
567 8235fe04 Michael Hanselmann
  # Add simple fields
568 8235fe04 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), NQ_CONFIG, _GetItemAttr(name))
569 8235fe04 Michael Hanselmann
                 for (name, (title, kind)) in _NODE_SIMPLE_FIELDS.items()])
570 8235fe04 Michael Hanselmann
571 8235fe04 Michael Hanselmann
  # Add fields requiring live data
572 8235fe04 Michael Hanselmann
  fields.extend([
573 8235fe04 Michael Hanselmann
    (_MakeField(name, title, kind), NQ_LIVE,
574 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
575 8235fe04 Michael Hanselmann
    for (name, (title, kind, nfield)) in _NODE_LIVE_FIELDS.items()
576 8235fe04 Michael Hanselmann
    ])
577 8235fe04 Michael Hanselmann
578 145bea54 Michael Hanselmann
  # Add timestamps
579 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
580 145bea54 Michael Hanselmann
581 8235fe04 Michael Hanselmann
  return _PrepareFieldList(fields)
582 8235fe04 Michael Hanselmann
583 8235fe04 Michael Hanselmann
584 1c8addc6 Michael Hanselmann
class InstanceQueryData:
585 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
586 1c8addc6 Michael Hanselmann

587 1c8addc6 Michael Hanselmann
  """
588 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
589 1c8addc6 Michael Hanselmann
               live_data):
590 1c8addc6 Michael Hanselmann
    """Initializes this class.
591 1c8addc6 Michael Hanselmann

592 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
593 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
594 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
595 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
596 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
597 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
598 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
599 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
600 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
601 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
602 1c8addc6 Michael Hanselmann

603 1c8addc6 Michael Hanselmann
    """
604 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
605 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
606 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
607 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
608 1c8addc6 Michael Hanselmann
609 1c8addc6 Michael Hanselmann
    self.instances = instances
610 1c8addc6 Michael Hanselmann
    self.cluster = cluster
611 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
612 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
613 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
614 1c8addc6 Michael Hanselmann
    self.live_data = live_data
615 1c8addc6 Michael Hanselmann
616 1c8addc6 Michael Hanselmann
    # Used for individual rows
617 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
618 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
619 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
620 1c8addc6 Michael Hanselmann
621 1c8addc6 Michael Hanselmann
  def __iter__(self):
622 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
623 1c8addc6 Michael Hanselmann

624 1c8addc6 Michael Hanselmann
    This function has side-effects and only one instance of the resulting
625 1c8addc6 Michael Hanselmann
    generator should be used at a time.
626 1c8addc6 Michael Hanselmann

627 1c8addc6 Michael Hanselmann
    """
628 1c8addc6 Michael Hanselmann
    for inst in self.instances:
629 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
630 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
631 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
632 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
633 1c8addc6 Michael Hanselmann
634 1c8addc6 Michael Hanselmann
      yield inst
635 1c8addc6 Michael Hanselmann
636 1c8addc6 Michael Hanselmann
637 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
638 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
639 1c8addc6 Michael Hanselmann

640 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
641 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
642 1c8addc6 Michael Hanselmann
  @param inst: Instance object
643 1c8addc6 Michael Hanselmann

644 1c8addc6 Michael Hanselmann
  """
645 a6070ef7 Michael Hanselmann
  # Can't use QRFS_OFFLINE here as it would describe the instance to be offline
646 a6070ef7 Michael Hanselmann
  # when we actually don't know due to missing data
647 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
648 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NODATA, None)
649 1c8addc6 Michael Hanselmann
  else:
650 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, bool(ctx.live_data.get(inst.name)))
651 1c8addc6 Michael Hanselmann
652 1c8addc6 Michael Hanselmann
653 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
654 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
655 1c8addc6 Michael Hanselmann

656 1c8addc6 Michael Hanselmann
  @type name: string
657 1c8addc6 Michael Hanselmann
  @param name: Live data field name
658 1c8addc6 Michael Hanselmann

659 1c8addc6 Michael Hanselmann
  """
660 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
661 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
662 1c8addc6 Michael Hanselmann

663 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
664 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
665 1c8addc6 Michael Hanselmann
    @param inst: Instance object
666 1c8addc6 Michael Hanselmann

667 1c8addc6 Michael Hanselmann
    """
668 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
669 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
670 a6070ef7 Michael Hanselmann
      # Can't use QRFS_OFFLINE here as it would describe the instance to be
671 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
672 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NODATA, None)
673 1c8addc6 Michael Hanselmann
674 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
675 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
676 1c8addc6 Michael Hanselmann
      if name in data:
677 1c8addc6 Michael Hanselmann
        return (constants.QRFS_NORMAL, data[name])
678 1c8addc6 Michael Hanselmann
679 1c8addc6 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
680 1c8addc6 Michael Hanselmann
681 1c8addc6 Michael Hanselmann
  return fn
682 1c8addc6 Michael Hanselmann
683 1c8addc6 Michael Hanselmann
684 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
685 1c8addc6 Michael Hanselmann
  """Get instance status.
686 1c8addc6 Michael Hanselmann

687 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
688 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
689 1c8addc6 Michael Hanselmann
  @param inst: Instance object
690 1c8addc6 Michael Hanselmann

691 1c8addc6 Michael Hanselmann
  """
692 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
693 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, "ERROR_nodeoffline")
694 1c8addc6 Michael Hanselmann
695 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
696 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, "ERROR_nodedown")
697 1c8addc6 Michael Hanselmann
698 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
699 1c8addc6 Michael Hanselmann
    if inst.admin_up:
700 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NORMAL, "running")
701 1c8addc6 Michael Hanselmann
    else:
702 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NORMAL, "ERROR_up")
703 1c8addc6 Michael Hanselmann
704 1c8addc6 Michael Hanselmann
  if inst.admin_up:
705 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, "ERROR_down")
706 1c8addc6 Michael Hanselmann
707 1c8addc6 Michael Hanselmann
  return (constants.QRFS_NORMAL, "ADMIN_down")
708 1c8addc6 Michael Hanselmann
709 1c8addc6 Michael Hanselmann
710 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
711 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
712 1c8addc6 Michael Hanselmann

713 1c8addc6 Michael Hanselmann
  @type index: int
714 1c8addc6 Michael Hanselmann
  @param index: Disk index
715 1c8addc6 Michael Hanselmann

716 1c8addc6 Michael Hanselmann
  """
717 1c8addc6 Michael Hanselmann
  def fn(_, inst):
718 1c8addc6 Michael Hanselmann
    """Get size of a disk.
719 1c8addc6 Michael Hanselmann

720 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
721 1c8addc6 Michael Hanselmann
    @param inst: Instance object
722 1c8addc6 Michael Hanselmann

723 1c8addc6 Michael Hanselmann
    """
724 1c8addc6 Michael Hanselmann
    try:
725 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NORMAL, inst.disks[index].size)
726 1c8addc6 Michael Hanselmann
    except IndexError:
727 1c8addc6 Michael Hanselmann
      return (constants.QRFS_UNAVAIL, None)
728 1c8addc6 Michael Hanselmann
729 1c8addc6 Michael Hanselmann
  return fn
730 1c8addc6 Michael Hanselmann
731 1c8addc6 Michael Hanselmann
732 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
733 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
734 1c8addc6 Michael Hanselmann

735 1c8addc6 Michael Hanselmann
  @type index: int
736 1c8addc6 Michael Hanselmann
  @param index: NIC index
737 1c8addc6 Michael Hanselmann
  @type cb: callable
738 1c8addc6 Michael Hanselmann
  @param cb: Callback
739 1c8addc6 Michael Hanselmann

740 1c8addc6 Michael Hanselmann
  """
741 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
742 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
743 1c8addc6 Michael Hanselmann

744 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
745 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
746 1c8addc6 Michael Hanselmann
    @param inst: Instance object
747 1c8addc6 Michael Hanselmann

748 1c8addc6 Michael Hanselmann
    """
749 1c8addc6 Michael Hanselmann
    try:
750 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
751 1c8addc6 Michael Hanselmann
    except IndexError:
752 1c8addc6 Michael Hanselmann
      return (constants.QRFS_UNAVAIL, None)
753 1c8addc6 Michael Hanselmann
754 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
755 1c8addc6 Michael Hanselmann
756 1c8addc6 Michael Hanselmann
  return fn
757 1c8addc6 Michael Hanselmann
758 1c8addc6 Michael Hanselmann
759 1c8addc6 Michael Hanselmann
def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613
760 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
761 1c8addc6 Michael Hanselmann

762 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
763 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
764 1c8addc6 Michael Hanselmann
  @param nic: NIC object
765 1c8addc6 Michael Hanselmann

766 1c8addc6 Michael Hanselmann
  """
767 1c8addc6 Michael Hanselmann
  if nic.ip is None:
768 1c8addc6 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
769 1c8addc6 Michael Hanselmann
  else:
770 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, nic.ip)
771 1c8addc6 Michael Hanselmann
772 1c8addc6 Michael Hanselmann
773 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
774 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
775 1c8addc6 Michael Hanselmann

776 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
777 1c8addc6 Michael Hanselmann
  @type index: int
778 1c8addc6 Michael Hanselmann
  @param index: NIC index
779 1c8addc6 Michael Hanselmann

780 1c8addc6 Michael Hanselmann
  """
781 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
782 1c8addc6 Michael Hanselmann
783 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
784 1c8addc6 Michael Hanselmann
785 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
786 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, nicparams[constants.NIC_LINK])
787 1c8addc6 Michael Hanselmann
  else:
788 1c8addc6 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
789 1c8addc6 Michael Hanselmann
790 1c8addc6 Michael Hanselmann
791 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
792 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
793 1c8addc6 Michael Hanselmann

794 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
795 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
796 1c8addc6 Michael Hanselmann
  @param inst: Instance object
797 1c8addc6 Michael Hanselmann

798 1c8addc6 Michael Hanselmann
  """
799 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
800 1c8addc6 Michael Hanselmann
801 1c8addc6 Michael Hanselmann
  result = []
802 1c8addc6 Michael Hanselmann
803 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
804 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
805 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
806 1c8addc6 Michael Hanselmann
    else:
807 1c8addc6 Michael Hanselmann
      result.append(None)
808 1c8addc6 Michael Hanselmann
809 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
810 1c8addc6 Michael Hanselmann
811 1c8addc6 Michael Hanselmann
  return (constants.QRFS_NORMAL, result)
812 1c8addc6 Michael Hanselmann
813 1c8addc6 Michael Hanselmann
814 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
815 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
816 1c8addc6 Michael Hanselmann

817 1c8addc6 Michael Hanselmann
  @type name: string
818 1c8addc6 Michael Hanselmann
  @param name: Parameter name
819 1c8addc6 Michael Hanselmann

820 1c8addc6 Michael Hanselmann
  """
821 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
822 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
823 1c8addc6 Michael Hanselmann

824 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
825 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
826 1c8addc6 Michael Hanselmann
    @param inst: Instance object
827 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
828 1c8addc6 Michael Hanselmann
    @param nic: NIC object
829 1c8addc6 Michael Hanselmann

830 1c8addc6 Michael Hanselmann
    """
831 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
832 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, ctx.inst_nicparams[index][name])
833 1c8addc6 Michael Hanselmann
834 1c8addc6 Michael Hanselmann
  return fn
835 1c8addc6 Michael Hanselmann
836 1c8addc6 Michael Hanselmann
837 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
838 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
839 1c8addc6 Michael Hanselmann

840 1c8addc6 Michael Hanselmann
  @return: List of field definitions used as input for L{_PrepareFieldList}
841 1c8addc6 Michael Hanselmann

842 1c8addc6 Michael Hanselmann
  """
843 1c8addc6 Michael Hanselmann
  nic_mac_fn = lambda ctx, _, nic: (constants.QRFS_NORMAL, nic.mac)
844 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
845 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
846 1c8addc6 Michael Hanselmann
847 1c8addc6 Michael Hanselmann
  fields = [
848 1c8addc6 Michael Hanselmann
    # First NIC (legacy)
849 1c8addc6 Michael Hanselmann
    (_MakeField("ip", "IP_address", constants.QFT_TEXT), IQ_CONFIG,
850 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicIp)),
851 1c8addc6 Michael Hanselmann
    (_MakeField("mac", "MAC_address", constants.QFT_TEXT), IQ_CONFIG,
852 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mac_fn)),
853 1c8addc6 Michael Hanselmann
    (_MakeField("bridge", "Bridge", constants.QFT_TEXT), IQ_CONFIG,
854 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicBridge)),
855 1c8addc6 Michael Hanselmann
    (_MakeField("nic_mode", "NIC_Mode", constants.QFT_TEXT), IQ_CONFIG,
856 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mode_fn)),
857 1c8addc6 Michael Hanselmann
    (_MakeField("nic_link", "NIC_Link", constants.QFT_TEXT), IQ_CONFIG,
858 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_link_fn)),
859 1c8addc6 Michael Hanselmann
860 1c8addc6 Michael Hanselmann
    # All NICs
861 1c8addc6 Michael Hanselmann
    (_MakeField("nic.count", "NICs", constants.QFT_NUMBER), IQ_CONFIG,
862 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, len(inst.nics))),
863 1c8addc6 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", constants.QFT_OTHER), IQ_CONFIG,
864 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, [nic.mac for nic in inst.nics])),
865 1c8addc6 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", constants.QFT_OTHER), IQ_CONFIG,
866 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, [nic.ip for nic in inst.nics])),
867 1c8addc6 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", constants.QFT_OTHER), IQ_CONFIG,
868 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL,
869 1c8addc6 Michael Hanselmann
                        [nicp[constants.NIC_MODE]
870 1c8addc6 Michael Hanselmann
                         for nicp in ctx.inst_nicparams])),
871 1c8addc6 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", constants.QFT_OTHER), IQ_CONFIG,
872 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL,
873 1c8addc6 Michael Hanselmann
                        [nicp[constants.NIC_LINK]
874 1c8addc6 Michael Hanselmann
                         for nicp in ctx.inst_nicparams])),
875 1c8addc6 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", constants.QFT_OTHER), IQ_CONFIG,
876 1c8addc6 Michael Hanselmann
     _GetInstAllNicBridges),
877 1c8addc6 Michael Hanselmann
    ]
878 1c8addc6 Michael Hanselmann
879 1c8addc6 Michael Hanselmann
  # NICs by number
880 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
881 1c8addc6 Michael Hanselmann
    fields.extend([
882 1c8addc6 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, constants.QFT_TEXT),
883 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicIp)),
884 1c8addc6 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, constants.QFT_TEXT),
885 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mac_fn)),
886 1c8addc6 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, constants.QFT_TEXT),
887 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mode_fn)),
888 1c8addc6 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, constants.QFT_TEXT),
889 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_link_fn)),
890 1c8addc6 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, constants.QFT_TEXT),
891 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicBridge)),
892 1c8addc6 Michael Hanselmann
      ])
893 1c8addc6 Michael Hanselmann
894 1c8addc6 Michael Hanselmann
  return fields
895 1c8addc6 Michael Hanselmann
896 1c8addc6 Michael Hanselmann
897 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
898 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
899 1c8addc6 Michael Hanselmann

900 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
901 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
902 1c8addc6 Michael Hanselmann
  @param inst: Instance object
903 1c8addc6 Michael Hanselmann

904 1c8addc6 Michael Hanselmann
  """
905 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
906 1c8addc6 Michael Hanselmann
907 1c8addc6 Michael Hanselmann
  if usage is None:
908 1c8addc6 Michael Hanselmann
    usage = 0
909 1c8addc6 Michael Hanselmann
910 1c8addc6 Michael Hanselmann
  return (constants.QRFS_NORMAL, usage)
911 1c8addc6 Michael Hanselmann
912 1c8addc6 Michael Hanselmann
913 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
914 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
915 1c8addc6 Michael Hanselmann

916 1c8addc6 Michael Hanselmann
  @return: List of field definitions used as input for L{_PrepareFieldList}
917 1c8addc6 Michael Hanselmann

918 1c8addc6 Michael Hanselmann
  """
919 1c8addc6 Michael Hanselmann
  fields = [
920 1c8addc6 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", constants.QFT_UNIT), IQ_DISKUSAGE,
921 1c8addc6 Michael Hanselmann
     _GetInstDiskUsage),
922 1c8addc6 Michael Hanselmann
    (_MakeField("sda_size", "LegacyDisk/0", constants.QFT_UNIT), IQ_CONFIG,
923 1c8addc6 Michael Hanselmann
     _GetInstDiskSize(0)),
924 1c8addc6 Michael Hanselmann
    (_MakeField("sdb_size", "LegacyDisk/1", constants.QFT_UNIT), IQ_CONFIG,
925 1c8addc6 Michael Hanselmann
     _GetInstDiskSize(1)),
926 1c8addc6 Michael Hanselmann
    (_MakeField("disk.count", "Disks", constants.QFT_NUMBER), IQ_CONFIG,
927 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, len(inst.disks))),
928 1c8addc6 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", constants.QFT_OTHER), IQ_CONFIG,
929 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL,
930 1c8addc6 Michael Hanselmann
                        [disk.size for disk in inst.disks])),
931 1c8addc6 Michael Hanselmann
    ]
932 1c8addc6 Michael Hanselmann
933 1c8addc6 Michael Hanselmann
  # Disks by number
934 1c8addc6 Michael Hanselmann
  fields.extend([
935 1c8addc6 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, constants.QFT_UNIT),
936 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstDiskSize(i))
937 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
938 1c8addc6 Michael Hanselmann
    ])
939 1c8addc6 Michael Hanselmann
940 1c8addc6 Michael Hanselmann
  return fields
941 1c8addc6 Michael Hanselmann
942 1c8addc6 Michael Hanselmann
943 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
944 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
945 1c8addc6 Michael Hanselmann

946 1c8addc6 Michael Hanselmann
  @return: List of field definitions used as input for L{_PrepareFieldList}
947 1c8addc6 Michael Hanselmann

948 1c8addc6 Michael Hanselmann
  """
949 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
950 1c8addc6 Michael Hanselmann
  be_title = {
951 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
952 1c8addc6 Michael Hanselmann
    constants.BE_MEMORY: "Configured_memory",
953 1c8addc6 Michael Hanselmann
    constants.BE_VCPUS: "VCPUs",
954 1c8addc6 Michael Hanselmann
    }
955 1c8addc6 Michael Hanselmann
956 1c8addc6 Michael Hanselmann
  hv_title = {
957 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
958 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
959 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
960 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
961 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
962 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
963 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
964 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
965 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
966 1c8addc6 Michael Hanselmann
    }
967 1c8addc6 Michael Hanselmann
968 1c8addc6 Michael Hanselmann
  fields = [
969 1c8addc6 Michael Hanselmann
    # Filled parameters
970 1c8addc6 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", constants.QFT_OTHER),
971 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, _: (constants.QRFS_NORMAL, ctx.inst_hvparams)),
972 1c8addc6 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", constants.QFT_OTHER),
973 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, _: (constants.QRFS_NORMAL, ctx.inst_beparams)),
974 1c8addc6 Michael Hanselmann
    (_MakeField("vcpus", "LegacyVCPUs", constants.QFT_NUMBER), IQ_CONFIG,
975 1c8addc6 Michael Hanselmann
     lambda ctx, _: (constants.QRFS_NORMAL,
976 1c8addc6 Michael Hanselmann
                     ctx.inst_beparams[constants.BE_VCPUS])),
977 1c8addc6 Michael Hanselmann
978 1c8addc6 Michael Hanselmann
    # Unfilled parameters
979 1c8addc6 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters",
980 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
981 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL, inst.hvparams)),
982 1c8addc6 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters",
983 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
984 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL, inst.beparams)),
985 1c8addc6 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters",
986 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
987 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL,
988 1c8addc6 Michael Hanselmann
                                   [nic.nicparams for nic in inst.nics])),
989 1c8addc6 Michael Hanselmann
    ]
990 1c8addc6 Michael Hanselmann
991 1c8addc6 Michael Hanselmann
  # HV params
992 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
993 1c8addc6 Michael Hanselmann
    return lambda ctx, _: (constants.QRFS_NORMAL,
994 1c8addc6 Michael Hanselmann
                           ctx.inst_hvparams.get(name, None))
995 1c8addc6 Michael Hanselmann
996 1c8addc6 Michael Hanselmann
  fields.extend([
997 1c8addc6 Michael Hanselmann
    # For now all hypervisor parameters are exported as QFT_OTHER
998 1c8addc6 Michael Hanselmann
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
999 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
1000 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstHvParam(name))
1001 1c8addc6 Michael Hanselmann
    for name in constants.HVS_PARAMETERS
1002 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1003 1c8addc6 Michael Hanselmann
    ])
1004 1c8addc6 Michael Hanselmann
1005 1c8addc6 Michael Hanselmann
  # BE params
1006 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1007 1c8addc6 Michael Hanselmann
    return lambda ctx, _: (constants.QRFS_NORMAL,
1008 1c8addc6 Michael Hanselmann
                           ctx.inst_beparams.get(name, None))
1009 1c8addc6 Michael Hanselmann
1010 1c8addc6 Michael Hanselmann
  fields.extend([
1011 1c8addc6 Michael Hanselmann
    # For now all backend parameters are exported as QFT_OTHER
1012 1c8addc6 Michael Hanselmann
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1013 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
1014 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstBeParam(name))
1015 1c8addc6 Michael Hanselmann
    for name in constants.BES_PARAMETERS
1016 1c8addc6 Michael Hanselmann
    ])
1017 1c8addc6 Michael Hanselmann
1018 1c8addc6 Michael Hanselmann
  return fields
1019 1c8addc6 Michael Hanselmann
1020 1c8addc6 Michael Hanselmann
1021 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1022 1c8addc6 Michael Hanselmann
  "disk_template": ("Disk_template", constants.QFT_TEXT),
1023 1c8addc6 Michael Hanselmann
  "hypervisor": ("Hypervisor", constants.QFT_TEXT),
1024 1c8addc6 Michael Hanselmann
  "name": ("Node", constants.QFT_TEXT),
1025 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1026 1c8addc6 Michael Hanselmann
  "network_port": ("Network_port", constants.QFT_OTHER),
1027 1c8addc6 Michael Hanselmann
  "os": ("OS", constants.QFT_TEXT),
1028 1c8addc6 Michael Hanselmann
  "serial_no": ("SerialNo", constants.QFT_NUMBER),
1029 1c8addc6 Michael Hanselmann
  "uuid": ("UUID", constants.QFT_TEXT),
1030 1c8addc6 Michael Hanselmann
  }
1031 1c8addc6 Michael Hanselmann
1032 1c8addc6 Michael Hanselmann
1033 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1034 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1035 1c8addc6 Michael Hanselmann

1036 1c8addc6 Michael Hanselmann
  """
1037 1c8addc6 Michael Hanselmann
  fields = [
1038 1c8addc6 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", constants.QFT_TEXT), IQ_CONFIG,
1039 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, inst.primary_node)),
1040 1c8addc6 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", constants.QFT_OTHER), IQ_CONFIG,
1041 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, list(inst.secondary_nodes))),
1042 1c8addc6 Michael Hanselmann
    (_MakeField("admin_state", "Autostart", constants.QFT_BOOL), IQ_CONFIG,
1043 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, inst.admin_up)),
1044 1c8addc6 Michael Hanselmann
    (_MakeField("tags", "Tags", constants.QFT_OTHER), IQ_CONFIG,
1045 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, list(inst.GetTags()))),
1046 1c8addc6 Michael Hanselmann
    ]
1047 1c8addc6 Michael Hanselmann
1048 1c8addc6 Michael Hanselmann
  # Add simple fields
1049 1c8addc6 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), IQ_CONFIG, _GetItemAttr(name))
1050 1c8addc6 Michael Hanselmann
                 for (name, (title, kind)) in _INST_SIMPLE_FIELDS.items()])
1051 1c8addc6 Michael Hanselmann
1052 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1053 1c8addc6 Michael Hanselmann
  fields.extend([
1054 1c8addc6 Michael Hanselmann
    (_MakeField("oper_state", "Running", constants.QFT_BOOL), IQ_LIVE,
1055 1c8addc6 Michael Hanselmann
     _GetInstOperState),
1056 1c8addc6 Michael Hanselmann
    (_MakeField("oper_ram", "RuntimeMemory", constants.QFT_UNIT), IQ_LIVE,
1057 1c8addc6 Michael Hanselmann
     _GetInstLiveData("memory")),
1058 1c8addc6 Michael Hanselmann
    (_MakeField("oper_vcpus", "RuntimeVCPUs", constants.QFT_NUMBER), IQ_LIVE,
1059 1c8addc6 Michael Hanselmann
     _GetInstLiveData("vcpus")),
1060 1c8addc6 Michael Hanselmann
    (_MakeField("status", "Status", constants.QFT_TEXT), IQ_LIVE,
1061 1c8addc6 Michael Hanselmann
     _GetInstStatus),
1062 1c8addc6 Michael Hanselmann
    ])
1063 1c8addc6 Michael Hanselmann
1064 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1065 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1066 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceNetworkFields())
1067 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1068 1c8addc6 Michael Hanselmann
1069 1c8addc6 Michael Hanselmann
  return _PrepareFieldList(fields)
1070 1c8addc6 Michael Hanselmann
1071 1c8addc6 Michael Hanselmann
1072 24d16f76 Michael Hanselmann
class LockQueryData:
1073 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1074 24d16f76 Michael Hanselmann

1075 24d16f76 Michael Hanselmann
  """
1076 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1077 24d16f76 Michael Hanselmann
    """Initializes this class.
1078 24d16f76 Michael Hanselmann

1079 24d16f76 Michael Hanselmann
    """
1080 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1081 24d16f76 Michael Hanselmann
1082 24d16f76 Michael Hanselmann
  def __iter__(self):
1083 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1084 24d16f76 Michael Hanselmann

1085 24d16f76 Michael Hanselmann
    """
1086 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1087 24d16f76 Michael Hanselmann
1088 24d16f76 Michael Hanselmann
1089 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1090 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1091 24d16f76 Michael Hanselmann

1092 24d16f76 Michael Hanselmann
  """
1093 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1094 24d16f76 Michael Hanselmann
1095 24d16f76 Michael Hanselmann
  if owners:
1096 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1097 24d16f76 Michael Hanselmann
1098 24d16f76 Michael Hanselmann
  return (constants.QRFS_NORMAL, owners)
1099 24d16f76 Michael Hanselmann
1100 24d16f76 Michael Hanselmann
1101 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1102 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1103 24d16f76 Michael Hanselmann

1104 24d16f76 Michael Hanselmann
  """
1105 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1106 24d16f76 Michael Hanselmann
1107 24d16f76 Michael Hanselmann
  if pending:
1108 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1109 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1110 24d16f76 Michael Hanselmann
1111 24d16f76 Michael Hanselmann
  return (constants.QRFS_NORMAL, pending)
1112 24d16f76 Michael Hanselmann
1113 24d16f76 Michael Hanselmann
1114 24d16f76 Michael Hanselmann
def _BuildLockFields():
1115 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1116 24d16f76 Michael Hanselmann

1117 24d16f76 Michael Hanselmann
  """
1118 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1119 24d16f76 Michael Hanselmann
    (_MakeField("name", "Name", constants.QFT_TEXT), None,
1120 24d16f76 Michael Hanselmann
     lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, name)),
1121 24d16f76 Michael Hanselmann
    (_MakeField("mode", "Mode", constants.QFT_OTHER), LQ_MODE,
1122 24d16f76 Michael Hanselmann
     lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, mode)),
1123 24d16f76 Michael Hanselmann
    (_MakeField("owner", "Owner", constants.QFT_OTHER), LQ_OWNER,
1124 24d16f76 Michael Hanselmann
     _GetLockOwners),
1125 24d16f76 Michael Hanselmann
    (_MakeField("pending", "Pending", constants.QFT_OTHER), LQ_PENDING,
1126 24d16f76 Michael Hanselmann
     _GetLockPending),
1127 24d16f76 Michael Hanselmann
    ])
1128 24d16f76 Michael Hanselmann
1129 24d16f76 Michael Hanselmann
1130 8e21cfc0 Adeodato Simo
class GroupQueryData:
1131 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1132 8e21cfc0 Adeodato Simo

1133 8e21cfc0 Adeodato Simo
  """
1134 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1135 8e21cfc0 Adeodato Simo
    """Initializes this class.
1136 8e21cfc0 Adeodato Simo

1137 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1138 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1139 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1140 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1141 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1142 8e21cfc0 Adeodato Simo

1143 8e21cfc0 Adeodato Simo
    """
1144 8e21cfc0 Adeodato Simo
    self.groups = groups
1145 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1146 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1147 8e21cfc0 Adeodato Simo
1148 8e21cfc0 Adeodato Simo
  def __iter__(self):
1149 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1150 8e21cfc0 Adeodato Simo

1151 8e21cfc0 Adeodato Simo
    """
1152 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1153 8e21cfc0 Adeodato Simo
1154 8e21cfc0 Adeodato Simo
1155 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1156 8e21cfc0 Adeodato Simo
  "alloc_policy": ("AllocPolicy", constants.QFT_TEXT),
1157 8e21cfc0 Adeodato Simo
  "name": ("Group", constants.QFT_TEXT),
1158 8e21cfc0 Adeodato Simo
  "serial_no": ("SerialNo", constants.QFT_NUMBER),
1159 8e21cfc0 Adeodato Simo
  "uuid": ("UUID", constants.QFT_TEXT),
1160 8e21cfc0 Adeodato Simo
  }
1161 8e21cfc0 Adeodato Simo
1162 8e21cfc0 Adeodato Simo
1163 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1164 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1165 8e21cfc0 Adeodato Simo

1166 8e21cfc0 Adeodato Simo
  """
1167 8e21cfc0 Adeodato Simo
  # Add simple fields
1168 8e21cfc0 Adeodato Simo
  fields = [(_MakeField(name, title, kind), GQ_CONFIG, _GetItemAttr(name))
1169 8e21cfc0 Adeodato Simo
            for (name, (title, kind)) in _GROUP_SIMPLE_FIELDS.items()]
1170 8e21cfc0 Adeodato Simo
1171 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1172 8e21cfc0 Adeodato Simo
    return lambda ctx, group: (constants.QRFS_NORMAL,
1173 8e21cfc0 Adeodato Simo
                               len(getter(ctx)[group.uuid]))
1174 8e21cfc0 Adeodato Simo
1175 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1176 8e21cfc0 Adeodato Simo
    return lambda ctx, group: (constants.QRFS_NORMAL,
1177 8e21cfc0 Adeodato Simo
                               utils.NiceSort(getter(ctx)[group.uuid]))
1178 8e21cfc0 Adeodato Simo
1179 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1180 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1181 8e21cfc0 Adeodato Simo
1182 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1183 8e21cfc0 Adeodato Simo
  fields.extend([
1184 8e21cfc0 Adeodato Simo
    (_MakeField("node_cnt", "Nodes", constants.QFT_NUMBER),
1185 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetLength(group_to_nodes)),
1186 8e21cfc0 Adeodato Simo
    (_MakeField("node_list", "NodeList", constants.QFT_OTHER),
1187 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetSortedList(group_to_nodes)),
1188 8e21cfc0 Adeodato Simo
    ])
1189 8e21cfc0 Adeodato Simo
1190 8e21cfc0 Adeodato Simo
  # Add fields for instances
1191 8e21cfc0 Adeodato Simo
  fields.extend([
1192 8e21cfc0 Adeodato Simo
    (_MakeField("pinst_cnt", "Instances", constants.QFT_NUMBER),
1193 8e21cfc0 Adeodato Simo
     GQ_INST, _GetLength(group_to_instances)),
1194 8e21cfc0 Adeodato Simo
    (_MakeField("pinst_list", "InstanceList", constants.QFT_OTHER),
1195 8e21cfc0 Adeodato Simo
     GQ_INST, _GetSortedList(group_to_instances)),
1196 8e21cfc0 Adeodato Simo
    ])
1197 8e21cfc0 Adeodato Simo
1198 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1199 8e21cfc0 Adeodato Simo
1200 8e21cfc0 Adeodato Simo
  return _PrepareFieldList(fields)
1201 8e21cfc0 Adeodato Simo
1202 8e21cfc0 Adeodato Simo
1203 8235fe04 Michael Hanselmann
#: Fields available for node queries
1204 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
1205 1c8addc6 Michael Hanselmann
1206 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
1207 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
1208 24d16f76 Michael Hanselmann
1209 24d16f76 Michael Hanselmann
#: Fields available for lock queries
1210 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
1211 e571ee44 Adeodato Simo
1212 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
1213 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
1214 8e21cfc0 Adeodato Simo
1215 e571ee44 Adeodato Simo
#: All available field lists
1216 8e21cfc0 Adeodato Simo
ALL_FIELD_LISTS = [NODE_FIELDS, INSTANCE_FIELDS, LOCK_FIELDS, GROUP_FIELDS]