Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 31554d0a

History | View | Annotate | Download (57 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 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
326 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
327 fb0be379 Michael Hanselmann

328 fb0be379 Michael Hanselmann
  """
329 fb0be379 Michael Hanselmann
  # String statement has no effect, pylint: disable-msg=W0105
330 fb0be379 Michael Hanselmann
331 fb0be379 Michael Hanselmann
  #: How deep filters can be nested
332 fb0be379 Michael Hanselmann
  _LEVELS_MAX = 10
333 fb0be379 Michael Hanselmann
334 fb0be379 Michael Hanselmann
  # Unique identifiers for operator groups
335 fb0be379 Michael Hanselmann
  (_OPTYPE_LOGIC,
336 fb0be379 Michael Hanselmann
   _OPTYPE_UNARY,
337 fb0be379 Michael Hanselmann
   _OPTYPE_BINARY) = range(1, 4)
338 fb0be379 Michael Hanselmann
339 fb0be379 Michael Hanselmann
  """Functions for equality checks depending on field flags.
340 fb0be379 Michael Hanselmann

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

345 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
346 fb0be379 Michael Hanselmann
  using binary AND.
347 fb0be379 Michael Hanselmann

348 fb0be379 Michael Hanselmann
  """
349 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
350 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
351 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
352 fb0be379 Michael Hanselmann
                                               case_sensitive=False)),
353 fb0be379 Michael Hanselmann
    (None, operator.eq),
354 fb0be379 Michael Hanselmann
    ]
355 fb0be379 Michael Hanselmann
356 fb0be379 Michael Hanselmann
  """Known operators
357 fb0be379 Michael Hanselmann

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

361 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
362 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
363 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
364 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
365 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
366 fb0be379 Michael Hanselmann

367 fb0be379 Michael Hanselmann
  """
368 fb0be379 Michael Hanselmann
  _OPS = {
369 fb0be379 Michael Hanselmann
    # Logic operators
370 fb0be379 Michael Hanselmann
    qlang.OP_OR: (_OPTYPE_LOGIC, compat.any),
371 fb0be379 Michael Hanselmann
    qlang.OP_AND: (_OPTYPE_LOGIC, compat.all),
372 fb0be379 Michael Hanselmann
373 fb0be379 Michael Hanselmann
    # Unary operators
374 3b877f08 Michael Hanselmann
    qlang.OP_NOT: (_OPTYPE_UNARY, None),
375 3b877f08 Michael Hanselmann
    qlang.OP_TRUE: (_OPTYPE_UNARY, None),
376 fb0be379 Michael Hanselmann
377 fb0be379 Michael Hanselmann
    # Binary operators
378 fb0be379 Michael Hanselmann
    qlang.OP_EQUAL: (_OPTYPE_BINARY, _EQUALITY_CHECKS),
379 fb0be379 Michael Hanselmann
    qlang.OP_NOT_EQUAL:
380 fb0be379 Michael Hanselmann
      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn))
381 fb0be379 Michael Hanselmann
                        for (flags, fn) in _EQUALITY_CHECKS]),
382 fb0be379 Michael Hanselmann
    qlang.OP_GLOB: (_OPTYPE_BINARY, NotImplemented),
383 fb0be379 Michael Hanselmann
    qlang.OP_REGEXP: (_OPTYPE_BINARY, NotImplemented),
384 fb0be379 Michael Hanselmann
    qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
385 fb0be379 Michael Hanselmann
      (None, operator.contains),
386 fb0be379 Michael Hanselmann
      ]),
387 fb0be379 Michael Hanselmann
    }
388 fb0be379 Michael Hanselmann
389 fb0be379 Michael Hanselmann
  def __init__(self, fields):
390 fb0be379 Michael Hanselmann
    """Initializes this class.
391 fb0be379 Michael Hanselmann

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

394 fb0be379 Michael Hanselmann
    """
395 fb0be379 Michael Hanselmann
    self._fields = fields
396 fb0be379 Michael Hanselmann
    self._hints = None
397 fb0be379 Michael Hanselmann
    self._op_handler = None
398 fb0be379 Michael Hanselmann
399 fb0be379 Michael Hanselmann
  def __call__(self, hints, filter_):
400 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
401 fb0be379 Michael Hanselmann

402 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
403 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
404 fb0be379 Michael Hanselmann
    @type filter_: list
405 fb0be379 Michael Hanselmann
    @param filter_: Filter structure
406 fb0be379 Michael Hanselmann
    @rtype: callable
407 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
408 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
409 fb0be379 Michael Hanselmann

410 fb0be379 Michael Hanselmann
    """
411 fb0be379 Michael Hanselmann
    self._op_handler = {
412 fb0be379 Michael Hanselmann
      self._OPTYPE_LOGIC:
413 fb0be379 Michael Hanselmann
        (self._HandleLogicOp, getattr(hints, "NoteLogicOp", None)),
414 fb0be379 Michael Hanselmann
      self._OPTYPE_UNARY:
415 fb0be379 Michael Hanselmann
        (self._HandleUnaryOp, getattr(hints, "NoteUnaryOp", None)),
416 fb0be379 Michael Hanselmann
      self._OPTYPE_BINARY:
417 fb0be379 Michael Hanselmann
        (self._HandleBinaryOp, getattr(hints, "NoteBinaryOp", None)),
418 fb0be379 Michael Hanselmann
      }
419 fb0be379 Michael Hanselmann
420 fb0be379 Michael Hanselmann
    try:
421 fb0be379 Michael Hanselmann
      filter_fn = self._Compile(filter_, 0)
422 fb0be379 Michael Hanselmann
    finally:
423 fb0be379 Michael Hanselmann
      self._op_handler = None
424 fb0be379 Michael Hanselmann
425 fb0be379 Michael Hanselmann
    return filter_fn
426 fb0be379 Michael Hanselmann
427 fb0be379 Michael Hanselmann
  def _Compile(self, filter_, level):
428 fb0be379 Michael Hanselmann
    """Inner function for converting filters.
429 fb0be379 Michael Hanselmann

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

433 fb0be379 Michael Hanselmann
    """
434 fb0be379 Michael Hanselmann
    if not (isinstance(filter_, (list, tuple)) and filter_):
435 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid filter on level %s" % level)
436 fb0be379 Michael Hanselmann
437 fb0be379 Michael Hanselmann
    # Limit recursion
438 fb0be379 Michael Hanselmann
    if level >= self._LEVELS_MAX:
439 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Only up to %s levels are allowed (filter"
440 fb0be379 Michael Hanselmann
                                  " nested too deep)" % self._LEVELS_MAX)
441 fb0be379 Michael Hanselmann
442 fb0be379 Michael Hanselmann
    # Create copy to be modified
443 fb0be379 Michael Hanselmann
    operands = filter_[:]
444 fb0be379 Michael Hanselmann
    op = operands.pop(0)
445 fb0be379 Michael Hanselmann
446 fb0be379 Michael Hanselmann
    try:
447 fb0be379 Michael Hanselmann
      (kind, op_data) = self._OPS[op]
448 fb0be379 Michael Hanselmann
    except KeyError:
449 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unknown operator '%s'" % op)
450 fb0be379 Michael Hanselmann
451 fb0be379 Michael Hanselmann
    (handler, hints_cb) = self._op_handler[kind]
452 fb0be379 Michael Hanselmann
453 fb0be379 Michael Hanselmann
    return handler(hints_cb, level, op, op_data, operands)
454 fb0be379 Michael Hanselmann
455 3b877f08 Michael Hanselmann
  def _LookupField(self, name):
456 3b877f08 Michael Hanselmann
    """Returns a field definition by name.
457 3b877f08 Michael Hanselmann

458 3b877f08 Michael Hanselmann
    """
459 3b877f08 Michael Hanselmann
    try:
460 3b877f08 Michael Hanselmann
      return self._fields[name]
461 3b877f08 Michael Hanselmann
    except KeyError:
462 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
463 3b877f08 Michael Hanselmann
464 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
465 fb0be379 Michael Hanselmann
    """Handles logic operators.
466 fb0be379 Michael Hanselmann

467 fb0be379 Michael Hanselmann
    @type hints_fn: callable
468 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
469 fb0be379 Michael Hanselmann
    @type level: integer
470 fb0be379 Michael Hanselmann
    @param level: Current depth
471 fb0be379 Michael Hanselmann
    @type op: string
472 fb0be379 Michael Hanselmann
    @param op: Operator
473 fb0be379 Michael Hanselmann
    @type op_fn: callable
474 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
475 fb0be379 Michael Hanselmann
    @type operands: list
476 fb0be379 Michael Hanselmann
    @param operands: List of operands
477 fb0be379 Michael Hanselmann

478 fb0be379 Michael Hanselmann
    """
479 fb0be379 Michael Hanselmann
    if hints_fn:
480 fb0be379 Michael Hanselmann
      hints_fn(op)
481 fb0be379 Michael Hanselmann
482 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
483 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
484 fb0be379 Michael Hanselmann
485 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
486 fb0be379 Michael Hanselmann
    """Handles unary operators.
487 fb0be379 Michael Hanselmann

488 fb0be379 Michael Hanselmann
    @type hints_fn: callable
489 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
490 fb0be379 Michael Hanselmann
    @type level: integer
491 fb0be379 Michael Hanselmann
    @param level: Current depth
492 fb0be379 Michael Hanselmann
    @type op: string
493 fb0be379 Michael Hanselmann
    @param op: Operator
494 fb0be379 Michael Hanselmann
    @type op_fn: callable
495 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
496 fb0be379 Michael Hanselmann
    @type operands: list
497 fb0be379 Michael Hanselmann
    @param operands: List of operands
498 fb0be379 Michael Hanselmann

499 fb0be379 Michael Hanselmann
    """
500 3b877f08 Michael Hanselmann
    assert op_fn is None
501 3b877f08 Michael Hanselmann
502 fb0be379 Michael Hanselmann
    if hints_fn:
503 fb0be379 Michael Hanselmann
      hints_fn(op)
504 fb0be379 Michael Hanselmann
505 fb0be379 Michael Hanselmann
    if len(operands) != 1:
506 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unary operator '%s' expects exactly one"
507 fb0be379 Michael Hanselmann
                                  " operand" % op)
