Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 82599b3e

History | View | Annotate | Download (34.3 kB)

1 4ca96421 Michael Hanselmann
#
2 4ca96421 Michael Hanselmann
#
3 4ca96421 Michael Hanselmann
4 82599b3e Iustin Pop
# Copyright (C) 2010, 2011 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 8f8ce6d1 Michael Hanselmann
"""Module for query operations
23 8f8ce6d1 Michael Hanselmann

24 8f8ce6d1 Michael Hanselmann
How it works:
25 8f8ce6d1 Michael Hanselmann

26 8f8ce6d1 Michael Hanselmann
  - Add field definitions
27 8f8ce6d1 Michael Hanselmann
    - See how L{NODE_FIELDS} is built
28 8f8ce6d1 Michael Hanselmann
    - Each field gets:
29 8f8ce6d1 Michael Hanselmann
      - Query field definition (L{objects.QueryFieldDefinition}, use
30 8f8ce6d1 Michael Hanselmann
        L{_MakeField} for creating), containing:
31 8f8ce6d1 Michael Hanselmann
          - Name, must be lowercase and match L{FIELD_NAME_RE}
32 8f8ce6d1 Michael Hanselmann
          - Title for tables, must not contain whitespace and match
33 8f8ce6d1 Michael Hanselmann
            L{TITLE_RE}
34 8f8ce6d1 Michael Hanselmann
          - Value data type, e.g. L{constants.QFT_NUMBER}
35 8f8ce6d1 Michael Hanselmann
      - Data request type, see e.g. C{NQ_*}
36 8f8ce6d1 Michael Hanselmann
      - A retrieval function, see L{Query.__init__} for description
37 8f8ce6d1 Michael Hanselmann
    - Pass list of fields through L{_PrepareFieldList} for preparation and
38 8f8ce6d1 Michael Hanselmann
      checks
39 8f8ce6d1 Michael Hanselmann
  - Instantiate L{Query} with prepared field list definition and selected fields
40 8f8ce6d1 Michael Hanselmann
  - Call L{Query.RequestedData} to determine what data to collect/compute
41 8f8ce6d1 Michael Hanselmann
  - Call L{Query.Query} or L{Query.OldStyleQuery} with collected data and use
42 8f8ce6d1 Michael Hanselmann
    result
43 8f8ce6d1 Michael Hanselmann
      - Data container must support iteration using C{__iter__}
44 8f8ce6d1 Michael Hanselmann
      - Items are passed to retrieval functions and can have any format
45 8f8ce6d1 Michael Hanselmann
  - Call L{Query.GetFields} to get list of definitions for selected fields
46 8f8ce6d1 Michael Hanselmann

47 8f8ce6d1 Michael Hanselmann
@attention: Retrieval functions must be idempotent. They can be called multiple
48 8f8ce6d1 Michael Hanselmann
  times, in any order and any number of times. This is important to keep in
49 8f8ce6d1 Michael Hanselmann
  mind for implementing filters in the future.
50 8f8ce6d1 Michael Hanselmann

51 8f8ce6d1 Michael Hanselmann
"""
52 4ca96421 Michael Hanselmann
53 8235fe04 Michael Hanselmann
import logging
54 4ca96421 Michael Hanselmann
import operator
55 4ca96421 Michael Hanselmann
import re
56 4ca96421 Michael Hanselmann
57 4ca96421 Michael Hanselmann
from ganeti import constants
58 4ca96421 Michael Hanselmann
from ganeti import errors
59 4ca96421 Michael Hanselmann
from ganeti import utils
60 4ca96421 Michael Hanselmann
from ganeti import compat
61 4ca96421 Michael Hanselmann
from ganeti import objects
62 4ca96421 Michael Hanselmann
from ganeti import ht
63 4ca96421 Michael Hanselmann
64 82599b3e Iustin Pop
from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
65 82599b3e Iustin Pop
                              QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER,
66 82599b3e Iustin Pop
                              QRFS_NORMAL, QRFS_UNKNOWN, QRFS_NODATA,
67 82599b3e Iustin Pop
                              QRFS_UNAVAIL, QRFS_OFFLINE)
68 82599b3e Iustin Pop
69 4ca96421 Michael Hanselmann
70 8f8ce6d1 Michael Hanselmann
# Constants for requesting data from the caller/data provider. Each property
71 8f8ce6d1 Michael Hanselmann
# collected/computed separately by the data provider should have its own to
72 8f8ce6d1 Michael Hanselmann
# only collect the requested data and not more.
73 8f8ce6d1 Michael Hanselmann
74 8235fe04 Michael Hanselmann
(NQ_CONFIG,
75 8235fe04 Michael Hanselmann
 NQ_INST,
76 8235fe04 Michael Hanselmann
 NQ_LIVE,
77 52b5d286 René Nussbaumer
 NQ_GROUP,
78 52b5d286 René Nussbaumer
 NQ_OOB) = range(1, 6)
79 8235fe04 Michael Hanselmann
80 1c8addc6 Michael Hanselmann
(IQ_CONFIG,
81 1c8addc6 Michael Hanselmann
 IQ_LIVE,
82 1c8addc6 Michael Hanselmann
 IQ_DISKUSAGE) = range(100, 103)
83 1c8addc6 Michael Hanselmann
84 24d16f76 Michael Hanselmann
(LQ_MODE,
85 24d16f76 Michael Hanselmann
 LQ_OWNER,
86 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
87 8235fe04 Michael Hanselmann
88 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
89 8e21cfc0 Adeodato Simo
 GQ_NODE,
90 8e21cfc0 Adeodato Simo
 GQ_INST) = range(200, 203)
91 8e21cfc0 Adeodato Simo
92 8e21cfc0 Adeodato Simo
93 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
94 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
95 4ca96421 Michael Hanselmann
96 4ca96421 Michael Hanselmann
#: Verification function for each field type
97 4ca96421 Michael Hanselmann
_VERIFY_FN = {
98 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
99 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
100 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
101 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
102 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
103 82599b3e Iustin Pop
  QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat),
104 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
105 4ca96421 Michael Hanselmann
  }
106 4ca96421 Michael Hanselmann
107 4ca96421 Michael Hanselmann
108 4ca96421 Michael Hanselmann
def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
109 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
110 4ca96421 Michael Hanselmann

111 4ca96421 Michael Hanselmann
  """
112 82599b3e Iustin Pop
  return (QRFS_UNKNOWN, None)
113 4ca96421 Michael Hanselmann
114 4ca96421 Michael Hanselmann
115 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
116 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
117 4ca96421 Michael Hanselmann

118 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
119 4ca96421 Michael Hanselmann

120 4ca96421 Michael Hanselmann
  @type fielddefs: dict
121 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
122 4ca96421 Michael Hanselmann
  @type selected: list of strings
123 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
124 4ca96421 Michael Hanselmann

125 4ca96421 Michael Hanselmann
  """
126 4ca96421 Michael Hanselmann
  result = []
127 4ca96421 Michael Hanselmann
128 4ca96421 Michael Hanselmann
  for name in selected:
129 4ca96421 Michael Hanselmann
    try:
130 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
131 4ca96421 Michael Hanselmann
    except KeyError:
132 82599b3e Iustin Pop
      fdef = (_MakeField(name, name, QFT_UNKNOWN), None, _GetUnknownField)
133 4ca96421 Michael Hanselmann
134 4ca96421 Michael Hanselmann
    assert len(fdef) == 3
135 4ca96421 Michael Hanselmann
136 4ca96421 Michael Hanselmann
    result.append(fdef)
137 4ca96421 Michael Hanselmann
138 4ca96421 Michael Hanselmann
  return result
139 4ca96421 Michael Hanselmann
140 4ca96421 Michael Hanselmann
141 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
142 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
143 4ca96421 Michael Hanselmann

144 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
145 4ca96421 Michael Hanselmann

