Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ ad5cc6bd

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

341 23d0a608 Michael Hanselmann
  """
342 23d0a608 Michael Hanselmann
  try:
343 23d0a608 Michael Hanselmann
    return re.compile(pattern)
344 23d0a608 Michael Hanselmann
  except re.error, err:
345 23d0a608 Michael Hanselmann
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
346 23d0a608 Michael Hanselmann
347 23d0a608 Michael Hanselmann
348 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
349 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
350 fb0be379 Michael Hanselmann

351 fb0be379 Michael Hanselmann
  """
352 b459a848 Andrea Spadaccini
  # String statement has no effect, pylint: disable=W0105
353 fb0be379 Michael Hanselmann
354 fb0be379 Michael Hanselmann
  #: How deep filters can be nested
355 fb0be379 Michael Hanselmann
  _LEVELS_MAX = 10
356 fb0be379 Michael Hanselmann
357 fb0be379 Michael Hanselmann
  # Unique identifiers for operator groups
358 fb0be379 Michael Hanselmann
  (_OPTYPE_LOGIC,
359 fb0be379 Michael Hanselmann
   _OPTYPE_UNARY,
360 fb0be379 Michael Hanselmann
   _OPTYPE_BINARY) = range(1, 4)
361 fb0be379 Michael Hanselmann
362 fb0be379 Michael Hanselmann
  """Functions for equality checks depending on field flags.
363 fb0be379 Michael Hanselmann

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

368 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
369 fb0be379 Michael Hanselmann
  using binary AND.
370 fb0be379 Michael Hanselmann

371 fb0be379 Michael Hanselmann
  """
372 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
373 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
374 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
375 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
376 23d0a608 Michael Hanselmann
     None),
377 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
378 fb0be379 Michael Hanselmann
    ]
379 fb0be379 Michael Hanselmann
380 fb0be379 Michael Hanselmann
  """Known operators
381 fb0be379 Michael Hanselmann

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

385 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
386 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
387 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
388 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
389 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
390 fb0be379 Michael Hanselmann

391 fb0be379 Michael Hanselmann
  """
392 fb0be379 Michael Hanselmann
  _OPS = {
393 fb0be379 Michael Hanselmann
    # Logic operators
394 fb0be379 Michael Hanselmann
    qlang.OP_OR: (_OPTYPE_LOGIC, compat.any),
395 fb0be379 Michael Hanselmann
    qlang.OP_AND: (_OPTYPE_LOGIC, compat.all),
396 fb0be379 Michael Hanselmann
397 fb0be379 Michael Hanselmann
    # Unary operators
398 3b877f08 Michael Hanselmann
    qlang.OP_NOT: (_OPTYPE_UNARY, None),
399 3b877f08 Michael Hanselmann
    qlang.OP_TRUE: (_OPTYPE_UNARY, None),
400 fb0be379 Michael Hanselmann
401 fb0be379 Michael Hanselmann
    # Binary operators
402 fb0be379 Michael Hanselmann
    qlang.OP_EQUAL: (_OPTYPE_BINARY, _EQUALITY_CHECKS),
403 fb0be379 Michael Hanselmann
    qlang.OP_NOT_EQUAL:
404 23d0a608 Michael Hanselmann
      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn), valprepfn)
405 23d0a608 Michael Hanselmann
                        for (flags, fn, valprepfn) in _EQUALITY_CHECKS]),
406 23d0a608 Michael Hanselmann
    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
407 23d0a608 Michael Hanselmann
      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
408 23d0a608 Michael Hanselmann
      ]),
409 fb0be379 Michael Hanselmann
    qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
410 23d0a608 Michael Hanselmann
      (None, operator.contains, None),
411 fb0be379 Michael Hanselmann
      ]),
412 fb0be379 Michael Hanselmann
    }
413 fb0be379 Michael Hanselmann
414 fb0be379 Michael Hanselmann
  def __init__(self, fields):
415 fb0be379 Michael Hanselmann
    """Initializes this class.
416 fb0be379 Michael Hanselmann

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

419 fb0be379 Michael Hanselmann
    """
420 fb0be379 Michael Hanselmann
    self._fields = fields
421 fb0be379 Michael Hanselmann
    self._hints = None
422 fb0be379 Michael Hanselmann
    self._op_handler = None
423 fb0be379 Michael Hanselmann
424 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
425 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
426 fb0be379 Michael Hanselmann

427 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
428 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
429 2e5c33db Iustin Pop
    @type qfilter: list
430 2e5c33db Iustin Pop
    @param qfilter: Filter structure
431 fb0be379 Michael Hanselmann
    @rtype: callable
432 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
433 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
434 fb0be379 Michael Hanselmann

435 fb0be379 Michael Hanselmann
    """
436 fb0be379 Michael Hanselmann
    self._op_handler = {
437 fb0be379 Michael Hanselmann
      self._OPTYPE_LOGIC:
438 fb0be379 Michael Hanselmann
        (self._HandleLogicOp, getattr(hints, "NoteLogicOp", None)),
439 fb0be379 Michael Hanselmann
      self._OPTYPE_UNARY:
440 fb0be379 Michael Hanselmann
        (self._HandleUnaryOp, getattr(hints, "NoteUnaryOp", None)),
441 fb0be379 Michael Hanselmann
      self._OPTYPE_BINARY:
442 fb0be379 Michael Hanselmann
        (self._HandleBinaryOp, getattr(hints, "NoteBinaryOp", None)),
443 fb0be379 Michael Hanselmann
      }
444 fb0be379 Michael Hanselmann
445 fb0be379 Michael Hanselmann
    try:
446 2e5c33db Iustin Pop
      filter_fn = self._Compile(qfilter, 0)
447 fb0be379 Michael Hanselmann
    finally:
448 fb0be379 Michael Hanselmann
      self._op_handler = None
449 fb0be379 Michael Hanselmann
450 fb0be379 Michael Hanselmann
    return filter_fn
451 fb0be379 Michael Hanselmann
452 2e5c33db Iustin Pop
  def _Compile(self, qfilter, level):
453 fb0be379 Michael Hanselmann
    """Inner function for converting filters.
454 fb0be379 Michael Hanselmann

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

458 fb0be379 Michael Hanselmann
    """
459 2e5c33db Iustin Pop
    if not (isinstance(qfilter, (list, tuple)) and qfilter):
460 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid filter on level %s" % level)
461 fb0be379 Michael Hanselmann
462 fb0be379 Michael Hanselmann
    # Limit recursion
463 fb0be379 Michael Hanselmann
    if level >= self._LEVELS_MAX:
464 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Only up to %s levels are allowed (filter"
465 fb0be379 Michael Hanselmann
                                  " nested too deep)" % self._LEVELS_MAX)
466 fb0be379 Michael Hanselmann
467 fb0be379 Michael Hanselmann
    # Create copy to be modified
468 2e5c33db Iustin Pop
    operands = qfilter[:]
469 fb0be379 Michael Hanselmann
    op = operands.pop(0)
470 fb0be379 Michael Hanselmann
471 fb0be379 Michael Hanselmann
    try:
472 fb0be379 Michael Hanselmann
      (kind, op_data) = self._OPS[op]
473 fb0be379 Michael Hanselmann
    except KeyError:
474 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unknown operator '%s'" % op)
475 fb0be379 Michael Hanselmann
476 fb0be379 Michael Hanselmann
    (handler, hints_cb) = self._op_handler[kind]
477 fb0be379 Michael Hanselmann
478 fb0be379 Michael Hanselmann
    return handler(hints_cb, level, op, op_data, operands)
479 fb0be379 Michael Hanselmann
480 3b877f08 Michael Hanselmann
  def _LookupField(self, name):
481 3b877f08 Michael Hanselmann
    """Returns a field definition by name.
482 3b877f08 Michael Hanselmann

483 3b877f08 Michael Hanselmann
    """
484 3b877f08 Michael Hanselmann
    try:
485 3b877f08 Michael Hanselmann
      return self._fields[name]
486 3b877f08 Michael Hanselmann
    except KeyError:
487 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
488 3b877f08 Michael Hanselmann
489 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
490 fb0be379 Michael Hanselmann
    """Handles logic operators.
491 fb0be379 Michael Hanselmann

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

503 fb0be379 Michael Hanselmann
    """
504 fb0be379 Michael Hanselmann
    if hints_fn:
505 fb0be379 Michael Hanselmann
      hints_fn(op)
506 fb0be379 Michael Hanselmann
507 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
508 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
509 fb0be379 Michael Hanselmann
510 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
511 fb0be379 Michael Hanselmann
    """Handles unary operators.
512 fb0be379 Michael Hanselmann

513 fb0be379 Michael Hanselmann
    @type hints_fn: callable
514 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
515 fb0be379 Michael Hanselmann
    @type level: integer
516 fb0be379 Michael Hanselmann
    @param level: Current depth
517 fb0be379 Michael Hanselmann
    @type op: string
518 fb0be379 Michael Hanselmann
    @param op: Operator
519 fb0be379 Michael Hanselmann
    @type op_fn: callable
520 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
521 fb0be379 Michael Hanselmann
    @type operands: list
522 fb0be379 Michael Hanselmann
    @param operands: List of operands
523 fb0be379 Michael Hanselmann

