Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 355d1f32

History | View | Annotate | Download (84.6 kB)

1 4ca96421 Michael Hanselmann
#
2 4ca96421 Michael Hanselmann
#
3 4ca96421 Michael Hanselmann
4 0b1c7a55 Iustin Pop
# Copyright (C) 2010, 2011, 2012, 2013 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 dff5f600 Michael Hanselmann
from ganeti import runtime
66 fb0be379 Michael Hanselmann
from ganeti import qlang
67 526f866b Michael Hanselmann
from ganeti import jstore
68 4ca96421 Michael Hanselmann
69 82599b3e Iustin Pop
from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
70 82599b3e Iustin Pop
                              QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER,
71 cfb084ae René Nussbaumer
                              RS_NORMAL, RS_UNKNOWN, RS_NODATA,
72 cfb084ae René Nussbaumer
                              RS_UNAVAIL, RS_OFFLINE)
73 82599b3e Iustin Pop
74 306bed0e Apollon Oikonomopoulos
(NETQ_CONFIG,
75 306bed0e Apollon Oikonomopoulos
 NETQ_GROUP,
76 306bed0e Apollon Oikonomopoulos
 NETQ_STATS,
77 306bed0e Apollon Oikonomopoulos
 NETQ_INST) = range(300, 304)
78 4ca96421 Michael Hanselmann
79 8f8ce6d1 Michael Hanselmann
# Constants for requesting data from the caller/data provider. Each property
80 8f8ce6d1 Michael Hanselmann
# collected/computed separately by the data provider should have its own to
81 8f8ce6d1 Michael Hanselmann
# only collect the requested data and not more.
82 8f8ce6d1 Michael Hanselmann
83 8235fe04 Michael Hanselmann
(NQ_CONFIG,
84 8235fe04 Michael Hanselmann
 NQ_INST,
85 8235fe04 Michael Hanselmann
 NQ_LIVE,
86 52b5d286 René Nussbaumer
 NQ_GROUP,
87 52b5d286 René Nussbaumer
 NQ_OOB) = range(1, 6)
88 8235fe04 Michael Hanselmann
89 1c8addc6 Michael Hanselmann
(IQ_CONFIG,
90 1c8addc6 Michael Hanselmann
 IQ_LIVE,
91 5d28cb6f Michael Hanselmann
 IQ_DISKUSAGE,
92 fab9573b Michael Hanselmann
 IQ_CONSOLE,
93 f98e1175 Dimitris Aragiorgis
 IQ_NODES,
94 f98e1175 Dimitris Aragiorgis
 IQ_NETWORKS) = range(100, 106)
95 1c8addc6 Michael Hanselmann
96 24d16f76 Michael Hanselmann
(LQ_MODE,
97 24d16f76 Michael Hanselmann
 LQ_OWNER,
98 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
99 8235fe04 Michael Hanselmann
100 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
101 8e21cfc0 Adeodato Simo
 GQ_NODE,
102 2c758845 René Nussbaumer
 GQ_INST,
103 2c758845 René Nussbaumer
 GQ_DISKPARAMS) = range(200, 204)
104 8e21cfc0 Adeodato Simo
105 dff5f600 Michael Hanselmann
(CQ_CONFIG,
106 dff5f600 Michael Hanselmann
 CQ_QUEUE_DRAINED,
107 dff5f600 Michael Hanselmann
 CQ_WATCHER_PAUSE) = range(300, 303)
108 dff5f600 Michael Hanselmann
109 0422250e Michael Hanselmann
(JQ_ARCHIVED, ) = range(400, 401)
110 0422250e Michael Hanselmann
111 111bf531 Michael Hanselmann
# Query field flags
112 111bf531 Michael Hanselmann
QFF_HOSTNAME = 0x01
113 111bf531 Michael Hanselmann
QFF_IP_ADDRESS = 0x02
114 526f866b Michael Hanselmann
QFF_JOB_ID = 0x04
115 526f866b Michael Hanselmann
QFF_SPLIT_TIMESTAMP = 0x08
116 526f866b Michael Hanselmann
# Next values: 0x10, 0x20, 0x40, 0x80, 0x100, 0x200
117 526f866b Michael Hanselmann
QFF_ALL = (QFF_HOSTNAME | QFF_IP_ADDRESS | QFF_JOB_ID | QFF_SPLIT_TIMESTAMP)
118 8e21cfc0 Adeodato Simo
119 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
120 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
121 1ae17369 Michael Hanselmann
DOC_RE = re.compile(r"^[A-Z].*[^.,?!]$")
122 4ca96421 Michael Hanselmann
123 4ca96421 Michael Hanselmann
#: Verification function for each field type
124 4ca96421 Michael Hanselmann
_VERIFY_FN = {
125 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
126 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
127 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
128 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
129 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
130 697f49d5 Michael Hanselmann
  QFT_TIMESTAMP: ht.TNumber,
131 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
132 4ca96421 Michael Hanselmann
  }
133 4ca96421 Michael Hanselmann
134 e2d188cc Iustin Pop
# Unique objects for special field statuses
135 e2d188cc Iustin Pop
_FS_UNKNOWN = object()
136 e2d188cc Iustin Pop
_FS_NODATA = object()
137 e2d188cc Iustin Pop
_FS_UNAVAIL = object()
138 e2d188cc Iustin Pop
_FS_OFFLINE = object()
139 e2d188cc Iustin Pop
140 425e5bf0 Michael Hanselmann
#: List of all special status
141 b8028dcf Michael Hanselmann
_FS_ALL = compat.UniqueFrozenset([
142 b8028dcf Michael Hanselmann
  _FS_UNKNOWN,
143 b8028dcf Michael Hanselmann
  _FS_NODATA,
144 b8028dcf Michael Hanselmann
  _FS_UNAVAIL,
145 b8028dcf Michael Hanselmann
  _FS_OFFLINE,
146 b8028dcf Michael Hanselmann
  ])
147 425e5bf0 Michael Hanselmann
148 af58707c Iustin Pop
#: VType to QFT mapping
149 af58707c Iustin Pop
_VTToQFT = {
150 af58707c Iustin Pop
  # TODO: fix validation of empty strings
151 af58707c Iustin Pop
  constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty
152 af58707c Iustin Pop
  constants.VTYPE_MAYBE_STRING: QFT_OTHER,
153 af58707c Iustin Pop
  constants.VTYPE_BOOL: QFT_BOOL,
154 af58707c Iustin Pop
  constants.VTYPE_SIZE: QFT_UNIT,
155 af58707c Iustin Pop
  constants.VTYPE_INT: QFT_NUMBER,
156 af58707c Iustin Pop
  }
157 af58707c Iustin Pop
158 79b2ca83 Michael Hanselmann
_SERIAL_NO_DOC = "%s object serial number, incremented on each modification"
159 79b2ca83 Michael Hanselmann
160 4ca96421 Michael Hanselmann
161 b459a848 Andrea Spadaccini
def _GetUnknownField(ctx, item): # pylint: disable=W0613
162 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
163 4ca96421 Michael Hanselmann

164 4ca96421 Michael Hanselmann
  """
165 e2d188cc Iustin Pop
  return _FS_UNKNOWN
166 4ca96421 Michael Hanselmann
167 4ca96421 Michael Hanselmann
168 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
169 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
170 4ca96421 Michael Hanselmann

171 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
172 4ca96421 Michael Hanselmann

173 4ca96421 Michael Hanselmann
  @type fielddefs: dict
174 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
175 4ca96421 Michael Hanselmann
  @type selected: list of strings
176 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
177 4ca96421 Michael Hanselmann

178 4ca96421 Michael Hanselmann
  """
179 4ca96421 Michael Hanselmann
  result = []
180 4ca96421 Michael Hanselmann
181 4ca96421 Michael Hanselmann
  for name in selected:
182 4ca96421 Michael Hanselmann
    try:
183 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
184 4ca96421 Michael Hanselmann
    except KeyError:
185 79b2ca83 Michael Hanselmann
      fdef = (_MakeField(name, name, QFT_UNKNOWN, "Unknown field '%s'" % name),
186 111bf531 Michael Hanselmann
              None, 0, _GetUnknownField)
187 4ca96421 Michael Hanselmann
188 111bf531 Michael Hanselmann
    assert len(fdef) == 4
189 4ca96421 Michael Hanselmann
190 4ca96421 Michael Hanselmann
    result.append(fdef)
191 4ca96421 Michael Hanselmann
192 4ca96421 Michael Hanselmann
  return result
193 4ca96421 Michael Hanselmann
194 4ca96421 Michael Hanselmann
195 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
196 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
197 4ca96421 Michael Hanselmann

198 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
199 4ca96421 Michael Hanselmann

200 4ca96421 Michael Hanselmann
  """
201 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
202 4ca96421 Michael Hanselmann
203 4ca96421 Michael Hanselmann
204 fb0be379 Michael Hanselmann
class _FilterHints:
205 fb0be379 Michael Hanselmann
  """Class for filter analytics.
206 fb0be379 Michael Hanselmann

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

212 fb0be379 Michael Hanselmann
  There are two ways to optimize this. The first, and simpler, is to assign
213 fb0be379 Michael Hanselmann
  each field a group of data, so that the caller can determine which
214 fb0be379 Michael Hanselmann
  computations are necessary depending on the data groups requested. The list
215 fb0be379 Michael Hanselmann
  of referenced groups must also be computed for fields referenced in the
216 fb0be379 Michael Hanselmann
  filter.
217 fb0be379 Michael Hanselmann

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

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

227 fb0be379 Michael Hanselmann
  """
228 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
229 fb0be379 Michael Hanselmann
    """Initializes this class.
230 fb0be379 Michael Hanselmann

231 fb0be379 Michael Hanselmann
    @type namefield: string
232 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
233 fb0be379 Michael Hanselmann

234 fb0be379 Michael Hanselmann
    """
235 fb0be379 Michael Hanselmann
    self._namefield = namefield
236 fb0be379 Michael Hanselmann
237 fb0be379 Michael Hanselmann
    #: Whether all names need to be requested (e.g. if a non-equality operator
238 fb0be379 Michael Hanselmann
    #: has been used)
239 fb0be379 Michael Hanselmann
    self._allnames = False
240 fb0be379 Michael Hanselmann
241 fb0be379 Michael Hanselmann
    #: Which names to request
242 fb0be379 Michael Hanselmann
    self._names = None
243 fb0be379 Michael Hanselmann
244 fb0be379 Michael Hanselmann
    #: Data kinds referenced by the filter (used by L{Query.RequestedData})
245 fb0be379 Michael Hanselmann
    self._datakinds = set()
246 fb0be379 Michael Hanselmann
247 fb0be379 Michael Hanselmann
  def RequestedNames(self):
248 fb0be379 Michael Hanselmann
    """Returns all requested values.
249 fb0be379 Michael Hanselmann

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

253 fb0be379 Michael Hanselmann
    @rtype: list
254 fb0be379 Michael Hanselmann

255 fb0be379 Michael Hanselmann
    """
256 fb0be379 Michael Hanselmann
    if self._allnames or self._names is None:
257 fb0be379 Michael Hanselmann
      return None
258 fb0be379 Michael Hanselmann
259 fb0be379 Michael Hanselmann
    return utils.UniqueSequence(self._names)
260 fb0be379 Michael Hanselmann
261 fb0be379 Michael Hanselmann
  def ReferencedData(self):
262 fb0be379 Michael Hanselmann
    """Returns all kinds of data referenced by the filter.
263 fb0be379 Michael Hanselmann

264 fb0be379 Michael Hanselmann
    """
265 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
266 fb0be379 Michael Hanselmann
267 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
268 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
269 fb0be379 Michael Hanselmann

270 fb0be379 Michael Hanselmann
    """
271 fb0be379 Michael Hanselmann
    self._allnames = True
272 fb0be379 Michael Hanselmann
    self._names = None
273 fb0be379 Michael Hanselmann
274 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
275 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
276 fb0be379 Michael Hanselmann

277 fb0be379 Michael Hanselmann
    @type op: string
278 fb0be379 Michael Hanselmann
    @param op: Operator
279 fb0be379 Michael Hanselmann

280 fb0be379 Michael Hanselmann
    """
281 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
282 fb0be379 Michael Hanselmann
      self._NeedAllNames()
283 fb0be379 Michael Hanselmann
284 52aa1efa Michael Hanselmann
  def NoteUnaryOp(self, op, datakind): # pylint: disable=W0613
285 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
286 fb0be379 Michael Hanselmann

287 fb0be379 Michael Hanselmann
    @type op: string
288 fb0be379 Michael Hanselmann
    @param op: Operator
289 fb0be379 Michael Hanselmann

290 fb0be379 Michael Hanselmann
    """
291 52aa1efa Michael Hanselmann
    if datakind is not None:
292 52aa1efa Michael Hanselmann
      self._datakinds.add(datakind)
293 52aa1efa Michael Hanselmann
294 fb0be379 Michael Hanselmann
    self._NeedAllNames()
295 fb0be379 Michael Hanselmann
296 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
297 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
298 fb0be379 Michael Hanselmann

299 fb0be379 Michael Hanselmann
    @type op: string
300 fb0be379 Michael Hanselmann
    @param op: Operator
301 fb0be379 Michael Hanselmann
    @type name: string
302 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
303 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
304 fb0be379 Michael Hanselmann

305 fb0be379 Michael Hanselmann
    """
306 fb0be379 Michael Hanselmann
    if datakind is not None:
307 fb0be379 Michael Hanselmann
      self._datakinds.add(datakind)
308 fb0be379 Michael Hanselmann
309 fb0be379 Michael Hanselmann
    if self._allnames:
310 fb0be379 Michael Hanselmann
      return
311 fb0be379 Michael Hanselmann
312 fb0be379 Michael Hanselmann
    # If any operator other than equality was used, all names need to be
313 fb0be379 Michael Hanselmann
    # retrieved
314 fb0be379 Michael Hanselmann
    if op == qlang.OP_EQUAL and name == self._namefield:
315 fb0be379 Michael Hanselmann
      if self._names is None:
316 fb0be379 Michael Hanselmann
        self._names = []
317 fb0be379 Michael Hanselmann
      self._names.append(value)
318 fb0be379 Michael Hanselmann
    else:
319 fb0be379 Michael Hanselmann
      self._NeedAllNames()
320 fb0be379 Michael Hanselmann
321 fb0be379 Michael Hanselmann
322 fb0be379 Michael Hanselmann
def _WrapLogicOp(op_fn, sentences, ctx, item):
323 fb0be379 Michael Hanselmann
  """Wrapper for logic operator functions.
324 fb0be379 Michael Hanselmann

325 fb0be379 Michael Hanselmann
  """
326 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
327 fb0be379 Michael Hanselmann
328 fb0be379 Michael Hanselmann
329 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
330 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
331 fb0be379 Michael Hanselmann

332 fb0be379 Michael Hanselmann
  """
333 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
334 fb0be379 Michael Hanselmann
335 fb0be379 Michael Hanselmann
336 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
337 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
338 fb0be379 Michael Hanselmann

339 fb0be379 Michael Hanselmann
  """
340 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
341 fb0be379 Michael Hanselmann
342 fb0be379 Michael Hanselmann
343 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
344 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
345 fb0be379 Michael Hanselmann

346 fb0be379 Michael Hanselmann
  """
347 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
348 fb0be379 Michael Hanselmann
349 fb0be379 Michael Hanselmann
350 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
351 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
352 23d0a608 Michael Hanselmann

353 23d0a608 Michael Hanselmann
  """
354 23d0a608 Michael Hanselmann
  try:
355 23d0a608 Michael Hanselmann
    return re.compile(pattern)
356 23d0a608 Michael Hanselmann
  except re.error, err:
357 23d0a608 Michael Hanselmann
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
358 23d0a608 Michael Hanselmann
359 23d0a608 Michael Hanselmann
360 526f866b Michael Hanselmann
def _PrepareSplitTimestamp(value):
361 526f866b Michael Hanselmann
  """Prepares a value for comparison by L{_MakeSplitTimestampComparison}.
362 526f866b Michael Hanselmann

363 526f866b Michael Hanselmann
  """
364 526f866b Michael Hanselmann
  if ht.TNumber(value):
365 526f866b Michael Hanselmann
    return value
366 526f866b Michael Hanselmann
  else:
367 526f866b Michael Hanselmann
    return utils.MergeTime(value)
368 526f866b Michael Hanselmann
369 526f866b Michael Hanselmann
370 526f866b Michael Hanselmann
def _MakeSplitTimestampComparison(fn):
371 526f866b Michael Hanselmann
  """Compares split timestamp values after converting to float.
372 526f866b Michael Hanselmann

373 526f866b Michael Hanselmann
  """
374 526f866b Michael Hanselmann
  return lambda lhs, rhs: fn(utils.MergeTime(lhs), rhs)
375 526f866b Michael Hanselmann
376 526f866b Michael Hanselmann
377 526f866b Michael Hanselmann
def _MakeComparisonChecks(fn):
378 526f866b Michael Hanselmann
  """Prepares flag-specific comparisons using a comparison function.
379 526f866b Michael Hanselmann

380 526f866b Michael Hanselmann
  """
381 526f866b Michael Hanselmann
  return [
382 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(fn),
383 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
384 526f866b Michael Hanselmann
    (QFF_JOB_ID, lambda lhs, rhs: fn(jstore.ParseJobId(lhs), rhs),
385 526f866b Michael Hanselmann
     jstore.ParseJobId),
386 526f866b Michael Hanselmann
    (None, fn, None),
387 526f866b Michael Hanselmann
    ]
388 526f866b Michael Hanselmann
389 526f866b Michael Hanselmann
390 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
391 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
392 fb0be379 Michael Hanselmann

393 fb0be379 Michael Hanselmann
  """
394 b459a848 Andrea Spadaccini
  # String statement has no effect, pylint: disable=W0105
395 fb0be379 Michael Hanselmann
396 fb0be379 Michael Hanselmann
  #: How deep filters can be nested
397 fb0be379 Michael Hanselmann
  _LEVELS_MAX = 10
398 fb0be379 Michael Hanselmann
399 fb0be379 Michael Hanselmann
  # Unique identifiers for operator groups
400 fb0be379 Michael Hanselmann
  (_OPTYPE_LOGIC,
401 fb0be379 Michael Hanselmann
   _OPTYPE_UNARY,
402 fb0be379 Michael Hanselmann
   _OPTYPE_BINARY) = range(1, 4)