146 4ca96421 Michael Hanselmann
  """
147 4ca96421 Michael Hanselmann
  return [fdef for (fdef, _, _) in fielddefs]
148 4ca96421 Michael Hanselmann
149 4ca96421 Michael Hanselmann
150 4ca96421 Michael Hanselmann
class Query:
151 4ca96421 Michael Hanselmann
  def __init__(self, fieldlist, selected):
152 4ca96421 Michael Hanselmann
    """Initializes this class.
153 4ca96421 Michael Hanselmann

154 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
155 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
156 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
157 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
158 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
159 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
160 4ca96421 Michael Hanselmann

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

164 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
165 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
166 4ca96421 Michael Hanselmann
    @type selected: list of strings
167 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
168 4ca96421 Michael Hanselmann

169 4ca96421 Michael Hanselmann
    """
170 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
171 4ca96421 Michael Hanselmann
172 4ca96421 Michael Hanselmann
  def RequestedData(self):
173 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
174 4ca96421 Michael Hanselmann

175 4ca96421 Michael Hanselmann
    @rtype: frozenset
176 4ca96421 Michael Hanselmann

177 4ca96421 Michael Hanselmann
    """
178 4ca96421 Michael Hanselmann
    return frozenset(datakind
179 4ca96421 Michael Hanselmann
                     for (_, datakind, _) in self._fields
180 4ca96421 Michael Hanselmann
                     if datakind is not None)
181 4ca96421 Michael Hanselmann
182 4ca96421 Michael Hanselmann
  def GetFields(self):
183 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
184 4ca96421 Michael Hanselmann

185 4ca96421 Michael Hanselmann
    Includes unknown fields.
186 4ca96421 Michael Hanselmann

187 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
188 4ca96421 Michael Hanselmann

189 4ca96421 Michael Hanselmann
    """
190 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
191 4ca96421 Michael Hanselmann
192 4ca96421 Michael Hanselmann
  def Query(self, ctx):
193 4ca96421 Michael Hanselmann
    """Execute a query.
194 4ca96421 Michael Hanselmann

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

198 4ca96421 Michael Hanselmann
    """
199 4ca96421 Michael Hanselmann
    result = [[fn(ctx, item) for (_, _, fn) in self._fields]
200 4ca96421 Michael Hanselmann
              for item in ctx]
201 4ca96421 Michael Hanselmann
202 4ca96421 Michael Hanselmann
    # Verify result
203 4ca96421 Michael Hanselmann
    if __debug__:
204 4ca96421 Michael Hanselmann
      for (idx, row) in enumerate(result):
205 4ca96421 Michael Hanselmann
        assert _VerifyResultRow(self._fields, row), \
206 4ca96421 Michael Hanselmann
               ("Inconsistent result for fields %s in row %s: %r" %
207 89ce4acc Michael Hanselmann
                (GetAllFields(self._fields), idx, row))
208 4ca96421 Michael Hanselmann
209 4ca96421 Michael Hanselmann
    return result
210 4ca96421 Michael Hanselmann
211 4ca96421 Michael Hanselmann
  def OldStyleQuery(self, ctx):
212 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
213 4ca96421 Michael Hanselmann

214 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
215 4ca96421 Michael Hanselmann

216 4ca96421 Michael Hanselmann
    """
217 4ca96421 Michael Hanselmann
    unknown = set(fdef.name
218 82599b3e Iustin Pop
                  for (fdef, _, _) in self._fields if fdef.kind == QFT_UNKNOWN)
219 4ca96421 Michael Hanselmann
    if unknown:
220 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
221 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
222 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
223 4ca96421 Michael Hanselmann
224 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
225 4ca96421 Michael Hanselmann
            for row in self.Query(ctx)]
226 4ca96421 Michael Hanselmann
227 4ca96421 Michael Hanselmann
228 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
229 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
230 4ca96421 Michael Hanselmann

231 4ca96421 Michael Hanselmann
  @type fields: list
232 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
233 4ca96421 Michael Hanselmann
  @type row: list of tuples
234 4ca96421 Michael Hanselmann
  @param row: Row data
235 4ca96421 Michael Hanselmann

236 4ca96421 Michael Hanselmann
  """
237 4ca96421 Michael Hanselmann
  return (len(row) == len(fields) and
238 82599b3e Iustin Pop
          compat.all((status == QRFS_NORMAL and _VERIFY_FN[fdef.kind](value)) or
239 4ca96421 Michael Hanselmann
                     # Value for an abnormal status must be None
240 82599b3e Iustin Pop
                     (status != QRFS_NORMAL and value is None)
241 4ca96421 Michael Hanselmann
                     for ((status, value), (fdef, _, _)) in zip(row, fields)))
242 4ca96421 Michael Hanselmann
243 4ca96421 Michael Hanselmann
244 4ca96421 Michael Hanselmann
def _PrepareFieldList(fields):
245 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
246 4ca96421 Michael Hanselmann

247 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
248 4ca96421 Michael Hanselmann

249 4ca96421 Michael Hanselmann
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data kind,
250 4ca96421 Michael Hanselmann
    retrieval function)
251 8f8ce6d1 Michael Hanselmann
  @param fields: List of fields, see L{Query.__init__} for a better description
252 4ca96421 Michael Hanselmann
  @rtype: dict
253 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
254 4ca96421 Michael Hanselmann

255 4ca96421 Michael Hanselmann
  """
256 89ce4acc Michael Hanselmann
  if __debug__:
257 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
258 89ce4acc Michael Hanselmann
                                      for (fdef, _, _) in fields)
259 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
260 4ca96421 Michael Hanselmann
261 4ca96421 Michael Hanselmann
  result = {}
262 4ca96421 Michael Hanselmann
263 4ca96421 Michael Hanselmann
  for field in fields:
264 4ca96421 Michael Hanselmann
    (fdef, _, fn) = field
265 4ca96421 Michael Hanselmann
266 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
267 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
268 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
269 4ca96421 Michael Hanselmann
    assert callable(fn)
270 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
271 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
272 4ca96421 Michael Hanselmann
273 4ca96421 Michael Hanselmann
    result[fdef.name] = field
274 4ca96421 Michael Hanselmann
275 4ca96421 Michael Hanselmann
  assert len(result) == len(fields)
276 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
277 4ca96421 Michael Hanselmann
                    for (name, (fdef, _, _)) in result.items())
278 4ca96421 Michael Hanselmann
279 4ca96421 Michael Hanselmann
  return result
280 4ca96421 Michael Hanselmann
281 4ca96421 Michael Hanselmann
282 b60fcb6f Michael Hanselmann
def GetQueryResponse(query, ctx):
283 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
284 b60fcb6f Michael Hanselmann

285 b60fcb6f Michael Hanselmann
  @type query: L{Query}
286 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
287 b60fcb6f Michael Hanselmann

288 b60fcb6f Michael Hanselmann
  """
289 b60fcb6f Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx),
290 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
291 b60fcb6f Michael Hanselmann
292 b60fcb6f Michael Hanselmann
293 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
294 aa29e95f Michael Hanselmann
  """Returns list of available fields.
295 aa29e95f Michael Hanselmann

296 aa29e95f Michael Hanselmann
  @type fielddefs: dict
297 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
298 aa29e95f Michael Hanselmann
  @type selected: list of strings
299 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
300 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
301 aa29e95f Michael Hanselmann

302 aa29e95f Michael Hanselmann
  """
303 aa29e95f Michael Hanselmann
  if selected is None:
304 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
305 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
306 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
307 aa29e95f Michael Hanselmann
  else:
308 aa29e95f Michael Hanselmann
    # Keep order as requested by client
309 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
310 aa29e95f Michael Hanselmann
311 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
312 aa29e95f Michael Hanselmann
313 aa29e95f Michael Hanselmann
314 4ca96421 Michael Hanselmann
def _MakeField(name, title, kind):
315 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
316 4ca96421 Michael Hanselmann

317 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
318 4ca96421 Michael Hanselmann
  @param title: Human-readable title
319 4ca96421 Michael Hanselmann
  @param kind: Field type
320 4ca96421 Michael Hanselmann

321 4ca96421 Michael Hanselmann
  """
