Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 4e272d8c

History | View | Annotate | Download (58 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 79b2ca83 Michael Hanselmann
          - Human-readable description, must not end with punctuation or
36 79b2ca83 Michael Hanselmann
            contain newlines
37 8f8ce6d1 Michael Hanselmann
      - Data request type, see e.g. C{NQ_*}
38 111bf531 Michael Hanselmann
      - OR-ed flags, see C{QFF_*}
39 8f8ce6d1 Michael Hanselmann
      - A retrieval function, see L{Query.__init__} for description
40 8f8ce6d1 Michael Hanselmann
    - Pass list of fields through L{_PrepareFieldList} for preparation and
41 8f8ce6d1 Michael Hanselmann
      checks
42 8f8ce6d1 Michael Hanselmann
  - Instantiate L{Query} with prepared field list definition and selected fields
43 8f8ce6d1 Michael Hanselmann
  - Call L{Query.RequestedData} to determine what data to collect/compute
44 8f8ce6d1 Michael Hanselmann
  - Call L{Query.Query} or L{Query.OldStyleQuery} with collected data and use
45 8f8ce6d1 Michael Hanselmann
    result
46 8f8ce6d1 Michael Hanselmann
      - Data container must support iteration using C{__iter__}
47 8f8ce6d1 Michael Hanselmann
      - Items are passed to retrieval functions and can have any format
48 8f8ce6d1 Michael Hanselmann
  - Call L{Query.GetFields} to get list of definitions for selected fields
49 8f8ce6d1 Michael Hanselmann

50 8f8ce6d1 Michael Hanselmann
@attention: Retrieval functions must be idempotent. They can be called multiple
51 fb0be379 Michael Hanselmann
  times, in any order and any number of times.
52 8f8ce6d1 Michael Hanselmann

53 8f8ce6d1 Michael Hanselmann
"""
54 4ca96421 Michael Hanselmann
55 8235fe04 Michael Hanselmann
import logging
56 4ca96421 Michael Hanselmann
import operator
57 4ca96421 Michael Hanselmann
import re
58 4ca96421 Michael Hanselmann
59 4ca96421 Michael Hanselmann
from ganeti import constants
60 4ca96421 Michael Hanselmann
from ganeti import errors
61 4ca96421 Michael Hanselmann
from ganeti import utils
62 4ca96421 Michael Hanselmann
from ganeti import compat
63 4ca96421 Michael Hanselmann
from ganeti import objects
64 4ca96421 Michael Hanselmann
from ganeti import ht
65 fb0be379 Michael Hanselmann
from ganeti import qlang
66 4ca96421 Michael Hanselmann
67 82599b3e Iustin Pop
from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
68 82599b3e Iustin Pop
                              QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER,
69 cfb084ae René Nussbaumer
                              RS_NORMAL, RS_UNKNOWN, RS_NODATA,
70 cfb084ae René Nussbaumer
                              RS_UNAVAIL, RS_OFFLINE)
71 82599b3e Iustin Pop
72 4ca96421 Michael Hanselmann
73 8f8ce6d1 Michael Hanselmann
# Constants for requesting data from the caller/data provider. Each property
74 8f8ce6d1 Michael Hanselmann
# collected/computed separately by the data provider should have its own to
75 8f8ce6d1 Michael Hanselmann
# only collect the requested data and not more.
76 8f8ce6d1 Michael Hanselmann
77 8235fe04 Michael Hanselmann
(NQ_CONFIG,
78 8235fe04 Michael Hanselmann
 NQ_INST,
79 8235fe04 Michael Hanselmann
 NQ_LIVE,
80 52b5d286 René Nussbaumer
 NQ_GROUP,
81 52b5d286 René Nussbaumer
 NQ_OOB) = range(1, 6)
82 8235fe04 Michael Hanselmann
83 1c8addc6 Michael Hanselmann
(IQ_CONFIG,
84 1c8addc6 Michael Hanselmann
 IQ_LIVE,
85 5d28cb6f Michael Hanselmann
 IQ_DISKUSAGE,
86 5d28cb6f Michael Hanselmann
 IQ_CONSOLE) = range(100, 104)
87 1c8addc6 Michael Hanselmann
88 24d16f76 Michael Hanselmann
(LQ_MODE,
89 24d16f76 Michael Hanselmann
 LQ_OWNER,
90 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
91 8235fe04 Michael Hanselmann
92 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
93 8e21cfc0 Adeodato Simo
 GQ_NODE,
94 8e21cfc0 Adeodato Simo
 GQ_INST) = range(200, 203)
95 8e21cfc0 Adeodato Simo
96 111bf531 Michael Hanselmann
# Query field flags
97 111bf531 Michael Hanselmann
QFF_HOSTNAME = 0x01
98 111bf531 Michael Hanselmann
QFF_IP_ADDRESS = 0x02
99 111bf531 Michael Hanselmann
# Next values: 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200
100 111bf531 Michael Hanselmann
QFF_ALL = (QFF_HOSTNAME | QFF_IP_ADDRESS)
101 8e21cfc0 Adeodato Simo
102 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
103 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
104 1ae17369 Michael Hanselmann
DOC_RE = re.compile(r"^[A-Z].*[^.,?!]$")
105 4ca96421 Michael Hanselmann
106 4ca96421 Michael Hanselmann
#: Verification function for each field type
107 4ca96421 Michael Hanselmann
_VERIFY_FN = {
108 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
109 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
110 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
111 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
112 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
113 82599b3e Iustin Pop
  QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat),
114 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
115 4ca96421 Michael Hanselmann
  }
116 4ca96421 Michael Hanselmann
117 e2d188cc Iustin Pop
# Unique objects for special field statuses
118 e2d188cc Iustin Pop
_FS_UNKNOWN = object()
119 e2d188cc Iustin Pop
_FS_NODATA = object()
120 e2d188cc Iustin Pop
_FS_UNAVAIL = object()
121 e2d188cc Iustin Pop
_FS_OFFLINE = object()
122 e2d188cc Iustin Pop
123 425e5bf0 Michael Hanselmann
#: List of all special status
124 425e5bf0 Michael Hanselmann
_FS_ALL = frozenset([_FS_UNKNOWN, _FS_NODATA, _FS_UNAVAIL, _FS_OFFLINE])
125 425e5bf0 Michael Hanselmann
126 af58707c Iustin Pop
#: VType to QFT mapping
127 af58707c Iustin Pop
_VTToQFT = {
128 af58707c Iustin Pop
  # TODO: fix validation of empty strings
129 af58707c Iustin Pop
  constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty
130 af58707c Iustin Pop
  constants.VTYPE_MAYBE_STRING: QFT_OTHER,
131 af58707c Iustin Pop
  constants.VTYPE_BOOL: QFT_BOOL,
132 af58707c Iustin Pop
  constants.VTYPE_SIZE: QFT_UNIT,
133 af58707c Iustin Pop
  constants.VTYPE_INT: QFT_NUMBER,
134 af58707c Iustin Pop
  }
135 af58707c Iustin Pop
136 79b2ca83 Michael Hanselmann
_SERIAL_NO_DOC = "%s object serial number, incremented on each modification"
137 79b2ca83 Michael Hanselmann
138 4ca96421 Michael Hanselmann
139 4ca96421 Michael Hanselmann
def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
140 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
141 4ca96421 Michael Hanselmann

142 4ca96421 Michael Hanselmann
  """
143 e2d188cc Iustin Pop
  return _FS_UNKNOWN
144 4ca96421 Michael Hanselmann
145 4ca96421 Michael Hanselmann
146 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
147 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
148 4ca96421 Michael Hanselmann

149 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
150 4ca96421 Michael Hanselmann

151 4ca96421 Michael Hanselmann
  @type fielddefs: dict
152 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
153 4ca96421 Michael Hanselmann
  @type selected: list of strings
154 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
155 4ca96421 Michael Hanselmann

156 4ca96421 Michael Hanselmann
  """
157 4ca96421 Michael Hanselmann
  result = []
158 4ca96421 Michael Hanselmann
159 4ca96421 Michael Hanselmann
  for name in selected:
160 4ca96421 Michael Hanselmann
    try:
161 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
162 4ca96421 Michael Hanselmann
    except KeyError:
163 79b2ca83 Michael Hanselmann
      fdef = (_MakeField(name, name, QFT_UNKNOWN, "Unknown field '%s'" % name),
164 111bf531 Michael Hanselmann
              None, 0, _GetUnknownField)
165 4ca96421 Michael Hanselmann
166 111bf531 Michael Hanselmann
    assert len(fdef) == 4
167 4ca96421 Michael Hanselmann
168 4ca96421 Michael Hanselmann
    result.append(fdef)
169 4ca96421 Michael Hanselmann
170 4ca96421 Michael Hanselmann
  return result
171 4ca96421 Michael Hanselmann
172 4ca96421 Michael Hanselmann
173 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
174 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
175 4ca96421 Michael Hanselmann

176 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
177 4ca96421 Michael Hanselmann

178 4ca96421 Michael Hanselmann
  """
179 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
180 4ca96421 Michael Hanselmann
181 4ca96421 Michael Hanselmann
182 fb0be379 Michael Hanselmann
class _FilterHints:
183 fb0be379 Michael Hanselmann
  """Class for filter analytics.
184 fb0be379 Michael Hanselmann

185 fb0be379 Michael Hanselmann
  When filters are used, the user of the L{Query} class usually doesn't know
186 fb0be379 Michael Hanselmann
  exactly which items will be necessary for building the result. It therefore
187 fb0be379 Michael Hanselmann
  has to prepare and compute the input data for potentially returning
188 fb0be379 Michael Hanselmann
  everything.
189 fb0be379 Michael Hanselmann

190 fb0be379 Michael Hanselmann
  There are two ways to optimize this. The first, and simpler, is to assign
191 fb0be379 Michael Hanselmann
  each field a group of data, so that the caller can determine which
192 fb0be379 Michael Hanselmann
  computations are necessary depending on the data groups requested. The list
193 fb0be379 Michael Hanselmann
  of referenced groups must also be computed for fields referenced in the
194 fb0be379 Michael Hanselmann
  filter.
195 fb0be379 Michael Hanselmann

196 fb0be379 Michael Hanselmann
  The second is restricting the items based on a primary key. The primary key
197 fb0be379 Michael Hanselmann
  is usually a unique name (e.g. a node name). This class extracts all
198 fb0be379 Michael Hanselmann
  referenced names from a filter. If it encounters any filter condition which
199 fb0be379 Michael Hanselmann
  disallows such a list to be determined (e.g. a non-equality filter), all
200 fb0be379 Michael Hanselmann
  names will be requested.
201 fb0be379 Michael Hanselmann

202 fb0be379 Michael Hanselmann
  The end-effect is that any operation other than L{qlang.OP_OR} and
203 fb0be379 Michael Hanselmann
  L{qlang.OP_EQUAL} will make the query more expensive.
204 fb0be379 Michael Hanselmann

205 fb0be379 Michael Hanselmann
  """
206 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
207 fb0be379 Michael Hanselmann
    """Initializes this class.
208 fb0be379 Michael Hanselmann

209 fb0be379 Michael Hanselmann
    @type namefield: string
210 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
211 fb0be379 Michael Hanselmann

212 fb0be379 Michael Hanselmann
    """
213 fb0be379 Michael Hanselmann
    self._namefield = namefield
214 fb0be379 Michael Hanselmann
215 fb0be379 Michael Hanselmann
    #: Whether all names need to be requested (e.g. if a non-equality operator
216 fb0be379 Michael Hanselmann
    #: has been used)
217 fb0be379 Michael Hanselmann
    self._allnames = False
218 fb0be379 Michael Hanselmann
219 fb0be379 Michael Hanselmann
    #: Which names to request
220 fb0be379 Michael Hanselmann
    self._names = None
221 fb0be379 Michael Hanselmann
222 fb0be379 Michael Hanselmann
    #: Data kinds referenced by the filter (used by L{Query.RequestedData})
223 fb0be379 Michael Hanselmann
    self._datakinds = set()
224 fb0be379 Michael Hanselmann
225 fb0be379 Michael Hanselmann
  def RequestedNames(self):
226 fb0be379 Michael Hanselmann
    """Returns all requested values.
227 fb0be379 Michael Hanselmann

228 fb0be379 Michael Hanselmann
    Returns C{None} if list of values can't be determined (e.g. encountered
229 fb0be379 Michael Hanselmann
    non-equality operators).
230 fb0be379 Michael Hanselmann

231 fb0be379 Michael Hanselmann
    @rtype: list
232 fb0be379 Michael Hanselmann

233 fb0be379 Michael Hanselmann
    """
234 fb0be379 Michael Hanselmann
    if self._allnames or self._names is None:
235 fb0be379 Michael Hanselmann
      return None
236 fb0be379 Michael Hanselmann
237 fb0be379 Michael Hanselmann
    return utils.UniqueSequence(self._names)
238 fb0be379 Michael Hanselmann
239 fb0be379 Michael Hanselmann
  def ReferencedData(self):
240 fb0be379 Michael Hanselmann
    """Returns all kinds of data referenced by the filter.
241 fb0be379 Michael Hanselmann

242 fb0be379 Michael Hanselmann
    """
243 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
244 fb0be379 Michael Hanselmann
245 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
246 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
247 fb0be379 Michael Hanselmann

248 fb0be379 Michael Hanselmann
    """
249 fb0be379 Michael Hanselmann
    self._allnames = True
250 fb0be379 Michael Hanselmann
    self._names = None
251 fb0be379 Michael Hanselmann
252 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
253 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
254 fb0be379 Michael Hanselmann

255 fb0be379 Michael Hanselmann
    @type op: string
256 fb0be379 Michael Hanselmann
    @param op: Operator
257 fb0be379 Michael Hanselmann

258 fb0be379 Michael Hanselmann
    """
259 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
260 fb0be379 Michael Hanselmann
      self._NeedAllNames()
261 fb0be379 Michael Hanselmann
262 fb0be379 Michael Hanselmann
  def NoteUnaryOp(self, op): # pylint: disable-msg=W0613
263 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
264 fb0be379 Michael Hanselmann

265 fb0be379 Michael Hanselmann
    @type op: string
266 fb0be379 Michael Hanselmann
    @param op: Operator
267 fb0be379 Michael Hanselmann

268 fb0be379 Michael Hanselmann
    """
269 fb0be379 Michael Hanselmann
    self._NeedAllNames()
270 fb0be379 Michael Hanselmann
271 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
272 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
273 fb0be379 Michael Hanselmann

274 fb0be379 Michael Hanselmann
    @type op: string
275 fb0be379 Michael Hanselmann
    @param op: Operator
276 fb0be379 Michael Hanselmann
    @type name: string
277 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
278 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
279 fb0be379 Michael Hanselmann

280 fb0be379 Michael Hanselmann
    """
281 fb0be379 Michael Hanselmann
    if datakind is not None:
282 fb0be379 Michael Hanselmann
      self._datakinds.add(datakind)
283 fb0be379 Michael Hanselmann
284 fb0be379 Michael Hanselmann
    if self._allnames:
285 fb0be379 Michael Hanselmann
      return
286 fb0be379 Michael Hanselmann
287 fb0be379 Michael Hanselmann
    # If any operator other than equality was used, all names need to be
288 fb0be379 Michael Hanselmann
    # retrieved
289 fb0be379 Michael Hanselmann
    if op == qlang.OP_EQUAL and name == self._namefield:
290 fb0be379 Michael Hanselmann
      if self._names is None:
291 fb0be379 Michael Hanselmann
        self._names = []
292 fb0be379 Michael Hanselmann
      self._names.append(value)
293 fb0be379 Michael Hanselmann
    else:
294 fb0be379 Michael Hanselmann
      self._NeedAllNames()
295 fb0be379 Michael Hanselmann
296 fb0be379 Michael Hanselmann
297 fb0be379 Michael Hanselmann
def _WrapLogicOp(op_fn, sentences, ctx, item):
298 fb0be379 Michael Hanselmann
  """Wrapper for logic operator functions.
299 fb0be379 Michael Hanselmann

300 fb0be379 Michael Hanselmann
  """
301 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
302 fb0be379 Michael Hanselmann
303 fb0be379 Michael Hanselmann
304 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
305 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
306 fb0be379 Michael Hanselmann

307 fb0be379 Michael Hanselmann
  """
308 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
309 fb0be379 Michael Hanselmann
310 fb0be379 Michael Hanselmann
311 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
312 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
313 fb0be379 Michael Hanselmann

314 fb0be379 Michael Hanselmann
  """
315 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
316 fb0be379 Michael Hanselmann
317 fb0be379 Michael Hanselmann
318 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
319 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
320 fb0be379 Michael Hanselmann

321 fb0be379 Michael Hanselmann
  """
322 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
323 fb0be379 Michael Hanselmann
324 fb0be379 Michael Hanselmann
325 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
326 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
327 23d0a608 Michael Hanselmann

328 23d0a608 Michael Hanselmann
  """
329 23d0a608 Michael Hanselmann
  try:
330 23d0a608 Michael Hanselmann
    return re.compile(pattern)
331 23d0a608 Michael Hanselmann
  except re.error, err:
332 23d0a608 Michael Hanselmann
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
333 23d0a608 Michael Hanselmann
334 23d0a608 Michael Hanselmann
335 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
336 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
337 fb0be379 Michael Hanselmann

338 fb0be379 Michael Hanselmann
  """
339 fb0be379 Michael Hanselmann
  # String statement has no effect, pylint: disable-msg=W0105
340 fb0be379 Michael Hanselmann
341 fb0be379 Michael Hanselmann
  #: How deep filters can be nested
342 fb0be379 Michael Hanselmann
  _LEVELS_MAX = 10
343 fb0be379 Michael Hanselmann
344 fb0be379 Michael Hanselmann
  # Unique identifiers for operator groups
345 fb0be379 Michael Hanselmann
  (_OPTYPE_LOGIC,
346 fb0be379 Michael Hanselmann
   _OPTYPE_UNARY,
347 fb0be379 Michael Hanselmann
   _OPTYPE_BINARY) = range(1, 4)
348 fb0be379 Michael Hanselmann
349 fb0be379 Michael Hanselmann
  """Functions for equality checks depending on field flags.
350 fb0be379 Michael Hanselmann

351 fb0be379 Michael Hanselmann
  List of tuples containing flags and a callable receiving the left- and
352 fb0be379 Michael Hanselmann
  right-hand side of the operator. The flags are an OR-ed value of C{QFF_*}
353 fb0be379 Michael Hanselmann
  (e.g. L{QFF_HOSTNAME}).
354 fb0be379 Michael Hanselmann

355 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
356 fb0be379 Michael Hanselmann
  using binary AND.
357 fb0be379 Michael Hanselmann

358 fb0be379 Michael Hanselmann
  """
359 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
360 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
361 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
362 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
363 23d0a608 Michael Hanselmann
     None),
364 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
365 fb0be379 Michael Hanselmann
    ]
366 fb0be379 Michael Hanselmann
367 fb0be379 Michael Hanselmann
  """Known operators
368 fb0be379 Michael Hanselmann

369 fb0be379 Michael Hanselmann
  Operator as key (C{qlang.OP_*}), value a tuple of operator group
370 fb0be379 Michael Hanselmann
  (C{_OPTYPE_*}) and a group-specific value:
371 fb0be379 Michael Hanselmann

372 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
373 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
374 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
375 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
376 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
377 fb0be379 Michael Hanselmann

378 fb0be379 Michael Hanselmann
  """
379 fb0be379 Michael Hanselmann
  _OPS = {
380 fb0be379 Michael Hanselmann
    # Logic operators
381 fb0be379 Michael Hanselmann
    qlang.OP_OR: (_OPTYPE_LOGIC, compat.any),
382 fb0be379 Michael Hanselmann
    qlang.OP_AND: (_OPTYPE_LOGIC, compat.all),
383 fb0be379 Michael Hanselmann
384 fb0be379 Michael Hanselmann
    # Unary operators
385 3b877f08 Michael Hanselmann
    qlang.OP_NOT: (_OPTYPE_UNARY, None),
386 3b877f08 Michael Hanselmann
    qlang.OP_TRUE: (_OPTYPE_UNARY, None),
387 fb0be379 Michael Hanselmann
388 fb0be379 Michael Hanselmann
    # Binary operators
389 fb0be379 Michael Hanselmann
    qlang.OP_EQUAL: (_OPTYPE_BINARY, _EQUALITY_CHECKS),
390 fb0be379 Michael Hanselmann
    qlang.OP_NOT_EQUAL:
391 23d0a608 Michael Hanselmann
      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn), valprepfn)
392 23d0a608 Michael Hanselmann
                        for (flags, fn, valprepfn) in _EQUALITY_CHECKS]),
393 23d0a608 Michael Hanselmann
    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
394 23d0a608 Michael Hanselmann
      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
395 23d0a608 Michael Hanselmann
      ]),
396 fb0be379 Michael Hanselmann
    qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
397 23d0a608 Michael Hanselmann
      (None, operator.contains, None),
398 fb0be379 Michael Hanselmann
      ]),
399 fb0be379 Michael Hanselmann
    }
400 fb0be379 Michael Hanselmann
401 fb0be379 Michael Hanselmann
  def __init__(self, fields):
402 fb0be379 Michael Hanselmann
    """Initializes this class.
403 fb0be379 Michael Hanselmann

404 fb0be379 Michael Hanselmann
    @param fields: Field definitions (return value of L{_PrepareFieldList})
405 fb0be379 Michael Hanselmann

406 fb0be379 Michael Hanselmann
    """
407 fb0be379 Michael Hanselmann
    self._fields = fields
408 fb0be379 Michael Hanselmann
    self._hints = None
409 fb0be379 Michael Hanselmann
    self._op_handler = None
410 fb0be379 Michael Hanselmann
411 fb0be379 Michael Hanselmann
  def __call__(self, hints, filter_):
412 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
413 fb0be379 Michael Hanselmann

414 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
415 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
416 fb0be379 Michael Hanselmann
    @type filter_: list
417 fb0be379 Michael Hanselmann
    @param filter_: Filter structure
418 fb0be379 Michael Hanselmann
    @rtype: callable
419 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
420 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
421 fb0be379 Michael Hanselmann

422 fb0be379 Michael Hanselmann
    """
423 fb0be379 Michael Hanselmann
    self._op_handler = {
424 fb0be379 Michael Hanselmann
      self._OPTYPE_LOGIC:
425 fb0be379 Michael Hanselmann
        (self._HandleLogicOp, getattr(hints, "NoteLogicOp", None)),
426 fb0be379 Michael Hanselmann
      self._OPTYPE_UNARY:
427 fb0be379 Michael Hanselmann
        (self._HandleUnaryOp, getattr(hints, "NoteUnaryOp", None)),
428 fb0be379 Michael Hanselmann
      self._OPTYPE_BINARY:
429 fb0be379 Michael Hanselmann
        (self._HandleBinaryOp, getattr(hints, "NoteBinaryOp", None)),
430 fb0be379 Michael Hanselmann
      }
431 fb0be379 Michael Hanselmann
432 fb0be379 Michael Hanselmann
    try:
433 fb0be379 Michael Hanselmann
      filter_fn = self._Compile(filter_, 0)
434 fb0be379 Michael Hanselmann
    finally:
435 fb0be379 Michael Hanselmann
      self._op_handler = None
436 fb0be379 Michael Hanselmann
437 fb0be379 Michael Hanselmann
    return filter_fn
438 fb0be379 Michael Hanselmann
439 fb0be379 Michael Hanselmann
  def _Compile(self, filter_, level):
440 fb0be379 Michael Hanselmann
    """Inner function for converting filters.
441 fb0be379 Michael Hanselmann

442 fb0be379 Michael Hanselmann
    Calls the correct handler functions for the top-level operator. This
443 fb0be379 Michael Hanselmann
    function is called recursively (e.g. for logic operators).
444 fb0be379 Michael Hanselmann

445 fb0be379 Michael Hanselmann
    """
446 fb0be379 Michael Hanselmann
    if not (isinstance(filter_, (list, tuple)) and filter_):
447 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid filter on level %s" % level)
448 fb0be379 Michael Hanselmann
449 fb0be379 Michael Hanselmann
    # Limit recursion
450 fb0be379 Michael Hanselmann
    if level >= self._LEVELS_MAX:
451 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Only up to %s levels are allowed (filter"
452 fb0be379 Michael Hanselmann
                                  " nested too deep)" % self._LEVELS_MAX)
453 fb0be379 Michael Hanselmann
454 fb0be379 Michael Hanselmann
    # Create copy to be modified
455 fb0be379 Michael Hanselmann
    operands = filter_[:]
456 fb0be379 Michael Hanselmann
    op = operands.pop(0)
457 fb0be379 Michael Hanselmann
458 fb0be379 Michael Hanselmann
    try:
459 fb0be379 Michael Hanselmann
      (kind, op_data) = self._OPS[op]
460 fb0be379 Michael Hanselmann
    except KeyError:
461 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unknown operator '%s'" % op)
462 fb0be379 Michael Hanselmann
463 fb0be379 Michael Hanselmann
    (handler, hints_cb) = self._op_handler[kind]
464 fb0be379 Michael Hanselmann
465 fb0be379 Michael Hanselmann
    return handler(hints_cb, level, op, op_data, operands)
466 fb0be379 Michael Hanselmann
467 3b877f08 Michael Hanselmann
  def _LookupField(self, name):
468 3b877f08 Michael Hanselmann
    """Returns a field definition by name.
469 3b877f08 Michael Hanselmann

470 3b877f08 Michael Hanselmann
    """
471 3b877f08 Michael Hanselmann
    try:
472 3b877f08 Michael Hanselmann
      return self._fields[name]
473 3b877f08 Michael Hanselmann
    except KeyError:
474 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
475 3b877f08 Michael Hanselmann
476 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
477 fb0be379 Michael Hanselmann
    """Handles logic operators.
478 fb0be379 Michael Hanselmann

479 fb0be379 Michael Hanselmann
    @type hints_fn: callable
480 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
481 fb0be379 Michael Hanselmann
    @type level: integer
482 fb0be379 Michael Hanselmann
    @param level: Current depth
483 fb0be379 Michael Hanselmann
    @type op: string
484 fb0be379 Michael Hanselmann
    @param op: Operator
485 fb0be379 Michael Hanselmann
    @type op_fn: callable
486 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
487 fb0be379 Michael Hanselmann
    @type operands: list
488 fb0be379 Michael Hanselmann
    @param operands: List of operands
489 fb0be379 Michael Hanselmann

490 fb0be379 Michael Hanselmann
    """
491 fb0be379 Michael Hanselmann
    if hints_fn:
492 fb0be379 Michael Hanselmann
      hints_fn(op)
493 fb0be379 Michael Hanselmann
494 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
495 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
496 fb0be379 Michael Hanselmann
497 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
498 fb0be379 Michael Hanselmann
    """Handles unary operators.
499 fb0be379 Michael Hanselmann

500 fb0be379 Michael Hanselmann
    @type hints_fn: callable
501 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
502 fb0be379 Michael Hanselmann
    @type level: integer
503 fb0be379 Michael Hanselmann
    @param level: Current depth
504 fb0be379 Michael Hanselmann
    @type op: string
505 fb0be379 Michael Hanselmann
    @param op: Operator
506 fb0be379 Michael Hanselmann
    @type op_fn: callable
507 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
508 fb0be379 Michael Hanselmann
    @type operands: list
509 fb0be379 Michael Hanselmann
    @param operands: List of operands
510 fb0be379 Michael Hanselmann

511 fb0be379 Michael Hanselmann
    """
512 3b877f08 Michael Hanselmann
    assert op_fn is None
513 3b877f08 Michael Hanselmann
514 fb0be379 Michael Hanselmann
    if hints_fn:
515 fb0be379 Michael Hanselmann
      hints_fn(op)
516 fb0be379 Michael Hanselmann
517 fb0be379 Michael Hanselmann
    if len(operands) != 1:
518 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unary operator '%s' expects exactly one"
519 fb0be379 Michael Hanselmann
                                  " operand" % op)