403 fb0be379 Michael Hanselmann
404 fb0be379 Michael Hanselmann
  """Functions for equality checks depending on field flags.
405 fb0be379 Michael Hanselmann

406 fb0be379 Michael Hanselmann
  List of tuples containing flags and a callable receiving the left- and
407 fb0be379 Michael Hanselmann
  right-hand side of the operator. The flags are an OR-ed value of C{QFF_*}
408 526f866b Michael Hanselmann
  (e.g. L{QFF_HOSTNAME} or L{QFF_SPLIT_TIMESTAMP}).
409 fb0be379 Michael Hanselmann

410 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
411 fb0be379 Michael Hanselmann
  using binary AND.
412 fb0be379 Michael Hanselmann

413 fb0be379 Michael Hanselmann
  """
414 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
415 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
416 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
417 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
418 23d0a608 Michael Hanselmann
     None),
419 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(operator.eq),
420 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
421 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
422 fb0be379 Michael Hanselmann
    ]
423 fb0be379 Michael Hanselmann
424 fb0be379 Michael Hanselmann
  """Known operators
425 fb0be379 Michael Hanselmann

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

429 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
430 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
431 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
432 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
433 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
434 fb0be379 Michael Hanselmann

435 fb0be379 Michael Hanselmann
  """
436 fb0be379 Michael Hanselmann
  _OPS = {
437 fb0be379 Michael Hanselmann
    # Logic operators
438 fb0be379 Michael Hanselmann
    qlang.OP_OR: (_OPTYPE_LOGIC, compat.any),
439 fb0be379 Michael Hanselmann
    qlang.OP_AND: (_OPTYPE_LOGIC, compat.all),
440 fb0be379 Michael Hanselmann
441 fb0be379 Michael Hanselmann
    # Unary operators
442 3b877f08 Michael Hanselmann
    qlang.OP_NOT: (_OPTYPE_UNARY, None),
443 3b877f08 Michael Hanselmann
    qlang.OP_TRUE: (_OPTYPE_UNARY, None),
444 fb0be379 Michael Hanselmann
445 fb0be379 Michael Hanselmann
    # Binary operators
446 fb0be379 Michael Hanselmann
    qlang.OP_EQUAL: (_OPTYPE_BINARY, _EQUALITY_CHECKS),
447 fb0be379 Michael Hanselmann
    qlang.OP_NOT_EQUAL:
448 23d0a608 Michael Hanselmann
      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn), valprepfn)
449 23d0a608 Michael Hanselmann
                        for (flags, fn, valprepfn) in _EQUALITY_CHECKS]),
450 526f866b Michael Hanselmann
    qlang.OP_LT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.lt)),
451 526f866b Michael Hanselmann
    qlang.OP_LE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.le)),
452 526f866b Michael Hanselmann
    qlang.OP_GT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.gt)),
453 526f866b Michael Hanselmann
    qlang.OP_GE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.ge)),
454 23d0a608 Michael Hanselmann
    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
455 23d0a608 Michael Hanselmann
      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
456 23d0a608 Michael Hanselmann
      ]),
457 fb0be379 Michael Hanselmann
    qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
458 23d0a608 Michael Hanselmann
      (None, operator.contains, None),
459 fb0be379 Michael Hanselmann
      ]),
460 fb0be379 Michael Hanselmann
    }
461 fb0be379 Michael Hanselmann
462 fb0be379 Michael Hanselmann
  def __init__(self, fields):
463 fb0be379 Michael Hanselmann
    """Initializes this class.
464 fb0be379 Michael Hanselmann

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

467 fb0be379 Michael Hanselmann
    """
468 fb0be379 Michael Hanselmann
    self._fields = fields
469 fb0be379 Michael Hanselmann
    self._hints = None
470 fb0be379 Michael Hanselmann
    self._op_handler = None
471 fb0be379 Michael Hanselmann
472 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
473 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
474 fb0be379 Michael Hanselmann

475 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
476 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
477 2e5c33db Iustin Pop
    @type qfilter: list
478 2e5c33db Iustin Pop
    @param qfilter: Filter structure
479 fb0be379 Michael Hanselmann
    @rtype: callable
480 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
481 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
482 fb0be379 Michael Hanselmann

483 fb0be379 Michael Hanselmann
    """
484 fb0be379 Michael Hanselmann
    self._op_handler = {
485 fb0be379 Michael Hanselmann
      self._OPTYPE_LOGIC:
486 fb0be379 Michael Hanselmann
        (self._HandleLogicOp, getattr(hints, "NoteLogicOp", None)),
487 fb0be379 Michael Hanselmann
      self._OPTYPE_UNARY:
488 fb0be379 Michael Hanselmann
        (self._HandleUnaryOp, getattr(hints, "NoteUnaryOp", None)),
489 fb0be379 Michael Hanselmann
      self._OPTYPE_BINARY:
490 fb0be379 Michael Hanselmann
        (self._HandleBinaryOp, getattr(hints, "NoteBinaryOp", None)),
491 fb0be379 Michael Hanselmann
      }
492 fb0be379 Michael Hanselmann
493 fb0be379 Michael Hanselmann
    try:
494 2e5c33db Iustin Pop
      filter_fn = self._Compile(qfilter, 0)
495 fb0be379 Michael Hanselmann
    finally:
496 fb0be379 Michael Hanselmann
      self._op_handler = None
497 fb0be379 Michael Hanselmann
498 fb0be379 Michael Hanselmann
    return filter_fn
499 fb0be379 Michael Hanselmann
500 2e5c33db Iustin Pop
  def _Compile(self, qfilter, level):
501 fb0be379 Michael Hanselmann
    """Inner function for converting filters.
502 fb0be379 Michael Hanselmann

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

506 fb0be379 Michael Hanselmann
    """
507 2e5c33db Iustin Pop
    if not (isinstance(qfilter, (list, tuple)) and qfilter):
508 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid filter on level %s" % level)
509 fb0be379 Michael Hanselmann
510 fb0be379 Michael Hanselmann
    # Limit recursion
511 fb0be379 Michael Hanselmann
    if level >= self._LEVELS_MAX:
512 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Only up to %s levels are allowed (filter"
513 fb0be379 Michael Hanselmann
                                  " nested too deep)" % self._LEVELS_MAX)
514 fb0be379 Michael Hanselmann
515 fb0be379 Michael Hanselmann
    # Create copy to be modified
516 2e5c33db Iustin Pop
    operands = qfilter[:]
517 fb0be379 Michael Hanselmann
    op = operands.pop(0)
518 fb0be379 Michael Hanselmann
519 fb0be379 Michael Hanselmann
    try:
520 fb0be379 Michael Hanselmann
      (kind, op_data) = self._OPS[op]
521 fb0be379 Michael Hanselmann
    except KeyError:
522 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unknown operator '%s'" % op)
523 fb0be379 Michael Hanselmann
524 fb0be379 Michael Hanselmann
    (handler, hints_cb) = self._op_handler[kind]
525 fb0be379 Michael Hanselmann
526 fb0be379 Michael Hanselmann
    return handler(hints_cb, level, op, op_data, operands)
527 fb0be379 Michael Hanselmann
528 3b877f08 Michael Hanselmann
  def _LookupField(self, name):
529 3b877f08 Michael Hanselmann
    """Returns a field definition by name.
530 3b877f08 Michael Hanselmann

531 3b877f08 Michael Hanselmann
    """
532 3b877f08 Michael Hanselmann
    try:
533 3b877f08 Michael Hanselmann
      return self._fields[name]
534 3b877f08 Michael Hanselmann
    except KeyError:
535 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
536 3b877f08 Michael Hanselmann
537 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
538 fb0be379 Michael Hanselmann
    """Handles logic operators.
539 fb0be379 Michael Hanselmann

540 fb0be379 Michael Hanselmann
    @type hints_fn: callable
541 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
542 fb0be379 Michael Hanselmann
    @type level: integer
543 fb0be379 Michael Hanselmann
    @param level: Current depth
544 fb0be379 Michael Hanselmann
    @type op: string
545 fb0be379 Michael Hanselmann
    @param op: Operator
546 fb0be379 Michael Hanselmann
    @type op_fn: callable
547 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
548 fb0be379 Michael Hanselmann
    @type operands: list
549 fb0be379 Michael Hanselmann
    @param operands: List of operands
550 fb0be379 Michael Hanselmann

551 fb0be379 Michael Hanselmann
    """
552 fb0be379 Michael Hanselmann
    if hints_fn:
553 fb0be379 Michael Hanselmann
      hints_fn(op)
554 fb0be379 Michael Hanselmann
555 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
556 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
557 fb0be379 Michael Hanselmann
558 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
559 fb0be379 Michael Hanselmann
    """Handles unary operators.
560 fb0be379 Michael Hanselmann

561 fb0be379 Michael Hanselmann
    @type hints_fn: callable
562 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
563 fb0be379 Michael Hanselmann
    @type level: integer
564 fb0be379 Michael Hanselmann
    @param level: Current depth
565 fb0be379 Michael Hanselmann
    @type op: string
566 fb0be379 Michael Hanselmann
    @param op: Operator
567 fb0be379 Michael Hanselmann
    @type op_fn: callable
568 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
569 fb0be379 Michael Hanselmann
    @type operands: list
570 fb0be379 Michael Hanselmann
    @param operands: List of operands
571 fb0be379 Michael Hanselmann

572 fb0be379 Michael Hanselmann
    """
573 3b877f08 Michael Hanselmann
    assert op_fn is None
574 3b877f08 Michael Hanselmann
575 fb0be379 Michael Hanselmann
    if len(operands) != 1:
576 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unary operator '%s' expects exactly one"
577 fb0be379 Michael Hanselmann
                                  " operand" % op)
578 fb0be379 Michael Hanselmann
579 3b877f08 Michael Hanselmann
    if op == qlang.OP_TRUE:
580 52aa1efa Michael Hanselmann
      (_, datakind, _, retrieval_fn) = self._LookupField(operands[0])
581 52aa1efa Michael Hanselmann
582 52aa1efa Michael Hanselmann
      if hints_fn:
583 52aa1efa Michael Hanselmann
        hints_fn(op, datakind)
584 3b877f08 Michael Hanselmann
585 3b877f08 Michael Hanselmann
      op_fn = operator.truth
586 3b877f08 Michael Hanselmann
      arg = retrieval_fn
587 3b877f08 Michael Hanselmann
    elif op == qlang.OP_NOT:
588 52aa1efa Michael Hanselmann
      if hints_fn:
589 52aa1efa Michael Hanselmann
        hints_fn(op, None)
590 52aa1efa Michael Hanselmann
591 3b877f08 Michael Hanselmann
      op_fn = operator.not_
592 3b877f08 Michael Hanselmann
      arg = self._Compile(operands[0], level + 1)
593 3b877f08 Michael Hanselmann
    else:
594 3b877f08 Michael Hanselmann
      raise errors.ProgrammerError("Can't handle operator '%s'" % op)
595 3b877f08 Michael Hanselmann
596 3b877f08 Michael Hanselmann
    return compat.partial(_WrapUnaryOp, op_fn, arg)
597 fb0be379 Michael Hanselmann
598 fb0be379 Michael Hanselmann
  def _HandleBinaryOp(self, hints_fn, level, op, op_data, operands):
599 fb0be379 Michael Hanselmann
    """Handles binary operators.
600 fb0be379 Michael Hanselmann

601 fb0be379 Michael Hanselmann
    @type hints_fn: callable
602 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
603 fb0be379 Michael Hanselmann
    @type level: integer
604 fb0be379 Michael Hanselmann
    @param level: Current depth
605 fb0be379 Michael Hanselmann
    @type op: string
606 fb0be379 Michael Hanselmann
    @param op: Operator
607 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
608 fb0be379 Michael Hanselmann
    @type operands: list
609 fb0be379 Michael Hanselmann
    @param operands: List of operands
610 fb0be379 Michael Hanselmann

611 fb0be379 Michael Hanselmann
    """
612 b459a848 Andrea Spadaccini
    # Unused arguments, pylint: disable=W0613
613 fb0be379 Michael Hanselmann
    try:
614 fb0be379 Michael Hanselmann
      (name, value) = operands
615 fb0be379 Michael Hanselmann
    except (ValueError, TypeError):
616 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid binary operator, expected exactly"
617 fb0be379 Michael Hanselmann
                                  " two operands")
618 fb0be379 Michael Hanselmann
619 3b877f08 Michael Hanselmann
    (fdef, datakind, field_flags, retrieval_fn) = self._LookupField(name)
620 fb0be379 Michael Hanselmann
621 fb0be379 Michael Hanselmann
    assert fdef.kind != QFT_UNKNOWN
622 fb0be379 Michael Hanselmann
623 fb0be379 Michael Hanselmann
    # TODO: Type conversions?
624 fb0be379 Michael Hanselmann
625 fb0be379 Michael Hanselmann
    verify_fn = _VERIFY_FN[fdef.kind]
626 fb0be379 Michael Hanselmann
    if not verify_fn(value):
627 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unable to compare field '%s' (type '%s')"
628 fb0be379 Michael Hanselmann
                                  " with '%s', expected %s" %
629 fb0be379 Michael Hanselmann
                                  (name, fdef.kind, value.__class__.__name__,
630 fb0be379 Michael Hanselmann
                                   verify_fn))
631 fb0be379 Michael Hanselmann
632 fb0be379 Michael Hanselmann
    if hints_fn:
633 fb0be379 Michael Hanselmann
      hints_fn(op, datakind, name, value)
634 fb0be379 Michael Hanselmann
635 23d0a608 Michael Hanselmann
    for (fn_flags, fn, valprepfn) in op_data:
636 fb0be379 Michael Hanselmann
      if fn_flags is None or fn_flags & field_flags:
637 23d0a608 Michael Hanselmann
        # Prepare value if necessary (e.g. compile regular expression)
638 23d0a608 Michael Hanselmann
        if valprepfn:
639 23d0a608 Michael Hanselmann
          value = valprepfn(value)
640 23d0a608 Michael Hanselmann
641 fb0be379 Michael Hanselmann
        return compat.partial(_WrapBinaryOp, fn, retrieval_fn, value)
642 fb0be379 Michael Hanselmann
643 fb0be379 Michael Hanselmann
    raise errors.ProgrammerError("Unable to find operator implementation"
644 fb0be379 Michael Hanselmann
                                 " (op '%s', flags %s)" % (op, field_flags))
645 fb0be379 Michael Hanselmann
646 fb0be379 Michael Hanselmann
647 2e5c33db Iustin Pop
def _CompileFilter(fields, hints, qfilter):
648 fb0be379 Michael Hanselmann
  """Converts a query filter into a callable function.
649 fb0be379 Michael Hanselmann

650 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
651 fb0be379 Michael Hanselmann

652 fb0be379 Michael Hanselmann
  @rtype: callable
653 fb0be379 Michael Hanselmann

654 fb0be379 Michael Hanselmann
  """
655 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
656 fb0be379 Michael Hanselmann
657 fb0be379 Michael Hanselmann
658 4ca96421 Michael Hanselmann
class Query:
659 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
660 4ca96421 Michael Hanselmann
    """Initializes this class.
661 4ca96421 Michael Hanselmann

662 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
663 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
664 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
665 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
666 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
667 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
668 4ca96421 Michael Hanselmann

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

672 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
673 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
674 4ca96421 Michael Hanselmann
    @type selected: list of strings
675 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
676 4ca96421 Michael Hanselmann

677 4ca96421 Michael Hanselmann
    """
678 fb0be379 Michael Hanselmann
    assert namefield is None or namefield in fieldlist
679 fb0be379 Michael Hanselmann
680 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
681 4ca96421 Michael Hanselmann
682 fb0be379 Michael Hanselmann
    self._filter_fn = None
683 fb0be379 Michael Hanselmann
    self._requested_names = None
684 fb0be379 Michael Hanselmann
    self._filter_datakinds = frozenset()
685 fb0be379 Michael Hanselmann
686 2e5c33db Iustin Pop
    if qfilter is not None:
687 fb0be379 Michael Hanselmann
      # Collect requested names if wanted
688 fb0be379 Michael Hanselmann
      if namefield:
689 fb0be379 Michael Hanselmann
        hints = _FilterHints(namefield)
690 fb0be379 Michael Hanselmann
      else:
691 fb0be379 Michael Hanselmann
        hints = None
692 fb0be379 Michael Hanselmann
693 fb0be379 Michael Hanselmann
      # Build filter function
694 2e5c33db Iustin Pop
      self._filter_fn = _CompileFilter(fieldlist, hints, qfilter)
695 fb0be379 Michael Hanselmann
      if hints:
696 fb0be379 Michael Hanselmann
        self._requested_names = hints.RequestedNames()
697 fb0be379 Michael Hanselmann
        self._filter_datakinds = hints.ReferencedData()
698 fb0be379 Michael Hanselmann
699 fb0be379 Michael Hanselmann
    if namefield is None:
700 fb0be379 Michael Hanselmann
      self._name_fn = None
701 fb0be379 Michael Hanselmann
    else:
702 fb0be379 Michael Hanselmann
      (_, _, _, self._name_fn) = fieldlist[namefield]
703 fb0be379 Michael Hanselmann
704 fb0be379 Michael Hanselmann
  def RequestedNames(self):
705 fb0be379 Michael Hanselmann
    """Returns all names referenced in the filter.
706 fb0be379 Michael Hanselmann

707 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
708 fb0be379 Michael Hanselmann
    names, C{None} is returned.
709 fb0be379 Michael Hanselmann

710 fb0be379 Michael Hanselmann
    """
711 fb0be379 Michael Hanselmann
    return self._requested_names
712 fb0be379 Michael Hanselmann
713 4ca96421 Michael Hanselmann
  def RequestedData(self):
714 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
715 4ca96421 Michael Hanselmann

716 4ca96421 Michael Hanselmann
    @rtype: frozenset
717 4ca96421 Michael Hanselmann

718 4ca96421 Michael Hanselmann
    """
719 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
720 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
721 fb0be379 Michael Hanselmann
                      if datakind is not None))
722 4ca96421 Michael Hanselmann
723 4ca96421 Michael Hanselmann
  def GetFields(self):