322 4ca96421 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind)
323 8235fe04 Michael Hanselmann
324 8235fe04 Michael Hanselmann
325 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
326 8235fe04 Michael Hanselmann
  """Determine node role.
327 8235fe04 Michael Hanselmann

328 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
329 8235fe04 Michael Hanselmann
  @param node: Node object
330 8235fe04 Michael Hanselmann
  @type master_name: string
331 8235fe04 Michael Hanselmann
  @param master_name: Master node name
332 8235fe04 Michael Hanselmann

333 8235fe04 Michael Hanselmann
  """
334 8235fe04 Michael Hanselmann
  if node.name == master_name:
335 8235fe04 Michael Hanselmann
    return "M"
336 8235fe04 Michael Hanselmann
  elif node.master_candidate:
337 8235fe04 Michael Hanselmann
    return "C"
338 8235fe04 Michael Hanselmann
  elif node.drained:
339 8235fe04 Michael Hanselmann
    return "D"
340 8235fe04 Michael Hanselmann
  elif node.offline:
341 8235fe04 Michael Hanselmann
    return "O"
342 8235fe04 Michael Hanselmann
  else:
343 8235fe04 Michael Hanselmann
    return "R"
344 8235fe04 Michael Hanselmann
345 8235fe04 Michael Hanselmann
346 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
347 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
348 8235fe04 Michael Hanselmann

349 8235fe04 Michael Hanselmann
  @param attr: Attribute name
350 8235fe04 Michael Hanselmann

351 8235fe04 Michael Hanselmann
  """
352 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
353 82599b3e Iustin Pop
  return lambda _, item: (QRFS_NORMAL, getter(item))
354 8235fe04 Michael Hanselmann
355 8235fe04 Michael Hanselmann
356 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
357 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
358 145bea54 Michael Hanselmann

359 145bea54 Michael Hanselmann
  @type getter: callable
360 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
361 145bea54 Michael Hanselmann

362 145bea54 Michael Hanselmann
  """
363 145bea54 Michael Hanselmann
  def fn(_, item):
364 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
365 145bea54 Michael Hanselmann

366 145bea54 Michael Hanselmann
    """
367 145bea54 Michael Hanselmann
    timestamp = getter(item)
368 145bea54 Michael Hanselmann
    if timestamp is None:
369 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
370 82599b3e Iustin Pop
      return (QRFS_UNAVAIL, None)
371 145bea54 Michael Hanselmann
    else:
372 82599b3e Iustin Pop
      return (QRFS_NORMAL, timestamp)
373 145bea54 Michael Hanselmann
374 145bea54 Michael Hanselmann
  return fn
375 145bea54 Michael Hanselmann
376 145bea54 Michael Hanselmann
377 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
378 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
379 145bea54 Michael Hanselmann

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

382 145bea54 Michael Hanselmann
  """
383 145bea54 Michael Hanselmann
  return [
384 82599b3e Iustin Pop
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP), datatype,
385 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("ctime"))),
386 82599b3e Iustin Pop
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP), datatype,
387 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("mtime"))),
388 145bea54 Michael Hanselmann
    ]
389 145bea54 Michael Hanselmann
390 145bea54 Michael Hanselmann
391 8235fe04 Michael Hanselmann
class NodeQueryData:
392 8235fe04 Michael Hanselmann
  """Data container for node data queries.
393 8235fe04 Michael Hanselmann

394 8235fe04 Michael Hanselmann
  """
395 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
396 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
397 8235fe04 Michael Hanselmann
    """Initializes this class.
398 8235fe04 Michael Hanselmann

399 8235fe04 Michael Hanselmann
    """
400 8235fe04 Michael Hanselmann
    self.nodes = nodes
401 8235fe04 Michael Hanselmann
    self.live_data = live_data
402 8235fe04 Michael Hanselmann
    self.master_name = master_name
403 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
404 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
405 8235fe04 Michael Hanselmann
    self.groups = groups
406 52b5d286 René Nussbaumer
    self.oob_support = oob_support
407 8572f1fe René Nussbaumer
    self.cluster = cluster
408 8235fe04 Michael Hanselmann
409 8235fe04 Michael Hanselmann
    # Used for individual rows
410 8235fe04 Michael Hanselmann
    self.curlive_data = None
411 8235fe04 Michael Hanselmann
412 8235fe04 Michael Hanselmann
  def __iter__(self):
413 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
414 8235fe04 Michael Hanselmann

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

418 8235fe04 Michael Hanselmann
    """
419 8235fe04 Michael Hanselmann
    for node in self.nodes:
420 8235fe04 Michael Hanselmann
      if self.live_data:
421 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
422 8235fe04 Michael Hanselmann
      else:
423 8235fe04 Michael Hanselmann
        self.curlive_data = None
424 8235fe04 Michael Hanselmann
      yield node
425 8235fe04 Michael Hanselmann
426 8235fe04 Michael Hanselmann
427 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
428 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
429 82599b3e Iustin Pop
  "drained": ("Drained", QFT_BOOL),
430 82599b3e Iustin Pop
  "master_candidate": ("MasterC", QFT_BOOL),
431 82599b3e Iustin Pop
  "master_capable": ("MasterCapable", QFT_BOOL),
432 82599b3e Iustin Pop
  "name": ("Node", QFT_TEXT),
433 82599b3e Iustin Pop
  "offline": ("Offline", QFT_BOOL),
434 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
435 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
436 82599b3e Iustin Pop
  "vm_capable": ("VMCapable", QFT_BOOL),
437 8235fe04 Michael Hanselmann
  }
438 8235fe04 Michael Hanselmann
439 8235fe04 Michael Hanselmann
440 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
441 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
442 82599b3e Iustin Pop
  "bootid": ("BootID", QFT_TEXT, "bootid"),
443 82599b3e Iustin Pop
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes"),
444 82599b3e Iustin Pop
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets"),
445 82599b3e Iustin Pop
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total"),
446 82599b3e Iustin Pop
  "dfree": ("DFree", QFT_UNIT, "vg_free"),
447 82599b3e Iustin Pop
  "dtotal": ("DTotal", QFT_UNIT, "vg_size"),
448 82599b3e Iustin Pop
  "mfree": ("MFree", QFT_UNIT, "memory_free"),
449 82599b3e Iustin Pop
  "mnode": ("MNode", QFT_UNIT, "memory_dom0"),
450 82599b3e Iustin Pop
  "mtotal": ("MTotal", QFT_UNIT, "memory_total"),
451 8235fe04 Michael Hanselmann
  }
452 8235fe04 Michael Hanselmann
453 8235fe04 Michael Hanselmann
454 8572f1fe René Nussbaumer
def _GetGroup(cb):
455 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
456 8572f1fe René Nussbaumer

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

459 8572f1fe René Nussbaumer
  """
460 8572f1fe René Nussbaumer
  def fn(ctx, node):
461 8572f1fe René Nussbaumer
    """Get group data for a node.
462 8572f1fe René Nussbaumer

463 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
464 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
465 8572f1fe René Nussbaumer
    @param inst: Node object
466 8572f1fe René Nussbaumer

467 8572f1fe René Nussbaumer
    """
468 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
469 8572f1fe René Nussbaumer
    if ng is None:
470 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
471 82599b3e Iustin Pop
      return (QRFS_UNAVAIL, None)
472 8572f1fe René Nussbaumer
473 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
474 8572f1fe René Nussbaumer
475 8572f1fe René Nussbaumer
  return fn
476 8572f1fe René Nussbaumer
477 8572f1fe René Nussbaumer
478 8572f1fe René Nussbaumer
def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613
479 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
480 8235fe04 Michael Hanselmann

