Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 2cbe9af3

History | View | Annotate | Download (72.1 kB)

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

152 4ca96421 Michael Hanselmann
  """
153 e2d188cc Iustin Pop
  return _FS_UNKNOWN
154 4ca96421 Michael Hanselmann
155 4ca96421 Michael Hanselmann
156 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
157 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
158 4ca96421 Michael Hanselmann

159 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
160 4ca96421 Michael Hanselmann

161 4ca96421 Michael Hanselmann
  @type fielddefs: dict
162 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
163 4ca96421 Michael Hanselmann
  @type selected: list of strings
164 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
165 4ca96421 Michael Hanselmann

166 4ca96421 Michael Hanselmann
  """
167 4ca96421 Michael Hanselmann
  result = []
168 4ca96421 Michael Hanselmann
169 4ca96421 Michael Hanselmann
  for name in selected:
170 4ca96421 Michael Hanselmann
    try:
171 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
172 4ca96421 Michael Hanselmann
    except KeyError:
173 79b2ca83 Michael Hanselmann
      fdef = (_MakeField(name, name, QFT_UNKNOWN, "Unknown field '%s'" % name),
174 111bf531 Michael Hanselmann
              None, 0, _GetUnknownField)
175 4ca96421 Michael Hanselmann
176 111bf531 Michael Hanselmann
    assert len(fdef) == 4
177 4ca96421 Michael Hanselmann
178 4ca96421 Michael Hanselmann
    result.append(fdef)
179 4ca96421 Michael Hanselmann
180 4ca96421 Michael Hanselmann
  return result
181 4ca96421 Michael Hanselmann
182 4ca96421 Michael Hanselmann
183 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
184 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
185 4ca96421 Michael Hanselmann

186 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
187 4ca96421 Michael Hanselmann

188 4ca96421 Michael Hanselmann
  """
189 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
190 4ca96421 Michael Hanselmann
191 4ca96421 Michael Hanselmann
192 fb0be379 Michael Hanselmann
class _FilterHints:
193 fb0be379 Michael Hanselmann
  """Class for filter analytics.
194 fb0be379 Michael Hanselmann

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

200 fb0be379 Michael Hanselmann
  There are two ways to optimize this. The first, and simpler, is to assign
201 fb0be379 Michael Hanselmann
  each field a group of data, so that the caller can determine which
202 fb0be379 Michael Hanselmann
  computations are necessary depending on the data groups requested. The list
203 fb0be379 Michael Hanselmann
  of referenced groups must also be computed for fields referenced in the
204 fb0be379 Michael Hanselmann
  filter.
205 fb0be379 Michael Hanselmann

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

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

215 fb0be379 Michael Hanselmann
  """
216 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
217 fb0be379 Michael Hanselmann
    """Initializes this class.
218 fb0be379 Michael Hanselmann

219 fb0be379 Michael Hanselmann
    @type namefield: string
220 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
221 fb0be379 Michael Hanselmann

222 fb0be379 Michael Hanselmann
    """
223 fb0be379 Michael Hanselmann
    self._namefield = namefield
224 fb0be379 Michael Hanselmann
225 fb0be379 Michael Hanselmann
    #: Whether all names need to be requested (e.g. if a non-equality operator
226 fb0be379 Michael Hanselmann
    #: has been used)
227 fb0be379 Michael Hanselmann
    self._allnames = False
228 fb0be379 Michael Hanselmann
229 fb0be379 Michael Hanselmann
    #: Which names to request
230 fb0be379 Michael Hanselmann
    self._names = None
231 fb0be379 Michael Hanselmann
232 fb0be379 Michael Hanselmann
    #: Data kinds referenced by the filter (used by L{Query.RequestedData})
233 fb0be379 Michael Hanselmann
    self._datakinds = set()
234 fb0be379 Michael Hanselmann
235 fb0be379 Michael Hanselmann
  def RequestedNames(self):
236 fb0be379 Michael Hanselmann
    """Returns all requested values.
237 fb0be379 Michael Hanselmann

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

241 fb0be379 Michael Hanselmann
    @rtype: list
242 fb0be379 Michael Hanselmann

243 fb0be379 Michael Hanselmann
    """
244 fb0be379 Michael Hanselmann
    if self._allnames or self._names is None:
245 fb0be379 Michael Hanselmann
      return None
246 fb0be379 Michael Hanselmann
247 fb0be379 Michael Hanselmann
    return utils.UniqueSequence(self._names)
248 fb0be379 Michael Hanselmann
249 fb0be379 Michael Hanselmann
  def ReferencedData(self):
250 fb0be379 Michael Hanselmann
    """Returns all kinds of data referenced by the filter.
251 fb0be379 Michael Hanselmann

252 fb0be379 Michael Hanselmann
    """
253 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
254 fb0be379 Michael Hanselmann
255 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
256 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
257 fb0be379 Michael Hanselmann

258 fb0be379 Michael Hanselmann
    """
259 fb0be379 Michael Hanselmann
    self._allnames = True
260 fb0be379 Michael Hanselmann
    self._names = None
261 fb0be379 Michael Hanselmann
262 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
263 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
264 fb0be379 Michael Hanselmann

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

268 fb0be379 Michael Hanselmann
    """
269 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
270 fb0be379 Michael Hanselmann
      self._NeedAllNames()
271 fb0be379 Michael Hanselmann
272 b459a848 Andrea Spadaccini
  def NoteUnaryOp(self, op): # pylint: disable=W0613
273 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
274 fb0be379 Michael Hanselmann

275 fb0be379 Michael Hanselmann
    @type op: string
276 fb0be379 Michael Hanselmann
    @param op: Operator
277 fb0be379 Michael Hanselmann

278 fb0be379 Michael Hanselmann
    """
279 fb0be379 Michael Hanselmann
    self._NeedAllNames()
280 fb0be379 Michael Hanselmann
281 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
282 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
283 fb0be379 Michael Hanselmann

284 fb0be379 Michael Hanselmann
    @type op: string
285 fb0be379 Michael Hanselmann
    @param op: Operator
286 fb0be379 Michael Hanselmann
    @type name: string
287 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
288 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
289 fb0be379 Michael Hanselmann

290 fb0be379 Michael Hanselmann
    """
291 fb0be379 Michael Hanselmann
    if datakind is not None:
292 fb0be379 Michael Hanselmann
      self._datakinds.add(datakind)
293 fb0be379 Michael Hanselmann
294 fb0be379 Michael Hanselmann
    if self._allnames:
295 fb0be379 Michael Hanselmann
      return
296 fb0be379 Michael Hanselmann
297 fb0be379 Michael Hanselmann
    # If any operator other than equality was used, all names need to be
298 fb0be379 Michael Hanselmann
    # retrieved
299 fb0be379 Michael Hanselmann
    if op == qlang.OP_EQUAL and name == self._namefield:
300 fb0be379 Michael Hanselmann
      if self._names is None:
301 fb0be379 Michael Hanselmann
        self._names = []
302 fb0be379 Michael Hanselmann
      self._names.append(value)
303 fb0be379 Michael Hanselmann
    else:
304 fb0be379 Michael Hanselmann
      self._NeedAllNames()
305 fb0be379 Michael Hanselmann
306 fb0be379 Michael Hanselmann
307 fb0be379 Michael Hanselmann
def _WrapLogicOp(op_fn, sentences, ctx, item):
308 fb0be379 Michael Hanselmann
  """Wrapper for logic operator functions.
309 fb0be379 Michael Hanselmann

310 fb0be379 Michael Hanselmann
  """
311 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
312 fb0be379 Michael Hanselmann
313 fb0be379 Michael Hanselmann
314 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
315 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
316 fb0be379 Michael Hanselmann

317 fb0be379 Michael Hanselmann
  """
318 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
319 fb0be379 Michael Hanselmann
320 fb0be379 Michael Hanselmann
321 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
322 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
323 fb0be379 Michael Hanselmann

324 fb0be379 Michael Hanselmann
  """
325 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
326 fb0be379 Michael Hanselmann
327 fb0be379 Michael Hanselmann
328 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
329 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
330 fb0be379 Michael Hanselmann

331 fb0be379 Michael Hanselmann
  """
332 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
333 fb0be379 Michael Hanselmann
334 fb0be379 Michael Hanselmann
335 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
336 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
337 23d0a608 Michael Hanselmann

338 23d0a608 Michael Hanselmann
  """
339 23d0a608 Michael Hanselmann
  try:
340 23d0a608 Michael Hanselmann
    return re.compile(pattern)
341 23d0a608 Michael Hanselmann
  except re.error, err:
342 23d0a608 Michael Hanselmann
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
343 23d0a608 Michael Hanselmann
344 23d0a608 Michael Hanselmann
345 526f866b Michael Hanselmann
def _PrepareSplitTimestamp(value):
346 526f866b Michael Hanselmann
  """Prepares a value for comparison by L{_MakeSplitTimestampComparison}.
347 526f866b Michael Hanselmann

348 526f866b Michael Hanselmann
  """
349 526f866b Michael Hanselmann
  if ht.TNumber(value):
350 526f866b Michael Hanselmann
    return value
351 526f866b Michael Hanselmann
  else:
352 526f866b Michael Hanselmann
    return utils.MergeTime(value)
353 526f866b Michael Hanselmann
354 526f866b Michael Hanselmann
355 526f866b Michael Hanselmann
def _MakeSplitTimestampComparison(fn):
356 526f866b Michael Hanselmann
  """Compares split timestamp values after converting to float.
357 526f866b Michael Hanselmann

358 526f866b Michael Hanselmann
  """
359 526f866b Michael Hanselmann
  return lambda lhs, rhs: fn(utils.MergeTime(lhs), rhs)
360 526f866b Michael Hanselmann
361 526f866b Michael Hanselmann
362 526f866b Michael Hanselmann
def _MakeComparisonChecks(fn):
363 526f866b Michael Hanselmann
  """Prepares flag-specific comparisons using a comparison function.
364 526f866b Michael Hanselmann

365 526f866b Michael Hanselmann
  """
366 526f866b Michael Hanselmann
  return [
367 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(fn),
368 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
369 526f866b Michael Hanselmann
    (QFF_JOB_ID, lambda lhs, rhs: fn(jstore.ParseJobId(lhs), rhs),
370 526f866b Michael Hanselmann
     jstore.ParseJobId),
371 526f866b Michael Hanselmann
    (None, fn, None),
372 526f866b Michael Hanselmann
    ]
373 526f866b Michael Hanselmann
374 526f866b Michael Hanselmann
375 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
376 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
377 fb0be379 Michael Hanselmann

378 fb0be379 Michael Hanselmann
  """
379 b459a848 Andrea Spadaccini
  # String statement has no effect, pylint: disable=W0105
380 fb0be379 Michael Hanselmann
381 fb0be379 Michael Hanselmann
  #: How deep filters can be nested
382 fb0be379 Michael Hanselmann
  _LEVELS_MAX = 10
383 fb0be379 Michael Hanselmann
384 fb0be379 Michael Hanselmann
  # Unique identifiers for operator groups
385 fb0be379 Michael Hanselmann
  (_OPTYPE_LOGIC,
386 fb0be379 Michael Hanselmann
   _OPTYPE_UNARY,
387 fb0be379 Michael Hanselmann
   _OPTYPE_BINARY) = range(1, 4)
388 fb0be379 Michael Hanselmann
389 fb0be379 Michael Hanselmann
  """Functions for equality checks depending on field flags.
390 fb0be379 Michael Hanselmann

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

395 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
396 fb0be379 Michael Hanselmann
  using binary AND.
397 fb0be379 Michael Hanselmann

398 fb0be379 Michael Hanselmann
  """
399 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
400 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
401 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
402 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
403 23d0a608 Michael Hanselmann
     None),
404 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(operator.eq),
405 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
406 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
407 fb0be379 Michael Hanselmann
    ]
408 fb0be379 Michael Hanselmann
409 fb0be379 Michael Hanselmann
  """Known operators
410 fb0be379 Michael Hanselmann

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

414 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
415 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
416 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
417 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
418 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
419 fb0be379 Michael Hanselmann

420 fb0be379 Michael Hanselmann
  """
421 fb0be379 Michael Hanselmann
  _OPS = {
422 fb0be379 Michael Hanselmann
    # Logic operators
423 fb0be379 Michael Hanselmann
    qlang.OP_OR: (_OPTYPE_LOGIC, compat.any),
424 fb0be379 Michael Hanselmann
    qlang.OP_AND: (_OPTYPE_LOGIC, compat.all),
425 fb0be379 Michael Hanselmann
426 fb0be379 Michael Hanselmann
    # Unary operators
427 3b877f08 Michael Hanselmann
    qlang.OP_NOT: (_OPTYPE_UNARY, None),
428 3b877f08 Michael Hanselmann
    qlang.OP_TRUE: (_OPTYPE_UNARY, None),
429 fb0be379 Michael Hanselmann
430 fb0be379 Michael Hanselmann
    # Binary operators
431 fb0be379 Michael Hanselmann
    qlang.OP_EQUAL: (_OPTYPE_BINARY, _EQUALITY_CHECKS),
432 fb0be379 Michael Hanselmann
    qlang.OP_NOT_EQUAL:
433 23d0a608 Michael Hanselmann
      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn), valprepfn)
