Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 63b4bb1e

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

149 4ca96421 Michael Hanselmann
  """
150 e2d188cc Iustin Pop
  return _FS_UNKNOWN
151 4ca96421 Michael Hanselmann
152 4ca96421 Michael Hanselmann
153 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
154 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
155 4ca96421 Michael Hanselmann

156 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
157 4ca96421 Michael Hanselmann

158 4ca96421 Michael Hanselmann
  @type fielddefs: dict
159 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
160 4ca96421 Michael Hanselmann
  @type selected: list of strings
161 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
162 4ca96421 Michael Hanselmann

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

183 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
184 4ca96421 Michael Hanselmann

185 4ca96421 Michael Hanselmann
  """
186 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
187 4ca96421 Michael Hanselmann
188 4ca96421 Michael Hanselmann
189 fb0be379 Michael Hanselmann
class _FilterHints:
190 fb0be379 Michael Hanselmann
  """Class for filter analytics.
191 fb0be379 Michael Hanselmann

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

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

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

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

212 fb0be379 Michael Hanselmann
  """
213 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
214 fb0be379 Michael Hanselmann
    """Initializes this class.
215 fb0be379 Michael Hanselmann

216 fb0be379 Michael Hanselmann
    @type namefield: string
217 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
218 fb0be379 Michael Hanselmann

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

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

238 fb0be379 Michael Hanselmann
    @rtype: list
239 fb0be379 Michael Hanselmann

240 fb0be379 Michael Hanselmann
    """
241 fb0be379 Michael Hanselmann
    if self._allnames or self._names is None:
242 fb0be379 Michael Hanselmann
      return None
243 fb0be379 Michael Hanselmann
244 fb0be379 Michael Hanselmann
    return utils.UniqueSequence(self._names)
245 fb0be379 Michael Hanselmann
246 fb0be379 Michael Hanselmann
  def ReferencedData(self):
247 fb0be379 Michael Hanselmann
    """Returns all kinds of data referenced by the filter.
248 fb0be379 Michael Hanselmann

249 fb0be379 Michael Hanselmann
    """
250 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
251 fb0be379 Michael Hanselmann
252 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
253 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
254 fb0be379 Michael Hanselmann

255 fb0be379 Michael Hanselmann
    """
256 fb0be379 Michael Hanselmann
    self._allnames = True
257 fb0be379 Michael Hanselmann
    self._names = None
258 fb0be379 Michael Hanselmann
259 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
260 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
261 fb0be379 Michael Hanselmann

262 fb0be379 Michael Hanselmann
    @type op: string
263 fb0be379 Michael Hanselmann
    @param op: Operator
264 fb0be379 Michael Hanselmann

265 fb0be379 Michael Hanselmann
    """
266 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
267 fb0be379 Michael Hanselmann
      self._NeedAllNames()
268 fb0be379 Michael Hanselmann
269 b459a848 Andrea Spadaccini
  def NoteUnaryOp(self, op): # pylint: disable=W0613
270 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
271 fb0be379 Michael Hanselmann

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

275 fb0be379 Michael Hanselmann
    """
276 fb0be379 Michael Hanselmann
    self._NeedAllNames()
277 fb0be379 Michael Hanselmann
278 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
279 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
280 fb0be379 Michael Hanselmann

281 fb0be379 Michael Hanselmann
    @type op: string
282 fb0be379 Michael Hanselmann
    @param op: Operator
283 fb0be379 Michael Hanselmann
    @type name: string
284 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
285 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
286 fb0be379 Michael Hanselmann

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

307 fb0be379 Michael Hanselmann
  """
308 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
309 fb0be379 Michael Hanselmann
310 fb0be379 Michael Hanselmann
311 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
312 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
313 fb0be379 Michael Hanselmann

314 fb0be379 Michael Hanselmann
  """
315 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
316 fb0be379 Michael Hanselmann
317 fb0be379 Michael Hanselmann
318 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
319 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
320 fb0be379 Michael Hanselmann

321 fb0be379 Michael Hanselmann
  """
322 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
323 fb0be379 Michael Hanselmann
324 fb0be379 Michael Hanselmann
325 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
326 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
327 fb0be379 Michael Hanselmann

328 fb0be379 Michael Hanselmann
  """
329 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
330 fb0be379 Michael Hanselmann
331 fb0be379 Michael Hanselmann
332 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
333 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
334 23d0a608 Michael Hanselmann

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

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

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

362 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
363 fb0be379 Michael Hanselmann
  using binary AND.
364 fb0be379 Michael Hanselmann

365 fb0be379 Michael Hanselmann
  """
366 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
367 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
368 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
369 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
370 23d0a608 Michael Hanselmann
     None),
371 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
372 fb0be379 Michael Hanselmann
    ]