508 fb0be379 Michael Hanselmann
509 3b877f08 Michael Hanselmann
    if op == qlang.OP_TRUE:
510 3b877f08 Michael Hanselmann
      (_, _, _, retrieval_fn) = self._LookupField(operands[0])
511 3b877f08 Michael Hanselmann
512 3b877f08 Michael Hanselmann
      op_fn = operator.truth
513 3b877f08 Michael Hanselmann
      arg = retrieval_fn
514 3b877f08 Michael Hanselmann
    elif op == qlang.OP_NOT:
515 3b877f08 Michael Hanselmann
      op_fn = operator.not_
516 3b877f08 Michael Hanselmann
      arg = self._Compile(operands[0], level + 1)
517 3b877f08 Michael Hanselmann
    else:
518 3b877f08 Michael Hanselmann
      raise errors.ProgrammerError("Can't handle operator '%s'" % op)
519 3b877f08 Michael Hanselmann
520 3b877f08 Michael Hanselmann
    return compat.partial(_WrapUnaryOp, op_fn, arg)
521 fb0be379 Michael Hanselmann
522 fb0be379 Michael Hanselmann
  def _HandleBinaryOp(self, hints_fn, level, op, op_data, operands):
523 fb0be379 Michael Hanselmann
    """Handles binary operators.
524 fb0be379 Michael Hanselmann

525 fb0be379 Michael Hanselmann
    @type hints_fn: callable
526 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
527 fb0be379 Michael Hanselmann
    @type level: integer
528 fb0be379 Michael Hanselmann
    @param level: Current depth
529 fb0be379 Michael Hanselmann
    @type op: string
530 fb0be379 Michael Hanselmann
    @param op: Operator
531 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
532 fb0be379 Michael Hanselmann
    @type operands: list
533 fb0be379 Michael Hanselmann
    @param operands: List of operands
534 fb0be379 Michael Hanselmann

535 fb0be379 Michael Hanselmann
    """
536 fb0be379 Michael Hanselmann
    # Unused arguments, pylint: disable-msg=W0613
537 fb0be379 Michael Hanselmann
    try:
538 fb0be379 Michael Hanselmann
      (name, value) = operands
539 fb0be379 Michael Hanselmann
    except (ValueError, TypeError):
540 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid binary operator, expected exactly"
541 fb0be379 Michael Hanselmann
                                  " two operands")
542 fb0be379 Michael Hanselmann
543 3b877f08 Michael Hanselmann
    (fdef, datakind, field_flags, retrieval_fn) = self._LookupField(name)
544 fb0be379 Michael Hanselmann
545 fb0be379 Michael Hanselmann
    assert fdef.kind != QFT_UNKNOWN
546 fb0be379 Michael Hanselmann
547 fb0be379 Michael Hanselmann
    # TODO: Type conversions?
548 fb0be379 Michael Hanselmann
549 fb0be379 Michael Hanselmann
    verify_fn = _VERIFY_FN[fdef.kind]
550 fb0be379 Michael Hanselmann
    if not verify_fn(value):
551 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unable to compare field '%s' (type '%s')"
552 fb0be379 Michael Hanselmann
                                  " with '%s', expected %s" %
553 fb0be379 Michael Hanselmann
                                  (name, fdef.kind, value.__class__.__name__,
554 fb0be379 Michael Hanselmann
                                   verify_fn))