434 23d0a608 Michael Hanselmann
                        for (flags, fn, valprepfn) in _EQUALITY_CHECKS]),
435 526f866b Michael Hanselmann
    qlang.OP_LT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.lt)),
436 526f866b Michael Hanselmann
    qlang.OP_LE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.le)),
437 526f866b Michael Hanselmann
    qlang.OP_GT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.gt)),
438 526f866b Michael Hanselmann
    qlang.OP_GE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.ge)),
439 23d0a608 Michael Hanselmann
    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
440 23d0a608 Michael Hanselmann
      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
441 23d0a608 Michael Hanselmann
      ]),
442 fb0be379 Michael Hanselmann
    qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
443 23d0a608 Michael Hanselmann
      (None, operator.contains, None),
444 fb0be379 Michael Hanselmann
      ]),
445 fb0be379 Michael Hanselmann
    }
446 fb0be379 Michael Hanselmann
447 fb0be379 Michael Hanselmann
  def __init__(self, fields):
448 fb0be379 Michael Hanselmann
    """Initializes this class.
449 fb0be379 Michael Hanselmann

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

452 fb0be379 Michael Hanselmann
    """
453 fb0be379 Michael Hanselmann
    self._fields = fields
454 fb0be379 Michael Hanselmann
    self._hints = None
455 fb0be379 Michael Hanselmann
    self._op_handler = None
456 fb0be379 Michael Hanselmann
457 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
458 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
459 fb0be379 Michael Hanselmann

460 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
461 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
462 2e5c33db Iustin Pop
    @type qfilter: list
463 2e5c33db Iustin Pop
    @param qfilter: Filter structure
464 fb0be379 Michael Hanselmann
    @rtype: callable
465 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
466 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
467 fb0be379 Michael Hanselmann

468 fb0be379 Michael Hanselmann
    """
469 fb0be379 Michael Hanselmann
    self._op_handler = {
470 fb0be379 Michael Hanselmann
      self._OPTYPE_LOGIC:
471 fb0be379 Michael Hanselmann
        (self._HandleLogicOp, getattr(hints, "NoteLogicOp", None)),
472 fb0be379 Michael Hanselmann
      self._OPTYPE_UNARY:
473 fb0be379 Michael Hanselmann
        (self._HandleUnaryOp, getattr(hints, "NoteUnaryOp", None)),
474 fb0be379 Michael Hanselmann
      self._OPTYPE_BINARY:
475 fb0be379 Michael Hanselmann
        (self._HandleBinaryOp, getattr(hints, "NoteBinaryOp", None)),
476 fb0be379 Michael Hanselmann
      }
477 fb0be379 Michael Hanselmann
478 fb0be379 Michael Hanselmann
    try:
479 2e5c33db Iustin Pop
      filter_fn = self._Compile(qfilter, 0)
480 fb0be379 Michael Hanselmann
    finally:
481 fb0be379 Michael Hanselmann
      self._op_handler = None
482 fb0be379 Michael Hanselmann
483 fb0be379 Michael Hanselmann
    return filter_fn
484 fb0be379 Michael Hanselmann
485 2e5c33db Iustin Pop
  def _Compile(self, qfilter, level):
486 fb0be379 Michael Hanselmann
    """Inner function for converting filters.
487 fb0be379 Michael Hanselmann

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

491 fb0be379 Michael Hanselmann
    """
492 2e5c33db Iustin Pop
    if not (isinstance(qfilter, (list, tuple)) and qfilter):
493 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid filter on level %s" % level)
494 fb0be379 Michael Hanselmann
495 fb0be379 Michael Hanselmann
    # Limit recursion
496 fb0be379 Michael Hanselmann
    if level >= self._LEVELS_MAX:
497 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Only up to %s levels are allowed (filter"
498 fb0be379 Michael Hanselmann
                                  " nested too deep)" % self._LEVELS_MAX)
499 fb0be379 Michael Hanselmann
500 fb0be379 Michael Hanselmann
    # Create copy to be modified
501 2e5c33db Iustin Pop
    operands = qfilter[:]
502 fb0be379 Michael Hanselmann
    op = operands.pop(0)
503 fb0be379 Michael Hanselmann
504 fb0be379 Michael Hanselmann
    try:
505 fb0be379 Michael Hanselmann
      (kind, op_data) = self._OPS[op]
506 fb0be379 Michael Hanselmann
    except KeyError:
507 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unknown operator '%s'" % op)
508 fb0be379 Michael Hanselmann
509 fb0be379 Michael Hanselmann
    (handler, hints_cb) = self._op_handler[kind]
510 fb0be379 Michael Hanselmann
511 fb0be379 Michael Hanselmann
    return handler(hints_cb, level, op, op_data, operands)
512 fb0be379 Michael Hanselmann
513 3b877f08 Michael Hanselmann
  def _LookupField(self, name):
514 3b877f08 Michael Hanselmann
    """Returns a field definition by name.
515 3b877f08 Michael Hanselmann

516 3b877f08 Michael Hanselmann
    """
517 3b877f08 Michael Hanselmann
    try:
518 3b877f08 Michael Hanselmann
      return self._fields[name]
519 3b877f08 Michael Hanselmann
    except KeyError:
520 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
521 3b877f08 Michael Hanselmann
522 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
523 fb0be379 Michael Hanselmann
    """Handles logic operators.
524 fb0be379 Michael Hanselmann

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

536 fb0be379 Michael Hanselmann
    """
537 fb0be379 Michael Hanselmann
    if hints_fn:
538 fb0be379 Michael Hanselmann
      hints_fn(op)
539 fb0be379 Michael Hanselmann
540 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
541 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
542 fb0be379 Michael Hanselmann
543 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
544 fb0be379 Michael Hanselmann
    """Handles unary operators.
545 fb0be379 Michael Hanselmann

546 fb0be379 Michael Hanselmann
    @type hints_fn: callable
547 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
548 fb0be379 Michael Hanselmann
    @type level: integer
549 fb0be379 Michael Hanselmann
    @param level: Current depth
550 fb0be379 Michael Hanselmann
    @type op: string
551 fb0be379 Michael Hanselmann
    @param op: Operator
552 fb0be379 Michael Hanselmann
    @type op_fn: callable
553 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
554 fb0be379 Michael Hanselmann
    @type operands: list
555 fb0be379 Michael Hanselmann
    @param operands: List of operands
556 fb0be379 Michael Hanselmann

557 fb0be379 Michael Hanselmann
    """
558 3b877f08 Michael Hanselmann
    assert op_fn is None
559 3b877f08 Michael Hanselmann
560 fb0be379 Michael Hanselmann
    if hints_fn:
561 fb0be379 Michael Hanselmann
      hints_fn(op)
562 fb0be379 Michael Hanselmann
563 fb0be379 Michael Hanselmann
    if len(operands) != 1:
564 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unary operator '%s' expects exactly one"
565 fb0be379 Michael Hanselmann
                                  " operand" % op)
566 fb0be379 Michael Hanselmann
567 3b877f08 Michael Hanselmann
    if op == qlang.OP_TRUE:
568 3b877f08 Michael Hanselmann
      (_, _, _, retrieval_fn) = self._LookupField(operands[0])
569 3b877f08 Michael Hanselmann
570 3b877f08 Michael Hanselmann
      op_fn = operator.truth
571 3b877f08 Michael Hanselmann
      arg = retrieval_fn
572 3b877f08 Michael Hanselmann
    elif op == qlang.OP_NOT:
573 3b877f08 Michael Hanselmann
      op_fn = operator.not_
574 3b877f08 Michael Hanselmann
      arg = self._Compile(operands[0], level + 1)
575 3b877f08 Michael Hanselmann
    else:
576 3b877f08 Michael Hanselmann
      raise errors.ProgrammerError("Can't handle operator '%s'" % op)
577 3b877f08 Michael Hanselmann
578 3b877f08 Michael Hanselmann
    return compat.partial(_WrapUnaryOp, op_fn, arg)
579 fb0be379 Michael Hanselmann
580 fb0be379 Michael Hanselmann
  def _HandleBinaryOp(self, hints_fn, level, op, op_data, operands):
581 fb0be379 Michael Hanselmann
    """Handles binary operators.
582 fb0be379 Michael Hanselmann

583 fb0be379 Michael Hanselmann
    @type hints_fn: callable
584 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
585 fb0be379 Michael Hanselmann
    @type level: integer
586 fb0be379 Michael Hanselmann
    @param level: Current depth
587 fb0be379 Michael Hanselmann
    @type op: string
588 fb0be379 Michael Hanselmann
    @param op: Operator
589 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
590 fb0be379 Michael Hanselmann
    @type operands: list
591 fb0be379 Michael Hanselmann
    @param operands: List of operands
592 fb0be379 Michael Hanselmann

593 fb0be379 Michael Hanselmann
    """
594 b459a848 Andrea Spadaccini
    # Unused arguments, pylint: disable=W0613
595 fb0be379 Michael Hanselmann
    try:
596 fb0be379 Michael Hanselmann
      (name, value) = operands
597 fb0be379 Michael Hanselmann
    except (ValueError, TypeError):
598 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid binary operator, expected exactly"
599 fb0be379 Michael Hanselmann
                                  " two operands")
600 fb0be379 Michael Hanselmann
601 3b877f08 Michael Hanselmann
    (fdef, datakind, field_flags, retrieval_fn) = self._LookupField(name)
602 fb0be379 Michael Hanselmann
603 fb0be379 Michael Hanselmann
    assert fdef.kind != QFT_UNKNOWN
604 fb0be379 Michael Hanselmann
605 fb0be379 Michael Hanselmann
    # TODO: Type conversions?
606 fb0be379 Michael Hanselmann
607 fb0be379 Michael Hanselmann
    verify_fn = _VERIFY_FN[fdef.kind]
608 fb0be379 Michael Hanselmann
    if not verify_fn(value):
609 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unable to compare field '%s' (type '%s')"
610 fb0be379 Michael Hanselmann
                                  " with '%s', expected %s" %
611 fb0be379 Michael Hanselmann
                                  (name, fdef.kind, value.__class__.__name__,
612 fb0be379 Michael Hanselmann
                                   verify_fn))
613 fb0be379 Michael Hanselmann
614 fb0be379 Michael Hanselmann
    if hints_fn:
615 fb0be379 Michael Hanselmann
      hints_fn(op, datakind, name, value)
616 fb0be379 Michael Hanselmann
617 23d0a608 Michael Hanselmann
    for (fn_flags, fn, valprepfn) in op_data:
618 fb0be379 Michael Hanselmann
      if fn_flags is None or fn_flags & field_flags:
619 23d0a608 Michael Hanselmann
        # Prepare value if necessary (e.g. compile regular expression)
620 23d0a608 Michael Hanselmann
        if valprepfn:
621 23d0a608 Michael Hanselmann
          value = valprepfn(value)
622 23d0a608 Michael Hanselmann
623 fb0be379 Michael Hanselmann
        return compat.partial(_WrapBinaryOp, fn, retrieval_fn, value)
624 fb0be379 Michael Hanselmann
625 fb0be379 Michael Hanselmann
    raise errors.ProgrammerError("Unable to find operator implementation"
626 fb0be379 Michael Hanselmann
                                 " (op '%s', flags %s)" % (op, field_flags))
627 fb0be379 Michael Hanselmann
628 fb0be379 Michael Hanselmann
629 2e5c33db Iustin Pop
def _CompileFilter(fields, hints, qfilter):
630 fb0be379 Michael Hanselmann
  """Converts a query filter into a callable function.
631 fb0be379 Michael Hanselmann

632 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
633 fb0be379 Michael Hanselmann

634 fb0be379 Michael Hanselmann
  @rtype: callable
635 fb0be379 Michael Hanselmann

636 fb0be379 Michael Hanselmann
  """
637 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
638 fb0be379 Michael Hanselmann
639 fb0be379 Michael Hanselmann
640 4ca96421 Michael Hanselmann
class Query:
641 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
642 4ca96421 Michael Hanselmann
    """Initializes this class.
643 4ca96421 Michael Hanselmann

644 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
645 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
646 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
647 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
648 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
649 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
650 4ca96421 Michael Hanselmann

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

654 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
655 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
656 4ca96421 Michael Hanselmann
    @type selected: list of strings