373 fb0be379 Michael Hanselmann
374 fb0be379 Michael Hanselmann
  """Known operators
375 fb0be379 Michael Hanselmann

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

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

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

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

413 fb0be379 Michael Hanselmann
    """
414 fb0be379 Michael Hanselmann
    self._fields = fields
415 fb0be379 Michael Hanselmann
    self._hints = None
416 fb0be379 Michael Hanselmann
    self._op_handler = None
417 fb0be379 Michael Hanselmann
418 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
419 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
420 fb0be379 Michael Hanselmann

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

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

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

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

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

486 fb0be379 Michael Hanselmann
    @type hints_fn: callable
487 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
488 fb0be379 Michael Hanselmann
    @type level: integer
489 fb0be379 Michael Hanselmann
    @param level: Current depth
490 fb0be379 Michael Hanselmann
    @type op: string
491 fb0be379 Michael Hanselmann
    @param op: Operator
492 fb0be379 Michael Hanselmann
    @type op_fn: callable
493 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
494 fb0be379 Michael Hanselmann
    @type operands: list
495 fb0be379 Michael Hanselmann
    @param operands: List of operands
496 fb0be379 Michael Hanselmann

497 fb0be379 Michael Hanselmann
    """
498 fb0be379 Michael Hanselmann
    if hints_fn:
499 fb0be379 Michael Hanselmann
      hints_fn(op)
500 fb0be379 Michael Hanselmann
501 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
502 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
503 fb0be379 Michael Hanselmann
504 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
505 fb0be379 Michael Hanselmann
    """Handles unary operators.
506 fb0be379 Michael Hanselmann

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

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

544 fb0be379 Michael Hanselmann
    @type hints_fn: callable
545 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
546 fb0be379 Michael Hanselmann
    @type level: integer
547 fb0be379 Michael Hanselmann
    @param level: Current depth
548 fb0be379 Michael Hanselmann
    @type op: string
549 fb0be379 Michael Hanselmann
    @param op: Operator
550 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
551 fb0be379 Michael Hanselmann
    @type operands: list
552 fb0be379 Michael Hanselmann
    @param operands: List of operands
553 fb0be379 Michael Hanselmann

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

593 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
594 fb0be379 Michael Hanselmann

595 fb0be379 Michael Hanselmann
  @rtype: callable
596 fb0be379 Michael Hanselmann

597 fb0be379 Michael Hanselmann
  """
598 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
599 fb0be379 Michael Hanselmann
600 fb0be379 Michael Hanselmann
601 4ca96421 Michael Hanselmann
class Query:
602 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
603 4ca96421 Michael Hanselmann
    """Initializes this class.
604 4ca96421 Michael Hanselmann

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

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

615 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
616 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
617 4ca96421 Michael Hanselmann
    @type selected: list of strings
618 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
619 4ca96421 Michael Hanselmann

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

650 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
651 fb0be379 Michael Hanselmann
    names, C{None} is returned.
652 fb0be379 Michael Hanselmann

653 fb0be379 Michael Hanselmann
    """
654 fb0be379 Michael Hanselmann
    return self._requested_names
655 fb0be379 Michael Hanselmann
656 4ca96421 Michael Hanselmann
  def RequestedData(self):
657 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
658 4ca96421 Michael Hanselmann

659 4ca96421 Michael Hanselmann
    @rtype: frozenset
660 4ca96421 Michael Hanselmann

661 4ca96421 Michael Hanselmann
    """
662 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
663 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
664 fb0be379 Michael Hanselmann
                      if datakind is not None))
665 4ca96421 Michael Hanselmann
666 4ca96421 Michael Hanselmann
  def GetFields(self):
667 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
668 4ca96421 Michael Hanselmann

669 4ca96421 Michael Hanselmann
    Includes unknown fields.
670 4ca96421 Michael Hanselmann

671 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
672 4ca96421 Michael Hanselmann

673 4ca96421 Michael Hanselmann
    """
674 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
675 4ca96421 Michael Hanselmann
676 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
677 4ca96421 Michael Hanselmann
    """Execute a query.
678 4ca96421 Michael Hanselmann

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

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

723 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
724 4ca96421 Michael Hanselmann

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

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

756 4ca96421 Michael Hanselmann
  @type fields: list
757 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
758 4ca96421 Michael Hanselmann
  @type row: list of tuples
759 4ca96421 Michael Hanselmann
  @param row: Row data
760 4ca96421 Michael Hanselmann

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

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

794 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
795 4ca96421 Michael Hanselmann

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

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

832 b60fcb6f Michael Hanselmann
  @type query: L{Query}
833 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
834 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
835 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
836 fbc263a9 Michael Hanselmann
    ordering
837 b60fcb6f Michael Hanselmann

