Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 7cb42171

History | View | Annotate | Download (72.8 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 8930b0f0 Iustin Pop
# TODO: Consider moving titles closer to constants
149 8930b0f0 Iustin Pop
NDP_TITLE = {
150 8930b0f0 Iustin Pop
  constants.ND_OOB_PROGRAM: "OutOfBandProgram",
151 8930b0f0 Iustin Pop
  constants.ND_SPINDLE_COUNT: "SpindleCount",
152 8930b0f0 Iustin Pop
  }
153 8930b0f0 Iustin Pop
154 4ca96421 Michael Hanselmann
155 b459a848 Andrea Spadaccini
def _GetUnknownField(ctx, item): # pylint: disable=W0613
156 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
157 4ca96421 Michael Hanselmann

158 4ca96421 Michael Hanselmann
  """
159 e2d188cc Iustin Pop
  return _FS_UNKNOWN
160 4ca96421 Michael Hanselmann
161 4ca96421 Michael Hanselmann
162 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
163 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
164 4ca96421 Michael Hanselmann

165 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
166 4ca96421 Michael Hanselmann

167 4ca96421 Michael Hanselmann
  @type fielddefs: dict
168 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
169 4ca96421 Michael Hanselmann
  @type selected: list of strings
170 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
171 4ca96421 Michael Hanselmann

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

192 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
193 4ca96421 Michael Hanselmann

194 4ca96421 Michael Hanselmann
  """
195 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
196 4ca96421 Michael Hanselmann
197 4ca96421 Michael Hanselmann
198 fb0be379 Michael Hanselmann
class _FilterHints:
199 fb0be379 Michael Hanselmann
  """Class for filter analytics.
200 fb0be379 Michael Hanselmann

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

206 fb0be379 Michael Hanselmann
  There are two ways to optimize this. The first, and simpler, is to assign
207 fb0be379 Michael Hanselmann
  each field a group of data, so that the caller can determine which
208 fb0be379 Michael Hanselmann
  computations are necessary depending on the data groups requested. The list
209 fb0be379 Michael Hanselmann
  of referenced groups must also be computed for fields referenced in the
210 fb0be379 Michael Hanselmann
  filter.
211 fb0be379 Michael Hanselmann

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

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

221 fb0be379 Michael Hanselmann
  """
222 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
223 fb0be379 Michael Hanselmann
    """Initializes this class.
224 fb0be379 Michael Hanselmann

225 fb0be379 Michael Hanselmann
    @type namefield: string
226 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
227 fb0be379 Michael Hanselmann

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

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

247 fb0be379 Michael Hanselmann
    @rtype: list
248 fb0be379 Michael Hanselmann

249 fb0be379 Michael Hanselmann
    """
250 fb0be379 Michael Hanselmann
    if self._allnames or self._names is None:
251 fb0be379 Michael Hanselmann
      return None
252 fb0be379 Michael Hanselmann
253 fb0be379 Michael Hanselmann
    return utils.UniqueSequence(self._names)
254 fb0be379 Michael Hanselmann
255 fb0be379 Michael Hanselmann
  def ReferencedData(self):
256 fb0be379 Michael Hanselmann
    """Returns all kinds of data referenced by the filter.
257 fb0be379 Michael Hanselmann

258 fb0be379 Michael Hanselmann
    """
259 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
260 fb0be379 Michael Hanselmann
261 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
262 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
263 fb0be379 Michael Hanselmann

264 fb0be379 Michael Hanselmann
    """
265 fb0be379 Michael Hanselmann
    self._allnames = True
266 fb0be379 Michael Hanselmann
    self._names = None
267 fb0be379 Michael Hanselmann
268 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
269 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
270 fb0be379 Michael Hanselmann

271 fb0be379 Michael Hanselmann
    @type op: string
272 fb0be379 Michael Hanselmann
    @param op: Operator
273 fb0be379 Michael Hanselmann

274 fb0be379 Michael Hanselmann
    """
275 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
276 fb0be379 Michael Hanselmann
      self._NeedAllNames()
277 fb0be379 Michael Hanselmann
278 b459a848 Andrea Spadaccini
  def NoteUnaryOp(self, op): # pylint: disable=W0613
279 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
280 fb0be379 Michael Hanselmann

281 fb0be379 Michael Hanselmann
    @type op: string
282 fb0be379 Michael Hanselmann
    @param op: Operator
283 fb0be379 Michael Hanselmann

284 fb0be379 Michael Hanselmann
    """
285 fb0be379 Michael Hanselmann
    self._NeedAllNames()
286 fb0be379 Michael Hanselmann
287 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
288 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
289 fb0be379 Michael Hanselmann

290 fb0be379 Michael Hanselmann
    @type op: string
291 fb0be379 Michael Hanselmann
    @param op: Operator
292 fb0be379 Michael Hanselmann
    @type name: string
293 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
294 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
295 fb0be379 Michael Hanselmann

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

316 fb0be379 Michael Hanselmann
  """
317 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
318 fb0be379 Michael Hanselmann
319 fb0be379 Michael Hanselmann
320 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
321 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
322 fb0be379 Michael Hanselmann

323 fb0be379 Michael Hanselmann
  """
324 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
325 fb0be379 Michael Hanselmann
326 fb0be379 Michael Hanselmann
327 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
328 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
329 fb0be379 Michael Hanselmann

330 fb0be379 Michael Hanselmann
  """
331 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
332 fb0be379 Michael Hanselmann
333 fb0be379 Michael Hanselmann
334 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
335 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
336 fb0be379 Michael Hanselmann

337 fb0be379 Michael Hanselmann
  """
338 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
339 fb0be379 Michael Hanselmann
340 fb0be379 Michael Hanselmann
341 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
342 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
343 23d0a608 Michael Hanselmann

344 23d0a608 Michael Hanselmann
  """
345 23d0a608 Michael Hanselmann
  try:
346 23d0a608 Michael Hanselmann
    return re.compile(pattern)
347 23d0a608 Michael Hanselmann
  except re.error, err:
348 23d0a608 Michael Hanselmann
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
349 23d0a608 Michael Hanselmann
350 23d0a608 Michael Hanselmann
351 526f866b Michael Hanselmann
def _PrepareSplitTimestamp(value):
352 526f866b Michael Hanselmann
  """Prepares a value for comparison by L{_MakeSplitTimestampComparison}.
353 526f866b Michael Hanselmann

354 526f866b Michael Hanselmann
  """
355 526f866b Michael Hanselmann
  if ht.TNumber(value):
356 526f866b Michael Hanselmann
    return value
357 526f866b Michael Hanselmann
  else:
358 526f866b Michael Hanselmann
    return utils.MergeTime(value)
359 526f866b Michael Hanselmann
360 526f866b Michael Hanselmann
361 526f866b Michael Hanselmann
def _MakeSplitTimestampComparison(fn):
362 526f866b Michael Hanselmann
  """Compares split timestamp values after converting to float.
363 526f866b Michael Hanselmann

364 526f866b Michael Hanselmann
  """
365 526f866b Michael Hanselmann
  return lambda lhs, rhs: fn(utils.MergeTime(lhs), rhs)
366 526f866b Michael Hanselmann
367 526f866b Michael Hanselmann
368 526f866b Michael Hanselmann
def _MakeComparisonChecks(fn):
369 526f866b Michael Hanselmann
  """Prepares flag-specific comparisons using a comparison function.
370 526f866b Michael Hanselmann

371 526f866b Michael Hanselmann
  """
372 526f866b Michael Hanselmann
  return [
373 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(fn),
374 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
375 526f866b Michael Hanselmann
    (QFF_JOB_ID, lambda lhs, rhs: fn(jstore.ParseJobId(lhs), rhs),
376 526f866b Michael Hanselmann
     jstore.ParseJobId),
377 526f866b Michael Hanselmann
    (None, fn, None),
378 526f866b Michael Hanselmann
    ]
379 526f866b Michael Hanselmann
380 526f866b Michael Hanselmann
381 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
382 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
383 fb0be379 Michael Hanselmann

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

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

401 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
402 fb0be379 Michael Hanselmann
  using binary AND.
403 fb0be379 Michael Hanselmann

404 fb0be379 Michael Hanselmann
  """
405 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
406 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
407 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
408 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
409 23d0a608 Michael Hanselmann
     None),
410 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(operator.eq),
411 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
412 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
413 fb0be379 Michael Hanselmann
    ]
414 fb0be379 Michael Hanselmann
415 fb0be379 Michael Hanselmann
  """Known operators
416 fb0be379 Michael Hanselmann

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

420 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
421 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
422 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
423 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
424 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
425 fb0be379 Michael Hanselmann

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

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

458 fb0be379 Michael Hanselmann
    """
459 fb0be379 Michael Hanselmann
    self._fields = fields
460 fb0be379 Michael Hanselmann
    self._hints = None
461 fb0be379 Michael Hanselmann
    self._op_handler = None
462 fb0be379 Michael Hanselmann
463 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
464 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
465 fb0be379 Michael Hanselmann

466 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
467 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
468 2e5c33db Iustin Pop
    @type qfilter: list
469 2e5c33db Iustin Pop
    @param qfilter: Filter structure
470 fb0be379 Michael Hanselmann
    @rtype: callable
471 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
472 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
473 fb0be379 Michael Hanselmann

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

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

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

522 3b877f08 Michael Hanselmann
    """
523 3b877f08 Michael Hanselmann
    try:
524 3b877f08 Michael Hanselmann
      return self._fields[name]
525 3b877f08 Michael Hanselmann
    except KeyError:
526 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
527 3b877f08 Michael Hanselmann
528 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
529 fb0be379 Michael Hanselmann
    """Handles logic operators.
530 fb0be379 Michael Hanselmann

531 fb0be379 Michael Hanselmann
    @type hints_fn: callable
532 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
533 fb0be379 Michael Hanselmann
    @type level: integer
534 fb0be379 Michael Hanselmann
    @param level: Current depth
535 fb0be379 Michael Hanselmann
    @type op: string
536 fb0be379 Michael Hanselmann
    @param op: Operator
537 fb0be379 Michael Hanselmann
    @type op_fn: callable
538 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
539 fb0be379 Michael Hanselmann
    @type operands: list
540 fb0be379 Michael Hanselmann
    @param operands: List of operands
541 fb0be379 Michael Hanselmann

542 fb0be379 Michael Hanselmann
    """
543 fb0be379 Michael Hanselmann
    if hints_fn:
544 fb0be379 Michael Hanselmann
      hints_fn(op)
545 fb0be379 Michael Hanselmann
546 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
547 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
548 fb0be379 Michael Hanselmann
549 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
550 fb0be379 Michael Hanselmann
    """Handles unary operators.
551 fb0be379 Michael Hanselmann

552 fb0be379 Michael Hanselmann
    @type hints_fn: callable
553 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
554 fb0be379 Michael Hanselmann
    @type level: integer
555 fb0be379 Michael Hanselmann
    @param level: Current depth
556 fb0be379 Michael Hanselmann
    @type op: string
557 fb0be379 Michael Hanselmann
    @param op: Operator
558 fb0be379 Michael Hanselmann
    @type op_fn: callable
559 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
560 fb0be379 Michael Hanselmann
    @type operands: list
561 fb0be379 Michael Hanselmann
    @param operands: List of operands
562 fb0be379 Michael Hanselmann

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

589 fb0be379 Michael Hanselmann
    @type hints_fn: callable
590 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
591 fb0be379 Michael Hanselmann
    @type level: integer
592 fb0be379 Michael Hanselmann
    @param level: Current depth
593 fb0be379 Michael Hanselmann
    @type op: string
594 fb0be379 Michael Hanselmann
    @param op: Operator
595 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
596 fb0be379 Michael Hanselmann
    @type operands: list
597 fb0be379 Michael Hanselmann
    @param operands: List of operands
598 fb0be379 Michael Hanselmann

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

638 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
639 fb0be379 Michael Hanselmann

640 fb0be379 Michael Hanselmann
  @rtype: callable
641 fb0be379 Michael Hanselmann

642 fb0be379 Michael Hanselmann
  """
643 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
644 fb0be379 Michael Hanselmann
645 fb0be379 Michael Hanselmann
646 4ca96421 Michael Hanselmann
class Query:
647 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
648 4ca96421 Michael Hanselmann
    """Initializes this class.
649 4ca96421 Michael Hanselmann

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

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

660 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
661 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
662 4ca96421 Michael Hanselmann
    @type selected: list of strings
663 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
664 4ca96421 Michael Hanselmann

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

695 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
696 fb0be379 Michael Hanselmann
    names, C{None} is returned.
697 fb0be379 Michael Hanselmann

698 fb0be379 Michael Hanselmann
    """
699 fb0be379 Michael Hanselmann
    return self._requested_names
700 fb0be379 Michael Hanselmann
701 4ca96421 Michael Hanselmann
  def RequestedData(self):
702 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
703 4ca96421 Michael Hanselmann

704 4ca96421 Michael Hanselmann
    @rtype: frozenset
705 4ca96421 Michael Hanselmann

706 4ca96421 Michael Hanselmann
    """
707 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
708 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
709 fb0be379 Michael Hanselmann
                      if datakind is not None))
710 4ca96421 Michael Hanselmann
711 4ca96421 Michael Hanselmann
  def GetFields(self):
712 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
713 4ca96421 Michael Hanselmann

714 4ca96421 Michael Hanselmann
    Includes unknown fields.
715 4ca96421 Michael Hanselmann

716 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
717 4ca96421 Michael Hanselmann

718 4ca96421 Michael Hanselmann
    """
719 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
720 4ca96421 Michael Hanselmann
721 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
722 4ca96421 Michael Hanselmann
    """Execute a query.
723 4ca96421 Michael Hanselmann

724 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
725 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
726 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
727 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
728 fbc263a9 Michael Hanselmann
      ordering
729 4ca96421 Michael Hanselmann

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

768 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
769 4ca96421 Michael Hanselmann

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

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

801 4ca96421 Michael Hanselmann
  @type fields: list
802 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
803 4ca96421 Michael Hanselmann
  @type row: list of tuples
804 4ca96421 Michael Hanselmann
  @param row: Row data
805 4ca96421 Michael Hanselmann

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

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

839 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
840 4ca96421 Michael Hanselmann

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

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

877 b60fcb6f Michael Hanselmann
  @type query: L{Query}
878 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
879 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
880 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
881 fbc263a9 Michael Hanselmann
    ordering
882 b60fcb6f Michael Hanselmann

883 b60fcb6f Michael Hanselmann
  """
884 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
885 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
886 b60fcb6f Michael Hanselmann
887 b60fcb6f Michael Hanselmann
888 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
889 aa29e95f Michael Hanselmann
  """Returns list of available fields.
890 aa29e95f Michael Hanselmann

891 aa29e95f Michael Hanselmann
  @type fielddefs: dict
892 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
893 aa29e95f Michael Hanselmann
  @type selected: list of strings
894 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
895 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
896 aa29e95f Michael Hanselmann

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

912 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
913 4ca96421 Michael Hanselmann
  @param title: Human-readable title
914 4ca96421 Michael Hanselmann
  @param kind: Field type
915 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
916 4ca96421 Michael Hanselmann

917 4ca96421 Michael Hanselmann
  """
918 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
919 1ae17369 Michael Hanselmann
                                      doc=doc)