657 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
658 4ca96421 Michael Hanselmann

659 4ca96421 Michael Hanselmann
    """
660 fb0be379 Michael Hanselmann
    assert namefield is None or namefield in fieldlist
661 fb0be379 Michael Hanselmann
662 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
663 4ca96421 Michael Hanselmann
664 fb0be379 Michael Hanselmann
    self._filter_fn = None
665 fb0be379 Michael Hanselmann
    self._requested_names = None
666 fb0be379 Michael Hanselmann
    self._filter_datakinds = frozenset()
667 fb0be379 Michael Hanselmann
668 2e5c33db Iustin Pop
    if qfilter is not None:
669 fb0be379 Michael Hanselmann
      # Collect requested names if wanted
670 fb0be379 Michael Hanselmann
      if namefield:
671 fb0be379 Michael Hanselmann
        hints = _FilterHints(namefield)
672 fb0be379 Michael Hanselmann
      else:
673 fb0be379 Michael Hanselmann
        hints = None
674 fb0be379 Michael Hanselmann
675 fb0be379 Michael Hanselmann
      # Build filter function
676 2e5c33db Iustin Pop
      self._filter_fn = _CompileFilter(fieldlist, hints, qfilter)
677 fb0be379 Michael Hanselmann
      if hints:
678 fb0be379 Michael Hanselmann
        self._requested_names = hints.RequestedNames()
679 fb0be379 Michael Hanselmann
        self._filter_datakinds = hints.ReferencedData()
680 fb0be379 Michael Hanselmann
681 fb0be379 Michael Hanselmann
    if namefield is None:
682 fb0be379 Michael Hanselmann
      self._name_fn = None
683 fb0be379 Michael Hanselmann
    else:
684 fb0be379 Michael Hanselmann
      (_, _, _, self._name_fn) = fieldlist[namefield]
685 fb0be379 Michael Hanselmann
686 fb0be379 Michael Hanselmann
  def RequestedNames(self):
687 fb0be379 Michael Hanselmann
    """Returns all names referenced in the filter.
688 fb0be379 Michael Hanselmann

689 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
690 fb0be379 Michael Hanselmann
    names, C{None} is returned.
691 fb0be379 Michael Hanselmann

692 fb0be379 Michael Hanselmann
    """
693 fb0be379 Michael Hanselmann
    return self._requested_names
694 fb0be379 Michael Hanselmann
695 4ca96421 Michael Hanselmann
  def RequestedData(self):
696 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
697 4ca96421 Michael Hanselmann

698 4ca96421 Michael Hanselmann
    @rtype: frozenset
699 4ca96421 Michael Hanselmann

700 4ca96421 Michael Hanselmann
    """
701 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
702 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
703 fb0be379 Michael Hanselmann
                      if datakind is not None))
704 4ca96421 Michael Hanselmann
705 4ca96421 Michael Hanselmann
  def GetFields(self):
706 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
707 4ca96421 Michael Hanselmann

708 4ca96421 Michael Hanselmann
    Includes unknown fields.
709 4ca96421 Michael Hanselmann

710 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
711 4ca96421 Michael Hanselmann

712 4ca96421 Michael Hanselmann
    """
713 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
714 4ca96421 Michael Hanselmann
715 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
716 4ca96421 Michael Hanselmann
    """Execute a query.
717 4ca96421 Michael Hanselmann

718 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
719 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
720 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
721 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
722 fbc263a9 Michael Hanselmann
      ordering
723 4ca96421 Michael Hanselmann

724 4ca96421 Michael Hanselmann
    """
725 fbc263a9 Michael Hanselmann
    sort = (self._name_fn and sort_by_name)
726 fbc263a9 Michael Hanselmann
727 fb0be379 Michael Hanselmann
    result = []
728 fb0be379 Michael Hanselmann
729 fb0be379 Michael Hanselmann
    for idx, item in enumerate(ctx):
730 fb0be379 Michael Hanselmann
      if not (self._filter_fn is None or self._filter_fn(ctx, item)):
731 fb0be379 Michael Hanselmann
        continue
732 4ca96421 Michael Hanselmann
733 fb0be379 Michael Hanselmann
      row = [_ProcessResult(fn(ctx, item)) for (_, _, _, fn) in self._fields]
734 fb0be379 Michael Hanselmann
735 fb0be379 Michael Hanselmann
      # Verify result
736 fb0be379 Michael Hanselmann
      if __debug__:
737 d1c3c3b3 Iustin Pop
        _VerifyResultRow(self._fields, row)
738 4ca96421 Michael Hanselmann
739 fbc263a9 Michael Hanselmann
      if sort:
740 fb0be379 Michael Hanselmann
        (status, name) = _ProcessResult(self._name_fn(ctx, item))
741 fb0be379 Michael Hanselmann
        assert status == constants.RS_NORMAL
742 fb0be379 Michael Hanselmann
        # TODO: Are there cases where we wouldn't want to use NiceSort?
743 76b62028 Iustin Pop
        # Answer: if the name field is non-string...
744 fbc263a9 Michael Hanselmann
        result.append((utils.NiceSortKey(name), idx, row))
745 fb0be379 Michael Hanselmann
      else:
746 fbc263a9 Michael Hanselmann
        result.append(row)
747 fb0be379 Michael Hanselmann
748 fbc263a9 Michael Hanselmann
    if not sort:
749 fbc263a9 Michael Hanselmann
      return result
750 fb0be379 Michael Hanselmann
751 fb0be379 Michael Hanselmann
    # TODO: Would "heapq" be more efficient than sorting?
752 fb0be379 Michael Hanselmann
753 fb0be379 Michael Hanselmann
    # Sorting in-place instead of using "sorted()"
754 fb0be379 Michael Hanselmann
    result.sort()
755 fb0be379 Michael Hanselmann
756 fb0be379 Michael Hanselmann
    assert not result or (len(result[0]) == 3 and len(result[-1]) == 3)
757 fb0be379 Michael Hanselmann
758 fb0be379 Michael Hanselmann
    return map(operator.itemgetter(2), result)
759 4ca96421 Michael Hanselmann
760 fbc263a9 Michael Hanselmann
  def OldStyleQuery(self, ctx, sort_by_name=True):
761 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
762 4ca96421 Michael Hanselmann

763 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
764 4ca96421 Michael Hanselmann

765 4ca96421 Michael Hanselmann
    """
766 111bf531 Michael Hanselmann
    unknown = set(fdef.name for (fdef, _, _, _) in self._fields
767 111bf531 Michael Hanselmann
                  if fdef.kind == QFT_UNKNOWN)
768 4ca96421 Michael Hanselmann
    if unknown:
769 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
770 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
771 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
772 4ca96421 Michael Hanselmann
773 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
774 fbc263a9 Michael Hanselmann
            for row in self.Query(ctx, sort_by_name=sort_by_name)]
775 4ca96421 Michael Hanselmann
776 4ca96421 Michael Hanselmann
777 e2d188cc Iustin Pop
def _ProcessResult(value):
778 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
779 e2d188cc Iustin Pop

780 e2d188cc Iustin Pop
  """
781 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
782 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
783 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
784 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
785 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
786 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
787 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
788 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
789 e2d188cc Iustin Pop
  else:
790 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
791 e2d188cc Iustin Pop
792 e2d188cc Iustin Pop
793 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
794 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
795 4ca96421 Michael Hanselmann

796 4ca96421 Michael Hanselmann
  @type fields: list
797 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
798 4ca96421 Michael Hanselmann
  @type row: list of tuples
799 4ca96421 Michael Hanselmann
  @param row: Row data
800 4ca96421 Michael Hanselmann

801 4ca96421 Michael Hanselmann
  """
802 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
803 d1c3c3b3 Iustin Pop
  errs = []
804 111bf531 Michael Hanselmann
  for ((status, value), (fdef, _, _, _)) in zip(row, fields):
805 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
806 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
807 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
808 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
809 d1c3c3b3 Iustin Pop
    elif value is not None:
810 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
811 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
812 34598551 Agata Murawska
                    (utils.CommaJoin(errs), row))
813 4ca96421 Michael Hanselmann
814 4ca96421 Michael Hanselmann
815 320e34df Michael Hanselmann
def _FieldDictKey((fdef, _, flags, fn)):
816 320e34df Michael Hanselmann
  """Generates key for field dictionary.
817 320e34df Michael Hanselmann

818 320e34df Michael Hanselmann
  """
819 320e34df Michael Hanselmann
  assert fdef.name and fdef.title, "Name and title are required"
820 320e34df Michael Hanselmann
  assert FIELD_NAME_RE.match(fdef.name)
821 320e34df Michael Hanselmann
  assert TITLE_RE.match(fdef.title)
822 320e34df Michael Hanselmann
  assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
823 320e34df Michael Hanselmann
          fdef.doc.strip() == fdef.doc), \
824 320e34df Michael Hanselmann
         "Invalid description for field '%s'" % fdef.name
825 320e34df Michael Hanselmann
  assert callable(fn)
826 320e34df Michael Hanselmann
  assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
827 320e34df Michael Hanselmann
828 320e34df Michael Hanselmann
  return fdef.name
829 320e34df Michael Hanselmann
830 320e34df Michael Hanselmann
831 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
832 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
833 4ca96421 Michael Hanselmann

834 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
835 4ca96421 Michael Hanselmann

836 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
837 d63bd540 Iustin Pop
      kind, retrieval function)
838 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
839 d63bd540 Iustin Pop
      description
840 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
841 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
842 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
843 4ca96421 Michael Hanselmann
  @rtype: dict
844 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
845 4ca96421 Michael Hanselmann

846 4ca96421 Michael Hanselmann
  """
847 89ce4acc Michael Hanselmann
  if __debug__:
848 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
849 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
850 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
851 4ca96421 Michael Hanselmann
852 320e34df Michael Hanselmann
  result = utils.SequenceToDict(fields, key=_FieldDictKey)
853 4ca96421 Michael Hanselmann
854 d63bd540 Iustin Pop
  for alias, target in aliases:
855 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
856 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
857 111bf531 Michael Hanselmann
    (fdef, k, flags, fn) = result[target]
858 d63bd540 Iustin Pop
    fdef = fdef.Copy()
859 d63bd540 Iustin Pop
    fdef.name = alias
860 111bf531 Michael Hanselmann
    result[alias] = (fdef, k, flags, fn)
861 d63bd540 Iustin Pop
862 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
863 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
864 111bf531 Michael Hanselmann
                    for (name, (fdef, _, _, _)) in result.items())
865 4ca96421 Michael Hanselmann
866 4ca96421 Michael Hanselmann
  return result
867 4ca96421 Michael Hanselmann
868 4ca96421 Michael Hanselmann
869 fbc263a9 Michael Hanselmann
def GetQueryResponse(query, ctx, sort_by_name=True):
870 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
871 b60fcb6f Michael Hanselmann

872 b60fcb6f Michael Hanselmann
  @type query: L{Query}
873 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
874 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
875 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
876 fbc263a9 Michael Hanselmann
    ordering
877 b60fcb6f Michael Hanselmann

878 b60fcb6f Michael Hanselmann
  """
879 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
880 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
881 b60fcb6f Michael Hanselmann
882 b60fcb6f Michael Hanselmann
883 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
884 aa29e95f Michael Hanselmann
  """Returns list of available fields.
885 aa29e95f Michael Hanselmann

886 aa29e95f Michael Hanselmann
  @type fielddefs: dict
887 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
888 aa29e95f Michael Hanselmann
  @type selected: list of strings
889 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
890 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
891 aa29e95f Michael Hanselmann

892 aa29e95f Michael Hanselmann
  """
893 aa29e95f Michael Hanselmann
  if selected is None:
894 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
895 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
896 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
897 aa29e95f Michael Hanselmann
  else:
898 aa29e95f Michael Hanselmann
    # Keep order as requested by client
899 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
900 aa29e95f Michael Hanselmann
901 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
902 aa29e95f Michael Hanselmann
903 aa29e95f Michael Hanselmann
904 79b2ca83 Michael Hanselmann
def _MakeField(name, title, kind, doc):
905 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
906 4ca96421 Michael Hanselmann

907 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
908 4ca96421 Michael Hanselmann
  @param title: Human-readable title
909 4ca96421 Michael Hanselmann
  @param kind: Field type
910 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
911 4ca96421 Michael Hanselmann

912 4ca96421 Michael Hanselmann
  """
913 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
914 1ae17369 Michael Hanselmann
                                      doc=doc)
915 8235fe04 Michael Hanselmann
916 8235fe04 Michael Hanselmann
917 dff5f600 Michael Hanselmann
def _StaticValueInner(value, ctx, _): # pylint: disable=W0613
918 dff5f600 Michael Hanselmann
  """Returns a static value.
919 dff5f600 Michael Hanselmann

