Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 769b0bde

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2004 8e21cfc0 Adeodato Simo
  """
2005 edd49f9b Agata Murawska
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances):
2006 8e21cfc0 Adeodato Simo
    """Initializes this class.
2007 8e21cfc0 Adeodato Simo

2008 edd49f9b Agata Murawska
    @param cluster: Cluster object
2009 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2010 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2011 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2012 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2013 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2014 8e21cfc0 Adeodato Simo

2015 8e21cfc0 Adeodato Simo
    """
2016 8e21cfc0 Adeodato Simo
    self.groups = groups
2017 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2018 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2019 edd49f9b Agata Murawska
    self.cluster = cluster
2020 edd49f9b Agata Murawska
2021 edd49f9b Agata Murawska
    # Used for individual rows
2022 edd49f9b Agata Murawska
    self.group_ipolicy = None
2023 8930b0f0 Iustin Pop
    self.ndparams = None
2024 8e21cfc0 Adeodato Simo
2025 8e21cfc0 Adeodato Simo
  def __iter__(self):
2026 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2027 8e21cfc0 Adeodato Simo

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

2031 8e21cfc0 Adeodato Simo
    """
2032 edd49f9b Agata Murawska
    for group in self.groups:
2033 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2034 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2035 edd49f9b Agata Murawska
      yield group
2036 8e21cfc0 Adeodato Simo
2037 8e21cfc0 Adeodato Simo
2038 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2039 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2040 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2041 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2042 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2043 8e21cfc0 Adeodato Simo
  }
2044 8e21cfc0 Adeodato Simo
2045 8e21cfc0 Adeodato Simo
2046 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2047 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2048 8e21cfc0 Adeodato Simo

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

2124 be3a4b14 Michael Hanselmann
  """
2125 be3a4b14 Michael Hanselmann
  fields = [
2126 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2127 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2128 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2129 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2130 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2131 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2132 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2133 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2134 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2135 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2136 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2137 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2138 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2139 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2140 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2141 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2142 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2143 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2144 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2145 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2146 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2147 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2148 be3a4b14 Michael Hanselmann
                "Status from node"),
2149 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2150 be3a4b14 Michael Hanselmann
    ]
2151 be3a4b14 Michael Hanselmann
2152 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2153 be3a4b14 Michael Hanselmann
2154 be3a4b14 Michael Hanselmann
2155 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2156 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2157 9665bb3a Michael Hanselmann

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

2161 9665bb3a Michael Hanselmann
  """
2162 9665bb3a Michael Hanselmann
  if job is None:
2163 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2164 9665bb3a Michael Hanselmann
  else:
2165 9665bb3a Michael Hanselmann
    return fn(job)
2166 9665bb3a Michael Hanselmann
2167 9665bb3a Michael Hanselmann
2168 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2169 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2170 9665bb3a Michael Hanselmann

2171 9665bb3a Michael Hanselmann
  """
2172 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2173 9665bb3a Michael Hanselmann
2174 9665bb3a Michael Hanselmann
2175 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2176 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2177 9665bb3a Michael Hanselmann

2178 9665bb3a Michael Hanselmann
  """
2179 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2180 9665bb3a Michael Hanselmann
2181 9665bb3a Michael Hanselmann
2182 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2183 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2184 9665bb3a Michael Hanselmann

2185 9665bb3a Michael Hanselmann
  """
2186 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2187 9665bb3a Michael Hanselmann
2188 9665bb3a Michael Hanselmann
2189 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2190 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2191 9665bb3a Michael Hanselmann

2192 9665bb3a Michael Hanselmann
  """
2193 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2194 9665bb3a Michael Hanselmann
2195 9665bb3a Michael Hanselmann
  if timestamp is None:
2196 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2197 9665bb3a Michael Hanselmann
  else:
2198 9665bb3a Michael Hanselmann
    return timestamp
2199 9665bb3a Michael Hanselmann
2200 9665bb3a Michael Hanselmann
2201 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2202 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2203 9665bb3a Michael Hanselmann

2204 9665bb3a Michael Hanselmann
  """
2205 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2206 9665bb3a Michael Hanselmann
2207 9665bb3a Michael Hanselmann
2208 9665bb3a Michael Hanselmann
def _BuildJobFields():
2209 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2210 9665bb3a Michael Hanselmann

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

2265 0fdf247d Michael Hanselmann
  """
2266 0fdf247d Michael Hanselmann
  if expname is None:
2267 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2268 0fdf247d Michael Hanselmann
  else:
2269 0fdf247d Michael Hanselmann
    return expname
2270 0fdf247d Michael Hanselmann
2271 0fdf247d Michael Hanselmann
2272 0fdf247d Michael Hanselmann
def _BuildExportFields():
2273 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2274 0fdf247d Michael Hanselmann

2275 0fdf247d Michael Hanselmann
  """
2276 0fdf247d Michael Hanselmann
  fields = [
2277 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2278 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2279 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2280 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2281 0fdf247d Michael Hanselmann
    ]
2282 0fdf247d Michael Hanselmann
2283 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2284 0fdf247d Michael Hanselmann
2285 0fdf247d Michael Hanselmann
2286 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2287 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2288 dff5f600 Michael Hanselmann
                       "Software version"),
2289 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2290 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2291 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2292 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2293 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2294 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2295 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2296 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2297 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2298 dff5f600 Michael Hanselmann
  }
2299 dff5f600 Michael Hanselmann
2300 dff5f600 Michael Hanselmann
2301 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2302 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2303 dff5f600 Michael Hanselmann
  "master_node": ("Master", QFT_TEXT, QFF_HOSTNAME, "Master node name"),
2304 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2305 dff5f600 Michael Hanselmann
  }
2306 dff5f600 Michael Hanselmann
2307 dff5f600 Michael Hanselmann
2308 dff5f600 Michael Hanselmann
class ClusterQueryData:
2309 dff5f600 Michael Hanselmann
  def __init__(self, cluster, drain_flag, watcher_pause):
2310 dff5f600 Michael Hanselmann
    """Initializes this class.
2311 dff5f600 Michael Hanselmann

2312 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2313 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2314 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2315 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2316 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2317 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2318 dff5f600 Michael Hanselmann

2319 dff5f600 Michael Hanselmann
    """
2320 dff5f600 Michael Hanselmann
    self._cluster = cluster
2321 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2322 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2323 dff5f600 Michael Hanselmann
2324 dff5f600 Michael Hanselmann
  def __iter__(self):
2325 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2326 dff5f600 Michael Hanselmann
2327 dff5f600 Michael Hanselmann
2328 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2329 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2330 dff5f600 Michael Hanselmann

2331 dff5f600 Michael Hanselmann
  """
2332 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2333 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2334 dff5f600 Michael Hanselmann
  else:
2335 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2336 dff5f600 Michael Hanselmann
2337 dff5f600 Michael Hanselmann
2338 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2339 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2340 dff5f600 Michael Hanselmann

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