838 b60fcb6f Michael Hanselmann
  """
839 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
840 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
841 b60fcb6f Michael Hanselmann
842 b60fcb6f Michael Hanselmann
843 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
844 aa29e95f Michael Hanselmann
  """Returns list of available fields.
845 aa29e95f Michael Hanselmann

846 aa29e95f Michael Hanselmann
  @type fielddefs: dict
847 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
848 aa29e95f Michael Hanselmann
  @type selected: list of strings
849 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
850 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
851 aa29e95f Michael Hanselmann

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

867 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
868 4ca96421 Michael Hanselmann
  @param title: Human-readable title
869 4ca96421 Michael Hanselmann
  @param kind: Field type
870 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
871 4ca96421 Michael Hanselmann

872 4ca96421 Michael Hanselmann
  """
873 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
874 1ae17369 Michael Hanselmann
                                      doc=doc)
875 8235fe04 Michael Hanselmann
876 8235fe04 Michael Hanselmann
877 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
878 8235fe04 Michael Hanselmann
  """Determine node role.
879 8235fe04 Michael Hanselmann

880 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
881 8235fe04 Michael Hanselmann
  @param node: Node object
882 8235fe04 Michael Hanselmann
  @type master_name: string
883 8235fe04 Michael Hanselmann
  @param master_name: Master node name
884 8235fe04 Michael Hanselmann

885 8235fe04 Michael Hanselmann
  """
886 8235fe04 Michael Hanselmann
  if node.name == master_name:
887 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
888 8235fe04 Michael Hanselmann
  elif node.master_candidate:
889 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
890 8235fe04 Michael Hanselmann
  elif node.drained:
891 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
892 8235fe04 Michael Hanselmann
  elif node.offline:
893 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
894 8235fe04 Michael Hanselmann
  else:
895 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
896 8235fe04 Michael Hanselmann
897 8235fe04 Michael Hanselmann
898 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
899 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
900 8235fe04 Michael Hanselmann

901 8235fe04 Michael Hanselmann
  @param attr: Attribute name
902 8235fe04 Michael Hanselmann

903 8235fe04 Michael Hanselmann
  """
904 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
905 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
906 8235fe04 Michael Hanselmann
907 8235fe04 Michael Hanselmann
908 8930b0f0 Iustin Pop
def _GetNDParam(name):
909 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
910 8930b0f0 Iustin Pop

911 8930b0f0 Iustin Pop
  """
912 8930b0f0 Iustin Pop
  def _helper(ctx, _):
913 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
914 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
915 8930b0f0 Iustin Pop
    else:
916 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
917 8930b0f0 Iustin Pop
  return _helper
918 8930b0f0 Iustin Pop
919 8930b0f0 Iustin Pop
920 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
921 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
922 8930b0f0 Iustin Pop

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

925 8930b0f0 Iustin Pop
  """
926 8930b0f0 Iustin Pop
  if is_group:
927 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
928 8930b0f0 Iustin Pop
  else:
929 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
930 8930b0f0 Iustin Pop
  return [(_MakeField("ndp/%s" % name, NDP_TITLE.get(name, "ndp/%s" % name),
931 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
932 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
933 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
934 8930b0f0 Iustin Pop
935 8930b0f0 Iustin Pop
936 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
937 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
938 425e5bf0 Michael Hanselmann

939 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
940 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
941 425e5bf0 Michael Hanselmann

942 425e5bf0 Michael Hanselmann
  """
943 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
944 425e5bf0 Michael Hanselmann
945 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
946 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
947 425e5bf0 Michael Hanselmann
    # Return right away
948 425e5bf0 Michael Hanselmann
    return value
949 425e5bf0 Michael Hanselmann
950 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
951 425e5bf0 Michael Hanselmann
  return convert(value)
952 425e5bf0 Michael Hanselmann
953 425e5bf0 Michael Hanselmann
954 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
955 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
956 425e5bf0 Michael Hanselmann

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

960 425e5bf0 Michael Hanselmann
  """
961 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
962 425e5bf0 Michael Hanselmann
963 425e5bf0 Michael Hanselmann
964 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
965 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
966 145bea54 Michael Hanselmann

967 145bea54 Michael Hanselmann
  @type getter: callable
968 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
969 145bea54 Michael Hanselmann

970 145bea54 Michael Hanselmann
  """
971 145bea54 Michael Hanselmann
  def fn(_, item):
972 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
973 145bea54 Michael Hanselmann

974 145bea54 Michael Hanselmann
    """
975 145bea54 Michael Hanselmann
    timestamp = getter(item)
976 145bea54 Michael Hanselmann
    if timestamp is None:
977 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
978 e2d188cc Iustin Pop
      return _FS_UNAVAIL
979 145bea54 Michael Hanselmann
    else:
980 e2d188cc Iustin Pop
      return timestamp
981 145bea54 Michael Hanselmann
982 145bea54 Michael Hanselmann
  return fn
983 145bea54 Michael Hanselmann
984 145bea54 Michael Hanselmann
985 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
986 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
987 145bea54 Michael Hanselmann

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

990 145bea54 Michael Hanselmann
  """
991 145bea54 Michael Hanselmann
  return [
992 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
993 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
994 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
995 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
996 145bea54 Michael Hanselmann
    ]
997 145bea54 Michael Hanselmann
998 145bea54 Michael Hanselmann
999 8235fe04 Michael Hanselmann
class NodeQueryData:
1000 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1001 8235fe04 Michael Hanselmann

1002 8235fe04 Michael Hanselmann
  """
1003 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1004 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1005 8235fe04 Michael Hanselmann
    """Initializes this class.
1006 8235fe04 Michael Hanselmann

1007 8235fe04 Michael Hanselmann
    """
1008 8235fe04 Michael Hanselmann
    self.nodes = nodes
1009 8235fe04 Michael Hanselmann
    self.live_data = live_data
1010 8235fe04 Michael Hanselmann
    self.master_name = master_name
1011 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1012 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1013 8235fe04 Michael Hanselmann
    self.groups = groups
1014 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1015 8572f1fe René Nussbaumer
    self.cluster = cluster
1016 8235fe04 Michael Hanselmann
1017 8235fe04 Michael Hanselmann
    # Used for individual rows
1018 8235fe04 Michael Hanselmann
    self.curlive_data = None
1019 8930b0f0 Iustin Pop
    self.ndparams = None
1020 8235fe04 Michael Hanselmann
1021 8235fe04 Michael Hanselmann
  def __iter__(self):
1022 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1023 8235fe04 Michael Hanselmann

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

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

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

1086 8572f1fe René Nussbaumer
  """
1087 8572f1fe René Nussbaumer
  def fn(ctx, node):
1088 8572f1fe René Nussbaumer
    """Get group data for a node.
1089 8572f1fe René Nussbaumer

1090 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1091 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1092 8572f1fe René Nussbaumer
    @param inst: Node object
1093 8572f1fe René Nussbaumer

1094 8572f1fe René Nussbaumer
    """
1095 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1096 8572f1fe René Nussbaumer
    if ng is None:
1097 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1098 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1099 8572f1fe René Nussbaumer
1100 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1101 8572f1fe René Nussbaumer
1102 8572f1fe René Nussbaumer
  return fn
1103 8572f1fe René Nussbaumer
1104 8572f1fe René Nussbaumer
1105 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1106 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1107 8235fe04 Michael Hanselmann

1108 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1109 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1110 8235fe04 Michael Hanselmann
  @param node: Node object
1111 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1112 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1113 8235fe04 Michael Hanselmann

1114 8235fe04 Michael Hanselmann
  """
1115 e2d188cc Iustin Pop
  return ng.name
1116 8235fe04 Michael Hanselmann
1117 8235fe04 Michael Hanselmann
1118 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1119 52b5d286 René Nussbaumer
  """Returns the node powered state
1120 52b5d286 René Nussbaumer

1121 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1122 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1123 52b5d286 René Nussbaumer
  @param node: Node object
1124 52b5d286 René Nussbaumer

1125 52b5d286 René Nussbaumer
  """
1126 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1127 e2d188cc Iustin Pop
    return node.powered
1128 52b5d286 René Nussbaumer
1129 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1130 52b5d286 René Nussbaumer
1131 52b5d286 René Nussbaumer
1132 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1133 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1134 8572f1fe René Nussbaumer

1135 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1136 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1137 8572f1fe René Nussbaumer
  @param node: Node object
1138 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1139 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1140 8572f1fe René Nussbaumer

1141 8572f1fe René Nussbaumer
  """
1142 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1143 8572f1fe René Nussbaumer
1144 8572f1fe René Nussbaumer
1145 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1146 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1147 8235fe04 Michael Hanselmann

1148 8235fe04 Michael Hanselmann
  @param field: Live field name
1149 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1150 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1151 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1152 a6070ef7 Michael Hanselmann
  @param node: Node object
1153 8235fe04 Michael Hanselmann

1154 8235fe04 Michael Hanselmann
  """
1155 a6070ef7 Michael Hanselmann
  if node.offline:
1156 e2d188cc Iustin Pop
    return _FS_OFFLINE
1157 a6070ef7 Michael Hanselmann
1158 effab4ca Iustin Pop
  if not node.vm_capable:
1159 effab4ca Iustin Pop
    return _FS_UNAVAIL
1160 effab4ca Iustin Pop
1161 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1162 e2d188cc Iustin Pop
    return _FS_NODATA
1163 8235fe04 Michael Hanselmann
1164 8235fe04 Michael Hanselmann
  try:
1165 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1166 8235fe04 Michael Hanselmann
  except KeyError:
1167 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1168 8235fe04 Michael Hanselmann
1169 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1170 e2d188cc Iustin Pop
    return value
1171 8235fe04 Michael Hanselmann
1172 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1173 8235fe04 Michael Hanselmann
1174 8235fe04 Michael Hanselmann
  # Try to convert into number
1175 8235fe04 Michael Hanselmann
  try:
1176 e2d188cc Iustin Pop
    return int(value)
1177 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1178 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1179 8235fe04 Michael Hanselmann
                      value, field)
1180 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1181 8235fe04 Michael Hanselmann
1182 8235fe04 Michael Hanselmann
1183 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1184 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1185 54ac87c0 Michael Hanselmann

1186 54ac87c0 Michael Hanselmann
  """
1187 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1188 54ac87c0 Michael Hanselmann
1189 54ac87c0 Michael Hanselmann
  if hv_state is None:
1190 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1191 54ac87c0 Michael Hanselmann
1192 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1193 54ac87c0 Michael Hanselmann
1194 54ac87c0 Michael Hanselmann
1195 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1196 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1197 54ac87c0 Michael Hanselmann

1198 54ac87c0 Michael Hanselmann
  """
1199 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1200 54ac87c0 Michael Hanselmann
1201 54ac87c0 Michael Hanselmann
  if disk_state is None:
1202 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1203 54ac87c0 Michael Hanselmann
1204 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1205 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1206 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1207 54ac87c0 Michael Hanselmann
1208 54ac87c0 Michael Hanselmann
1209 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1210 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1211 8235fe04 Michael Hanselmann

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

1297 1c8addc6 Michael Hanselmann
  """
1298 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1299 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1300 1c8addc6 Michael Hanselmann
    """Initializes this class.
1301 1c8addc6 Michael Hanselmann

1302 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1303 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1304 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1305 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1306 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1307 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1308 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1309 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1310 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1311 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1312 e431074f René Nussbaumer
    @type wrongnode_inst: set
1313 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1314 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1315 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1316 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1317 fab9573b Michael Hanselmann
    @param nodes: Node objects
1318 1c8addc6 Michael Hanselmann

1319 1c8addc6 Michael Hanselmann
    """
1320 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1321 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1322 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1323 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1324 1c8addc6 Michael Hanselmann
1325 1c8addc6 Michael Hanselmann
    self.instances = instances
1326 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1327 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1328 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1329 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1330 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1331 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1332 5d28cb6f Michael Hanselmann
    self.console = console
1333 fab9573b Michael Hanselmann
    self.nodes = nodes
1334 fab9573b Michael Hanselmann
    self.groups = groups
1335 1c8addc6 Michael Hanselmann
1336 1c8addc6 Michael Hanselmann
    # Used for individual rows
1337 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1338 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1339 7c670076 Michael Hanselmann
    self.inst_osparams = None
1340 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1341 1c8addc6 Michael Hanselmann
1342 1c8addc6 Michael Hanselmann
  def __iter__(self):
1343 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1344 1c8addc6 Michael Hanselmann

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

1348 1c8addc6 Michael Hanselmann
    """
1349 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1350 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1351 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1352 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1353 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1354 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1355 1c8addc6 Michael Hanselmann
1356 1c8addc6 Michael Hanselmann
      yield inst
1357 1c8addc6 Michael Hanselmann
1358 1c8addc6 Michael Hanselmann
1359 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1360 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1361 1c8addc6 Michael Hanselmann

1362 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1363 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1364 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1365 1c8addc6 Michael Hanselmann

1366 1c8addc6 Michael Hanselmann
  """
1367 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1368 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1369 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1370 e2d188cc Iustin Pop
    return _FS_NODATA
1371 1c8addc6 Michael Hanselmann
  else:
1372 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1373 1c8addc6 Michael Hanselmann
1374 1c8addc6 Michael Hanselmann
1375 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1376 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1377 1c8addc6 Michael Hanselmann

1378 1c8addc6 Michael Hanselmann
  @type name: string
1379 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1380 1c8addc6 Michael Hanselmann

1381 1c8addc6 Michael Hanselmann
  """
1382 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1383 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1384 1c8addc6 Michael Hanselmann

1385 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1386 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1387 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1388 1c8addc6 Michael Hanselmann

1389 1c8addc6 Michael Hanselmann
    """
1390 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1391 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1392 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1393 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1394 e2d188cc Iustin Pop
      return _FS_NODATA
1395 1c8addc6 Michael Hanselmann
1396 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1397 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1398 1c8addc6 Michael Hanselmann
      if name in data:
1399 e2d188cc Iustin Pop
        return data[name]
1400 1c8addc6 Michael Hanselmann
1401 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1402 1c8addc6 Michael Hanselmann
1403 1c8addc6 Michael Hanselmann
  return fn
1404 1c8addc6 Michael Hanselmann
1405 1c8addc6 Michael Hanselmann
1406 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1407 1c8addc6 Michael Hanselmann
  """Get instance status.
1408 1c8addc6 Michael Hanselmann

1409 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1410 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1411 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1412 1c8addc6 Michael Hanselmann

1413 1c8addc6 Michael Hanselmann
  """
1414 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1415 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1416 1c8addc6 Michael Hanselmann
1417 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1418 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1419 1c8addc6 Michael Hanselmann
1420 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1421 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1422 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1423 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1424 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1425 1c8addc6 Michael Hanselmann
    else:
1426 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1427 1c8addc6 Michael Hanselmann
1428 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1429 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1430 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1431 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1432 1c8addc6 Michael Hanselmann
1433 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1434 1c8addc6 Michael Hanselmann
1435 1c8addc6 Michael Hanselmann
1436 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1437 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1438 1c8addc6 Michael Hanselmann

1439 1c8addc6 Michael Hanselmann
  @type index: int
1440 1c8addc6 Michael Hanselmann
  @param index: Disk index
1441 1c8addc6 Michael Hanselmann

1442 1c8addc6 Michael Hanselmann
  """
1443 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1444 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1445 1c8addc6 Michael Hanselmann

1446 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1447 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1448 1c8addc6 Michael Hanselmann

1449 1c8addc6 Michael Hanselmann
    """
1450 1c8addc6 Michael Hanselmann
    try:
1451 e2d188cc Iustin Pop
      return inst.disks[index].size
1452 1c8addc6 Michael Hanselmann
    except IndexError:
1453 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1454 1c8addc6 Michael Hanselmann
1455 1c8addc6 Michael Hanselmann
  return fn
1456 1c8addc6 Michael Hanselmann
1457 1c8addc6 Michael Hanselmann
1458 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1459 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1460 1c8addc6 Michael Hanselmann

1461 1c8addc6 Michael Hanselmann
  @type index: int
1462 1c8addc6 Michael Hanselmann
  @param index: NIC index
1463 1c8addc6 Michael Hanselmann
  @type cb: callable
1464 1c8addc6 Michael Hanselmann
  @param cb: Callback
1465 1c8addc6 Michael Hanselmann

1466 1c8addc6 Michael Hanselmann
  """
1467 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1468 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1469 1c8addc6 Michael Hanselmann

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

1474 1c8addc6 Michael Hanselmann
    """
1475 1c8addc6 Michael Hanselmann
    try:
1476 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1477 1c8addc6 Michael Hanselmann
    except IndexError:
1478 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1479 1c8addc6 Michael Hanselmann
1480 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1481 1c8addc6 Michael Hanselmann
1482 1c8addc6 Michael Hanselmann
  return fn
1483 1c8addc6 Michael Hanselmann
1484 1c8addc6 Michael Hanselmann
1485 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1486 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1487 1c8addc6 Michael Hanselmann

1488 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1489 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1490 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1491 1c8addc6 Michael Hanselmann

1492 1c8addc6 Michael Hanselmann
  """
1493 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1494 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1495 1c8addc6 Michael Hanselmann
  else:
1496 e2d188cc Iustin Pop
    return nic.ip
1497 1c8addc6 Michael Hanselmann
1498 1c8addc6 Michael Hanselmann
1499 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1500 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1501 1c8addc6 Michael Hanselmann

1502 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1503 1c8addc6 Michael Hanselmann
  @type index: int
1504 1c8addc6 Michael Hanselmann
  @param index: NIC index
1505 1c8addc6 Michael Hanselmann

1506 1c8addc6 Michael Hanselmann
  """
1507 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1508 1c8addc6 Michael Hanselmann
1509 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1510 1c8addc6 Michael Hanselmann
1511 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1512 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1513 1c8addc6 Michael Hanselmann
  else:
1514 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1515 1c8addc6 Michael Hanselmann
1516 1c8addc6 Michael Hanselmann
1517 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1518 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1519 1c8addc6 Michael Hanselmann

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

1524 1c8addc6 Michael Hanselmann
  """
1525 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1526 1c8addc6 Michael Hanselmann
1527 1c8addc6 Michael Hanselmann
  result = []
1528 1c8addc6 Michael Hanselmann
1529 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1530 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1531 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1532 1c8addc6 Michael Hanselmann
    else:
1533 1c8addc6 Michael Hanselmann
      result.append(None)
1534 1c8addc6 Michael Hanselmann
1535 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1536 1c8addc6 Michael Hanselmann
1537 e2d188cc Iustin Pop
  return result
1538 1c8addc6 Michael Hanselmann
1539 1c8addc6 Michael Hanselmann
1540 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1541 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1542 1c8addc6 Michael Hanselmann

1543 1c8addc6 Michael Hanselmann
  @type name: string
1544 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1545 1c8addc6 Michael Hanselmann

1546 1c8addc6 Michael Hanselmann
  """
1547 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1548 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1549 1c8addc6 Michael Hanselmann

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

1556 1c8addc6 Michael Hanselmann
    """
1557 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1558 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1559 1c8addc6 Michael Hanselmann
1560 1c8addc6 Michael Hanselmann
  return fn
1561 1c8addc6 Michael Hanselmann
1562 1c8addc6 Michael Hanselmann
1563 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1564 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1565 1c8addc6 Michael Hanselmann

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

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

1634 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1635 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1636 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1637 1c8addc6 Michael Hanselmann

1638 1c8addc6 Michael Hanselmann
  """
1639 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1640 1c8addc6 Michael Hanselmann
1641 1c8addc6 Michael Hanselmann
  if usage is None:
1642 1c8addc6 Michael Hanselmann
    usage = 0
1643 1c8addc6 Michael Hanselmann
1644 e2d188cc Iustin Pop
  return usage
1645 1c8addc6 Michael Hanselmann
1646 1c8addc6 Michael Hanselmann
1647 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1648 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1649 5d28cb6f Michael Hanselmann

1650 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1651 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1652 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1653 5d28cb6f Michael Hanselmann

1654 5d28cb6f Michael Hanselmann
  """
1655 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1656 5d28cb6f Michael Hanselmann
1657 5d28cb6f Michael Hanselmann
  if consinfo is None:
1658 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1659 5d28cb6f Michael Hanselmann
1660 5d28cb6f Michael Hanselmann
  return consinfo
1661 5d28cb6f Michael Hanselmann
1662 5d28cb6f Michael Hanselmann
1663 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1664 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1665 1c8addc6 Michael Hanselmann

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

1668 1c8addc6 Michael Hanselmann
  """
1669 1c8addc6 Michael Hanselmann
  fields = [
1670 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1671 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1672 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1673 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1674 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1675 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1676 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1677 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1678 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1679 1c8addc6 Michael Hanselmann
    ]
1680 1c8addc6 Michael Hanselmann
1681 1c8addc6 Michael Hanselmann
  # Disks by number
1682 1c8addc6 Michael Hanselmann
  fields.extend([
1683 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1684 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1685 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1686 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1687 1c8addc6 Michael Hanselmann
    ])
1688 1c8addc6 Michael Hanselmann
1689 1c8addc6 Michael Hanselmann
  return fields
1690 1c8addc6 Michael Hanselmann
1691 1c8addc6 Michael Hanselmann
1692 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1693 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1694 1c8addc6 Michael Hanselmann

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

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

1787 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1788 fab9573b Michael Hanselmann
  @param default: Default value
1789 fab9573b Michael Hanselmann
  @type node_name: string
1790 fab9573b Michael Hanselmann
  @param node_name: Node name
1791 fab9573b Michael Hanselmann

1792 fab9573b Michael Hanselmann
  """
1793 fab9573b Michael Hanselmann
  try:
1794 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1795 fab9573b Michael Hanselmann
  except KeyError:
1796 fab9573b Michael Hanselmann
    return default
1797 fab9573b Michael Hanselmann
  else:
1798 fab9573b Michael Hanselmann
    return node.group
1799 fab9573b Michael Hanselmann
1800 fab9573b Michael Hanselmann
1801 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1802 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1803 fab9573b Michael Hanselmann

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

1809 fab9573b Michael Hanselmann
  """
1810 fab9573b Michael Hanselmann
  try:
1811 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1812 fab9573b Michael Hanselmann
  except KeyError:
1813 fab9573b Michael Hanselmann
    return default
1814 fab9573b Michael Hanselmann
1815 fab9573b Michael Hanselmann
  try:
1816 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1817 fab9573b Michael Hanselmann
  except KeyError:
1818 fab9573b Michael Hanselmann
    return default
1819 fab9573b Michael Hanselmann
1820 fab9573b Michael Hanselmann
  return group.name
1821 fab9573b Michael Hanselmann
1822 fab9573b Michael Hanselmann
1823 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1824 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1825 1c8addc6 Michael Hanselmann

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

1923 24d16f76 Michael Hanselmann
  """
1924 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1925 24d16f76 Michael Hanselmann
    """Initializes this class.
1926 24d16f76 Michael Hanselmann

1927 24d16f76 Michael Hanselmann
    """
1928 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1929 24d16f76 Michael Hanselmann
1930 24d16f76 Michael Hanselmann
  def __iter__(self):
1931 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1932 24d16f76 Michael Hanselmann

1933 24d16f76 Michael Hanselmann
    """
1934 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1935 24d16f76 Michael Hanselmann
1936 24d16f76 Michael Hanselmann
1937 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1938 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1939 24d16f76 Michael Hanselmann

1940 24d16f76 Michael Hanselmann
  """
1941 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1942 24d16f76 Michael Hanselmann
1943 24d16f76 Michael Hanselmann
  if owners:
1944 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1945 24d16f76 Michael Hanselmann
1946 e2d188cc Iustin Pop
  return owners
1947 24d16f76 Michael Hanselmann
1948 24d16f76 Michael Hanselmann
1949 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1950 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1951 24d16f76 Michael Hanselmann

1952 24d16f76 Michael Hanselmann
  """
1953 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1954 24d16f76 Michael Hanselmann
1955 24d16f76 Michael Hanselmann
  if pending:
1956 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1957 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1958 24d16f76 Michael Hanselmann
1959 e2d188cc Iustin Pop
  return pending
1960 24d16f76 Michael Hanselmann
1961 24d16f76 Michael Hanselmann
1962 24d16f76 Michael Hanselmann
def _BuildLockFields():
1963 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1964 24d16f76 Michael Hanselmann

1965 24d16f76 Michael Hanselmann
  """
1966 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1967 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
1968 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
1969 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1970 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
1971 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
1972 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
1973 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
1974 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
1975 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
1976 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
1977 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
1978 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
1979 d63bd540 Iustin Pop
    ], [])