520 fb0be379 Michael Hanselmann
521 3b877f08 Michael Hanselmann
    if op == qlang.OP_TRUE:
522 3b877f08 Michael Hanselmann
      (_, _, _, retrieval_fn) = self._LookupField(operands[0])
523 3b877f08 Michael Hanselmann
524 3b877f08 Michael Hanselmann
      op_fn = operator.truth
525 3b877f08 Michael Hanselmann
      arg = retrieval_fn
526 3b877f08 Michael Hanselmann
    elif op == qlang.OP_NOT:
527 3b877f08 Michael Hanselmann
      op_fn = operator.not_
528 3b877f08 Michael Hanselmann
      arg = self._Compile(operands[0], level + 1)
529 3b877f08 Michael Hanselmann
    else:
530 3b877f08 Michael Hanselmann
      raise errors.ProgrammerError("Can't handle operator '%s'" % op)
531 3b877f08 Michael Hanselmann
532 3b877f08 Michael Hanselmann
    return compat.partial(_WrapUnaryOp, op_fn, arg)
533 fb0be379 Michael Hanselmann
534 fb0be379 Michael Hanselmann
  def _HandleBinaryOp(self, hints_fn, level, op, op_data, operands):
535 fb0be379 Michael Hanselmann
    """Handles binary operators.
536 fb0be379 Michael Hanselmann

537 fb0be379 Michael Hanselmann
    @type hints_fn: callable
538 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
539 fb0be379 Michael Hanselmann
    @type level: integer
540 fb0be379 Michael Hanselmann
    @param level: Current depth
541 fb0be379 Michael Hanselmann
    @type op: string
542 fb0be379 Michael Hanselmann
    @param op: Operator
543 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
544 fb0be379 Michael Hanselmann
    @type operands: list
545 fb0be379 Michael Hanselmann
    @param operands: List of operands
546 fb0be379 Michael Hanselmann

547 fb0be379 Michael Hanselmann
    """