524 fb0be379 Michael Hanselmann
    """
525 3b877f08 Michael Hanselmann
    assert op_fn is None
526 3b877f08 Michael Hanselmann
527 fb0be379 Michael Hanselmann
    if hints_fn:
528 fb0be379 Michael Hanselmann
      hints_fn(op)
529 fb0be379 Michael Hanselmann
530 fb0be379 Michael Hanselmann
    if len(operands) != 1:
531 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unary operator '%s' expects exactly one"
532 fb0be379 Michael Hanselmann
                                  " operand" % op)
533 fb0be379 Michael Hanselmann
534 3b877f08 Michael Hanselmann
    if op == qlang.OP_TRUE:
535 3b877f08 Michael Hanselmann
      (_, _, _, retrieval_fn) = self._LookupField(operands[0])
536 3b877f08 Michael Hanselmann
537 3b877f08 Michael Hanselmann
      op_fn = operator.truth
538 3b877f08 Michael Hanselmann
      arg = retrieval_fn
539 3b877f08 Michael Hanselmann
    elif op == qlang.OP_NOT:
540 3b877f08 Michael Hanselmann
      op_fn = operator.not_
541 3b877f08 Michael Hanselmann
      arg = self._Compile(operands[0], level + 1)
542 3b877f08 Michael Hanselmann
    else:
543 3b877f08 Michael Hanselmann
      raise errors.ProgrammerError("Can't handle operator '%s'" % op)
544 3b877f08 Michael Hanselmann
545 3b877f08 Michael Hanselmann
    return compat.partial(_WrapUnaryOp, op_fn, arg)
546 fb0be379 Michael Hanselmann
547 fb0be379 Michael Hanselmann
  def _HandleBinaryOp(self, hints_fn, level, op, op_data, operands):
548 fb0be379 Michael Hanselmann
    """Handles binary operators.
549 fb0be379 Michael Hanselmann

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

560 fb0be379 Michael Hanselmann
    """
561 b459a848 Andrea Spadaccini
    # Unused arguments, pylint: disable=W0613
562 fb0be379 Michael Hanselmann
    try:
563 fb0be379 Michael Hanselmann
      (name, value) = operands
564 fb0be379 Michael Hanselmann
    except (ValueError, TypeError):
565 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid binary operator, expected exactly"
566 fb0be379 Michael Hanselmann
                                  " two operands")
567 fb0be379 Michael Hanselmann
568 3b877f08 Michael Hanselmann
    (fdef, datakind, field_flags, retrieval_fn) = self._LookupField(name)
569 fb0be379 Michael Hanselmann
570 fb0be379 Michael Hanselmann
    assert fdef.kind != QFT_UNKNOWN
571 fb0be379 Michael Hanselmann
572 fb0be379 Michael Hanselmann
    # TODO: Type conversions?
573 fb0be379 Michael Hanselmann
574 fb0be379 Michael Hanselmann
    verify_fn = _VERIFY_FN[fdef.kind]
575 fb0be379 Michael Hanselmann
    if not verify_fn(value):
576 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unable to compare field '%s' (type '%s')"
577 fb0be379 Michael Hanselmann
                                  " with '%s', expected %s" %
578 fb0be379 Michael Hanselmann
                                  (name, fdef.kind, value.__class__.__name__,
579 fb0be379 Michael Hanselmann
                                   verify_fn))
580 fb0be379 Michael Hanselmann
581 fb0be379 Michael Hanselmann
    if hints_fn:
582 fb0be379 Michael Hanselmann
      hints_fn(op, datakind, name, value)
583 fb0be379 Michael Hanselmann
584 23d0a608 Michael Hanselmann
    for (fn_flags, fn, valprepfn) in op_data:
585 fb0be379 Michael Hanselmann
      if fn_flags is None or fn_flags & field_flags:
586 23d0a608 Michael Hanselmann
        # Prepare value if necessary (e.g. compile regular expression)
587 23d0a608 Michael Hanselmann
        if valprepfn:
588 23d0a608 Michael Hanselmann
          value = valprepfn(value)
589 23d0a608 Michael Hanselmann
590 fb0be379 Michael Hanselmann
        return compat.partial(_WrapBinaryOp, fn, retrieval_fn, value)
591 fb0be379 Michael Hanselmann
592 fb0be379 Michael Hanselmann
    raise errors.ProgrammerError("Unable to find operator implementation"
593 fb0be379 Michael Hanselmann
                                 " (op '%s', flags %s)" % (op, field_flags))
594 fb0be379 Michael Hanselmann
595 fb0be379 Michael Hanselmann
596 2e5c33db Iustin Pop
def _CompileFilter(fields, hints, qfilter):
597 fb0be379 Michael Hanselmann
  """Converts a query filter into a callable function.
598 fb0be379 Michael Hanselmann

599 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
600 fb0be379 Michael Hanselmann

601 fb0be379 Michael Hanselmann
  @rtype: callable
602 fb0be379 Michael Hanselmann

603 fb0be379 Michael Hanselmann
  """
604 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
605 fb0be379 Michael Hanselmann
606 fb0be379 Michael Hanselmann
607 4ca96421 Michael Hanselmann
class Query:
608 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
609 4ca96421 Michael Hanselmann
    """Initializes this class.
610 4ca96421 Michael Hanselmann

611 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
612 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
613 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
614 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
615 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
616 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
617 4ca96421 Michael Hanselmann

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

621 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
622 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
623 4ca96421 Michael Hanselmann
    @type selected: list of strings
624 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
625 4ca96421 Michael Hanselmann

626 4ca96421 Michael Hanselmann
    """
627 fb0be379 Michael Hanselmann
    assert namefield is None or namefield in fieldlist
628 fb0be379 Michael Hanselmann
629 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
630 4ca96421 Michael Hanselmann
631 fb0be379 Michael Hanselmann
    self._filter_fn = None
632 fb0be379 Michael Hanselmann
    self._requested_names = None
633 fb0be379 Michael Hanselmann
    self._filter_datakinds = frozenset()
634 fb0be379 Michael Hanselmann
635 2e5c33db Iustin Pop
    if qfilter is not None:
636 fb0be379 Michael Hanselmann
      # Collect requested names if wanted
637 fb0be379 Michael Hanselmann
      if namefield:
638 fb0be379 Michael Hanselmann
        hints = _FilterHints(namefield)
639 fb0be379 Michael Hanselmann
      else:
640 fb0be379 Michael Hanselmann
        hints = None
641 fb0be379 Michael Hanselmann
642 fb0be379 Michael Hanselmann
      # Build filter function
643 2e5c33db Iustin Pop
      self._filter_fn = _CompileFilter(fieldlist, hints, qfilter)
644 fb0be379 Michael Hanselmann
      if hints:
645 fb0be379 Michael Hanselmann
        self._requested_names = hints.RequestedNames()
646 fb0be379 Michael Hanselmann
        self._filter_datakinds = hints.ReferencedData()
647 fb0be379 Michael Hanselmann
648 fb0be379 Michael Hanselmann
    if namefield is None:
649 fb0be379 Michael Hanselmann
      self._name_fn = None
650 fb0be379 Michael Hanselmann
    else:
651 fb0be379 Michael Hanselmann
      (_, _, _, self._name_fn) = fieldlist[namefield]
652 fb0be379 Michael Hanselmann
653 fb0be379 Michael Hanselmann
  def RequestedNames(self):
654 fb0be379 Michael Hanselmann
    """Returns all names referenced in the filter.
655 fb0be379 Michael Hanselmann

656 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
657 fb0be379 Michael Hanselmann
    names, C{None} is returned.
658 fb0be379 Michael Hanselmann

659 fb0be379 Michael Hanselmann
    """
660 fb0be379 Michael Hanselmann
    return self._requested_names
661 fb0be379 Michael Hanselmann
662 4ca96421 Michael Hanselmann
  def RequestedData(self):
663 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
664 4ca96421 Michael Hanselmann

665 4ca96421 Michael Hanselmann
    @rtype: frozenset
666 4ca96421 Michael Hanselmann

667 4ca96421 Michael Hanselmann
    """
668 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
669 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
670 fb0be379 Michael Hanselmann
                      if datakind is not None))
671 4ca96421 Michael Hanselmann
672 4ca96421 Michael Hanselmann
  def GetFields(self):
673 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
674 4ca96421 Michael Hanselmann

675 4ca96421 Michael Hanselmann
    Includes unknown fields.
676 4ca96421 Michael Hanselmann

677 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
678 4ca96421 Michael Hanselmann

679 4ca96421 Michael Hanselmann
    """
680 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
681 4ca96421 Michael Hanselmann
682 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
683 4ca96421 Michael Hanselmann
    """Execute a query.
684 4ca96421 Michael Hanselmann

685 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
686 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
687 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
688 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
689 fbc263a9 Michael Hanselmann
      ordering
690 4ca96421 Michael Hanselmann