920 8235fe04 Michael Hanselmann
921 8235fe04 Michael Hanselmann
922 dff5f600 Michael Hanselmann
def _StaticValueInner(value, ctx, _): # pylint: disable=W0613
923 dff5f600 Michael Hanselmann
  """Returns a static value.
924 dff5f600 Michael Hanselmann

925 dff5f600 Michael Hanselmann
  """
926 dff5f600 Michael Hanselmann
  return value
927 dff5f600 Michael Hanselmann
928 dff5f600 Michael Hanselmann
929 dff5f600 Michael Hanselmann
def _StaticValue(value):
930 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
931 dff5f600 Michael Hanselmann

932 dff5f600 Michael Hanselmann
  """
933 dff5f600 Michael Hanselmann
  return compat.partial(_StaticValueInner, value)
934 dff5f600 Michael Hanselmann
935 dff5f600 Michael Hanselmann
936 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
937 8235fe04 Michael Hanselmann
  """Determine node role.
938 8235fe04 Michael Hanselmann

939 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
940 8235fe04 Michael Hanselmann
  @param node: Node object
941 8235fe04 Michael Hanselmann
  @type master_name: string
942 8235fe04 Michael Hanselmann
  @param master_name: Master node name
943 8235fe04 Michael Hanselmann

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