724 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
725 4ca96421 Michael Hanselmann

726 4ca96421 Michael Hanselmann
    Includes unknown fields.
727 4ca96421 Michael Hanselmann

728 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
729 4ca96421 Michael Hanselmann

730 4ca96421 Michael Hanselmann
    """
731 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
732 4ca96421 Michael Hanselmann
733 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
734 4ca96421 Michael Hanselmann
    """Execute a query.
735 4ca96421 Michael Hanselmann

736 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
737 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
738 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
739 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
740 fbc263a9 Michael Hanselmann
      ordering
741 4ca96421 Michael Hanselmann

742 4ca96421 Michael Hanselmann
    """
743 fbc263a9 Michael Hanselmann
    sort = (self._name_fn and sort_by_name)
744 fbc263a9 Michael Hanselmann
745 fb0be379 Michael Hanselmann
    result = []
746 fb0be379 Michael Hanselmann
747 fb0be379 Michael Hanselmann
    for idx, item in enumerate(ctx):
748 fb0be379 Michael Hanselmann
      if not (self._filter_fn is None or self._filter_fn(ctx, item)):
749 fb0be379 Michael Hanselmann
        continue
750 4ca96421 Michael Hanselmann
751 fb0be379 Michael Hanselmann
      row = [_ProcessResult(fn(ctx, item)) for (_, _, _, fn) in self._fields]
752 fb0be379 Michael Hanselmann
753 fb0be379 Michael Hanselmann
      # Verify result
754 fb0be379 Michael Hanselmann
      if __debug__:
755 d1c3c3b3 Iustin Pop
        _VerifyResultRow(self._fields, row)
756 4ca96421 Michael Hanselmann
757 fbc263a9 Michael Hanselmann
      if sort:
758 fb0be379 Michael Hanselmann
        (status, name) = _ProcessResult(self._name_fn(ctx, item))
759 fb0be379 Michael Hanselmann
        assert status == constants.RS_NORMAL
760 fb0be379 Michael Hanselmann
        # TODO: Are there cases where we wouldn't want to use NiceSort?
761 76b62028 Iustin Pop
        # Answer: if the name field is non-string...
762 fbc263a9 Michael Hanselmann
        result.append((utils.NiceSortKey(name), idx, row))
763 fb0be379 Michael Hanselmann
      else:
764 fbc263a9 Michael Hanselmann
        result.append(row)
765 fb0be379 Michael Hanselmann
766 fbc263a9 Michael Hanselmann
    if not sort:
767 fbc263a9 Michael Hanselmann
      return result
768 fb0be379 Michael Hanselmann
769 fb0be379 Michael Hanselmann
    # TODO: Would "heapq" be more efficient than sorting?
770 fb0be379 Michael Hanselmann
771 fb0be379 Michael Hanselmann
    # Sorting in-place instead of using "sorted()"
772 fb0be379 Michael Hanselmann
    result.sort()
773 fb0be379 Michael Hanselmann
774 fb0be379 Michael Hanselmann
    assert not result or (len(result[0]) == 3 and len(result[-1]) == 3)
775 fb0be379 Michael Hanselmann
776 fb0be379 Michael Hanselmann
    return map(operator.itemgetter(2), result)
777 4ca96421 Michael Hanselmann
778 fbc263a9 Michael Hanselmann
  def OldStyleQuery(self, ctx, sort_by_name=True):
779 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
780 4ca96421 Michael Hanselmann

781 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
782 4ca96421 Michael Hanselmann

783 4ca96421 Michael Hanselmann
    """
784 111bf531 Michael Hanselmann
    unknown = set(fdef.name for (fdef, _, _, _) in self._fields
785 111bf531 Michael Hanselmann
                  if fdef.kind == QFT_UNKNOWN)
786 4ca96421 Michael Hanselmann
    if unknown:
787 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
788 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
789 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
790 4ca96421 Michael Hanselmann
791 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
792 fbc263a9 Michael Hanselmann
            for row in self.Query(ctx, sort_by_name=sort_by_name)]
793 4ca96421 Michael Hanselmann
794 4ca96421 Michael Hanselmann
795 e2d188cc Iustin Pop
def _ProcessResult(value):
796 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
797 e2d188cc Iustin Pop

798 e2d188cc Iustin Pop
  """
799 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
800 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
801 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
802 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
803 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
804 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
805 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
806 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
807 e2d188cc Iustin Pop
  else:
808 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
809 e2d188cc Iustin Pop
810 e2d188cc Iustin Pop
811 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
812 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
813 4ca96421 Michael Hanselmann

814 4ca96421 Michael Hanselmann
  @type fields: list
815 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
816 4ca96421 Michael Hanselmann
  @type row: list of tuples
817 4ca96421 Michael Hanselmann
  @param row: Row data
818 4ca96421 Michael Hanselmann

819 4ca96421 Michael Hanselmann
  """
820 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
821 d1c3c3b3 Iustin Pop
  errs = []
822 111bf531 Michael Hanselmann
  for ((status, value), (fdef, _, _, _)) in zip(row, fields):
823 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
824 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
825 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
826 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
827 d1c3c3b3 Iustin Pop
    elif value is not None:
828 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
829 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
830 34598551 Agata Murawska
                    (utils.CommaJoin(errs), row))
831 4ca96421 Michael Hanselmann
832 4ca96421 Michael Hanselmann
833 320e34df Michael Hanselmann
def _FieldDictKey((fdef, _, flags, fn)):
834 320e34df Michael Hanselmann
  """Generates key for field dictionary.
835 320e34df Michael Hanselmann

836 320e34df Michael Hanselmann
  """
837 320e34df Michael Hanselmann
  assert fdef.name and fdef.title, "Name and title are required"
838 320e34df Michael Hanselmann
  assert FIELD_NAME_RE.match(fdef.name)
839 320e34df Michael Hanselmann
  assert TITLE_RE.match(fdef.title)
840 320e34df Michael Hanselmann
  assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
841 320e34df Michael Hanselmann
          fdef.doc.strip() == fdef.doc), \
842 320e34df Michael Hanselmann
         "Invalid description for field '%s'" % fdef.name
843 320e34df Michael Hanselmann
  assert callable(fn)
844 320e34df Michael Hanselmann
  assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
845 320e34df Michael Hanselmann
846 320e34df Michael Hanselmann
  return fdef.name
847 320e34df Michael Hanselmann
848 320e34df Michael Hanselmann
849 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
850 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
851 4ca96421 Michael Hanselmann

852 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
853 4ca96421 Michael Hanselmann

854 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
855 d63bd540 Iustin Pop
      kind, retrieval function)
856 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
857 d63bd540 Iustin Pop
      description
858 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
859 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
860 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
861 4ca96421 Michael Hanselmann
  @rtype: dict
862 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
863 4ca96421 Michael Hanselmann

864 4ca96421 Michael Hanselmann
  """
865 89ce4acc Michael Hanselmann
  if __debug__:
866 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
867 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
868 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
869 4ca96421 Michael Hanselmann
870 320e34df Michael Hanselmann
  result = utils.SequenceToDict(fields, key=_FieldDictKey)
871 4ca96421 Michael Hanselmann
872 d63bd540 Iustin Pop
  for alias, target in aliases:
873 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
874 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
875 111bf531 Michael Hanselmann
    (fdef, k, flags, fn) = result[target]
876 d63bd540 Iustin Pop
    fdef = fdef.Copy()
877 d63bd540 Iustin Pop
    fdef.name = alias
878 111bf531 Michael Hanselmann
    result[alias] = (fdef, k, flags, fn)
879 d63bd540 Iustin Pop
880 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
881 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
882 111bf531 Michael Hanselmann
                    for (name, (fdef, _, _, _)) in result.items())
883 4ca96421 Michael Hanselmann
884 4ca96421 Michael Hanselmann
  return result
885 4ca96421 Michael Hanselmann
886 4ca96421 Michael Hanselmann
887 fbc263a9 Michael Hanselmann
def GetQueryResponse(query, ctx, sort_by_name=True):
888 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
889 b60fcb6f Michael Hanselmann

890 b60fcb6f Michael Hanselmann
  @type query: L{Query}
891 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
892 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
893 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
894 fbc263a9 Michael Hanselmann
    ordering
895 b60fcb6f Michael Hanselmann

896 b60fcb6f Michael Hanselmann
  """
897 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
898 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
899 b60fcb6f Michael Hanselmann
900 b60fcb6f Michael Hanselmann
901 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
902 aa29e95f Michael Hanselmann
  """Returns list of available fields.
903 aa29e95f Michael Hanselmann

904 aa29e95f Michael Hanselmann
  @type fielddefs: dict
905 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
906 aa29e95f Michael Hanselmann
  @type selected: list of strings
907 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
908 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
909 aa29e95f Michael Hanselmann

910 aa29e95f Michael Hanselmann
  """
911 aa29e95f Michael Hanselmann
  if selected is None:
912 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
913 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
914 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
915 aa29e95f Michael Hanselmann
  else:
916 aa29e95f Michael Hanselmann
    # Keep order as requested by client
917 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
918 aa29e95f Michael Hanselmann
919 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
920 aa29e95f Michael Hanselmann
921 aa29e95f Michael Hanselmann
922 79b2ca83 Michael Hanselmann
def _MakeField(name, title, kind, doc):
923 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
924 4ca96421 Michael Hanselmann

925 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
926 4ca96421 Michael Hanselmann
  @param title: Human-readable title
927 4ca96421 Michael Hanselmann
  @param kind: Field type
928 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
929 4ca96421 Michael Hanselmann

930 4ca96421 Michael Hanselmann
  """
931 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
932 1ae17369 Michael Hanselmann
                                      doc=doc)
933 8235fe04 Michael Hanselmann
934 8235fe04 Michael Hanselmann
935 dff5f600 Michael Hanselmann
def _StaticValueInner(value, ctx, _): # pylint: disable=W0613
936 dff5f600 Michael Hanselmann
  """Returns a static value.
937 dff5f600 Michael Hanselmann

938 dff5f600 Michael Hanselmann
  """
939 dff5f600 Michael Hanselmann
  return value
940 dff5f600 Michael Hanselmann
941 dff5f600 Michael Hanselmann
942 dff5f600 Michael Hanselmann
def _StaticValue(value):
943 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
944 dff5f600 Michael Hanselmann

945 dff5f600 Michael Hanselmann
  """
946 dff5f600 Michael Hanselmann
  return compat.partial(_StaticValueInner, value)
947 dff5f600 Michael Hanselmann
948 dff5f600 Michael Hanselmann
949 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
950 8235fe04 Michael Hanselmann
  """Determine node role.
951 8235fe04 Michael Hanselmann

952 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
953 8235fe04 Michael Hanselmann
  @param node: Node object
954 8235fe04 Michael Hanselmann
  @type master_name: string
955 8235fe04 Michael Hanselmann
  @param master_name: Master node name
956 8235fe04 Michael Hanselmann

957 8235fe04 Michael Hanselmann
  """
958 8235fe04 Michael Hanselmann
  if node.name == master_name:
959 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
960 8235fe04 Michael Hanselmann
  elif node.master_candidate:
961 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
962 8235fe04 Michael Hanselmann
  elif node.drained:
963 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
964 8235fe04 Michael Hanselmann
  elif node.offline:
965 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
966 8235fe04 Michael Hanselmann
  else:
967 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
968 8235fe04 Michael Hanselmann
969 8235fe04 Michael Hanselmann
970 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
971 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
972 8235fe04 Michael Hanselmann

973 8235fe04 Michael Hanselmann
  @param attr: Attribute name
974 8235fe04 Michael Hanselmann

975 8235fe04 Michael Hanselmann
  """
976 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
977 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
978 8235fe04 Michael Hanselmann
979 8235fe04 Michael Hanselmann
980 40b118d3 Iustin Pop
def _GetItemMaybeAttr(attr):
981 40b118d3 Iustin Pop
  """Returns a field function to return a not-None attribute of the item.
982 40b118d3 Iustin Pop

983 40b118d3 Iustin Pop
  If the value is None, then C{_FS_UNAVAIL} will be returned instead.
984 40b118d3 Iustin Pop

985 40b118d3 Iustin Pop
  @param attr: Attribute name
986 40b118d3 Iustin Pop

987 40b118d3 Iustin Pop
  """
988 40b118d3 Iustin Pop
  def _helper(_, obj):
989 40b118d3 Iustin Pop
    val = getattr(obj, attr)
990 40b118d3 Iustin Pop
    if val is None:
991 40b118d3 Iustin Pop
      return _FS_UNAVAIL
992 40b118d3 Iustin Pop
    else:
993 40b118d3 Iustin Pop
      return val
994 40b118d3 Iustin Pop
  return _helper
995 40b118d3 Iustin Pop
996 40b118d3 Iustin Pop
997 8930b0f0 Iustin Pop
def _GetNDParam(name):
998 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
999 8930b0f0 Iustin Pop

1000 8930b0f0 Iustin Pop
  """
1001 8930b0f0 Iustin Pop
  def _helper(ctx, _):
1002 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
1003 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
1004 8930b0f0 Iustin Pop
    else:
1005 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
1006 8930b0f0 Iustin Pop
  return _helper
1007 8930b0f0 Iustin Pop
1008 8930b0f0 Iustin Pop
1009 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
1010 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
1011 8930b0f0 Iustin Pop

1012 8930b0f0 Iustin Pop
  @param is_group: whether this is called at group or node level
1013 8930b0f0 Iustin Pop

1014 8930b0f0 Iustin Pop
  """
1015 8930b0f0 Iustin Pop
  if is_group:
1016 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
1017 8930b0f0 Iustin Pop
  else:
1018 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
1019 a6c7e2a2 Iustin Pop
  return [(_MakeField("ndp/%s" % name,
1020 a6c7e2a2 Iustin Pop
                      constants.NDS_PARAMETER_TITLES.get(name,
1021 a6c7e2a2 Iustin Pop
                                                         "ndp/%s" % name),
1022 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
1023 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
1024 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
1025 8930b0f0 Iustin Pop
1026 8930b0f0 Iustin Pop
1027 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
1028 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
1029 425e5bf0 Michael Hanselmann

1030 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1031 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1032 425e5bf0 Michael Hanselmann

1033 425e5bf0 Michael Hanselmann
  """
1034 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
1035 425e5bf0 Michael Hanselmann
1036 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
1037 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
1038 425e5bf0 Michael Hanselmann
    # Return right away
1039 425e5bf0 Michael Hanselmann
    return value
1040 425e5bf0 Michael Hanselmann
1041 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
1042 425e5bf0 Michael Hanselmann
  return convert(value)
1043 425e5bf0 Michael Hanselmann
1044 425e5bf0 Michael Hanselmann
1045 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
1046 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
1047 425e5bf0 Michael Hanselmann

1048 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1049 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1050 425e5bf0 Michael Hanselmann

1051 425e5bf0 Michael Hanselmann
  """
1052 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
1053 425e5bf0 Michael Hanselmann
1054 425e5bf0 Michael Hanselmann
1055 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
1056 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
1057 145bea54 Michael Hanselmann

1058 145bea54 Michael Hanselmann
  @type getter: callable
1059 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1060 145bea54 Michael Hanselmann

1061 145bea54 Michael Hanselmann
  """
1062 145bea54 Michael Hanselmann
  def fn(_, item):
1063 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1064 145bea54 Michael Hanselmann

1065 145bea54 Michael Hanselmann
    """
1066 145bea54 Michael Hanselmann
    timestamp = getter(item)
1067 145bea54 Michael Hanselmann
    if timestamp is None:
1068 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
1069 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1070 145bea54 Michael Hanselmann
    else:
1071 e2d188cc Iustin Pop
      return timestamp
1072 145bea54 Michael Hanselmann
1073 145bea54 Michael Hanselmann
  return fn
1074 145bea54 Michael Hanselmann
1075 145bea54 Michael Hanselmann
1076 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
1077 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
1078 145bea54 Michael Hanselmann

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

1081 145bea54 Michael Hanselmann
  """
1082 145bea54 Michael Hanselmann
  return [
1083 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
1084 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
1085 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
1086 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
1087 145bea54 Michael Hanselmann
    ]
1088 145bea54 Michael Hanselmann
1089 145bea54 Michael Hanselmann
1090 8235fe04 Michael Hanselmann
class NodeQueryData:
1091 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1092 8235fe04 Michael Hanselmann

1093 8235fe04 Michael Hanselmann
  """
1094 1c3231aa Thomas Thrainer
  def __init__(self, nodes, live_data, master_uuid, node_to_primary,
1095 da4a52a3 Thomas Thrainer
               node_to_secondary, inst_uuid_to_inst_name, groups, oob_support,
1096 da4a52a3 Thomas Thrainer
               cluster):
1097 8235fe04 Michael Hanselmann
    """Initializes this class.
1098 8235fe04 Michael Hanselmann

1099 8235fe04 Michael Hanselmann
    """
1100 8235fe04 Michael Hanselmann
    self.nodes = nodes
1101 8235fe04 Michael Hanselmann
    self.live_data = live_data
1102 1c3231aa Thomas Thrainer
    self.master_uuid = master_uuid
1103 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1104 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1105 da4a52a3 Thomas Thrainer
    self.inst_uuid_to_inst_name = inst_uuid_to_inst_name
1106 8235fe04 Michael Hanselmann
    self.groups = groups
1107 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1108 8572f1fe René Nussbaumer
    self.cluster = cluster
1109 8235fe04 Michael Hanselmann
1110 8235fe04 Michael Hanselmann
    # Used for individual rows
1111 8235fe04 Michael Hanselmann
    self.curlive_data = None
1112 8930b0f0 Iustin Pop
    self.ndparams = None
1113 8235fe04 Michael Hanselmann
1114 8235fe04 Michael Hanselmann
  def __iter__(self):
1115 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1116 8235fe04 Michael Hanselmann

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

1120 8235fe04 Michael Hanselmann
    """
1121 8235fe04 Michael Hanselmann
    for node in self.nodes:
1122 8930b0f0 Iustin Pop
      group = self.groups.get(node.group, None)
1123 8930b0f0 Iustin Pop
      if group is None:
1124 8930b0f0 Iustin Pop
        self.ndparams = None
1125 8930b0f0 Iustin Pop
      else:
1126 8930b0f0 Iustin Pop
        self.ndparams = self.cluster.FillND(node, group)