481 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
482 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
483 8235fe04 Michael Hanselmann
  @param node: Node object
484 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
485 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
486 8235fe04 Michael Hanselmann

487 8235fe04 Michael Hanselmann
  """
488 82599b3e Iustin Pop
  return (QRFS_NORMAL, ng.name)
489 8235fe04 Michael Hanselmann
490 8235fe04 Michael Hanselmann
491 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
492 52b5d286 René Nussbaumer
  """Returns the node powered state
493 52b5d286 René Nussbaumer

494 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
495 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
496 52b5d286 René Nussbaumer
  @param node: Node object
497 52b5d286 René Nussbaumer

498 52b5d286 René Nussbaumer
  """
499 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
500 82599b3e Iustin Pop
    return (QRFS_NORMAL, node.powered)
501 52b5d286 René Nussbaumer
502 82599b3e Iustin Pop
  return (QRFS_UNAVAIL, None)
503 52b5d286 René Nussbaumer
504 52b5d286 René Nussbaumer
505 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
506 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
507 8572f1fe René Nussbaumer

508 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
509 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
510 8572f1fe René Nussbaumer
  @param node: Node object
511 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
512 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
513 8572f1fe René Nussbaumer

514 8572f1fe René Nussbaumer
  """
515 82599b3e Iustin Pop
  return (QRFS_NORMAL, ctx.cluster.SimpleFillND(ng.FillND(node)))
516 8572f1fe René Nussbaumer
517 8572f1fe René Nussbaumer
518 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
519 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
520 8235fe04 Michael Hanselmann

521 8235fe04 Michael Hanselmann
  @param field: Live field name
522 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
523 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
524 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
525 a6070ef7 Michael Hanselmann
  @param node: Node object
526 8235fe04 Michael Hanselmann

527 8235fe04 Michael Hanselmann
  """
528 a6070ef7 Michael Hanselmann
  if node.offline:
529 82599b3e Iustin Pop
    return (QRFS_OFFLINE, None)
530 a6070ef7 Michael Hanselmann
531 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
532 82599b3e Iustin Pop
    return (QRFS_NODATA, None)
533 8235fe04 Michael Hanselmann
534 8235fe04 Michael Hanselmann
  try:
535 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
536 8235fe04 Michael Hanselmann
  except KeyError:
537 82599b3e Iustin Pop
    return (QRFS_UNAVAIL, None)
538 8235fe04 Michael Hanselmann
539 82599b3e Iustin Pop
  if kind == QFT_TEXT:
540 82599b3e Iustin Pop
    return (QRFS_NORMAL, value)
541 8235fe04 Michael Hanselmann
542 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
543 8235fe04 Michael Hanselmann
544 8235fe04 Michael Hanselmann
  # Try to convert into number
545 8235fe04 Michael Hanselmann
  try:
546 82599b3e Iustin Pop
    return (QRFS_NORMAL, int(value))
547 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
548 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
549 8235fe04 Michael Hanselmann
                      value, field)
550 82599b3e Iustin Pop
    return (QRFS_UNAVAIL, None)
551 8235fe04 Michael Hanselmann
552 8235fe04 Michael Hanselmann
553 8235fe04 Michael Hanselmann
def _BuildNodeFields():
554 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
555 8235fe04 Michael Hanselmann

556 8235fe04 Michael Hanselmann
  """
557 8235fe04 Michael Hanselmann
  fields = [
558 82599b3e Iustin Pop
    (_MakeField("pip", "PrimaryIP", QFT_TEXT), NQ_CONFIG,
559 82599b3e Iustin Pop
     lambda ctx, node: (QRFS_NORMAL, node.primary_ip)),
560 82599b3e Iustin Pop
    (_MakeField("sip", "SecondaryIP", QFT_TEXT), NQ_CONFIG,
561 82599b3e Iustin Pop
     lambda ctx, node: (QRFS_NORMAL, node.secondary_ip)),
562 82599b3e Iustin Pop
    (_MakeField("tags", "Tags", QFT_OTHER), NQ_CONFIG,
563 82599b3e Iustin Pop
     lambda ctx, node: (QRFS_NORMAL, list(node.GetTags()))),
564 82599b3e Iustin Pop
    (_MakeField("master", "IsMaster", QFT_BOOL), NQ_CONFIG,
565 82599b3e Iustin Pop
     lambda ctx, node: (QRFS_NORMAL, node.name == ctx.master_name)),
566 82599b3e Iustin Pop
    (_MakeField("role", "Role", QFT_TEXT), NQ_CONFIG,
567 82599b3e Iustin Pop
     lambda ctx, node: (QRFS_NORMAL, _GetNodeRole(node, ctx.master_name))),
568 82599b3e Iustin Pop
    (_MakeField("group", "Group", QFT_TEXT), NQ_GROUP,
569 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
570 82599b3e Iustin Pop
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT),
571 82599b3e Iustin Pop
     NQ_CONFIG, lambda ctx, node: (QRFS_NORMAL, node.group)),
572 82599b3e Iustin Pop
    (_MakeField("powered", "Powered", QFT_BOOL), NQ_OOB, _GetNodePower),
573 82599b3e Iustin Pop
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER), NQ_GROUP,
574 8572f1fe René Nussbaumer
      _GetGroup(_GetNdParams)),
575 82599b3e Iustin Pop
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER),
576 82599b3e Iustin Pop
      NQ_GROUP, lambda ctx, node: (QRFS_NORMAL, node.ndparams)),
577 8235fe04 Michael Hanselmann
    ]
578 8235fe04 Michael Hanselmann
579 8235fe04 Michael Hanselmann
  def _GetLength(getter):
580 82599b3e Iustin Pop
    return lambda ctx, node: (QRFS_NORMAL, len(getter(ctx)[node.name]))
581 8235fe04 Michael Hanselmann
582 8235fe04 Michael Hanselmann
  def _GetList(getter):
583 82599b3e Iustin Pop
    return lambda ctx, node: (QRFS_NORMAL, list(getter(ctx)[node.name]))
584 8235fe04 Michael Hanselmann
585 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
586 8235fe04 Michael Hanselmann
  for prefix, titleprefix, getter in \
587 8235fe04 Michael Hanselmann
      [("p", "Pri", operator.attrgetter("node_to_primary")),
588 8235fe04 Michael Hanselmann
       ("s", "Sec", operator.attrgetter("node_to_secondary"))]:
589 8235fe04 Michael Hanselmann
    fields.extend([
590 82599b3e Iustin Pop
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER),
591 8235fe04 Michael Hanselmann
       NQ_INST, _GetLength(getter)),
592 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
593 82599b3e Iustin Pop
                  QFT_OTHER),
594 8235fe04 Michael Hanselmann
       NQ_INST, _GetList(getter)),
595 8235fe04 Michael Hanselmann
      ])
596 8235fe04 Michael Hanselmann
597 8235fe04 Michael Hanselmann
  # Add simple fields
598 8235fe04 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), NQ_CONFIG, _GetItemAttr(name))
599 8235fe04 Michael Hanselmann
                 for (name, (title, kind)) in _NODE_SIMPLE_FIELDS.items()])
600 8235fe04 Michael Hanselmann
601 8235fe04 Michael Hanselmann
  # Add fields requiring live data