920 dff5f600 Michael Hanselmann
  """
921 dff5f600 Michael Hanselmann
  return value
922 dff5f600 Michael Hanselmann
923 dff5f600 Michael Hanselmann
924 dff5f600 Michael Hanselmann
def _StaticValue(value):
925 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
926 dff5f600 Michael Hanselmann

927 dff5f600 Michael Hanselmann
  """
928 dff5f600 Michael Hanselmann
  return compat.partial(_StaticValueInner, value)
929 dff5f600 Michael Hanselmann
930 dff5f600 Michael Hanselmann
931 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
932 8235fe04 Michael Hanselmann
  """Determine node role.
933 8235fe04 Michael Hanselmann

934 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
935 8235fe04 Michael Hanselmann
  @param node: Node object
936 8235fe04 Michael Hanselmann
  @type master_name: string
937 8235fe04 Michael Hanselmann
  @param master_name: Master node name
938 8235fe04 Michael Hanselmann

939 8235fe04 Michael Hanselmann
  """
940 8235fe04 Michael Hanselmann
  if node.name == master_name:
941 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
942 8235fe04 Michael Hanselmann
  elif node.master_candidate:
943 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
944 8235fe04 Michael Hanselmann
  elif node.drained:
945 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
946 8235fe04 Michael Hanselmann
  elif node.offline:
947 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
948 8235fe04 Michael Hanselmann
  else:
949 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
950 8235fe04 Michael Hanselmann
951 8235fe04 Michael Hanselmann
952 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
953 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
954 8235fe04 Michael Hanselmann

955 8235fe04 Michael Hanselmann
  @param attr: Attribute name
956 8235fe04 Michael Hanselmann

957 8235fe04 Michael Hanselmann
  """
958 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
959 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
960 8235fe04 Michael Hanselmann
961 8235fe04 Michael Hanselmann
962 8930b0f0 Iustin Pop
def _GetNDParam(name):
963 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
964 8930b0f0 Iustin Pop

965 8930b0f0 Iustin Pop
  """
966 8930b0f0 Iustin Pop
  def _helper(ctx, _):
967 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
968 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
969 8930b0f0 Iustin Pop
    else:
970 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
971 8930b0f0 Iustin Pop
  return _helper
972 8930b0f0 Iustin Pop
973 8930b0f0 Iustin Pop
974 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
975 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
976 8930b0f0 Iustin Pop

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

979 8930b0f0 Iustin Pop
  """
980 8930b0f0 Iustin Pop
  if is_group:
981 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
982 8930b0f0 Iustin Pop
  else:
983 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
984 a6c7e2a2 Iustin Pop
  return [(_MakeField("ndp/%s" % name,
985 a6c7e2a2 Iustin Pop
                      constants.NDS_PARAMETER_TITLES.get(name,
986 a6c7e2a2 Iustin Pop
                                                         "ndp/%s" % name),
987 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
988 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
989 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
990 8930b0f0 Iustin Pop
991 8930b0f0 Iustin Pop
992 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
993 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
994 425e5bf0 Michael Hanselmann

995 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
996 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
997 425e5bf0 Michael Hanselmann

998 425e5bf0 Michael Hanselmann
  """
999 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
1000 425e5bf0 Michael Hanselmann
1001 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
1002 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
1003 425e5bf0 Michael Hanselmann
    # Return right away
1004 425e5bf0 Michael Hanselmann
    return value
1005 425e5bf0 Michael Hanselmann
1006 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
1007 425e5bf0 Michael Hanselmann
  return convert(value)
1008 425e5bf0 Michael Hanselmann
1009 425e5bf0 Michael Hanselmann
1010 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
1011 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
1012 425e5bf0 Michael Hanselmann

1013 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1014 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1015 425e5bf0 Michael Hanselmann

1016 425e5bf0 Michael Hanselmann
  """
1017 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
1018 425e5bf0 Michael Hanselmann
1019 425e5bf0 Michael Hanselmann
1020 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
1021 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
1022 145bea54 Michael Hanselmann

1023 145bea54 Michael Hanselmann
  @type getter: callable
1024 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1025 145bea54 Michael Hanselmann

1026 145bea54 Michael Hanselmann
  """
1027 145bea54 Michael Hanselmann
  def fn(_, item):
1028 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1029 145bea54 Michael Hanselmann

1030 145bea54 Michael Hanselmann
    """
1031 145bea54 Michael Hanselmann
    timestamp = getter(item)
1032 145bea54 Michael Hanselmann
    if timestamp is None:
1033 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
1034 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1035 145bea54 Michael Hanselmann
    else:
1036 e2d188cc Iustin Pop
      return timestamp
1037 145bea54 Michael Hanselmann
1038 145bea54 Michael Hanselmann
  return fn
1039 145bea54 Michael Hanselmann
1040 145bea54 Michael Hanselmann
1041 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
1042 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
1043 145bea54 Michael Hanselmann

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

1046 145bea54 Michael Hanselmann
  """
1047 145bea54 Michael Hanselmann
  return [
1048 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
1049 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
1050 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
1051 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
1052 145bea54 Michael Hanselmann
    ]
1053 145bea54 Michael Hanselmann
1054 145bea54 Michael Hanselmann
1055 8235fe04 Michael Hanselmann
class NodeQueryData:
1056 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1057 8235fe04 Michael Hanselmann

1058 8235fe04 Michael Hanselmann
  """
1059 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1060 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1061 8235fe04 Michael Hanselmann
    """Initializes this class.
1062 8235fe04 Michael Hanselmann

1063 8235fe04 Michael Hanselmann
    """
1064 8235fe04 Michael Hanselmann
    self.nodes = nodes
1065 8235fe04 Michael Hanselmann
    self.live_data = live_data
1066 8235fe04 Michael Hanselmann
    self.master_name = master_name
1067 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1068 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1069 8235fe04 Michael Hanselmann
    self.groups = groups
1070 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1071 8572f1fe René Nussbaumer
    self.cluster = cluster
1072 8235fe04 Michael Hanselmann
1073 8235fe04 Michael Hanselmann
    # Used for individual rows
1074 8235fe04 Michael Hanselmann
    self.curlive_data = None
1075 8930b0f0 Iustin Pop
    self.ndparams = None
1076 8235fe04 Michael Hanselmann
1077 8235fe04 Michael Hanselmann
  def __iter__(self):
1078 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1079 8235fe04 Michael Hanselmann

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

1083 8235fe04 Michael Hanselmann
    """
1084 8235fe04 Michael Hanselmann
    for node in self.nodes:
1085 8930b0f0 Iustin Pop
      group = self.groups.get(node.group, None)
1086 8930b0f0 Iustin Pop
      if group is None:
1087 8930b0f0 Iustin Pop
        self.ndparams = None
1088 8930b0f0 Iustin Pop
      else:
1089 8930b0f0 Iustin Pop
        self.ndparams = self.cluster.FillND(node, group)
1090 8235fe04 Michael Hanselmann
      if self.live_data:
1091 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
1092 8235fe04 Michael Hanselmann
      else:
1093 8235fe04 Michael Hanselmann
        self.curlive_data = None
1094 8235fe04 Michael Hanselmann
      yield node
1095 8235fe04 Michael Hanselmann
1096 8235fe04 Michael Hanselmann
1097 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
1098 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
1099 111bf531 Michael Hanselmann
  "drained": ("Drained", QFT_BOOL, 0, "Whether node is drained"),
1100 111bf531 Michael Hanselmann
  "master_candidate": ("MasterC", QFT_BOOL, 0,
1101 79b2ca83 Michael Hanselmann
                       "Whether node is a master candidate"),
1102 111bf531 Michael Hanselmann
  "master_capable": ("MasterCapable", QFT_BOOL, 0,
1103 79b2ca83 Michael Hanselmann
                     "Whether node can become a master candidate"),
1104 111bf531 Michael Hanselmann
  "name": ("Node", QFT_TEXT, QFF_HOSTNAME, "Node name"),
1105 111bf531 Michael Hanselmann
  "offline": ("Offline", QFT_BOOL, 0, "Whether node is marked offline"),
1106 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Node"),
1107 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Node UUID"),
1108 111bf531 Michael Hanselmann
  "vm_capable": ("VMCapable", QFT_BOOL, 0, "Whether node can host instances"),
1109 8235fe04 Michael Hanselmann
  }
1110 8235fe04 Michael Hanselmann
1111 8235fe04 Michael Hanselmann
1112 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
1113 effab4ca Iustin Pop
# Note that none of these are available for non-vm_capable nodes
1114 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
1115 79b2ca83 Michael Hanselmann
  "bootid": ("BootID", QFT_TEXT, "bootid",
1116 79b2ca83 Michael Hanselmann
             "Random UUID renewed for each system reboot, can be used"
1117 79b2ca83 Michael Hanselmann
             " for detecting reboots by tracking changes"),
1118 79b2ca83 Michael Hanselmann
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes",
1119 79b2ca83 Michael Hanselmann
             "Number of NUMA domains on node (if exported by hypervisor)"),
1120 79b2ca83 Michael Hanselmann
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets",
1121 79b2ca83 Michael Hanselmann
               "Number of physical CPU sockets (if exported by hypervisor)"),
1122 79b2ca83 Michael Hanselmann
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total", "Number of logical processors"),
1123 79b2ca83 Michael Hanselmann
  "dfree": ("DFree", QFT_UNIT, "vg_free",
1124 79b2ca83 Michael Hanselmann
            "Available disk space in volume group"),
1125 79b2ca83 Michael Hanselmann
  "dtotal": ("DTotal", QFT_UNIT, "vg_size",
1126 79b2ca83 Michael Hanselmann
             "Total disk space in volume group used for instance disk"
1127 79b2ca83 Michael Hanselmann
             " allocation"),
1128 79b2ca83 Michael Hanselmann
  "mfree": ("MFree", QFT_UNIT, "memory_free",
1129 79b2ca83 Michael Hanselmann
            "Memory available for instance allocations"),
1130 79b2ca83 Michael Hanselmann
  "mnode": ("MNode", QFT_UNIT, "memory_dom0",
1131 79b2ca83 Michael Hanselmann
            "Amount of memory used by node (dom0 for Xen)"),
1132 79b2ca83 Michael Hanselmann
  "mtotal": ("MTotal", QFT_UNIT, "memory_total",
1133 79b2ca83 Michael Hanselmann
             "Total amount of memory of physical machine"),
1134 8235fe04 Michael Hanselmann
  }
1135 8235fe04 Michael Hanselmann
1136 8235fe04 Michael Hanselmann
1137 8572f1fe René Nussbaumer
def _GetGroup(cb):
1138 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
1139 8572f1fe René Nussbaumer

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

1142 8572f1fe René Nussbaumer
  """
1143 8572f1fe René Nussbaumer
  def fn(ctx, node):
1144 8572f1fe René Nussbaumer
    """Get group data for a node.
1145 8572f1fe René Nussbaumer

1146 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1147 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1148 8572f1fe René Nussbaumer
    @param inst: Node object
1149 8572f1fe René Nussbaumer

1150 8572f1fe René Nussbaumer
    """
1151 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1152 8572f1fe René Nussbaumer
    if ng is None:
1153 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1154 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1155 8572f1fe René Nussbaumer
1156 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1157 8572f1fe René Nussbaumer
1158 8572f1fe René Nussbaumer
  return fn
1159 8572f1fe René Nussbaumer
1160 8572f1fe René Nussbaumer
1161 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1162 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1163 8235fe04 Michael Hanselmann

1164 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1165 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1166 8235fe04 Michael Hanselmann
  @param node: Node object
1167 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1168 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1169 8235fe04 Michael Hanselmann

1170 8235fe04 Michael Hanselmann
  """
1171 e2d188cc Iustin Pop
  return ng.name
1172 8235fe04 Michael Hanselmann
1173 8235fe04 Michael Hanselmann
1174 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1175 52b5d286 René Nussbaumer
  """Returns the node powered state
1176 52b5d286 René Nussbaumer

1177 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1178 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1179 52b5d286 René Nussbaumer
  @param node: Node object
1180 52b5d286 René Nussbaumer

1181 52b5d286 René Nussbaumer
  """
1182 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1183 e2d188cc Iustin Pop
    return node.powered
1184 52b5d286 René Nussbaumer
1185 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1186 52b5d286 René Nussbaumer
1187 52b5d286 René Nussbaumer
1188 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1189 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1190 8572f1fe René Nussbaumer

1191 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1192 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1193 8572f1fe René Nussbaumer
  @param node: Node object
1194 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1195 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1196 8572f1fe René Nussbaumer