960 8235fe04 Michael Hanselmann
  @param attr: Attribute name
961 8235fe04 Michael Hanselmann

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

970 8930b0f0 Iustin Pop
  """
971 8930b0f0 Iustin Pop
  def _helper(ctx, _):
972 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
973 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
974 8930b0f0 Iustin Pop
    else:
975 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
976 8930b0f0 Iustin Pop
  return _helper
977 8930b0f0 Iustin Pop
978 8930b0f0 Iustin Pop
979 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
980 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
981 8930b0f0 Iustin Pop

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

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

998 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
999 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1000 425e5bf0 Michael Hanselmann

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

1016 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1017 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1018 425e5bf0 Michael Hanselmann

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

1026 145bea54 Michael Hanselmann
  @type getter: callable
1027 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1028 145bea54 Michael Hanselmann

1029 145bea54 Michael Hanselmann
  """
1030 145bea54 Michael Hanselmann
  def fn(_, item):
1031 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1032 145bea54 Michael Hanselmann

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

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

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

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

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

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

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

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

1145 8572f1fe René Nussbaumer
  """
1146 8572f1fe René Nussbaumer
  def fn(ctx, node):
1147 8572f1fe René Nussbaumer
    """Get group data for a node.
1148 8572f1fe René Nussbaumer