602 8235fe04 Michael Hanselmann
  fields.extend([
603 8235fe04 Michael Hanselmann
    (_MakeField(name, title, kind), NQ_LIVE,
604 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
605 8235fe04 Michael Hanselmann
    for (name, (title, kind, nfield)) in _NODE_LIVE_FIELDS.items()
606 8235fe04 Michael Hanselmann
    ])
607 8235fe04 Michael Hanselmann
608 145bea54 Michael Hanselmann
  # Add timestamps
609 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
610 145bea54 Michael Hanselmann
611 8235fe04 Michael Hanselmann
  return _PrepareFieldList(fields)
612 8235fe04 Michael Hanselmann
613 8235fe04 Michael Hanselmann
614 1c8addc6 Michael Hanselmann
class InstanceQueryData:
615 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
616 1c8addc6 Michael Hanselmann

617 1c8addc6 Michael Hanselmann
  """
618 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
619 1c8addc6 Michael Hanselmann
               live_data):
620 1c8addc6 Michael Hanselmann
    """Initializes this class.
621 1c8addc6 Michael Hanselmann

622 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
623 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
624 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
625 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
626 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
627 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
628 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
629 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
630 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
631 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
632 1c8addc6 Michael Hanselmann

633 1c8addc6 Michael Hanselmann
    """
634 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
635 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
636 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
637 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
638 1c8addc6 Michael Hanselmann
639 1c8addc6 Michael Hanselmann
    self.instances = instances
640 1c8addc6 Michael Hanselmann
    self.cluster = cluster
641 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
642 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
643 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
644 1c8addc6 Michael Hanselmann
    self.live_data = live_data
645 1c8addc6 Michael Hanselmann
646 1c8addc6 Michael Hanselmann
    # Used for individual rows
647 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
648 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
649 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
650 1c8addc6 Michael Hanselmann
651 1c8addc6 Michael Hanselmann
  def __iter__(self):
652 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
653 1c8addc6 Michael Hanselmann

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

657 1c8addc6 Michael Hanselmann
    """
658 1c8addc6 Michael Hanselmann
    for inst in self.instances:
659 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
660 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
661 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
662 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
663 1c8addc6 Michael Hanselmann
664 1c8addc6 Michael Hanselmann
      yield inst
665 1c8addc6 Michael Hanselmann
666 1c8addc6 Michael Hanselmann
667 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
668 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
669 1c8addc6 Michael Hanselmann

670 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
671 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
672 1c8addc6 Michael Hanselmann
  @param inst: Instance object
673 1c8addc6 Michael Hanselmann

674 1c8addc6 Michael Hanselmann
  """
675 a6070ef7 Michael Hanselmann
  # Can't use QRFS_OFFLINE here as it would describe the instance to be offline
676 a6070ef7 Michael Hanselmann
  # when we actually don't know due to missing data
677 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
678 82599b3e Iustin Pop
    return (QRFS_NODATA, None)
679 1c8addc6 Michael Hanselmann
  else:
680 82599b3e Iustin Pop
    return (QRFS_NORMAL, bool(ctx.live_data.get(inst.name)))
681 1c8addc6 Michael Hanselmann
682 1c8addc6 Michael Hanselmann
683 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
684 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
685 1c8addc6 Michael Hanselmann

686 1c8addc6 Michael Hanselmann
  @type name: string
687 1c8addc6 Michael Hanselmann
  @param name: Live data field name
688 1c8addc6 Michael Hanselmann

689 1c8addc6 Michael Hanselmann
  """
690 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
691 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
692 1c8addc6 Michael Hanselmann

693 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
694 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
695 1c8addc6 Michael Hanselmann
    @param inst: Instance object
696 1c8addc6 Michael Hanselmann

697 1c8addc6 Michael Hanselmann
    """
698 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
699 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
700 a6070ef7 Michael Hanselmann
      # Can't use QRFS_OFFLINE here as it would describe the instance to be
701 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
702 82599b3e Iustin Pop
      return (QRFS_NODATA, None)
703 1c8addc6 Michael Hanselmann
704 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
705 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
706 1c8addc6 Michael Hanselmann
      if name in data:
707 82599b3e Iustin Pop
        return (QRFS_NORMAL, data[name])
708 1c8addc6 Michael Hanselmann
709 82599b3e Iustin Pop
    return (QRFS_UNAVAIL, None)
710 1c8addc6 Michael Hanselmann
711 1c8addc6 Michael Hanselmann
  return fn
712 1c8addc6 Michael Hanselmann
713 1c8addc6 Michael Hanselmann
714 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
715 1c8addc6 Michael Hanselmann
  """Get instance status.
716 1c8addc6 Michael Hanselmann

717 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
718 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
719 1c8addc6 Michael Hanselmann
  @param inst: Instance object
720 1c8addc6 Michael Hanselmann

721 1c8addc6 Michael Hanselmann
  """
722 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
723 82599b3e Iustin Pop
    return (QRFS_NORMAL, "ERROR_nodeoffline")
724 1c8addc6 Michael Hanselmann
725 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
726 82599b3e Iustin Pop
    return (QRFS_NORMAL, "ERROR_nodedown")
727 1c8addc6 Michael Hanselmann
728 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
729 1c8addc6 Michael Hanselmann
    if inst.admin_up:
730 82599b3e Iustin Pop
      return (QRFS_NORMAL, "running")
731 1c8addc6 Michael Hanselmann
    else:
732 82599b3e Iustin Pop
      return (QRFS_NORMAL, "ERROR_up")
733 1c8addc6 Michael Hanselmann
734 1c8addc6 Michael Hanselmann
  if inst.admin_up:
735 82599b3e Iustin Pop
    return (QRFS_NORMAL, "ERROR_down")
736 1c8addc6 Michael Hanselmann
737 82599b3e Iustin Pop
  return (QRFS_NORMAL, "ADMIN_down")
738 1c8addc6 Michael Hanselmann
739 1c8addc6 Michael Hanselmann
740 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
741 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
742 1c8addc6 Michael Hanselmann

743 1c8addc6 Michael Hanselmann
  @type index: int
744 1c8addc6 Michael Hanselmann
  @param index: Disk index
745 1c8addc6 Michael Hanselmann

746 1c8addc6 Michael Hanselmann
  """
747 1c8addc6 Michael Hanselmann
  def fn(_, inst):
748 1c8addc6 Michael Hanselmann
    """Get size of a disk.
749 1c8addc6 Michael Hanselmann

750 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
751 1c8addc6 Michael Hanselmann
    @param inst: Instance object
752 1c8addc6 Michael Hanselmann

753 1c8addc6 Michael Hanselmann
    """
754 1c8addc6 Michael Hanselmann
    try:
755 82599b3e Iustin Pop
      return (QRFS_NORMAL, inst.disks[index].size)
756 1c8addc6 Michael Hanselmann
    except IndexError:
757 82599b3e Iustin Pop
      return (QRFS_UNAVAIL, None)
758 1c8addc6 Michael Hanselmann
759 1c8addc6 Michael Hanselmann
  return fn
760 1c8addc6 Michael Hanselmann
761 1c8addc6 Michael Hanselmann
762 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
763 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
764 1c8addc6 Michael Hanselmann

765 1c8addc6 Michael Hanselmann
  @type index: int
766 1c8addc6 Michael Hanselmann
  @param index: NIC index
767 1c8addc6 Michael Hanselmann
  @type cb: callable
768 1c8addc6 Michael Hanselmann
  @param cb: Callback
769 1c8addc6 Michael Hanselmann

770 1c8addc6 Michael Hanselmann
  """
771 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
772 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
773 1c8addc6 Michael Hanselmann

774 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
775 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
776 1c8addc6 Michael Hanselmann
    @param inst: Instance object
777 1c8addc6 Michael Hanselmann

778 1c8addc6 Michael Hanselmann
    """
779 1c8addc6 Michael Hanselmann
    try:
780 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
781 1c8addc6 Michael Hanselmann
    except IndexError:
782 82599b3e Iustin Pop
      return (QRFS_UNAVAIL, None)
783 1c8addc6 Michael Hanselmann
784 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
785 1c8addc6 Michael Hanselmann
786 1c8addc6 Michael Hanselmann
  return fn
787 1c8addc6 Michael Hanselmann
788 1c8addc6 Michael Hanselmann
789 1c8addc6 Michael Hanselmann
def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613
790 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
791 1c8addc6 Michael Hanselmann

792 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
793 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
794 1c8addc6 Michael Hanselmann
  @param nic: NIC object
795 1c8addc6 Michael Hanselmann

796 1c8addc6 Michael Hanselmann
  """
797 1c8addc6 Michael Hanselmann
  if nic.ip is None:
798 82599b3e Iustin Pop
    return (QRFS_UNAVAIL, None)
799 1c8addc6 Michael Hanselmann
  else:
800 82599b3e Iustin Pop
    return (QRFS_NORMAL, nic.ip)
801 1c8addc6 Michael Hanselmann
802 1c8addc6 Michael Hanselmann
803 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
804 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
805 1c8addc6 Michael Hanselmann

806 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
807 1c8addc6 Michael Hanselmann
  @type index: int
808 1c8addc6 Michael Hanselmann
  @param index: NIC index
809 1c8addc6 Michael Hanselmann

810 1c8addc6 Michael Hanselmann
  """
811 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
812 1c8addc6 Michael Hanselmann
813 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
814 1c8addc6 Michael Hanselmann
815 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
816 82599b3e Iustin Pop
    return (QRFS_NORMAL, nicparams[constants.NIC_LINK])
817 1c8addc6 Michael Hanselmann
  else:
818 82599b3e Iustin Pop
    return (QRFS_UNAVAIL, None)
819 1c8addc6 Michael Hanselmann
820 1c8addc6 Michael Hanselmann
821 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
822 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
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

828 1c8addc6 Michael Hanselmann
  """
829 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
830 1c8addc6 Michael Hanselmann
831 1c8addc6 Michael Hanselmann
  result = []
832 1c8addc6 Michael Hanselmann
833 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
834 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
835 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
836 1c8addc6 Michael Hanselmann
    else:
837 1c8addc6 Michael Hanselmann
      result.append(None)
838 1c8addc6 Michael Hanselmann
839 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
840 1c8addc6 Michael Hanselmann
841 82599b3e Iustin Pop
  return (QRFS_NORMAL, result)
842 1c8addc6 Michael Hanselmann
843 1c8addc6 Michael Hanselmann
844 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
845 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
846 1c8addc6 Michael Hanselmann

847 1c8addc6 Michael Hanselmann
  @type name: string
848 1c8addc6 Michael Hanselmann
  @param name: Parameter name
849 1c8addc6 Michael Hanselmann

850 1c8addc6 Michael Hanselmann
  """
851 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
852 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
853 1c8addc6 Michael Hanselmann

854 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
855 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
856 1c8addc6 Michael Hanselmann
    @param inst: Instance object
857 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
858 1c8addc6 Michael Hanselmann
    @param nic: NIC object
859 1c8addc6 Michael Hanselmann

860 1c8addc6 Michael Hanselmann
    """
861 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
862 82599b3e Iustin Pop
    return (QRFS_NORMAL, ctx.inst_nicparams[index][name])
863 1c8addc6 Michael Hanselmann
864 1c8addc6 Michael Hanselmann
  return fn
865 1c8addc6 Michael Hanselmann
866 1c8addc6 Michael Hanselmann
867 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
868 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
869 1c8addc6 Michael Hanselmann

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

872 1c8addc6 Michael Hanselmann
  """
873 82599b3e Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: (QRFS_NORMAL, nic.mac)
874 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
875 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
876 1c8addc6 Michael Hanselmann
877 1c8addc6 Michael Hanselmann
  fields = [
878 1c8addc6 Michael Hanselmann
    # First NIC (legacy)
879 82599b3e Iustin Pop
    (_MakeField("ip", "IP_address", QFT_TEXT), IQ_CONFIG,
880 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicIp)),
881 82599b3e Iustin Pop
    (_MakeField("mac", "MAC_address", QFT_TEXT), IQ_CONFIG,
882 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mac_fn)),
883 82599b3e Iustin Pop
    (_MakeField("bridge", "Bridge", QFT_TEXT), IQ_CONFIG,
884 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicBridge)),
885 82599b3e Iustin Pop
    (_MakeField("nic_mode", "NIC_Mode", QFT_TEXT), IQ_CONFIG,
886 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mode_fn)),
887 82599b3e Iustin Pop
    (_MakeField("nic_link", "NIC_Link", QFT_TEXT), IQ_CONFIG,
888 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_link_fn)),
889 1c8addc6 Michael Hanselmann
890 1c8addc6 Michael Hanselmann
    # All NICs