548 fb0be379 Michael Hanselmann
    # Unused arguments, pylint: disable-msg=W0613
549 fb0be379 Michael Hanselmann
    try:
550 fb0be379 Michael Hanselmann
      (name, value) = operands
551 fb0be379 Michael Hanselmann
    except (ValueError, TypeError):
552 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid binary operator, expected exactly"
553 fb0be379 Michael Hanselmann
                                  " two operands")
554 fb0be379 Michael Hanselmann
555 3b877f08 Michael Hanselmann
    (fdef, datakind, field_flags, retrieval_fn) = self._LookupField(name)
556 fb0be379 Michael Hanselmann
557 fb0be379 Michael Hanselmann
    assert fdef.kind != QFT_UNKNOWN
558 fb0be379 Michael Hanselmann
559 fb0be379 Michael Hanselmann
    # TODO: Type conversions?
560 fb0be379 Michael Hanselmann
561 fb0be379 Michael Hanselmann
    verify_fn = _VERIFY_FN[fdef.kind]
562 fb0be379 Michael Hanselmann
    if not verify_fn(value):
563 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unable to compare field '%s' (type '%s')"
564 fb0be379 Michael Hanselmann
                                  " with '%s', expected %s" %
565 fb0be379 Michael Hanselmann
                                  (name, fdef.kind, value.__class__.__name__,
566 fb0be379 Michael Hanselmann
                                   verify_fn))
567 fb0be379 Michael Hanselmann
568 fb0be379 Michael Hanselmann
    if hints_fn:
569 fb0be379 Michael Hanselmann
      hints_fn(op, datakind, name, value)
570 fb0be379 Michael Hanselmann
571 23d0a608 Michael Hanselmann
    for (fn_flags, fn, valprepfn) in op_data:
572 fb0be379 Michael Hanselmann
      if fn_flags is None or fn_flags & field_flags:
573 23d0a608 Michael Hanselmann
        # Prepare value if necessary (e.g. compile regular expression)
574 23d0a608 Michael Hanselmann
        if valprepfn:
575 23d0a608 Michael Hanselmann
          value = valprepfn(value)
576 23d0a608 Michael Hanselmann
577 fb0be379 Michael Hanselmann
        return compat.partial(_WrapBinaryOp, fn, retrieval_fn, value)
578 fb0be379 Michael Hanselmann
579 fb0be379 Michael Hanselmann
    raise errors.ProgrammerError("Unable to find operator implementation"
580 fb0be379 Michael Hanselmann
                                 " (op '%s', flags %s)" % (op, field_flags))
581 fb0be379 Michael Hanselmann
582 fb0be379 Michael Hanselmann
583 fb0be379 Michael Hanselmann
def _CompileFilter(fields, hints, filter_):
584 fb0be379 Michael Hanselmann
  """Converts a query filter into a callable function.
585 fb0be379 Michael Hanselmann

586 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
587 fb0be379 Michael Hanselmann

588 fb0be379 Michael Hanselmann
  @rtype: callable
589 fb0be379 Michael Hanselmann

590 fb0be379 Michael Hanselmann
  """
