Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 70817cee

History | View | Annotate | Download (71.8 kB)

1 4ca96421 Michael Hanselmann
#
2 4ca96421 Michael Hanselmann
#
3 4ca96421 Michael Hanselmann
4 8930b0f0 Iustin Pop
# Copyright (C) 2010, 2011, 2012 Google Inc.
5 4ca96421 Michael Hanselmann
#
6 4ca96421 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 4ca96421 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 4ca96421 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 4ca96421 Michael Hanselmann
# (at your option) any later version.
10 4ca96421 Michael Hanselmann
#
11 4ca96421 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 4ca96421 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 4ca96421 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4ca96421 Michael Hanselmann
# General Public License for more details.
15 4ca96421 Michael Hanselmann
#
16 4ca96421 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 4ca96421 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 4ca96421 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 4ca96421 Michael Hanselmann
# 02110-1301, USA.
20 4ca96421 Michael Hanselmann
21 4ca96421 Michael Hanselmann
22 8f8ce6d1 Michael Hanselmann
"""Module for query operations
23 8f8ce6d1 Michael Hanselmann

24 8f8ce6d1 Michael Hanselmann
How it works:
25 8f8ce6d1 Michael Hanselmann

26 8f8ce6d1 Michael Hanselmann
  - Add field definitions
27 8f8ce6d1 Michael Hanselmann
    - See how L{NODE_FIELDS} is built
28 8f8ce6d1 Michael Hanselmann
    - Each field gets:
29 8f8ce6d1 Michael Hanselmann
      - Query field definition (L{objects.QueryFieldDefinition}, use
30 8f8ce6d1 Michael Hanselmann
        L{_MakeField} for creating), containing:
31 8f8ce6d1 Michael Hanselmann
          - Name, must be lowercase and match L{FIELD_NAME_RE}
32 8f8ce6d1 Michael Hanselmann
          - Title for tables, must not contain whitespace and match
33 8f8ce6d1 Michael Hanselmann
            L{TITLE_RE}
34 8f8ce6d1 Michael Hanselmann
          - Value data type, e.g. L{constants.QFT_NUMBER}
35 79b2ca83 Michael Hanselmann
          - Human-readable description, must not end with punctuation or
36 79b2ca83 Michael Hanselmann
            contain newlines
37 8f8ce6d1 Michael Hanselmann
      - Data request type, see e.g. C{NQ_*}
38 111bf531 Michael Hanselmann
      - OR-ed flags, see C{QFF_*}
39 8f8ce6d1 Michael Hanselmann
      - A retrieval function, see L{Query.__init__} for description
40 8f8ce6d1 Michael Hanselmann
    - Pass list of fields through L{_PrepareFieldList} for preparation and
41 8f8ce6d1 Michael Hanselmann
      checks
42 8f8ce6d1 Michael Hanselmann
  - Instantiate L{Query} with prepared field list definition and selected fields
43 8f8ce6d1 Michael Hanselmann
  - Call L{Query.RequestedData} to determine what data to collect/compute
44 8f8ce6d1 Michael Hanselmann
  - Call L{Query.Query} or L{Query.OldStyleQuery} with collected data and use
45 8f8ce6d1 Michael Hanselmann
    result
46 8f8ce6d1 Michael Hanselmann
      - Data container must support iteration using C{__iter__}
47 8f8ce6d1 Michael Hanselmann
      - Items are passed to retrieval functions and can have any format
48 8f8ce6d1 Michael Hanselmann
  - Call L{Query.GetFields} to get list of definitions for selected fields
49 8f8ce6d1 Michael Hanselmann

50 8f8ce6d1 Michael Hanselmann
@attention: Retrieval functions must be idempotent. They can be called multiple
51 fb0be379 Michael Hanselmann
  times, in any order and any number of times.
52 8f8ce6d1 Michael Hanselmann

53 8f8ce6d1 Michael Hanselmann
"""
54 4ca96421 Michael Hanselmann
55 8235fe04 Michael Hanselmann
import logging
56 4ca96421 Michael Hanselmann
import operator
57 4ca96421 Michael Hanselmann
import re
58 4ca96421 Michael Hanselmann
59 4ca96421 Michael Hanselmann
from ganeti import constants
60 4ca96421 Michael Hanselmann
from ganeti import errors
61 4ca96421 Michael Hanselmann
from ganeti import utils
62 4ca96421 Michael Hanselmann
from ganeti import compat
63 4ca96421 Michael Hanselmann
from ganeti import objects
64 4ca96421 Michael Hanselmann
from ganeti import ht
65 dff5f600 Michael Hanselmann
from ganeti import runtime
66 fb0be379 Michael Hanselmann
from ganeti import qlang
67 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 ad48eacc Michael Hanselmann
    qlang.OP_LT: (_OPTYPE_BINARY, [
407 ad48eacc Michael Hanselmann
      (None, operator.lt, None),
408 ad48eacc Michael Hanselmann
      ]),
409 ad48eacc Michael Hanselmann
    qlang.OP_GT: (_OPTYPE_BINARY, [
410 ad48eacc Michael Hanselmann
      (None, operator.gt, None),
411 ad48eacc Michael Hanselmann
      ]),
412 ad48eacc Michael Hanselmann
    qlang.OP_LE: (_OPTYPE_BINARY, [
413 ad48eacc Michael Hanselmann
      (None, operator.le, None),
414 ad48eacc Michael Hanselmann
      ]),
415 ad48eacc Michael Hanselmann
    qlang.OP_GE: (_OPTYPE_BINARY, [
416 ad48eacc Michael Hanselmann
      (None, operator.ge, None),
417 ad48eacc Michael Hanselmann
      ]),
418 23d0a608 Michael Hanselmann
    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
419 23d0a608 Michael Hanselmann
      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
420 23d0a608 Michael Hanselmann
      ]),
421 fb0be379 Michael Hanselmann
    qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
422 23d0a608 Michael Hanselmann
      (None, operator.contains, None),
423 fb0be379 Michael Hanselmann
      ]),
424 fb0be379 Michael Hanselmann
    }
425 fb0be379 Michael Hanselmann
426 fb0be379 Michael Hanselmann
  def __init__(self, fields):
427 fb0be379 Michael Hanselmann
    """Initializes this class.
428 fb0be379 Michael Hanselmann

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

431 fb0be379 Michael Hanselmann
    """
432 fb0be379 Michael Hanselmann
    self._fields = fields
433 fb0be379 Michael Hanselmann
    self._hints = None