1149 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1150 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1151 8572f1fe René Nussbaumer
    @param inst: Node object
1152 8572f1fe René Nussbaumer

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

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

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

1180 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1181 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1182 52b5d286 René Nussbaumer
  @param node: Node object
1183 52b5d286 René Nussbaumer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1437 1c8addc6 Michael Hanselmann
  @type name: string
1438 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1439 1c8addc6 Michael Hanselmann

1440 1c8addc6 Michael Hanselmann
  """
1441 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1442 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1443 1c8addc6 Michael Hanselmann

1444 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1445 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1446 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1447 1c8addc6 Michael Hanselmann

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

1468 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1469 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1470 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1471 1c8addc6 Michael Hanselmann

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

1498 1c8addc6 Michael Hanselmann
  @type index: int
1499 1c8addc6 Michael Hanselmann
  @param index: Disk index
1500 1c8addc6 Michael Hanselmann

1501 1c8addc6 Michael Hanselmann
  """
1502 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1503 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1504 1c8addc6 Michael Hanselmann

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

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

1520 1c8addc6 Michael Hanselmann
  @type index: int
1521 1c8addc6 Michael Hanselmann
  @param index: NIC index
1522 1c8addc6 Michael Hanselmann
  @type cb: callable
1523 1c8addc6 Michael Hanselmann
  @param cb: Callback
1524 1c8addc6 Michael Hanselmann