591 fb0be379 Michael Hanselmann
  return _FilterCompilerHelper(fields)(hints, filter_)
592 fb0be379 Michael Hanselmann
593 fb0be379 Michael Hanselmann
594 4ca96421 Michael Hanselmann
class Query:
595 fb0be379 Michael Hanselmann
  def __init__(self, fieldlist, selected, filter_=None, namefield=None):
596 4ca96421 Michael Hanselmann
    """Initializes this class.
597 4ca96421 Michael Hanselmann

598 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
599 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
600 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
601 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
602 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
603 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
604 4ca96421 Michael Hanselmann

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

608 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
609 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
610 4ca96421 Michael Hanselmann
    @type selected: list of strings
611 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
612 4ca96421 Michael Hanselmann

613 4ca96421 Michael Hanselmann
    """
614 fb0be379 Michael Hanselmann
    assert namefield is None or namefield in fieldlist
615 fb0be379 Michael Hanselmann
616 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
617 4ca96421 Michael Hanselmann
618 fb0be379 Michael Hanselmann
    self._filter_fn = None
619 fb0be379 Michael Hanselmann
    self._requested_names = None
620 fb0be379 Michael Hanselmann
    self._filter_datakinds = frozenset()
621 fb0be379 Michael Hanselmann
622 fb0be379 Michael Hanselmann
    if filter_ is not None:
623 fb0be379 Michael Hanselmann
      # Collect requested names if wanted
624 fb0be379 Michael Hanselmann
      if namefield:
625 fb0be379 Michael Hanselmann
        hints = _FilterHints(namefield)
626 fb0be379 Michael Hanselmann
      else:
627 fb0be379 Michael Hanselmann
        hints = None
628 fb0be379 Michael Hanselmann
629 fb0be379 Michael Hanselmann
      # Build filter function
630 fb0be379 Michael Hanselmann
      self._filter_fn = _CompileFilter(fieldlist, hints, filter_)
631 fb0be379 Michael Hanselmann
      if hints:
632 fb0be379 Michael Hanselmann
        self._requested_names = hints.RequestedNames()
633 fb0be379 Michael Hanselmann
        self._filter_datakinds = hints.ReferencedData()
634 fb0be379 Michael Hanselmann
635 fb0be379 Michael Hanselmann
    if namefield is None:
636 fb0be379 Michael Hanselmann
      self._name_fn = None
637 fb0be379 Michael Hanselmann
    else:
638 fb0be379 Michael Hanselmann
      (_, _, _, self._name_fn) = fieldlist[namefield]
639 fb0be379 Michael Hanselmann
640 fb0be379 Michael Hanselmann
  def RequestedNames(self):
641 fb0be379 Michael Hanselmann
    """Returns all names referenced in the filter.
642 fb0be379 Michael Hanselmann

643 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
644 fb0be379 Michael Hanselmann
    names, C{None} is returned.
645 fb0be379 Michael Hanselmann

646 fb0be379 Michael Hanselmann
    """
647 fb0be379 Michael Hanselmann
    return self._requested_names
648 fb0be379 Michael Hanselmann
649 4ca96421 Michael Hanselmann
  def RequestedData(self):
650 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
651 4ca96421 Michael Hanselmann

652 4ca96421 Michael Hanselmann
    @rtype: frozenset
653 4ca96421 Michael Hanselmann

654 4ca96421 Michael Hanselmann
    """
655 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
656 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
657 fb0be379 Michael Hanselmann
                      if datakind is not None))
658 4ca96421 Michael Hanselmann
659 4ca96421 Michael Hanselmann
  def GetFields(self):
660 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
661 4ca96421 Michael Hanselmann

662 4ca96421 Michael Hanselmann
    Includes unknown fields.
663 4ca96421 Michael Hanselmann

664 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
665 4ca96421 Michael Hanselmann

666 4ca96421 Michael Hanselmann
    """
667 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
668 4ca96421 Michael Hanselmann
669 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
670 4ca96421 Michael Hanselmann
    """Execute a query.
671 4ca96421 Michael Hanselmann

672 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
673 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
674 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
675 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
676 fbc263a9 Michael Hanselmann
      ordering
677 4ca96421 Michael Hanselmann

678 4ca96421 Michael Hanselmann
    """
679 fbc263a9 Michael Hanselmann
    sort = (self._name_fn and sort_by_name)
680 fbc263a9 Michael Hanselmann
681 fb0be379 Michael Hanselmann
    result = []
682 fb0be379 Michael Hanselmann
683 fb0be379 Michael Hanselmann
    for idx, item in enumerate(ctx):
684 fb0be379 Michael Hanselmann
      if not (self._filter_fn is None or self._filter_fn(ctx, item)):
685 fb0be379 Michael Hanselmann
        continue
686 4ca96421 Michael Hanselmann
687 fb0be379 Michael Hanselmann
      row = [_ProcessResult(fn(ctx, item)) for (_, _, _, fn) in self._fields]
688 fb0be379 Michael Hanselmann
689 fb0be379 Michael Hanselmann
      # Verify result
690 fb0be379 Michael Hanselmann
      if __debug__:
691 d1c3c3b3 Iustin Pop
        _VerifyResultRow(self._fields, row)
692 4ca96421 Michael Hanselmann
693 fbc263a9 Michael Hanselmann
      if sort:
694 fb0be379 Michael Hanselmann
        (status, name) = _ProcessResult(self._name_fn(ctx, item))
695 fb0be379 Michael Hanselmann
        assert status == constants.RS_NORMAL
696 fb0be379 Michael Hanselmann
        # TODO: Are there cases where we wouldn't want to use NiceSort?
697 fbc263a9 Michael Hanselmann
        result.append((utils.NiceSortKey(name), idx, row))
698 fb0be379 Michael Hanselmann
      else:
699 fbc263a9 Michael Hanselmann
        result.append(row)
700 fb0be379 Michael Hanselmann
701 fbc263a9 Michael Hanselmann
    if not sort:
702 fbc263a9 Michael Hanselmann
      return result
703 fb0be379 Michael Hanselmann
704 fb0be379 Michael Hanselmann
    # TODO: Would "heapq" be more efficient than sorting?
705 fb0be379 Michael Hanselmann
706 fb0be379 Michael Hanselmann
    # Sorting in-place instead of using "sorted()"
707 fb0be379 Michael Hanselmann
    result.sort()
708 fb0be379 Michael Hanselmann
709 fb0be379 Michael Hanselmann
    assert not result or (len(result[0]) == 3 and len(result[-1]) == 3)
710 fb0be379 Michael Hanselmann
711 fb0be379 Michael Hanselmann
    return map(operator.itemgetter(2), result)
712 4ca96421 Michael Hanselmann
713 fbc263a9 Michael Hanselmann
  def OldStyleQuery(self, ctx, sort_by_name=True):
714 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
715 4ca96421 Michael Hanselmann

716 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
717 4ca96421 Michael Hanselmann

718 4ca96421 Michael Hanselmann
    """
719 111bf531 Michael Hanselmann
    unknown = set(fdef.name for (fdef, _, _, _) in self._fields
720 111bf531 Michael Hanselmann
                  if fdef.kind == QFT_UNKNOWN)
721 4ca96421 Michael Hanselmann
    if unknown:
722 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
723 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
724 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
725 4ca96421 Michael Hanselmann
726 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
727 fbc263a9 Michael Hanselmann
            for row in self.Query(ctx, sort_by_name=sort_by_name)]
728 4ca96421 Michael Hanselmann
729 4ca96421 Michael Hanselmann
730 e2d188cc Iustin Pop
def _ProcessResult(value):
731 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
732 e2d188cc Iustin Pop

733 e2d188cc Iustin Pop
  """
734 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
735 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
736 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
737 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
738 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
739 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
740 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
741 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
742 e2d188cc Iustin Pop
  else:
743 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
744 e2d188cc Iustin Pop
745 e2d188cc Iustin Pop
746 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
747 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
748 4ca96421 Michael Hanselmann

749 4ca96421 Michael Hanselmann
  @type fields: list
750 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
751 4ca96421 Michael Hanselmann
  @type row: list of tuples
752 4ca96421 Michael Hanselmann
  @param row: Row data
753 4ca96421 Michael Hanselmann

754 4ca96421 Michael Hanselmann
  """
755 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
756 d1c3c3b3 Iustin Pop
  errs = []
757 111bf531 Michael Hanselmann
  for ((status, value), (fdef, _, _, _)) in zip(row, fields):
758 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
759 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
760 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
761 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
762 d1c3c3b3 Iustin Pop
    elif value is not None:
763 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
764 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
765 d1c3c3b3 Iustin Pop
                    (utils.CommaJoin(errors), row))
766 4ca96421 Michael Hanselmann
767 4ca96421 Michael Hanselmann
768 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
769 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
770 4ca96421 Michael Hanselmann

771 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
772 4ca96421 Michael Hanselmann

773 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
774 d63bd540 Iustin Pop
      kind, retrieval function)
775 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
776 d63bd540 Iustin Pop
      description
777 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
778 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
779 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
780 4ca96421 Michael Hanselmann
  @rtype: dict
781 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
782 4ca96421 Michael Hanselmann

783 4ca96421 Michael Hanselmann
  """
784 89ce4acc Michael Hanselmann
  if __debug__:
785 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
786 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
787 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
788 4ca96421 Michael Hanselmann
789 4ca96421 Michael Hanselmann
  result = {}
790 4ca96421 Michael Hanselmann
791 4ca96421 Michael Hanselmann
  for field in fields:
792 111bf531 Michael Hanselmann
    (fdef, _, flags, fn) = field
793 4ca96421 Michael Hanselmann
794 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
795 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
796 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
797 79b2ca83 Michael Hanselmann
    assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
798 79b2ca83 Michael Hanselmann
            fdef.doc.strip() == fdef.doc), \
799 79b2ca83 Michael Hanselmann
           "Invalid description for field '%s'" % fdef.name
800 4ca96421 Michael Hanselmann
    assert callable(fn)
801 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
802 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
803 111bf531 Michael Hanselmann
    assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
804 4ca96421 Michael Hanselmann
805 4ca96421 Michael Hanselmann
    result[fdef.name] = field
806 4ca96421 Michael Hanselmann
807 d63bd540 Iustin Pop
  for alias, target in aliases:
808 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
809 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
810 111bf531 Michael Hanselmann
    (fdef, k, flags, fn) = result[target]
811 d63bd540 Iustin Pop
    fdef = fdef.Copy()
812 d63bd540 Iustin Pop
    fdef.name = alias
813 111bf531 Michael Hanselmann
    result[alias] = (fdef, k, flags, fn)
814 d63bd540 Iustin Pop
815 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
816 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
817 111bf531 Michael Hanselmann
                    for (name, (fdef, _, _, _)) in result.items())