434 fb0be379 Michael Hanselmann
    self._op_handler = None
435 fb0be379 Michael Hanselmann
436 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
437 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
438 fb0be379 Michael Hanselmann

439 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
440 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
441 2e5c33db Iustin Pop
    @type qfilter: list
442 2e5c33db Iustin Pop
    @param qfilter: Filter structure
443 fb0be379 Michael Hanselmann
    @rtype: callable
444 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
445 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
446 fb0be379 Michael Hanselmann

447 fb0be379 Michael Hanselmann
    """
448 fb0be379 Michael Hanselmann
    self._op_handler = {
449 fb0be379 Michael Hanselmann
      self._OPTYPE_LOGIC:
450 fb0be379 Michael Hanselmann
        (self._HandleLogicOp, getattr(hints, "NoteLogicOp", None)),
451 fb0be379 Michael Hanselmann
      self._OPTYPE_UNARY:
452 fb0be379 Michael Hanselmann
        (self._HandleUnaryOp, getattr(hints, "NoteUnaryOp", None)),
453 fb0be379 Michael Hanselmann
      self._OPTYPE_BINARY:
454 fb0be379 Michael Hanselmann
        (self._HandleBinaryOp, getattr(hints, "NoteBinaryOp", None)),
455 fb0be379 Michael Hanselmann
      }
456 fb0be379 Michael Hanselmann
457 fb0be379 Michael Hanselmann
    try:
458 2e5c33db Iustin Pop
      filter_fn = self._Compile(qfilter, 0)
459 fb0be379 Michael Hanselmann
    finally:
460 fb0be379 Michael Hanselmann
      self._op_handler = None
461 fb0be379 Michael Hanselmann
462 fb0be379 Michael Hanselmann
    return filter_fn
463 fb0be379 Michael Hanselmann
464 2e5c33db Iustin Pop
  def _Compile(self, qfilter, level):
465 fb0be379 Michael Hanselmann
    """Inner function for converting filters.
466 fb0be379 Michael Hanselmann

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

470 fb0be379 Michael Hanselmann
    """
471 2e5c33db Iustin Pop
    if not (isinstance(qfilter, (list, tuple)) and qfilter):
472 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid filter on level %s" % level)
473 fb0be379 Michael Hanselmann
474 fb0be379 Michael Hanselmann
    # Limit recursion
475 fb0be379 Michael Hanselmann
    if level >= self._LEVELS_MAX:
476 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Only up to %s levels are allowed (filter"
477 fb0be379 Michael Hanselmann
                                  " nested too deep)" % self._LEVELS_MAX)
478 fb0be379 Michael Hanselmann
479 fb0be379 Michael Hanselmann
    # Create copy to be modified
480 2e5c33db Iustin Pop
    operands = qfilter[:]
481 fb0be379 Michael Hanselmann
    op = operands.pop(0)
482 fb0be379 Michael Hanselmann
483 fb0be379 Michael Hanselmann
    try:
484 fb0be379 Michael Hanselmann
      (kind, op_data) = self._OPS[op]
485 fb0be379 Michael Hanselmann
    except KeyError:
486 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unknown operator '%s'" % op)
487 fb0be379 Michael Hanselmann
488 fb0be379 Michael Hanselmann
    (handler, hints_cb) = self._op_handler[kind]
489 fb0be379 Michael Hanselmann
490 fb0be379 Michael Hanselmann
    return handler(hints_cb, level, op, op_data, operands)
491 fb0be379 Michael Hanselmann
492 3b877f08 Michael Hanselmann
  def _LookupField(self, name):
493 3b877f08 Michael Hanselmann
    """Returns a field definition by name.
494 3b877f08 Michael Hanselmann

495 3b877f08 Michael Hanselmann
    """
496 3b877f08 Michael Hanselmann
    try:
497 3b877f08 Michael Hanselmann
      return self._fields[name]
498 3b877f08 Michael Hanselmann
    except KeyError:
499 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
500 3b877f08 Michael Hanselmann
501 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
502 fb0be379 Michael Hanselmann
    """Handles logic operators.
503 fb0be379 Michael Hanselmann

504 fb0be379 Michael Hanselmann
    @type hints_fn: callable
505 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
506 fb0be379 Michael Hanselmann
    @type level: integer
507 fb0be379 Michael Hanselmann
    @param level: Current depth
508 fb0be379 Michael Hanselmann
    @type op: string
509 fb0be379 Michael Hanselmann
    @param op: Operator
510 fb0be379 Michael Hanselmann
    @type op_fn: callable
511 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
512 fb0be379 Michael Hanselmann
    @type operands: list
513 fb0be379 Michael Hanselmann
    @param operands: List of operands
514 fb0be379 Michael Hanselmann

515 fb0be379 Michael Hanselmann
    """
516 fb0be379 Michael Hanselmann
    if hints_fn:
517 fb0be379 Michael Hanselmann
      hints_fn(op)
518 fb0be379 Michael Hanselmann
519 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
520 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
521 fb0be379 Michael Hanselmann
522 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
523 fb0be379 Michael Hanselmann
    """Handles unary operators.
524 fb0be379 Michael Hanselmann

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

536 fb0be379 Michael Hanselmann
    """
537 3b877f08 Michael Hanselmann
    assert op_fn is None
538 3b877f08 Michael Hanselmann
539 fb0be379 Michael Hanselmann
    if hints_fn:
540 fb0be379 Michael Hanselmann
      hints_fn(op)
541 fb0be379 Michael Hanselmann
542 fb0be379 Michael Hanselmann
    if len(operands) != 1:
543 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unary operator '%s' expects exactly one"
544 fb0be379 Michael Hanselmann
                                  " operand" % op)
545 fb0be379 Michael Hanselmann
546 3b877f08 Michael Hanselmann
    if op == qlang.OP_TRUE:
547 3b877f08 Michael Hanselmann
      (_, _, _, retrieval_fn) = self._LookupField(operands[0])
548 3b877f08 Michael Hanselmann
549 3b877f08 Michael Hanselmann
      op_fn = operator.truth
550 3b877f08 Michael Hanselmann
      arg = retrieval_fn
551 3b877f08 Michael Hanselmann
    elif op == qlang.OP_NOT:
552 3b877f08 Michael Hanselmann
      op_fn = operator.not_
553 3b877f08 Michael Hanselmann
      arg = self._Compile(operands[0], level + 1)
554 3b877f08 Michael Hanselmann
    else:
555 3b877f08 Michael Hanselmann
      raise errors.ProgrammerError("Can't handle operator '%s'" % op)
556 3b877f08 Michael Hanselmann
557 3b877f08 Michael Hanselmann
    return compat.partial(_WrapUnaryOp, op_fn, arg)
558 fb0be379 Michael Hanselmann
559 fb0be379 Michael Hanselmann
  def _HandleBinaryOp(self, hints_fn, level, op, op_data, operands):
560 fb0be379 Michael Hanselmann
    """Handles binary operators.