691 4ca96421 Michael Hanselmann
    """
692 fbc263a9 Michael Hanselmann
    sort = (self._name_fn and sort_by_name)
693 fbc263a9 Michael Hanselmann
694 fb0be379 Michael Hanselmann
    result = []
695 fb0be379 Michael Hanselmann
696 fb0be379 Michael Hanselmann
    for idx, item in enumerate(ctx):
697 fb0be379 Michael Hanselmann
      if not (self._filter_fn is None or self._filter_fn(ctx, item)):
698 fb0be379 Michael Hanselmann
        continue
699 4ca96421 Michael Hanselmann
700 fb0be379 Michael Hanselmann
      row = [_ProcessResult(fn(ctx, item)) for (_, _, _, fn) in self._fields]
701 fb0be379 Michael Hanselmann
702 fb0be379 Michael Hanselmann
      # Verify result
703 fb0be379 Michael Hanselmann
      if __debug__:
704 d1c3c3b3 Iustin Pop
        _VerifyResultRow(self._fields, row)
705 4ca96421 Michael Hanselmann
706 fbc263a9 Michael Hanselmann
      if sort:
707 fb0be379 Michael Hanselmann
        (status, name) = _ProcessResult(self._name_fn(ctx, item))
708 fb0be379 Michael Hanselmann
        assert status == constants.RS_NORMAL
709 fb0be379 Michael Hanselmann
        # TODO: Are there cases where we wouldn't want to use NiceSort?
710 fbc263a9 Michael Hanselmann
        result.append((utils.NiceSortKey(name), idx, row))
711 fb0be379 Michael Hanselmann
      else:
712 fbc263a9 Michael Hanselmann
        result.append(row)
713 fb0be379 Michael Hanselmann
714 fbc263a9 Michael Hanselmann
    if not sort:
715 fbc263a9 Michael Hanselmann
      return result
716 fb0be379 Michael Hanselmann
717 fb0be379 Michael Hanselmann
    # TODO: Would "heapq" be more efficient than sorting?
718 fb0be379 Michael Hanselmann
719 fb0be379 Michael Hanselmann
    # Sorting in-place instead of using "sorted()"
720 fb0be379 Michael Hanselmann
    result.sort()
721 fb0be379 Michael Hanselmann
722 fb0be379 Michael Hanselmann
    assert not result or (len(result[0]) == 3 and len(result[-1]) == 3)
723 fb0be379 Michael Hanselmann
724 fb0be379 Michael Hanselmann
    return map(operator.itemgetter(2), result)
725 4ca96421 Michael Hanselmann
726 fbc263a9 Michael Hanselmann
  def OldStyleQuery(self, ctx, sort_by_name=True):
727 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
728 4ca96421 Michael Hanselmann

729 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
730 4ca96421 Michael Hanselmann

731 4ca96421 Michael Hanselmann
    """
732 111bf531 Michael Hanselmann
    unknown = set(fdef.name for (fdef, _, _, _) in self._fields
733 111bf531 Michael Hanselmann
                  if fdef.kind == QFT_UNKNOWN)
734 4ca96421 Michael Hanselmann
    if unknown:
735 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
736 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
737 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
738 4ca96421 Michael Hanselmann
739 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
740 fbc263a9 Michael Hanselmann
            for row in self.Query(ctx, sort_by_name=sort_by_name)]
741 4ca96421 Michael Hanselmann
742 4ca96421 Michael Hanselmann
743 e2d188cc Iustin Pop
def _ProcessResult(value):
744 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
745 e2d188cc Iustin Pop

746 e2d188cc Iustin Pop
  """
747 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
748 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
749 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
750 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
751 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
752 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
753 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
754 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
755 e2d188cc Iustin Pop
  else:
756 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
757 e2d188cc Iustin Pop
758 e2d188cc Iustin Pop
759 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
760 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
761 4ca96421 Michael Hanselmann

762 4ca96421 Michael Hanselmann
  @type fields: list
763 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
764 4ca96421 Michael Hanselmann
  @type row: list of tuples
765 4ca96421 Michael Hanselmann
  @param row: Row data
766 4ca96421 Michael Hanselmann

767 4ca96421 Michael Hanselmann
  """
768 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
769 d1c3c3b3 Iustin Pop
  errs = []
770 111bf531 Michael Hanselmann
  for ((status, value), (fdef, _, _, _)) in zip(row, fields):
771 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
772 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
773 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
774 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
775 d1c3c3b3 Iustin Pop
    elif value is not None:
776 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
777 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
778 34598551 Agata Murawska
                    (utils.CommaJoin(errs), row))
779 4ca96421 Michael Hanselmann
780 4ca96421 Michael Hanselmann
781 320e34df Michael Hanselmann
def _FieldDictKey((fdef, _, flags, fn)):
782 320e34df Michael Hanselmann
  """Generates key for field dictionary.
783 320e34df Michael Hanselmann

784 320e34df Michael Hanselmann
  """
785 320e34df Michael Hanselmann
  assert fdef.name and fdef.title, "Name and title are required"
786 320e34df Michael Hanselmann
  assert FIELD_NAME_RE.match(fdef.name)
787 320e34df Michael Hanselmann
  assert TITLE_RE.match(fdef.title)
788 320e34df Michael Hanselmann
  assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
789 320e34df Michael Hanselmann
          fdef.doc.strip() == fdef.doc), \
790 320e34df Michael Hanselmann
         "Invalid description for field '%s'" % fdef.name
791 320e34df Michael Hanselmann
  assert callable(fn)
792 320e34df Michael Hanselmann
  assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
793 320e34df Michael Hanselmann
794 320e34df Michael Hanselmann
  return fdef.name
795 320e34df Michael Hanselmann
796 320e34df Michael Hanselmann
797 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
798 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
799 4ca96421 Michael Hanselmann

800 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
801 4ca96421 Michael Hanselmann

802 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
803 d63bd540 Iustin Pop
      kind, retrieval function)
804 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
805 d63bd540 Iustin Pop
      description
806 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
807 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
808 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
809 4ca96421 Michael Hanselmann
  @rtype: dict
810 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
811 4ca96421 Michael Hanselmann

812 4ca96421 Michael Hanselmann
  """
813 89ce4acc Michael Hanselmann
  if __debug__:
814 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
815 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
816 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
817 4ca96421 Michael Hanselmann
818 320e34df Michael Hanselmann
  result = utils.SequenceToDict(fields, key=_FieldDictKey)
819 4ca96421 Michael Hanselmann
820 d63bd540 Iustin Pop
  for alias, target in aliases:
821 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
822 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
823 111bf531 Michael Hanselmann
    (fdef, k, flags, fn) = result[target]
824 d63bd540 Iustin Pop
    fdef = fdef.Copy()
825 d63bd540 Iustin Pop
    fdef.name = alias
826 111bf531 Michael Hanselmann
    result[alias] = (fdef, k, flags, fn)
827 d63bd540 Iustin Pop
828 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
829 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
830 111bf531 Michael Hanselmann
                    for (name, (fdef, _, _, _)) in result.items())
831 4ca96421 Michael Hanselmann
832 4ca96421 Michael Hanselmann
  return result
833 4ca96421 Michael Hanselmann
834 4ca96421 Michael Hanselmann
835 fbc263a9 Michael Hanselmann
def GetQueryResponse(query, ctx, sort_by_name=True):
836 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
837 b60fcb6f Michael Hanselmann

838 b60fcb6f Michael Hanselmann
  @type query: L{Query}
839 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
840 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
841 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
842 fbc263a9 Michael Hanselmann
    ordering
843 b60fcb6f Michael Hanselmann

844 b60fcb6f Michael Hanselmann
  """
845 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
846 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
847 b60fcb6f Michael Hanselmann
848 b60fcb6f Michael Hanselmann
849 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
850 aa29e95f Michael Hanselmann
  """Returns list of available fields.
851 aa29e95f Michael Hanselmann

852 aa29e95f Michael Hanselmann
  @type fielddefs: dict
853 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
854 aa29e95f Michael Hanselmann
  @type selected: list of strings
855 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
856 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
857 aa29e95f Michael Hanselmann

858 aa29e95f Michael Hanselmann
  """
859 aa29e95f Michael Hanselmann
  if selected is None:
860 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
861 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
862 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
863 aa29e95f Michael Hanselmann
  else:
864 aa29e95f Michael Hanselmann
    # Keep order as requested by client
865 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
866 aa29e95f Michael Hanselmann
867 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
868 aa29e95f Michael Hanselmann
869 aa29e95f Michael Hanselmann
870 79b2ca83 Michael Hanselmann
def _MakeField(name, title, kind, doc):
871 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
872 4ca96421 Michael Hanselmann

873 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
874 4ca96421 Michael Hanselmann
  @param title: Human-readable title
875 4ca96421 Michael Hanselmann
  @param kind: Field type
876 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
877 4ca96421 Michael Hanselmann

878 4ca96421 Michael Hanselmann
  """
879 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
880 1ae17369 Michael Hanselmann
                                      doc=doc)
881 8235fe04 Michael Hanselmann
882 8235fe04 Michael Hanselmann
883 dff5f600 Michael Hanselmann
def _StaticValueInner(value, ctx, _): # pylint: disable=W0613
884 dff5f600 Michael Hanselmann
  """Returns a static value.
885 dff5f600 Michael Hanselmann

886 dff5f600 Michael Hanselmann
  """
887 dff5f600 Michael Hanselmann
  return value
888 dff5f600 Michael Hanselmann
889 dff5f600 Michael Hanselmann
890 dff5f600 Michael Hanselmann
def _StaticValue(value):
891 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
892 dff5f600 Michael Hanselmann

893 dff5f600 Michael Hanselmann
  """
894 dff5f600 Michael Hanselmann
  return compat.partial(_StaticValueInner, value)
895 dff5f600 Michael Hanselmann
896 dff5f600 Michael Hanselmann
897 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
898 8235fe04 Michael Hanselmann
  """Determine node role.
899 8235fe04 Michael Hanselmann

900 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
901 8235fe04 Michael Hanselmann
  @param node: Node object
902 8235fe04 Michael Hanselmann
  @type master_name: string
903 8235fe04 Michael Hanselmann
  @param master_name: Master node name
904 8235fe04 Michael Hanselmann

905 8235fe04 Michael Hanselmann
  """