1980 24d16f76 Michael Hanselmann
1981 24d16f76 Michael Hanselmann
1982 8e21cfc0 Adeodato Simo
class GroupQueryData:
1983 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1984 8e21cfc0 Adeodato Simo

1985 8e21cfc0 Adeodato Simo
  """
1986 edd49f9b Agata Murawska
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances):
1987 8e21cfc0 Adeodato Simo
    """Initializes this class.
1988 8e21cfc0 Adeodato Simo

1989 edd49f9b Agata Murawska
    @param cluster: Cluster object
1990 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1991 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1992 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1993 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1994 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1995 8e21cfc0 Adeodato Simo

1996 8e21cfc0 Adeodato Simo
    """
1997 8e21cfc0 Adeodato Simo
    self.groups = groups
1998 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1999 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2000 edd49f9b Agata Murawska
    self.cluster = cluster
2001 edd49f9b Agata Murawska
2002 edd49f9b Agata Murawska
    # Used for individual rows
2003 edd49f9b Agata Murawska
    self.group_ipolicy = None
2004 8930b0f0 Iustin Pop
    self.ndparams = None
2005 8e21cfc0 Adeodato Simo
2006 8e21cfc0 Adeodato Simo
  def __iter__(self):
2007 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2008 8e21cfc0 Adeodato Simo

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

2012 8e21cfc0 Adeodato Simo
    """