555 fb0be379 Michael Hanselmann
556 fb0be379 Michael Hanselmann
    if hints_fn:
557 fb0be379 Michael Hanselmann
      hints_fn(op, datakind, name, value)
558 fb0be379 Michael Hanselmann
559 fb0be379 Michael Hanselmann
    for (fn_flags, fn) in op_data:
560 fb0be379 Michael Hanselmann
      if fn_flags is None or fn_flags & field_flags:
561 fb0be379 Michael Hanselmann
        return compat.partial(_WrapBinaryOp, fn, retrieval_fn, value)
562 fb0be379 Michael Hanselmann
563 fb0be379 Michael Hanselmann
    raise errors.ProgrammerError("Unable to find operator implementation"
564 fb0be379 Michael Hanselmann
                                 " (op '%s', flags %s)" % (op, field_flags))
565 fb0be379 Michael Hanselmann
566 fb0be379 Michael Hanselmann
567 fb0be379 Michael Hanselmann
def _CompileFilter(fields, hints, filter_):
568 fb0be379 Michael Hanselmann
  """Converts a query filter into a callable function.
569 fb0be379 Michael Hanselmann

570 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
571 fb0be379 Michael Hanselmann

572 fb0be379 Michael Hanselmann
  @rtype: callable
573 fb0be379 Michael Hanselmann

574 fb0be379 Michael Hanselmann
  """
575 fb0be379 Michael Hanselmann
  return _FilterCompilerHelper(fields)(hints, filter_)
576 fb0be379 Michael Hanselmann
577 fb0be379 Michael Hanselmann
578 4ca96421 Michael Hanselmann
class Query:
579 fb0be379 Michael Hanselmann
  def __init__(self, fieldlist, selected, filter_=None, namefield=None):
580 4ca96421 Michael Hanselmann
    """Initializes this class.
581 4ca96421 Michael Hanselmann

582 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
583 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
584 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
585 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
586 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
587 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
588 4ca96421 Michael Hanselmann

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

592 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
593 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
594 4ca96421 Michael Hanselmann
    @type selected: list of strings
595 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
596 4ca96421 Michael Hanselmann

597 4ca96421 Michael Hanselmann
    """
598 fb0be379 Michael Hanselmann
    assert namefield is None or namefield in fieldlist
599 fb0be379 Michael Hanselmann
600 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
601 4ca96421 Michael Hanselmann
602 fb0be379 Michael Hanselmann
    self._filter_fn = None
603 fb0be379 Michael Hanselmann
    self._requested_names = None
604 fb0be379 Michael Hanselmann
    self._filter_datakinds = frozenset()
605 fb0be379 Michael Hanselmann
606 fb0be379 Michael Hanselmann
    if filter_ is not None:
607 fb0be379 Michael Hanselmann
      # Collect requested names if wanted
608 fb0be379 Michael Hanselmann
      if namefield:
609 fb0be379 Michael Hanselmann
        hints = _FilterHints(namefield)
610 fb0be379 Michael Hanselmann
      else:
611 fb0be379 Michael Hanselmann
        hints = None
612 fb0be379 Michael Hanselmann
613 fb0be379 Michael Hanselmann
      # Build filter function
614 fb0be379 Michael Hanselmann
      self._filter_fn = _CompileFilter(fieldlist, hints, filter_)
615 fb0be379 Michael Hanselmann
      if hints:
616 fb0be379 Michael Hanselmann
        self._requested_names = hints.RequestedNames()
617 fb0be379 Michael Hanselmann
        self._filter_datakinds = hints.ReferencedData()
618 fb0be379 Michael Hanselmann
619 fb0be379 Michael Hanselmann
    if namefield is None:
620 fb0be379 Michael Hanselmann
      self._name_fn = None
621 fb0be379 Michael Hanselmann
    else:
622 fb0be379 Michael Hanselmann
      (_, _, _, self._name_fn) = fieldlist[namefield]
623 fb0be379 Michael Hanselmann
624 fb0be379 Michael Hanselmann
  def RequestedNames(self):
625 fb0be379 Michael Hanselmann
    """Returns all names referenced in the filter.
626 fb0be379 Michael Hanselmann

627 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
628 fb0be379 Michael Hanselmann
    names, C{None} is returned.
629 fb0be379 Michael Hanselmann

630 fb0be379 Michael Hanselmann
    """
631 fb0be379 Michael Hanselmann
    return self._requested_names
632 fb0be379 Michael Hanselmann
633 4ca96421 Michael Hanselmann
  def RequestedData(self):
634 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
635 4ca96421 Michael Hanselmann

636 4ca96421 Michael Hanselmann
    @rtype: frozenset
637 4ca96421 Michael Hanselmann

638 4ca96421 Michael Hanselmann
    """
639 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
640 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
641 fb0be379 Michael Hanselmann
                      if datakind is not None))
642 4ca96421 Michael Hanselmann
643 4ca96421 Michael Hanselmann
  def GetFields(self):
644 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
645 4ca96421 Michael Hanselmann

646 4ca96421 Michael Hanselmann
    Includes unknown fields.
647 4ca96421 Michael Hanselmann

648 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
649 4ca96421 Michael Hanselmann

650 4ca96421 Michael Hanselmann
    """
651 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
652 4ca96421 Michael Hanselmann
653 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
654 4ca96421 Michael Hanselmann
    """Execute a query.
655 4ca96421 Michael Hanselmann

656 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
657 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
658 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
659 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
660 fbc263a9 Michael Hanselmann
      ordering
661 4ca96421 Michael Hanselmann

662 4ca96421 Michael Hanselmann
    """
663 fbc263a9 Michael Hanselmann
    sort = (self._name_fn and sort_by_name)
664 fbc263a9 Michael Hanselmann
665 fb0be379 Michael Hanselmann
    result = []
666 fb0be379 Michael Hanselmann
667 fb0be379 Michael Hanselmann
    for idx, item in enumerate(ctx):
668 fb0be379 Michael Hanselmann
      if not (self._filter_fn is None or self._filter_fn(ctx, item)):
669 fb0be379 Michael Hanselmann
        continue
670 4ca96421 Michael Hanselmann
671 fb0be379 Michael Hanselmann
      row = [_ProcessResult(fn(ctx, item)) for (_, _, _, fn) in self._fields]
672 fb0be379 Michael Hanselmann
673 fb0be379 Michael Hanselmann
      # Verify result
674 fb0be379 Michael Hanselmann
      if __debug__:
675 d1c3c3b3 Iustin Pop
        _VerifyResultRow(self._fields, row)
676 4ca96421 Michael Hanselmann
677 fbc263a9 Michael Hanselmann
      if sort:
678 fb0be379 Michael Hanselmann
        (status, name) = _ProcessResult(self._name_fn(ctx, item))
