Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 1a2eb2dc

History | View | Annotate | Download (72.5 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 0422250e Michael Hanselmann
(JQ_ARCHIVED, ) = range(400, 401)
105 0422250e Michael Hanselmann
106 111bf531 Michael Hanselmann
# Query field flags
107 111bf531 Michael Hanselmann
QFF_HOSTNAME = 0x01
108 111bf531 Michael Hanselmann
QFF_IP_ADDRESS = 0x02
109 526f866b Michael Hanselmann
QFF_JOB_ID = 0x04
110 526f866b Michael Hanselmann
QFF_SPLIT_TIMESTAMP = 0x08
111 526f866b Michael Hanselmann
# Next values: 0x10, 0x20, 0x40, 0x80, 0x100, 0x200
112 526f866b Michael Hanselmann
QFF_ALL = (QFF_HOSTNAME | QFF_IP_ADDRESS | QFF_JOB_ID | QFF_SPLIT_TIMESTAMP)
113 8e21cfc0 Adeodato Simo
114 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
115 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
116 1ae17369 Michael Hanselmann
DOC_RE = re.compile(r"^[A-Z].*[^.,?!]$")
117 4ca96421 Michael Hanselmann
118 4ca96421 Michael Hanselmann
#: Verification function for each field type
119 4ca96421 Michael Hanselmann
_VERIFY_FN = {
120 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
121 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
122 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
123 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
124 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
125 697f49d5 Michael Hanselmann
  QFT_TIMESTAMP: ht.TNumber,
126 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
127 4ca96421 Michael Hanselmann
  }
128 4ca96421 Michael Hanselmann
129 e2d188cc Iustin Pop
# Unique objects for special field statuses
130 e2d188cc Iustin Pop
_FS_UNKNOWN = object()
131 e2d188cc Iustin Pop
_FS_NODATA = object()
132 e2d188cc Iustin Pop
_FS_UNAVAIL = object()
133 e2d188cc Iustin Pop
_FS_OFFLINE = object()
134 e2d188cc Iustin Pop
135 425e5bf0 Michael Hanselmann
#: List of all special status
136 425e5bf0 Michael Hanselmann
_FS_ALL = frozenset([_FS_UNKNOWN, _FS_NODATA, _FS_UNAVAIL, _FS_OFFLINE])
137 425e5bf0 Michael Hanselmann
138 af58707c Iustin Pop
#: VType to QFT mapping
139 af58707c Iustin Pop
_VTToQFT = {
140 af58707c Iustin Pop
  # TODO: fix validation of empty strings
141 af58707c Iustin Pop
  constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty
142 af58707c Iustin Pop
  constants.VTYPE_MAYBE_STRING: QFT_OTHER,
143 af58707c Iustin Pop
  constants.VTYPE_BOOL: QFT_BOOL,
144 af58707c Iustin Pop
  constants.VTYPE_SIZE: QFT_UNIT,
145 af58707c Iustin Pop
  constants.VTYPE_INT: QFT_NUMBER,
146 af58707c Iustin Pop
  }
147 af58707c Iustin Pop
148 79b2ca83 Michael Hanselmann
_SERIAL_NO_DOC = "%s object serial number, incremented on each modification"
149 79b2ca83 Michael Hanselmann
150 4ca96421 Michael Hanselmann
151 b459a848 Andrea Spadaccini
def _GetUnknownField(ctx, item): # pylint: disable=W0613
152 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
153 4ca96421 Michael Hanselmann

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

161 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
162 4ca96421 Michael Hanselmann

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

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

188 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
189 4ca96421 Michael Hanselmann

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

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

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

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

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

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

221 fb0be379 Michael Hanselmann
    @type namefield: string
222 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
223 fb0be379 Michael Hanselmann

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

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

243 fb0be379 Michael Hanselmann
    @rtype: list
244 fb0be379 Michael Hanselmann

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

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

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

267 fb0be379 Michael Hanselmann
    @type op: string
268 fb0be379 Michael Hanselmann
    @param op: Operator
269 fb0be379 Michael Hanselmann

270 fb0be379 Michael Hanselmann
    """
271 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
272 fb0be379 Michael Hanselmann
      self._NeedAllNames()
273 fb0be379 Michael Hanselmann
274 52aa1efa Michael Hanselmann
  def NoteUnaryOp(self, op, datakind): # pylint: disable=W0613
275 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
276 fb0be379 Michael Hanselmann

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

280 fb0be379 Michael Hanselmann
    """
281 52aa1efa Michael Hanselmann
    if datakind is not None:
282 52aa1efa Michael Hanselmann
      self._datakinds.add(datakind)
283 52aa1efa Michael Hanselmann
284 fb0be379 Michael Hanselmann
    self._NeedAllNames()
285 fb0be379 Michael Hanselmann
286 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
287 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
288 fb0be379 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

640 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
641 fb0be379 Michael Hanselmann

642 fb0be379 Michael Hanselmann
  @rtype: callable
643 fb0be379 Michael Hanselmann

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

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

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

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

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

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

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

706 4ca96421 Michael Hanselmann
    @rtype: frozenset
707 4ca96421 Michael Hanselmann

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

716 4ca96421 Michael Hanselmann
    Includes unknown fields.
717 4ca96421 Michael Hanselmann

718 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
719 4ca96421 Michael Hanselmann

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

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

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

771 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
772 4ca96421 Michael Hanselmann

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

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

804 4ca96421 Michael Hanselmann
  @type fields: list
805 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
806 4ca96421 Michael Hanselmann
  @type row: list of tuples
807 4ca96421 Michael Hanselmann
  @param row: Row data
808 4ca96421 Michael Hanselmann

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

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

842 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
843 4ca96421 Michael Hanselmann

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

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

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

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

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

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

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

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

928 dff5f600 Michael Hanselmann
  """
929 dff5f600 Michael Hanselmann
  return value
930 dff5f600 Michael Hanselmann
931 dff5f600 Michael Hanselmann
932 dff5f600 Michael Hanselmann
def _StaticValue(value):
933 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
934 dff5f600 Michael Hanselmann

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

942 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
943 8235fe04 Michael Hanselmann
  @param node: Node object
944 8235fe04 Michael Hanselmann
  @type master_name: string
945 8235fe04 Michael Hanselmann
  @param master_name: Master node name
946 8235fe04 Michael Hanselmann

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

963 8235fe04 Michael Hanselmann
  @param attr: Attribute name
964 8235fe04 Michael Hanselmann

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

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

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

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

1003 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1004 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1005 425e5bf0 Michael Hanselmann

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

1021 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1022 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1023 425e5bf0 Michael Hanselmann

1024 425e5bf0 Michael Hanselmann
  """
1025 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
1026 425e5bf0 Michael Hanselmann
1027 425e5bf0 Michael Hanselmann
1028 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
1029 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
1030 145bea54 Michael Hanselmann

1031 145bea54 Michael Hanselmann
  @type getter: callable
1032 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1033 145bea54 Michael Hanselmann

1034 145bea54 Michael Hanselmann
  """
1035 145bea54 Michael Hanselmann
  def fn(_, item):
1036 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1037 145bea54 Michael Hanselmann

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

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

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

1066 8235fe04 Michael Hanselmann
  """
1067 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1068 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1069 8235fe04 Michael Hanselmann
    """Initializes this class.
1070 8235fe04 Michael Hanselmann

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

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

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

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

1150 8572f1fe René Nussbaumer
  """
1151 8572f1fe René Nussbaumer
  def fn(ctx, node):
1152 8572f1fe René Nussbaumer
    """Get group data for a node.
1153 8572f1fe René Nussbaumer

1154 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1155 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1156 8572f1fe René Nussbaumer
    @param inst: Node object
1157 8572f1fe René Nussbaumer

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

1172 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1173 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1174 8235fe04 Michael Hanselmann
  @param node: Node object
1175 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1176 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1177 8235fe04 Michael Hanselmann

1178 8235fe04 Michael Hanselmann
  """
1179 e2d188cc Iustin Pop
  return ng.name
1180 8235fe04 Michael Hanselmann
1181 8235fe04 Michael Hanselmann
1182 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1183 52b5d286 René Nussbaumer
  """Returns the node powered state
1184 52b5d286 René Nussbaumer

1185 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1186 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1187 52b5d286 René Nussbaumer
  @param node: Node object
1188 52b5d286 René Nussbaumer

1189 52b5d286 René Nussbaumer
  """
1190 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1191 e2d188cc Iustin Pop
    return node.powered
1192 52b5d286 René Nussbaumer
1193 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1194 52b5d286 René Nussbaumer
1195 52b5d286 René Nussbaumer
1196 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1197 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1198 8572f1fe René Nussbaumer

1199 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1200 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1201 8572f1fe René Nussbaumer
  @param node: Node object
1202 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1203 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1204 8572f1fe René Nussbaumer

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

1212 8235fe04 Michael Hanselmann
  @param field: Live field name
1213 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1214 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1215 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1216 a6070ef7 Michael Hanselmann
  @param node: Node object
1217 8235fe04 Michael Hanselmann

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

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

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

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

1361 1c8addc6 Michael Hanselmann
  """
1362 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1363 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1364 1c8addc6 Michael Hanselmann
    """Initializes this class.
1365 1c8addc6 Michael Hanselmann

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

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

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

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

1426 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1427 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1428 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1429 1c8addc6 Michael Hanselmann

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

1442 1c8addc6 Michael Hanselmann
  @type name: string
1443 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1444 1c8addc6 Michael Hanselmann

1445 1c8addc6 Michael Hanselmann
  """
1446 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1447 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1448 1c8addc6 Michael Hanselmann

1449 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1450 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1451 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1452 1c8addc6 Michael Hanselmann

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

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

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

1503 1c8addc6 Michael Hanselmann
  @type index: int
1504 1c8addc6 Michael Hanselmann
  @param index: Disk index
1505 1c8addc6 Michael Hanselmann

1506 1c8addc6 Michael Hanselmann
  """
1507 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1508 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1509 1c8addc6 Michael Hanselmann

1510 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1511 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1512 1c8addc6 Michael Hanselmann

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

1525 1c8addc6 Michael Hanselmann
  @type index: int
1526 1c8addc6 Michael Hanselmann
  @param index: NIC index
1527 1c8addc6 Michael Hanselmann
  @type cb: callable
1528 1c8addc6 Michael Hanselmann
  @param cb: Callback
1529 1c8addc6 Michael Hanselmann

1530 1c8addc6 Michael Hanselmann
  """
1531 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1532 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1533 1c8addc6 Michael Hanselmann

1534 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1535 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1536 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1537 1c8addc6 Michael Hanselmann

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

1552 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1553 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1554 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1555 1c8addc6 Michael Hanselmann

1556 1c8addc6 Michael Hanselmann
  """
1557 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1558 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1559 1c8addc6 Michael Hanselmann
  else:
1560 e2d188cc Iustin Pop
    return nic.ip
1561 1c8addc6 Michael Hanselmann
1562 1c8addc6 Michael Hanselmann
1563 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1564 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1565 1c8addc6 Michael Hanselmann

1566 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1567 1c8addc6 Michael Hanselmann
  @type index: int
1568 1c8addc6 Michael Hanselmann
  @param index: NIC index
1569 1c8addc6 Michael Hanselmann

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

1584 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1585 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1586 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1587 1c8addc6 Michael Hanselmann

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

1607 1c8addc6 Michael Hanselmann
  @type name: string
1608 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1609 1c8addc6 Michael Hanselmann

1610 1c8addc6 Michael Hanselmann
  """
1611 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1612 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1613 1c8addc6 Michael Hanselmann

1614 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1615 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1616 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1617 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1618 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1619 1c8addc6 Michael Hanselmann

1620 1c8addc6 Michael Hanselmann
    """
1621 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1622 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1623 1c8addc6 Michael Hanselmann
1624 1c8addc6 Michael Hanselmann
  return fn
1625 1c8addc6 Michael Hanselmann
1626 1c8addc6 Michael Hanselmann
1627 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1628 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1629 1c8addc6 Michael Hanselmann

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

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

1698 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1699 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1700 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1701 1c8addc6 Michael Hanselmann

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

1714 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1715 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1716 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1717 5d28cb6f Michael Hanselmann

1718 5d28cb6f Michael Hanselmann
  """
1719 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1720 5d28cb6f Michael Hanselmann
1721 5d28cb6f Michael Hanselmann
  if consinfo is None:
1722 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1723 5d28cb6f Michael Hanselmann
1724 5d28cb6f Michael Hanselmann
  return consinfo
1725 5d28cb6f Michael Hanselmann
1726 5d28cb6f Michael Hanselmann
1727 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1728 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1729 1c8addc6 Michael Hanselmann

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

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

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

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

1833 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1834 fab9573b Michael Hanselmann
  @param default: Default value
1835 fab9573b Michael Hanselmann
  @type node_name: string
1836 fab9573b Michael Hanselmann
  @param node_name: Node name
1837 fab9573b Michael Hanselmann

1838 fab9573b Michael Hanselmann
  """
1839 fab9573b Michael Hanselmann
  try:
1840 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1841 fab9573b Michael Hanselmann
  except KeyError:
1842 fab9573b Michael Hanselmann
    return default
1843 fab9573b Michael Hanselmann
  else:
1844 fab9573b Michael Hanselmann
    return node.group
1845 fab9573b Michael Hanselmann
1846 fab9573b Michael Hanselmann
1847 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1848 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1849 fab9573b Michael Hanselmann

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

1855 fab9573b Michael Hanselmann
  """
1856 fab9573b Michael Hanselmann
  try:
1857 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1858 fab9573b Michael Hanselmann
  except KeyError:
1859 fab9573b Michael Hanselmann
    return default
1860 fab9573b Michael Hanselmann
1861 fab9573b Michael Hanselmann
  try:
1862 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1863 fab9573b Michael Hanselmann
  except KeyError:
1864 fab9573b Michael Hanselmann
    return default
1865 fab9573b Michael Hanselmann
1866 fab9573b Michael Hanselmann
  return group.name
1867 fab9573b Michael Hanselmann
1868 fab9573b Michael Hanselmann
1869 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1870 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1871 1c8addc6 Michael Hanselmann

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

1969 24d16f76 Michael Hanselmann
  """
1970 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1971 24d16f76 Michael Hanselmann
    """Initializes this class.
1972 24d16f76 Michael Hanselmann

1973 24d16f76 Michael Hanselmann
    """
1974 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1975 24d16f76 Michael Hanselmann
1976 24d16f76 Michael Hanselmann
  def __iter__(self):
1977 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1978 24d16f76 Michael Hanselmann

1979 24d16f76 Michael Hanselmann
    """
1980 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1981 24d16f76 Michael Hanselmann
1982 24d16f76 Michael Hanselmann
1983 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1984 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1985 24d16f76 Michael Hanselmann

1986 24d16f76 Michael Hanselmann
  """
1987 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1988 24d16f76 Michael Hanselmann
1989 24d16f76 Michael Hanselmann
  if owners:
1990 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1991 24d16f76 Michael Hanselmann
1992 e2d188cc Iustin Pop
  return owners
1993 24d16f76 Michael Hanselmann
1994 24d16f76 Michael Hanselmann
1995 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1996 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1997 24d16f76 Michael Hanselmann

1998 24d16f76 Michael Hanselmann
  """
1999 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
2000 24d16f76 Michael Hanselmann
2001 24d16f76 Michael Hanselmann
  if pending:
2002 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
2003 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
2004 24d16f76 Michael Hanselmann
2005 e2d188cc Iustin Pop
  return pending
2006 24d16f76 Michael Hanselmann
2007 24d16f76 Michael Hanselmann
2008 24d16f76 Michael Hanselmann
def _BuildLockFields():
2009 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
2010 24d16f76 Michael Hanselmann

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

2031 8e21cfc0 Adeodato Simo
  """
2032 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2033 2c758845 René Nussbaumer
               want_diskparams):