1127 8235fe04 Michael Hanselmann
      if self.live_data:
1128 1c3231aa Thomas Thrainer
        self.curlive_data = self.live_data.get(node.uuid, None)
1129 8235fe04 Michael Hanselmann
      else:
1130 8235fe04 Michael Hanselmann
        self.curlive_data = None
1131 8235fe04 Michael Hanselmann
      yield node
1132 8235fe04 Michael Hanselmann
1133 8235fe04 Michael Hanselmann
1134 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
1135 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
1136 111bf531 Michael Hanselmann
  "drained": ("Drained", QFT_BOOL, 0, "Whether node is drained"),
1137 111bf531 Michael Hanselmann
  "master_candidate": ("MasterC", QFT_BOOL, 0,
1138 79b2ca83 Michael Hanselmann
                       "Whether node is a master candidate"),
1139 111bf531 Michael Hanselmann
  "master_capable": ("MasterCapable", QFT_BOOL, 0,
1140 79b2ca83 Michael Hanselmann
                     "Whether node can become a master candidate"),
1141 111bf531 Michael Hanselmann
  "name": ("Node", QFT_TEXT, QFF_HOSTNAME, "Node name"),
1142 111bf531 Michael Hanselmann
  "offline": ("Offline", QFT_BOOL, 0, "Whether node is marked offline"),
1143 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Node"),
1144 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Node UUID"),
1145 111bf531 Michael Hanselmann
  "vm_capable": ("VMCapable", QFT_BOOL, 0, "Whether node can host instances"),
1146 8235fe04 Michael Hanselmann
  }
1147 8235fe04 Michael Hanselmann
1148 8235fe04 Michael Hanselmann
1149 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
1150 effab4ca Iustin Pop
# Note that none of these are available for non-vm_capable nodes
1151 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
1152 79b2ca83 Michael Hanselmann
  "bootid": ("BootID", QFT_TEXT, "bootid",
1153 79b2ca83 Michael Hanselmann
             "Random UUID renewed for each system reboot, can be used"
1154 79b2ca83 Michael Hanselmann
             " for detecting reboots by tracking changes"),
1155 79b2ca83 Michael Hanselmann
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes",
1156 79b2ca83 Michael Hanselmann
             "Number of NUMA domains on node (if exported by hypervisor)"),
1157 f43c898d Bernardo Dal Seno
  "cnos": ("CNOs", QFT_NUMBER, "cpu_dom0",
1158 f43c898d Bernardo Dal Seno
            "Number of logical processors used by the node OS (dom0 for Xen)"),
1159 79b2ca83 Michael Hanselmann
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets",
1160 79b2ca83 Michael Hanselmann
               "Number of physical CPU sockets (if exported by hypervisor)"),
1161 79b2ca83 Michael Hanselmann
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total", "Number of logical processors"),
1162 32389d91 Helga Velroyen
  "dfree": ("DFree", QFT_UNIT, "storage_free",
1163 32389d91 Helga Velroyen
            "Available storage space in storage unit"),
1164 32389d91 Helga Velroyen
  "dtotal": ("DTotal", QFT_UNIT, "storage_size",
1165 32389d91 Helga Velroyen
             "Total storage space in storage unit used for instance disk"
1166 79b2ca83 Michael Hanselmann
             " allocation"),
1167 06fb92cf Bernardo Dal Seno
  "spfree": ("SpFree", QFT_NUMBER, "spindles_free",
1168 06fb92cf Bernardo Dal Seno
             "Available spindles in volume group (exclusive storage only)"),
1169 06fb92cf Bernardo Dal Seno
  "sptotal": ("SpTotal", QFT_NUMBER, "spindles_total",
1170 06fb92cf Bernardo Dal Seno
              "Total spindles in volume group (exclusive storage only)"),
1171 79b2ca83 Michael Hanselmann
  "mfree": ("MFree", QFT_UNIT, "memory_free",
1172 79b2ca83 Michael Hanselmann
            "Memory available for instance allocations"),
1173 79b2ca83 Michael Hanselmann
  "mnode": ("MNode", QFT_UNIT, "memory_dom0",
1174 79b2ca83 Michael Hanselmann
            "Amount of memory used by node (dom0 for Xen)"),
1175 79b2ca83 Michael Hanselmann
  "mtotal": ("MTotal", QFT_UNIT, "memory_total",
1176 79b2ca83 Michael Hanselmann
             "Total amount of memory of physical machine"),
1177 8235fe04 Michael Hanselmann
  }
1178 8235fe04 Michael Hanselmann
1179 8235fe04 Michael Hanselmann
1180 8572f1fe René Nussbaumer
def _GetGroup(cb):
1181 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
1182 8572f1fe René Nussbaumer

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

1185 8572f1fe René Nussbaumer
  """
1186 8572f1fe René Nussbaumer
  def fn(ctx, node):
1187 8572f1fe René Nussbaumer
    """Get group data for a node.
1188 8572f1fe René Nussbaumer

1189 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1190 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1191 8572f1fe René Nussbaumer
    @param inst: Node object
1192 8572f1fe René Nussbaumer

1193 8572f1fe René Nussbaumer
    """
1194 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1195 8572f1fe René Nussbaumer
    if ng is None:
1196 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1197 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1198 8572f1fe René Nussbaumer
1199 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1200 8572f1fe René Nussbaumer
1201 8572f1fe René Nussbaumer
  return fn
1202 8572f1fe René Nussbaumer
1203 8572f1fe René Nussbaumer
1204 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1205 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1206 8235fe04 Michael Hanselmann

1207 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1208 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1209 8235fe04 Michael Hanselmann
  @param node: Node object
1210 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1211 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1212 8235fe04 Michael Hanselmann

1213 8235fe04 Michael Hanselmann
  """
1214 e2d188cc Iustin Pop
  return ng.name
1215 8235fe04 Michael Hanselmann
1216 8235fe04 Michael Hanselmann
1217 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1218 52b5d286 René Nussbaumer
  """Returns the node powered state
1219 52b5d286 René Nussbaumer

1220 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1221 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1222 52b5d286 René Nussbaumer
  @param node: Node object
1223 52b5d286 René Nussbaumer

1224 52b5d286 René Nussbaumer
  """
1225 1c3231aa Thomas Thrainer
  if ctx.oob_support[node.uuid]:
1226 e2d188cc Iustin Pop
    return node.powered
1227 52b5d286 René Nussbaumer
1228 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1229 52b5d286 René Nussbaumer
1230 52b5d286 René Nussbaumer
1231 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1232 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1233 8572f1fe René Nussbaumer

1234 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1235 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1236 8572f1fe René Nussbaumer
  @param node: Node object
1237 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1238 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1239 8572f1fe René Nussbaumer

1240 8572f1fe René Nussbaumer
  """
1241 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1242 8572f1fe René Nussbaumer
1243 8572f1fe René Nussbaumer
1244 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1245 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1246 8235fe04 Michael Hanselmann

1247 8235fe04 Michael Hanselmann
  @param field: Live field name
1248 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1249 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1250 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1251 a6070ef7 Michael Hanselmann
  @param node: Node object
1252 8235fe04 Michael Hanselmann

1253 8235fe04 Michael Hanselmann
  """
1254 a6070ef7 Michael Hanselmann
  if node.offline:
1255 e2d188cc Iustin Pop
    return _FS_OFFLINE
1256 a6070ef7 Michael Hanselmann
1257 effab4ca Iustin Pop
  if not node.vm_capable:
1258 effab4ca Iustin Pop
    return _FS_UNAVAIL
1259 effab4ca Iustin Pop
1260 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1261 e2d188cc Iustin Pop
    return _FS_NODATA
1262 8235fe04 Michael Hanselmann
1263 b4600d4f Michael Hanselmann
  return _GetStatsField(field, kind, ctx.curlive_data)
1264 b4600d4f Michael Hanselmann
1265 b4600d4f Michael Hanselmann
1266 b4600d4f Michael Hanselmann
def _GetStatsField(field, kind, data):
1267 b4600d4f Michael Hanselmann
  """Gets a value from live statistics.
1268 b4600d4f Michael Hanselmann

1269 b4600d4f Michael Hanselmann
  If the value is not found, L{_FS_UNAVAIL} is returned. If the field kind is
1270 b4600d4f Michael Hanselmann
  numeric a conversion to integer is attempted. If that fails, L{_FS_UNAVAIL}
1271 b4600d4f Michael Hanselmann
  is returned.
1272 b4600d4f Michael Hanselmann

1273 b4600d4f Michael Hanselmann
  @param field: Live field name
1274 b4600d4f Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1275 b4600d4f Michael Hanselmann
  @type data: dict
1276 b4600d4f Michael Hanselmann
  @param data: Statistics
1277 b4600d4f Michael Hanselmann

1278 b4600d4f Michael Hanselmann
  """
1279 8235fe04 Michael Hanselmann
  try:
1280 b4600d4f Michael Hanselmann
    value = data[field]
1281 8235fe04 Michael Hanselmann
  except KeyError:
1282 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1283 8235fe04 Michael Hanselmann
1284 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1285 e2d188cc Iustin Pop
    return value
1286 8235fe04 Michael Hanselmann
1287 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1288 8235fe04 Michael Hanselmann
1289 8235fe04 Michael Hanselmann
  # Try to convert into number
1290 8235fe04 Michael Hanselmann
  try:
1291 e2d188cc Iustin Pop
    return int(value)
1292 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1293 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1294 b4600d4f Michael Hanselmann
                      field, value)
1295 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1296 8235fe04 Michael Hanselmann
1297 8235fe04 Michael Hanselmann
1298 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1299 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1300 54ac87c0 Michael Hanselmann

1301 54ac87c0 Michael Hanselmann
  """
1302 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1303 54ac87c0 Michael Hanselmann
1304 54ac87c0 Michael Hanselmann
  if hv_state is None:
1305 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1306 54ac87c0 Michael Hanselmann
1307 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1308 54ac87c0 Michael Hanselmann
1309 54ac87c0 Michael Hanselmann
1310 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1311 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1312 54ac87c0 Michael Hanselmann

1313 54ac87c0 Michael Hanselmann
  """
1314 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1315 54ac87c0 Michael Hanselmann
1316 54ac87c0 Michael Hanselmann
  if disk_state is None:
1317 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1318 54ac87c0 Michael Hanselmann
1319 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1320 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1321 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1322 54ac87c0 Michael Hanselmann
1323 54ac87c0 Michael Hanselmann
1324 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1325 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1326 8235fe04 Michael Hanselmann

1327 8235fe04 Michael Hanselmann
  """
1328 8235fe04 Michael Hanselmann
  fields = [
1329 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1330 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1331 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1332 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1333 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1334 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1335 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1336 1c3231aa Thomas Thrainer
     NQ_CONFIG, 0, lambda ctx, node: node.uuid == ctx.master_uuid),
1337 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1338 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1339 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1340 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1341 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1342 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1343 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1344 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1345 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1346 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1347 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1348 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1349 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1350 54ac87c0 Michael Hanselmann
    (_MakeField("hv_state", "HypervisorState", QFT_OTHER, "Hypervisor state"),
1351 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeHvState),
1352 54ac87c0 Michael Hanselmann
    (_MakeField("disk_state", "DiskState", QFT_OTHER, "Disk state"),
1353 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeDiskState),
1354 8235fe04 Michael Hanselmann
    ]
1355 8235fe04 Michael Hanselmann
1356 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(False))
1357 8930b0f0 Iustin Pop
1358 79b2ca83 Michael Hanselmann
  # Node role
1359 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1360 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1361 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1362 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1363 a9310b2f Iustin Pop
              " \"%s\" for regular, \"%s\" for drained, \"%s\" for offline" %
1364 79b2ca83 Michael Hanselmann
              role_values)
1365 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1366 1c3231aa Thomas Thrainer
                 lambda ctx, node: _GetNodeRole(node, ctx.master_uuid)))
1367 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1368 79b2ca83 Michael Hanselmann
1369 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1370 1c3231aa Thomas Thrainer
    return lambda ctx, node: len(getter(ctx)[node.uuid])
1371 8235fe04 Michael Hanselmann
1372 8235fe04 Michael Hanselmann
  def _GetList(getter):
1373 da4a52a3 Thomas Thrainer
    return lambda ctx, node: utils.NiceSort(
1374 da4a52a3 Thomas Thrainer
                               [ctx.inst_uuid_to_inst_name[uuid]
1375 da4a52a3 Thomas Thrainer
                                for uuid in getter(ctx)[node.uuid]])
1376 8235fe04 Michael Hanselmann
1377 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1378 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1379 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1380 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1381 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1382 8235fe04 Michael Hanselmann
    fields.extend([
1383 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1384 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1385 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1386 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1387 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1388 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1389 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1390 8235fe04 Michael Hanselmann
      ])
1391 8235fe04 Michael Hanselmann
1392 8235fe04 Michael Hanselmann
  # Add simple fields
1393 111bf531 Michael Hanselmann
  fields.extend([
1394 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1395 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()])
1396 8235fe04 Michael Hanselmann
1397 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1398 8235fe04 Michael Hanselmann
  fields.extend([
1399 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1400 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1401 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()])
1402 8235fe04 Michael Hanselmann
1403 145bea54 Michael Hanselmann
  # Add timestamps
1404 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1405 145bea54 Michael Hanselmann
1406 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1407 8235fe04 Michael Hanselmann
1408 8235fe04 Michael Hanselmann
1409 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1410 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1411 1c8addc6 Michael Hanselmann

1412 1c8addc6 Michael Hanselmann
  """
1413 1c3231aa Thomas Thrainer
  def __init__(self, instances, cluster, disk_usage, offline_node_uuids,
1414 1c3231aa Thomas Thrainer
               bad_node_uuids, live_data, wrongnode_inst, console, nodes,
1415 1c3231aa Thomas Thrainer
               groups, networks):
1416 1c8addc6 Michael Hanselmann
    """Initializes this class.
1417 1c8addc6 Michael Hanselmann

1418 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1419 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1420 da4a52a3 Thomas Thrainer
    @type disk_usage: dict; instance UUID as key
1421 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1422 1c3231aa Thomas Thrainer
    @type offline_node_uuids: list of strings
1423 1c3231aa Thomas Thrainer
    @param offline_node_uuids: List of offline nodes
1424 1c3231aa Thomas Thrainer
    @type bad_node_uuids: list of strings
1425 1c3231aa Thomas Thrainer
    @param bad_node_uuids: List of faulty nodes
1426 da4a52a3 Thomas Thrainer
    @type live_data: dict; instance UUID as key
1427 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1428 e431074f René Nussbaumer
    @type wrongnode_inst: set
1429 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1430 da4a52a3 Thomas Thrainer
    @type console: dict; instance UUID as key
1431 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1432 1c3231aa Thomas Thrainer
    @type nodes: dict; node UUID as key
1433 fab9573b Michael Hanselmann
    @param nodes: Node objects
1434 f98e1175 Dimitris Aragiorgis
    @type networks: dict; net_uuid as key
1435 f98e1175 Dimitris Aragiorgis
    @param networks: Network objects
1436 1c8addc6 Michael Hanselmann

1437 1c8addc6 Michael Hanselmann
    """
1438 1c3231aa Thomas Thrainer
    assert len(set(bad_node_uuids) & set(offline_node_uuids)) == \
1439 1c3231aa Thomas Thrainer
           len(offline_node_uuids), \
1440 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1441 1c3231aa Thomas Thrainer
    assert not (set(live_data.keys()) & set(bad_node_uuids)), \
1442 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1443 1c8addc6 Michael Hanselmann
1444 1c8addc6 Michael Hanselmann
    self.instances = instances
1445 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1446 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1447 1c3231aa Thomas Thrainer
    self.offline_nodes = offline_node_uuids
1448 1c3231aa Thomas Thrainer
    self.bad_nodes = bad_node_uuids
1449 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1450 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1451 5d28cb6f Michael Hanselmann
    self.console = console
1452 fab9573b Michael Hanselmann
    self.nodes = nodes
1453 fab9573b Michael Hanselmann
    self.groups = groups
1454 f98e1175 Dimitris Aragiorgis
    self.networks = networks
1455 1c8addc6 Michael Hanselmann
1456 1c8addc6 Michael Hanselmann
    # Used for individual rows
1457 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1458 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1459 7c670076 Michael Hanselmann
    self.inst_osparams = None
1460 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1461 1c8addc6 Michael Hanselmann
1462 1c8addc6 Michael Hanselmann
  def __iter__(self):
1463 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1464 1c8addc6 Michael Hanselmann

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

1468 1c8addc6 Michael Hanselmann
    """
1469 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1470 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1471 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1472 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1473 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1474 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1475 1c8addc6 Michael Hanselmann
1476 1c8addc6 Michael Hanselmann
      yield inst
1477 1c8addc6 Michael Hanselmann
1478 1c8addc6 Michael Hanselmann
1479 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1480 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1481 1c8addc6 Michael Hanselmann

1482 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1483 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1484 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1485 1c8addc6 Michael Hanselmann

1486 1c8addc6 Michael Hanselmann
  """
1487 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1488 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1489 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1490 e2d188cc Iustin Pop
    return _FS_NODATA
1491 1c8addc6 Michael Hanselmann
  else:
1492 da4a52a3 Thomas Thrainer
    return bool(ctx.live_data.get(inst.uuid))
1493 1c8addc6 Michael Hanselmann
1494 1c8addc6 Michael Hanselmann
1495 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1496 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1497 1c8addc6 Michael Hanselmann

1498 1c8addc6 Michael Hanselmann
  @type name: string
1499 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1500 1c8addc6 Michael Hanselmann

1501 1c8addc6 Michael Hanselmann
  """
1502 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1503 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1504 1c8addc6 Michael Hanselmann

1505 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1506 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1507 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1508 1c8addc6 Michael Hanselmann

1509 1c8addc6 Michael Hanselmann
    """
1510 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1511 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1512 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1513 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1514 e2d188cc Iustin Pop
      return _FS_NODATA
1515 1c8addc6 Michael Hanselmann
1516 da4a52a3 Thomas Thrainer
    if inst.uuid in ctx.live_data:
1517 da4a52a3 Thomas Thrainer
      data = ctx.live_data[inst.uuid]
1518 1c8addc6 Michael Hanselmann
      if name in data:
1519 e2d188cc Iustin Pop
        return data[name]