818 4ca96421 Michael Hanselmann
819 4ca96421 Michael Hanselmann
  return result
820 4ca96421 Michael Hanselmann
821 4ca96421 Michael Hanselmann
822 fbc263a9 Michael Hanselmann
def GetQueryResponse(query, ctx, sort_by_name=True):
823 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
824 b60fcb6f Michael Hanselmann

825 b60fcb6f Michael Hanselmann
  @type query: L{Query}
826 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
827 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
828 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
829 fbc263a9 Michael Hanselmann
    ordering
830 b60fcb6f Michael Hanselmann

831 b60fcb6f Michael Hanselmann
  """
832 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
833 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
834 b60fcb6f Michael Hanselmann
835 b60fcb6f Michael Hanselmann
836 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
837 aa29e95f Michael Hanselmann
  """Returns list of available fields.
838 aa29e95f Michael Hanselmann

839 aa29e95f Michael Hanselmann
  @type fielddefs: dict
840 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
841 aa29e95f Michael Hanselmann
  @type selected: list of strings
842 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
843 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
844 aa29e95f Michael Hanselmann

845 aa29e95f Michael Hanselmann
  """
846 aa29e95f Michael Hanselmann
  if selected is None:
847 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
848 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
849 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
850 aa29e95f Michael Hanselmann
  else:
851 aa29e95f Michael Hanselmann
    # Keep order as requested by client
852 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
853 aa29e95f Michael Hanselmann
854 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
855 aa29e95f Michael Hanselmann
856 aa29e95f Michael Hanselmann
857 79b2ca83 Michael Hanselmann
def _MakeField(name, title, kind, doc):
858 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
859 4ca96421 Michael Hanselmann

860 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
861 4ca96421 Michael Hanselmann
  @param title: Human-readable title
862 4ca96421 Michael Hanselmann
  @param kind: Field type
863 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
864 4ca96421 Michael Hanselmann

865 4ca96421 Michael Hanselmann
  """
866 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
867 1ae17369 Michael Hanselmann
                                      doc=doc)
868 8235fe04 Michael Hanselmann
869 8235fe04 Michael Hanselmann
870 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
871 8235fe04 Michael Hanselmann
  """Determine node role.
872 8235fe04 Michael Hanselmann

873 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
874 8235fe04 Michael Hanselmann
  @param node: Node object
875 8235fe04 Michael Hanselmann
  @type master_name: string
876 8235fe04 Michael Hanselmann
  @param master_name: Master node name
877 8235fe04 Michael Hanselmann

878 8235fe04 Michael Hanselmann
  """
879 8235fe04 Michael Hanselmann
  if node.name == master_name:
880 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
881 8235fe04 Michael Hanselmann
  elif node.master_candidate:
882 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
883 8235fe04 Michael Hanselmann
  elif node.drained:
884 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
885 8235fe04 Michael Hanselmann
  elif node.offline:
886 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
887 8235fe04 Michael Hanselmann
  else:
888 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
889 8235fe04 Michael Hanselmann
890 8235fe04 Michael Hanselmann
891 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
892 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
893 8235fe04 Michael Hanselmann

894 8235fe04 Michael Hanselmann
  @param attr: Attribute name
895 8235fe04 Michael Hanselmann

896 8235fe04 Michael Hanselmann
  """
897 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
898 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
899 8235fe04 Michael Hanselmann
900 8235fe04 Michael Hanselmann
901 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
902 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
903 425e5bf0 Michael Hanselmann

904 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
905 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
906 425e5bf0 Michael Hanselmann

907 425e5bf0 Michael Hanselmann
  """
908 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
909 425e5bf0 Michael Hanselmann
910 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
911 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
912 425e5bf0 Michael Hanselmann
    # Return right away
913 425e5bf0 Michael Hanselmann
    return value
914 425e5bf0 Michael Hanselmann
915 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
916 425e5bf0 Michael Hanselmann
  return convert(value)
917 425e5bf0 Michael Hanselmann
918 425e5bf0 Michael Hanselmann
919 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
920 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
921 425e5bf0 Michael Hanselmann

922 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
923 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
924 425e5bf0 Michael Hanselmann

925 425e5bf0 Michael Hanselmann
  """
926 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
927 425e5bf0 Michael Hanselmann
928 425e5bf0 Michael Hanselmann
929 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
930 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
931 145bea54 Michael Hanselmann

932 145bea54 Michael Hanselmann
  @type getter: callable
933 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
934 145bea54 Michael Hanselmann

935 145bea54 Michael Hanselmann
  """
936 145bea54 Michael Hanselmann
  def fn(_, item):
937 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
938 145bea54 Michael Hanselmann

939 145bea54 Michael Hanselmann
    """
940 145bea54 Michael Hanselmann
    timestamp = getter(item)
941 145bea54 Michael Hanselmann
    if timestamp is None:
942 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
943 e2d188cc Iustin Pop
      return _FS_UNAVAIL
944 145bea54 Michael Hanselmann
    else:
945 e2d188cc Iustin Pop
      return timestamp
946 145bea54 Michael Hanselmann
947 145bea54 Michael Hanselmann
  return fn
948 145bea54 Michael Hanselmann
949 145bea54 Michael Hanselmann
950 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
951 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
952 145bea54 Michael Hanselmann

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

955 145bea54 Michael Hanselmann
  """
956 145bea54 Michael Hanselmann
  return [
957 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
958 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
959 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
960 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
961 145bea54 Michael Hanselmann
    ]
962 145bea54 Michael Hanselmann
963 145bea54 Michael Hanselmann
964 8235fe04 Michael Hanselmann
class NodeQueryData:
965 8235fe04 Michael Hanselmann
  """Data container for node data queries.
966 8235fe04 Michael Hanselmann

967 8235fe04 Michael Hanselmann
  """
968 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
969 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
970 8235fe04 Michael Hanselmann
    """Initializes this class.
971 8235fe04 Michael Hanselmann

972 8235fe04 Michael Hanselmann
    """
973 8235fe04 Michael Hanselmann
    self.nodes = nodes
974 8235fe04 Michael Hanselmann
    self.live_data = live_data
975 8235fe04 Michael Hanselmann
    self.master_name = master_name
976 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
977 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
978 8235fe04 Michael Hanselmann
    self.groups = groups
979 52b5d286 René Nussbaumer
    self.oob_support = oob_support
980 8572f1fe René Nussbaumer
    self.cluster = cluster
981 8235fe04 Michael Hanselmann
982 8235fe04 Michael Hanselmann
    # Used for individual rows
983 8235fe04 Michael Hanselmann
    self.curlive_data = None
984 8235fe04 Michael Hanselmann
985 8235fe04 Michael Hanselmann
  def __iter__(self):
986 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
987 8235fe04 Michael Hanselmann

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

991 8235fe04 Michael Hanselmann
    """
992 8235fe04 Michael Hanselmann
    for node in self.nodes:
993 8235fe04 Michael Hanselmann
      if self.live_data:
994 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
995 8235fe04 Michael Hanselmann
      else:
996 8235fe04 Michael Hanselmann
        self.curlive_data = None
997 8235fe04 Michael Hanselmann
      yield node
998 8235fe04 Michael Hanselmann
999 8235fe04 Michael Hanselmann
1000 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
1001 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
1002 111bf531 Michael Hanselmann
  "drained": ("Drained", QFT_BOOL, 0, "Whether node is drained"),
1003 111bf531 Michael Hanselmann
  "master_candidate": ("MasterC", QFT_BOOL, 0,
1004 79b2ca83 Michael Hanselmann
                       "Whether node is a master candidate"),
1005 111bf531 Michael Hanselmann
  "master_capable": ("MasterCapable", QFT_BOOL, 0,
1006 79b2ca83 Michael Hanselmann
                     "Whether node can become a master candidate"),
1007 111bf531 Michael Hanselmann
  "name": ("Node", QFT_TEXT, QFF_HOSTNAME, "Node name"),
1008 111bf531 Michael Hanselmann
  "offline": ("Offline", QFT_BOOL, 0, "Whether node is marked offline"),
1009 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Node"),
1010 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Node UUID"),
1011 111bf531 Michael Hanselmann
  "vm_capable": ("VMCapable", QFT_BOOL, 0, "Whether node can host instances"),
1012 8235fe04 Michael Hanselmann
  }
1013 8235fe04 Michael Hanselmann
1014 8235fe04 Michael Hanselmann
1015 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
1016 effab4ca Iustin Pop
# Note that none of these are available for non-vm_capable nodes
1017 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
1018 79b2ca83 Michael Hanselmann
  "bootid": ("BootID", QFT_TEXT, "bootid",
1019 79b2ca83 Michael Hanselmann
             "Random UUID renewed for each system reboot, can be used"
1020 79b2ca83 Michael Hanselmann
             " for detecting reboots by tracking changes"),
1021 79b2ca83 Michael Hanselmann
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes",
1022 79b2ca83 Michael Hanselmann
             "Number of NUMA domains on node (if exported by hypervisor)"),
1023 79b2ca83 Michael Hanselmann
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets",
1024 79b2ca83 Michael Hanselmann
               "Number of physical CPU sockets (if exported by hypervisor)"),
1025 79b2ca83 Michael Hanselmann
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total", "Number of logical processors"),
1026 79b2ca83 Michael Hanselmann
  "dfree": ("DFree", QFT_UNIT, "vg_free",
1027 79b2ca83 Michael Hanselmann
            "Available disk space in volume group"),
1028 79b2ca83 Michael Hanselmann
  "dtotal": ("DTotal", QFT_UNIT, "vg_size",
1029 79b2ca83 Michael Hanselmann
             "Total disk space in volume group used for instance disk"
1030 79b2ca83 Michael Hanselmann
             " allocation"),
1031 79b2ca83 Michael Hanselmann
  "mfree": ("MFree", QFT_UNIT, "memory_free",
1032 79b2ca83 Michael Hanselmann
            "Memory available for instance allocations"),
1033 79b2ca83 Michael Hanselmann
  "mnode": ("MNode", QFT_UNIT, "memory_dom0",
1034 79b2ca83 Michael Hanselmann
            "Amount of memory used by node (dom0 for Xen)"),
1035 79b2ca83 Michael Hanselmann
  "mtotal": ("MTotal", QFT_UNIT, "memory_total",
1036 79b2ca83 Michael Hanselmann
             "Total amount of memory of physical machine"),
1037 8235fe04 Michael Hanselmann
  }
1038 8235fe04 Michael Hanselmann
1039 8235fe04 Michael Hanselmann
1040 8572f1fe René Nussbaumer
def _GetGroup(cb):
1041 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
1042 8572f1fe René Nussbaumer

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

1045 8572f1fe René Nussbaumer
  """
1046 8572f1fe René Nussbaumer
  def fn(ctx, node):
1047 8572f1fe René Nussbaumer
    """Get group data for a node.
1048 8572f1fe René Nussbaumer

1049 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1050 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1051 8572f1fe René Nussbaumer
    @param inst: Node object
1052 8572f1fe René Nussbaumer

1053 8572f1fe René Nussbaumer
    """