2034 8e21cfc0 Adeodato Simo
    """Initializes this class.
2035 8e21cfc0 Adeodato Simo

2036 edd49f9b Agata Murawska
    @param cluster: Cluster object
2037 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2038 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2039 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2040 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2041 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2042 2c758845 René Nussbaumer
    @type want_diskparams: bool
2043 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2044 8e21cfc0 Adeodato Simo

2045 8e21cfc0 Adeodato Simo
    """
2046 8e21cfc0 Adeodato Simo
    self.groups = groups
2047 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2048 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2049 edd49f9b Agata Murawska
    self.cluster = cluster
2050 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2051 edd49f9b Agata Murawska
2052 edd49f9b Agata Murawska
    # Used for individual rows
2053 edd49f9b Agata Murawska
    self.group_ipolicy = None
2054 8930b0f0 Iustin Pop
    self.ndparams = None
2055 2c758845 René Nussbaumer
    self.group_dp = None
2056 8e21cfc0 Adeodato Simo
2057 8e21cfc0 Adeodato Simo
  def __iter__(self):
2058 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2059 8e21cfc0 Adeodato Simo

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

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

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

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

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

2203 9665bb3a Michael Hanselmann
  """
2204 9665bb3a Michael Hanselmann
  if job is None:
2205 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2206 9665bb3a Michael Hanselmann
  else:
2207 9665bb3a Michael Hanselmann
    return fn(job)
2208 9665bb3a Michael Hanselmann
2209 9665bb3a Michael Hanselmann
2210 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2211 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2212 9665bb3a Michael Hanselmann

2213 9665bb3a Michael Hanselmann
  """