1197 8572f1fe René Nussbaumer
  """
1198 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1199 8572f1fe René Nussbaumer
1200 8572f1fe René Nussbaumer
1201 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1202 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1203 8235fe04 Michael Hanselmann

1204 8235fe04 Michael Hanselmann
  @param field: Live field name
1205 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1206 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1207 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1208 a6070ef7 Michael Hanselmann
  @param node: Node object
1209 8235fe04 Michael Hanselmann

1210 8235fe04 Michael Hanselmann
  """
1211 a6070ef7 Michael Hanselmann
  if node.offline:
1212 e2d188cc Iustin Pop
    return _FS_OFFLINE
1213 a6070ef7 Michael Hanselmann
1214 effab4ca Iustin Pop
  if not node.vm_capable:
1215 effab4ca Iustin Pop
    return _FS_UNAVAIL
1216 effab4ca Iustin Pop
1217 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1218 e2d188cc Iustin Pop
    return _FS_NODATA
1219 8235fe04 Michael Hanselmann
1220 8235fe04 Michael Hanselmann
  try:
1221 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1222 8235fe04 Michael Hanselmann
  except KeyError:
1223 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1224 8235fe04 Michael Hanselmann
1225 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1226 e2d188cc Iustin Pop
    return value
1227 8235fe04 Michael Hanselmann
1228 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1229 8235fe04 Michael Hanselmann
1230 8235fe04 Michael Hanselmann
  # Try to convert into number
1231 8235fe04 Michael Hanselmann
  try:
1232 e2d188cc Iustin Pop
    return int(value)
1233 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1234 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1235 8235fe04 Michael Hanselmann
                      value, field)
1236 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1237 8235fe04 Michael Hanselmann
1238 8235fe04 Michael Hanselmann
1239 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1240 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1241 54ac87c0 Michael Hanselmann

1242 54ac87c0 Michael Hanselmann
  """
1243 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1244 54ac87c0 Michael Hanselmann
1245 54ac87c0 Michael Hanselmann
  if hv_state is None:
1246 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1247 54ac87c0 Michael Hanselmann
1248 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1249 54ac87c0 Michael Hanselmann
1250 54ac87c0 Michael Hanselmann
1251 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1252 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1253 54ac87c0 Michael Hanselmann

1254 54ac87c0 Michael Hanselmann
  """
1255 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1256 54ac87c0 Michael Hanselmann
1257 54ac87c0 Michael Hanselmann
  if disk_state is None:
1258 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1259 54ac87c0 Michael Hanselmann
1260 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1261 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1262 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1263 54ac87c0 Michael Hanselmann
1264 54ac87c0 Michael Hanselmann
1265 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1266 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1267 8235fe04 Michael Hanselmann

1268 8235fe04 Michael Hanselmann
  """
1269 8235fe04 Michael Hanselmann
  fields = [
1270 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1271 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1272 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1273 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1274 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1275 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1276 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1277 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, lambda ctx, node: node.name == ctx.master_name),
1278 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1279 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1280 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1281 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1282 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1283 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1284 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1285 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1286 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1287 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1288 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1289 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1290 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1291 54ac87c0 Michael Hanselmann
    (_MakeField("hv_state", "HypervisorState", QFT_OTHER, "Hypervisor state"),
1292 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeHvState),
1293 54ac87c0 Michael Hanselmann
    (_MakeField("disk_state", "DiskState", QFT_OTHER, "Disk state"),
1294 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeDiskState),
1295 8235fe04 Michael Hanselmann
    ]
1296 8235fe04 Michael Hanselmann
1297 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(False))
1298 8930b0f0 Iustin Pop
1299 79b2ca83 Michael Hanselmann
  # Node role
1300 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1301 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1302 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1303 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1304 a9310b2f Iustin Pop
              " \"%s\" for regular, \"%s\" for drained, \"%s\" for offline" %
1305 79b2ca83 Michael Hanselmann
              role_values)
1306 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1307 79b2ca83 Michael Hanselmann
                 lambda ctx, node: _GetNodeRole(node, ctx.master_name)))
1308 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1309 79b2ca83 Michael Hanselmann
1310 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1311 e2d188cc Iustin Pop
    return lambda ctx, node: len(getter(ctx)[node.name])
1312 8235fe04 Michael Hanselmann
1313 8235fe04 Michael Hanselmann
  def _GetList(getter):
1314 e2d188cc Iustin Pop
    return lambda ctx, node: list(getter(ctx)[node.name])
1315 8235fe04 Michael Hanselmann
1316 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1317 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1318 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1319 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1320 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1321 8235fe04 Michael Hanselmann
    fields.extend([
1322 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1323 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1324 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1325 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1326 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1327 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1328 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1329 8235fe04 Michael Hanselmann
      ])
1330 8235fe04 Michael Hanselmann
1331 8235fe04 Michael Hanselmann
  # Add simple fields
1332 111bf531 Michael Hanselmann
  fields.extend([
1333 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1334 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()
1335 111bf531 Michael Hanselmann
    ])
1336 8235fe04 Michael Hanselmann
1337 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1338 8235fe04 Michael Hanselmann
  fields.extend([
1339 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1340 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1341 79b2ca83 Michael Hanselmann
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()
1342 8235fe04 Michael Hanselmann
    ])
1343 8235fe04 Michael Hanselmann
1344 145bea54 Michael Hanselmann
  # Add timestamps
1345 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1346 145bea54 Michael Hanselmann
1347 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1348 8235fe04 Michael Hanselmann
1349 8235fe04 Michael Hanselmann
1350 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1351 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1352 1c8addc6 Michael Hanselmann

1353 1c8addc6 Michael Hanselmann
  """
1354 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1355 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1356 1c8addc6 Michael Hanselmann
    """Initializes this class.
1357 1c8addc6 Michael Hanselmann

1358 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1359 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1360 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1361 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1362 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1363 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1364 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1365 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1366 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1367 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1368 e431074f René Nussbaumer
    @type wrongnode_inst: set
1369 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1370 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1371 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1372 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1373 fab9573b Michael Hanselmann
    @param nodes: Node objects
1374 1c8addc6 Michael Hanselmann

1375 1c8addc6 Michael Hanselmann
    """
1376 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1377 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1378 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1379 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1380 1c8addc6 Michael Hanselmann
1381 1c8addc6 Michael Hanselmann
    self.instances = instances
1382 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1383 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1384 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1385 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1386 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1387 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1388 5d28cb6f Michael Hanselmann
    self.console = console
1389 fab9573b Michael Hanselmann
    self.nodes = nodes
1390 fab9573b Michael Hanselmann
    self.groups = groups
1391 1c8addc6 Michael Hanselmann
1392 1c8addc6 Michael Hanselmann
    # Used for individual rows
1393 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1394 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1395 7c670076 Michael Hanselmann
    self.inst_osparams = None
1396 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1397 1c8addc6 Michael Hanselmann
1398 1c8addc6 Michael Hanselmann
  def __iter__(self):
1399 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1400 1c8addc6 Michael Hanselmann

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

1404 1c8addc6 Michael Hanselmann
    """
1405 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1406 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1407 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1408 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1409 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1410 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1411 1c8addc6 Michael Hanselmann
1412 1c8addc6 Michael Hanselmann
      yield inst
1413 1c8addc6 Michael Hanselmann
1414 1c8addc6 Michael Hanselmann
1415 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1416 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1417 1c8addc6 Michael Hanselmann

1418 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1419 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1420 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1421 1c8addc6 Michael Hanselmann

1422 1c8addc6 Michael Hanselmann
  """
1423 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1424 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1425 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1426 e2d188cc Iustin Pop
    return _FS_NODATA
1427 1c8addc6 Michael Hanselmann
  else:
1428 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1429 1c8addc6 Michael Hanselmann
1430 1c8addc6 Michael Hanselmann
1431 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1432 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1433 1c8addc6 Michael Hanselmann

1434 1c8addc6 Michael Hanselmann
  @type name: string
1435 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1436 1c8addc6 Michael Hanselmann

1437 1c8addc6 Michael Hanselmann
  """
1438 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1439 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1440 1c8addc6 Michael Hanselmann

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

1445 1c8addc6 Michael Hanselmann
    """
1446 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1447 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1448 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1449 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1450 e2d188cc Iustin Pop
      return _FS_NODATA
1451 1c8addc6 Michael Hanselmann
1452 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1453 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1454 1c8addc6 Michael Hanselmann
      if name in data:
1455 e2d188cc Iustin Pop
        return data[name]
1456 1c8addc6 Michael Hanselmann
1457 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1458 1c8addc6 Michael Hanselmann
1459 1c8addc6 Michael Hanselmann
  return fn
1460 1c8addc6 Michael Hanselmann
1461 1c8addc6 Michael Hanselmann
1462 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1463 1c8addc6 Michael Hanselmann
  """Get instance status.
1464 1c8addc6 Michael Hanselmann

1465 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1466 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1467 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1468 1c8addc6 Michael Hanselmann

1469 1c8addc6 Michael Hanselmann
  """
1470 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1471 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1472 1c8addc6 Michael Hanselmann
1473 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1474 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1475 1c8addc6 Michael Hanselmann
1476 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1477 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1478 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1479 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1480 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1481 1c8addc6 Michael Hanselmann
    else:
1482 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1483 1c8addc6 Michael Hanselmann
1484 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1485 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1486 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1487 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1488 1c8addc6 Michael Hanselmann
1489 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1490 1c8addc6 Michael Hanselmann
1491 1c8addc6 Michael Hanselmann
1492 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1493 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1494 1c8addc6 Michael Hanselmann

1495 1c8addc6 Michael Hanselmann
  @type index: int
1496 1c8addc6 Michael Hanselmann
  @param index: Disk index
1497 1c8addc6 Michael Hanselmann

1498 1c8addc6 Michael Hanselmann
  """
1499 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1500 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1501 1c8addc6 Michael Hanselmann

1502 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1503 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1504 1c8addc6 Michael Hanselmann

1505 1c8addc6 Michael Hanselmann
    """
1506 1c8addc6 Michael Hanselmann
    try:
1507 e2d188cc Iustin Pop
      return inst.disks[index].size
1508 1c8addc6 Michael Hanselmann
    except IndexError:
1509 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1510 1c8addc6 Michael Hanselmann
1511 1c8addc6 Michael Hanselmann
  return fn
1512 1c8addc6 Michael Hanselmann
1513 1c8addc6 Michael Hanselmann
1514 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1515 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1516 1c8addc6 Michael Hanselmann

1517 1c8addc6 Michael Hanselmann
  @type index: int
1518 1c8addc6 Michael Hanselmann
  @param index: NIC index
1519 1c8addc6 Michael Hanselmann
  @type cb: callable
1520 1c8addc6 Michael Hanselmann
  @param cb: Callback
1521 1c8addc6 Michael Hanselmann

1522 1c8addc6 Michael Hanselmann
  """
1523 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1524 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1525 1c8addc6 Michael Hanselmann

1526 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1527 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1528 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1529 1c8addc6 Michael Hanselmann

1530 1c8addc6 Michael Hanselmann
    """
1531 1c8addc6 Michael Hanselmann
    try:
1532 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1533 1c8addc6 Michael Hanselmann
    except IndexError:
1534 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1535 1c8addc6 Michael Hanselmann
1536 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1537 1c8addc6 Michael Hanselmann
1538 1c8addc6 Michael Hanselmann
  return fn
1539 1c8addc6 Michael Hanselmann
1540 1c8addc6 Michael Hanselmann
1541 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1542 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1543 1c8addc6 Michael Hanselmann

1544 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1545 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1546 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1547 1c8addc6 Michael Hanselmann

1548 1c8addc6 Michael Hanselmann
  """
1549 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1550 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1551 1c8addc6 Michael Hanselmann
  else:
1552 e2d188cc Iustin Pop
    return nic.ip
1553 1c8addc6 Michael Hanselmann
1554 1c8addc6 Michael Hanselmann
1555 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1556 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1557 1c8addc6 Michael Hanselmann

1558 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1559 1c8addc6 Michael Hanselmann
  @type index: int
1560 1c8addc6 Michael Hanselmann
  @param index: NIC index
1561 1c8addc6 Michael Hanselmann

1562 1c8addc6 Michael Hanselmann
  """
1563 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1564 1c8addc6 Michael Hanselmann
1565 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1566 1c8addc6 Michael Hanselmann
1567 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1568 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1569 1c8addc6 Michael Hanselmann
  else:
1570 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1571 1c8addc6 Michael Hanselmann
1572 1c8addc6 Michael Hanselmann
1573 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1574 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1575 1c8addc6 Michael Hanselmann

1576 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1577 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1578 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1579 1c8addc6 Michael Hanselmann