561 fb0be379 Michael Hanselmann

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

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

611 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
612 fb0be379 Michael Hanselmann

613 fb0be379 Michael Hanselmann
  @rtype: callable
614 fb0be379 Michael Hanselmann

615 fb0be379 Michael Hanselmann
  """
616 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
617 fb0be379 Michael Hanselmann
618 fb0be379 Michael Hanselmann
619 4ca96421 Michael Hanselmann
class Query:
620 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
621 4ca96421 Michael Hanselmann
    """Initializes this class.
622 4ca96421 Michael Hanselmann

623 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
624 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
625 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
626 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
627 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
628 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
629 4ca96421 Michael Hanselmann

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

633 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
634 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
635 4ca96421 Michael Hanselmann
    @type selected: list of strings
636 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
637 4ca96421 Michael Hanselmann

638 4ca96421 Michael Hanselmann
    """
639 fb0be379 Michael Hanselmann
    assert namefield is None or namefield in fieldlist
640 fb0be379 Michael Hanselmann
641 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
642 4ca96421 Michael Hanselmann
643 fb0be379 Michael Hanselmann
    self._filter_fn = None
644 fb0be379 Michael Hanselmann
    self._requested_names = None
645 fb0be379 Michael Hanselmann
    self._filter_datakinds = frozenset()
646 fb0be379 Michael Hanselmann
647 2e5c33db Iustin Pop
    if qfilter is not None:
648 fb0be379 Michael Hanselmann
      # Collect requested names if wanted
649 fb0be379 Michael Hanselmann
      if namefield:
650 fb0be379 Michael Hanselmann
        hints = _FilterHints(namefield)
651 fb0be379 Michael Hanselmann
      else:
652 fb0be379 Michael Hanselmann
        hints = None
653 fb0be379 Michael Hanselmann
654 fb0be379 Michael Hanselmann
      # Build filter function
655 2e5c33db Iustin Pop
      self._filter_fn = _CompileFilter(fieldlist, hints, qfilter)
656 fb0be379 Michael Hanselmann
      if hints:
657 fb0be379 Michael Hanselmann
        self._requested_names = hints.RequestedNames()
658 fb0be379 Michael Hanselmann
        self._filter_datakinds = hints.ReferencedData()
659 fb0be379 Michael Hanselmann
660 fb0be379 Michael Hanselmann
    if namefield is None:
661 fb0be379 Michael Hanselmann
      self._name_fn = None
662 fb0be379 Michael Hanselmann
    else:
663 fb0be379 Michael Hanselmann
      (_, _, _, self._name_fn) = fieldlist[namefield]
664 fb0be379 Michael Hanselmann
665 fb0be379 Michael Hanselmann
  def RequestedNames(self):
666 fb0be379 Michael Hanselmann
    """Returns all names referenced in the filter.
667 fb0be379 Michael Hanselmann

668 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
669 fb0be379 Michael Hanselmann
    names, C{None} is returned.
670 fb0be379 Michael Hanselmann

671 fb0be379 Michael Hanselmann
    """
672 fb0be379 Michael Hanselmann
    return self._requested_names
673 fb0be379 Michael Hanselmann
674 4ca96421 Michael Hanselmann
  def RequestedData(self):
675 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
676 4ca96421 Michael Hanselmann

677 4ca96421 Michael Hanselmann
    @rtype: frozenset
678 4ca96421 Michael Hanselmann

679 4ca96421 Michael Hanselmann
    """
680 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
681 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
682 fb0be379 Michael Hanselmann
                      if datakind is not None))
683 4ca96421 Michael Hanselmann
684 4ca96421 Michael Hanselmann
  def GetFields(self):
685 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
686 4ca96421 Michael Hanselmann

687 4ca96421 Michael Hanselmann
    Includes unknown fields.
688 4ca96421 Michael Hanselmann

689 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
690 4ca96421 Michael Hanselmann

691 4ca96421 Michael Hanselmann
    """
692 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
693 4ca96421 Michael Hanselmann
694 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
695 4ca96421 Michael Hanselmann
    """Execute a query.
696 4ca96421 Michael Hanselmann

697 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
698 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
699 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
700 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
701 fbc263a9 Michael Hanselmann
      ordering
702 4ca96421 Michael Hanselmann

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

741 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
742 4ca96421 Michael Hanselmann

743 4ca96421 Michael Hanselmann
    """
744 111bf531 Michael Hanselmann
    unknown = set(fdef.name for (fdef, _, _, _) in self._fields
745 111bf531 Michael Hanselmann
                  if fdef.kind == QFT_UNKNOWN)
746 4ca96421 Michael Hanselmann
    if unknown:
747 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
748 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
749 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
750 4ca96421 Michael Hanselmann
751 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
752 fbc263a9 Michael Hanselmann
            for row in self.Query(ctx, sort_by_name=sort_by_name)]
753 4ca96421 Michael Hanselmann
754 4ca96421 Michael Hanselmann
755 e2d188cc Iustin Pop
def _ProcessResult(value):
756 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
757 e2d188cc Iustin Pop

758 e2d188cc Iustin Pop
  """
759 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
760 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
761 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
762 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
763 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
764 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
765 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
766 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
767 e2d188cc Iustin Pop
  else:
768 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
769 e2d188cc Iustin Pop
770 e2d188cc Iustin Pop
771 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
772 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
773 4ca96421 Michael Hanselmann

774 4ca96421 Michael Hanselmann
  @type fields: list
775 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
776 4ca96421 Michael Hanselmann
  @type row: list of tuples
777 4ca96421 Michael Hanselmann
  @param row: Row data
778 4ca96421 Michael Hanselmann