2214 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2215 9665bb3a Michael Hanselmann
2216 9665bb3a Michael Hanselmann
2217 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2218 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2219 9665bb3a Michael Hanselmann

2220 9665bb3a Michael Hanselmann
  """
2221 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2222 9665bb3a Michael Hanselmann
2223 9665bb3a Michael Hanselmann
2224 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2225 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2226 9665bb3a Michael Hanselmann

2227 9665bb3a Michael Hanselmann
  """
2228 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2229 9665bb3a Michael Hanselmann
2230 9665bb3a Michael Hanselmann
2231 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2232 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2233 9665bb3a Michael Hanselmann

2234 9665bb3a Michael Hanselmann
  """
2235 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2236 9665bb3a Michael Hanselmann
2237 9665bb3a Michael Hanselmann
  if timestamp is None:
2238 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2239 9665bb3a Michael Hanselmann
  else:
2240 9665bb3a Michael Hanselmann
    return timestamp
2241 9665bb3a Michael Hanselmann
2242 9665bb3a Michael Hanselmann
2243 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2244 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2245 9665bb3a Michael Hanselmann

2246 9665bb3a Michael Hanselmann
  """
2247 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2248 9665bb3a Michael Hanselmann
2249 9665bb3a Michael Hanselmann
2250 9665bb3a Michael Hanselmann
def _BuildJobFields():
2251 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2252 9665bb3a Michael Hanselmann

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