679 fb0be379 Michael Hanselmann
        assert status == constants.RS_NORMAL
680 fb0be379 Michael Hanselmann
        # TODO: Are there cases where we wouldn't want to use NiceSort?
681 fbc263a9 Michael Hanselmann
        result.append((utils.NiceSortKey(name), idx, row))
682 fb0be379 Michael Hanselmann
      else:
683 fbc263a9 Michael Hanselmann
        result.append(row)
684 fb0be379 Michael Hanselmann
685 fbc263a9 Michael Hanselmann
    if not sort:
686 fbc263a9 Michael Hanselmann
      return result
687 fb0be379 Michael Hanselmann
688 fb0be379 Michael Hanselmann
    # TODO: Would "heapq" be more efficient than sorting?
689 fb0be379 Michael Hanselmann
690 fb0be379 Michael Hanselmann
    # Sorting in-place instead of using "sorted()"
691 fb0be379 Michael Hanselmann
    result.sort()
692 fb0be379 Michael Hanselmann
693 fb0be379 Michael Hanselmann
    assert not result or (len(result[0]) == 3 and len(result[-1]) == 3)
694 fb0be379 Michael Hanselmann
695 fb0be379 Michael Hanselmann
    return map(operator.itemgetter(2), result)
696 4ca96421 Michael Hanselmann
697 fbc263a9 Michael Hanselmann
  def OldStyleQuery(self, ctx, sort_by_name=True):
698 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
699 4ca96421 Michael Hanselmann

700 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
701 4ca96421 Michael Hanselmann

702 4ca96421 Michael Hanselmann
    """
703 111bf531 Michael Hanselmann
    unknown = set(fdef.name for (fdef, _, _, _) in self._fields
704 111bf531 Michael Hanselmann
                  if fdef.kind == QFT_UNKNOWN)
705 4ca96421 Michael Hanselmann
    if unknown:
706 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
707 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
708 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
709 4ca96421 Michael Hanselmann
710 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
711 fbc263a9 Michael Hanselmann
            for row in self.Query(ctx, sort_by_name=sort_by_name)]
712 4ca96421 Michael Hanselmann
713 4ca96421 Michael Hanselmann
714 e2d188cc Iustin Pop
def _ProcessResult(value):
715 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
716 e2d188cc Iustin Pop

717 e2d188cc Iustin Pop
  """
718 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
719 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
720 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
721 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
722 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
723 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
724 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
725 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
726 e2d188cc Iustin Pop
  else:
727 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
728 e2d188cc Iustin Pop
729 e2d188cc Iustin Pop
730 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
731 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
732 4ca96421 Michael Hanselmann

733 4ca96421 Michael Hanselmann
  @type fields: list
734 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
735 4ca96421 Michael Hanselmann
  @type row: list of tuples
736 4ca96421 Michael Hanselmann
  @param row: Row data
737 4ca96421 Michael Hanselmann

738 4ca96421 Michael Hanselmann
  """
739 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
740 d1c3c3b3 Iustin Pop
  errs = []
741 111bf531 Michael Hanselmann
  for ((status, value), (fdef, _, _, _)) in zip(row, fields):
742 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
743 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
744 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
745 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
746 d1c3c3b3 Iustin Pop
    elif value is not None:
747 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
748 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
749 d1c3c3b3 Iustin Pop
                    (utils.CommaJoin(errors), row))
750 4ca96421 Michael Hanselmann
751 4ca96421 Michael Hanselmann
752 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
753 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
754 4ca96421 Michael Hanselmann

755 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
756 4ca96421 Michael Hanselmann

757 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
758 d63bd540 Iustin Pop
      kind, retrieval function)
759 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
760 d63bd540 Iustin Pop
      description
761 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
762 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
763 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
764 4ca96421 Michael Hanselmann
  @rtype: dict
765 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
766 4ca96421 Michael Hanselmann

767 4ca96421 Michael Hanselmann
  """
768 89ce4acc Michael Hanselmann
  if __debug__:
769 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
770 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
771 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
772 4ca96421 Michael Hanselmann
773 4ca96421 Michael Hanselmann
  result = {}
774 4ca96421 Michael Hanselmann
775 4ca96421 Michael Hanselmann
  for field in fields:
776 111bf531 Michael Hanselmann
    (fdef, _, flags, fn) = field
777 4ca96421 Michael Hanselmann
778 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
779 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
780 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
781 79b2ca83 Michael Hanselmann
    assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
782 79b2ca83 Michael Hanselmann
            fdef.doc.strip() == fdef.doc), \
783 79b2ca83 Michael Hanselmann
           "Invalid description for field '%s'" % fdef.name
784 4ca96421 Michael Hanselmann
    assert callable(fn)
785 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
786 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
787 111bf531 Michael Hanselmann
    assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
788 4ca96421 Michael Hanselmann
789 4ca96421 Michael Hanselmann
    result[fdef.name] = field
790 4ca96421 Michael Hanselmann
791 d63bd540 Iustin Pop
  for alias, target in aliases:
792 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
793 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
794 111bf531 Michael Hanselmann
    (fdef, k, flags, fn) = result[target]
795 d63bd540 Iustin Pop
    fdef = fdef.Copy()
796 d63bd540 Iustin Pop
    fdef.name = alias
797 111bf531 Michael Hanselmann
    result[alias] = (fdef, k, flags, fn)
798 d63bd540 Iustin Pop
799 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
800 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
801 111bf531 Michael Hanselmann
                    for (name, (fdef, _, _, _)) in result.items())
802 4ca96421 Michael Hanselmann
803 4ca96421 Michael Hanselmann
  return result
804 4ca96421 Michael Hanselmann
805 4ca96421 Michael Hanselmann
806 fbc263a9 Michael Hanselmann
def GetQueryResponse(query, ctx, sort_by_name=True):
807 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
808 b60fcb6f Michael Hanselmann

809 b60fcb6f Michael Hanselmann
  @type query: L{Query}
810 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
811 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
812 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
813 fbc263a9 Michael Hanselmann
    ordering
814 b60fcb6f Michael Hanselmann

815 b60fcb6f Michael Hanselmann
  """
816 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
817 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
818 b60fcb6f Michael Hanselmann
819 b60fcb6f Michael Hanselmann
820 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
821 aa29e95f Michael Hanselmann
  """Returns list of available fields.
822 aa29e95f Michael Hanselmann

823 aa29e95f Michael Hanselmann
  @type fielddefs: dict
824 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
825 aa29e95f Michael Hanselmann
  @type selected: list of strings
826 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
827 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
828 aa29e95f Michael Hanselmann