906 8235fe04 Michael Hanselmann
  if node.name == master_name:
907 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
908 8235fe04 Michael Hanselmann
  elif node.master_candidate:
909 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
910 8235fe04 Michael Hanselmann
  elif node.drained:
911 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
912 8235fe04 Michael Hanselmann
  elif node.offline:
913 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
914 8235fe04 Michael Hanselmann
  else:
915 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
916 8235fe04 Michael Hanselmann
917 8235fe04 Michael Hanselmann
918 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
919 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
920 8235fe04 Michael Hanselmann

921 8235fe04 Michael Hanselmann
  @param attr: Attribute name
922 8235fe04 Michael Hanselmann

923 8235fe04 Michael Hanselmann
  """
924 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
925 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
926 8235fe04 Michael Hanselmann
927 8235fe04 Michael Hanselmann
928 8930b0f0 Iustin Pop
def _GetNDParam(name):
929 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
930 8930b0f0 Iustin Pop

931 8930b0f0 Iustin Pop
  """
932 8930b0f0 Iustin Pop
  def _helper(ctx, _):
933 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
934 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
935 8930b0f0 Iustin Pop
    else:
936 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
937 8930b0f0 Iustin Pop
  return _helper
938 8930b0f0 Iustin Pop
939 8930b0f0 Iustin Pop
940 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
941 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
942 8930b0f0 Iustin Pop

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

945 8930b0f0 Iustin Pop
  """
946 8930b0f0 Iustin Pop
  if is_group:
947 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
948 8930b0f0 Iustin Pop
  else:
949 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
950 8930b0f0 Iustin Pop
  return [(_MakeField("ndp/%s" % name, NDP_TITLE.get(name, "ndp/%s" % name),
951 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
952 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
953 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
954 8930b0f0 Iustin Pop
955 8930b0f0 Iustin Pop
956 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
957 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
958 425e5bf0 Michael Hanselmann

959 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
960 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
961 425e5bf0 Michael Hanselmann

962 425e5bf0 Michael Hanselmann
  """
963 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
964 425e5bf0 Michael Hanselmann
965 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
966 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
967 425e5bf0 Michael Hanselmann
    # Return right away
968 425e5bf0 Michael Hanselmann
    return value
969 425e5bf0 Michael Hanselmann
970 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
971 425e5bf0 Michael Hanselmann
  return convert(value)
972 425e5bf0 Michael Hanselmann
973 425e5bf0 Michael Hanselmann
974 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
975 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
976 425e5bf0 Michael Hanselmann

977 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
978 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
979 425e5bf0 Michael Hanselmann

980 425e5bf0 Michael Hanselmann
  """
981 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
982 425e5bf0 Michael Hanselmann
983 425e5bf0 Michael Hanselmann
984 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
985 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
986 145bea54 Michael Hanselmann

987 145bea54 Michael Hanselmann
  @type getter: callable
988 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
989 145bea54 Michael Hanselmann

990 145bea54 Michael Hanselmann
  """
991 145bea54 Michael Hanselmann
  def fn(_, item):
992 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
993 145bea54 Michael Hanselmann

994 145bea54 Michael Hanselmann
    """
995 145bea54 Michael Hanselmann
    timestamp = getter(item)
996 145bea54 Michael Hanselmann
    if timestamp is None:
997 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
998 e2d188cc Iustin Pop
      return _FS_UNAVAIL
999 145bea54 Michael Hanselmann
    else:
1000 e2d188cc Iustin Pop
      return timestamp
1001 145bea54 Michael Hanselmann
1002 145bea54 Michael Hanselmann
  return fn
1003 145bea54 Michael Hanselmann
1004 145bea54 Michael Hanselmann
1005 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
1006 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
1007 145bea54 Michael Hanselmann

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

1010 145bea54 Michael Hanselmann
  """
1011 145bea54 Michael Hanselmann
  return [
1012 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
1013 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
1014 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
1015 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
1016 145bea54 Michael Hanselmann
    ]
1017 145bea54 Michael Hanselmann
1018 145bea54 Michael Hanselmann
1019 8235fe04 Michael Hanselmann
class NodeQueryData:
1020 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1021 8235fe04 Michael Hanselmann

1022 8235fe04 Michael Hanselmann
  """
1023 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1024 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1025 8235fe04 Michael Hanselmann
    """Initializes this class.
1026 8235fe04 Michael Hanselmann

1027 8235fe04 Michael Hanselmann
    """
1028 8235fe04 Michael Hanselmann
    self.nodes = nodes
1029 8235fe04 Michael Hanselmann
    self.live_data = live_data
1030 8235fe04 Michael Hanselmann
    self.master_name = master_name
1031 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1032 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1033 8235fe04 Michael Hanselmann
    self.groups = groups
1034 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1035 8572f1fe René Nussbaumer
    self.cluster = cluster
1036 8235fe04 Michael Hanselmann
1037 8235fe04 Michael Hanselmann
    # Used for individual rows
1038 8235fe04 Michael Hanselmann
    self.curlive_data = None
1039 8930b0f0 Iustin Pop
    self.ndparams = None
1040 8235fe04 Michael Hanselmann
1041 8235fe04 Michael Hanselmann
  def __iter__(self):
1042 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1043 8235fe04 Michael Hanselmann

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

1047 8235fe04 Michael Hanselmann
    """
1048 8235fe04 Michael Hanselmann
    for node in self.nodes:
1049 8930b0f0 Iustin Pop
      group = self.groups.get(node.group, None)
1050 8930b0f0 Iustin Pop
      if group is None:
1051 8930b0f0 Iustin Pop
        self.ndparams = None
1052 8930b0f0 Iustin Pop
      else:
1053 8930b0f0 Iustin Pop
        self.ndparams = self.cluster.FillND(node, group)
1054 8235fe04 Michael Hanselmann
      if self.live_data:
1055 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
1056 8235fe04 Michael Hanselmann
      else:
1057 8235fe04 Michael Hanselmann
        self.curlive_data = None
1058 8235fe04 Michael Hanselmann
      yield node
1059 8235fe04 Michael Hanselmann
1060 8235fe04 Michael Hanselmann
1061 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
1062 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
1063 111bf531 Michael Hanselmann
  "drained": ("Drained", QFT_BOOL, 0, "Whether node is drained"),
1064 111bf531 Michael Hanselmann
  "master_candidate": ("MasterC", QFT_BOOL, 0,
1065 79b2ca83 Michael Hanselmann
                       "Whether node is a master candidate"),
1066 111bf531 Michael Hanselmann
  "master_capable": ("MasterCapable", QFT_BOOL, 0,
1067 79b2ca83 Michael Hanselmann
                     "Whether node can become a master candidate"),
1068 111bf531 Michael Hanselmann
  "name": ("Node", QFT_TEXT, QFF_HOSTNAME, "Node name"),
1069 111bf531 Michael Hanselmann
  "offline": ("Offline", QFT_BOOL, 0, "Whether node is marked offline"),
1070 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Node"),
1071 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Node UUID"),
1072 111bf531 Michael Hanselmann
  "vm_capable": ("VMCapable", QFT_BOOL, 0, "Whether node can host instances"),
1073 8235fe04 Michael Hanselmann
  }
1074 8235fe04 Michael Hanselmann
1075 8235fe04 Michael Hanselmann
1076 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
1077 effab4ca Iustin Pop
# Note that none of these are available for non-vm_capable nodes
1078 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
1079 79b2ca83 Michael Hanselmann
  "bootid": ("BootID", QFT_TEXT, "bootid",
1080 79b2ca83 Michael Hanselmann
             "Random UUID renewed for each system reboot, can be used"
1081 79b2ca83 Michael Hanselmann
             " for detecting reboots by tracking changes"),
1082 79b2ca83 Michael Hanselmann
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes",
1083 79b2ca83 Michael Hanselmann
             "Number of NUMA domains on node (if exported by hypervisor)"),
1084 79b2ca83 Michael Hanselmann
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets",
1085 79b2ca83 Michael Hanselmann
               "Number of physical CPU sockets (if exported by hypervisor)"),
1086 79b2ca83 Michael Hanselmann
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total", "Number of logical processors"),
1087 79b2ca83 Michael Hanselmann
  "dfree": ("DFree", QFT_UNIT, "vg_free",
1088 79b2ca83 Michael Hanselmann
            "Available disk space in volume group"),
1089 79b2ca83 Michael Hanselmann
  "dtotal": ("DTotal", QFT_UNIT, "vg_size",
1090 79b2ca83 Michael Hanselmann
             "Total disk space in volume group used for instance disk"
1091 79b2ca83 Michael Hanselmann
             " allocation"),
1092 79b2ca83 Michael Hanselmann
  "mfree": ("MFree", QFT_UNIT, "memory_free",
1093 79b2ca83 Michael Hanselmann
            "Memory available for instance allocations"),
1094 79b2ca83 Michael Hanselmann
  "mnode": ("MNode", QFT_UNIT, "memory_dom0",
1095 79b2ca83 Michael Hanselmann
            "Amount of memory used by node (dom0 for Xen)"),
1096 79b2ca83 Michael Hanselmann
  "mtotal": ("MTotal", QFT_UNIT, "memory_total",
1097 79b2ca83 Michael Hanselmann
             "Total amount of memory of physical machine"),