891 82599b3e Iustin Pop
    (_MakeField("nic.count", "NICs", QFT_NUMBER), IQ_CONFIG,
892 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, len(inst.nics))),
893 82599b3e Iustin Pop
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER), IQ_CONFIG,
894 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, [nic.mac for nic in inst.nics])),
895 82599b3e Iustin Pop
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER), IQ_CONFIG,
896 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, [nic.ip for nic in inst.nics])),
897 82599b3e Iustin Pop
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER), IQ_CONFIG,
898 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, [nicp[constants.NIC_MODE]
899 82599b3e Iustin Pop
                                      for nicp in ctx.inst_nicparams])),
900 82599b3e Iustin Pop
    (_MakeField("nic.links", "NIC_links", QFT_OTHER), IQ_CONFIG,
901 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, [nicp[constants.NIC_LINK]
902 82599b3e Iustin Pop
                                      for nicp in ctx.inst_nicparams])),
903 82599b3e Iustin Pop
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER), IQ_CONFIG,
904 1c8addc6 Michael Hanselmann
     _GetInstAllNicBridges),
905 1c8addc6 Michael Hanselmann
    ]
906 1c8addc6 Michael Hanselmann
907 1c8addc6 Michael Hanselmann
  # NICs by number
908 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
909 1c8addc6 Michael Hanselmann
    fields.extend([
910 82599b3e Iustin Pop
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT),
911 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicIp)),
912 82599b3e Iustin Pop
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT),
913 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mac_fn)),
914 82599b3e Iustin Pop
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT),
915 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mode_fn)),
916 82599b3e Iustin Pop
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT),
917 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_link_fn)),
918 82599b3e Iustin Pop
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT),
919 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicBridge)),
920 1c8addc6 Michael Hanselmann
      ])
921 1c8addc6 Michael Hanselmann
922 1c8addc6 Michael Hanselmann
  return fields
923 1c8addc6 Michael Hanselmann
924 1c8addc6 Michael Hanselmann
925 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
926 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
927 1c8addc6 Michael Hanselmann

928 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
929 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
930 1c8addc6 Michael Hanselmann
  @param inst: Instance object
931 1c8addc6 Michael Hanselmann

932 1c8addc6 Michael Hanselmann
  """
933 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
934 1c8addc6 Michael Hanselmann
935 1c8addc6 Michael Hanselmann
  if usage is None:
936 1c8addc6 Michael Hanselmann
    usage = 0
937 1c8addc6 Michael Hanselmann
938 82599b3e Iustin Pop
  return (QRFS_NORMAL, usage)
939 1c8addc6 Michael Hanselmann
940 1c8addc6 Michael Hanselmann
941 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
942 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
943 1c8addc6 Michael Hanselmann

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

946 1c8addc6 Michael Hanselmann
  """
947 1c8addc6 Michael Hanselmann
  fields = [
948 82599b3e Iustin Pop
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT), IQ_DISKUSAGE,
949 1c8addc6 Michael Hanselmann
     _GetInstDiskUsage),
950 82599b3e Iustin Pop
    (_MakeField("sda_size", "LegacyDisk/0", QFT_UNIT), IQ_CONFIG,
951 1c8addc6 Michael Hanselmann
     _GetInstDiskSize(0)),
952 82599b3e Iustin Pop
    (_MakeField("sdb_size", "LegacyDisk/1", QFT_UNIT), IQ_CONFIG,
953 1c8addc6 Michael Hanselmann
     _GetInstDiskSize(1)),