1525 1c8addc6 Michael Hanselmann
  """
1526 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1527 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1528 1c8addc6 Michael Hanselmann

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

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

1547 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1548 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1549 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1550 1c8addc6 Michael Hanselmann

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

1561 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1562 1c8addc6 Michael Hanselmann
  @type index: int
1563 1c8addc6 Michael Hanselmann
  @param index: NIC index
1564 1c8addc6 Michael Hanselmann

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

1579 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1580 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1581 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1582 1c8addc6 Michael Hanselmann

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

1602 1c8addc6 Michael Hanselmann
  @type name: string
1603 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1604 1c8addc6 Michael Hanselmann

1605 1c8addc6 Michael Hanselmann
  """
1606 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1607 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1608 1c8addc6 Michael Hanselmann

1609 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1610 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1611 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1612 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1613 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1614 1c8addc6 Michael Hanselmann

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

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

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

1693 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1694 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1695 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1696 1c8addc6 Michael Hanselmann

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

1709 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1710 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1711 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1712 5d28cb6f Michael Hanselmann

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

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

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

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

1756 1c8addc6 Michael Hanselmann
  """
1757 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1758 1c8addc6 Michael Hanselmann
  be_title = {
1759 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1760 31d1791a Guido Trotter
    constants.BE_MAXMEM: "ConfigMaxMem",
1761 31d1791a Guido Trotter
    constants.BE_MINMEM: "ConfigMinMem",
1762 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1763 1c8addc6 Michael Hanselmann
    }
1764 1c8addc6 Michael Hanselmann
1765 1c8addc6 Michael Hanselmann
  hv_title = {
1766 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1767 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1768 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1769 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1770 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1771 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1772 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1773 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1774 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1775 87f0aa48 Jack
    constants.HV_PASSTHROUGH: "pci_pass",
1776 7cb42171 Nikita Staroverov
    constants.HV_CPU_TYPE: "cpu_type",
1777 1c8addc6 Michael Hanselmann
    }
1778 1c8addc6 Michael Hanselmann
1779 1c8addc6 Michael Hanselmann
  fields = [
1780 1c8addc6 Michael Hanselmann
    # Filled parameters
1781 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1782 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1783 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1784 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1785 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1786 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1787 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1788 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1789 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1790 1c8addc6 Michael Hanselmann
1791 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1792 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1793 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1794 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1795 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1796 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1797 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1798 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1799 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1800 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1801 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1802 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1803 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1804 1c8addc6 Michael Hanselmann
    ]
1805 1c8addc6 Michael Hanselmann
1806 1c8addc6 Michael Hanselmann
  # HV params
1807 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1808 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1809 1c8addc6 Michael Hanselmann
1810 1c8addc6 Michael Hanselmann
  fields.extend([
1811 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1812 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1813 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1814 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1815 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1816 1c8addc6 Michael Hanselmann
    ])
1817 1c8addc6 Michael Hanselmann
1818 1c8addc6 Michael Hanselmann
  # BE params
1819 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1820 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1821 1c8addc6 Michael Hanselmann
1822 1c8addc6 Michael Hanselmann
  fields.extend([
1823 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1824 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1825 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1826 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1827 1c8addc6 Michael Hanselmann
    ])
1828 1c8addc6 Michael Hanselmann
1829 1c8addc6 Michael Hanselmann
  return fields
1830 1c8addc6 Michael Hanselmann
1831 1c8addc6 Michael Hanselmann
1832 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1833 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1834 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1835 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1836 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1837 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1838 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1839 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1840 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1841 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1842 1c8addc6 Michael Hanselmann
  }
1843 1c8addc6 Michael Hanselmann
1844 1c8addc6 Michael Hanselmann
1845 fab9573b Michael Hanselmann
def _GetInstNodeGroup(ctx, default, node_name):
1846 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
1847 fab9573b Michael Hanselmann

1848 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1849 fab9573b Michael Hanselmann
  @param default: Default value
1850 fab9573b Michael Hanselmann
  @type node_name: string
1851 fab9573b Michael Hanselmann
  @param node_name: Node name
1852 fab9573b Michael Hanselmann

1853 fab9573b Michael Hanselmann
  """
1854 fab9573b Michael Hanselmann
  try:
1855 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1856 fab9573b Michael Hanselmann
  except KeyError:
1857 fab9573b Michael Hanselmann
    return default
1858 fab9573b Michael Hanselmann
  else:
1859 fab9573b Michael Hanselmann
    return node.group
1860 fab9573b Michael Hanselmann
1861 fab9573b Michael Hanselmann
1862 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1863 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1864 fab9573b Michael Hanselmann

1865 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1866 fab9573b Michael Hanselmann
  @param default: Default value
1867 fab9573b Michael Hanselmann
  @type node_name: string
1868 fab9573b Michael Hanselmann
  @param node_name: Node name
1869 fab9573b Michael Hanselmann