1098 8235fe04 Michael Hanselmann
  }
1099 8235fe04 Michael Hanselmann
1100 8235fe04 Michael Hanselmann
1101 8572f1fe René Nussbaumer
def _GetGroup(cb):
1102 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
1103 8572f1fe René Nussbaumer

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

1106 8572f1fe René Nussbaumer
  """
1107 8572f1fe René Nussbaumer
  def fn(ctx, node):
1108 8572f1fe René Nussbaumer
    """Get group data for a node.
1109 8572f1fe René Nussbaumer

1110 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1111 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1112 8572f1fe René Nussbaumer
    @param inst: Node object
1113 8572f1fe René Nussbaumer

1114 8572f1fe René Nussbaumer
    """
1115 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1116 8572f1fe René Nussbaumer
    if ng is None:
1117 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1118 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1119 8572f1fe René Nussbaumer
1120 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1121 8572f1fe René Nussbaumer
1122 8572f1fe René Nussbaumer
  return fn
1123 8572f1fe René Nussbaumer
1124 8572f1fe René Nussbaumer
1125 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1126 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1127 8235fe04 Michael Hanselmann

1128 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1129 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1130 8235fe04 Michael Hanselmann
  @param node: Node object
1131 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1132 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1133 8235fe04 Michael Hanselmann

1134 8235fe04 Michael Hanselmann
  """
1135 e2d188cc Iustin Pop
  return ng.name
1136 8235fe04 Michael Hanselmann
1137 8235fe04 Michael Hanselmann
1138 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1139 52b5d286 René Nussbaumer
  """Returns the node powered state
1140 52b5d286 René Nussbaumer

1141 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1142 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1143 52b5d286 René Nussbaumer
  @param node: Node object
1144 52b5d286 René Nussbaumer

1145 52b5d286 René Nussbaumer
  """
1146 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1147 e2d188cc Iustin Pop
    return node.powered
1148 52b5d286 René Nussbaumer
1149 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1150 52b5d286 René Nussbaumer
1151 52b5d286 René Nussbaumer
1152 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1153 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1154 8572f1fe René Nussbaumer

1155 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1156 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1157 8572f1fe René Nussbaumer
  @param node: Node object
1158 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1159 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1160 8572f1fe René Nussbaumer

1161 8572f1fe René Nussbaumer
  """
1162 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1163 8572f1fe René Nussbaumer
1164 8572f1fe René Nussbaumer
1165 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1166 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1167 8235fe04 Michael Hanselmann

1168 8235fe04 Michael Hanselmann
  @param field: Live field name
1169 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1170 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1171 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1172 a6070ef7 Michael Hanselmann
  @param node: Node object
1173 8235fe04 Michael Hanselmann

1174 8235fe04 Michael Hanselmann
  """
1175 a6070ef7 Michael Hanselmann
  if node.offline:
1176 e2d188cc Iustin Pop
    return _FS_OFFLINE
1177 a6070ef7 Michael Hanselmann
1178 effab4ca Iustin Pop
  if not node.vm_capable:
1179 effab4ca Iustin Pop
    return _FS_UNAVAIL
1180 effab4ca Iustin Pop
1181 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1182 e2d188cc Iustin Pop
    return _FS_NODATA
1183 8235fe04 Michael Hanselmann
1184 8235fe04 Michael Hanselmann
  try:
1185 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1186 8235fe04 Michael Hanselmann
  except KeyError:
1187 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1188 8235fe04 Michael Hanselmann
1189 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1190 e2d188cc Iustin Pop
    return value
1191 8235fe04 Michael Hanselmann
1192 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1193 8235fe04 Michael Hanselmann
1194 8235fe04 Michael Hanselmann
  # Try to convert into number
1195 8235fe04 Michael Hanselmann
  try:
1196 e2d188cc Iustin Pop
    return int(value)
1197 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1198 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1199 8235fe04 Michael Hanselmann
                      value, field)
1200 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1201 8235fe04 Michael Hanselmann
1202 8235fe04 Michael Hanselmann
1203 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1204 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1205 54ac87c0 Michael Hanselmann

1206 54ac87c0 Michael Hanselmann
  """
1207 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1208 54ac87c0 Michael Hanselmann
1209 54ac87c0 Michael Hanselmann
  if hv_state is None:
1210 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1211 54ac87c0 Michael Hanselmann
1212 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1213 54ac87c0 Michael Hanselmann
1214 54ac87c0 Michael Hanselmann
1215 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1216 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1217 54ac87c0 Michael Hanselmann

1218 54ac87c0 Michael Hanselmann
  """
1219 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1220 54ac87c0 Michael Hanselmann
1221 54ac87c0 Michael Hanselmann
  if disk_state is None:
1222 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1223 54ac87c0 Michael Hanselmann
1224 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1225 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1226 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1227 54ac87c0 Michael Hanselmann
1228 54ac87c0 Michael Hanselmann
1229 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1230 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1231 8235fe04 Michael Hanselmann

1232 8235fe04 Michael Hanselmann
  """
1233 8235fe04 Michael Hanselmann
  fields = [
1234 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1235 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1236 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1237 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1238 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1239 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1240 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1241 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, lambda ctx, node: node.name == ctx.master_name),
1242 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1243 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1244 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1245 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1246 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1247 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1248 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1249 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1250 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1251 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1252 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1253 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1254 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1255 54ac87c0 Michael Hanselmann
    (_MakeField("hv_state", "HypervisorState", QFT_OTHER, "Hypervisor state"),
1256 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeHvState),
1257 54ac87c0 Michael Hanselmann
    (_MakeField("disk_state", "DiskState", QFT_OTHER, "Disk state"),
1258 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeDiskState),
1259 8235fe04 Michael Hanselmann
    ]
1260 8235fe04 Michael Hanselmann
1261 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(False))
1262 8930b0f0 Iustin Pop
1263 79b2ca83 Michael Hanselmann
  # Node role
1264 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1265 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1266 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1267 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1268 79b2ca83 Michael Hanselmann
              " \"%s\" for regular, \"%s\" for a drained, \"%s\" for offline" %
1269 79b2ca83 Michael Hanselmann
              role_values)
1270 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1271 79b2ca83 Michael Hanselmann
                 lambda ctx, node: _GetNodeRole(node, ctx.master_name)))
1272 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1273 79b2ca83 Michael Hanselmann
1274 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1275 e2d188cc Iustin Pop
    return lambda ctx, node: len(getter(ctx)[node.name])
1276 8235fe04 Michael Hanselmann
1277 8235fe04 Michael Hanselmann
  def _GetList(getter):
1278 e2d188cc Iustin Pop
    return lambda ctx, node: list(getter(ctx)[node.name])
1279 8235fe04 Michael Hanselmann
1280 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1281 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1282 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1283 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1284 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1285 8235fe04 Michael Hanselmann
    fields.extend([
1286 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1287 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1288 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1289 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1290 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1291 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1292 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1293 8235fe04 Michael Hanselmann
      ])
1294 8235fe04 Michael Hanselmann
1295 8235fe04 Michael Hanselmann
  # Add simple fields
1296 111bf531 Michael Hanselmann
  fields.extend([
1297 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1298 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()
1299 111bf531 Michael Hanselmann
    ])
1300 8235fe04 Michael Hanselmann
1301 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1302 8235fe04 Michael Hanselmann
  fields.extend([
1303 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1304 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1305 79b2ca83 Michael Hanselmann
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()
1306 8235fe04 Michael Hanselmann
    ])
1307 8235fe04 Michael Hanselmann
1308 145bea54 Michael Hanselmann
  # Add timestamps
1309 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1310 145bea54 Michael Hanselmann
1311 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1312 8235fe04 Michael Hanselmann
1313 8235fe04 Michael Hanselmann
1314 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1315 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1316 1c8addc6 Michael Hanselmann

1317 1c8addc6 Michael Hanselmann
  """
1318 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1319 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1320 1c8addc6 Michael Hanselmann
    """Initializes this class.
1321 1c8addc6 Michael Hanselmann

1322 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1323 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1324 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1325 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1326 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1327 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1328 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1329 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1330 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1331 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1332 e431074f René Nussbaumer
    @type wrongnode_inst: set
1333 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1334 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1335 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1336 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1337 fab9573b Michael Hanselmann
    @param nodes: Node objects
1338 1c8addc6 Michael Hanselmann

1339 1c8addc6 Michael Hanselmann
    """
1340 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1341 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1342 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1343 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1344 1c8addc6 Michael Hanselmann
1345 1c8addc6 Michael Hanselmann
    self.instances = instances
1346 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1347 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1348 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1349 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1350 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1351 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1352 5d28cb6f Michael Hanselmann
    self.console = console
1353 fab9573b Michael Hanselmann
    self.nodes = nodes
1354 fab9573b Michael Hanselmann
    self.groups = groups
1355 1c8addc6 Michael Hanselmann
1356 1c8addc6 Michael Hanselmann
    # Used for individual rows
1357 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1358 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1359 7c670076 Michael Hanselmann
    self.inst_osparams = None
1360 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1361 1c8addc6 Michael Hanselmann
1362 1c8addc6 Michael Hanselmann
  def __iter__(self):
1363 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1364 1c8addc6 Michael Hanselmann

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