779 4ca96421 Michael Hanselmann
  """
780 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
781 d1c3c3b3 Iustin Pop
  errs = []
782 111bf531 Michael Hanselmann
  for ((status, value), (fdef, _, _, _)) in zip(row, fields):
783 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
784 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
785 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
786 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
787 d1c3c3b3 Iustin Pop
    elif value is not None:
788 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
789 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
790 34598551 Agata Murawska
                    (utils.CommaJoin(errs), row))
791 4ca96421 Michael Hanselmann
792 4ca96421 Michael Hanselmann
793 320e34df Michael Hanselmann
def _FieldDictKey((fdef, _, flags, fn)):
794 320e34df Michael Hanselmann
  """Generates key for field dictionary.
795 320e34df Michael Hanselmann

796 320e34df Michael Hanselmann
  """
797 320e34df Michael Hanselmann
  assert fdef.name and fdef.title, "Name and title are required"
798 320e34df Michael Hanselmann
  assert FIELD_NAME_RE.match(fdef.name)
799 320e34df Michael Hanselmann
  assert TITLE_RE.match(fdef.title)
800 320e34df Michael Hanselmann
  assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
801 320e34df Michael Hanselmann
          fdef.doc.strip() == fdef.doc), \
802 320e34df Michael Hanselmann
         "Invalid description for field '%s'" % fdef.name
803 320e34df Michael Hanselmann
  assert callable(fn)
804 320e34df Michael Hanselmann
  assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
805 320e34df Michael Hanselmann
806 320e34df Michael Hanselmann
  return fdef.name
807 320e34df Michael Hanselmann
808 320e34df Michael Hanselmann
809 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
810 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
811 4ca96421 Michael Hanselmann

812 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
813 4ca96421 Michael Hanselmann

814 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
815 d63bd540 Iustin Pop
      kind, retrieval function)
816 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
817 d63bd540 Iustin Pop
      description
818 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
819 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
820 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
821 4ca96421 Michael Hanselmann
  @rtype: dict
822 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
823 4ca96421 Michael Hanselmann

824 4ca96421 Michael Hanselmann
  """
825 89ce4acc Michael Hanselmann
  if __debug__:
826 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
827 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
828 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
829 4ca96421 Michael Hanselmann
830 320e34df Michael Hanselmann
  result = utils.SequenceToDict(fields, key=_FieldDictKey)
831 4ca96421 Michael Hanselmann
832 d63bd540 Iustin Pop
  for alias, target in aliases:
833 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
834 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
835 111bf531 Michael Hanselmann
    (fdef, k, flags, fn) = result[target]
836 d63bd540 Iustin Pop
    fdef = fdef.Copy()
837 d63bd540 Iustin Pop
    fdef.name = alias
838 111bf531 Michael Hanselmann
    result[alias] = (fdef, k, flags, fn)
839 d63bd540 Iustin Pop
840 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
841 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
842 111bf531 Michael Hanselmann
                    for (name, (fdef, _, _, _)) in result.items())
843 4ca96421 Michael Hanselmann
844 4ca96421 Michael Hanselmann
  return result
845 4ca96421 Michael Hanselmann
846 4ca96421 Michael Hanselmann
847 fbc263a9 Michael Hanselmann
def GetQueryResponse(query, ctx, sort_by_name=True):
848 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
849 b60fcb6f Michael Hanselmann

850 b60fcb6f Michael Hanselmann
  @type query: L{Query}
851 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
852 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
853 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
854 fbc263a9 Michael Hanselmann
    ordering
855 b60fcb6f Michael Hanselmann

856 b60fcb6f Michael Hanselmann
  """
857 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
858 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
859 b60fcb6f Michael Hanselmann
860 b60fcb6f Michael Hanselmann
861 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
862 aa29e95f Michael Hanselmann
  """Returns list of available fields.
863 aa29e95f Michael Hanselmann

864 aa29e95f Michael Hanselmann
  @type fielddefs: dict
865 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
866 aa29e95f Michael Hanselmann
  @type selected: list of strings
867 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
868 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
869 aa29e95f Michael Hanselmann

870 aa29e95f Michael Hanselmann
  """
871 aa29e95f Michael Hanselmann
  if selected is None:
872 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
873 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
874 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
875 aa29e95f Michael Hanselmann
  else:
876 aa29e95f Michael Hanselmann
    # Keep order as requested by client
877 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
878 aa29e95f Michael Hanselmann
879 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
880 aa29e95f Michael Hanselmann
881 aa29e95f Michael Hanselmann
882 79b2ca83 Michael Hanselmann
def _MakeField(name, title, kind, doc):
883 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
884 4ca96421 Michael Hanselmann

885 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
886 4ca96421 Michael Hanselmann
  @param title: Human-readable title
887 4ca96421 Michael Hanselmann
  @param kind: Field type
888 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
889 4ca96421 Michael Hanselmann

890 4ca96421 Michael Hanselmann
  """
891 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
892 1ae17369 Michael Hanselmann
                                      doc=doc)
893 8235fe04 Michael Hanselmann
894 8235fe04 Michael Hanselmann
895 dff5f600 Michael Hanselmann
def _StaticValueInner(value, ctx, _): # pylint: disable=W0613
896 dff5f600 Michael Hanselmann
  """Returns a static value.
897 dff5f600 Michael Hanselmann

898 dff5f600 Michael Hanselmann
  """
899 dff5f600 Michael Hanselmann
  return value
900 dff5f600 Michael Hanselmann
901 dff5f600 Michael Hanselmann
902 dff5f600 Michael Hanselmann
def _StaticValue(value):
903 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
904 dff5f600 Michael Hanselmann

905 dff5f600 Michael Hanselmann
  """
906 dff5f600 Michael Hanselmann
  return compat.partial(_StaticValueInner, value)
907 dff5f600 Michael Hanselmann
908 dff5f600 Michael Hanselmann
909 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
910 8235fe04 Michael Hanselmann
  """Determine node role.
911 8235fe04 Michael Hanselmann

912 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
913 8235fe04 Michael Hanselmann
  @param node: Node object
914 8235fe04 Michael Hanselmann
  @type master_name: string
915 8235fe04 Michael Hanselmann
  @param master_name: Master node name
916 8235fe04 Michael Hanselmann

917 8235fe04 Michael Hanselmann
  """
918 8235fe04 Michael Hanselmann
  if node.name == master_name:
919 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
920 8235fe04 Michael Hanselmann
  elif node.master_candidate:
921 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
922 8235fe04 Michael Hanselmann
  elif node.drained:
923 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
924 8235fe04 Michael Hanselmann
  elif node.offline:
925 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
926 8235fe04 Michael Hanselmann
  else:
927 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
928 8235fe04 Michael Hanselmann
929 8235fe04 Michael Hanselmann
930 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
931 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
932 8235fe04 Michael Hanselmann

933 8235fe04 Michael Hanselmann
  @param attr: Attribute name
934 8235fe04 Michael Hanselmann

935 8235fe04 Michael Hanselmann
  """