829 aa29e95f Michael Hanselmann
  """
830 aa29e95f Michael Hanselmann
  if selected is None:
831 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
832 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
833 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
834 aa29e95f Michael Hanselmann
  else:
835 aa29e95f Michael Hanselmann
    # Keep order as requested by client
836 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
837 aa29e95f Michael Hanselmann
838 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
839 aa29e95f Michael Hanselmann
840 aa29e95f Michael Hanselmann
841 79b2ca83 Michael Hanselmann
def _MakeField(name, title, kind, doc):
842 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
843 4ca96421 Michael Hanselmann

844 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
845 4ca96421 Michael Hanselmann
  @param title: Human-readable title
846 4ca96421 Michael Hanselmann
  @param kind: Field type
847 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
848 4ca96421 Michael Hanselmann

849 4ca96421 Michael Hanselmann
  """
850 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
851 1ae17369 Michael Hanselmann
                                      doc=doc)
852 8235fe04 Michael Hanselmann
853 8235fe04 Michael Hanselmann
854 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
855 8235fe04 Michael Hanselmann
  """Determine node role.
856 8235fe04 Michael Hanselmann

857 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
858 8235fe04 Michael Hanselmann
  @param node: Node object
859 8235fe04 Michael Hanselmann
  @type master_name: string
860 8235fe04 Michael Hanselmann
  @param master_name: Master node name
861 8235fe04 Michael Hanselmann

862 8235fe04 Michael Hanselmann
  """
863 8235fe04 Michael Hanselmann
  if node.name == master_name:
864 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
865 8235fe04 Michael Hanselmann
  elif node.master_candidate:
866 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
867 8235fe04 Michael Hanselmann
  elif node.drained:
868 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
869 8235fe04 Michael Hanselmann
  elif node.offline:
870 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
871 8235fe04 Michael Hanselmann
  else:
872 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
873 8235fe04 Michael Hanselmann
874 8235fe04 Michael Hanselmann
875 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
876 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
877 8235fe04 Michael Hanselmann

878 8235fe04 Michael Hanselmann
  @param attr: Attribute name
879 8235fe04 Michael Hanselmann

880 8235fe04 Michael Hanselmann
  """
881 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
882 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
883 8235fe04 Michael Hanselmann
884 8235fe04 Michael Hanselmann
885 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
886 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
887 425e5bf0 Michael Hanselmann

888 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
889 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
890 425e5bf0 Michael Hanselmann

891 425e5bf0 Michael Hanselmann
  """
892 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
893 425e5bf0 Michael Hanselmann
894 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
895 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
896 425e5bf0 Michael Hanselmann
    # Return right away
897 425e5bf0 Michael Hanselmann
    return value
898 425e5bf0 Michael Hanselmann
899 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
900 425e5bf0 Michael Hanselmann
  return convert(value)
901 425e5bf0 Michael Hanselmann
902 425e5bf0 Michael Hanselmann
903 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
904 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
905 425e5bf0 Michael Hanselmann

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

909 425e5bf0 Michael Hanselmann
  """
910 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
911 425e5bf0 Michael Hanselmann
912 425e5bf0 Michael Hanselmann
913 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
914 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
915 145bea54 Michael Hanselmann

916 145bea54 Michael Hanselmann
  @type getter: callable
917 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
918 145bea54 Michael Hanselmann

919 145bea54 Michael Hanselmann
  """
920 145bea54 Michael Hanselmann
  def fn(_, item):
921 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
922 145bea54 Michael Hanselmann

923 145bea54 Michael Hanselmann
    """
924 145bea54 Michael Hanselmann
    timestamp = getter(item)
925 145bea54 Michael Hanselmann
    if timestamp is None:
926 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
927 e2d188cc Iustin Pop
      return _FS_UNAVAIL
928 145bea54 Michael Hanselmann
    else:
929 e2d188cc Iustin Pop
      return timestamp
930 145bea54 Michael Hanselmann
931 145bea54 Michael Hanselmann
  return fn
932 145bea54 Michael Hanselmann
933 145bea54 Michael Hanselmann
934 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
935 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
936 145bea54 Michael Hanselmann

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

939 145bea54 Michael Hanselmann
  """
940 145bea54 Michael Hanselmann
  return [
941 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
942 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
943 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
944 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
945 145bea54 Michael Hanselmann
    ]
946 145bea54 Michael Hanselmann
947 145bea54 Michael Hanselmann
948 8235fe04 Michael Hanselmann
class NodeQueryData:
949 8235fe04 Michael Hanselmann
  """Data container for node data queries.
950 8235fe04 Michael Hanselmann

951 8235fe04 Michael Hanselmann
  """
952 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
953 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
954 8235fe04 Michael Hanselmann
    """Initializes this class.
955 8235fe04 Michael Hanselmann

956 8235fe04 Michael Hanselmann
    """
957 8235fe04 Michael Hanselmann
    self.nodes = nodes
958 8235fe04 Michael Hanselmann
    self.live_data = live_data
959 8235fe04 Michael Hanselmann
    self.master_name = master_name
960 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
961 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
962 8235fe04 Michael Hanselmann
    self.groups = groups
963 52b5d286 René Nussbaumer
    self.oob_support = oob_support
964 8572f1fe René Nussbaumer
    self.cluster = cluster
965 8235fe04 Michael Hanselmann
966 8235fe04 Michael Hanselmann
    # Used for individual rows
967 8235fe04 Michael Hanselmann
    self.curlive_data = None
968 8235fe04 Michael Hanselmann
969 8235fe04 Michael Hanselmann
  def __iter__(self):
970 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
971 8235fe04 Michael Hanselmann

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

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

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

1029 8572f1fe René Nussbaumer
  """
1030 8572f1fe René Nussbaumer
  def fn(ctx, node):
1031 8572f1fe René Nussbaumer
    """Get group data for a node.
1032 8572f1fe René Nussbaumer

1033 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1034 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1035 8572f1fe René Nussbaumer
    @param inst: Node object
1036 8572f1fe René Nussbaumer

1037 8572f1fe René Nussbaumer
    """
1038 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1039 8572f1fe René Nussbaumer
    if ng is None:
1040 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1041 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1042 8572f1fe René Nussbaumer
1043 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1044 8572f1fe René Nussbaumer
1045 8572f1fe René Nussbaumer
  return fn
1046 8572f1fe René Nussbaumer
1047 8572f1fe René Nussbaumer
1048 8572f1fe René Nussbaumer
def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613
1049 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1050 8235fe04 Michael Hanselmann

1051 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1052 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1053 8235fe04 Michael Hanselmann
  @param node: Node object
1054 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1055 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1056 8235fe04 Michael Hanselmann

1057 8235fe04 Michael Hanselmann
  """
1058 e2d188cc Iustin Pop
  return ng.name
1059 8235fe04 Michael Hanselmann
1060 8235fe04 Michael Hanselmann
1061 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1062 52b5d286 René Nussbaumer
  """Returns the node powered state
1063 52b5d286 René Nussbaumer

1064 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1065 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1066 52b5d286 René Nussbaumer
  @param node: Node object
1067 52b5d286 René Nussbaumer

1068 52b5d286 René Nussbaumer
  """