954 82599b3e Iustin Pop
    (_MakeField("disk.count", "Disks", QFT_NUMBER), IQ_CONFIG,
955 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, len(inst.disks))),
956 82599b3e Iustin Pop
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER), IQ_CONFIG,
957 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, [disk.size for disk in inst.disks])),
958 1c8addc6 Michael Hanselmann
    ]
959 1c8addc6 Michael Hanselmann
960 1c8addc6 Michael Hanselmann
  # Disks by number
961 1c8addc6 Michael Hanselmann
  fields.extend([
962 82599b3e Iustin Pop
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT),
963 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstDiskSize(i))
964 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
965 1c8addc6 Michael Hanselmann
    ])
966 1c8addc6 Michael Hanselmann
967 1c8addc6 Michael Hanselmann
  return fields
968 1c8addc6 Michael Hanselmann
969 1c8addc6 Michael Hanselmann
970 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
971 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
972 1c8addc6 Michael Hanselmann

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

975 1c8addc6 Michael Hanselmann
  """
976 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
977 1c8addc6 Michael Hanselmann
  be_title = {
978 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
979 1c8addc6 Michael Hanselmann
    constants.BE_MEMORY: "Configured_memory",
980 1c8addc6 Michael Hanselmann
    constants.BE_VCPUS: "VCPUs",
981 1c8addc6 Michael Hanselmann
    }
982 1c8addc6 Michael Hanselmann
983 1c8addc6 Michael Hanselmann
  hv_title = {
984 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
985 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
986 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
987 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
988 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
989 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
990 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
991 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
992 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
993 1c8addc6 Michael Hanselmann
    }
994 1c8addc6 Michael Hanselmann
995 1c8addc6 Michael Hanselmann
  fields = [
996 1c8addc6 Michael Hanselmann
    # Filled parameters
997 82599b3e Iustin Pop
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER),
998 82599b3e Iustin Pop
     IQ_CONFIG, lambda ctx, _: (QRFS_NORMAL, ctx.inst_hvparams)),
999 82599b3e Iustin Pop
    (_MakeField("beparams", "BackendParameters", QFT_OTHER),
1000 82599b3e Iustin Pop
     IQ_CONFIG, lambda ctx, _: (QRFS_NORMAL, ctx.inst_beparams)),
1001 82599b3e Iustin Pop
    (_MakeField("vcpus", "LegacyVCPUs", QFT_NUMBER), IQ_CONFIG,
1002 82599b3e Iustin Pop
     lambda ctx, _: (QRFS_NORMAL, ctx.inst_beparams[constants.BE_VCPUS])),
1003 1c8addc6 Michael Hanselmann
1004 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1005 82599b3e Iustin Pop
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER),
1006 82599b3e Iustin Pop
     IQ_CONFIG, lambda ctx, inst: (QRFS_NORMAL, inst.hvparams)),
1007 82599b3e Iustin Pop
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER),
1008 82599b3e Iustin Pop
     IQ_CONFIG, lambda ctx, inst: (QRFS_NORMAL, inst.beparams)),
1009 82599b3e Iustin Pop
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER),
1010 82599b3e Iustin Pop
     IQ_CONFIG, lambda ctx, inst: (QRFS_NORMAL,
1011 1c8addc6 Michael Hanselmann
                                   [nic.nicparams for nic in inst.nics])),
1012 1c8addc6 Michael Hanselmann
    ]
1013 1c8addc6 Michael Hanselmann
1014 1c8addc6 Michael Hanselmann
  # HV params
1015 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1016 82599b3e Iustin Pop
    return lambda ctx, _: (QRFS_NORMAL, ctx.inst_hvparams.get(name, None))
1017 1c8addc6 Michael Hanselmann
1018 1c8addc6 Michael Hanselmann
  fields.extend([
1019 1c8addc6 Michael Hanselmann
    # For now all hypervisor parameters are exported as QFT_OTHER
1020 82599b3e Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name), QFT_OTHER),
1021 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstHvParam(name))
1022 1c8addc6 Michael Hanselmann
    for name in constants.HVS_PARAMETERS
1023 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1024 1c8addc6 Michael Hanselmann
    ])
1025 1c8addc6 Michael Hanselmann
1026 1c8addc6 Michael Hanselmann
  # BE params
1027 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1028 82599b3e Iustin Pop
    return lambda ctx, _: (QRFS_NORMAL, ctx.inst_beparams.get(name, None))
1029 1c8addc6 Michael Hanselmann
1030 1c8addc6 Michael Hanselmann
  fields.extend([
1031 1c8addc6 Michael Hanselmann
    # For now all backend parameters are exported as QFT_OTHER
1032 82599b3e Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name), QFT_OTHER),
1033 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstBeParam(name))
1034 1c8addc6 Michael Hanselmann
    for name in constants.BES_PARAMETERS
1035 1c8addc6 Michael Hanselmann
    ])
1036 1c8addc6 Michael Hanselmann
1037 1c8addc6 Michael Hanselmann
  return fields
1038 1c8addc6 Michael Hanselmann
1039 1c8addc6 Michael Hanselmann
1040 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1041 82599b3e Iustin Pop
  "disk_template": ("Disk_template", QFT_TEXT),
1042 82599b3e Iustin Pop
  "hypervisor": ("Hypervisor", QFT_TEXT),
1043 82599b3e Iustin Pop
  "name": ("Node", QFT_TEXT),
1044 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1045 82599b3e Iustin Pop
  "network_port": ("Network_port", QFT_OTHER),
1046 82599b3e Iustin Pop
  "os": ("OS", QFT_TEXT),
1047 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
1048 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
1049 1c8addc6 Michael Hanselmann
  }
1050 1c8addc6 Michael Hanselmann
1051 1c8addc6 Michael Hanselmann
1052 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1053 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1054 1c8addc6 Michael Hanselmann

1055 1c8addc6 Michael Hanselmann
  """
1056 1c8addc6 Michael Hanselmann
  fields = [
1057 82599b3e Iustin Pop
    (_MakeField("pnode", "Primary_node", QFT_TEXT), IQ_CONFIG,
1058 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, inst.primary_node)),
1059 82599b3e Iustin Pop
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER), IQ_CONFIG,
1060 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, list(inst.secondary_nodes))),
1061 82599b3e Iustin Pop
    (_MakeField("admin_state", "Autostart", QFT_BOOL), IQ_CONFIG,
1062 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, inst.admin_up)),
1063 82599b3e Iustin Pop
    (_MakeField("tags", "Tags", QFT_OTHER), IQ_CONFIG,
1064 82599b3e Iustin Pop
     lambda ctx, inst: (QRFS_NORMAL, list(inst.GetTags()))),
1065 1c8addc6 Michael Hanselmann
    ]
1066 1c8addc6 Michael Hanselmann
1067 1c8addc6 Michael Hanselmann
  # Add simple fields
1068 1c8addc6 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), IQ_CONFIG, _GetItemAttr(name))
1069 1c8addc6 Michael Hanselmann
                 for (name, (title, kind)) in _INST_SIMPLE_FIELDS.items()])
1070 1c8addc6 Michael Hanselmann
1071 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1072 1c8addc6 Michael Hanselmann
  fields.extend([
1073 82599b3e Iustin Pop
    (_MakeField("oper_state", "Running", QFT_BOOL), IQ_LIVE,
1074 1c8addc6 Michael Hanselmann
     _GetInstOperState),
1075 82599b3e Iustin Pop
    (_MakeField("oper_ram", "RuntimeMemory", QFT_UNIT), IQ_LIVE,
1076 1c8addc6 Michael Hanselmann
     _GetInstLiveData("memory")),
1077 82599b3e Iustin Pop
    (_MakeField("oper_vcpus", "RuntimeVCPUs", QFT_NUMBER), IQ_LIVE,
1078 1c8addc6 Michael Hanselmann
     _GetInstLiveData("vcpus")),
1079 82599b3e Iustin Pop
    (_MakeField("status", "Status", QFT_TEXT), IQ_LIVE, _GetInstStatus),
1080 1c8addc6 Michael Hanselmann
    ])