1368 1c8addc6 Michael Hanselmann
    """
1369 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1370 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1371 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1372 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1373 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1374 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1375 1c8addc6 Michael Hanselmann
1376 1c8addc6 Michael Hanselmann
      yield inst
1377 1c8addc6 Michael Hanselmann
1378 1c8addc6 Michael Hanselmann
1379 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1380 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1381 1c8addc6 Michael Hanselmann

1382 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1383 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1384 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1385 1c8addc6 Michael Hanselmann

1386 1c8addc6 Michael Hanselmann
  """
1387 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1388 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1389 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1390 e2d188cc Iustin Pop
    return _FS_NODATA
1391 1c8addc6 Michael Hanselmann
  else:
1392 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1393 1c8addc6 Michael Hanselmann
1394 1c8addc6 Michael Hanselmann
1395 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1396 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1397 1c8addc6 Michael Hanselmann

1398 1c8addc6 Michael Hanselmann
  @type name: string
1399 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1400 1c8addc6 Michael Hanselmann

1401 1c8addc6 Michael Hanselmann
  """
1402 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1403 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1404 1c8addc6 Michael Hanselmann

1405 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1406 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1407 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1408 1c8addc6 Michael Hanselmann

1409 1c8addc6 Michael Hanselmann
    """
1410 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1411 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1412 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1413 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1414 e2d188cc Iustin Pop
      return _FS_NODATA
1415 1c8addc6 Michael Hanselmann
1416 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1417 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1418 1c8addc6 Michael Hanselmann
      if name in data:
1419 e2d188cc Iustin Pop
        return data[name]
1420 1c8addc6 Michael Hanselmann
1421 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1422 1c8addc6 Michael Hanselmann
1423 1c8addc6 Michael Hanselmann
  return fn
1424 1c8addc6 Michael Hanselmann
1425 1c8addc6 Michael Hanselmann
1426 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1427 1c8addc6 Michael Hanselmann
  """Get instance status.
1428 1c8addc6 Michael Hanselmann

1429 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1430 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1431 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1432 1c8addc6 Michael Hanselmann

1433 1c8addc6 Michael Hanselmann
  """
1434 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1435 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1436 1c8addc6 Michael Hanselmann
1437 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1438 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1439 1c8addc6 Michael Hanselmann
1440 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1441 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1442 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1443 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1444 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1445 1c8addc6 Michael Hanselmann
    else:
1446 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1447 1c8addc6 Michael Hanselmann
1448 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1449 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1450 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1451 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1452 1c8addc6 Michael Hanselmann
1453 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1454 1c8addc6 Michael Hanselmann
1455 1c8addc6 Michael Hanselmann
1456 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1457 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1458 1c8addc6 Michael Hanselmann

1459 1c8addc6 Michael Hanselmann
  @type index: int
1460 1c8addc6 Michael Hanselmann
  @param index: Disk index
1461 1c8addc6 Michael Hanselmann

1462 1c8addc6 Michael Hanselmann
  """
1463 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1464 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1465 1c8addc6 Michael Hanselmann

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

1469 1c8addc6 Michael Hanselmann
    """
1470 1c8addc6 Michael Hanselmann
    try:
1471 e2d188cc Iustin Pop
      return inst.disks[index].size
1472 1c8addc6 Michael Hanselmann
    except IndexError:
1473 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1474 1c8addc6 Michael Hanselmann
1475 1c8addc6 Michael Hanselmann
  return fn
1476 1c8addc6 Michael Hanselmann
1477 1c8addc6 Michael Hanselmann
1478 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1479 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1480 1c8addc6 Michael Hanselmann

1481 1c8addc6 Michael Hanselmann
  @type index: int
1482 1c8addc6 Michael Hanselmann
  @param index: NIC index
1483 1c8addc6 Michael Hanselmann
  @type cb: callable
1484 1c8addc6 Michael Hanselmann
  @param cb: Callback
1485 1c8addc6 Michael Hanselmann

1486 1c8addc6 Michael Hanselmann
  """
1487 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1488 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1489 1c8addc6 Michael Hanselmann

1490 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1491 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1492 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1493 1c8addc6 Michael Hanselmann

1494 1c8addc6 Michael Hanselmann
    """
1495 1c8addc6 Michael Hanselmann
    try:
1496 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1497 1c8addc6 Michael Hanselmann
    except IndexError:
1498 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1499 1c8addc6 Michael Hanselmann
1500 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1501 1c8addc6 Michael Hanselmann
1502 1c8addc6 Michael Hanselmann
  return fn
1503 1c8addc6 Michael Hanselmann
1504 1c8addc6 Michael Hanselmann
1505 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1506 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1507 1c8addc6 Michael Hanselmann

1508 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1509 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1510 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1511 1c8addc6 Michael Hanselmann

1512 1c8addc6 Michael Hanselmann
  """
1513 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1514 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1515 1c8addc6 Michael Hanselmann
  else:
1516 e2d188cc Iustin Pop
    return nic.ip
1517 1c8addc6 Michael Hanselmann
1518 1c8addc6 Michael Hanselmann
1519 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1520 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1521 1c8addc6 Michael Hanselmann

1522 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1523 1c8addc6 Michael Hanselmann
  @type index: int
1524 1c8addc6 Michael Hanselmann
  @param index: NIC index
1525 1c8addc6 Michael Hanselmann

1526 1c8addc6 Michael Hanselmann
  """
1527 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1528 1c8addc6 Michael Hanselmann
1529 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1530 1c8addc6 Michael Hanselmann
1531 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1532 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1533 1c8addc6 Michael Hanselmann
  else:
1534 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1535 1c8addc6 Michael Hanselmann
1536 1c8addc6 Michael Hanselmann
1537 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1538 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1539 1c8addc6 Michael Hanselmann

1540 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1541 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1542 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1543 1c8addc6 Michael Hanselmann

1544 1c8addc6 Michael Hanselmann
  """
1545 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1546 1c8addc6 Michael Hanselmann
1547 1c8addc6 Michael Hanselmann
  result = []
1548 1c8addc6 Michael Hanselmann
1549 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1550 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1551 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1552 1c8addc6 Michael Hanselmann
    else:
1553 1c8addc6 Michael Hanselmann
      result.append(None)
1554 1c8addc6 Michael Hanselmann
1555 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1556 1c8addc6 Michael Hanselmann
1557 e2d188cc Iustin Pop
  return result
1558 1c8addc6 Michael Hanselmann
1559 1c8addc6 Michael Hanselmann
1560 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1561 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1562 1c8addc6 Michael Hanselmann

1563 1c8addc6 Michael Hanselmann
  @type name: string
1564 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1565 1c8addc6 Michael Hanselmann

1566 1c8addc6 Michael Hanselmann
  """
1567 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1568 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1569 1c8addc6 Michael Hanselmann

1570 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1571 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1572 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1573 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1574 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1575 1c8addc6 Michael Hanselmann

1576 1c8addc6 Michael Hanselmann
    """
1577 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1578 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1579 1c8addc6 Michael Hanselmann
1580 1c8addc6 Michael Hanselmann
  return fn
1581 1c8addc6 Michael Hanselmann
1582 1c8addc6 Michael Hanselmann
1583 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1584 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1585 1c8addc6 Michael Hanselmann

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

1589 1c8addc6 Michael Hanselmann
  """
1590 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1591 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1592 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1593 1c8addc6 Michael Hanselmann
1594 1c8addc6 Michael Hanselmann
  fields = [
1595 1c8addc6 Michael Hanselmann
    # All NICs
1596 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1597 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1598 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1599 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1600 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1601 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1602 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1603 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1604 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1605 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1606 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1607 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1608 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1609 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1610 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1611 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1612 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1613 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1614 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1615 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1616 1c8addc6 Michael Hanselmann
    ]
1617 1c8addc6 Michael Hanselmann
1618 1c8addc6 Michael Hanselmann
  # NICs by number
1619 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1620 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1621 1c8addc6 Michael Hanselmann
    fields.extend([
1622 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1623 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1624 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1625 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1626 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1627 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1628 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1629 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1630 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1631 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1632 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1633 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1634 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1635 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1636 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1637 1c8addc6 Michael Hanselmann
      ])
1638 1c8addc6 Michael Hanselmann
1639 4cc4d1fa Michael Hanselmann
  aliases = [
1640 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1641 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1642 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1643 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1644 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1645 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1646 4cc4d1fa Michael Hanselmann
    ]
1647 4cc4d1fa Michael Hanselmann
1648 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1649 1c8addc6 Michael Hanselmann
1650 1c8addc6 Michael Hanselmann
1651 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1652 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1653 1c8addc6 Michael Hanselmann

1654 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1655 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1656 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1657 1c8addc6 Michael Hanselmann

1658 1c8addc6 Michael Hanselmann
  """
1659 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1660 1c8addc6 Michael Hanselmann
1661 1c8addc6 Michael Hanselmann
  if usage is None:
1662 1c8addc6 Michael Hanselmann
    usage = 0
1663 1c8addc6 Michael Hanselmann
1664 e2d188cc Iustin Pop
  return usage
1665 1c8addc6 Michael Hanselmann
1666 1c8addc6 Michael Hanselmann
1667 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1668 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1669 5d28cb6f Michael Hanselmann

1670 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1671 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1672 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1673 5d28cb6f Michael Hanselmann

1674 5d28cb6f Michael Hanselmann
  """
1675 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1676 5d28cb6f Michael Hanselmann
1677 5d28cb6f Michael Hanselmann
  if consinfo is None:
1678 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1679 5d28cb6f Michael Hanselmann
1680 5d28cb6f Michael Hanselmann
  return consinfo