1069 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1070 e2d188cc Iustin Pop
    return node.powered
1071 52b5d286 René Nussbaumer
1072 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1073 52b5d286 René Nussbaumer
1074 52b5d286 René Nussbaumer
1075 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1076 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1077 8572f1fe René Nussbaumer

1078 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1079 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1080 8572f1fe René Nussbaumer
  @param node: Node object
1081 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1082 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1083 8572f1fe René Nussbaumer

1084 8572f1fe René Nussbaumer
  """
1085 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1086 8572f1fe René Nussbaumer
1087 8572f1fe René Nussbaumer
1088 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1089 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1090 8235fe04 Michael Hanselmann

1091 8235fe04 Michael Hanselmann
  @param field: Live field name
1092 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1093 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1094 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1095 a6070ef7 Michael Hanselmann
  @param node: Node object
1096 8235fe04 Michael Hanselmann

1097 8235fe04 Michael Hanselmann
  """
1098 a6070ef7 Michael Hanselmann
  if node.offline:
1099 e2d188cc Iustin Pop
    return _FS_OFFLINE
1100 a6070ef7 Michael Hanselmann
1101 effab4ca Iustin Pop
  if not node.vm_capable:
1102 effab4ca Iustin Pop
    return _FS_UNAVAIL
1103 effab4ca Iustin Pop
1104 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1105 e2d188cc Iustin Pop
    return _FS_NODATA
1106 8235fe04 Michael Hanselmann
1107 8235fe04 Michael Hanselmann
  try:
1108 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1109 8235fe04 Michael Hanselmann
  except KeyError:
1110 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1111 8235fe04 Michael Hanselmann
1112 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1113 e2d188cc Iustin Pop
    return value
1114 8235fe04 Michael Hanselmann
1115 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1116 8235fe04 Michael Hanselmann
1117 8235fe04 Michael Hanselmann
  # Try to convert into number
1118 8235fe04 Michael Hanselmann
  try:
1119 e2d188cc Iustin Pop
    return int(value)
1120 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1121 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1122 8235fe04 Michael Hanselmann
                      value, field)
1123 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1124 8235fe04 Michael Hanselmann
1125 8235fe04 Michael Hanselmann
1126 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1127 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1128 8235fe04 Michael Hanselmann

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

1208 1c8addc6 Michael Hanselmann
  """
1209 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1210 5d28cb6f Michael Hanselmann
               live_data, wrongnode_inst, console):
1211 1c8addc6 Michael Hanselmann
    """Initializes this class.
1212 1c8addc6 Michael Hanselmann

1213 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1214 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1215 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1216 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1217 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1218 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1219 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1220 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1221 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1222 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1223 e431074f René Nussbaumer
    @type wrongnode_inst: set
1224 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1225 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1226 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1227 1c8addc6 Michael Hanselmann

1228 1c8addc6 Michael Hanselmann
    """
1229 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1230 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1231 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1232 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1233 1c8addc6 Michael Hanselmann
1234 1c8addc6 Michael Hanselmann
    self.instances = instances
1235 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1236 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1237 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1238 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1239 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1240 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1241 5d28cb6f Michael Hanselmann
    self.console = console
1242 1c8addc6 Michael Hanselmann
1243 1c8addc6 Michael Hanselmann
    # Used for individual rows
1244 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1245 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1246 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1247 1c8addc6 Michael Hanselmann
1248 1c8addc6 Michael Hanselmann
  def __iter__(self):
1249 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1250 1c8addc6 Michael Hanselmann

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

1254 1c8addc6 Michael Hanselmann
    """
1255 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1256 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1257 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1258 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1259 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1260 1c8addc6 Michael Hanselmann
1261 1c8addc6 Michael Hanselmann
      yield inst
1262 1c8addc6 Michael Hanselmann
1263 1c8addc6 Michael Hanselmann
1264 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1265 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1266 1c8addc6 Michael Hanselmann

1267 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1268 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1269 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1270 1c8addc6 Michael Hanselmann

1271 1c8addc6 Michael Hanselmann
  """
1272 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1273 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1274 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1275 e2d188cc Iustin Pop
    return _FS_NODATA
1276 1c8addc6 Michael Hanselmann
  else:
1277 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1278 1c8addc6 Michael Hanselmann
1279 1c8addc6 Michael Hanselmann
1280 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1281 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1282 1c8addc6 Michael Hanselmann

1283 1c8addc6 Michael Hanselmann
  @type name: string
1284 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1285 1c8addc6 Michael Hanselmann

1286 1c8addc6 Michael Hanselmann
  """
1287 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1288 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1289 1c8addc6 Michael Hanselmann

1290 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1291 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1292 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1293 1c8addc6 Michael Hanselmann

1294 1c8addc6 Michael Hanselmann
    """
1295 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1296 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1297 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1298 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1299 e2d188cc Iustin Pop
      return _FS_NODATA
1300 1c8addc6 Michael Hanselmann
1301 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1302 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1303 1c8addc6 Michael Hanselmann
      if name in data:
1304 e2d188cc Iustin Pop
        return data[name]
1305 1c8addc6 Michael Hanselmann
1306 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1307 1c8addc6 Michael Hanselmann
1308 1c8addc6 Michael Hanselmann
  return fn
1309 1c8addc6 Michael Hanselmann
1310 1c8addc6 Michael Hanselmann
1311 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1312 1c8addc6 Michael Hanselmann
  """Get instance status.
1313 1c8addc6 Michael Hanselmann

1314 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1315 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1316 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1317 1c8addc6 Michael Hanselmann

1318 1c8addc6 Michael Hanselmann
  """
1319 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1320 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1321 1c8addc6 Michael Hanselmann
1322 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1323 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1324 1c8addc6 Michael Hanselmann
1325 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1326 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1327 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1328 e431074f René Nussbaumer
    elif inst.admin_up:
1329 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1330 1c8addc6 Michael Hanselmann
    else:
1331 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1332 1c8addc6 Michael Hanselmann
1333 1c8addc6 Michael Hanselmann
  if inst.admin_up:
1334 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1335 1c8addc6 Michael Hanselmann
1336 61a980a9 Michael Hanselmann
  return constants.INSTST_ADMINDOWN
1337 1c8addc6 Michael Hanselmann
1338 1c8addc6 Michael Hanselmann
1339 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1340 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1341 1c8addc6 Michael Hanselmann

1342 1c8addc6 Michael Hanselmann
  @type index: int
1343 1c8addc6 Michael Hanselmann
  @param index: Disk index
1344 1c8addc6 Michael Hanselmann

1345 1c8addc6 Michael Hanselmann
  """