1520 1c8addc6 Michael Hanselmann
1521 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1522 1c8addc6 Michael Hanselmann
1523 1c8addc6 Michael Hanselmann
  return fn
1524 1c8addc6 Michael Hanselmann
1525 1c8addc6 Michael Hanselmann
1526 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1527 1c8addc6 Michael Hanselmann
  """Get instance status.
1528 1c8addc6 Michael Hanselmann

1529 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1530 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1531 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1532 1c8addc6 Michael Hanselmann

1533 1c8addc6 Michael Hanselmann
  """
1534 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1535 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1536 1c8addc6 Michael Hanselmann
1537 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1538 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1539 1c8addc6 Michael Hanselmann
1540 da4a52a3 Thomas Thrainer
  if bool(ctx.live_data.get(inst.uuid)):
1541 da4a52a3 Thomas Thrainer
    if inst.uuid in ctx.wrongnode_inst:
1542 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1543 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1544 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1545 1c8addc6 Michael Hanselmann
    else:
1546 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1547 1c8addc6 Michael Hanselmann
1548 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1549 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1550 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1551 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1552 1c8addc6 Michael Hanselmann
1553 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1554 1c8addc6 Michael Hanselmann
1555 1c8addc6 Michael Hanselmann
1556 3fe22abd Christos Stavrakakis
def _GetInstDisk(index, cb):
1557 3fe22abd Christos Stavrakakis
  """Build function for calling another function with an instance Disk.
1558 1c8addc6 Michael Hanselmann

1559 1c8addc6 Michael Hanselmann
  @type index: int
1560 1c8addc6 Michael Hanselmann
  @param index: Disk index
1561 3fe22abd Christos Stavrakakis
  @type cb: callable
1562 3fe22abd Christos Stavrakakis
  @param cb: Callback
1563 1c8addc6 Michael Hanselmann

1564 1c8addc6 Michael Hanselmann
  """
1565 3fe22abd Christos Stavrakakis
  def fn(ctx, inst):
1566 3fe22abd Christos Stavrakakis
    """Call helper function with instance Disk.
1567 1c8addc6 Michael Hanselmann

1568 3fe22abd Christos Stavrakakis
    @type ctx: L{InstanceQueryData}
1569 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1570 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1571 1c8addc6 Michael Hanselmann

1572 1c8addc6 Michael Hanselmann
    """
1573 1c8addc6 Michael Hanselmann
    try:
1574 3fe22abd Christos Stavrakakis
      nic = inst.disks[index]
1575 1c8addc6 Michael Hanselmann
    except IndexError:
1576 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1577 1c8addc6 Michael Hanselmann
1578 3fe22abd Christos Stavrakakis
    return cb(ctx, index, nic)
1579 3fe22abd Christos Stavrakakis
1580 1c8addc6 Michael Hanselmann
  return fn
1581 1c8addc6 Michael Hanselmann
1582 1c8addc6 Michael Hanselmann
1583 3fe22abd Christos Stavrakakis
def _GetInstDiskSize(ctx, _, disk): # pylint: disable=W0613
1584 3fe22abd Christos Stavrakakis
  """Get a Disk's size.
1585 3fe22abd Christos Stavrakakis

1586 3fe22abd Christos Stavrakakis
  @type ctx: L{InstanceQueryData}
1587 3fe22abd Christos Stavrakakis
  @type disk: L{objects.Disk}
1588 3fe22abd Christos Stavrakakis
  @param disk: The Disk object
1589 3fe22abd Christos Stavrakakis

1590 3fe22abd Christos Stavrakakis
  """
1591 3fe22abd Christos Stavrakakis
  if disk.size is None:
1592 3fe22abd Christos Stavrakakis
    return _FS_UNAVAIL
1593 3fe22abd Christos Stavrakakis
  else:
1594 3fe22abd Christos Stavrakakis
    return disk.size
1595 3fe22abd Christos Stavrakakis
1596 3fe22abd Christos Stavrakakis
1597 0e514de1 Bernardo Dal Seno
def _GetInstDiskSpindles(ctx, _, disk): # pylint: disable=W0613
1598 0e514de1 Bernardo Dal Seno
  """Get a Disk's spindles.
1599 0e514de1 Bernardo Dal Seno

1600 0e514de1 Bernardo Dal Seno
  @type disk: L{objects.Disk}
1601 0e514de1 Bernardo Dal Seno
  @param disk: The Disk object
1602 0e514de1 Bernardo Dal Seno

1603 0e514de1 Bernardo Dal Seno
  """
1604 0e514de1 Bernardo Dal Seno
  if disk.spindles is None:
1605 0e514de1 Bernardo Dal Seno
    return _FS_UNAVAIL
1606 0e514de1 Bernardo Dal Seno
  else:
1607 0e514de1 Bernardo Dal Seno
    return disk.spindles
1608 0e514de1 Bernardo Dal Seno
1609 0e514de1 Bernardo Dal Seno
1610 3fe22abd Christos Stavrakakis
def _GetInstDeviceName(ctx, _, device): # pylint: disable=W0613
1611 3fe22abd Christos Stavrakakis
  """Get a Device's Name.
1612 3fe22abd Christos Stavrakakis

1613 3fe22abd Christos Stavrakakis
  @type ctx: L{InstanceQueryData}
1614 3fe22abd Christos Stavrakakis
  @type device: L{objects.NIC} or L{objects.Disk}
1615 3fe22abd Christos Stavrakakis
  @param device: The NIC or Disk object
1616 3fe22abd Christos Stavrakakis

1617 3fe22abd Christos Stavrakakis
  """
1618 3fe22abd Christos Stavrakakis
  if device.name is None:
1619 3fe22abd Christos Stavrakakis
    return _FS_UNAVAIL
1620 3fe22abd Christos Stavrakakis
  else:
1621 3fe22abd Christos Stavrakakis
    return device.name
1622 3fe22abd Christos Stavrakakis
1623 3fe22abd Christos Stavrakakis
1624 3fe22abd Christos Stavrakakis
def _GetInstDeviceUUID(ctx, _, device): # pylint: disable=W0613
1625 3fe22abd Christos Stavrakakis
  """Get a Device's UUID.
1626 3fe22abd Christos Stavrakakis

1627 3fe22abd Christos Stavrakakis
  @type ctx: L{InstanceQueryData}
1628 3fe22abd Christos Stavrakakis
  @type device: L{objects.NIC} or L{objects.Disk}
1629 3fe22abd Christos Stavrakakis
  @param device: The NIC or Disk object
1630 3fe22abd Christos Stavrakakis

1631 3fe22abd Christos Stavrakakis
  """
1632 3fe22abd Christos Stavrakakis
  if device.uuid is None:
1633 3fe22abd Christos Stavrakakis
    return _FS_UNAVAIL
1634 3fe22abd Christos Stavrakakis
  else:
1635 3fe22abd Christos Stavrakakis
    return device.uuid
1636 3fe22abd Christos Stavrakakis
1637 3fe22abd Christos Stavrakakis
1638 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1639 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1640 1c8addc6 Michael Hanselmann

1641 1c8addc6 Michael Hanselmann
  @type index: int
1642 1c8addc6 Michael Hanselmann
  @param index: NIC index
1643 1c8addc6 Michael Hanselmann
  @type cb: callable
1644 1c8addc6 Michael Hanselmann
  @param cb: Callback
1645 1c8addc6 Michael Hanselmann

1646 1c8addc6 Michael Hanselmann
  """
1647 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1648 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1649 1c8addc6 Michael Hanselmann

1650 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1651 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1652 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1653 1c8addc6 Michael Hanselmann

1654 1c8addc6 Michael Hanselmann
    """
1655 1c8addc6 Michael Hanselmann
    try:
1656 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1657 1c8addc6 Michael Hanselmann
    except IndexError:
1658 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1659 1c8addc6 Michael Hanselmann
1660 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1661 1c8addc6 Michael Hanselmann
1662 1c8addc6 Michael Hanselmann
  return fn
1663 1c8addc6 Michael Hanselmann
1664 1c8addc6 Michael Hanselmann
1665 f98e1175 Dimitris Aragiorgis
def _GetInstNicNetworkName(ctx, _, nic): # pylint: disable=W0613
1666 f98e1175 Dimitris Aragiorgis
  """Get a NIC's Network.
1667 f98e1175 Dimitris Aragiorgis

1668 f98e1175 Dimitris Aragiorgis
  @type ctx: L{InstanceQueryData}
1669 f98e1175 Dimitris Aragiorgis
  @type nic: L{objects.NIC}
1670 f98e1175 Dimitris Aragiorgis
  @param nic: NIC object
1671 f98e1175 Dimitris Aragiorgis

1672 f98e1175 Dimitris Aragiorgis
  """
1673 f98e1175 Dimitris Aragiorgis
  if nic.network is None:
1674 f98e1175 Dimitris Aragiorgis
    return _FS_UNAVAIL
1675 f98e1175 Dimitris Aragiorgis
  else:
1676 f98e1175 Dimitris Aragiorgis
    return ctx.networks[nic.network].name
1677 f98e1175 Dimitris Aragiorgis
1678 f98e1175 Dimitris Aragiorgis
1679 d4117a72 Apollon Oikonomopoulos
def _GetInstNicNetwork(ctx, _, nic): # pylint: disable=W0613
1680 d4117a72 Apollon Oikonomopoulos
  """Get a NIC's Network.
1681 d4117a72 Apollon Oikonomopoulos

1682 d4117a72 Apollon Oikonomopoulos
  @type ctx: L{InstanceQueryData}
1683 d4117a72 Apollon Oikonomopoulos
  @type nic: L{objects.NIC}
1684 d4117a72 Apollon Oikonomopoulos
  @param nic: NIC object
1685 d4117a72 Apollon Oikonomopoulos

1686 d4117a72 Apollon Oikonomopoulos
  """
1687 d4117a72 Apollon Oikonomopoulos
  if nic.network is None:
1688 d4117a72 Apollon Oikonomopoulos
    return _FS_UNAVAIL
1689 d4117a72 Apollon Oikonomopoulos
  else:
1690 d4117a72 Apollon Oikonomopoulos
    return nic.network
1691 d4117a72 Apollon Oikonomopoulos
1692 d4117a72 Apollon Oikonomopoulos
1693 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1694 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1695 1c8addc6 Michael Hanselmann

1696 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1697 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1698 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1699 1c8addc6 Michael Hanselmann

1700 1c8addc6 Michael Hanselmann
  """
1701 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1702 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1703 1c8addc6 Michael Hanselmann
  else:
1704 e2d188cc Iustin Pop
    return nic.ip
1705 1c8addc6 Michael Hanselmann
1706 1c8addc6 Michael Hanselmann
1707 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1708 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1709 1c8addc6 Michael Hanselmann

1710 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1711 1c8addc6 Michael Hanselmann
  @type index: int
1712 1c8addc6 Michael Hanselmann
  @param index: NIC index
1713 1c8addc6 Michael Hanselmann

1714 1c8addc6 Michael Hanselmann
  """
1715 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1716 1c8addc6 Michael Hanselmann
1717 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1718 1c8addc6 Michael Hanselmann
1719 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1720 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1721 1c8addc6 Michael Hanselmann
  else:
1722 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1723 1c8addc6 Michael Hanselmann
1724 1c8addc6 Michael Hanselmann
1725 f98e1175 Dimitris Aragiorgis
def _GetInstAllNicNetworkNames(ctx, inst):
1726 f98e1175 Dimitris Aragiorgis
  """Get all network names for an instance.
1727 f98e1175 Dimitris Aragiorgis

1728 f98e1175 Dimitris Aragiorgis
  @type ctx: L{InstanceQueryData}
1729 f98e1175 Dimitris Aragiorgis
  @type inst: L{objects.Instance}
1730 f98e1175 Dimitris Aragiorgis
  @param inst: Instance object
1731 f98e1175 Dimitris Aragiorgis

1732 f98e1175 Dimitris Aragiorgis
  """
1733 f98e1175 Dimitris Aragiorgis
  result = []
1734 f98e1175 Dimitris Aragiorgis
1735 f98e1175 Dimitris Aragiorgis
  for nic in inst.nics:
1736 f98e1175 Dimitris Aragiorgis
    name = None
1737 f98e1175 Dimitris Aragiorgis
    if nic.network:
1738 f98e1175 Dimitris Aragiorgis
      name = ctx.networks[nic.network].name
1739 f98e1175 Dimitris Aragiorgis
    result.append(name)
1740 f98e1175 Dimitris Aragiorgis
1741 f98e1175 Dimitris Aragiorgis
  assert len(result) == len(inst.nics)
1742 f98e1175 Dimitris Aragiorgis
1743 f98e1175 Dimitris Aragiorgis
  return result
1744 f98e1175 Dimitris Aragiorgis
1745 f98e1175 Dimitris Aragiorgis
1746 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1747 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1748 1c8addc6 Michael Hanselmann

1749 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1750 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1751 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1752 1c8addc6 Michael Hanselmann

1753 1c8addc6 Michael Hanselmann
  """
1754 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1755 1c8addc6 Michael Hanselmann
1756 1c8addc6 Michael Hanselmann
  result = []
1757 1c8addc6 Michael Hanselmann
1758 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1759 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1760 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1761 1c8addc6 Michael Hanselmann
    else:
1762 1c8addc6 Michael Hanselmann
      result.append(None)
1763 1c8addc6 Michael Hanselmann
1764 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1765 1c8addc6 Michael Hanselmann
1766 e2d188cc Iustin Pop
  return result
1767 1c8addc6 Michael Hanselmann
1768 1c8addc6 Michael Hanselmann
1769 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1770 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1771 1c8addc6 Michael Hanselmann

1772 1c8addc6 Michael Hanselmann
  @type name: string
1773 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1774 1c8addc6 Michael Hanselmann

1775 1c8addc6 Michael Hanselmann
  """
1776 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1777 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1778 1c8addc6 Michael Hanselmann

1779 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1780 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1781 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1782 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1783 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1784 1c8addc6 Michael Hanselmann

1785 1c8addc6 Michael Hanselmann
    """
1786 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1787 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1788 1c8addc6 Michael Hanselmann
1789 1c8addc6 Michael Hanselmann
  return fn
1790 1c8addc6 Michael Hanselmann
1791 1c8addc6 Michael Hanselmann
1792 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1793 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1794 1c8addc6 Michael Hanselmann

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

1798 1c8addc6 Michael Hanselmann
  """
1799 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1800 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1801 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1802 1c8addc6 Michael Hanselmann
1803 1c8addc6 Michael Hanselmann
  fields = [
1804 1c8addc6 Michael Hanselmann
    # All NICs
1805 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1806 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1807 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1808 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1809 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1810 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1811 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1812 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1813 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1814 3fe22abd Christos Stavrakakis
    (_MakeField("nic.names", "NIC_Names", QFT_OTHER,
1815 3fe22abd Christos Stavrakakis
                "List containing each network interface's name"),
1816 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [nic.name for nic in inst.nics]),
1817 3fe22abd Christos Stavrakakis
    (_MakeField("nic.uuids", "NIC_UUIDs", QFT_OTHER,
1818 3fe22abd Christos Stavrakakis
                "List containing each network interface's UUID"),
1819 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [nic.uuid for nic in inst.nics]),
1820 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1821 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1822 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1823 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1824 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1825 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1826 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1827 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1828 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1829 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1830 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1831 d4117a72 Apollon Oikonomopoulos
    (_MakeField("nic.networks", "NIC_networks", QFT_OTHER,
1832 d4117a72 Apollon Oikonomopoulos
                "List containing each interface's network"), IQ_CONFIG, 0,
1833 d4117a72 Apollon Oikonomopoulos
     lambda ctx, inst: [nic.network for nic in inst.nics]),
1834 f98e1175 Dimitris Aragiorgis
    (_MakeField("nic.networks.names", "NIC_networks_names", QFT_OTHER,
1835 f98e1175 Dimitris Aragiorgis
                "List containing each interface's network"),
1836 f98e1175 Dimitris Aragiorgis
     IQ_NETWORKS, 0, _GetInstAllNicNetworkNames)
1837 1c8addc6 Michael Hanselmann
    ]
1838 1c8addc6 Michael Hanselmann
1839 1c8addc6 Michael Hanselmann
  # NICs by number
1840 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1841 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1842 1c8addc6 Michael Hanselmann
    fields.extend([
1843 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1844 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1845 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1846 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1847 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1848 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1849 3fe22abd Christos Stavrakakis
      (_MakeField("nic.name/%s" % i, "NicName/%s" % i, QFT_TEXT,
1850 3fe22abd Christos Stavrakakis
                  "Name address of %s network interface" % numtext),
1851 3fe22abd Christos Stavrakakis
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstDeviceName)),
1852 3fe22abd Christos Stavrakakis
      (_MakeField("nic.uuid/%s" % i, "NicUUID/%s" % i, QFT_TEXT,
1853 3fe22abd Christos Stavrakakis
                  "UUID address of %s network interface" % numtext),
1854 3fe22abd Christos Stavrakakis
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstDeviceUUID)),
1855 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1856 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1857 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1858 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1859 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1860 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1861 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1862 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1863 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1864 d4117a72 Apollon Oikonomopoulos
      (_MakeField("nic.network/%s" % i, "NicNetwork/%s" % i, QFT_TEXT,
1865 d4117a72 Apollon Oikonomopoulos
                  "Network of %s network interface" % numtext),
1866 d4117a72 Apollon Oikonomopoulos
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicNetwork)),
1867 f98e1175 Dimitris Aragiorgis
      (_MakeField("nic.network.name/%s" % i, "NicNetworkName/%s" % i, QFT_TEXT,
1868 f98e1175 Dimitris Aragiorgis
                  "Network name of %s network interface" % numtext),
1869 f98e1175 Dimitris Aragiorgis
       IQ_NETWORKS, 0, _GetInstNic(i, _GetInstNicNetworkName)),
1870 1c8addc6 Michael Hanselmann
      ])
1871 1c8addc6 Michael Hanselmann
1872 4cc4d1fa Michael Hanselmann
  aliases = [
1873 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1874 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1875 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1876 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1877 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1878 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1879 d4117a72 Apollon Oikonomopoulos
    ("nic_network", "nic.network/0"),
1880 4cc4d1fa Michael Hanselmann
    ]