1681 5d28cb6f Michael Hanselmann
1682 5d28cb6f Michael Hanselmann
1683 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1684 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1685 1c8addc6 Michael Hanselmann

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

1688 1c8addc6 Michael Hanselmann
  """
1689 1c8addc6 Michael Hanselmann
  fields = [
1690 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1691 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1692 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1693 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1694 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1695 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1696 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1697 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1698 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1699 1c8addc6 Michael Hanselmann
    ]
1700 1c8addc6 Michael Hanselmann
1701 1c8addc6 Michael Hanselmann
  # Disks by number
1702 1c8addc6 Michael Hanselmann
  fields.extend([
1703 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1704 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1705 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1706 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1707 1c8addc6 Michael Hanselmann
    ])
1708 1c8addc6 Michael Hanselmann
1709 1c8addc6 Michael Hanselmann
  return fields
1710 1c8addc6 Michael Hanselmann
1711 1c8addc6 Michael Hanselmann
1712 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1713 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1714 1c8addc6 Michael Hanselmann

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

1717 1c8addc6 Michael Hanselmann
  """
1718 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1719 1c8addc6 Michael Hanselmann
  be_title = {
1720 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1721 31d1791a Guido Trotter
    constants.BE_MAXMEM: "ConfigMaxMem",
1722 31d1791a Guido Trotter
    constants.BE_MINMEM: "ConfigMinMem",
1723 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1724 1c8addc6 Michael Hanselmann
    }
1725 1c8addc6 Michael Hanselmann
1726 1c8addc6 Michael Hanselmann
  hv_title = {
1727 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1728 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1729 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1730 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1731 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1732 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1733 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1734 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1735 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1736 1c8addc6 Michael Hanselmann
    }
1737 1c8addc6 Michael Hanselmann
1738 1c8addc6 Michael Hanselmann
  fields = [
1739 1c8addc6 Michael Hanselmann
    # Filled parameters
1740 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1741 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1742 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1743 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1744 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1745 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1746 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1747 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1748 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1749 1c8addc6 Michael Hanselmann
1750 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1751 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1752 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1753 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1754 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1755 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1756 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1757 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1758 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1759 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1760 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1761 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1762 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1763 1c8addc6 Michael Hanselmann
    ]
1764 1c8addc6 Michael Hanselmann
1765 1c8addc6 Michael Hanselmann
  # HV params
1766 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1767 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1768 1c8addc6 Michael Hanselmann
1769 1c8addc6 Michael Hanselmann
  fields.extend([
1770 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1771 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1772 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1773 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1774 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1775 1c8addc6 Michael Hanselmann
    ])
1776 1c8addc6 Michael Hanselmann
1777 1c8addc6 Michael Hanselmann
  # BE params
1778 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1779 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1780 1c8addc6 Michael Hanselmann
1781 1c8addc6 Michael Hanselmann
  fields.extend([
1782 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1783 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1784 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1785 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1786 1c8addc6 Michael Hanselmann
    ])
1787 1c8addc6 Michael Hanselmann
1788 1c8addc6 Michael Hanselmann
  return fields
1789 1c8addc6 Michael Hanselmann
1790 1c8addc6 Michael Hanselmann
1791 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1792 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1793 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1794 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1795 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1796 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1797 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1798 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1799 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1800 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1801 1c8addc6 Michael Hanselmann
  }
1802 1c8addc6 Michael Hanselmann
1803 1c8addc6 Michael Hanselmann
1804 fab9573b Michael Hanselmann
def _GetInstNodeGroup(ctx, default, node_name):
1805 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
1806 fab9573b Michael Hanselmann

1807 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1808 fab9573b Michael Hanselmann
  @param default: Default value
1809 fab9573b Michael Hanselmann
  @type node_name: string
1810 fab9573b Michael Hanselmann
  @param node_name: Node name
1811 fab9573b Michael Hanselmann

1812 fab9573b Michael Hanselmann
  """
1813 fab9573b Michael Hanselmann
  try:
1814 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1815 fab9573b Michael Hanselmann
  except KeyError:
1816 fab9573b Michael Hanselmann
    return default
1817 fab9573b Michael Hanselmann
  else:
1818 fab9573b Michael Hanselmann
    return node.group
1819 fab9573b Michael Hanselmann
1820 fab9573b Michael Hanselmann
1821 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1822 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1823 fab9573b Michael Hanselmann

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

1829 fab9573b Michael Hanselmann
  """
1830 fab9573b Michael Hanselmann
  try:
1831 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1832 fab9573b Michael Hanselmann
  except KeyError:
1833 fab9573b Michael Hanselmann
    return default
1834 fab9573b Michael Hanselmann
1835 fab9573b Michael Hanselmann
  try:
1836 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1837 fab9573b Michael Hanselmann
  except KeyError:
1838 fab9573b Michael Hanselmann
    return default
1839 fab9573b Michael Hanselmann
1840 fab9573b Michael Hanselmann
  return group.name
1841 fab9573b Michael Hanselmann
1842 fab9573b Michael Hanselmann
1843 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1844 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1845 1c8addc6 Michael Hanselmann

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

1943 24d16f76 Michael Hanselmann
  """
1944 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1945 24d16f76 Michael Hanselmann
    """Initializes this class.
1946 24d16f76 Michael Hanselmann

1947 24d16f76 Michael Hanselmann
    """
1948 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1949 24d16f76 Michael Hanselmann
1950 24d16f76 Michael Hanselmann
  def __iter__(self):
1951 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1952 24d16f76 Michael Hanselmann

1953 24d16f76 Michael Hanselmann
    """
1954 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1955 24d16f76 Michael Hanselmann
1956 24d16f76 Michael Hanselmann
1957 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1958 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1959 24d16f76 Michael Hanselmann

1960 24d16f76 Michael Hanselmann
  """
1961 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1962 24d16f76 Michael Hanselmann
1963 24d16f76 Michael Hanselmann
  if owners:
1964 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1965 24d16f76 Michael Hanselmann
1966 e2d188cc Iustin Pop
  return owners
1967 24d16f76 Michael Hanselmann
1968 24d16f76 Michael Hanselmann
1969 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1970 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1971 24d16f76 Michael Hanselmann

1972 24d16f76 Michael Hanselmann
  """
1973 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1974 24d16f76 Michael Hanselmann
1975 24d16f76 Michael Hanselmann
  if pending:
1976 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1977 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1978 24d16f76 Michael Hanselmann
1979 e2d188cc Iustin Pop
  return pending
1980 24d16f76 Michael Hanselmann
1981 24d16f76 Michael Hanselmann
1982 24d16f76 Michael Hanselmann
def _BuildLockFields():
1983 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1984 24d16f76 Michael Hanselmann

1985 24d16f76 Michael Hanselmann
  """
1986 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1987 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
1988 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
1989 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1990 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
1991 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
1992 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
1993 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
1994 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
1995 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
1996 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
1997 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
1998 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
1999 d63bd540 Iustin Pop
    ], [])
2000 24d16f76 Michael Hanselmann
2001 24d16f76 Michael Hanselmann
2002 8e21cfc0 Adeodato Simo
class GroupQueryData:
2003 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
2004 8e21cfc0 Adeodato Simo

2005 8e21cfc0 Adeodato Simo
  """
2006 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2007 2c758845 René Nussbaumer
               want_diskparams):
2008 8e21cfc0 Adeodato Simo
    """Initializes this class.
2009 8e21cfc0 Adeodato Simo

2010 edd49f9b Agata Murawska
    @param cluster: Cluster object
2011 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2012 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2013 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2014 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2015 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2016 2c758845 René Nussbaumer
    @type want_diskparams: bool
2017 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2018 8e21cfc0 Adeodato Simo

2019 8e21cfc0 Adeodato Simo
    """
2020 8e21cfc0 Adeodato Simo
    self.groups = groups
2021 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2022 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2023 edd49f9b Agata Murawska
    self.cluster = cluster
2024 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2025 edd49f9b Agata Murawska
2026 edd49f9b Agata Murawska
    # Used for individual rows
2027 edd49f9b Agata Murawska
    self.group_ipolicy = None
2028 8930b0f0 Iustin Pop
    self.ndparams = None
2029 2c758845 René Nussbaumer
    self.group_dp = None
2030 8e21cfc0 Adeodato Simo
2031 8e21cfc0 Adeodato Simo
  def __iter__(self):
2032 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2033 8e21cfc0 Adeodato Simo

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

2037 8e21cfc0 Adeodato Simo
    """
2038 edd49f9b Agata Murawska
    for group in self.groups:
2039 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2040 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2041 2c758845 René Nussbaumer
      if self.want_diskparams:
2042 2c758845 René Nussbaumer
        self.group_dp = self.cluster.SimpleFillDP(group.diskparams)
2043 2c758845 René Nussbaumer
      else:
2044 2c758845 René Nussbaumer
        self.group_dp = None
2045 edd49f9b Agata Murawska
      yield group
2046 8e21cfc0 Adeodato Simo
2047 8e21cfc0 Adeodato Simo
2048 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2049 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2050 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2051 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2052 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2053 8e21cfc0 Adeodato Simo
  }
2054 8e21cfc0 Adeodato Simo
2055 8e21cfc0 Adeodato Simo
2056 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2057 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2058 8e21cfc0 Adeodato Simo

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

2140 be3a4b14 Michael Hanselmann
  """