1346 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1347 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1348 1c8addc6 Michael Hanselmann

1349 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1350 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1351 1c8addc6 Michael Hanselmann

1352 1c8addc6 Michael Hanselmann
    """
1353 1c8addc6 Michael Hanselmann
    try:
1354 e2d188cc Iustin Pop
      return inst.disks[index].size
1355 1c8addc6 Michael Hanselmann
    except IndexError:
1356 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1357 1c8addc6 Michael Hanselmann
1358 1c8addc6 Michael Hanselmann
  return fn
1359 1c8addc6 Michael Hanselmann
1360 1c8addc6 Michael Hanselmann
1361 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1362 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1363 1c8addc6 Michael Hanselmann

1364 1c8addc6 Michael Hanselmann
  @type index: int
1365 1c8addc6 Michael Hanselmann
  @param index: NIC index
1366 1c8addc6 Michael Hanselmann
  @type cb: callable
1367 1c8addc6 Michael Hanselmann
  @param cb: Callback
1368 1c8addc6 Michael Hanselmann

1369 1c8addc6 Michael Hanselmann
  """
1370 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1371 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1372 1c8addc6 Michael Hanselmann

1373 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1374 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1375 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1376 1c8addc6 Michael Hanselmann

1377 1c8addc6 Michael Hanselmann
    """
1378 1c8addc6 Michael Hanselmann
    try:
1379 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1380 1c8addc6 Michael Hanselmann
    except IndexError:
1381 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1382 1c8addc6 Michael Hanselmann
1383 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1384 1c8addc6 Michael Hanselmann
1385 1c8addc6 Michael Hanselmann
  return fn
1386 1c8addc6 Michael Hanselmann
1387 1c8addc6 Michael Hanselmann
1388 1c8addc6 Michael Hanselmann
def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613
1389 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1390 1c8addc6 Michael Hanselmann

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

1395 1c8addc6 Michael Hanselmann
  """
1396 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1397 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1398 1c8addc6 Michael Hanselmann
  else:
1399 e2d188cc Iustin Pop
    return nic.ip
1400 1c8addc6 Michael Hanselmann
1401 1c8addc6 Michael Hanselmann
1402 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1403 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1404 1c8addc6 Michael Hanselmann

1405 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1406 1c8addc6 Michael Hanselmann
  @type index: int
1407 1c8addc6 Michael Hanselmann
  @param index: NIC index
1408 1c8addc6 Michael Hanselmann

1409 1c8addc6 Michael Hanselmann
  """
1410 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1411 1c8addc6 Michael Hanselmann
1412 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1413 1c8addc6 Michael Hanselmann
1414 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1415 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1416 1c8addc6 Michael Hanselmann
  else:
1417 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1418 1c8addc6 Michael Hanselmann
1419 1c8addc6 Michael Hanselmann
1420 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1421 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1422 1c8addc6 Michael Hanselmann

1423 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1424 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1425 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1426 1c8addc6 Michael Hanselmann

1427 1c8addc6 Michael Hanselmann
  """
1428 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1429 1c8addc6 Michael Hanselmann
1430 1c8addc6 Michael Hanselmann
  result = []
1431 1c8addc6 Michael Hanselmann
1432 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1433 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1434 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1435 1c8addc6 Michael Hanselmann
    else:
1436 1c8addc6 Michael Hanselmann
      result.append(None)
1437 1c8addc6 Michael Hanselmann
1438 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1439 1c8addc6 Michael Hanselmann
1440 e2d188cc Iustin Pop
  return result
1441 1c8addc6 Michael Hanselmann
1442 1c8addc6 Michael Hanselmann
1443 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1444 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1445 1c8addc6 Michael Hanselmann

1446 1c8addc6 Michael Hanselmann
  @type name: string
1447 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1448 1c8addc6 Michael Hanselmann

1449 1c8addc6 Michael Hanselmann
  """
1450 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1451 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1452 1c8addc6 Michael Hanselmann

1453 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1454 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1455 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1456 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1457 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1458 1c8addc6 Michael Hanselmann

1459 1c8addc6 Michael Hanselmann
    """
1460 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1461 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1462 1c8addc6 Michael Hanselmann
1463 1c8addc6 Michael Hanselmann
  return fn
1464 1c8addc6 Michael Hanselmann
1465 1c8addc6 Michael Hanselmann
1466 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1467 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1468 1c8addc6 Michael Hanselmann

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

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

1537 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1538 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1539 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1540 1c8addc6 Michael Hanselmann

1541 1c8addc6 Michael Hanselmann
  """
1542 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1543 1c8addc6 Michael Hanselmann
1544 1c8addc6 Michael Hanselmann
  if usage is None:
1545 1c8addc6 Michael Hanselmann
    usage = 0
1546 1c8addc6 Michael Hanselmann
1547 e2d188cc Iustin Pop
  return usage
1548 1c8addc6 Michael Hanselmann
1549 1c8addc6 Michael Hanselmann
1550 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1551 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1552 5d28cb6f Michael Hanselmann

1553 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1554 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1555 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1556 5d28cb6f Michael Hanselmann

1557 5d28cb6f Michael Hanselmann
  """
1558 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1559 5d28cb6f Michael Hanselmann
1560 5d28cb6f Michael Hanselmann
  if consinfo is None:
1561 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1562 5d28cb6f Michael Hanselmann
1563 5d28cb6f Michael Hanselmann
  return consinfo
1564 5d28cb6f Michael Hanselmann
1565 5d28cb6f Michael Hanselmann
1566 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1567 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1568 1c8addc6 Michael Hanselmann

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

1571 1c8addc6 Michael Hanselmann
  """
1572 1c8addc6 Michael Hanselmann
  fields = [
1573 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1574 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1575 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1576 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1577 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1578 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1579 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1580 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1581 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1582 1c8addc6 Michael Hanselmann
    ]
1583 1c8addc6 Michael Hanselmann
1584 1c8addc6 Michael Hanselmann
  # Disks by number
1585 1c8addc6 Michael Hanselmann
  fields.extend([
1586 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1587 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1588 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1589 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1590 1c8addc6 Michael Hanselmann
    ])
1591 1c8addc6 Michael Hanselmann
1592 1c8addc6 Michael Hanselmann
  return fields
1593 1c8addc6 Michael Hanselmann
1594 1c8addc6 Michael Hanselmann
1595 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1596 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1597 1c8addc6 Michael Hanselmann

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

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

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

1757 24d16f76 Michael Hanselmann
  """
1758 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1759 24d16f76 Michael Hanselmann
    """Initializes this class.
1760 24d16f76 Michael Hanselmann

1761 24d16f76 Michael Hanselmann
    """
1762 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1763 24d16f76 Michael Hanselmann
1764 24d16f76 Michael Hanselmann
  def __iter__(self):
1765 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1766 24d16f76 Michael Hanselmann