1054 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1055 8572f1fe René Nussbaumer
    if ng is None:
1056 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1057 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1058 8572f1fe René Nussbaumer
1059 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1060 8572f1fe René Nussbaumer
1061 8572f1fe René Nussbaumer
  return fn
1062 8572f1fe René Nussbaumer
1063 8572f1fe René Nussbaumer
1064 8572f1fe René Nussbaumer
def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613
1065 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1066 8235fe04 Michael Hanselmann

1067 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1068 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1069 8235fe04 Michael Hanselmann
  @param node: Node object
1070 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1071 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1072 8235fe04 Michael Hanselmann

1073 8235fe04 Michael Hanselmann
  """
1074 e2d188cc Iustin Pop
  return ng.name
1075 8235fe04 Michael Hanselmann
1076 8235fe04 Michael Hanselmann
1077 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1078 52b5d286 René Nussbaumer
  """Returns the node powered state
1079 52b5d286 René Nussbaumer

1080 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1081 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1082 52b5d286 René Nussbaumer
  @param node: Node object
1083 52b5d286 René Nussbaumer

1084 52b5d286 René Nussbaumer
  """
1085 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1086 e2d188cc Iustin Pop
    return node.powered
1087 52b5d286 René Nussbaumer
1088 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1089 52b5d286 René Nussbaumer
1090 52b5d286 René Nussbaumer
1091 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1092 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1093 8572f1fe René Nussbaumer

1094 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1095 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1096 8572f1fe René Nussbaumer
  @param node: Node object
1097 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1098 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1099 8572f1fe René Nussbaumer

1100 8572f1fe René Nussbaumer
  """
1101 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1102 8572f1fe René Nussbaumer
1103 8572f1fe René Nussbaumer
1104 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1105 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1106 8235fe04 Michael Hanselmann

1107 8235fe04 Michael Hanselmann
  @param field: Live field name
1108 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1109 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1110 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1111 a6070ef7 Michael Hanselmann
  @param node: Node object
1112 8235fe04 Michael Hanselmann

1113 8235fe04 Michael Hanselmann
  """
1114 a6070ef7 Michael Hanselmann
  if node.offline:
1115 e2d188cc Iustin Pop
    return _FS_OFFLINE
1116 a6070ef7 Michael Hanselmann
1117 effab4ca Iustin Pop
  if not node.vm_capable:
1118 effab4ca Iustin Pop
    return _FS_UNAVAIL
1119 effab4ca Iustin Pop
1120 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1121 e2d188cc Iustin Pop
    return _FS_NODATA
1122 8235fe04 Michael Hanselmann
1123 8235fe04 Michael Hanselmann
  try:
1124 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1125 8235fe04 Michael Hanselmann
  except KeyError:
1126 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1127 8235fe04 Michael Hanselmann
1128 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1129 e2d188cc Iustin Pop
    return value
1130 8235fe04 Michael Hanselmann
1131 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1132 8235fe04 Michael Hanselmann
1133 8235fe04 Michael Hanselmann
  # Try to convert into number
1134 8235fe04 Michael Hanselmann
  try:
1135 e2d188cc Iustin Pop
    return int(value)
1136 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1137 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1138 8235fe04 Michael Hanselmann
                      value, field)
1139 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1140 8235fe04 Michael Hanselmann
1141 8235fe04 Michael Hanselmann
1142 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1143 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1144 8235fe04 Michael Hanselmann

1145 8235fe04 Michael Hanselmann
  """
1146 8235fe04 Michael Hanselmann
  fields = [
1147 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1148 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1149 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1150 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1151 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1152 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1153 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1154 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, lambda ctx, node: node.name == ctx.master_name),
1155 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1156 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1157 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1158 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1159 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1160 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1161 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1162 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1163 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1164 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1165 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1166 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1167 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1168 8235fe04 Michael Hanselmann
    ]
1169 8235fe04 Michael Hanselmann
1170 79b2ca83 Michael Hanselmann
  # Node role
1171 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1172 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1173 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1174 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1175 79b2ca83 Michael Hanselmann
              " \"%s\" for regular, \"%s\" for a drained, \"%s\" for offline" %
1176 79b2ca83 Michael Hanselmann
              role_values)
1177 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1178 79b2ca83 Michael Hanselmann
                 lambda ctx, node: _GetNodeRole(node, ctx.master_name)))
1179 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1180 79b2ca83 Michael Hanselmann
1181 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1182 e2d188cc Iustin Pop
    return lambda ctx, node: len(getter(ctx)[node.name])
1183 8235fe04 Michael Hanselmann
1184 8235fe04 Michael Hanselmann
  def _GetList(getter):
1185 e2d188cc Iustin Pop
    return lambda ctx, node: list(getter(ctx)[node.name])
1186 8235fe04 Michael Hanselmann
1187 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1188 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1189 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1190 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1191 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1192 8235fe04 Michael Hanselmann
    fields.extend([
1193 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1194 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1195 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1196 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1197 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1198 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1199 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1200 8235fe04 Michael Hanselmann
      ])
1201 8235fe04 Michael Hanselmann
1202 8235fe04 Michael Hanselmann
  # Add simple fields
1203 111bf531 Michael Hanselmann
  fields.extend([
1204 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1205 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()
1206 111bf531 Michael Hanselmann
    ])
1207 8235fe04 Michael Hanselmann
1208 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1209 8235fe04 Michael Hanselmann
  fields.extend([
1210 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1211 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1212 79b2ca83 Michael Hanselmann
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()
1213 8235fe04 Michael Hanselmann
    ])
1214 8235fe04 Michael Hanselmann
1215 145bea54 Michael Hanselmann
  # Add timestamps
1216 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1217 145bea54 Michael Hanselmann
1218 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1219 8235fe04 Michael Hanselmann
1220 8235fe04 Michael Hanselmann
1221 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1222 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1223 1c8addc6 Michael Hanselmann

1224 1c8addc6 Michael Hanselmann
  """
1225 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1226 5d28cb6f Michael Hanselmann
               live_data, wrongnode_inst, console):
1227 1c8addc6 Michael Hanselmann
    """Initializes this class.
1228 1c8addc6 Michael Hanselmann

1229 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1230 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1231 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1232 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1233 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1234 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1235 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1236 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1237 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1238 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1239 e431074f René Nussbaumer
    @type wrongnode_inst: set
1240 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1241 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1242 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1243 1c8addc6 Michael Hanselmann

1244 1c8addc6 Michael Hanselmann
    """
1245 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1246 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1247 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1248 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1249 1c8addc6 Michael Hanselmann
1250 1c8addc6 Michael Hanselmann
    self.instances = instances
1251 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1252 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1253 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1254 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1255 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1256 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1257 5d28cb6f Michael Hanselmann
    self.console = console
1258 1c8addc6 Michael Hanselmann
1259 1c8addc6 Michael Hanselmann
    # Used for individual rows
1260 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1261 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1262 7c670076 Michael Hanselmann
    self.inst_osparams = None
1263 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1264 1c8addc6 Michael Hanselmann
1265 1c8addc6 Michael Hanselmann
  def __iter__(self):
1266 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1267 1c8addc6 Michael Hanselmann

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

1271 1c8addc6 Michael Hanselmann
    """
1272 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1273 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1274 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1275 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1276 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1277 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1278 1c8addc6 Michael Hanselmann
1279 1c8addc6 Michael Hanselmann
      yield inst
1280 1c8addc6 Michael Hanselmann
1281 1c8addc6 Michael Hanselmann
1282 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1283 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1284 1c8addc6 Michael Hanselmann

1285 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1286 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1287 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1288 1c8addc6 Michael Hanselmann

1289 1c8addc6 Michael Hanselmann
  """
1290 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1291 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1292 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1293 e2d188cc Iustin Pop
    return _FS_NODATA
1294 1c8addc6 Michael Hanselmann
  else:
1295 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1296 1c8addc6 Michael Hanselmann
1297 1c8addc6 Michael Hanselmann
1298 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1299 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1300 1c8addc6 Michael Hanselmann

1301 1c8addc6 Michael Hanselmann
  @type name: string
1302 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1303 1c8addc6 Michael Hanselmann

1304 1c8addc6 Michael Hanselmann
  """
1305 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1306 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1307 1c8addc6 Michael Hanselmann

1308 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1309 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1310 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1311 1c8addc6 Michael Hanselmann

1312 1c8addc6 Michael Hanselmann
    """
1313 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1314 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1315 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1316 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1317 e2d188cc Iustin Pop
      return _FS_NODATA
1318 1c8addc6 Michael Hanselmann
1319 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1320 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1321 1c8addc6 Michael Hanselmann
      if name in data:
1322 e2d188cc Iustin Pop
        return data[name]
1323 1c8addc6 Michael Hanselmann
1324 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1325 1c8addc6 Michael Hanselmann
1326 1c8addc6 Michael Hanselmann
  return fn
1327 1c8addc6 Michael Hanselmann
1328 1c8addc6 Michael Hanselmann
1329 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1330 1c8addc6 Michael Hanselmann
  """Get instance status.
1331 1c8addc6 Michael Hanselmann

1332 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1333 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1334 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1335 1c8addc6 Michael Hanselmann

1336 1c8addc6 Michael Hanselmann
  """
1337 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1338 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1339 1c8addc6 Michael Hanselmann
1340 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1341 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1342 1c8addc6 Michael Hanselmann
1343 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1344 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1345 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1346 e431074f René Nussbaumer
    elif inst.admin_up:
1347 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1348 1c8addc6 Michael Hanselmann
    else:
1349 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1350 1c8addc6 Michael Hanselmann
1351 1c8addc6 Michael Hanselmann
  if inst.admin_up:
1352 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1353 1c8addc6 Michael Hanselmann
1354 61a980a9 Michael Hanselmann
  return constants.INSTST_ADMINDOWN
1355 1c8addc6 Michael Hanselmann
1356 1c8addc6 Michael Hanselmann
1357 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1358 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1359 1c8addc6 Michael Hanselmann

1360 1c8addc6 Michael Hanselmann
  @type index: int
1361 1c8addc6 Michael Hanselmann
  @param index: Disk index
1362 1c8addc6 Michael Hanselmann

1363 1c8addc6 Michael Hanselmann
  """
1364 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1365 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1366 1c8addc6 Michael Hanselmann

1367 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1368 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1369 1c8addc6 Michael Hanselmann

1370 1c8addc6 Michael Hanselmann
    """
1371 1c8addc6 Michael Hanselmann
    try:
1372 e2d188cc Iustin Pop
      return inst.disks[index].size
1373 1c8addc6 Michael Hanselmann
    except IndexError:
1374 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1375 1c8addc6 Michael Hanselmann
1376 1c8addc6 Michael Hanselmann
  return fn
1377 1c8addc6 Michael Hanselmann
1378 1c8addc6 Michael Hanselmann
1379 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1380 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1381 1c8addc6 Michael Hanselmann

1382 1c8addc6 Michael Hanselmann
  @type index: int
1383 1c8addc6 Michael Hanselmann
  @param index: NIC index
1384 1c8addc6 Michael Hanselmann
  @type cb: callable
1385 1c8addc6 Michael Hanselmann
  @param cb: Callback
1386 1c8addc6 Michael Hanselmann

1387 1c8addc6 Michael Hanselmann
  """