2141 be3a4b14 Michael Hanselmann
  fields = [
2142 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2143 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2144 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2145 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2146 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2147 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2148 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2149 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2150 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2151 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2152 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2153 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2154 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2155 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2156 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2157 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2158 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2159 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2160 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2161 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2162 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2163 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2164 be3a4b14 Michael Hanselmann
                "Status from node"),
2165 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2166 be3a4b14 Michael Hanselmann
    ]
2167 be3a4b14 Michael Hanselmann
2168 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2169 be3a4b14 Michael Hanselmann
2170 be3a4b14 Michael Hanselmann
2171 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2172 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2173 9665bb3a Michael Hanselmann

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

2177 9665bb3a Michael Hanselmann
  """
2178 9665bb3a Michael Hanselmann
  if job is None:
2179 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2180 9665bb3a Michael Hanselmann
  else:
2181 9665bb3a Michael Hanselmann
    return fn(job)
2182 9665bb3a Michael Hanselmann
2183 9665bb3a Michael Hanselmann
2184 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2185 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2186 9665bb3a Michael Hanselmann

2187 9665bb3a Michael Hanselmann
  """
2188 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2189 9665bb3a Michael Hanselmann
2190 9665bb3a Michael Hanselmann
2191 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2192 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2193 9665bb3a Michael Hanselmann

2194 9665bb3a Michael Hanselmann
  """
2195 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2196 9665bb3a Michael Hanselmann
2197 9665bb3a Michael Hanselmann
2198 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2199 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2200 9665bb3a Michael Hanselmann

2201 9665bb3a Michael Hanselmann
  """
2202 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2203 9665bb3a Michael Hanselmann
2204 9665bb3a Michael Hanselmann
2205 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2206 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2207 9665bb3a Michael Hanselmann

2208 9665bb3a Michael Hanselmann
  """
2209 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2210 9665bb3a Michael Hanselmann
2211 9665bb3a Michael Hanselmann
  if timestamp is None:
2212 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2213 9665bb3a Michael Hanselmann
  else:
2214 9665bb3a Michael Hanselmann
    return timestamp
2215 9665bb3a Michael Hanselmann
2216 9665bb3a Michael Hanselmann
2217 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2218 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2219 9665bb3a Michael Hanselmann

2220 9665bb3a Michael Hanselmann
  """
2221 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2222 9665bb3a Michael Hanselmann
2223 9665bb3a Michael Hanselmann
2224 9665bb3a Michael Hanselmann
def _BuildJobFields():
2225 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2226 9665bb3a Michael Hanselmann

2227 9665bb3a Michael Hanselmann
  """
2228 9665bb3a Michael Hanselmann
  fields = [
2229 9665bb3a Michael Hanselmann
    (_MakeField("id", "ID", QFT_TEXT, "Job ID"),
2230 9665bb3a Michael Hanselmann
     None, 0, lambda _, (job_id, job): job_id),
2231 9665bb3a Michael Hanselmann
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2232 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2233 9665bb3a Michael Hanselmann
    (_MakeField("priority", "Priority", QFT_NUMBER,
2234 9665bb3a Michael Hanselmann
                ("Current job priority (%s to %s)" %
2235 9665bb3a Michael Hanselmann
                 (constants.OP_PRIO_LOWEST, constants.OP_PRIO_HIGHEST))),
2236 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcPriority())),
2237 9665bb3a Michael Hanselmann
    (_MakeField("ops", "OpCodes", QFT_OTHER, "List of all opcodes"),
2238 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.__getstate__())),
2239 9665bb3a Michael Hanselmann
    (_MakeField("opresult", "OpCode_result", QFT_OTHER,
2240 9665bb3a Michael Hanselmann
                "List of opcodes results"),
2241 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("result"))),
2242 9665bb3a Michael Hanselmann
    (_MakeField("opstatus", "OpCode_status", QFT_OTHER,
2243 9665bb3a Michael Hanselmann
                "List of opcodes status"),
2244 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("status"))),
2245 9665bb3a Michael Hanselmann
    (_MakeField("oplog", "OpCode_log", QFT_OTHER,
2246 9665bb3a Michael Hanselmann
                "List of opcode output logs"),
2247 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("log"))),
2248 9665bb3a Michael Hanselmann
    (_MakeField("opstart", "OpCode_start", QFT_OTHER,
2249 9665bb3a Michael Hanselmann
                "List of opcode start timestamps (before acquiring locks)"),
2250 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("start_timestamp"))),
2251 9665bb3a Michael Hanselmann
    (_MakeField("opexec", "OpCode_exec", QFT_OTHER,
2252 9665bb3a Michael Hanselmann
                "List of opcode execution start timestamps (after acquiring"
2253 9665bb3a Michael Hanselmann
                " locks)"),
2254 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("exec_timestamp"))),
2255 9665bb3a Michael Hanselmann
    (_MakeField("opend", "OpCode_end", QFT_OTHER,
2256 9665bb3a Michael Hanselmann
                "List of opcode execution end timestamps"),
2257 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("end_timestamp"))),
2258 9665bb3a Michael Hanselmann
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2259 9665bb3a Michael Hanselmann
                "List of opcode priorities"),
2260 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2261 9665bb3a Michael Hanselmann
    (_MakeField("received_ts", "Received", QFT_OTHER,
2262 9665bb3a Michael Hanselmann
                "Timestamp of when job was received"),
2263 9665bb3a Michael Hanselmann
     None, 0, _JobTimestamp(operator.attrgetter("received_timestamp"))),
2264 9665bb3a Michael Hanselmann
    (_MakeField("start_ts", "Start", QFT_OTHER,
2265 9665bb3a Michael Hanselmann
                "Timestamp of job start"),
2266 9665bb3a Michael Hanselmann
     None, 0, _JobTimestamp(operator.attrgetter("start_timestamp"))),
2267 9665bb3a Michael Hanselmann
    (_MakeField("end_ts", "End", QFT_OTHER,
2268 9665bb3a Michael Hanselmann
                "Timestamp of job end"),
2269 9665bb3a Michael Hanselmann
     None, 0, _JobTimestamp(operator.attrgetter("end_timestamp"))),
2270 9665bb3a Michael Hanselmann
    (_MakeField("summary", "Summary", QFT_OTHER,
2271 9665bb3a Michael Hanselmann
                "List of per-opcode summaries"),
2272 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2273 9665bb3a Michael Hanselmann
    ]
2274 9665bb3a Michael Hanselmann
2275 9665bb3a Michael Hanselmann
  return _PrepareFieldList(fields, [])
2276 9665bb3a Michael Hanselmann
2277 9665bb3a Michael Hanselmann
2278 0fdf247d Michael Hanselmann
def _GetExportName(_, (node_name, expname)): # pylint: disable=W0613
2279 0fdf247d Michael Hanselmann
  """Returns an export name if available.
2280 0fdf247d Michael Hanselmann

2281 0fdf247d Michael Hanselmann
  """
2282 0fdf247d Michael Hanselmann
  if expname is None:
2283 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2284 0fdf247d Michael Hanselmann
  else:
2285 0fdf247d Michael Hanselmann
    return expname
2286 0fdf247d Michael Hanselmann
2287 0fdf247d Michael Hanselmann
2288 0fdf247d Michael Hanselmann
def _BuildExportFields():
2289 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2290 0fdf247d Michael Hanselmann

2291 0fdf247d Michael Hanselmann
  """
2292 0fdf247d Michael Hanselmann
  fields = [
2293 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2294 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2295 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2296 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2297 0fdf247d Michael Hanselmann
    ]
2298 0fdf247d Michael Hanselmann
2299 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2300 0fdf247d Michael Hanselmann
2301 0fdf247d Michael Hanselmann
2302 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2303 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2304 dff5f600 Michael Hanselmann
                       "Software version"),
2305 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2306 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2307 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2308 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2309 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2310 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2311 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2312 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2313 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2314 dff5f600 Michael Hanselmann
  }
2315 dff5f600 Michael Hanselmann
2316 dff5f600 Michael Hanselmann
2317 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2318 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2319 dff5f600 Michael Hanselmann
  "master_node": ("Master", QFT_TEXT, QFF_HOSTNAME, "Master node name"),
2320 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2321 dff5f600 Michael Hanselmann
  }
2322 dff5f600 Michael Hanselmann
2323 dff5f600 Michael Hanselmann
2324 dff5f600 Michael Hanselmann
class ClusterQueryData:
2325 dff5f600 Michael Hanselmann
  def __init__(self, cluster, drain_flag, watcher_pause):
2326 dff5f600 Michael Hanselmann
    """Initializes this class.
2327 dff5f600 Michael Hanselmann

2328 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2329 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2330 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2331 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2332 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2333 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2334 dff5f600 Michael Hanselmann

2335 dff5f600 Michael Hanselmann
    """
2336 dff5f600 Michael Hanselmann
    self._cluster = cluster
2337 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2338 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2339 dff5f600 Michael Hanselmann
2340 dff5f600 Michael Hanselmann
  def __iter__(self):
2341 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2342 dff5f600 Michael Hanselmann
2343 dff5f600 Michael Hanselmann
2344 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2345 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2346 dff5f600 Michael Hanselmann

2347 dff5f600 Michael Hanselmann
  """
2348 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2349 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2350 dff5f600 Michael Hanselmann
  else:
2351 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2352 dff5f600 Michael Hanselmann
2353 dff5f600 Michael Hanselmann
2354 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2355 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2356 dff5f600 Michael Hanselmann

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