1870 fab9573b Michael Hanselmann
  """
1871 fab9573b Michael Hanselmann
  try:
1872 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1873 fab9573b Michael Hanselmann
  except KeyError:
1874 fab9573b Michael Hanselmann
    return default
1875 fab9573b Michael Hanselmann
1876 fab9573b Michael Hanselmann
  try:
1877 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1878 fab9573b Michael Hanselmann
  except KeyError:
1879 fab9573b Michael Hanselmann
    return default
1880 fab9573b Michael Hanselmann
1881 fab9573b Michael Hanselmann
  return group.name
1882 fab9573b Michael Hanselmann
1883 fab9573b Michael Hanselmann
1884 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1885 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1886 1c8addc6 Michael Hanselmann

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

1984 24d16f76 Michael Hanselmann
  """
1985 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1986 24d16f76 Michael Hanselmann
    """Initializes this class.
1987 24d16f76 Michael Hanselmann

1988 24d16f76 Michael Hanselmann
    """
1989 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1990 24d16f76 Michael Hanselmann
1991 24d16f76 Michael Hanselmann
  def __iter__(self):
1992 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1993 24d16f76 Michael Hanselmann

1994 24d16f76 Michael Hanselmann
    """
1995 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1996 24d16f76 Michael Hanselmann
1997 24d16f76 Michael Hanselmann
1998 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1999 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
2000 24d16f76 Michael Hanselmann

2001 24d16f76 Michael Hanselmann
  """
2002 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
2003 24d16f76 Michael Hanselmann
2004 24d16f76 Michael Hanselmann
  if owners:
2005 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
2006 24d16f76 Michael Hanselmann
2007 e2d188cc Iustin Pop
  return owners
2008 24d16f76 Michael Hanselmann
2009 24d16f76 Michael Hanselmann
2010 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
2011 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
2012 24d16f76 Michael Hanselmann

2013 24d16f76 Michael Hanselmann
  """
2014 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
2015 24d16f76 Michael Hanselmann
2016 24d16f76 Michael Hanselmann
  if pending:
2017 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
2018 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
2019 24d16f76 Michael Hanselmann
2020 e2d188cc Iustin Pop
  return pending
2021 24d16f76 Michael Hanselmann
2022 24d16f76 Michael Hanselmann
2023 24d16f76 Michael Hanselmann
def _BuildLockFields():
2024 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
2025 24d16f76 Michael Hanselmann

2026 24d16f76 Michael Hanselmann
  """
2027 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
2028 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
2029 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
2030 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
2031 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
2032 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
2033 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
2034 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
2035 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
2036 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
2037 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
2038 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
2039 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
2040 d63bd540 Iustin Pop
    ], [])
2041 24d16f76 Michael Hanselmann
2042 24d16f76 Michael Hanselmann
2043 8e21cfc0 Adeodato Simo
class GroupQueryData:
2044 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
2045 8e21cfc0 Adeodato Simo

2046 8e21cfc0 Adeodato Simo
  """
2047 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2048 2c758845 René Nussbaumer
               want_diskparams):
2049 8e21cfc0 Adeodato Simo
    """Initializes this class.
2050 8e21cfc0 Adeodato Simo

2051 edd49f9b Agata Murawska
    @param cluster: Cluster object
2052 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2053 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2054 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2055 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2056 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2057 2c758845 René Nussbaumer
    @type want_diskparams: bool
2058 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2059 8e21cfc0 Adeodato Simo

2060 8e21cfc0 Adeodato Simo
    """
2061 8e21cfc0 Adeodato Simo
    self.groups = groups
2062 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2063 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2064 edd49f9b Agata Murawska
    self.cluster = cluster
2065 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2066 edd49f9b Agata Murawska
2067 edd49f9b Agata Murawska
    # Used for individual rows
2068 edd49f9b Agata Murawska
    self.group_ipolicy = None
2069 8930b0f0 Iustin Pop
    self.ndparams = None
2070 2c758845 René Nussbaumer
    self.group_dp = None
2071 8e21cfc0 Adeodato Simo
2072 8e21cfc0 Adeodato Simo
  def __iter__(self):
2073 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2074 8e21cfc0 Adeodato Simo

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

2078 8e21cfc0 Adeodato Simo
    """
2079 edd49f9b Agata Murawska
    for group in self.groups:
2080 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2081 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2082 2c758845 René Nussbaumer
      if self.want_diskparams:
2083 2c758845 René Nussbaumer
        self.group_dp = self.cluster.SimpleFillDP(group.diskparams)
2084 2c758845 René Nussbaumer
      else:
2085 2c758845 René Nussbaumer
        self.group_dp = None
2086 edd49f9b Agata Murawska
      yield group
2087 8e21cfc0 Adeodato Simo
2088 8e21cfc0 Adeodato Simo
2089 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2090 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2091 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2092 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2093 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2094 8e21cfc0 Adeodato Simo
  }
2095 8e21cfc0 Adeodato Simo
2096 8e21cfc0 Adeodato Simo
2097 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2098 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2099 8e21cfc0 Adeodato Simo

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