1580 1c8addc6 Michael Hanselmann
  """
1581 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1582 1c8addc6 Michael Hanselmann
1583 1c8addc6 Michael Hanselmann
  result = []
1584 1c8addc6 Michael Hanselmann
1585 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1586 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1587 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1588 1c8addc6 Michael Hanselmann
    else:
1589 1c8addc6 Michael Hanselmann
      result.append(None)
1590 1c8addc6 Michael Hanselmann
1591 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1592 1c8addc6 Michael Hanselmann
1593 e2d188cc Iustin Pop
  return result
1594 1c8addc6 Michael Hanselmann
1595 1c8addc6 Michael Hanselmann
1596 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1597 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1598 1c8addc6 Michael Hanselmann

1599 1c8addc6 Michael Hanselmann
  @type name: string
1600 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1601 1c8addc6 Michael Hanselmann

1602 1c8addc6 Michael Hanselmann
  """
1603 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1604 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1605 1c8addc6 Michael Hanselmann

1606 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1607 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1608 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1609 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1610 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1611 1c8addc6 Michael Hanselmann

1612 1c8addc6 Michael Hanselmann
    """
1613 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1614 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1615 1c8addc6 Michael Hanselmann
1616 1c8addc6 Michael Hanselmann
  return fn
1617 1c8addc6 Michael Hanselmann
1618 1c8addc6 Michael Hanselmann
1619 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1620 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1621 1c8addc6 Michael Hanselmann

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

1625 1c8addc6 Michael Hanselmann
  """
1626 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1627 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1628 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1629 1c8addc6 Michael Hanselmann
1630 1c8addc6 Michael Hanselmann
  fields = [
1631 1c8addc6 Michael Hanselmann
    # All NICs
1632 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1633 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1634 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1635 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1636 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1637 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1638 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1639 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1640 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1641 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1642 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1643 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1644 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1645 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1646 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1647 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1648 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1649 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1650 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1651 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1652 1c8addc6 Michael Hanselmann
    ]
1653 1c8addc6 Michael Hanselmann
1654 1c8addc6 Michael Hanselmann
  # NICs by number
1655 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1656 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1657 1c8addc6 Michael Hanselmann
    fields.extend([
1658 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1659 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1660 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1661 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1662 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1663 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1664 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1665 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1666 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1667 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1668 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1669 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1670 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1671 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1672 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1673 1c8addc6 Michael Hanselmann
      ])
1674 1c8addc6 Michael Hanselmann
1675 4cc4d1fa Michael Hanselmann
  aliases = [
1676 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1677 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1678 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1679 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1680 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1681 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1682 4cc4d1fa Michael Hanselmann
    ]
1683 4cc4d1fa Michael Hanselmann
1684 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1685 1c8addc6 Michael Hanselmann
1686 1c8addc6 Michael Hanselmann
1687 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1688 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1689 1c8addc6 Michael Hanselmann

1690 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1691 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1692 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1693 1c8addc6 Michael Hanselmann

1694 1c8addc6 Michael Hanselmann
  """
1695 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1696 1c8addc6 Michael Hanselmann
1697 1c8addc6 Michael Hanselmann
  if usage is None:
1698 1c8addc6 Michael Hanselmann
    usage = 0
1699 1c8addc6 Michael Hanselmann
1700 e2d188cc Iustin Pop
  return usage
1701 1c8addc6 Michael Hanselmann
1702 1c8addc6 Michael Hanselmann
1703 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1704 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1705 5d28cb6f Michael Hanselmann

1706 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1707 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1708 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1709 5d28cb6f Michael Hanselmann

1710 5d28cb6f Michael Hanselmann
  """
1711 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1712 5d28cb6f Michael Hanselmann
1713 5d28cb6f Michael Hanselmann
  if consinfo is None:
1714 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1715 5d28cb6f Michael Hanselmann
1716 5d28cb6f Michael Hanselmann
  return consinfo
1717 5d28cb6f Michael Hanselmann
1718 5d28cb6f Michael Hanselmann
1719 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1720 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1721 1c8addc6 Michael Hanselmann

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

1724 1c8addc6 Michael Hanselmann
  """
1725 1c8addc6 Michael Hanselmann
  fields = [
1726 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1727 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1728 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1729 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1730 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1731 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1732 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1733 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1734 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1735 1c8addc6 Michael Hanselmann
    ]
1736 1c8addc6 Michael Hanselmann
1737 1c8addc6 Michael Hanselmann
  # Disks by number
1738 1c8addc6 Michael Hanselmann
  fields.extend([
1739 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1740 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1741 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1742 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1743 1c8addc6 Michael Hanselmann
    ])
1744 1c8addc6 Michael Hanselmann
1745 1c8addc6 Michael Hanselmann
  return fields
1746 1c8addc6 Michael Hanselmann
1747 1c8addc6 Michael Hanselmann
1748 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1749 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1750 1c8addc6 Michael Hanselmann

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

1753 1c8addc6 Michael Hanselmann
  """
1754 1c8addc6 Michael Hanselmann
  fields = [
1755 1c8addc6 Michael Hanselmann
    # Filled parameters
1756 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1757 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1758 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1759 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1760 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1761 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1762 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1763 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1764 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1765 1c8addc6 Michael Hanselmann
1766 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1767 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1768 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1769 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1770 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1771 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1772 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1773 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1774 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1775 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1776 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1777 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1778 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1779 1c8addc6 Michael Hanselmann
    ]
1780 1c8addc6 Michael Hanselmann
1781 1c8addc6 Michael Hanselmann
  # HV params
1782 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1783 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1784 1c8addc6 Michael Hanselmann
1785 1c8addc6 Michael Hanselmann
  fields.extend([
1786 a6c7e2a2 Iustin Pop
    (_MakeField("hv/%s" % name,
1787 a6c7e2a2 Iustin Pop
                constants.HVS_PARAMETER_TITLES.get(name, "hv/%s" % name),
1788 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1789 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1790 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1791 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1792 1c8addc6 Michael Hanselmann
    ])
1793 1c8addc6 Michael Hanselmann
1794 1c8addc6 Michael Hanselmann
  # BE params
1795 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1796 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1797 1c8addc6 Michael Hanselmann
1798 1c8addc6 Michael Hanselmann
  fields.extend([
1799 a6c7e2a2 Iustin Pop
    (_MakeField("be/%s" % name,
1800 a6c7e2a2 Iustin Pop
                constants.BES_PARAMETER_TITLES.get(name, "be/%s" % name),
1801 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1802 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1803 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1804 1c8addc6 Michael Hanselmann
    ])
1805 1c8addc6 Michael Hanselmann
1806 1c8addc6 Michael Hanselmann
  return fields
1807 1c8addc6 Michael Hanselmann
1808 1c8addc6 Michael Hanselmann
1809 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1810 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1811 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1812 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1813 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1814 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1815 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1816 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1817 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1818 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1819 1c8addc6 Michael Hanselmann
  }
1820 1c8addc6 Michael Hanselmann
1821 1c8addc6 Michael Hanselmann
1822 fab9573b Michael Hanselmann
def _GetInstNodeGroup(ctx, default, node_name):
1823 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
1824 fab9573b Michael Hanselmann

1825 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1826 fab9573b Michael Hanselmann
  @param default: Default value
1827 fab9573b Michael Hanselmann
  @type node_name: string
1828 fab9573b Michael Hanselmann
  @param node_name: Node name
1829 fab9573b Michael Hanselmann

1830 fab9573b Michael Hanselmann
  """
1831 fab9573b Michael Hanselmann
  try:
1832 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1833 fab9573b Michael Hanselmann
  except KeyError:
1834 fab9573b Michael Hanselmann
    return default
1835 fab9573b Michael Hanselmann
  else:
1836 fab9573b Michael Hanselmann
    return node.group
1837 fab9573b Michael Hanselmann
1838 fab9573b Michael Hanselmann
1839 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1840 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1841 fab9573b Michael Hanselmann

1842 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1843 fab9573b Michael Hanselmann
  @param default: Default value
1844 fab9573b Michael Hanselmann
  @type node_name: string
1845 fab9573b Michael Hanselmann
  @param node_name: Node name
1846 fab9573b Michael Hanselmann

1847 fab9573b Michael Hanselmann
  """
1848 fab9573b Michael Hanselmann
  try:
1849 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1850 fab9573b Michael Hanselmann
  except KeyError:
1851 fab9573b Michael Hanselmann
    return default
1852 fab9573b Michael Hanselmann
1853 fab9573b Michael Hanselmann
  try:
1854 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1855 fab9573b Michael Hanselmann
  except KeyError:
1856 fab9573b Michael Hanselmann
    return default
1857 fab9573b Michael Hanselmann
1858 fab9573b Michael Hanselmann
  return group.name
1859 fab9573b Michael Hanselmann
1860 fab9573b Michael Hanselmann
1861 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1862 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1863 1c8addc6 Michael Hanselmann

1864 1c8addc6 Michael Hanselmann
  """
1865 1c8addc6 Michael Hanselmann
  fields = [
1866 111bf531 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", QFT_TEXT, "Primary node"),
1867 111bf531 Michael Hanselmann
     IQ_CONFIG, QFF_HOSTNAME, _GetItemAttr("primary_node")),
1868 fab9573b Michael Hanselmann
    (_MakeField("pnode.group", "PrimaryNodeGroup", QFT_TEXT,
1869 fab9573b Michael Hanselmann
                "Primary node's group"),
1870 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1871 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroupName(ctx, _FS_UNAVAIL,
1872 fab9573b Michael Hanselmann
                                             inst.primary_node)),
1873 fab9573b Michael Hanselmann
    (_MakeField("pnode.group.uuid", "PrimaryNodeGroupUUID", QFT_TEXT,
1874 fab9573b Michael Hanselmann
                "Primary node's group UUID"),
1875 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1876 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroup(ctx, _FS_UNAVAIL, inst.primary_node)),
1877 111bf531 Michael Hanselmann
    # TODO: Allow filtering by secondary node as hostname
1878 79b2ca83 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER,
1879 79b2ca83 Michael Hanselmann
                "Secondary nodes; usually this will just be one node"),
1880 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: list(inst.secondary_nodes)),
1881 fab9573b Michael Hanselmann
    (_MakeField("snodes.group", "SecondaryNodesGroups", QFT_OTHER,
1882 fab9573b Michael Hanselmann
                "Node groups of secondary nodes"),
1883 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1884 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroupName, ctx, None),
1885 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1886 fab9573b Michael Hanselmann
    (_MakeField("snodes.group.uuid", "SecondaryNodesGroupsUUID", QFT_OTHER,
1887 fab9573b Michael Hanselmann
                "Node group UUIDs of secondary nodes"),
1888 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1889 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroup, ctx, None),
1890 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1891 2e04d454 Agata Murawska
    (_MakeField("admin_state", "InstanceState", QFT_TEXT,
1892 2e04d454 Agata Murawska
                "Desired state of instance"),
1893 9ca8a7c5 Agata Murawska
     IQ_CONFIG, 0, _GetItemAttr("admin_state")),
1894 754cc530 Agata Murawska
    (_MakeField("admin_up", "Autostart", QFT_BOOL,
1895 754cc530 Agata Murawska
                "Desired state of instance"),
1896 754cc530 Agata Murawska
     IQ_CONFIG, 0, lambda ctx, inst: inst.admin_state == constants.ADMINST_UP),
1897 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
1898 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
1899 79b2ca83 Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER,
1900 111bf531 Michael Hanselmann
                "Instance console information"), IQ_CONSOLE, 0,
1901 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
1902 1c8addc6 Michael Hanselmann
    ]
1903 1c8addc6 Michael Hanselmann
1904 1c8addc6 Michael Hanselmann
  # Add simple fields
1905 111bf531 Michael Hanselmann
  fields.extend([
1906 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
1907 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()
1908 111bf531 Michael Hanselmann
    ])
1909 1c8addc6 Michael Hanselmann
1910 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1911 1c8addc6 Michael Hanselmann
  fields.extend([
1912 79b2ca83 Michael Hanselmann
    (_MakeField("oper_state", "Running", QFT_BOOL, "Actual state of instance"),
1913 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstOperState),
1914 79b2ca83 Michael Hanselmann
    (_MakeField("oper_ram", "Memory", QFT_UNIT,
1915 79b2ca83 Michael Hanselmann
                "Actual memory usage as seen by hypervisor"),
1916 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("memory")),
1917 79b2ca83 Michael Hanselmann
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER,
1918 79b2ca83 Michael Hanselmann
                "Actual number of VCPUs as seen by hypervisor"),
1919 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("vcpus")),
1920 1c8addc6 Michael Hanselmann
    ])
1921 1c8addc6 Michael Hanselmann
1922 79b2ca83 Michael Hanselmann
  # Status field
1923 79b2ca83 Michael Hanselmann
  status_values = (constants.INSTST_RUNNING, constants.INSTST_ADMINDOWN,
1924 79b2ca83 Michael Hanselmann
                   constants.INSTST_WRONGNODE, constants.INSTST_ERRORUP,
1925 79b2ca83 Michael Hanselmann
                   constants.INSTST_ERRORDOWN, constants.INSTST_NODEDOWN,
1926 2e04d454 Agata Murawska
                   constants.INSTST_NODEOFFLINE, constants.INSTST_ADMINOFFLINE)
1927 79b2ca83 Michael Hanselmann
  status_doc = ("Instance status; \"%s\" if instance is set to be running"
1928 79b2ca83 Michael Hanselmann
                " and actually is, \"%s\" if instance is stopped and"
1929 79b2ca83 Michael Hanselmann
                " is not running, \"%s\" if instance running, but not on its"
1930 79b2ca83 Michael Hanselmann
                " designated primary node, \"%s\" if instance should be"
1931 79b2ca83 Michael Hanselmann
                " stopped, but is actually running, \"%s\" if instance should"
1932 79b2ca83 Michael Hanselmann
                " run, but doesn't, \"%s\" if instance's primary node is down,"
1933 2e04d454 Agata Murawska
                " \"%s\" if instance's primary node is marked offline,"
1934 2e04d454 Agata Murawska
                " \"%s\" if instance is offline and does not use dynamic"
1935 2e04d454 Agata Murawska
                " resources" % status_values)
1936 79b2ca83 Michael Hanselmann
  fields.append((_MakeField("status", "Status", QFT_TEXT, status_doc),
1937 111bf531 Michael Hanselmann
                 IQ_LIVE, 0, _GetInstStatus))
1938 79b2ca83 Michael Hanselmann
  assert set(status_values) == constants.INSTST_ALL, \
1939 79b2ca83 Michael Hanselmann
         "Status documentation mismatch"
1940 79b2ca83 Michael Hanselmann
1941 4cc4d1fa Michael Hanselmann
  (network_fields, network_aliases) = _GetInstanceNetworkFields()
1942 4cc4d1fa Michael Hanselmann
1943 4cc4d1fa Michael Hanselmann
  fields.extend(network_fields)
1944 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1945 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1946 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1947 1c8addc6 Michael Hanselmann
1948 e7e8037b Iustin Pop
  aliases = [
1949 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
1950 31d1791a Guido Trotter
    ("be/memory", "be/maxmem"),
1951 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
1952 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
1953 4cc4d1fa Michael Hanselmann
    ] + network_aliases
1954 e7e8037b Iustin Pop
1955 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
1956 1c8addc6 Michael Hanselmann
1957 1c8addc6 Michael Hanselmann
1958 24d16f76 Michael Hanselmann
class LockQueryData:
1959 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1960 24d16f76 Michael Hanselmann

1961 24d16f76 Michael Hanselmann
  """
1962 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1963 24d16f76 Michael Hanselmann
    """Initializes this class.
1964 24d16f76 Michael Hanselmann

1965 24d16f76 Michael Hanselmann
    """
1966 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1967 24d16f76 Michael Hanselmann
1968 24d16f76 Michael Hanselmann
  def __iter__(self):
1969 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1970 24d16f76 Michael Hanselmann

1971 24d16f76 Michael Hanselmann
    """
1972 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1973 24d16f76 Michael Hanselmann
1974 24d16f76 Michael Hanselmann
1975 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1976 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1977 24d16f76 Michael Hanselmann

1978 24d16f76 Michael Hanselmann
  """
1979 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1980 24d16f76 Michael Hanselmann
1981 24d16f76 Michael Hanselmann
  if owners:
1982 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1983 24d16f76 Michael Hanselmann
1984 e2d188cc Iustin Pop
  return owners
1985 24d16f76 Michael Hanselmann
1986 24d16f76 Michael Hanselmann
1987 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1988 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1989 24d16f76 Michael Hanselmann

1990 24d16f76 Michael Hanselmann
  """
1991 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1992 24d16f76 Michael Hanselmann
1993 24d16f76 Michael Hanselmann
  if pending:
1994 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1995 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1996 24d16f76 Michael Hanselmann
1997 e2d188cc Iustin Pop
  return pending
1998 24d16f76 Michael Hanselmann
1999 24d16f76 Michael Hanselmann
2000 24d16f76 Michael Hanselmann
def _BuildLockFields():
2001 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
2002 24d16f76 Michael Hanselmann

2003 24d16f76 Michael Hanselmann
  """
2004 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
2005 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
2006 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
2007 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
2008 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
2009 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
2010 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
2011 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
2012 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
2013 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
2014 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
2015 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
2016 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
2017 d63bd540 Iustin Pop
    ], [])
2018 24d16f76 Michael Hanselmann
2019 24d16f76 Michael Hanselmann
2020 8e21cfc0 Adeodato Simo
class GroupQueryData:
2021 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
2022 8e21cfc0 Adeodato Simo

2023 8e21cfc0 Adeodato Simo
  """
2024 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2025 2c758845 René Nussbaumer
               want_diskparams):
2026 8e21cfc0 Adeodato Simo
    """Initializes this class.
2027 8e21cfc0 Adeodato Simo

2028 edd49f9b Agata Murawska
    @param cluster: Cluster object
2029 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2030 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2031 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2032 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2033 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2034 2c758845 René Nussbaumer
    @type want_diskparams: bool
2035 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2036 8e21cfc0 Adeodato Simo

2037 8e21cfc0 Adeodato Simo
    """
2038 8e21cfc0 Adeodato Simo
    self.groups = groups
2039 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2040 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2041 edd49f9b Agata Murawska
    self.cluster = cluster
2042 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2043 edd49f9b Agata Murawska
2044 edd49f9b Agata Murawska
    # Used for individual rows
2045 edd49f9b Agata Murawska
    self.group_ipolicy = None
2046 8930b0f0 Iustin Pop
    self.ndparams = None
2047 2c758845 René Nussbaumer
    self.group_dp = None
2048 8e21cfc0 Adeodato Simo
2049 8e21cfc0 Adeodato Simo
  def __iter__(self):
2050 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2051 8e21cfc0 Adeodato Simo

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

2055 8e21cfc0 Adeodato Simo
    """
2056 edd49f9b Agata Murawska
    for group in self.groups:
2057 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2058 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2059 2c758845 René Nussbaumer
      if self.want_diskparams:
2060 2c758845 René Nussbaumer
        self.group_dp = self.cluster.SimpleFillDP(group.diskparams)
2061 2c758845 René Nussbaumer
      else:
2062 2c758845 René Nussbaumer
        self.group_dp = None
2063 edd49f9b Agata Murawska
      yield group
2064 8e21cfc0 Adeodato Simo
2065 8e21cfc0 Adeodato Simo
2066 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2067 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2068 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2069 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2070 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2071 8e21cfc0 Adeodato Simo
  }