1081 1c8addc6 Michael Hanselmann
1082 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1083 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1084 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceNetworkFields())
1085 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1086 1c8addc6 Michael Hanselmann
1087 1c8addc6 Michael Hanselmann
  return _PrepareFieldList(fields)
1088 1c8addc6 Michael Hanselmann
1089 1c8addc6 Michael Hanselmann
1090 24d16f76 Michael Hanselmann
class LockQueryData:
1091 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1092 24d16f76 Michael Hanselmann

1093 24d16f76 Michael Hanselmann
  """
1094 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1095 24d16f76 Michael Hanselmann
    """Initializes this class.
1096 24d16f76 Michael Hanselmann

1097 24d16f76 Michael Hanselmann
    """
1098 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1099 24d16f76 Michael Hanselmann
1100 24d16f76 Michael Hanselmann
  def __iter__(self):
1101 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1102 24d16f76 Michael Hanselmann

1103 24d16f76 Michael Hanselmann
    """
1104 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1105 24d16f76 Michael Hanselmann
1106 24d16f76 Michael Hanselmann
1107 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1108 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1109 24d16f76 Michael Hanselmann

1110 24d16f76 Michael Hanselmann
  """
1111 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1112 24d16f76 Michael Hanselmann
1113 24d16f76 Michael Hanselmann
  if owners:
1114 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1115 24d16f76 Michael Hanselmann
1116 82599b3e Iustin Pop
  return (QRFS_NORMAL, owners)
1117 24d16f76 Michael Hanselmann
1118 24d16f76 Michael Hanselmann
1119 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1120 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1121 24d16f76 Michael Hanselmann

1122 24d16f76 Michael Hanselmann
  """
1123 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1124 24d16f76 Michael Hanselmann
1125 24d16f76 Michael Hanselmann
  if pending:
1126 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1127 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1128 24d16f76 Michael Hanselmann
1129 82599b3e Iustin Pop
  return (QRFS_NORMAL, pending)
1130 24d16f76 Michael Hanselmann
1131 24d16f76 Michael Hanselmann
1132 24d16f76 Michael Hanselmann
def _BuildLockFields():
1133 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1134 24d16f76 Michael Hanselmann

1135 24d16f76 Michael Hanselmann
  """
1136 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1137 82599b3e Iustin Pop
    (_MakeField("name", "Name", QFT_TEXT), None,
1138 82599b3e Iustin Pop
     lambda ctx, (name, mode, owners, pending): (QRFS_NORMAL, name)),
1139 82599b3e Iustin Pop
    (_MakeField("mode", "Mode", QFT_OTHER), LQ_MODE,
1140 82599b3e Iustin Pop
     lambda ctx, (name, mode, owners, pending): (QRFS_NORMAL, mode)),
1141 82599b3e Iustin Pop
    (_MakeField("owner", "Owner", QFT_OTHER), LQ_OWNER, _GetLockOwners),
1142 82599b3e Iustin Pop
    (_MakeField("pending", "Pending", QFT_OTHER), LQ_PENDING, _GetLockPending),
1143 24d16f76 Michael Hanselmann
    ])
1144 24d16f76 Michael Hanselmann
1145 24d16f76 Michael Hanselmann
1146 8e21cfc0 Adeodato Simo
class GroupQueryData:
1147 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1148 8e21cfc0 Adeodato Simo

1149 8e21cfc0 Adeodato Simo
  """
1150 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1151 8e21cfc0 Adeodato Simo
    """Initializes this class.
1152 8e21cfc0 Adeodato Simo

1153 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1154 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1155 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1156 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1157 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1158 8e21cfc0 Adeodato Simo

1159 8e21cfc0 Adeodato Simo
    """
1160 8e21cfc0 Adeodato Simo
    self.groups = groups
1161 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1162 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1163 8e21cfc0 Adeodato Simo
1164 8e21cfc0 Adeodato Simo
  def __iter__(self):
1165 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1166 8e21cfc0 Adeodato Simo

1167 8e21cfc0 Adeodato Simo
    """
1168 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1169 8e21cfc0 Adeodato Simo
1170 8e21cfc0 Adeodato Simo
1171 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1172 82599b3e Iustin Pop
  "alloc_policy": ("AllocPolicy", QFT_TEXT),
1173 82599b3e Iustin Pop
  "name": ("Group", QFT_TEXT),
1174 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
1175 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
1176 82599b3e Iustin Pop
  "ndparams": ("NDParams", QFT_OTHER),
1177 8e21cfc0 Adeodato Simo
  }
1178 8e21cfc0 Adeodato Simo
1179 8e21cfc0 Adeodato Simo
1180 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1181 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1182 8e21cfc0 Adeodato Simo

1183 8e21cfc0 Adeodato Simo
  """
1184 8e21cfc0 Adeodato Simo
  # Add simple fields
1185 8e21cfc0 Adeodato Simo
  fields = [(_MakeField(name, title, kind), GQ_CONFIG, _GetItemAttr(name))
1186 8e21cfc0 Adeodato Simo
            for (name, (title, kind)) in _GROUP_SIMPLE_FIELDS.items()]
1187 8e21cfc0 Adeodato Simo
1188 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1189 82599b3e Iustin Pop
    return lambda ctx, group: (QRFS_NORMAL, len(getter(ctx)[group.uuid]))
1190 8e21cfc0 Adeodato Simo
1191 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1192 82599b3e Iustin Pop
    return lambda ctx, group: (QRFS_NORMAL,
1193 8e21cfc0 Adeodato Simo
                               utils.NiceSort(getter(ctx)[group.uuid]))
1194 8e21cfc0 Adeodato Simo
1195 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1196 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1197 8e21cfc0 Adeodato Simo
1198 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1199 8e21cfc0 Adeodato Simo
  fields.extend([
1200 82599b3e Iustin Pop
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER),
1201 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetLength(group_to_nodes)),
1202 82599b3e Iustin Pop
    (_MakeField("node_list", "NodeList", QFT_OTHER),
1203 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetSortedList(group_to_nodes)),
1204 8e21cfc0 Adeodato Simo
    ])
1205 8e21cfc0 Adeodato Simo
1206 8e21cfc0 Adeodato Simo
  # Add fields for instances
1207 8e21cfc0 Adeodato Simo
  fields.extend([
1208 82599b3e Iustin Pop
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER),
1209 8e21cfc0 Adeodato Simo
     GQ_INST, _GetLength(group_to_instances)),
1210 82599b3e Iustin Pop
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER),
1211 8e21cfc0 Adeodato Simo
     GQ_INST, _GetSortedList(group_to_instances)),
1212 8e21cfc0 Adeodato Simo
    ])
1213 8e21cfc0 Adeodato Simo
1214 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1215 8e21cfc0 Adeodato Simo
1216 8e21cfc0 Adeodato Simo
  return _PrepareFieldList(fields)
1217 8e21cfc0 Adeodato Simo
1218 8e21cfc0 Adeodato Simo
1219 8235fe04 Michael Hanselmann
#: Fields available for node queries
1220 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
1221 1c8addc6 Michael Hanselmann
1222 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
1223 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
1224 24d16f76 Michael Hanselmann
1225 24d16f76 Michael Hanselmann
#: Fields available for lock queries
1226 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
1227 e571ee44 Adeodato Simo
1228 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
1229 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
1230 8e21cfc0 Adeodato Simo
1231 e571ee44 Adeodato Simo
#: All available field lists
1232 8e21cfc0 Adeodato Simo
ALL_FIELD_LISTS = [NODE_FIELDS, INSTANCE_FIELDS, LOCK_FIELDS, GROUP_FIELDS]