936 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
937 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
938 8235fe04 Michael Hanselmann
939 8235fe04 Michael Hanselmann
940 8930b0f0 Iustin Pop
def _GetNDParam(name):
941 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
942 8930b0f0 Iustin Pop

943 8930b0f0 Iustin Pop
  """
944 8930b0f0 Iustin Pop
  def _helper(ctx, _):
945 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
946 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
947 8930b0f0 Iustin Pop
    else:
948 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
949 8930b0f0 Iustin Pop
  return _helper
950 8930b0f0 Iustin Pop
951 8930b0f0 Iustin Pop
952 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
953 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
954 8930b0f0 Iustin Pop

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

957 8930b0f0 Iustin Pop
  """
958 8930b0f0 Iustin Pop
  if is_group:
959 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
960 8930b0f0 Iustin Pop
  else:
961 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
962 8930b0f0 Iustin Pop
  return [(_MakeField("ndp/%s" % name, NDP_TITLE.get(name, "ndp/%s" % name),
963 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
964 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
965 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
966 8930b0f0 Iustin Pop
967 8930b0f0 Iustin Pop
968 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
969 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
970 425e5bf0 Michael Hanselmann

971 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
972 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
973 425e5bf0 Michael Hanselmann

974 425e5bf0 Michael Hanselmann
  """
975 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
976 425e5bf0 Michael Hanselmann
977 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
978 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
979 425e5bf0 Michael Hanselmann
    # Return right away
980 425e5bf0 Michael Hanselmann
    return value
981 425e5bf0 Michael Hanselmann
982 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
983 425e5bf0 Michael Hanselmann
  return convert(value)
984 425e5bf0 Michael Hanselmann
985 425e5bf0 Michael Hanselmann
986 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
987 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
988 425e5bf0 Michael Hanselmann

989 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
990 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
991 425e5bf0 Michael Hanselmann

992 425e5bf0 Michael Hanselmann
  """
993 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
994 425e5bf0 Michael Hanselmann
995 425e5bf0 Michael Hanselmann
996 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
997 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
998 145bea54 Michael Hanselmann

999 145bea54 Michael Hanselmann
  @type getter: callable
1000 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1001 145bea54 Michael Hanselmann

1002 145bea54 Michael Hanselmann
  """
1003 145bea54 Michael Hanselmann
  def fn(_, item):
1004 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1005 145bea54 Michael Hanselmann

1006 145bea54 Michael Hanselmann
    """
1007 145bea54 Michael Hanselmann
    timestamp = getter(item)
1008 145bea54 Michael Hanselmann
    if timestamp is None:
1009 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
1010 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1011 145bea54 Michael Hanselmann
    else:
1012 e2d188cc Iustin Pop
      return timestamp
1013 145bea54 Michael Hanselmann
1014 145bea54 Michael Hanselmann
  return fn
1015 145bea54 Michael Hanselmann
1016 145bea54 Michael Hanselmann
1017 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
1018 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
1019 145bea54 Michael Hanselmann

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

1022 145bea54 Michael Hanselmann
  """
1023 145bea54 Michael Hanselmann
  return [
1024 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
1025 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
1026 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
1027 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
1028 145bea54 Michael Hanselmann
    ]
1029 145bea54 Michael Hanselmann
1030 145bea54 Michael Hanselmann
1031 8235fe04 Michael Hanselmann
class NodeQueryData:
1032 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1033 8235fe04 Michael Hanselmann

1034 8235fe04 Michael Hanselmann
  """
1035 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1036 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1037 8235fe04 Michael Hanselmann
    """Initializes this class.
1038 8235fe04 Michael Hanselmann

1039 8235fe04 Michael Hanselmann
    """
1040 8235fe04 Michael Hanselmann
    self.nodes = nodes
1041 8235fe04 Michael Hanselmann
    self.live_data = live_data
1042 8235fe04 Michael Hanselmann
    self.master_name = master_name
1043 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1044 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1045 8235fe04 Michael Hanselmann
    self.groups = groups
1046 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1047 8572f1fe René Nussbaumer
    self.cluster = cluster
1048 8235fe04 Michael Hanselmann
1049 8235fe04 Michael Hanselmann
    # Used for individual rows
1050 8235fe04 Michael Hanselmann
    self.curlive_data = None
1051 8930b0f0 Iustin Pop
    self.ndparams = None
1052 8235fe04 Michael Hanselmann
1053 8235fe04 Michael Hanselmann
  def __iter__(self):
1054 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1055 8235fe04 Michael Hanselmann

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

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

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

1118 8572f1fe René Nussbaumer
  """
1119 8572f1fe René Nussbaumer
  def fn(ctx, node):
1120 8572f1fe René Nussbaumer
    """Get group data for a node.
1121 8572f1fe René Nussbaumer

1122 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1123 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1124 8572f1fe René Nussbaumer
    @param inst: Node object
1125 8572f1fe René Nussbaumer

1126 8572f1fe René Nussbaumer
    """
1127 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1128 8572f1fe René Nussbaumer
    if ng is None:
1129 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1130 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1131 8572f1fe René Nussbaumer
1132 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1133 8572f1fe René Nussbaumer
1134 8572f1fe René Nussbaumer
  return fn
1135 8572f1fe René Nussbaumer
1136 8572f1fe René Nussbaumer
1137 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1138 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1139 8235fe04 Michael Hanselmann

1140 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1141 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1142 8235fe04 Michael Hanselmann
  @param node: Node object
1143 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1144 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1145 8235fe04 Michael Hanselmann

1146 8235fe04 Michael Hanselmann
  """
1147 e2d188cc Iustin Pop
  return ng.name
1148 8235fe04 Michael Hanselmann
1149 8235fe04 Michael Hanselmann
1150 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1151 52b5d286 René Nussbaumer
  """Returns the node powered state
1152 52b5d286 René Nussbaumer

1153 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1154 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1155 52b5d286 René Nussbaumer
  @param node: Node object
1156 52b5d286 René Nussbaumer

1157 52b5d286 René Nussbaumer
  """
1158 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1159 e2d188cc Iustin Pop
    return node.powered
1160 52b5d286 René Nussbaumer
1161 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1162 52b5d286 René Nussbaumer
1163 52b5d286 René Nussbaumer
1164 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1165 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1166 8572f1fe René Nussbaumer

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

1173 8572f1fe René Nussbaumer
  """
1174 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1175 8572f1fe René Nussbaumer
1176 8572f1fe René Nussbaumer
1177 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1178 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1179 8235fe04 Michael Hanselmann

1180 8235fe04 Michael Hanselmann
  @param field: Live field name
1181 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1182 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1183 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1184 a6070ef7 Michael Hanselmann
  @param node: Node object
1185 8235fe04 Michael Hanselmann

1186 8235fe04 Michael Hanselmann
  """
1187 a6070ef7 Michael Hanselmann
  if node.offline:
1188 e2d188cc Iustin Pop
    return _FS_OFFLINE
1189 a6070ef7 Michael Hanselmann
1190 effab4ca Iustin Pop
  if not node.vm_capable:
1191 effab4ca Iustin Pop
    return _FS_UNAVAIL
1192 effab4ca Iustin Pop
1193 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1194 e2d188cc Iustin Pop
    return _FS_NODATA
1195 8235fe04 Michael Hanselmann
1196 8235fe04 Michael Hanselmann
  try:
1197 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1198 8235fe04 Michael Hanselmann
  except KeyError:
1199 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1200 8235fe04 Michael Hanselmann
1201 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1202 e2d188cc Iustin Pop
    return value
1203 8235fe04 Michael Hanselmann
1204 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1205 8235fe04 Michael Hanselmann
1206 8235fe04 Michael Hanselmann
  # Try to convert into number
1207 8235fe04 Michael Hanselmann
  try:
1208 e2d188cc Iustin Pop
    return int(value)
1209 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1210 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1211 8235fe04 Michael Hanselmann
                      value, field)
1212 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1213 8235fe04 Michael Hanselmann
1214 8235fe04 Michael Hanselmann
1215 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1216 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1217 54ac87c0 Michael Hanselmann

1218 54ac87c0 Michael Hanselmann
  """
1219 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1220 54ac87c0 Michael Hanselmann
1221 54ac87c0 Michael Hanselmann
  if hv_state is None:
1222 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1223 54ac87c0 Michael Hanselmann
1224 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1225 54ac87c0 Michael Hanselmann
1226 54ac87c0 Michael Hanselmann
1227 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1228 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1229 54ac87c0 Michael Hanselmann

1230 54ac87c0 Michael Hanselmann
  """
1231 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1232 54ac87c0 Michael Hanselmann
1233 54ac87c0 Michael Hanselmann
  if disk_state is None:
1234 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1235 54ac87c0 Michael Hanselmann
1236 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1237 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1238 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1239 54ac87c0 Michael Hanselmann
1240 54ac87c0 Michael Hanselmann
1241 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1242 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1243 8235fe04 Michael Hanselmann

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

1329 1c8addc6 Michael Hanselmann
  """
1330 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1331 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1332 1c8addc6 Michael Hanselmann
    """Initializes this class.
1333 1c8addc6 Michael Hanselmann

1334 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1335 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1336 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1337 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1338 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1339 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1340 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1341 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1342 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1343 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1344 e431074f René Nussbaumer
    @type wrongnode_inst: set
1345 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1346 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1347 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1348 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1349 fab9573b Michael Hanselmann
    @param nodes: Node objects
1350 1c8addc6 Michael Hanselmann

1351 1c8addc6 Michael Hanselmann
    """
1352 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1353 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1354 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1355 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1356 1c8addc6 Michael Hanselmann
1357 1c8addc6 Michael Hanselmann
    self.instances = instances
1358 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1359 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1360 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1361 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1362 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1363 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1364 5d28cb6f Michael Hanselmann
    self.console = console
1365 fab9573b Michael Hanselmann
    self.nodes = nodes
1366 fab9573b Michael Hanselmann
    self.groups = groups
1367 1c8addc6 Michael Hanselmann
1368 1c8addc6 Michael Hanselmann
    # Used for individual rows
1369 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1370 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1371 7c670076 Michael Hanselmann
    self.inst_osparams = None
1372 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1373 1c8addc6 Michael Hanselmann
1374 1c8addc6 Michael Hanselmann
  def __iter__(self):
1375 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1376 1c8addc6 Michael Hanselmann

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

1380 1c8addc6 Michael Hanselmann
    """
1381 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1382 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1383 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1384 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1385 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1386 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1387 1c8addc6 Michael Hanselmann
1388 1c8addc6 Michael Hanselmann
      yield inst
1389 1c8addc6 Michael Hanselmann
1390 1c8addc6 Michael Hanselmann
1391 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1392 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1393 1c8addc6 Michael Hanselmann

1394 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1395 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1396 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1397 1c8addc6 Michael Hanselmann

1398 1c8addc6 Michael Hanselmann
  """
1399 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1400 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1401 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1402 e2d188cc Iustin Pop
    return _FS_NODATA
1403 1c8addc6 Michael Hanselmann
  else:
1404 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1405 1c8addc6 Michael Hanselmann
1406 1c8addc6 Michael Hanselmann
1407 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1408 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1409 1c8addc6 Michael Hanselmann

1410 1c8addc6 Michael Hanselmann
  @type name: string
1411 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1412 1c8addc6 Michael Hanselmann

1413 1c8addc6 Michael Hanselmann
  """
1414 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1415 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1416 1c8addc6 Michael Hanselmann

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

1421 1c8addc6 Michael Hanselmann
    """
1422 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1423 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1424 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1425 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1426 e2d188cc Iustin Pop
      return _FS_NODATA
1427 1c8addc6 Michael Hanselmann
1428 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1429 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1430 1c8addc6 Michael Hanselmann
      if name in data:
1431 e2d188cc Iustin Pop
        return data[name]
1432 1c8addc6 Michael Hanselmann
1433 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1434 1c8addc6 Michael Hanselmann
1435 1c8addc6 Michael Hanselmann
  return fn
1436 1c8addc6 Michael Hanselmann
1437 1c8addc6 Michael Hanselmann
1438 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1439 1c8addc6 Michael Hanselmann
  """Get instance status.
1440 1c8addc6 Michael Hanselmann

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

1445 1c8addc6 Michael Hanselmann
  """
1446 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1447 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1448 1c8addc6 Michael Hanselmann
1449 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1450 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1451 1c8addc6 Michael Hanselmann
1452 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1453 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1454 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1455 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1456 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1457 1c8addc6 Michael Hanselmann
    else:
1458 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1459 1c8addc6 Michael Hanselmann
1460 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1461 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1462 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1463 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1464 1c8addc6 Michael Hanselmann
1465 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1466 1c8addc6 Michael Hanselmann
1467 1c8addc6 Michael Hanselmann
1468 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1469 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1470 1c8addc6 Michael Hanselmann

1471 1c8addc6 Michael Hanselmann
  @type index: int
1472 1c8addc6 Michael Hanselmann
  @param index: Disk index
1473 1c8addc6 Michael Hanselmann

1474 1c8addc6 Michael Hanselmann
  """
1475 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1476 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1477 1c8addc6 Michael Hanselmann

1478 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1479 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1480 1c8addc6 Michael Hanselmann

1481 1c8addc6 Michael Hanselmann
    """
1482 1c8addc6 Michael Hanselmann
    try:
1483 e2d188cc Iustin Pop
      return inst.disks[index].size
1484 1c8addc6 Michael Hanselmann
    except IndexError:
1485 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1486 1c8addc6 Michael Hanselmann
1487 1c8addc6 Michael Hanselmann
  return fn
1488 1c8addc6 Michael Hanselmann
1489 1c8addc6 Michael Hanselmann
1490 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1491 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1492 1c8addc6 Michael Hanselmann

1493 1c8addc6 Michael Hanselmann
  @type index: int
1494 1c8addc6 Michael Hanselmann
  @param index: NIC index
1495 1c8addc6 Michael Hanselmann
  @type cb: callable
1496 1c8addc6 Michael Hanselmann
  @param cb: Callback
1497 1c8addc6 Michael Hanselmann

1498 1c8addc6 Michael Hanselmann
  """
1499 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1500 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1501 1c8addc6 Michael Hanselmann

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

1506 1c8addc6 Michael Hanselmann
    """
1507 1c8addc6 Michael Hanselmann
    try:
1508 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1509 1c8addc6 Michael Hanselmann
    except IndexError:
1510 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1511 1c8addc6 Michael Hanselmann
1512 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1513 1c8addc6 Michael Hanselmann
1514 1c8addc6 Michael Hanselmann
  return fn
1515 1c8addc6 Michael Hanselmann
1516 1c8addc6 Michael Hanselmann
1517 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1518 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1519 1c8addc6 Michael Hanselmann

1520 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1521 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1522 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1523 1c8addc6 Michael Hanselmann

1524 1c8addc6 Michael Hanselmann
  """
1525 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1526 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1527 1c8addc6 Michael Hanselmann
  else:
1528 e2d188cc Iustin Pop
    return nic.ip
1529 1c8addc6 Michael Hanselmann
1530 1c8addc6 Michael Hanselmann
1531 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1532 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1533 1c8addc6 Michael Hanselmann

1534 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1535 1c8addc6 Michael Hanselmann
  @type index: int
1536 1c8addc6 Michael Hanselmann
  @param index: NIC index
1537 1c8addc6 Michael Hanselmann

1538 1c8addc6 Michael Hanselmann
  """
1539 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1540 1c8addc6 Michael Hanselmann
1541 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1542 1c8addc6 Michael Hanselmann
1543 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1544 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1545 1c8addc6 Michael Hanselmann
  else:
1546 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1547 1c8addc6 Michael Hanselmann
1548 1c8addc6 Michael Hanselmann
1549 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1550 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1551 1c8addc6 Michael Hanselmann

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

1556 1c8addc6 Michael Hanselmann
  """
1557 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1558 1c8addc6 Michael Hanselmann
1559 1c8addc6 Michael Hanselmann
  result = []
1560 1c8addc6 Michael Hanselmann
1561 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1562 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1563 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1564 1c8addc6 Michael Hanselmann
    else:
1565 1c8addc6 Michael Hanselmann
      result.append(None)
1566 1c8addc6 Michael Hanselmann
1567 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1568 1c8addc6 Michael Hanselmann
1569 e2d188cc Iustin Pop
  return result
1570 1c8addc6 Michael Hanselmann
1571 1c8addc6 Michael Hanselmann
1572 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1573 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1574 1c8addc6 Michael Hanselmann

1575 1c8addc6 Michael Hanselmann
  @type name: string
1576 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1577 1c8addc6 Michael Hanselmann

1578 1c8addc6 Michael Hanselmann
  """
1579 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1580 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1581 1c8addc6 Michael Hanselmann

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

1588 1c8addc6 Michael Hanselmann
    """
1589 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1590 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1591 1c8addc6 Michael Hanselmann
1592 1c8addc6 Michael Hanselmann
  return fn
1593 1c8addc6 Michael Hanselmann
1594 1c8addc6 Michael Hanselmann
1595 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1596 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1597 1c8addc6 Michael Hanselmann

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

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

1666 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1667 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1668 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1669 1c8addc6 Michael Hanselmann

1670 1c8addc6 Michael Hanselmann
  """
1671 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1672 1c8addc6 Michael Hanselmann
1673 1c8addc6 Michael Hanselmann
  if usage is None:
1674 1c8addc6 Michael Hanselmann
    usage = 0
1675 1c8addc6 Michael Hanselmann
1676 e2d188cc Iustin Pop
  return usage
1677 1c8addc6 Michael Hanselmann
1678 1c8addc6 Michael Hanselmann
1679 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1680 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1681 5d28cb6f Michael Hanselmann

1682 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1683 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1684 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1685 5d28cb6f Michael Hanselmann

1686 5d28cb6f Michael Hanselmann
  """
1687 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1688 5d28cb6f Michael Hanselmann
1689 5d28cb6f Michael Hanselmann
  if consinfo is None:
1690 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1691 5d28cb6f Michael Hanselmann
1692 5d28cb6f Michael Hanselmann
  return consinfo
1693 5d28cb6f Michael Hanselmann
1694 5d28cb6f Michael Hanselmann
1695 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1696 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1697 1c8addc6 Michael Hanselmann

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

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

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

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

1819 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1820 fab9573b Michael Hanselmann
  @param default: Default value
1821 fab9573b Michael Hanselmann
  @type node_name: string
1822 fab9573b Michael Hanselmann
  @param node_name: Node name
1823 fab9573b Michael Hanselmann

1824 fab9573b Michael Hanselmann
  """
1825 fab9573b Michael Hanselmann
  try:
1826 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1827 fab9573b Michael Hanselmann
  except KeyError:
1828 fab9573b Michael Hanselmann
    return default
1829 fab9573b Michael Hanselmann
  else:
1830 fab9573b Michael Hanselmann
    return node.group
1831 fab9573b Michael Hanselmann
1832 fab9573b Michael Hanselmann
1833 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1834 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1835 fab9573b Michael Hanselmann

1836 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1837 fab9573b Michael Hanselmann
  @param default: Default value
1838 fab9573b Michael Hanselmann
  @type node_name: string
1839 fab9573b Michael Hanselmann
  @param node_name: Node name
1840 fab9573b Michael Hanselmann

1841 fab9573b Michael Hanselmann
  """
1842 fab9573b Michael Hanselmann
  try:
1843 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1844 fab9573b Michael Hanselmann
  except KeyError:
1845 fab9573b Michael Hanselmann
    return default
1846 fab9573b Michael Hanselmann
1847 fab9573b Michael Hanselmann
  try:
1848 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1849 fab9573b Michael Hanselmann
  except KeyError:
1850 fab9573b Michael Hanselmann
    return default
1851 fab9573b Michael Hanselmann
1852 fab9573b Michael Hanselmann
  return group.name
1853 fab9573b Michael Hanselmann
1854 fab9573b Michael Hanselmann
1855 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1856 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1857 1c8addc6 Michael Hanselmann

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

1955 24d16f76 Michael Hanselmann
  """
1956 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1957 24d16f76 Michael Hanselmann
    """Initializes this class.
1958 24d16f76 Michael Hanselmann

1959 24d16f76 Michael Hanselmann
    """
1960 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1961 24d16f76 Michael Hanselmann
1962 24d16f76 Michael Hanselmann
  def __iter__(self):
1963 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1964 24d16f76 Michael Hanselmann

1965 24d16f76 Michael Hanselmann
    """
1966 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1967 24d16f76 Michael Hanselmann
1968 24d16f76 Michael Hanselmann
1969 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1970 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1971 24d16f76 Michael Hanselmann

1972 24d16f76 Michael Hanselmann
  """
1973 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1974 24d16f76 Michael Hanselmann
1975 24d16f76 Michael Hanselmann
  if owners:
1976 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1977 24d16f76 Michael Hanselmann
1978 e2d188cc Iustin Pop
  return owners
1979 24d16f76 Michael Hanselmann
1980 24d16f76 Michael Hanselmann
1981 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1982 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1983 24d16f76 Michael Hanselmann

1984 24d16f76 Michael Hanselmann
  """
1985 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1986 24d16f76 Michael Hanselmann
1987 24d16f76 Michael Hanselmann
  if pending:
1988 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1989 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1990 24d16f76 Michael Hanselmann
1991 e2d188cc Iustin Pop
  return pending
1992 24d16f76 Michael Hanselmann
1993 24d16f76 Michael Hanselmann
1994 24d16f76 Michael Hanselmann
def _BuildLockFields():
1995 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1996 24d16f76 Michael Hanselmann

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

2017 8e21cfc0 Adeodato Simo
  """
2018 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2019 2c758845 René Nussbaumer
               want_diskparams):
2020 8e21cfc0 Adeodato Simo
    """Initializes this class.
2021 8e21cfc0 Adeodato Simo

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

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

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

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

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

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

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

2189 9665bb3a Michael Hanselmann
  """
2190 9665bb3a Michael Hanselmann
  if job is None:
2191 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2192 9665bb3a Michael Hanselmann
  else:
2193 9665bb3a Michael Hanselmann
    return fn(job)
2194 9665bb3a Michael Hanselmann
2195 9665bb3a Michael Hanselmann
2196 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2197 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2198 9665bb3a Michael Hanselmann

2199 9665bb3a Michael Hanselmann
  """
2200 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2201 9665bb3a Michael Hanselmann
2202 9665bb3a Michael Hanselmann
2203 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2204 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2205 9665bb3a Michael Hanselmann

2206 9665bb3a Michael Hanselmann
  """
2207 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2208 9665bb3a Michael Hanselmann
2209 9665bb3a Michael Hanselmann
2210 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2211 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2212 9665bb3a Michael Hanselmann

2213 9665bb3a Michael Hanselmann
  """
2214 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2215 9665bb3a Michael Hanselmann
2216 9665bb3a Michael Hanselmann
2217 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2218 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2219 9665bb3a Michael Hanselmann

2220 9665bb3a Michael Hanselmann
  """
2221 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2222 9665bb3a Michael Hanselmann
2223 9665bb3a Michael Hanselmann
  if timestamp is None:
2224 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2225 9665bb3a Michael Hanselmann
  else:
2226 9665bb3a Michael Hanselmann
    return timestamp
2227 9665bb3a Michael Hanselmann
2228 9665bb3a Michael Hanselmann
2229 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2230 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2231 9665bb3a Michael Hanselmann

2232 9665bb3a Michael Hanselmann
  """
2233 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2234 9665bb3a Michael Hanselmann
2235 9665bb3a Michael Hanselmann
2236 9665bb3a Michael Hanselmann
def _BuildJobFields():
2237 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2238 9665bb3a Michael Hanselmann

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

2293 0fdf247d Michael Hanselmann
  """
2294 0fdf247d Michael Hanselmann
  if expname is None:
2295 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2296 0fdf247d Michael Hanselmann
  else:
2297 0fdf247d Michael Hanselmann
    return expname
2298 0fdf247d Michael Hanselmann
2299 0fdf247d Michael Hanselmann
2300 0fdf247d Michael Hanselmann
def _BuildExportFields():
2301 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2302 0fdf247d Michael Hanselmann

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

2340 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2341 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2342 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2343 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2344 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2345 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2346 dff5f600 Michael Hanselmann

2347 dff5f600 Michael Hanselmann
    """
2348 dff5f600 Michael Hanselmann
    self._cluster = cluster
2349 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2350 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2351 dff5f600 Michael Hanselmann
2352 dff5f600 Michael Hanselmann
  def __iter__(self):
2353 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2354 dff5f600 Michael Hanselmann
2355 dff5f600 Michael Hanselmann
2356 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2357 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2358 dff5f600 Michael Hanselmann

2359 dff5f600 Michael Hanselmann
  """
2360 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2361 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2362 dff5f600 Michael Hanselmann
  else:
2363 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2364 dff5f600 Michael Hanselmann
2365 dff5f600 Michael Hanselmann
2366 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2367 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2368 dff5f600 Michael Hanselmann

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