2181 be3a4b14 Michael Hanselmann
  """
2182 be3a4b14 Michael Hanselmann
  fields = [
2183 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2184 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2185 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2186 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2187 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2188 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2189 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2190 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2191 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2192 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2193 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2194 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2195 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2196 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2197 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2198 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2199 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2200 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2201 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2202 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2203 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2204 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2205 be3a4b14 Michael Hanselmann
                "Status from node"),
2206 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2207 be3a4b14 Michael Hanselmann
    ]
2208 be3a4b14 Michael Hanselmann
2209 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2210 be3a4b14 Michael Hanselmann
2211 be3a4b14 Michael Hanselmann
2212 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2213 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2214 9665bb3a Michael Hanselmann

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

2218 9665bb3a Michael Hanselmann
  """
2219 9665bb3a Michael Hanselmann
  if job is None:
2220 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2221 9665bb3a Michael Hanselmann
  else:
2222 9665bb3a Michael Hanselmann
    return fn(job)
2223 9665bb3a Michael Hanselmann
2224 9665bb3a Michael Hanselmann
2225 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2226 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2227 9665bb3a Michael Hanselmann

2228 9665bb3a Michael Hanselmann
  """
2229 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2230 9665bb3a Michael Hanselmann
2231 9665bb3a Michael Hanselmann
2232 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2233 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2234 9665bb3a Michael Hanselmann

2235 9665bb3a Michael Hanselmann
  """
2236 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2237 9665bb3a Michael Hanselmann
2238 9665bb3a Michael Hanselmann
2239 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2240 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2241 9665bb3a Michael Hanselmann

2242 9665bb3a Michael Hanselmann
  """
2243 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2244 9665bb3a Michael Hanselmann
2245 9665bb3a Michael Hanselmann
2246 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2247 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2248 9665bb3a Michael Hanselmann

2249 9665bb3a Michael Hanselmann
  """
2250 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2251 9665bb3a Michael Hanselmann
2252 9665bb3a Michael Hanselmann
  if timestamp is None:
2253 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2254 9665bb3a Michael Hanselmann
  else:
2255 9665bb3a Michael Hanselmann
    return timestamp
2256 9665bb3a Michael Hanselmann
2257 9665bb3a Michael Hanselmann
2258 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2259 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2260 9665bb3a Michael Hanselmann

2261 9665bb3a Michael Hanselmann
  """
2262 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2263 9665bb3a Michael Hanselmann
2264 9665bb3a Michael Hanselmann
2265 9665bb3a Michael Hanselmann
def _BuildJobFields():
2266 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2267 9665bb3a Michael Hanselmann

2268 9665bb3a Michael Hanselmann
  """
2269 9665bb3a Michael Hanselmann
  fields = [
2270 9665bb3a Michael Hanselmann
    (_MakeField("id", "ID", QFT_TEXT, "Job ID"),
2271 526f866b Michael Hanselmann
     None, QFF_JOB_ID, lambda _, (job_id, job): job_id),
2272 9665bb3a Michael Hanselmann
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2273 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2274 9665bb3a Michael Hanselmann
    (_MakeField("priority", "Priority", QFT_NUMBER,
2275 9665bb3a Michael Hanselmann
                ("Current job priority (%s to %s)" %
2276 9665bb3a Michael Hanselmann
                 (constants.OP_PRIO_LOWEST, constants.OP_PRIO_HIGHEST))),
2277 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcPriority())),
2278 9665bb3a Michael Hanselmann
    (_MakeField("ops", "OpCodes", QFT_OTHER, "List of all opcodes"),
2279 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.__getstate__())),
2280 9665bb3a Michael Hanselmann
    (_MakeField("opresult", "OpCode_result", QFT_OTHER,
2281 9665bb3a Michael Hanselmann
                "List of opcodes results"),
2282 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("result"))),
2283 9665bb3a Michael Hanselmann
    (_MakeField("opstatus", "OpCode_status", QFT_OTHER,
2284 9665bb3a Michael Hanselmann
                "List of opcodes status"),
2285 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("status"))),
2286 9665bb3a Michael Hanselmann
    (_MakeField("oplog", "OpCode_log", QFT_OTHER,
2287 9665bb3a Michael Hanselmann
                "List of opcode output logs"),
2288 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("log"))),
2289 9665bb3a Michael Hanselmann
    (_MakeField("opstart", "OpCode_start", QFT_OTHER,
2290 9665bb3a Michael Hanselmann
                "List of opcode start timestamps (before acquiring locks)"),
2291 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("start_timestamp"))),
2292 9665bb3a Michael Hanselmann
    (_MakeField("opexec", "OpCode_exec", QFT_OTHER,
2293 9665bb3a Michael Hanselmann
                "List of opcode execution start timestamps (after acquiring"
2294 9665bb3a Michael Hanselmann
                " locks)"),
2295 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("exec_timestamp"))),
2296 9665bb3a Michael Hanselmann
    (_MakeField("opend", "OpCode_end", QFT_OTHER,
2297 9665bb3a Michael Hanselmann
                "List of opcode execution end timestamps"),
2298 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("end_timestamp"))),
2299 9665bb3a Michael Hanselmann
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2300 9665bb3a Michael Hanselmann
                "List of opcode priorities"),