2072 8e21cfc0 Adeodato Simo
2073 8e21cfc0 Adeodato Simo
2074 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2075 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2076 8e21cfc0 Adeodato Simo

2077 8e21cfc0 Adeodato Simo
  """
2078 8e21cfc0 Adeodato Simo
  # Add simple fields
2079 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
2080 111bf531 Michael Hanselmann
             _GetItemAttr(name))
2081 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
2082 8e21cfc0 Adeodato Simo
2083 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
2084 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
2085 8e21cfc0 Adeodato Simo
2086 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
2087 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
2088 8e21cfc0 Adeodato Simo
2089 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
2090 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
2091 8e21cfc0 Adeodato Simo
2092 8e21cfc0 Adeodato Simo
  # Add fields for nodes
2093 8e21cfc0 Adeodato Simo
  fields.extend([
2094 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
2095 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
2096 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
2097 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
2098 8e21cfc0 Adeodato Simo
    ])
2099 8e21cfc0 Adeodato Simo
2100 8e21cfc0 Adeodato Simo
  # Add fields for instances
2101 8e21cfc0 Adeodato Simo
  fields.extend([
2102 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
2103 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
2104 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
2105 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
2106 79b2ca83 Michael Hanselmann
                "List of primary instances"),
2107 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
2108 8e21cfc0 Adeodato Simo
    ])
2109 8e21cfc0 Adeodato Simo
2110 1ffd2673 Michael Hanselmann
  # Other fields
2111 1ffd2673 Michael Hanselmann
  fields.extend([
2112 1ffd2673 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
2113 1ffd2673 Michael Hanselmann
     lambda ctx, group: list(group.GetTags())),
2114 edd49f9b Agata Murawska
    (_MakeField("ipolicy", "InstancePolicy", QFT_OTHER,
2115 edd49f9b Agata Murawska
                "Instance policy limitations (merged)"),
2116 edd49f9b Agata Murawska
     GQ_CONFIG, 0, lambda ctx, _: ctx.group_ipolicy),
2117 edd49f9b Agata Murawska
    (_MakeField("custom_ipolicy", "CustomInstancePolicy", QFT_OTHER,
2118 edd49f9b Agata Murawska
                "Custom instance policy limitations"),
2119 edd49f9b Agata Murawska
     GQ_CONFIG, 0, _GetItemAttr("ipolicy")),
2120 8930b0f0 Iustin Pop
    (_MakeField("custom_ndparams", "CustomNDParams", QFT_OTHER,
2121 8930b0f0 Iustin Pop
                "Custom node parameters"),
2122 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, _GetItemAttr("ndparams")),
2123 8930b0f0 Iustin Pop
    (_MakeField("ndparams", "NDParams", QFT_OTHER,
2124 8930b0f0 Iustin Pop
                "Node parameters"),
2125 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, lambda ctx, _: ctx.ndparams),
2126 2c758845 René Nussbaumer
    (_MakeField("diskparams", "DiskParameters", QFT_OTHER,
2127 2c758845 René Nussbaumer
                "Disk parameters (merged)"),
2128 2c758845 René Nussbaumer
     GQ_DISKPARAMS, 0, lambda ctx, _: ctx.group_dp),
2129 2c758845 René Nussbaumer
    (_MakeField("custom_diskparams", "CustomDiskParameters", QFT_OTHER,
2130 2c758845 René Nussbaumer
                "Custom disk parameters"),
2131 2c758845 René Nussbaumer
     GQ_CONFIG, 0, _GetItemAttr("diskparams")),
2132 1ffd2673 Michael Hanselmann
    ])
2133 1ffd2673 Michael Hanselmann
2134 8930b0f0 Iustin Pop
  # ND parameters
2135 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(True))
2136 8930b0f0 Iustin Pop
2137 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
2138 8e21cfc0 Adeodato Simo
2139 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
2140 8e21cfc0 Adeodato Simo
2141 8e21cfc0 Adeodato Simo
2142 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
2143 be3a4b14 Michael Hanselmann
  __slots__ = [
2144 be3a4b14 Michael Hanselmann
    "name",
2145 be3a4b14 Michael Hanselmann
    "valid",
2146 be3a4b14 Michael Hanselmann
    "hidden",
2147 be3a4b14 Michael Hanselmann
    "blacklisted",
2148 be3a4b14 Michael Hanselmann
    "variants",
2149 be3a4b14 Michael Hanselmann
    "api_versions",
2150 be3a4b14 Michael Hanselmann
    "parameters",
2151 be3a4b14 Michael Hanselmann
    "node_status",
2152 be3a4b14 Michael Hanselmann
    ]
2153 be3a4b14 Michael Hanselmann
2154 be3a4b14 Michael Hanselmann
2155 be3a4b14 Michael Hanselmann
def _BuildOsFields():
2156 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
2157 be3a4b14 Michael Hanselmann

2158 be3a4b14 Michael Hanselmann
  """
2159 be3a4b14 Michael Hanselmann
  fields = [
2160 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2161 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2162 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2163 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2164 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2165 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2166 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2167 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2168 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2169 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2170 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2171 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2172 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2173 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2174 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2175 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2176 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2177 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2178 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2179 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2180 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2181 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2182 be3a4b14 Michael Hanselmann
                "Status from node"),
2183 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2184 be3a4b14 Michael Hanselmann
    ]
2185 be3a4b14 Michael Hanselmann
2186 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2187 be3a4b14 Michael Hanselmann
2188 be3a4b14 Michael Hanselmann
2189 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2190 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2191 9665bb3a Michael Hanselmann

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

2195 9665bb3a Michael Hanselmann
  """
2196 9665bb3a Michael Hanselmann
  if job is None:
2197 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2198 9665bb3a Michael Hanselmann
  else:
2199 9665bb3a Michael Hanselmann
    return fn(job)
2200 9665bb3a Michael Hanselmann
2201 9665bb3a Michael Hanselmann
2202 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2203 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2204 9665bb3a Michael Hanselmann

2205 9665bb3a Michael Hanselmann
  """
2206 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2207 9665bb3a Michael Hanselmann
2208 9665bb3a Michael Hanselmann
2209 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2210 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2211 9665bb3a Michael Hanselmann