1881 4cc4d1fa Michael Hanselmann
1882 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1883 1c8addc6 Michael Hanselmann
1884 1c8addc6 Michael Hanselmann
1885 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1886 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1887 1c8addc6 Michael Hanselmann

1888 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1889 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1890 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1891 1c8addc6 Michael Hanselmann

1892 1c8addc6 Michael Hanselmann
  """
1893 da4a52a3 Thomas Thrainer
  usage = ctx.disk_usage[inst.uuid]
1894 1c8addc6 Michael Hanselmann
1895 1c8addc6 Michael Hanselmann
  if usage is None:
1896 1c8addc6 Michael Hanselmann
    usage = 0
1897 1c8addc6 Michael Hanselmann
1898 e2d188cc Iustin Pop
  return usage
1899 1c8addc6 Michael Hanselmann
1900 1c8addc6 Michael Hanselmann
1901 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1902 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1903 5d28cb6f Michael Hanselmann

1904 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1905 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1906 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1907 5d28cb6f Michael Hanselmann

1908 5d28cb6f Michael Hanselmann
  """
1909 da4a52a3 Thomas Thrainer
  consinfo = ctx.console[inst.uuid]
1910 5d28cb6f Michael Hanselmann
1911 5d28cb6f Michael Hanselmann
  if consinfo is None:
1912 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1913 5d28cb6f Michael Hanselmann
1914 5d28cb6f Michael Hanselmann
  return consinfo
1915 5d28cb6f Michael Hanselmann
1916 5d28cb6f Michael Hanselmann
1917 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1918 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1919 1c8addc6 Michael Hanselmann

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

1922 1c8addc6 Michael Hanselmann
  """
1923 1c8addc6 Michael Hanselmann
  fields = [
1924 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1925 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1926 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1927 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1928 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1929 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1930 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1931 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1932 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1933 0e514de1 Bernardo Dal Seno
    (_MakeField("disk.spindles", "Disk_spindles", QFT_OTHER,
1934 0e514de1 Bernardo Dal Seno
                "List of disk spindles"),
1935 0e514de1 Bernardo Dal Seno
     IQ_CONFIG, 0, lambda ctx, inst: [disk.spindles for disk in inst.disks]),
1936 3fe22abd Christos Stavrakakis
    (_MakeField("disk.names", "Disk_names", QFT_OTHER, "List of disk names"),
1937 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [disk.name for disk in inst.disks]),
1938 3fe22abd Christos Stavrakakis
    (_MakeField("disk.uuids", "Disk_UUIDs", QFT_OTHER, "List of disk UUIDs"),
1939 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [disk.uuid for disk in inst.disks]),
1940 1c8addc6 Michael Hanselmann
    ]
1941 1c8addc6 Michael Hanselmann
1942 1c8addc6 Michael Hanselmann
  # Disks by number
1943 3fe22abd Christos Stavrakakis
  for i in range(constants.MAX_DISKS):
1944 3fe22abd Christos Stavrakakis
    numtext = utils.FormatOrdinal(i + 1)
1945 3fe22abd Christos Stavrakakis
    fields.extend([
1946 3fe22abd Christos Stavrakakis
        (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1947 3fe22abd Christos Stavrakakis
                    "Disk size of %s disk" % numtext),
1948 3fe22abd Christos Stavrakakis
        IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDiskSize)),
1949 0e514de1 Bernardo Dal Seno
        (_MakeField("disk.spindles/%s" % i, "DiskSpindles/%s" % i, QFT_NUMBER,
1950 0e514de1 Bernardo Dal Seno
                    "Spindles of %s disk" % numtext),
1951 0e514de1 Bernardo Dal Seno
         IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDiskSpindles)),
1952 3fe22abd Christos Stavrakakis
        (_MakeField("disk.name/%s" % i, "DiskName/%s" % i, QFT_TEXT,
1953 3fe22abd Christos Stavrakakis
                    "Name of %s disk" % numtext),
1954 3fe22abd Christos Stavrakakis
        IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDeviceName)),
1955 3fe22abd Christos Stavrakakis
        (_MakeField("disk.uuid/%s" % i, "DiskUUID/%s" % i, QFT_TEXT,
1956 3fe22abd Christos Stavrakakis
                    "UUID of %s disk" % numtext),
1957 3fe22abd Christos Stavrakakis
        IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDeviceUUID))])
1958 1c8addc6 Michael Hanselmann
1959 1c8addc6 Michael Hanselmann
  return fields
1960 1c8addc6 Michael Hanselmann
1961 1c8addc6 Michael Hanselmann
1962 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1963 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1964 1c8addc6 Michael Hanselmann

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

1967 1c8addc6 Michael Hanselmann
  """
1968 1c8addc6 Michael Hanselmann
  fields = [
1969 1c8addc6 Michael Hanselmann
    # Filled parameters
1970 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1971 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1972 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1973 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1974 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1975 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1976 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1977 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1978 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1979 1c8addc6 Michael Hanselmann
1980 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1981 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1982 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1983 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1984 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1985 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1986 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1987 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1988 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1989 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1990 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1991 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1992 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1993 1c8addc6 Michael Hanselmann
    ]
1994 1c8addc6 Michael Hanselmann
1995 1c8addc6 Michael Hanselmann
  # HV params
1996 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1997 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1998 1c8addc6 Michael Hanselmann
1999 1c8addc6 Michael Hanselmann
  fields.extend([
2000 a6c7e2a2 Iustin Pop
    (_MakeField("hv/%s" % name,
2001 a6c7e2a2 Iustin Pop
                constants.HVS_PARAMETER_TITLES.get(name, "hv/%s" % name),
2002 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
2003 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
2004 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
2005 3c286190 Dimitris Aragiorgis
    if name not in constants.HVC_GLOBALS])
2006 1c8addc6 Michael Hanselmann
2007 1c8addc6 Michael Hanselmann
  # BE params
2008 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
2009 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
2010 1c8addc6 Michael Hanselmann
2011 1c8addc6 Michael Hanselmann
  fields.extend([
2012 a6c7e2a2 Iustin Pop
    (_MakeField("be/%s" % name,
2013 a6c7e2a2 Iustin Pop
                constants.BES_PARAMETER_TITLES.get(name, "be/%s" % name),
2014 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
2015 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
2016 3c286190 Dimitris Aragiorgis
    for name, kind in constants.BES_PARAMETER_TYPES.items()])
2017 1c8addc6 Michael Hanselmann
2018 1c8addc6 Michael Hanselmann
  return fields
2019 1c8addc6 Michael Hanselmann
2020 1c8addc6 Michael Hanselmann
2021 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
2022 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
2023 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
2024 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
2025 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
2026 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
2027 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
2028 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
2029 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
2030 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
2031 1c8addc6 Michael Hanselmann
  }
2032 1c8addc6 Michael Hanselmann
2033 1c8addc6 Michael Hanselmann
2034 1c3231aa Thomas Thrainer
def _GetNodeName(ctx, default, node_uuid):
2035 1c3231aa Thomas Thrainer
  """Gets node name of a node.
2036 1c3231aa Thomas Thrainer

2037 1c3231aa Thomas Thrainer
  @type ctx: L{InstanceQueryData}
2038 1c3231aa Thomas Thrainer
  @param default: Default value
2039 1c3231aa Thomas Thrainer
  @type node_uuid: string
2040 1c3231aa Thomas Thrainer
  @param node_uuid: Node UUID
2041 1c3231aa Thomas Thrainer

2042 1c3231aa Thomas Thrainer
  """
2043 1c3231aa Thomas Thrainer
  try:
2044 1c3231aa Thomas Thrainer
    node = ctx.nodes[node_uuid]
2045 1c3231aa Thomas Thrainer
  except KeyError:
2046 1c3231aa Thomas Thrainer
    return default
2047 1c3231aa Thomas Thrainer
  else:
2048 1c3231aa Thomas Thrainer
    return node.name
2049 1c3231aa Thomas Thrainer
2050 1c3231aa Thomas Thrainer
2051 1c3231aa Thomas Thrainer
def _GetInstNodeGroup(ctx, default, node_uuid):
2052 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
2053 fab9573b Michael Hanselmann

2054 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
2055 fab9573b Michael Hanselmann
  @param default: Default value
2056 1c3231aa Thomas Thrainer
  @type node_uuid: string
2057 1c3231aa Thomas Thrainer
  @param node_uuid: Node UUID
2058 fab9573b Michael Hanselmann

2059 fab9573b Michael Hanselmann
  """
2060 fab9573b Michael Hanselmann
  try:
2061 1c3231aa Thomas Thrainer
    node = ctx.nodes[node_uuid]
2062 fab9573b Michael Hanselmann
  except KeyError:
2063 fab9573b Michael Hanselmann
    return default
2064 fab9573b Michael Hanselmann
  else:
2065 fab9573b Michael Hanselmann
    return node.group
2066 fab9573b Michael Hanselmann
2067 fab9573b Michael Hanselmann
2068 1c3231aa Thomas Thrainer
def _GetInstNodeGroupName(ctx, default, node_uuid):
2069 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
2070 fab9573b Michael Hanselmann

2071 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
2072 fab9573b Michael Hanselmann
  @param default: Default value
2073 1c3231aa Thomas Thrainer
  @type node_uuid: string
2074 1c3231aa Thomas Thrainer
  @param node_uuid: Node UUID
2075 fab9573b Michael Hanselmann

2076 fab9573b Michael Hanselmann
  """
2077 fab9573b Michael Hanselmann
  try:
2078 1c3231aa Thomas Thrainer
    node = ctx.nodes[node_uuid]
2079 fab9573b Michael Hanselmann
  except KeyError:
2080 fab9573b Michael Hanselmann
    return default
2081 fab9573b Michael Hanselmann
2082 fab9573b Michael Hanselmann
  try:
2083 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
2084 fab9573b Michael Hanselmann
  except KeyError:
2085 fab9573b Michael Hanselmann
    return default
2086 fab9573b Michael Hanselmann
2087 fab9573b Michael Hanselmann
  return group.name
2088 fab9573b Michael Hanselmann
2089 fab9573b Michael Hanselmann
2090 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
2091 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
2092 1c8addc6 Michael Hanselmann

2093 1c8addc6 Michael Hanselmann
  """
2094 1c8addc6 Michael Hanselmann
  fields = [
2095 111bf531 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", QFT_TEXT, "Primary node"),
2096 1c3231aa Thomas Thrainer
     IQ_NODES, QFF_HOSTNAME,
2097 1c3231aa Thomas Thrainer
     lambda ctx, inst: _GetNodeName(ctx, None, inst.primary_node)),
2098 fab9573b Michael Hanselmann
    (_MakeField("pnode.group", "PrimaryNodeGroup", QFT_TEXT,
2099 fab9573b Michael Hanselmann
                "Primary node's group"),
2100 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2101 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroupName(ctx, _FS_UNAVAIL,
2102 fab9573b Michael Hanselmann
                                             inst.primary_node)),
2103 fab9573b Michael Hanselmann
    (_MakeField("pnode.group.uuid", "PrimaryNodeGroupUUID", QFT_TEXT,
2104 fab9573b Michael Hanselmann
                "Primary node's group UUID"),
2105 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2106 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroup(ctx, _FS_UNAVAIL, inst.primary_node)),
2107 111bf531 Michael Hanselmann
    # TODO: Allow filtering by secondary node as hostname
2108 79b2ca83 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER,
2109 79b2ca83 Michael Hanselmann
                "Secondary nodes; usually this will just be one node"),
2110 1c3231aa Thomas Thrainer
     IQ_NODES, 0,
2111 1c3231aa Thomas Thrainer
     lambda ctx, inst: map(compat.partial(_GetNodeName, ctx, None),
2112 1c3231aa Thomas Thrainer
                           inst.secondary_nodes)),
2113 fab9573b Michael Hanselmann
    (_MakeField("snodes.group", "SecondaryNodesGroups", QFT_OTHER,
2114 fab9573b Michael Hanselmann
                "Node groups of secondary nodes"),
2115 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2116 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroupName, ctx, None),
2117 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
2118 fab9573b Michael Hanselmann
    (_MakeField("snodes.group.uuid", "SecondaryNodesGroupsUUID", QFT_OTHER,
2119 fab9573b Michael Hanselmann
                "Node group UUIDs of secondary nodes"),
2120 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2121 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroup, ctx, None),
2122 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
2123 2e04d454 Agata Murawska
    (_MakeField("admin_state", "InstanceState", QFT_TEXT,
2124 2e04d454 Agata Murawska
                "Desired state of instance"),
2125 9ca8a7c5 Agata Murawska
     IQ_CONFIG, 0, _GetItemAttr("admin_state")),
2126 754cc530 Agata Murawska
    (_MakeField("admin_up", "Autostart", QFT_BOOL,
2127 754cc530 Agata Murawska
                "Desired state of instance"),
2128 754cc530 Agata Murawska
     IQ_CONFIG, 0, lambda ctx, inst: inst.admin_state == constants.ADMINST_UP),
2129 ca83454f Thomas Thrainer
    (_MakeField("disks_active", "DisksActive", QFT_BOOL,
2130 ca83454f Thomas Thrainer
                "Desired state of instance disks"),
2131 ca83454f Thomas Thrainer
     IQ_CONFIG, 0, _GetItemAttr("disks_active")),
2132 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
2133 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
2134 79b2ca83 Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER,
2135 111bf531 Michael Hanselmann
                "Instance console information"), IQ_CONSOLE, 0,
2136 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
2137 1c8addc6 Michael Hanselmann
    ]
2138 1c8addc6 Michael Hanselmann
2139 1c8addc6 Michael Hanselmann
  # Add simple fields
2140 111bf531 Michael Hanselmann
  fields.extend([
2141 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
2142 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()])
2143 1c8addc6 Michael Hanselmann
2144 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
2145 1c8addc6 Michael Hanselmann
  fields.extend([
2146 79b2ca83 Michael Hanselmann
    (_MakeField("oper_state", "Running", QFT_BOOL, "Actual state of instance"),
2147 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstOperState),
2148 79b2ca83 Michael Hanselmann
    (_MakeField("oper_ram", "Memory", QFT_UNIT,
2149 79b2ca83 Michael Hanselmann
                "Actual memory usage as seen by hypervisor"),
2150 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("memory")),
2151 79b2ca83 Michael Hanselmann
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER,
2152 79b2ca83 Michael Hanselmann
                "Actual number of VCPUs as seen by hypervisor"),
2153 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("vcpus")),
2154 1c8addc6 Michael Hanselmann
    ])
2155 1c8addc6 Michael Hanselmann
2156 79b2ca83 Michael Hanselmann
  # Status field
2157 79b2ca83 Michael Hanselmann
  status_values = (constants.INSTST_RUNNING, constants.INSTST_ADMINDOWN,
2158 79b2ca83 Michael Hanselmann
                   constants.INSTST_WRONGNODE, constants.INSTST_ERRORUP,
2159 79b2ca83 Michael Hanselmann
                   constants.INSTST_ERRORDOWN, constants.INSTST_NODEDOWN,
2160 2e04d454 Agata Murawska
                   constants.INSTST_NODEOFFLINE, constants.INSTST_ADMINOFFLINE)
2161 79b2ca83 Michael Hanselmann
  status_doc = ("Instance status; \"%s\" if instance is set to be running"
2162 79b2ca83 Michael Hanselmann
                " and actually is, \"%s\" if instance is stopped and"
2163 79b2ca83 Michael Hanselmann
                " is not running, \"%s\" if instance running, but not on its"
2164 79b2ca83 Michael Hanselmann
                " designated primary node, \"%s\" if instance should be"
2165 79b2ca83 Michael Hanselmann
                " stopped, but is actually running, \"%s\" if instance should"
2166 79b2ca83 Michael Hanselmann
                " run, but doesn't, \"%s\" if instance's primary node is down,"
2167 2e04d454 Agata Murawska
                " \"%s\" if instance's primary node is marked offline,"
2168 2e04d454 Agata Murawska
                " \"%s\" if instance is offline and does not use dynamic"
2169 2e04d454 Agata Murawska
                " resources" % status_values)
2170 79b2ca83 Michael Hanselmann
  fields.append((_MakeField("status", "Status", QFT_TEXT, status_doc),
2171 111bf531 Michael Hanselmann
                 IQ_LIVE, 0, _GetInstStatus))
2172 79b2ca83 Michael Hanselmann
  assert set(status_values) == constants.INSTST_ALL, \
2173 79b2ca83 Michael Hanselmann
         "Status documentation mismatch"
2174 79b2ca83 Michael Hanselmann
2175 4cc4d1fa Michael Hanselmann
  (network_fields, network_aliases) = _GetInstanceNetworkFields()
2176 4cc4d1fa Michael Hanselmann
2177 4cc4d1fa Michael Hanselmann
  fields.extend(network_fields)
2178 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
2179 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
2180 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
2181 1c8addc6 Michael Hanselmann
2182 e7e8037b Iustin Pop
  aliases = [
2183 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
2184 31d1791a Guido Trotter
    ("be/memory", "be/maxmem"),
2185 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
2186 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
2187 4cc4d1fa Michael Hanselmann
    ] + network_aliases
2188 e7e8037b Iustin Pop
2189 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
2190 1c8addc6 Michael Hanselmann
2191 1c8addc6 Michael Hanselmann
2192 24d16f76 Michael Hanselmann
class LockQueryData:
2193 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
2194 24d16f76 Michael Hanselmann

2195 24d16f76 Michael Hanselmann
  """
2196 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
2197 24d16f76 Michael Hanselmann
    """Initializes this class.
2198 24d16f76 Michael Hanselmann

2199 24d16f76 Michael Hanselmann
    """
2200 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
2201 24d16f76 Michael Hanselmann
2202 24d16f76 Michael Hanselmann
  def __iter__(self):
2203 24d16f76 Michael Hanselmann
    """Iterate over all locks.
2204 24d16f76 Michael Hanselmann

2205 24d16f76 Michael Hanselmann
    """
2206 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
2207 24d16f76 Michael Hanselmann
2208 24d16f76 Michael Hanselmann
2209 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
2210 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
2211 24d16f76 Michael Hanselmann

2212 24d16f76 Michael Hanselmann
  """
2213 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
2214 24d16f76 Michael Hanselmann
2215 24d16f76 Michael Hanselmann
  if owners:
2216 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
2217 24d16f76 Michael Hanselmann
2218 e2d188cc Iustin Pop
  return owners
2219 24d16f76 Michael Hanselmann
2220 24d16f76 Michael Hanselmann
2221 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
2222 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
2223 24d16f76 Michael Hanselmann

2224 24d16f76 Michael Hanselmann
  """
2225 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
2226 24d16f76 Michael Hanselmann
2227 24d16f76 Michael Hanselmann
  if pending:
2228 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
2229 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
2230 24d16f76 Michael Hanselmann
2231 e2d188cc Iustin Pop
  return pending
2232 24d16f76 Michael Hanselmann
2233 24d16f76 Michael Hanselmann
2234 24d16f76 Michael Hanselmann
def _BuildLockFields():
2235 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
2236 24d16f76 Michael Hanselmann

2237 24d16f76 Michael Hanselmann
  """
2238 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
2239 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
2240 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
2241 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
2242 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
2243 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
2244 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
2245 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
2246 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
2247 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
2248 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
2249 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
2250 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
2251 d63bd540 Iustin Pop
    ], [])
2252 24d16f76 Michael Hanselmann
2253 24d16f76 Michael Hanselmann
2254 8e21cfc0 Adeodato Simo
class GroupQueryData:
2255 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
2256 8e21cfc0 Adeodato Simo

2257 8e21cfc0 Adeodato Simo
  """
2258 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2259 2c758845 René Nussbaumer
               want_diskparams):
2260 8e21cfc0 Adeodato Simo
    """Initializes this class.
2261 8e21cfc0 Adeodato Simo

2262 edd49f9b Agata Murawska
    @param cluster: Cluster object
2263 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2264 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2265 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2266 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2267 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2268 2c758845 René Nussbaumer
    @type want_diskparams: bool
2269 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2270 8e21cfc0 Adeodato Simo

2271 8e21cfc0 Adeodato Simo
    """
2272 8e21cfc0 Adeodato Simo
    self.groups = groups
2273 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2274 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2275 edd49f9b Agata Murawska
    self.cluster = cluster
2276 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2277 edd49f9b Agata Murawska
2278 edd49f9b Agata Murawska
    # Used for individual rows
2279 edd49f9b Agata Murawska
    self.group_ipolicy = None
2280 8930b0f0 Iustin Pop
    self.ndparams = None
2281 2c758845 René Nussbaumer
    self.group_dp = None
2282 8e21cfc0 Adeodato Simo
2283 8e21cfc0 Adeodato Simo
  def __iter__(self):
2284 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2285 8e21cfc0 Adeodato Simo

2286 edd49f9b Agata Murawska
    This function has side-effects and only one instance of the resulting
2287 edd49f9b Agata Murawska
    generator should be used at a time.
2288 edd49f9b Agata Murawska

2289 8e21cfc0 Adeodato Simo
    """
2290 edd49f9b Agata Murawska
    for group in self.groups:
2291 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2292 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2293 2c758845 René Nussbaumer
      if self.want_diskparams:
2294 2c758845 René Nussbaumer
        self.group_dp = self.cluster.SimpleFillDP(group.diskparams)
2295 2c758845 René Nussbaumer
      else:
2296 2c758845 René Nussbaumer
        self.group_dp = None
2297 edd49f9b Agata Murawska
      yield group
2298 8e21cfc0 Adeodato Simo
2299 8e21cfc0 Adeodato Simo
2300 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2301 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2302 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2303 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2304 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2305 8e21cfc0 Adeodato Simo
  }
2306 8e21cfc0 Adeodato Simo
2307 8e21cfc0 Adeodato Simo
2308 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2309 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2310 8e21cfc0 Adeodato Simo

2311 8e21cfc0 Adeodato Simo
  """
2312 8e21cfc0 Adeodato Simo
  # Add simple fields
2313 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
2314 111bf531 Michael Hanselmann
             _GetItemAttr(name))
2315 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
2316 8e21cfc0 Adeodato Simo
2317 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
2318 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
2319 8e21cfc0 Adeodato Simo
2320 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
2321 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
2322 8e21cfc0 Adeodato Simo
2323 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
2324 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
2325 8e21cfc0 Adeodato Simo
2326 8e21cfc0 Adeodato Simo
  # Add fields for nodes
2327 8e21cfc0 Adeodato Simo
  fields.extend([
2328 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
2329 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
2330 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
2331 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
2332 8e21cfc0 Adeodato Simo
    ])
2333 8e21cfc0 Adeodato Simo
2334 8e21cfc0 Adeodato Simo
  # Add fields for instances
2335 8e21cfc0 Adeodato Simo
  fields.extend([
2336 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
2337 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
2338 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
2339 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
2340 79b2ca83 Michael Hanselmann
                "List of primary instances"),
2341 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
2342 8e21cfc0 Adeodato Simo
    ])