2013 edd49f9b Agata Murawska
    for group in self.groups:
2014 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2015 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2016 edd49f9b Agata Murawska
      yield group
2017 8e21cfc0 Adeodato Simo
2018 8e21cfc0 Adeodato Simo
2019 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2020 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2021 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2022 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2023 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2024 8e21cfc0 Adeodato Simo
  }
2025 8e21cfc0 Adeodato Simo
2026 8e21cfc0 Adeodato Simo
2027 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2028 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2029 8e21cfc0 Adeodato Simo

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

2105 be3a4b14 Michael Hanselmann
  """
2106 be3a4b14 Michael Hanselmann
  fields = [
2107 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2108 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2109 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2110 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2111 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2112 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2113 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2114 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2115 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2116 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2117 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2118 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2119 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2120 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2121 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2122 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2123 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2124 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2125 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2126 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2127 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2128 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2129 be3a4b14 Michael Hanselmann
                "Status from node"),
2130 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2131 be3a4b14 Michael Hanselmann
    ]
2132 be3a4b14 Michael Hanselmann
2133 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2134 be3a4b14 Michael Hanselmann
2135 be3a4b14 Michael Hanselmann
2136 8235fe04 Michael Hanselmann
#: Fields available for node queries
2137 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2138 1c8addc6 Michael Hanselmann
2139 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2140 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2141 24d16f76 Michael Hanselmann
2142 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2143 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2144 e571ee44 Adeodato Simo
2145 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2146 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2147 8e21cfc0 Adeodato Simo
2148 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2149 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2150 be3a4b14 Michael Hanselmann
2151 95eb4188 Michael Hanselmann
#: All available resources
2152 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2153 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2154 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2155 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2156 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2157 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2158 95eb4188 Michael Hanselmann
  }
2159 95eb4188 Michael Hanselmann
2160 e571ee44 Adeodato Simo
#: All available field lists
2161 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()