2212 9665bb3a Michael Hanselmann
  """
2213 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2214 9665bb3a Michael Hanselmann
2215 9665bb3a Michael Hanselmann
2216 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2217 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2218 9665bb3a Michael Hanselmann

2219 9665bb3a Michael Hanselmann
  """
2220 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2221 9665bb3a Michael Hanselmann
2222 9665bb3a Michael Hanselmann
2223 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2224 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2225 9665bb3a Michael Hanselmann

2226 9665bb3a Michael Hanselmann
  """
2227 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2228 9665bb3a Michael Hanselmann
2229 9665bb3a Michael Hanselmann
  if timestamp is None:
2230 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2231 9665bb3a Michael Hanselmann
  else:
2232 9665bb3a Michael Hanselmann
    return timestamp
2233 9665bb3a Michael Hanselmann
2234 9665bb3a Michael Hanselmann
2235 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2236 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2237 9665bb3a Michael Hanselmann

2238 9665bb3a Michael Hanselmann
  """
2239 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2240 9665bb3a Michael Hanselmann
2241 9665bb3a Michael Hanselmann
2242 9665bb3a Michael Hanselmann
def _BuildJobFields():
2243 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2244 9665bb3a Michael Hanselmann

2245 9665bb3a Michael Hanselmann
  """
2246 9665bb3a Michael Hanselmann
  fields = [
2247 76b62028 Iustin Pop
    (_MakeField("id", "ID", QFT_NUMBER, "Job ID"),
2248 526f866b Michael Hanselmann
     None, QFF_JOB_ID, lambda _, (job_id, job): job_id),
2249 9665bb3a Michael Hanselmann
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2250 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2251 9665bb3a Michael Hanselmann
    (_MakeField("priority", "Priority", QFT_NUMBER,
2252 9665bb3a Michael Hanselmann
                ("Current job priority (%s to %s)" %
2253 9665bb3a Michael Hanselmann
                 (constants.OP_PRIO_LOWEST, constants.OP_PRIO_HIGHEST))),
2254 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcPriority())),
2255 9665bb3a Michael Hanselmann
    (_MakeField("ops", "OpCodes", QFT_OTHER, "List of all opcodes"),
2256 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.__getstate__())),
2257 9665bb3a Michael Hanselmann
    (_MakeField("opresult", "OpCode_result", QFT_OTHER,
2258 9665bb3a Michael Hanselmann
                "List of opcodes results"),
2259 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("result"))),
2260 9665bb3a Michael Hanselmann
    (_MakeField("opstatus", "OpCode_status", QFT_OTHER,
2261 9665bb3a Michael Hanselmann
                "List of opcodes status"),
2262 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("status"))),
2263 9665bb3a Michael Hanselmann
    (_MakeField("oplog", "OpCode_log", QFT_OTHER,
2264 9665bb3a Michael Hanselmann
                "List of opcode output logs"),
2265 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("log"))),
2266 9665bb3a Michael Hanselmann
    (_MakeField("opstart", "OpCode_start", QFT_OTHER,
2267 9665bb3a Michael Hanselmann
                "List of opcode start timestamps (before acquiring locks)"),
2268 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("start_timestamp"))),
2269 9665bb3a Michael Hanselmann
    (_MakeField("opexec", "OpCode_exec", QFT_OTHER,
2270 9665bb3a Michael Hanselmann
                "List of opcode execution start timestamps (after acquiring"
2271 9665bb3a Michael Hanselmann
                " locks)"),
2272 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("exec_timestamp"))),
2273 9665bb3a Michael Hanselmann
    (_MakeField("opend", "OpCode_end", QFT_OTHER,
2274 9665bb3a Michael Hanselmann
                "List of opcode execution end timestamps"),
2275 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("end_timestamp"))),
2276 9665bb3a Michael Hanselmann
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2277 9665bb3a Michael Hanselmann
                "List of opcode priorities"),
2278 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2279 9665bb3a Michael Hanselmann
    (_MakeField("summary", "Summary", QFT_OTHER,
2280 9665bb3a Michael Hanselmann
                "List of per-opcode summaries"),
2281 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2282 9665bb3a Michael Hanselmann
    ]
2283 9665bb3a Michael Hanselmann
2284 526f866b Michael Hanselmann
  # Timestamp fields
2285 526f866b Michael Hanselmann
  for (name, attr, title, desc) in [
2286 526f866b Michael Hanselmann
    ("received_ts", "received_timestamp", "Received",
2287 526f866b Michael Hanselmann
     "Timestamp of when job was received"),
2288 526f866b Michael Hanselmann
    ("start_ts", "start_timestamp", "Start", "Timestamp of job start"),
2289 526f866b Michael Hanselmann
    ("end_ts", "end_timestamp", "End", "Timestamp of job end"),
2290 526f866b Michael Hanselmann
    ]:
2291 526f866b Michael Hanselmann
    getter = operator.attrgetter(attr)
2292 526f866b Michael Hanselmann
    fields.extend([
2293 526f866b Michael Hanselmann
      (_MakeField(name, title, QFT_OTHER,
2294 526f866b Michael Hanselmann
                  "%s (tuple containing seconds and microseconds)" % desc),
2295 526f866b Michael Hanselmann
       None, QFF_SPLIT_TIMESTAMP, _JobTimestamp(getter)),
2296 526f866b Michael Hanselmann
      ])
2297 526f866b Michael Hanselmann
2298 9665bb3a Michael Hanselmann
  return _PrepareFieldList(fields, [])
2299 9665bb3a Michael Hanselmann
2300 9665bb3a Michael Hanselmann
2301 0fdf247d Michael Hanselmann
def _GetExportName(_, (node_name, expname)): # pylint: disable=W0613
2302 0fdf247d Michael Hanselmann
  """Returns an export name if available.
2303 0fdf247d Michael Hanselmann

2304 0fdf247d Michael Hanselmann
  """
2305 0fdf247d Michael Hanselmann
  if expname is None:
2306 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2307 0fdf247d Michael Hanselmann
  else:
2308 0fdf247d Michael Hanselmann
    return expname
2309 0fdf247d Michael Hanselmann
2310 0fdf247d Michael Hanselmann
2311 0fdf247d Michael Hanselmann
def _BuildExportFields():
2312 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2313 0fdf247d Michael Hanselmann

2314 0fdf247d Michael Hanselmann
  """
2315 0fdf247d Michael Hanselmann
  fields = [
2316 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2317 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2318 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2319 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2320 0fdf247d Michael Hanselmann
    ]
2321 0fdf247d Michael Hanselmann
2322 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2323 0fdf247d Michael Hanselmann
2324 0fdf247d Michael Hanselmann
2325 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2326 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2327 dff5f600 Michael Hanselmann
                       "Software version"),
2328 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2329 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2330 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2331 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2332 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2333 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2334 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2335 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2336 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2337 dff5f600 Michael Hanselmann
  }
2338 dff5f600 Michael Hanselmann
2339 dff5f600 Michael Hanselmann
2340 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2341 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2342 dff5f600 Michael Hanselmann
  "master_node": ("Master", QFT_TEXT, QFF_HOSTNAME, "Master node name"),
2343 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2344 dff5f600 Michael Hanselmann
  }
2345 dff5f600 Michael Hanselmann
2346 dff5f600 Michael Hanselmann
2347 dff5f600 Michael Hanselmann
class ClusterQueryData:
2348 dff5f600 Michael Hanselmann
  def __init__(self, cluster, drain_flag, watcher_pause):
2349 dff5f600 Michael Hanselmann
    """Initializes this class.
2350 dff5f600 Michael Hanselmann

2351 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2352 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2353 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2354 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2355 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2356 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2357 dff5f600 Michael Hanselmann

2358 dff5f600 Michael Hanselmann
    """
2359 dff5f600 Michael Hanselmann
    self._cluster = cluster
2360 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2361 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2362 dff5f600 Michael Hanselmann
2363 dff5f600 Michael Hanselmann
  def __iter__(self):
2364 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2365 dff5f600 Michael Hanselmann
2366 dff5f600 Michael Hanselmann
2367 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2368 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2369 dff5f600 Michael Hanselmann

2370 dff5f600 Michael Hanselmann
  """
2371 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2372 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2373 dff5f600 Michael Hanselmann
  else:
2374 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2375 dff5f600 Michael Hanselmann
2376 dff5f600 Michael Hanselmann
2377 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2378 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2379 dff5f600 Michael Hanselmann

2380 dff5f600 Michael Hanselmann
  """
2381 dff5f600 Michael Hanselmann
  fields = [
2382 dff5f600 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), CQ_CONFIG, 0,
2383 dff5f600 Michael Hanselmann
     lambda ctx, cluster: list(cluster.GetTags())),
2384 dff5f600 Michael Hanselmann
    (_MakeField("architecture", "ArchInfo", QFT_OTHER,
2385 dff5f600 Michael Hanselmann
                "Architecture information"), None, 0,
2386 dff5f600 Michael Hanselmann
     lambda ctx, _: runtime.GetArchInfo()),
2387 dff5f600 Michael Hanselmann
    (_MakeField("drain_flag", "QueueDrained", QFT_BOOL,
2388 dff5f600 Michael Hanselmann
                "Flag whether job queue is drained"), CQ_QUEUE_DRAINED, 0,
2389 dff5f600 Michael Hanselmann
     lambda ctx, _: ctx.drain_flag),
2390 dff5f600 Michael Hanselmann
    (_MakeField("watcher_pause", "WatcherPause", QFT_TIMESTAMP,
2391 dff5f600 Michael Hanselmann
                "Until when watcher is paused"), CQ_WATCHER_PAUSE, 0,
2392 dff5f600 Michael Hanselmann
     _ClusterWatcherPause),
2393 dff5f600 Michael Hanselmann
    ]
2394 dff5f600 Michael Hanselmann
2395 dff5f600 Michael Hanselmann
  # Simple fields
2396 dff5f600 Michael Hanselmann
  fields.extend([
2397 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), CQ_CONFIG, flags, _GetItemAttr(name))
2398 dff5f600 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _CLUSTER_SIMPLE_FIELDS.items()
2399 dff5f600 Michael Hanselmann
    ])
2400 dff5f600 Michael Hanselmann
2401 dff5f600 Michael Hanselmann
  # Version fields
2402 dff5f600 Michael Hanselmann
  fields.extend([
2403 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), None, 0, _StaticValue(value))
2404 dff5f600 Michael Hanselmann
    for (name, (title, kind, value, doc)) in _CLUSTER_VERSION_FIELDS.items()
2405 dff5f600 Michael Hanselmann
    ])
2406 dff5f600 Michael Hanselmann
2407 dff5f600 Michael Hanselmann
  # Add timestamps
2408 dff5f600 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(CQ_CONFIG))
2409 dff5f600 Michael Hanselmann
2410 dff5f600 Michael Hanselmann
  return _PrepareFieldList(fields, [
2411 dff5f600 Michael Hanselmann
    ("name", "cluster_name"),
2412 dff5f600 Michael Hanselmann
    ])
2413 dff5f600 Michael Hanselmann
2414 dff5f600 Michael Hanselmann
2415 dff5f600 Michael Hanselmann
#: Fields for cluster information
2416 dff5f600 Michael Hanselmann
CLUSTER_FIELDS = _BuildClusterFields()
2417 dff5f600 Michael Hanselmann
2418 8235fe04 Michael Hanselmann
#: Fields available for node queries
2419 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2420 1c8addc6 Michael Hanselmann
2421 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2422 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2423 24d16f76 Michael Hanselmann
2424 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2425 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2426 e571ee44 Adeodato Simo
2427 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2428 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2429 8e21cfc0 Adeodato Simo
2430 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2431 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2432 be3a4b14 Michael Hanselmann
2433 9665bb3a Michael Hanselmann
#: Fields available for job queries
2434 9665bb3a Michael Hanselmann
JOB_FIELDS = _BuildJobFields()
2435 9665bb3a Michael Hanselmann
2436 0fdf247d Michael Hanselmann
#: Fields available for exports
2437 0fdf247d Michael Hanselmann
EXPORT_FIELDS = _BuildExportFields()
2438 0fdf247d Michael Hanselmann
2439 95eb4188 Michael Hanselmann
#: All available resources
2440 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2441 dff5f600 Michael Hanselmann
  constants.QR_CLUSTER: CLUSTER_FIELDS,
2442 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2443 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2444 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2445 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2446 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2447 9665bb3a Michael Hanselmann
  constants.QR_JOB: JOB_FIELDS,
2448 0fdf247d Michael Hanselmann
  constants.QR_EXPORT: EXPORT_FIELDS,
2449 95eb4188 Michael Hanselmann
  }
2450 95eb4188 Michael Hanselmann
2451 e571ee44 Adeodato Simo
#: All available field lists
2452 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()