2314 0fdf247d Michael Hanselmann
  """
2315 0fdf247d Michael Hanselmann
  if expname is None:
2316 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2317 0fdf247d Michael Hanselmann
  else:
2318 0fdf247d Michael Hanselmann
    return expname
2319 0fdf247d Michael Hanselmann
2320 0fdf247d Michael Hanselmann
2321 0fdf247d Michael Hanselmann
def _BuildExportFields():
2322 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2323 0fdf247d Michael Hanselmann

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

2361 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2362 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2363 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2364 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2365 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2366 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2367 dff5f600 Michael Hanselmann

2368 dff5f600 Michael Hanselmann
    """
2369 dff5f600 Michael Hanselmann
    self._cluster = cluster
2370 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2371 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2372 dff5f600 Michael Hanselmann
2373 dff5f600 Michael Hanselmann
  def __iter__(self):
2374 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2375 dff5f600 Michael Hanselmann
2376 dff5f600 Michael Hanselmann
2377 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2378 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2379 dff5f600 Michael Hanselmann

2380 dff5f600 Michael Hanselmann
  """
2381 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2382 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2383 dff5f600 Michael Hanselmann
  else:
2384 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2385 dff5f600 Michael Hanselmann
2386 dff5f600 Michael Hanselmann
2387 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2388 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2389 dff5f600 Michael Hanselmann

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