2301 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2302 9665bb3a Michael Hanselmann
    (_MakeField("summary", "Summary", QFT_OTHER,
2303 9665bb3a Michael Hanselmann
                "List of per-opcode summaries"),
2304 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2305 9665bb3a Michael Hanselmann
    ]
2306 9665bb3a Michael Hanselmann
2307 526f866b Michael Hanselmann
  # Timestamp fields
2308 526f866b Michael Hanselmann
  for (name, attr, title, desc) in [
2309 526f866b Michael Hanselmann
    ("received_ts", "received_timestamp", "Received",
2310 526f866b Michael Hanselmann
     "Timestamp of when job was received"),
2311 526f866b Michael Hanselmann
    ("start_ts", "start_timestamp", "Start", "Timestamp of job start"),
2312 526f866b Michael Hanselmann
    ("end_ts", "end_timestamp", "End", "Timestamp of job end"),
2313 526f866b Michael Hanselmann
    ]:
2314 526f866b Michael Hanselmann
    getter = operator.attrgetter(attr)
2315 526f866b Michael Hanselmann
    fields.extend([
2316 526f866b Michael Hanselmann
      (_MakeField(name, title, QFT_OTHER,
2317 526f866b Michael Hanselmann
                  "%s (tuple containing seconds and microseconds)" % desc),
2318 526f866b Michael Hanselmann
       None, QFF_SPLIT_TIMESTAMP, _JobTimestamp(getter)),
2319 526f866b Michael Hanselmann
      ])
2320 526f866b Michael Hanselmann
2321 9665bb3a Michael Hanselmann
  return _PrepareFieldList(fields, [])
2322 9665bb3a Michael Hanselmann
2323 9665bb3a Michael Hanselmann
2324 0fdf247d Michael Hanselmann
def _GetExportName(_, (node_name, expname)): # pylint: disable=W0613
2325 0fdf247d Michael Hanselmann
  """Returns an export name if available.
2326 0fdf247d Michael Hanselmann

2327 0fdf247d Michael Hanselmann
  """
2328 0fdf247d Michael Hanselmann
  if expname is None:
2329 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2330 0fdf247d Michael Hanselmann
  else:
2331 0fdf247d Michael Hanselmann
    return expname
2332 0fdf247d Michael Hanselmann
2333 0fdf247d Michael Hanselmann
2334 0fdf247d Michael Hanselmann
def _BuildExportFields():
2335 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2336 0fdf247d Michael Hanselmann

2337 0fdf247d Michael Hanselmann
  """
2338 0fdf247d Michael Hanselmann
  fields = [
2339 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2340 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2341 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2342 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2343 0fdf247d Michael Hanselmann
    ]
2344 0fdf247d Michael Hanselmann
2345 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2346 0fdf247d Michael Hanselmann
2347 0fdf247d Michael Hanselmann
2348 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2349 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2350 dff5f600 Michael Hanselmann
                       "Software version"),
2351 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2352 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2353 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2354 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2355 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2356 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2357 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2358 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2359 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2360 dff5f600 Michael Hanselmann
  }
2361 dff5f600 Michael Hanselmann
2362 dff5f600 Michael Hanselmann
2363 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2364 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2365 dff5f600 Michael Hanselmann
  "master_node": ("Master", QFT_TEXT, QFF_HOSTNAME, "Master node name"),
2366 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2367 dff5f600 Michael Hanselmann
  }
2368 dff5f600 Michael Hanselmann
2369 dff5f600 Michael Hanselmann
2370 dff5f600 Michael Hanselmann
class ClusterQueryData:
2371 dff5f600 Michael Hanselmann
  def __init__(self, cluster, drain_flag, watcher_pause):
2372 dff5f600 Michael Hanselmann
    """Initializes this class.
2373 dff5f600 Michael Hanselmann

2374 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2375 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2376 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2377 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2378 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2379 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2380 dff5f600 Michael Hanselmann

2381 dff5f600 Michael Hanselmann
    """
2382 dff5f600 Michael Hanselmann
    self._cluster = cluster
2383 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2384 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2385 dff5f600 Michael Hanselmann
2386 dff5f600 Michael Hanselmann
  def __iter__(self):
2387 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2388 dff5f600 Michael Hanselmann
2389 dff5f600 Michael Hanselmann
2390 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2391 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2392 dff5f600 Michael Hanselmann

2393 dff5f600 Michael Hanselmann
  """
2394 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2395 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2396 dff5f600 Michael Hanselmann
  else:
2397 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2398 dff5f600 Michael Hanselmann
2399 dff5f600 Michael Hanselmann
2400 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2401 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2402 dff5f600 Michael Hanselmann

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