1767 24d16f76 Michael Hanselmann
    """
1768 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1769 24d16f76 Michael Hanselmann
1770 24d16f76 Michael Hanselmann
1771 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1772 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1773 24d16f76 Michael Hanselmann

1774 24d16f76 Michael Hanselmann
  """
1775 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1776 24d16f76 Michael Hanselmann
1777 24d16f76 Michael Hanselmann
  if owners:
1778 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1779 24d16f76 Michael Hanselmann
1780 e2d188cc Iustin Pop
  return owners
1781 24d16f76 Michael Hanselmann
1782 24d16f76 Michael Hanselmann
1783 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1784 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1785 24d16f76 Michael Hanselmann

1786 24d16f76 Michael Hanselmann
  """
1787 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1788 24d16f76 Michael Hanselmann
1789 24d16f76 Michael Hanselmann
  if pending:
1790 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1791 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1792 24d16f76 Michael Hanselmann
1793 e2d188cc Iustin Pop
  return pending
1794 24d16f76 Michael Hanselmann
1795 24d16f76 Michael Hanselmann
1796 24d16f76 Michael Hanselmann
def _BuildLockFields():
1797 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1798 24d16f76 Michael Hanselmann

1799 24d16f76 Michael Hanselmann
  """
1800 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1801 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
1802 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
1803 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1804 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
1805 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
1806 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
1807 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
1808 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
1809 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
1810 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
1811 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
1812 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
1813 d63bd540 Iustin Pop
    ], [])
1814 24d16f76 Michael Hanselmann
1815 24d16f76 Michael Hanselmann
1816 8e21cfc0 Adeodato Simo
class GroupQueryData:
1817 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1818 8e21cfc0 Adeodato Simo

1819 8e21cfc0 Adeodato Simo
  """
1820 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1821 8e21cfc0 Adeodato Simo
    """Initializes this class.
1822 8e21cfc0 Adeodato Simo

1823 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1824 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1825 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1826 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1827 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1828 8e21cfc0 Adeodato Simo

1829 8e21cfc0 Adeodato Simo
    """
1830 8e21cfc0 Adeodato Simo
    self.groups = groups
1831 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1832 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1833 8e21cfc0 Adeodato Simo
1834 8e21cfc0 Adeodato Simo
  def __iter__(self):
1835 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1836 8e21cfc0 Adeodato Simo

1837 8e21cfc0 Adeodato Simo
    """
1838 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1839 8e21cfc0 Adeodato Simo
1840 8e21cfc0 Adeodato Simo
1841 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1842 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
1843 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
1844 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
1845 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
1846 79b2ca83 Michael Hanselmann
  "ndparams": ("NDParams", QFT_OTHER, "Node parameters"),
1847 8e21cfc0 Adeodato Simo
  }
1848 8e21cfc0 Adeodato Simo
1849 8e21cfc0 Adeodato Simo
1850 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1851 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1852 8e21cfc0 Adeodato Simo

1853 8e21cfc0 Adeodato Simo
  """
1854 8e21cfc0 Adeodato Simo
  # Add simple fields
1855 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
1856 111bf531 Michael Hanselmann
             _GetItemAttr(name))
1857 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
1858 8e21cfc0 Adeodato Simo
1859 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1860 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
1861 8e21cfc0 Adeodato Simo
1862 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1863 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
1864 8e21cfc0 Adeodato Simo
1865 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1866 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1867 8e21cfc0 Adeodato Simo
1868 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1869 8e21cfc0 Adeodato Simo
  fields.extend([
1870 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
1871 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
1872 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
1873 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
1874 8e21cfc0 Adeodato Simo
    ])
1875 8e21cfc0 Adeodato Simo
1876 8e21cfc0 Adeodato Simo
  # Add fields for instances
1877 8e21cfc0 Adeodato Simo
  fields.extend([
1878 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
1879 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
1880 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
1881 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
1882 79b2ca83 Michael Hanselmann
                "List of primary instances"),
1883 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
1884 8e21cfc0 Adeodato Simo
    ])
1885 8e21cfc0 Adeodato Simo
1886 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1887 8e21cfc0 Adeodato Simo
1888 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1889 8e21cfc0 Adeodato Simo
1890 8e21cfc0 Adeodato Simo
1891 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
1892 be3a4b14 Michael Hanselmann
  __slots__ = [
1893 be3a4b14 Michael Hanselmann
    "name",
1894 be3a4b14 Michael Hanselmann
    "valid",
1895 be3a4b14 Michael Hanselmann
    "hidden",
1896 be3a4b14 Michael Hanselmann
    "blacklisted",
1897 be3a4b14 Michael Hanselmann
    "variants",
1898 be3a4b14 Michael Hanselmann
    "api_versions",
1899 be3a4b14 Michael Hanselmann
    "parameters",
1900 be3a4b14 Michael Hanselmann
    "node_status",
1901 be3a4b14 Michael Hanselmann
    ]
1902 be3a4b14 Michael Hanselmann
1903 be3a4b14 Michael Hanselmann
1904 be3a4b14 Michael Hanselmann
def _BuildOsFields():
1905 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
1906 be3a4b14 Michael Hanselmann

1907 be3a4b14 Michael Hanselmann
  """
1908 be3a4b14 Michael Hanselmann
  fields = [
1909 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
1910 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
1911 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
1912 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
1913 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
1914 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
1915 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
1916 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
1917 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
1918 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
1919 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
1920 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
1921 be3a4b14 Michael Hanselmann
                "Operating system variants"),
1922 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
1923 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
1924 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
1925 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
1926 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
1927 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
1928 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("parameters"))),
1929 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
1930 be3a4b14 Michael Hanselmann
                "Status from node"),
1931 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
1932 be3a4b14 Michael Hanselmann
    ]
1933 be3a4b14 Michael Hanselmann
1934 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
1935 be3a4b14 Michael Hanselmann
1936 be3a4b14 Michael Hanselmann
1937 8235fe04 Michael Hanselmann
#: Fields available for node queries
1938 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
1939 1c8addc6 Michael Hanselmann
1940 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
1941 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
1942 24d16f76 Michael Hanselmann
1943 24d16f76 Michael Hanselmann
#: Fields available for lock queries
1944 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
1945 e571ee44 Adeodato Simo
1946 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
1947 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
1948 8e21cfc0 Adeodato Simo
1949 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
1950 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
1951 be3a4b14 Michael Hanselmann
1952 95eb4188 Michael Hanselmann
#: All available resources
1953 95eb4188 Michael Hanselmann
ALL_FIELDS = {
1954 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
1955 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
1956 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
1957 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
1958 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
1959 95eb4188 Michael Hanselmann
  }
1960 95eb4188 Michael Hanselmann
1961 e571ee44 Adeodato Simo
#: All available field lists
1962 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()