1388 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1389 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1390 1c8addc6 Michael Hanselmann

1391 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1392 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1393 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1394 1c8addc6 Michael Hanselmann

1395 1c8addc6 Michael Hanselmann
    """
1396 1c8addc6 Michael Hanselmann
    try:
1397 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1398 1c8addc6 Michael Hanselmann
    except IndexError:
1399 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1400 1c8addc6 Michael Hanselmann
1401 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1402 1c8addc6 Michael Hanselmann
1403 1c8addc6 Michael Hanselmann
  return fn
1404 1c8addc6 Michael Hanselmann
1405 1c8addc6 Michael Hanselmann
1406 1c8addc6 Michael Hanselmann
def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613
1407 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1408 1c8addc6 Michael Hanselmann

1409 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1410 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1411 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1412 1c8addc6 Michael Hanselmann

1413 1c8addc6 Michael Hanselmann
  """
1414 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1415 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1416 1c8addc6 Michael Hanselmann
  else:
1417 e2d188cc Iustin Pop
    return nic.ip
1418 1c8addc6 Michael Hanselmann
1419 1c8addc6 Michael Hanselmann
1420 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1421 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1422 1c8addc6 Michael Hanselmann

1423 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1424 1c8addc6 Michael Hanselmann
  @type index: int
1425 1c8addc6 Michael Hanselmann
  @param index: NIC index
1426 1c8addc6 Michael Hanselmann

1427 1c8addc6 Michael Hanselmann
  """
1428 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1429 1c8addc6 Michael Hanselmann
1430 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1431 1c8addc6 Michael Hanselmann
1432 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1433 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1434 1c8addc6 Michael Hanselmann
  else:
1435 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1436 1c8addc6 Michael Hanselmann
1437 1c8addc6 Michael Hanselmann
1438 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1439 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1440 1c8addc6 Michael Hanselmann

1441 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1442 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1443 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1444 1c8addc6 Michael Hanselmann

1445 1c8addc6 Michael Hanselmann
  """
1446 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1447 1c8addc6 Michael Hanselmann
1448 1c8addc6 Michael Hanselmann
  result = []
1449 1c8addc6 Michael Hanselmann
1450 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1451 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1452 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1453 1c8addc6 Michael Hanselmann
    else:
1454 1c8addc6 Michael Hanselmann
      result.append(None)
1455 1c8addc6 Michael Hanselmann
1456 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1457 1c8addc6 Michael Hanselmann
1458 e2d188cc Iustin Pop
  return result
1459 1c8addc6 Michael Hanselmann
1460 1c8addc6 Michael Hanselmann
1461 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1462 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1463 1c8addc6 Michael Hanselmann

1464 1c8addc6 Michael Hanselmann
  @type name: string
1465 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1466 1c8addc6 Michael Hanselmann

1467 1c8addc6 Michael Hanselmann
  """
1468 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1469 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1470 1c8addc6 Michael Hanselmann

1471 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1472 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1473 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1474 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1475 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1476 1c8addc6 Michael Hanselmann

1477 1c8addc6 Michael Hanselmann
    """
1478 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1479 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1480 1c8addc6 Michael Hanselmann
1481 1c8addc6 Michael Hanselmann
  return fn
1482 1c8addc6 Michael Hanselmann
1483 1c8addc6 Michael Hanselmann
1484 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1485 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1486 1c8addc6 Michael Hanselmann

1487 4cc4d1fa Michael Hanselmann
  @return: Tuple containing list of field definitions used as input for
1488 4cc4d1fa Michael Hanselmann
    L{_PrepareFieldList} and a list of aliases
1489 1c8addc6 Michael Hanselmann

1490 1c8addc6 Michael Hanselmann
  """
1491 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1492 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1493 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1494 1c8addc6 Michael Hanselmann
1495 1c8addc6 Michael Hanselmann
  fields = [
1496 1c8addc6 Michael Hanselmann
    # All NICs
1497 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1498 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1499 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1500 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1501 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1502 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1503 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1504 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1505 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1506 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1507 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1508 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1509 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1510 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1511 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1512 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1513 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1514 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1515 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1516 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1517 1c8addc6 Michael Hanselmann
    ]
1518 1c8addc6 Michael Hanselmann
1519 1c8addc6 Michael Hanselmann
  # NICs by number
1520 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1521 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1522 1c8addc6 Michael Hanselmann
    fields.extend([
1523 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1524 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1525 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1526 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1527 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1528 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1529 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1530 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1531 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1532 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1533 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1534 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1535 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1536 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1537 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1538 1c8addc6 Michael Hanselmann
      ])
1539 1c8addc6 Michael Hanselmann
1540 4cc4d1fa Michael Hanselmann
  aliases = [
1541 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1542 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1543 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1544 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1545 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1546 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1547 4cc4d1fa Michael Hanselmann
    ]
1548 4cc4d1fa Michael Hanselmann
1549 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1550 1c8addc6 Michael Hanselmann
1551 1c8addc6 Michael Hanselmann
1552 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1553 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1554 1c8addc6 Michael Hanselmann

1555 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1556 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1557 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1558 1c8addc6 Michael Hanselmann

1559 1c8addc6 Michael Hanselmann
  """
1560 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1561 1c8addc6 Michael Hanselmann
1562 1c8addc6 Michael Hanselmann
  if usage is None:
1563 1c8addc6 Michael Hanselmann
    usage = 0
1564 1c8addc6 Michael Hanselmann
1565 e2d188cc Iustin Pop
  return usage
1566 1c8addc6 Michael Hanselmann
1567 1c8addc6 Michael Hanselmann
1568 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1569 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1570 5d28cb6f Michael Hanselmann

1571 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1572 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1573 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1574 5d28cb6f Michael Hanselmann

1575 5d28cb6f Michael Hanselmann
  """
1576 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1577 5d28cb6f Michael Hanselmann
1578 5d28cb6f Michael Hanselmann
  if consinfo is None:
1579 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1580 5d28cb6f Michael Hanselmann
1581 5d28cb6f Michael Hanselmann
  return consinfo
1582 5d28cb6f Michael Hanselmann
1583 5d28cb6f Michael Hanselmann
1584 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1585 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1586 1c8addc6 Michael Hanselmann

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

1589 1c8addc6 Michael Hanselmann
  """
1590 1c8addc6 Michael Hanselmann
  fields = [
1591 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1592 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1593 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1594 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1595 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1596 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1597 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1598 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1599 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1600 1c8addc6 Michael Hanselmann
    ]
1601 1c8addc6 Michael Hanselmann
1602 1c8addc6 Michael Hanselmann
  # Disks by number
1603 1c8addc6 Michael Hanselmann
  fields.extend([
1604 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1605 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1606 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1607 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1608 1c8addc6 Michael Hanselmann
    ])
1609 1c8addc6 Michael Hanselmann
1610 1c8addc6 Michael Hanselmann
  return fields
1611 1c8addc6 Michael Hanselmann
1612 1c8addc6 Michael Hanselmann
1613 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1614 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1615 1c8addc6 Michael Hanselmann

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

1618 1c8addc6 Michael Hanselmann
  """
1619 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1620 1c8addc6 Michael Hanselmann
  be_title = {
1621 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1622 0ca7e384 Iustin Pop
    constants.BE_MEMORY: "ConfigMemory",
1623 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1624 1c8addc6 Michael Hanselmann
    }
1625 1c8addc6 Michael Hanselmann
1626 1c8addc6 Michael Hanselmann
  hv_title = {
1627 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1628 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1629 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1630 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1631 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1632 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1633 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1634 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1635 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1636 1c8addc6 Michael Hanselmann
    }
1637 1c8addc6 Michael Hanselmann
1638 1c8addc6 Michael Hanselmann
  fields = [
1639 1c8addc6 Michael Hanselmann
    # Filled parameters
1640 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1641 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1642 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1643 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1644 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1645 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1646 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1647 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1648 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1649 1c8addc6 Michael Hanselmann
1650 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1651 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1652 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1653 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1654 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1655 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1656 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1657 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1658 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1659 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1660 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1661 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1662 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1663 1c8addc6 Michael Hanselmann
    ]
1664 1c8addc6 Michael Hanselmann
1665 1c8addc6 Michael Hanselmann
  # HV params
1666 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1667 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1668 1c8addc6 Michael Hanselmann
1669 1c8addc6 Michael Hanselmann
  fields.extend([
1670 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1671 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1672 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1673 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1674 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1675 1c8addc6 Michael Hanselmann
    ])
1676 1c8addc6 Michael Hanselmann
1677 1c8addc6 Michael Hanselmann
  # BE params
1678 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1679 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1680 1c8addc6 Michael Hanselmann
1681 1c8addc6 Michael Hanselmann
  fields.extend([
1682 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1683 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1684 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1685 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1686 1c8addc6 Michael Hanselmann
    ])
1687 1c8addc6 Michael Hanselmann
1688 1c8addc6 Michael Hanselmann
  return fields
1689 1c8addc6 Michael Hanselmann
1690 1c8addc6 Michael Hanselmann
1691 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1692 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1693 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1694 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1695 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1696 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1697 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1698 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1699 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1700 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1701 1c8addc6 Michael Hanselmann
  }
1702 1c8addc6 Michael Hanselmann
1703 1c8addc6 Michael Hanselmann
1704 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1705 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1706 1c8addc6 Michael Hanselmann

1707 1c8addc6 Michael Hanselmann
  """
1708 1c8addc6 Michael Hanselmann
  fields = [
1709 111bf531 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", QFT_TEXT, "Primary node"),
1710 111bf531 Michael Hanselmann
     IQ_CONFIG, QFF_HOSTNAME, _GetItemAttr("primary_node")),
1711 111bf531 Michael Hanselmann
    # TODO: Allow filtering by secondary node as hostname
1712 79b2ca83 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER,
1713 79b2ca83 Michael Hanselmann
                "Secondary nodes; usually this will just be one node"),
1714 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: list(inst.secondary_nodes)),
1715 79b2ca83 Michael Hanselmann
    (_MakeField("admin_state", "Autostart", QFT_BOOL,
1716 79b2ca83 Michael Hanselmann
                "Desired state of instance (if set, the instance should be"
1717 79b2ca83 Michael Hanselmann
                " up)"),
1718 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("admin_up")),
1719 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
1720 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
1721 79b2ca83 Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER,
1722 111bf531 Michael Hanselmann
                "Instance console information"), IQ_CONSOLE, 0,
1723 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
1724 1c8addc6 Michael Hanselmann
    ]
1725 1c8addc6 Michael Hanselmann
1726 1c8addc6 Michael Hanselmann
  # Add simple fields
1727 111bf531 Michael Hanselmann
  fields.extend([
1728 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
1729 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()
1730 111bf531 Michael Hanselmann
    ])