2343 8e21cfc0 Adeodato Simo
2344 1ffd2673 Michael Hanselmann
  # Other fields
2345 1ffd2673 Michael Hanselmann
  fields.extend([
2346 1ffd2673 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
2347 1ffd2673 Michael Hanselmann
     lambda ctx, group: list(group.GetTags())),
2348 edd49f9b Agata Murawska
    (_MakeField("ipolicy", "InstancePolicy", QFT_OTHER,
2349 edd49f9b Agata Murawska
                "Instance policy limitations (merged)"),
2350 edd49f9b Agata Murawska
     GQ_CONFIG, 0, lambda ctx, _: ctx.group_ipolicy),
2351 edd49f9b Agata Murawska
    (_MakeField("custom_ipolicy", "CustomInstancePolicy", QFT_OTHER,
2352 edd49f9b Agata Murawska
                "Custom instance policy limitations"),
2353 edd49f9b Agata Murawska
     GQ_CONFIG, 0, _GetItemAttr("ipolicy")),
2354 8930b0f0 Iustin Pop
    (_MakeField("custom_ndparams", "CustomNDParams", QFT_OTHER,
2355 8930b0f0 Iustin Pop
                "Custom node parameters"),
2356 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, _GetItemAttr("ndparams")),
2357 8930b0f0 Iustin Pop
    (_MakeField("ndparams", "NDParams", QFT_OTHER,
2358 8930b0f0 Iustin Pop
                "Node parameters"),
2359 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, lambda ctx, _: ctx.ndparams),
2360 2c758845 René Nussbaumer
    (_MakeField("diskparams", "DiskParameters", QFT_OTHER,
2361 2c758845 René Nussbaumer
                "Disk parameters (merged)"),
2362 2c758845 René Nussbaumer
     GQ_DISKPARAMS, 0, lambda ctx, _: ctx.group_dp),
2363 2c758845 René Nussbaumer
    (_MakeField("custom_diskparams", "CustomDiskParameters", QFT_OTHER,
2364 2c758845 René Nussbaumer
                "Custom disk parameters"),
2365 2c758845 René Nussbaumer
     GQ_CONFIG, 0, _GetItemAttr("diskparams")),
2366 1ffd2673 Michael Hanselmann
    ])
2367 1ffd2673 Michael Hanselmann
2368 8930b0f0 Iustin Pop
  # ND parameters
2369 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(True))
2370 8930b0f0 Iustin Pop
2371 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
2372 8e21cfc0 Adeodato Simo
2373 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
2374 8e21cfc0 Adeodato Simo
2375 8e21cfc0 Adeodato Simo
2376 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
2377 be3a4b14 Michael Hanselmann
  __slots__ = [
2378 be3a4b14 Michael Hanselmann
    "name",
2379 be3a4b14 Michael Hanselmann
    "valid",
2380 be3a4b14 Michael Hanselmann
    "hidden",
2381 be3a4b14 Michael Hanselmann
    "blacklisted",
2382 be3a4b14 Michael Hanselmann
    "variants",
2383 be3a4b14 Michael Hanselmann
    "api_versions",
2384 be3a4b14 Michael Hanselmann
    "parameters",
2385 be3a4b14 Michael Hanselmann
    "node_status",
2386 be3a4b14 Michael Hanselmann
    ]
2387 be3a4b14 Michael Hanselmann
2388 be3a4b14 Michael Hanselmann
2389 be3a4b14 Michael Hanselmann
def _BuildOsFields():
2390 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
2391 be3a4b14 Michael Hanselmann

2392 be3a4b14 Michael Hanselmann
  """
2393 be3a4b14 Michael Hanselmann
  fields = [
2394 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2395 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2396 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2397 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2398 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2399 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2400 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2401 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2402 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2403 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2404 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2405 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2406 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2407 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2408 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2409 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2410 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2411 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2412 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2413 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2414 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2415 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2416 be3a4b14 Michael Hanselmann
                "Status from node"),
2417 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2418 be3a4b14 Michael Hanselmann
    ]
2419 be3a4b14 Michael Hanselmann
2420 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2421 be3a4b14 Michael Hanselmann
2422 be3a4b14 Michael Hanselmann
2423 b954f097 Constantinos Venetsanopoulos
class ExtStorageInfo(objects.ConfigObject):
2424 b954f097 Constantinos Venetsanopoulos
  __slots__ = [
2425 b954f097 Constantinos Venetsanopoulos
    "name",
2426 b954f097 Constantinos Venetsanopoulos
    "node_status",
2427 b954f097 Constantinos Venetsanopoulos
    "nodegroup_status",
2428 b954f097 Constantinos Venetsanopoulos
    "parameters",
2429 b954f097 Constantinos Venetsanopoulos
    ]
2430 b954f097 Constantinos Venetsanopoulos
2431 b954f097 Constantinos Venetsanopoulos
2432 b954f097 Constantinos Venetsanopoulos
def _BuildExtStorageFields():
2433 b954f097 Constantinos Venetsanopoulos
  """Builds list of fields for extstorage provider queries.
2434 b954f097 Constantinos Venetsanopoulos

2435 b954f097 Constantinos Venetsanopoulos
  """
2436 b954f097 Constantinos Venetsanopoulos
  fields = [
2437 b954f097 Constantinos Venetsanopoulos
    (_MakeField("name", "Name", QFT_TEXT, "ExtStorage provider name"),
2438 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("name")),
2439 b954f097 Constantinos Venetsanopoulos
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2440 b954f097 Constantinos Venetsanopoulos
                "Status from node"),
2441 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("node_status")),
2442 b954f097 Constantinos Venetsanopoulos
    (_MakeField("nodegroup_status", "NodegroupStatus", QFT_OTHER,
2443 b954f097 Constantinos Venetsanopoulos
                "Overall Nodegroup status"),
2444 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("nodegroup_status")),
2445 b954f097 Constantinos Venetsanopoulos
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2446 b954f097 Constantinos Venetsanopoulos
                "ExtStorage provider parameters"),
2447 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("parameters")),
2448 b954f097 Constantinos Venetsanopoulos
    ]
2449 b954f097 Constantinos Venetsanopoulos
2450 b954f097 Constantinos Venetsanopoulos
  return _PrepareFieldList(fields, [])
2451 b954f097 Constantinos Venetsanopoulos
2452 b954f097 Constantinos Venetsanopoulos
2453 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2454 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2455 9665bb3a Michael Hanselmann

2456 9665bb3a Michael Hanselmann
  When listing specifc jobs (e.g. "gnt-job list 1 2 3"), a job may not be
2457 9665bb3a Michael Hanselmann
  found, in which case this function converts it to L{_FS_UNAVAIL}.
2458 9665bb3a Michael Hanselmann

2459 9665bb3a Michael Hanselmann
  """
2460 9665bb3a Michael Hanselmann
  if job is None:
2461 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2462 9665bb3a Michael Hanselmann
  else:
2463 9665bb3a Michael Hanselmann
    return fn(job)
2464 9665bb3a Michael Hanselmann
2465 9665bb3a Michael Hanselmann
2466 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2467 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2468 9665bb3a Michael Hanselmann

2469 9665bb3a Michael Hanselmann
  """
2470 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2471 9665bb3a Michael Hanselmann
2472 9665bb3a Michael Hanselmann
2473 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2474 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2475 9665bb3a Michael Hanselmann

2476 9665bb3a Michael Hanselmann
  """
2477 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2478 9665bb3a Michael Hanselmann
2479 9665bb3a Michael Hanselmann
2480 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2481 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2482 9665bb3a Michael Hanselmann

2483 9665bb3a Michael Hanselmann
  """
2484 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2485 9665bb3a Michael Hanselmann
2486 9665bb3a Michael Hanselmann
2487 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2488 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2489 9665bb3a Michael Hanselmann

2490 9665bb3a Michael Hanselmann
  """
2491 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2492 9665bb3a Michael Hanselmann
2493 9665bb3a Michael Hanselmann
  if timestamp is None:
2494 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2495 9665bb3a Michael Hanselmann
  else:
2496 9665bb3a Michael Hanselmann
    return timestamp
2497 9665bb3a Michael Hanselmann
2498 9665bb3a Michael Hanselmann
2499 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2500 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2501 9665bb3a Michael Hanselmann

2502 9665bb3a Michael Hanselmann
  """
2503 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2504 9665bb3a Michael Hanselmann
2505 9665bb3a Michael Hanselmann
2506 9665bb3a Michael Hanselmann
def _BuildJobFields():
2507 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2508 9665bb3a Michael Hanselmann

2509 9665bb3a Michael Hanselmann
  """
2510 9665bb3a Michael Hanselmann
  fields = [
2511 76b62028 Iustin Pop
    (_MakeField("id", "ID", QFT_NUMBER, "Job ID"),
2512 526f866b Michael Hanselmann
     None, QFF_JOB_ID, lambda _, (job_id, job): job_id),
2513 9665bb3a Michael Hanselmann
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2514 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2515 9665bb3a Michael Hanselmann
    (_MakeField("priority", "Priority", QFT_NUMBER,
2516 9665bb3a Michael Hanselmann
                ("Current job priority (%s to %s)" %
2517 9665bb3a Michael Hanselmann
                 (constants.OP_PRIO_LOWEST, constants.OP_PRIO_HIGHEST))),
2518 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcPriority())),
2519 0422250e Michael Hanselmann
    (_MakeField("archived", "Archived", QFT_BOOL, "Whether job is archived"),
2520 0422250e Michael Hanselmann
     JQ_ARCHIVED, 0, lambda _, (job_id, job): job.archived),
2521 9665bb3a Michael Hanselmann
    (_MakeField("ops", "OpCodes", QFT_OTHER, "List of all opcodes"),
2522 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.__getstate__())),
2523 9665bb3a Michael Hanselmann
    (_MakeField("opresult", "OpCode_result", QFT_OTHER,
2524 9665bb3a Michael Hanselmann
                "List of opcodes results"),
2525 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("result"))),
2526 9665bb3a Michael Hanselmann
    (_MakeField("opstatus", "OpCode_status", QFT_OTHER,
2527 9665bb3a Michael Hanselmann
                "List of opcodes status"),
2528 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("status"))),
2529 9665bb3a Michael Hanselmann
    (_MakeField("oplog", "OpCode_log", QFT_OTHER,
2530 9665bb3a Michael Hanselmann
                "List of opcode output logs"),
2531 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("log"))),
2532 9665bb3a Michael Hanselmann
    (_MakeField("opstart", "OpCode_start", QFT_OTHER,
2533 9665bb3a Michael Hanselmann
                "List of opcode start timestamps (before acquiring locks)"),
2534 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("start_timestamp"))),
2535 9665bb3a Michael Hanselmann
    (_MakeField("opexec", "OpCode_exec", QFT_OTHER,
2536 9665bb3a Michael Hanselmann
                "List of opcode execution start timestamps (after acquiring"
2537 9665bb3a Michael Hanselmann
                " locks)"),
2538 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("exec_timestamp"))),
2539 9665bb3a Michael Hanselmann
    (_MakeField("opend", "OpCode_end", QFT_OTHER,
2540 9665bb3a Michael Hanselmann
                "List of opcode execution end timestamps"),
2541 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("end_timestamp"))),
2542 9665bb3a Michael Hanselmann
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2543 9665bb3a Michael Hanselmann
                "List of opcode priorities"),
2544 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2545 9665bb3a Michael Hanselmann
    (_MakeField("summary", "Summary", QFT_OTHER,
2546 9665bb3a Michael Hanselmann
                "List of per-opcode summaries"),
2547 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2548 9665bb3a Michael Hanselmann
    ]
2549 9665bb3a Michael Hanselmann
2550 526f866b Michael Hanselmann
  # Timestamp fields
2551 526f866b Michael Hanselmann
  for (name, attr, title, desc) in [
2552 526f866b Michael Hanselmann
    ("received_ts", "received_timestamp", "Received",
2553 526f866b Michael Hanselmann
     "Timestamp of when job was received"),
2554 526f866b Michael Hanselmann
    ("start_ts", "start_timestamp", "Start", "Timestamp of job start"),
2555 526f866b Michael Hanselmann
    ("end_ts", "end_timestamp", "End", "Timestamp of job end"),
2556 526f866b Michael Hanselmann
    ]:
2557 526f866b Michael Hanselmann
    getter = operator.attrgetter(attr)
2558 526f866b Michael Hanselmann
    fields.extend([
2559 526f866b Michael Hanselmann
      (_MakeField(name, title, QFT_OTHER,
2560 526f866b Michael Hanselmann
                  "%s (tuple containing seconds and microseconds)" % desc),
2561 526f866b Michael Hanselmann
       None, QFF_SPLIT_TIMESTAMP, _JobTimestamp(getter)),
2562 526f866b Michael Hanselmann
      ])
2563 526f866b Michael Hanselmann
2564 9665bb3a Michael Hanselmann
  return _PrepareFieldList(fields, [])
2565 9665bb3a Michael Hanselmann
2566 9665bb3a Michael Hanselmann
2567 0fdf247d Michael Hanselmann
def _GetExportName(_, (node_name, expname)): # pylint: disable=W0613
2568 0fdf247d Michael Hanselmann
  """Returns an export name if available.
2569 0fdf247d Michael Hanselmann

2570 0fdf247d Michael Hanselmann
  """
2571 0fdf247d Michael Hanselmann
  if expname is None:
2572 0b1c7a55 Iustin Pop
    return _FS_NODATA
2573 0fdf247d Michael Hanselmann
  else:
2574 0fdf247d Michael Hanselmann
    return expname
2575 0fdf247d Michael Hanselmann
2576 0fdf247d Michael Hanselmann
2577 0fdf247d Michael Hanselmann
def _BuildExportFields():
2578 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2579 0fdf247d Michael Hanselmann

2580 0fdf247d Michael Hanselmann
  """
2581 0fdf247d Michael Hanselmann
  fields = [
2582 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2583 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2584 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2585 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2586 0fdf247d Michael Hanselmann
    ]
2587 0fdf247d Michael Hanselmann
2588 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2589 0fdf247d Michael Hanselmann
2590 0fdf247d Michael Hanselmann
2591 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2592 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2593 dff5f600 Michael Hanselmann
                       "Software version"),
2594 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2595 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2596 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2597 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2598 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2599 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2600 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2601 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2602 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2603 026f444f Thomas Thrainer
  "vcs_version": ("VCSVersion", QFT_TEXT, constants.VCS_VERSION,
2604 026f444f Thomas Thrainer
                     "VCS version"),
2605 dff5f600 Michael Hanselmann
  }
2606 dff5f600 Michael Hanselmann
2607 dff5f600 Michael Hanselmann
2608 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2609 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2610 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2611 dff5f600 Michael Hanselmann
  }
2612 dff5f600 Michael Hanselmann
2613 dff5f600 Michael Hanselmann
2614 dff5f600 Michael Hanselmann
class ClusterQueryData:
2615 1c3231aa Thomas Thrainer
  def __init__(self, cluster, nodes, drain_flag, watcher_pause):
2616 dff5f600 Michael Hanselmann
    """Initializes this class.
2617 dff5f600 Michael Hanselmann

2618 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2619 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2620 1c3231aa Thomas Thrainer
    @type nodes: dict; node UUID as key
2621 1c3231aa Thomas Thrainer
    @param nodes: Node objects
2622 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2623 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2624 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2625 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2626 dff5f600 Michael Hanselmann

2627 dff5f600 Michael Hanselmann
    """
2628 dff5f600 Michael Hanselmann
    self._cluster = cluster
2629 1c3231aa Thomas Thrainer
    self.nodes = nodes
2630 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2631 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2632 dff5f600 Michael Hanselmann
2633 dff5f600 Michael Hanselmann
  def __iter__(self):
2634 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2635 dff5f600 Michael Hanselmann
2636 dff5f600 Michael Hanselmann
2637 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2638 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2639 dff5f600 Michael Hanselmann

2640 dff5f600 Michael Hanselmann
  """
2641 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2642 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2643 dff5f600 Michael Hanselmann
  else:
2644 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2645 dff5f600 Michael Hanselmann
2646 dff5f600 Michael Hanselmann
2647 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2648 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2649 dff5f600 Michael Hanselmann

2650 dff5f600 Michael Hanselmann
  """
2651 dff5f600 Michael Hanselmann
  fields = [
2652 dff5f600 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), CQ_CONFIG, 0,
2653 dff5f600 Michael Hanselmann
     lambda ctx, cluster: list(cluster.GetTags())),
2654 dff5f600 Michael Hanselmann
    (_MakeField("architecture", "ArchInfo", QFT_OTHER,
2655 dff5f600 Michael Hanselmann
                "Architecture information"), None, 0,
2656 dff5f600 Michael Hanselmann
     lambda ctx, _: runtime.GetArchInfo()),
2657 dff5f600 Michael Hanselmann
    (_MakeField("drain_flag", "QueueDrained", QFT_BOOL,
2658 dff5f600 Michael Hanselmann
                "Flag whether job queue is drained"), CQ_QUEUE_DRAINED, 0,
2659 dff5f600 Michael Hanselmann
     lambda ctx, _: ctx.drain_flag),
2660 dff5f600 Michael Hanselmann
    (_MakeField("watcher_pause", "WatcherPause", QFT_TIMESTAMP,
2661 dff5f600 Michael Hanselmann
                "Until when watcher is paused"), CQ_WATCHER_PAUSE, 0,
2662 dff5f600 Michael Hanselmann
     _ClusterWatcherPause),
2663 1c3231aa Thomas Thrainer
    (_MakeField("master_node", "Master", QFT_TEXT, "Master node name"),
2664 1c3231aa Thomas Thrainer
     CQ_CONFIG, QFF_HOSTNAME,
2665 1c3231aa Thomas Thrainer
     lambda ctx, cluster: _GetNodeName(ctx, None, cluster.master_node)),
2666 dff5f600 Michael Hanselmann
    ]
2667 dff5f600 Michael Hanselmann
2668 dff5f600 Michael Hanselmann
  # Simple fields
2669 dff5f600 Michael Hanselmann
  fields.extend([
2670 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), CQ_CONFIG, flags, _GetItemAttr(name))
2671 dff5f600 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _CLUSTER_SIMPLE_FIELDS.items()
2672 3c286190 Dimitris Aragiorgis
    ],)
2673 dff5f600 Michael Hanselmann
2674 dff5f600 Michael Hanselmann
  # Version fields
2675 dff5f600 Michael Hanselmann
  fields.extend([
2676 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), None, 0, _StaticValue(value))
2677 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, value, doc)) in _CLUSTER_VERSION_FIELDS.items()])
2678 dff5f600 Michael Hanselmann
2679 dff5f600 Michael Hanselmann
  # Add timestamps
2680 dff5f600 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(CQ_CONFIG))
2681 dff5f600 Michael Hanselmann
2682 dff5f600 Michael Hanselmann
  return _PrepareFieldList(fields, [
2683 3c286190 Dimitris Aragiorgis
    ("name", "cluster_name")])
2684 dff5f600 Michael Hanselmann
2685 dff5f600 Michael Hanselmann
2686 306bed0e Apollon Oikonomopoulos
class NetworkQueryData:
2687 306bed0e Apollon Oikonomopoulos
  """Data container for network data queries.
2688 306bed0e Apollon Oikonomopoulos

2689 306bed0e Apollon Oikonomopoulos
  """
2690 306bed0e Apollon Oikonomopoulos
  def __init__(self, networks, network_to_groups,
2691 306bed0e Apollon Oikonomopoulos
               network_to_instances, stats):
2692 306bed0e Apollon Oikonomopoulos
    """Initializes this class.
2693 306bed0e Apollon Oikonomopoulos

2694 306bed0e Apollon Oikonomopoulos
    @param networks: List of network objects
2695 306bed0e Apollon Oikonomopoulos
    @type network_to_groups: dict; network UUID as key
2696 306bed0e Apollon Oikonomopoulos
    @param network_to_groups: Per-network list of groups
2697 306bed0e Apollon Oikonomopoulos
    @type network_to_instances: dict; network UUID as key
2698 306bed0e Apollon Oikonomopoulos
    @param network_to_instances: Per-network list of instances
2699 306bed0e Apollon Oikonomopoulos
    @type stats: dict; network UUID as key
2700 306bed0e Apollon Oikonomopoulos
    @param stats: Per-network usage statistics
2701 306bed0e Apollon Oikonomopoulos

2702 306bed0e Apollon Oikonomopoulos
    """
2703 306bed0e Apollon Oikonomopoulos
    self.networks = networks
2704 306bed0e Apollon Oikonomopoulos
    self.network_to_groups = network_to_groups
2705 306bed0e Apollon Oikonomopoulos
    self.network_to_instances = network_to_instances
2706 306bed0e Apollon Oikonomopoulos
    self.stats = stats
2707 306bed0e Apollon Oikonomopoulos
2708 306bed0e Apollon Oikonomopoulos
  def __iter__(self):
2709 306bed0e Apollon Oikonomopoulos
    """Iterate over all networks.
2710 306bed0e Apollon Oikonomopoulos

2711 306bed0e Apollon Oikonomopoulos
    """
2712 306bed0e Apollon Oikonomopoulos
    for net in self.networks:
2713 306bed0e Apollon Oikonomopoulos
      if self.stats:
2714 306bed0e Apollon Oikonomopoulos
        self.curstats = self.stats.get(net.uuid, None)
2715 306bed0e Apollon Oikonomopoulos
      else:
2716 306bed0e Apollon Oikonomopoulos
        self.curstats = None
2717 306bed0e Apollon Oikonomopoulos
      yield net
2718 306bed0e Apollon Oikonomopoulos
2719 306bed0e Apollon Oikonomopoulos
2720 306bed0e Apollon Oikonomopoulos
_NETWORK_SIMPLE_FIELDS = {
2721 0b3f2215 Michael Hanselmann
  "name": ("Network", QFT_TEXT, 0, "Name"),
2722 0b3f2215 Michael Hanselmann
  "network": ("Subnet", QFT_TEXT, 0, "IPv4 subnet"),
2723 0b3f2215 Michael Hanselmann
  "gateway": ("Gateway", QFT_OTHER, 0, "IPv4 gateway"),
2724 0b3f2215 Michael Hanselmann
  "network6": ("IPv6Subnet", QFT_OTHER, 0, "IPv6 subnet"),
2725 0b3f2215 Michael Hanselmann
  "gateway6": ("IPv6Gateway", QFT_OTHER, 0, "IPv6 gateway"),
2726 0b3f2215 Michael Hanselmann
  "mac_prefix": ("MacPrefix", QFT_OTHER, 0, "MAC address prefix"),
2727 9675661c Dimitris Aragiorgis
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Network"),
2728 9675661c Dimitris Aragiorgis
  "uuid": ("UUID", QFT_TEXT, 0, "Network UUID"),
2729 306bed0e Apollon Oikonomopoulos
  }
2730 306bed0e Apollon Oikonomopoulos
2731 306bed0e Apollon Oikonomopoulos
2732 306bed0e Apollon Oikonomopoulos
_NETWORK_STATS_FIELDS = {
2733 0b3f2215 Michael Hanselmann
  "free_count": ("FreeCount", QFT_NUMBER, 0, "Number of available addresses"),
2734 0b3f2215 Michael Hanselmann
  "reserved_count":
2735 0b3f2215 Michael Hanselmann
    ("ReservedCount", QFT_NUMBER, 0, "Number of reserved addresses"),
2736 0b3f2215 Michael Hanselmann
  "map": ("Map", QFT_TEXT, 0, "Actual mapping"),
2737 0b3f2215 Michael Hanselmann
  "external_reservations":
2738 0b3f2215 Michael Hanselmann
    ("ExternalReservations", QFT_TEXT, 0, "External reservations"),
2739 306bed0e Apollon Oikonomopoulos
  }
2740 306bed0e Apollon Oikonomopoulos
2741 3c286190 Dimitris Aragiorgis
2742 83a14695 Helga Velroyen
def _GetNetworkStatsField(field, kind, ctx, _):
2743 306bed0e Apollon Oikonomopoulos
  """Gets the value of a "stats" field from L{NetworkQueryData}.
2744 306bed0e Apollon Oikonomopoulos

2745 306bed0e Apollon Oikonomopoulos
  @param field: Field name
2746 306bed0e Apollon Oikonomopoulos
  @param kind: Data kind, one of L{constants.QFT_ALL}
2747 306bed0e Apollon Oikonomopoulos
  @type ctx: L{NetworkQueryData}
2748 306bed0e Apollon Oikonomopoulos

2749 306bed0e Apollon Oikonomopoulos
  """
2750 b4600d4f Michael Hanselmann
  return _GetStatsField(field, kind, ctx.curstats)
2751 306bed0e Apollon Oikonomopoulos
2752 306bed0e Apollon Oikonomopoulos
2753 306bed0e Apollon Oikonomopoulos
def _BuildNetworkFields():
2754 306bed0e Apollon Oikonomopoulos
  """Builds list of fields for network queries.
2755 306bed0e Apollon Oikonomopoulos

2756 306bed0e Apollon Oikonomopoulos
  """
2757 306bed0e Apollon Oikonomopoulos
  fields = [
2758 8140e24f Dimitris Aragiorgis
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
2759 8140e24f Dimitris Aragiorgis
     lambda ctx, inst: list(inst.GetTags())),
2760 8140e24f Dimitris Aragiorgis
    ]
2761 8140e24f Dimitris Aragiorgis
2762 8140e24f Dimitris Aragiorgis
  # Add simple fields
2763 8140e24f Dimitris Aragiorgis
  fields.extend([
2764 306bed0e Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc),
2765 40b118d3 Iustin Pop
     NETQ_CONFIG, 0, _GetItemMaybeAttr(name))
2766 3c286190 Dimitris Aragiorgis
     for (name, (title, kind, _, doc)) in _NETWORK_SIMPLE_FIELDS.items()])
2767 306bed0e Apollon Oikonomopoulos
2768 306bed0e Apollon Oikonomopoulos
  def _GetLength(getter):
2769 306bed0e Apollon Oikonomopoulos
    return lambda ctx, network: len(getter(ctx)[network.uuid])
2770 306bed0e Apollon Oikonomopoulos
2771 306bed0e Apollon Oikonomopoulos
  def _GetSortedList(getter):
2772 306bed0e Apollon Oikonomopoulos
    return lambda ctx, network: utils.NiceSort(getter(ctx)[network.uuid])
2773 306bed0e Apollon Oikonomopoulos
2774 306bed0e Apollon Oikonomopoulos
  network_to_groups = operator.attrgetter("network_to_groups")
2775 306bed0e Apollon Oikonomopoulos
  network_to_instances = operator.attrgetter("network_to_instances")
2776 306bed0e Apollon Oikonomopoulos
2777 306bed0e Apollon Oikonomopoulos
  # Add fields for node groups
2778 306bed0e Apollon Oikonomopoulos
  fields.extend([
2779 306bed0e Apollon Oikonomopoulos
    (_MakeField("group_cnt", "NodeGroups", QFT_NUMBER, "Number of nodegroups"),
2780 306bed0e Apollon Oikonomopoulos
     NETQ_GROUP, 0, _GetLength(network_to_groups)),
2781 503574ec Michael Hanselmann
    (_MakeField("group_list", "GroupList", QFT_OTHER,
2782 503574ec Michael Hanselmann
     "List of nodegroups (group name, NIC mode, NIC link)"),
2783 503574ec Michael Hanselmann
     NETQ_GROUP, 0, lambda ctx, network: network_to_groups(ctx)[network.uuid]),
2784 306bed0e Apollon Oikonomopoulos
    ])
2785 306bed0e Apollon Oikonomopoulos
2786 306bed0e Apollon Oikonomopoulos
  # Add fields for instances
2787 306bed0e Apollon Oikonomopoulos
  fields.extend([
2788 306bed0e Apollon Oikonomopoulos
    (_MakeField("inst_cnt", "Instances", QFT_NUMBER, "Number of instances"),
2789 306bed0e Apollon Oikonomopoulos
     NETQ_INST, 0, _GetLength(network_to_instances)),
2790 306bed0e Apollon Oikonomopoulos
    (_MakeField("inst_list", "InstanceList", QFT_OTHER, "List of instances"),
2791 306bed0e Apollon Oikonomopoulos
     NETQ_INST, 0, _GetSortedList(network_to_instances)),
2792 306bed0e Apollon Oikonomopoulos
    ])
2793 306bed0e Apollon Oikonomopoulos
2794 306bed0e Apollon Oikonomopoulos
  # Add fields for usage statistics
2795 306bed0e Apollon Oikonomopoulos
  fields.extend([
2796 306bed0e Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc), NETQ_STATS, 0,
2797 306bed0e Apollon Oikonomopoulos
    compat.partial(_GetNetworkStatsField, name, kind))
2798 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, _, doc)) in _NETWORK_STATS_FIELDS.items()])
2799 306bed0e Apollon Oikonomopoulos
2800 22ff02a7 Christos Stavrakakis
  # Add timestamps
2801 22ff02a7 Christos Stavrakakis
  fields.extend(_GetItemTimestampFields(IQ_NETWORKS))
2802 22ff02a7 Christos Stavrakakis
2803 306bed0e Apollon Oikonomopoulos
  return _PrepareFieldList(fields, [])
2804 306bed0e Apollon Oikonomopoulos
2805 dff5f600 Michael Hanselmann
#: Fields for cluster information
2806 dff5f600 Michael Hanselmann
CLUSTER_FIELDS = _BuildClusterFields()
2807 dff5f600 Michael Hanselmann
2808 8235fe04 Michael Hanselmann
#: Fields available for node queries
2809 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2810 1c8addc6 Michael Hanselmann
2811 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2812 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2813 24d16f76 Michael Hanselmann
2814 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2815 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2816 e571ee44 Adeodato Simo
2817 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2818 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2819 8e21cfc0 Adeodato Simo
2820 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2821 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2822 be3a4b14 Michael Hanselmann
2823 b954f097 Constantinos Venetsanopoulos
#: Fields available for extstorage provider queries
2824 b954f097 Constantinos Venetsanopoulos
EXTSTORAGE_FIELDS = _BuildExtStorageFields()
2825 b954f097 Constantinos Venetsanopoulos
2826 9665bb3a Michael Hanselmann
#: Fields available for job queries
2827 9665bb3a Michael Hanselmann
JOB_FIELDS = _BuildJobFields()
2828 9665bb3a Michael Hanselmann
2829 0fdf247d Michael Hanselmann
#: Fields available for exports
2830 0fdf247d Michael Hanselmann
EXPORT_FIELDS = _BuildExportFields()
2831 0fdf247d Michael Hanselmann
2832 306bed0e Apollon Oikonomopoulos
#: Fields available for network queries
2833 306bed0e Apollon Oikonomopoulos
NETWORK_FIELDS = _BuildNetworkFields()
2834 306bed0e Apollon Oikonomopoulos
2835 95eb4188 Michael Hanselmann
#: All available resources
2836 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2837 dff5f600 Michael Hanselmann
  constants.QR_CLUSTER: CLUSTER_FIELDS,
2838 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2839 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2840 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2841 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2842 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2843 b954f097 Constantinos Venetsanopoulos
  constants.QR_EXTSTORAGE: EXTSTORAGE_FIELDS,
2844 9665bb3a Michael Hanselmann
  constants.QR_JOB: JOB_FIELDS,
2845 0fdf247d Michael Hanselmann
  constants.QR_EXPORT: EXPORT_FIELDS,
2846 306bed0e Apollon Oikonomopoulos
  constants.QR_NETWORK: NETWORK_FIELDS,
2847 95eb4188 Michael Hanselmann
  }
2848 95eb4188 Michael Hanselmann
2849 e571ee44 Adeodato Simo
#: All available field lists
2850 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()