1731 1c8addc6 Michael Hanselmann
1732 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1733 1c8addc6 Michael Hanselmann
  fields.extend([
1734 79b2ca83 Michael Hanselmann
    (_MakeField("oper_state", "Running", QFT_BOOL, "Actual state of instance"),
1735 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstOperState),
1736 79b2ca83 Michael Hanselmann
    (_MakeField("oper_ram", "Memory", QFT_UNIT,
1737 79b2ca83 Michael Hanselmann
                "Actual memory usage as seen by hypervisor"),
1738 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("memory")),
1739 79b2ca83 Michael Hanselmann
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER,
1740 79b2ca83 Michael Hanselmann
                "Actual number of VCPUs as seen by hypervisor"),
1741 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("vcpus")),
1742 1c8addc6 Michael Hanselmann
    ])
1743 1c8addc6 Michael Hanselmann
1744 79b2ca83 Michael Hanselmann
  # Status field
1745 79b2ca83 Michael Hanselmann
  status_values = (constants.INSTST_RUNNING, constants.INSTST_ADMINDOWN,
1746 79b2ca83 Michael Hanselmann
                   constants.INSTST_WRONGNODE, constants.INSTST_ERRORUP,
1747 79b2ca83 Michael Hanselmann
                   constants.INSTST_ERRORDOWN, constants.INSTST_NODEDOWN,
1748 79b2ca83 Michael Hanselmann
                   constants.INSTST_NODEOFFLINE)
1749 79b2ca83 Michael Hanselmann
  status_doc = ("Instance status; \"%s\" if instance is set to be running"
1750 79b2ca83 Michael Hanselmann
                " and actually is, \"%s\" if instance is stopped and"
1751 79b2ca83 Michael Hanselmann
                " is not running, \"%s\" if instance running, but not on its"
1752 79b2ca83 Michael Hanselmann
                " designated primary node, \"%s\" if instance should be"
1753 79b2ca83 Michael Hanselmann
                " stopped, but is actually running, \"%s\" if instance should"
1754 79b2ca83 Michael Hanselmann
                " run, but doesn't, \"%s\" if instance's primary node is down,"
1755 79b2ca83 Michael Hanselmann
                " \"%s\" if instance's primary node is marked offline" %
1756 79b2ca83 Michael Hanselmann
                status_values)
1757 79b2ca83 Michael Hanselmann
  fields.append((_MakeField("status", "Status", QFT_TEXT, status_doc),
1758 111bf531 Michael Hanselmann
                 IQ_LIVE, 0, _GetInstStatus))
1759 79b2ca83 Michael Hanselmann
  assert set(status_values) == constants.INSTST_ALL, \
1760 79b2ca83 Michael Hanselmann
         "Status documentation mismatch"
1761 79b2ca83 Michael Hanselmann
1762 4cc4d1fa Michael Hanselmann
  (network_fields, network_aliases) = _GetInstanceNetworkFields()
1763 4cc4d1fa Michael Hanselmann
1764 4cc4d1fa Michael Hanselmann
  fields.extend(network_fields)
1765 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1766 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1767 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1768 1c8addc6 Michael Hanselmann
1769 e7e8037b Iustin Pop
  aliases = [
1770 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
1771 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
1772 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
1773 4cc4d1fa Michael Hanselmann
    ] + network_aliases
1774 e7e8037b Iustin Pop
1775 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
1776 1c8addc6 Michael Hanselmann
1777 1c8addc6 Michael Hanselmann
1778 24d16f76 Michael Hanselmann
class LockQueryData:
1779 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1780 24d16f76 Michael Hanselmann

1781 24d16f76 Michael Hanselmann
  """
1782 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1783 24d16f76 Michael Hanselmann
    """Initializes this class.
1784 24d16f76 Michael Hanselmann

1785 24d16f76 Michael Hanselmann
    """
1786 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1787 24d16f76 Michael Hanselmann
1788 24d16f76 Michael Hanselmann
  def __iter__(self):
1789 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1790 24d16f76 Michael Hanselmann

1791 24d16f76 Michael Hanselmann
    """
1792 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1793 24d16f76 Michael Hanselmann
1794 24d16f76 Michael Hanselmann
1795 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1796 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1797 24d16f76 Michael Hanselmann

1798 24d16f76 Michael Hanselmann
  """
1799 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1800 24d16f76 Michael Hanselmann
1801 24d16f76 Michael Hanselmann
  if owners:
1802 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1803 24d16f76 Michael Hanselmann
1804 e2d188cc Iustin Pop
  return owners
1805 24d16f76 Michael Hanselmann
1806 24d16f76 Michael Hanselmann
1807 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1808 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1809 24d16f76 Michael Hanselmann

1810 24d16f76 Michael Hanselmann
  """
1811 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1812 24d16f76 Michael Hanselmann
1813 24d16f76 Michael Hanselmann
  if pending:
1814 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1815 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1816 24d16f76 Michael Hanselmann
1817 e2d188cc Iustin Pop
  return pending
1818 24d16f76 Michael Hanselmann
1819 24d16f76 Michael Hanselmann
1820 24d16f76 Michael Hanselmann
def _BuildLockFields():
1821 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1822 24d16f76 Michael Hanselmann

1823 24d16f76 Michael Hanselmann
  """
1824 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1825 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
1826 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
1827 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1828 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
1829 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
1830 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
1831 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
1832 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
1833 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
1834 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
1835 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
1836 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
1837 d63bd540 Iustin Pop
    ], [])
1838 24d16f76 Michael Hanselmann
1839 24d16f76 Michael Hanselmann
1840 8e21cfc0 Adeodato Simo
class GroupQueryData:
1841 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1842 8e21cfc0 Adeodato Simo

1843 8e21cfc0 Adeodato Simo
  """
1844 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1845 8e21cfc0 Adeodato Simo
    """Initializes this class.
1846 8e21cfc0 Adeodato Simo

1847 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1848 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1849 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1850 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1851 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1852 8e21cfc0 Adeodato Simo

1853 8e21cfc0 Adeodato Simo
    """
1854 8e21cfc0 Adeodato Simo
    self.groups = groups
1855 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1856 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1857 8e21cfc0 Adeodato Simo
1858 8e21cfc0 Adeodato Simo
  def __iter__(self):
1859 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1860 8e21cfc0 Adeodato Simo

1861 8e21cfc0 Adeodato Simo
    """
1862 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1863 8e21cfc0 Adeodato Simo
1864 8e21cfc0 Adeodato Simo
1865 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1866 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
1867 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
1868 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
1869 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
1870 79b2ca83 Michael Hanselmann
  "ndparams": ("NDParams", QFT_OTHER, "Node parameters"),
1871 8e21cfc0 Adeodato Simo
  }
1872 8e21cfc0 Adeodato Simo
1873 8e21cfc0 Adeodato Simo
1874 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1875 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1876 8e21cfc0 Adeodato Simo

1877 8e21cfc0 Adeodato Simo
  """
1878 8e21cfc0 Adeodato Simo
  # Add simple fields
1879 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
1880 111bf531 Michael Hanselmann
             _GetItemAttr(name))
1881 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
1882 8e21cfc0 Adeodato Simo
1883 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1884 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
1885 8e21cfc0 Adeodato Simo
1886 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1887 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
1888 8e21cfc0 Adeodato Simo
1889 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1890 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1891 8e21cfc0 Adeodato Simo
1892 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1893 8e21cfc0 Adeodato Simo
  fields.extend([
1894 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
1895 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
1896 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
1897 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
1898 8e21cfc0 Adeodato Simo
    ])
1899 8e21cfc0 Adeodato Simo
1900 8e21cfc0 Adeodato Simo
  # Add fields for instances
1901 8e21cfc0 Adeodato Simo
  fields.extend([
1902 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
1903 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
1904 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
1905 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
1906 79b2ca83 Michael Hanselmann
                "List of primary instances"),
1907 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
1908 8e21cfc0 Adeodato Simo
    ])
1909 8e21cfc0 Adeodato Simo
1910 1ffd2673 Michael Hanselmann
  # Other fields
1911 1ffd2673 Michael Hanselmann
  fields.extend([
1912 1ffd2673 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
1913 1ffd2673 Michael Hanselmann
     lambda ctx, group: list(group.GetTags())),
1914 1ffd2673 Michael Hanselmann
    ])
1915 1ffd2673 Michael Hanselmann
1916 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1917 8e21cfc0 Adeodato Simo
1918 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1919 8e21cfc0 Adeodato Simo
1920 8e21cfc0 Adeodato Simo
1921 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
1922 be3a4b14 Michael Hanselmann
  __slots__ = [
1923 be3a4b14 Michael Hanselmann
    "name",
1924 be3a4b14 Michael Hanselmann
    "valid",
1925 be3a4b14 Michael Hanselmann
    "hidden",
1926 be3a4b14 Michael Hanselmann
    "blacklisted",
1927 be3a4b14 Michael Hanselmann
    "variants",
1928 be3a4b14 Michael Hanselmann
    "api_versions",
1929 be3a4b14 Michael Hanselmann
    "parameters",
1930 be3a4b14 Michael Hanselmann
    "node_status",
1931 be3a4b14 Michael Hanselmann
    ]
1932 be3a4b14 Michael Hanselmann
1933 be3a4b14 Michael Hanselmann
1934 be3a4b14 Michael Hanselmann
def _BuildOsFields():
1935 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
1936 be3a4b14 Michael Hanselmann

1937 be3a4b14 Michael Hanselmann
  """
1938 be3a4b14 Michael Hanselmann
  fields = [
1939 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
1940 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
1941 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
1942 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
1943 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
1944 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
1945 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
1946 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
1947 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
1948 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
1949 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
1950 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
1951 be3a4b14 Michael Hanselmann
                "Operating system variants"),
1952 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
1953 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
1954 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
1955 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
1956 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
1957 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
1958 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("parameters"))),
1959 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
1960 be3a4b14 Michael Hanselmann
                "Status from node"),
1961 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
1962 be3a4b14 Michael Hanselmann
    ]
1963 be3a4b14 Michael Hanselmann
1964 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
1965 be3a4b14 Michael Hanselmann
1966 be3a4b14 Michael Hanselmann
1967 8235fe04 Michael Hanselmann
#: Fields available for node queries
1968 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
1969 1c8addc6 Michael Hanselmann
1970 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
1971 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
1972 24d16f76 Michael Hanselmann
1973 24d16f76 Michael Hanselmann
#: Fields available for lock queries
1974 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
1975 e571ee44 Adeodato Simo
1976 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
1977 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
1978 8e21cfc0 Adeodato Simo
1979 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
1980 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
1981 be3a4b14 Michael Hanselmann
1982 95eb4188 Michael Hanselmann
#: All available resources
1983 95eb4188 Michael Hanselmann
ALL_FIELDS = {
1984 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
1985 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
1986 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
1987 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
1988 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
1989 95eb4188 Michael Hanselmann
  }
1990 95eb4188 Michael Hanselmann
1991 e571ee44 Adeodato Simo
#: All available field lists
1992 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()