Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 9fa567b3

History | View | Annotate | Download (61.8 kB)

1 4ca96421 Michael Hanselmann
#
2 4ca96421 Michael Hanselmann
#
3 4ca96421 Michael Hanselmann
4 82599b3e Iustin Pop
# Copyright (C) 2010, 2011 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 4ca96421 Michael Hanselmann
140 b459a848 Andrea Spadaccini
def _GetUnknownField(ctx, item): # pylint: disable=W0613
141 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
142 4ca96421 Michael Hanselmann

143 4ca96421 Michael Hanselmann
  """
144 e2d188cc Iustin Pop
  return _FS_UNKNOWN
145 4ca96421 Michael Hanselmann
146 4ca96421 Michael Hanselmann
147 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
148 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
149 4ca96421 Michael Hanselmann

150 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
151 4ca96421 Michael Hanselmann

152 4ca96421 Michael Hanselmann
  @type fielddefs: dict
153 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
154 4ca96421 Michael Hanselmann
  @type selected: list of strings
155 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
156 4ca96421 Michael Hanselmann

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

177 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
178 4ca96421 Michael Hanselmann

179 4ca96421 Michael Hanselmann
  """
180 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
181 4ca96421 Michael Hanselmann
182 4ca96421 Michael Hanselmann
183 fb0be379 Michael Hanselmann
class _FilterHints:
184 fb0be379 Michael Hanselmann
  """Class for filter analytics.
185 fb0be379 Michael Hanselmann

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

191 fb0be379 Michael Hanselmann
  There are two ways to optimize this. The first, and simpler, is to assign
192 fb0be379 Michael Hanselmann
  each field a group of data, so that the caller can determine which
193 fb0be379 Michael Hanselmann
  computations are necessary depending on the data groups requested. The list
194 fb0be379 Michael Hanselmann
  of referenced groups must also be computed for fields referenced in the
195 fb0be379 Michael Hanselmann
  filter.
196 fb0be379 Michael Hanselmann

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

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

206 fb0be379 Michael Hanselmann
  """
207 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
208 fb0be379 Michael Hanselmann
    """Initializes this class.
209 fb0be379 Michael Hanselmann

210 fb0be379 Michael Hanselmann
    @type namefield: string
211 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
212 fb0be379 Michael Hanselmann

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

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

232 fb0be379 Michael Hanselmann
    @rtype: list
233 fb0be379 Michael Hanselmann

234 fb0be379 Michael Hanselmann
    """
235 fb0be379 Michael Hanselmann
    if self._allnames or self._names is None:
236 fb0be379 Michael Hanselmann
      return None
237 fb0be379 Michael Hanselmann
238 fb0be379 Michael Hanselmann
    return utils.UniqueSequence(self._names)
239 fb0be379 Michael Hanselmann
240 fb0be379 Michael Hanselmann
  def ReferencedData(self):
241 fb0be379 Michael Hanselmann
    """Returns all kinds of data referenced by the filter.
242 fb0be379 Michael Hanselmann

243 fb0be379 Michael Hanselmann
    """
244 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
245 fb0be379 Michael Hanselmann
246 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
247 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
248 fb0be379 Michael Hanselmann

249 fb0be379 Michael Hanselmann
    """
250 fb0be379 Michael Hanselmann
    self._allnames = True
251 fb0be379 Michael Hanselmann
    self._names = None
252 fb0be379 Michael Hanselmann
253 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
254 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
255 fb0be379 Michael Hanselmann

256 fb0be379 Michael Hanselmann
    @type op: string
257 fb0be379 Michael Hanselmann
    @param op: Operator
258 fb0be379 Michael Hanselmann

259 fb0be379 Michael Hanselmann
    """
260 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
261 fb0be379 Michael Hanselmann
      self._NeedAllNames()
262 fb0be379 Michael Hanselmann
263 b459a848 Andrea Spadaccini
  def NoteUnaryOp(self, op): # pylint: disable=W0613
264 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
265 fb0be379 Michael Hanselmann

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

269 fb0be379 Michael Hanselmann
    """
270 fb0be379 Michael Hanselmann
    self._NeedAllNames()
271 fb0be379 Michael Hanselmann
272 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
273 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
274 fb0be379 Michael Hanselmann

275 fb0be379 Michael Hanselmann
    @type op: string
276 fb0be379 Michael Hanselmann
    @param op: Operator
277 fb0be379 Michael Hanselmann
    @type name: string
278 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
279 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
280 fb0be379 Michael Hanselmann

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

301 fb0be379 Michael Hanselmann
  """
302 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
303 fb0be379 Michael Hanselmann
304 fb0be379 Michael Hanselmann
305 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
306 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
307 fb0be379 Michael Hanselmann

308 fb0be379 Michael Hanselmann
  """
309 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
310 fb0be379 Michael Hanselmann
311 fb0be379 Michael Hanselmann
312 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
313 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
314 fb0be379 Michael Hanselmann

315 fb0be379 Michael Hanselmann
  """
316 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
317 fb0be379 Michael Hanselmann
318 fb0be379 Michael Hanselmann
319 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
320 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
321 fb0be379 Michael Hanselmann

322 fb0be379 Michael Hanselmann
  """
323 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
324 fb0be379 Michael Hanselmann
325 fb0be379 Michael Hanselmann
326 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
327 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
328 23d0a608 Michael Hanselmann

329 23d0a608 Michael Hanselmann
  """
330 23d0a608 Michael Hanselmann
  try:
331 23d0a608 Michael Hanselmann
    return re.compile(pattern)
332 23d0a608 Michael Hanselmann
  except re.error, err:
333 23d0a608 Michael Hanselmann
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
334 23d0a608 Michael Hanselmann
335 23d0a608 Michael Hanselmann
336 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
337 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
338 fb0be379 Michael Hanselmann

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

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

356 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
357 fb0be379 Michael Hanselmann
  using binary AND.
358 fb0be379 Michael Hanselmann

359 fb0be379 Michael Hanselmann
  """
360 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
361 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
362 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
363 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
364 23d0a608 Michael Hanselmann
     None),
365 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
366 fb0be379 Michael Hanselmann
    ]
367 fb0be379 Michael Hanselmann
368 fb0be379 Michael Hanselmann
  """Known operators
369 fb0be379 Michael Hanselmann

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

373 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
374 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
375 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
376 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
377 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
378 fb0be379 Michael Hanselmann

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

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

407 fb0be379 Michael Hanselmann
    """
408 fb0be379 Michael Hanselmann
    self._fields = fields
409 fb0be379 Michael Hanselmann
    self._hints = None
410 fb0be379 Michael Hanselmann
    self._op_handler = None
411 fb0be379 Michael Hanselmann
412 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
413 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
414 fb0be379 Michael Hanselmann

415 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
416 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
417 2e5c33db Iustin Pop
    @type qfilter: list
418 2e5c33db Iustin Pop
    @param qfilter: Filter structure
419 fb0be379 Michael Hanselmann
    @rtype: callable
420 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
421 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
422 fb0be379 Michael Hanselmann

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

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

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

471 3b877f08 Michael Hanselmann
    """
472 3b877f08 Michael Hanselmann
    try:
473 3b877f08 Michael Hanselmann
      return self._fields[name]
474 3b877f08 Michael Hanselmann
    except KeyError:
475 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
476 3b877f08 Michael Hanselmann
477 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
478 fb0be379 Michael Hanselmann
    """Handles logic operators.
479 fb0be379 Michael Hanselmann

480 fb0be379 Michael Hanselmann
    @type hints_fn: callable
481 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
482 fb0be379 Michael Hanselmann
    @type level: integer
483 fb0be379 Michael Hanselmann
    @param level: Current depth
484 fb0be379 Michael Hanselmann
    @type op: string
485 fb0be379 Michael Hanselmann
    @param op: Operator
486 fb0be379 Michael Hanselmann
    @type op_fn: callable
487 fb0be379 Michael Hanselmann
    @param op_fn: Function implementing operator
488 fb0be379 Michael Hanselmann
    @type operands: list
489 fb0be379 Michael Hanselmann
    @param operands: List of operands
490 fb0be379 Michael Hanselmann

491 fb0be379 Michael Hanselmann
    """
492 fb0be379 Michael Hanselmann
    if hints_fn:
493 fb0be379 Michael Hanselmann
      hints_fn(op)
494 fb0be379 Michael Hanselmann
495 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
496 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
497 fb0be379 Michael Hanselmann
498 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
499 fb0be379 Michael Hanselmann
    """Handles unary operators.
500 fb0be379 Michael Hanselmann

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

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

538 fb0be379 Michael Hanselmann
    @type hints_fn: callable
539 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
540 fb0be379 Michael Hanselmann
    @type level: integer
541 fb0be379 Michael Hanselmann
    @param level: Current depth
542 fb0be379 Michael Hanselmann
    @type op: string
543 fb0be379 Michael Hanselmann
    @param op: Operator
544 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
545 fb0be379 Michael Hanselmann
    @type operands: list
546 fb0be379 Michael Hanselmann
    @param operands: List of operands
547 fb0be379 Michael Hanselmann

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

587 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
588 fb0be379 Michael Hanselmann

589 fb0be379 Michael Hanselmann
  @rtype: callable
590 fb0be379 Michael Hanselmann

591 fb0be379 Michael Hanselmann
  """
592 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
593 fb0be379 Michael Hanselmann
594 fb0be379 Michael Hanselmann
595 4ca96421 Michael Hanselmann
class Query:
596 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
597 4ca96421 Michael Hanselmann
    """Initializes this class.
598 4ca96421 Michael Hanselmann

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

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

609 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
610 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
611 4ca96421 Michael Hanselmann
    @type selected: list of strings
612 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
613 4ca96421 Michael Hanselmann

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

644 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
645 fb0be379 Michael Hanselmann
    names, C{None} is returned.
646 fb0be379 Michael Hanselmann

647 fb0be379 Michael Hanselmann
    """
648 fb0be379 Michael Hanselmann
    return self._requested_names
649 fb0be379 Michael Hanselmann
650 4ca96421 Michael Hanselmann
  def RequestedData(self):
651 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
652 4ca96421 Michael Hanselmann

653 4ca96421 Michael Hanselmann
    @rtype: frozenset
654 4ca96421 Michael Hanselmann

655 4ca96421 Michael Hanselmann
    """
656 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
657 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
658 fb0be379 Michael Hanselmann
                      if datakind is not None))
659 4ca96421 Michael Hanselmann
660 4ca96421 Michael Hanselmann
  def GetFields(self):
661 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
662 4ca96421 Michael Hanselmann

663 4ca96421 Michael Hanselmann
    Includes unknown fields.
664 4ca96421 Michael Hanselmann

665 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
666 4ca96421 Michael Hanselmann

667 4ca96421 Michael Hanselmann
    """
668 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
669 4ca96421 Michael Hanselmann
670 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
671 4ca96421 Michael Hanselmann
    """Execute a query.
672 4ca96421 Michael Hanselmann

673 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
674 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
675 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
676 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
677 fbc263a9 Michael Hanselmann
      ordering
678 4ca96421 Michael Hanselmann

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

717 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
718 4ca96421 Michael Hanselmann

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

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

750 4ca96421 Michael Hanselmann
  @type fields: list
751 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
752 4ca96421 Michael Hanselmann
  @type row: list of tuples
753 4ca96421 Michael Hanselmann
  @param row: Row data
754 4ca96421 Michael Hanselmann

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

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

788 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
789 4ca96421 Michael Hanselmann

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

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

826 b60fcb6f Michael Hanselmann
  @type query: L{Query}
827 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
828 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
829 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
830 fbc263a9 Michael Hanselmann
    ordering
831 b60fcb6f Michael Hanselmann

832 b60fcb6f Michael Hanselmann
  """
833 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
834 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
835 b60fcb6f Michael Hanselmann
836 b60fcb6f Michael Hanselmann
837 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
838 aa29e95f Michael Hanselmann
  """Returns list of available fields.
839 aa29e95f Michael Hanselmann

840 aa29e95f Michael Hanselmann
  @type fielddefs: dict
841 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
842 aa29e95f Michael Hanselmann
  @type selected: list of strings
843 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
844 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
845 aa29e95f Michael Hanselmann

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

861 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
862 4ca96421 Michael Hanselmann
  @param title: Human-readable title
863 4ca96421 Michael Hanselmann
  @param kind: Field type
864 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
865 4ca96421 Michael Hanselmann

866 4ca96421 Michael Hanselmann
  """
867 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
868 1ae17369 Michael Hanselmann
                                      doc=doc)
869 8235fe04 Michael Hanselmann
870 8235fe04 Michael Hanselmann
871 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
872 8235fe04 Michael Hanselmann
  """Determine node role.
873 8235fe04 Michael Hanselmann

874 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
875 8235fe04 Michael Hanselmann
  @param node: Node object
876 8235fe04 Michael Hanselmann
  @type master_name: string
877 8235fe04 Michael Hanselmann
  @param master_name: Master node name
878 8235fe04 Michael Hanselmann

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

895 8235fe04 Michael Hanselmann
  @param attr: Attribute name
896 8235fe04 Michael Hanselmann

897 8235fe04 Michael Hanselmann
  """
898 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
899 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
900 8235fe04 Michael Hanselmann
901 8235fe04 Michael Hanselmann
902 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
903 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
904 425e5bf0 Michael Hanselmann

905 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
906 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
907 425e5bf0 Michael Hanselmann

908 425e5bf0 Michael Hanselmann
  """
909 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
910 425e5bf0 Michael Hanselmann
911 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
912 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
913 425e5bf0 Michael Hanselmann
    # Return right away
914 425e5bf0 Michael Hanselmann
    return value
915 425e5bf0 Michael Hanselmann
916 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
917 425e5bf0 Michael Hanselmann
  return convert(value)
918 425e5bf0 Michael Hanselmann
919 425e5bf0 Michael Hanselmann
920 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
921 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
922 425e5bf0 Michael Hanselmann

923 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
924 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
925 425e5bf0 Michael Hanselmann

926 425e5bf0 Michael Hanselmann
  """
927 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
928 425e5bf0 Michael Hanselmann
929 425e5bf0 Michael Hanselmann
930 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
931 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
932 145bea54 Michael Hanselmann

933 145bea54 Michael Hanselmann
  @type getter: callable
934 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
935 145bea54 Michael Hanselmann

936 145bea54 Michael Hanselmann
  """
937 145bea54 Michael Hanselmann
  def fn(_, item):
938 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
939 145bea54 Michael Hanselmann

940 145bea54 Michael Hanselmann
    """
941 145bea54 Michael Hanselmann
    timestamp = getter(item)
942 145bea54 Michael Hanselmann
    if timestamp is None:
943 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
944 e2d188cc Iustin Pop
      return _FS_UNAVAIL
945 145bea54 Michael Hanselmann
    else:
946 e2d188cc Iustin Pop
      return timestamp
947 145bea54 Michael Hanselmann
948 145bea54 Michael Hanselmann
  return fn
949 145bea54 Michael Hanselmann
950 145bea54 Michael Hanselmann
951 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
952 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
953 145bea54 Michael Hanselmann

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

956 145bea54 Michael Hanselmann
  """
957 145bea54 Michael Hanselmann
  return [
958 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
959 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
960 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
961 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
962 145bea54 Michael Hanselmann
    ]
963 145bea54 Michael Hanselmann
964 145bea54 Michael Hanselmann
965 8235fe04 Michael Hanselmann
class NodeQueryData:
966 8235fe04 Michael Hanselmann
  """Data container for node data queries.
967 8235fe04 Michael Hanselmann

968 8235fe04 Michael Hanselmann
  """
969 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
970 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
971 8235fe04 Michael Hanselmann
    """Initializes this class.
972 8235fe04 Michael Hanselmann

973 8235fe04 Michael Hanselmann
    """
974 8235fe04 Michael Hanselmann
    self.nodes = nodes
975 8235fe04 Michael Hanselmann
    self.live_data = live_data
976 8235fe04 Michael Hanselmann
    self.master_name = master_name
977 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
978 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
979 8235fe04 Michael Hanselmann
    self.groups = groups
980 52b5d286 René Nussbaumer
    self.oob_support = oob_support
981 8572f1fe René Nussbaumer
    self.cluster = cluster
982 8235fe04 Michael Hanselmann
983 8235fe04 Michael Hanselmann
    # Used for individual rows
984 8235fe04 Michael Hanselmann
    self.curlive_data = None
985 8235fe04 Michael Hanselmann
986 8235fe04 Michael Hanselmann
  def __iter__(self):
987 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
988 8235fe04 Michael Hanselmann

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

992 8235fe04 Michael Hanselmann
    """
993 8235fe04 Michael Hanselmann
    for node in self.nodes:
994 8235fe04 Michael Hanselmann
      if self.live_data:
995 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
996 8235fe04 Michael Hanselmann
      else:
997 8235fe04 Michael Hanselmann
        self.curlive_data = None
998 8235fe04 Michael Hanselmann
      yield node
999 8235fe04 Michael Hanselmann
1000 8235fe04 Michael Hanselmann
1001 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
1002 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
1003 111bf531 Michael Hanselmann
  "drained": ("Drained", QFT_BOOL, 0, "Whether node is drained"),
1004 111bf531 Michael Hanselmann
  "master_candidate": ("MasterC", QFT_BOOL, 0,
1005 79b2ca83 Michael Hanselmann
                       "Whether node is a master candidate"),
1006 111bf531 Michael Hanselmann
  "master_capable": ("MasterCapable", QFT_BOOL, 0,
1007 79b2ca83 Michael Hanselmann
                     "Whether node can become a master candidate"),
1008 111bf531 Michael Hanselmann
  "name": ("Node", QFT_TEXT, QFF_HOSTNAME, "Node name"),
1009 111bf531 Michael Hanselmann
  "offline": ("Offline", QFT_BOOL, 0, "Whether node is marked offline"),
1010 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Node"),
1011 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Node UUID"),
1012 111bf531 Michael Hanselmann
  "vm_capable": ("VMCapable", QFT_BOOL, 0, "Whether node can host instances"),
1013 8235fe04 Michael Hanselmann
  }
1014 8235fe04 Michael Hanselmann
1015 8235fe04 Michael Hanselmann
1016 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
1017 effab4ca Iustin Pop
# Note that none of these are available for non-vm_capable nodes
1018 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
1019 79b2ca83 Michael Hanselmann
  "bootid": ("BootID", QFT_TEXT, "bootid",
1020 79b2ca83 Michael Hanselmann
             "Random UUID renewed for each system reboot, can be used"
1021 79b2ca83 Michael Hanselmann
             " for detecting reboots by tracking changes"),
1022 79b2ca83 Michael Hanselmann
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes",
1023 79b2ca83 Michael Hanselmann
             "Number of NUMA domains on node (if exported by hypervisor)"),
1024 79b2ca83 Michael Hanselmann
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets",
1025 79b2ca83 Michael Hanselmann
               "Number of physical CPU sockets (if exported by hypervisor)"),
1026 79b2ca83 Michael Hanselmann
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total", "Number of logical processors"),
1027 79b2ca83 Michael Hanselmann
  "dfree": ("DFree", QFT_UNIT, "vg_free",
1028 79b2ca83 Michael Hanselmann
            "Available disk space in volume group"),
1029 79b2ca83 Michael Hanselmann
  "dtotal": ("DTotal", QFT_UNIT, "vg_size",
1030 79b2ca83 Michael Hanselmann
             "Total disk space in volume group used for instance disk"
1031 79b2ca83 Michael Hanselmann
             " allocation"),
1032 79b2ca83 Michael Hanselmann
  "mfree": ("MFree", QFT_UNIT, "memory_free",
1033 79b2ca83 Michael Hanselmann
            "Memory available for instance allocations"),
1034 79b2ca83 Michael Hanselmann
  "mnode": ("MNode", QFT_UNIT, "memory_dom0",
1035 79b2ca83 Michael Hanselmann
            "Amount of memory used by node (dom0 for Xen)"),
1036 79b2ca83 Michael Hanselmann
  "mtotal": ("MTotal", QFT_UNIT, "memory_total",
1037 79b2ca83 Michael Hanselmann
             "Total amount of memory of physical machine"),
1038 8235fe04 Michael Hanselmann
  }
1039 8235fe04 Michael Hanselmann
1040 8235fe04 Michael Hanselmann
1041 8572f1fe René Nussbaumer
def _GetGroup(cb):
1042 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
1043 8572f1fe René Nussbaumer

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

1046 8572f1fe René Nussbaumer
  """
1047 8572f1fe René Nussbaumer
  def fn(ctx, node):
1048 8572f1fe René Nussbaumer
    """Get group data for a node.
1049 8572f1fe René Nussbaumer

1050 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1051 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1052 8572f1fe René Nussbaumer
    @param inst: Node object
1053 8572f1fe René Nussbaumer

1054 8572f1fe René Nussbaumer
    """
1055 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1056 8572f1fe René Nussbaumer
    if ng is None:
1057 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1058 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1059 8572f1fe René Nussbaumer
1060 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1061 8572f1fe René Nussbaumer
1062 8572f1fe René Nussbaumer
  return fn
1063 8572f1fe René Nussbaumer
1064 8572f1fe René Nussbaumer
1065 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1066 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1067 8235fe04 Michael Hanselmann

1068 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1069 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1070 8235fe04 Michael Hanselmann
  @param node: Node object
1071 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1072 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1073 8235fe04 Michael Hanselmann

1074 8235fe04 Michael Hanselmann
  """
1075 e2d188cc Iustin Pop
  return ng.name
1076 8235fe04 Michael Hanselmann
1077 8235fe04 Michael Hanselmann
1078 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1079 52b5d286 René Nussbaumer
  """Returns the node powered state
1080 52b5d286 René Nussbaumer

1081 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1082 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1083 52b5d286 René Nussbaumer
  @param node: Node object
1084 52b5d286 René Nussbaumer

1085 52b5d286 René Nussbaumer
  """
1086 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1087 e2d188cc Iustin Pop
    return node.powered
1088 52b5d286 René Nussbaumer
1089 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1090 52b5d286 René Nussbaumer
1091 52b5d286 René Nussbaumer
1092 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1093 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1094 8572f1fe René Nussbaumer

1095 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1096 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1097 8572f1fe René Nussbaumer
  @param node: Node object
1098 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1099 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1100 8572f1fe René Nussbaumer

1101 8572f1fe René Nussbaumer
  """
1102 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1103 8572f1fe René Nussbaumer
1104 8572f1fe René Nussbaumer
1105 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1106 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1107 8235fe04 Michael Hanselmann

1108 8235fe04 Michael Hanselmann
  @param field: Live field name
1109 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1110 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1111 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1112 a6070ef7 Michael Hanselmann
  @param node: Node object
1113 8235fe04 Michael Hanselmann

1114 8235fe04 Michael Hanselmann
  """
1115 a6070ef7 Michael Hanselmann
  if node.offline:
1116 e2d188cc Iustin Pop
    return _FS_OFFLINE
1117 a6070ef7 Michael Hanselmann
1118 effab4ca Iustin Pop
  if not node.vm_capable:
1119 effab4ca Iustin Pop
    return _FS_UNAVAIL
1120 effab4ca Iustin Pop
1121 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1122 e2d188cc Iustin Pop
    return _FS_NODATA
1123 8235fe04 Michael Hanselmann
1124 8235fe04 Michael Hanselmann
  try:
1125 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1126 8235fe04 Michael Hanselmann
  except KeyError:
1127 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1128 8235fe04 Michael Hanselmann
1129 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1130 e2d188cc Iustin Pop
    return value
1131 8235fe04 Michael Hanselmann
1132 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1133 8235fe04 Michael Hanselmann
1134 8235fe04 Michael Hanselmann
  # Try to convert into number
1135 8235fe04 Michael Hanselmann
  try:
1136 e2d188cc Iustin Pop
    return int(value)
1137 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1138 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1139 8235fe04 Michael Hanselmann
                      value, field)
1140 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1141 8235fe04 Michael Hanselmann
1142 8235fe04 Michael Hanselmann
1143 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1144 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1145 54ac87c0 Michael Hanselmann

1146 54ac87c0 Michael Hanselmann
  """
1147 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1148 54ac87c0 Michael Hanselmann
1149 54ac87c0 Michael Hanselmann
  if hv_state is None:
1150 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1151 54ac87c0 Michael Hanselmann
1152 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1153 54ac87c0 Michael Hanselmann
1154 54ac87c0 Michael Hanselmann
1155 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1156 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1157 54ac87c0 Michael Hanselmann

1158 54ac87c0 Michael Hanselmann
  """
1159 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1160 54ac87c0 Michael Hanselmann
1161 54ac87c0 Michael Hanselmann
  if disk_state is None:
1162 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1163 54ac87c0 Michael Hanselmann
1164 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1165 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1166 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1167 54ac87c0 Michael Hanselmann
1168 54ac87c0 Michael Hanselmann
1169 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1170 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1171 8235fe04 Michael Hanselmann

1172 8235fe04 Michael Hanselmann
  """
1173 8235fe04 Michael Hanselmann
  fields = [
1174 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1175 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1176 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1177 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1178 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1179 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1180 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1181 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, lambda ctx, node: node.name == ctx.master_name),
1182 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1183 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1184 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1185 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1186 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1187 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1188 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1189 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1190 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1191 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1192 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1193 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1194 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1195 54ac87c0 Michael Hanselmann
    (_MakeField("hv_state", "HypervisorState", QFT_OTHER, "Hypervisor state"),
1196 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeHvState),
1197 54ac87c0 Michael Hanselmann
    (_MakeField("disk_state", "DiskState", QFT_OTHER, "Disk state"),
1198 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeDiskState),
1199 8235fe04 Michael Hanselmann
    ]
1200 8235fe04 Michael Hanselmann
1201 79b2ca83 Michael Hanselmann
  # Node role
1202 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1203 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1204 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1205 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1206 79b2ca83 Michael Hanselmann
              " \"%s\" for regular, \"%s\" for a drained, \"%s\" for offline" %
1207 79b2ca83 Michael Hanselmann
              role_values)
1208 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1209 79b2ca83 Michael Hanselmann
                 lambda ctx, node: _GetNodeRole(node, ctx.master_name)))
1210 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1211 79b2ca83 Michael Hanselmann
1212 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1213 e2d188cc Iustin Pop
    return lambda ctx, node: len(getter(ctx)[node.name])
1214 8235fe04 Michael Hanselmann
1215 8235fe04 Michael Hanselmann
  def _GetList(getter):
1216 e2d188cc Iustin Pop
    return lambda ctx, node: list(getter(ctx)[node.name])
1217 8235fe04 Michael Hanselmann
1218 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1219 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1220 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1221 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1222 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1223 8235fe04 Michael Hanselmann
    fields.extend([
1224 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1225 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1226 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1227 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1228 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1229 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1230 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1231 8235fe04 Michael Hanselmann
      ])
1232 8235fe04 Michael Hanselmann
1233 8235fe04 Michael Hanselmann
  # Add simple fields
1234 111bf531 Michael Hanselmann
  fields.extend([
1235 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1236 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()
1237 111bf531 Michael Hanselmann
    ])
1238 8235fe04 Michael Hanselmann
1239 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1240 8235fe04 Michael Hanselmann
  fields.extend([
1241 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1242 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1243 79b2ca83 Michael Hanselmann
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()
1244 8235fe04 Michael Hanselmann
    ])
1245 8235fe04 Michael Hanselmann
1246 145bea54 Michael Hanselmann
  # Add timestamps
1247 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1248 145bea54 Michael Hanselmann
1249 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1250 8235fe04 Michael Hanselmann
1251 8235fe04 Michael Hanselmann
1252 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1253 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1254 1c8addc6 Michael Hanselmann

1255 1c8addc6 Michael Hanselmann
  """
1256 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1257 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1258 1c8addc6 Michael Hanselmann
    """Initializes this class.
1259 1c8addc6 Michael Hanselmann

1260 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1261 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1262 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1263 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1264 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1265 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1266 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1267 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1268 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1269 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1270 e431074f René Nussbaumer
    @type wrongnode_inst: set
1271 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1272 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1273 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1274 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1275 fab9573b Michael Hanselmann
    @param nodes: Node objects
1276 1c8addc6 Michael Hanselmann

1277 1c8addc6 Michael Hanselmann
    """
1278 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1279 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1280 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1281 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1282 1c8addc6 Michael Hanselmann
1283 1c8addc6 Michael Hanselmann
    self.instances = instances
1284 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1285 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1286 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1287 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1288 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1289 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1290 5d28cb6f Michael Hanselmann
    self.console = console
1291 fab9573b Michael Hanselmann
    self.nodes = nodes
1292 fab9573b Michael Hanselmann
    self.groups = groups
1293 1c8addc6 Michael Hanselmann
1294 1c8addc6 Michael Hanselmann
    # Used for individual rows
1295 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1296 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1297 7c670076 Michael Hanselmann
    self.inst_osparams = None
1298 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1299 1c8addc6 Michael Hanselmann
1300 1c8addc6 Michael Hanselmann
  def __iter__(self):
1301 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1302 1c8addc6 Michael Hanselmann

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

1306 1c8addc6 Michael Hanselmann
    """
1307 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1308 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1309 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1310 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1311 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1312 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1313 1c8addc6 Michael Hanselmann
1314 1c8addc6 Michael Hanselmann
      yield inst
1315 1c8addc6 Michael Hanselmann
1316 1c8addc6 Michael Hanselmann
1317 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1318 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1319 1c8addc6 Michael Hanselmann

1320 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1321 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1322 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1323 1c8addc6 Michael Hanselmann

1324 1c8addc6 Michael Hanselmann
  """
1325 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1326 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1327 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1328 e2d188cc Iustin Pop
    return _FS_NODATA
1329 1c8addc6 Michael Hanselmann
  else:
1330 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1331 1c8addc6 Michael Hanselmann
1332 1c8addc6 Michael Hanselmann
1333 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1334 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1335 1c8addc6 Michael Hanselmann

1336 1c8addc6 Michael Hanselmann
  @type name: string
1337 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1338 1c8addc6 Michael Hanselmann

1339 1c8addc6 Michael Hanselmann
  """
1340 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1341 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1342 1c8addc6 Michael Hanselmann

1343 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1344 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1345 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1346 1c8addc6 Michael Hanselmann

1347 1c8addc6 Michael Hanselmann
    """
1348 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1349 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1350 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1351 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1352 e2d188cc Iustin Pop
      return _FS_NODATA
1353 1c8addc6 Michael Hanselmann
1354 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1355 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1356 1c8addc6 Michael Hanselmann
      if name in data:
1357 e2d188cc Iustin Pop
        return data[name]
1358 1c8addc6 Michael Hanselmann
1359 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1360 1c8addc6 Michael Hanselmann
1361 1c8addc6 Michael Hanselmann
  return fn
1362 1c8addc6 Michael Hanselmann
1363 1c8addc6 Michael Hanselmann
1364 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1365 1c8addc6 Michael Hanselmann
  """Get instance status.
1366 1c8addc6 Michael Hanselmann

1367 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1368 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1369 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1370 1c8addc6 Michael Hanselmann

1371 1c8addc6 Michael Hanselmann
  """
1372 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1373 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1374 1c8addc6 Michael Hanselmann
1375 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1376 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1377 1c8addc6 Michael Hanselmann
1378 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1379 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1380 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1381 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1382 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1383 1c8addc6 Michael Hanselmann
    else:
1384 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1385 1c8addc6 Michael Hanselmann
1386 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1387 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1388 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1389 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1390 1c8addc6 Michael Hanselmann
1391 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1392 1c8addc6 Michael Hanselmann
1393 1c8addc6 Michael Hanselmann
1394 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1395 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1396 1c8addc6 Michael Hanselmann

1397 1c8addc6 Michael Hanselmann
  @type index: int
1398 1c8addc6 Michael Hanselmann
  @param index: Disk index
1399 1c8addc6 Michael Hanselmann

1400 1c8addc6 Michael Hanselmann
  """
1401 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1402 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1403 1c8addc6 Michael Hanselmann

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

1407 1c8addc6 Michael Hanselmann
    """
1408 1c8addc6 Michael Hanselmann
    try:
1409 e2d188cc Iustin Pop
      return inst.disks[index].size
1410 1c8addc6 Michael Hanselmann
    except IndexError:
1411 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1412 1c8addc6 Michael Hanselmann
1413 1c8addc6 Michael Hanselmann
  return fn
1414 1c8addc6 Michael Hanselmann
1415 1c8addc6 Michael Hanselmann
1416 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1417 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1418 1c8addc6 Michael Hanselmann

1419 1c8addc6 Michael Hanselmann
  @type index: int
1420 1c8addc6 Michael Hanselmann
  @param index: NIC index
1421 1c8addc6 Michael Hanselmann
  @type cb: callable
1422 1c8addc6 Michael Hanselmann
  @param cb: Callback
1423 1c8addc6 Michael Hanselmann

1424 1c8addc6 Michael Hanselmann
  """
1425 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1426 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1427 1c8addc6 Michael Hanselmann

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

1432 1c8addc6 Michael Hanselmann
    """
1433 1c8addc6 Michael Hanselmann
    try:
1434 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1435 1c8addc6 Michael Hanselmann
    except IndexError:
1436 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1437 1c8addc6 Michael Hanselmann
1438 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1439 1c8addc6 Michael Hanselmann
1440 1c8addc6 Michael Hanselmann
  return fn
1441 1c8addc6 Michael Hanselmann
1442 1c8addc6 Michael Hanselmann
1443 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1444 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1445 1c8addc6 Michael Hanselmann

1446 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1447 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1448 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1449 1c8addc6 Michael Hanselmann

1450 1c8addc6 Michael Hanselmann
  """
1451 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1452 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1453 1c8addc6 Michael Hanselmann
  else:
1454 e2d188cc Iustin Pop
    return nic.ip
1455 1c8addc6 Michael Hanselmann
1456 1c8addc6 Michael Hanselmann
1457 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1458 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1459 1c8addc6 Michael Hanselmann

1460 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1461 1c8addc6 Michael Hanselmann
  @type index: int
1462 1c8addc6 Michael Hanselmann
  @param index: NIC index
1463 1c8addc6 Michael Hanselmann

1464 1c8addc6 Michael Hanselmann
  """
1465 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1466 1c8addc6 Michael Hanselmann
1467 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1468 1c8addc6 Michael Hanselmann
1469 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1470 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1471 1c8addc6 Michael Hanselmann
  else:
1472 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1473 1c8addc6 Michael Hanselmann
1474 1c8addc6 Michael Hanselmann
1475 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1476 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1477 1c8addc6 Michael Hanselmann

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

1482 1c8addc6 Michael Hanselmann
  """
1483 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1484 1c8addc6 Michael Hanselmann
1485 1c8addc6 Michael Hanselmann
  result = []
1486 1c8addc6 Michael Hanselmann
1487 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1488 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1489 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1490 1c8addc6 Michael Hanselmann
    else:
1491 1c8addc6 Michael Hanselmann
      result.append(None)
1492 1c8addc6 Michael Hanselmann
1493 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1494 1c8addc6 Michael Hanselmann
1495 e2d188cc Iustin Pop
  return result
1496 1c8addc6 Michael Hanselmann
1497 1c8addc6 Michael Hanselmann
1498 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1499 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1500 1c8addc6 Michael Hanselmann

1501 1c8addc6 Michael Hanselmann
  @type name: string
1502 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1503 1c8addc6 Michael Hanselmann

1504 1c8addc6 Michael Hanselmann
  """
1505 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1506 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1507 1c8addc6 Michael Hanselmann

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

1514 1c8addc6 Michael Hanselmann
    """
1515 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1516 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1517 1c8addc6 Michael Hanselmann
1518 1c8addc6 Michael Hanselmann
  return fn
1519 1c8addc6 Michael Hanselmann
1520 1c8addc6 Michael Hanselmann
1521 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1522 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1523 1c8addc6 Michael Hanselmann

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

1527 1c8addc6 Michael Hanselmann
  """
1528 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1529 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1530 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1531 1c8addc6 Michael Hanselmann
1532 1c8addc6 Michael Hanselmann
  fields = [
1533 1c8addc6 Michael Hanselmann
    # All NICs
1534 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1535 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1536 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1537 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1538 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1539 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1540 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1541 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1542 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1543 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1544 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1545 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1546 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1547 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1548 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1549 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1550 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1551 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1552 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1553 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1554 1c8addc6 Michael Hanselmann
    ]
1555 1c8addc6 Michael Hanselmann
1556 1c8addc6 Michael Hanselmann
  # NICs by number
1557 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1558 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1559 1c8addc6 Michael Hanselmann
    fields.extend([
1560 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1561 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1562 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1563 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1564 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1565 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1566 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1567 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1568 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1569 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1570 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1571 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1572 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1573 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1574 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1575 1c8addc6 Michael Hanselmann
      ])
1576 1c8addc6 Michael Hanselmann
1577 4cc4d1fa Michael Hanselmann
  aliases = [
1578 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1579 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1580 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1581 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1582 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1583 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1584 4cc4d1fa Michael Hanselmann
    ]
1585 4cc4d1fa Michael Hanselmann
1586 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1587 1c8addc6 Michael Hanselmann
1588 1c8addc6 Michael Hanselmann
1589 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1590 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1591 1c8addc6 Michael Hanselmann

1592 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1593 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1594 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1595 1c8addc6 Michael Hanselmann

1596 1c8addc6 Michael Hanselmann
  """
1597 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1598 1c8addc6 Michael Hanselmann
1599 1c8addc6 Michael Hanselmann
  if usage is None:
1600 1c8addc6 Michael Hanselmann
    usage = 0
1601 1c8addc6 Michael Hanselmann
1602 e2d188cc Iustin Pop
  return usage
1603 1c8addc6 Michael Hanselmann
1604 1c8addc6 Michael Hanselmann
1605 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1606 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1607 5d28cb6f Michael Hanselmann

1608 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1609 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1610 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1611 5d28cb6f Michael Hanselmann

1612 5d28cb6f Michael Hanselmann
  """
1613 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1614 5d28cb6f Michael Hanselmann
1615 5d28cb6f Michael Hanselmann
  if consinfo is None:
1616 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1617 5d28cb6f Michael Hanselmann
1618 5d28cb6f Michael Hanselmann
  return consinfo
1619 5d28cb6f Michael Hanselmann
1620 5d28cb6f Michael Hanselmann
1621 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1622 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1623 1c8addc6 Michael Hanselmann

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

1626 1c8addc6 Michael Hanselmann
  """
1627 1c8addc6 Michael Hanselmann
  fields = [
1628 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1629 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1630 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1631 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1632 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1633 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1634 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1635 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1636 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1637 1c8addc6 Michael Hanselmann
    ]
1638 1c8addc6 Michael Hanselmann
1639 1c8addc6 Michael Hanselmann
  # Disks by number
1640 1c8addc6 Michael Hanselmann
  fields.extend([
1641 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1642 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1643 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1644 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1645 1c8addc6 Michael Hanselmann
    ])
1646 1c8addc6 Michael Hanselmann
1647 1c8addc6 Michael Hanselmann
  return fields
1648 1c8addc6 Michael Hanselmann
1649 1c8addc6 Michael Hanselmann
1650 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1651 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1652 1c8addc6 Michael Hanselmann

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

1655 1c8addc6 Michael Hanselmann
  """
1656 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1657 1c8addc6 Michael Hanselmann
  be_title = {
1658 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1659 31d1791a Guido Trotter
    constants.BE_MAXMEM: "ConfigMaxMem",
1660 31d1791a Guido Trotter
    constants.BE_MINMEM: "ConfigMinMem",
1661 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1662 1c8addc6 Michael Hanselmann
    }
1663 1c8addc6 Michael Hanselmann
1664 1c8addc6 Michael Hanselmann
  hv_title = {
1665 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1666 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1667 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1668 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1669 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1670 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1671 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1672 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1673 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1674 1c8addc6 Michael Hanselmann
    }
1675 1c8addc6 Michael Hanselmann
1676 1c8addc6 Michael Hanselmann
  fields = [
1677 1c8addc6 Michael Hanselmann
    # Filled parameters
1678 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1679 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1680 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1681 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1682 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1683 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1684 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1685 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1686 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1687 1c8addc6 Michael Hanselmann
1688 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1689 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1690 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1691 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1692 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1693 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1694 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1695 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1696 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1697 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1698 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1699 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1700 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1701 1c8addc6 Michael Hanselmann
    ]
1702 1c8addc6 Michael Hanselmann
1703 1c8addc6 Michael Hanselmann
  # HV params
1704 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1705 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1706 1c8addc6 Michael Hanselmann
1707 1c8addc6 Michael Hanselmann
  fields.extend([
1708 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1709 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1710 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1711 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1712 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1713 1c8addc6 Michael Hanselmann
    ])
1714 1c8addc6 Michael Hanselmann
1715 1c8addc6 Michael Hanselmann
  # BE params
1716 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1717 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1718 1c8addc6 Michael Hanselmann
1719 1c8addc6 Michael Hanselmann
  fields.extend([
1720 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1721 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1722 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1723 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1724 1c8addc6 Michael Hanselmann
    ])
1725 1c8addc6 Michael Hanselmann
1726 1c8addc6 Michael Hanselmann
  return fields
1727 1c8addc6 Michael Hanselmann
1728 1c8addc6 Michael Hanselmann
1729 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1730 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1731 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1732 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1733 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1734 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1735 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1736 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1737 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1738 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1739 1c8addc6 Michael Hanselmann
  }
1740 1c8addc6 Michael Hanselmann
1741 1c8addc6 Michael Hanselmann
1742 fab9573b Michael Hanselmann
def _GetInstNodeGroup(ctx, default, node_name):
1743 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
1744 fab9573b Michael Hanselmann

1745 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1746 fab9573b Michael Hanselmann
  @param default: Default value
1747 fab9573b Michael Hanselmann
  @type node_name: string
1748 fab9573b Michael Hanselmann
  @param node_name: Node name
1749 fab9573b Michael Hanselmann

1750 fab9573b Michael Hanselmann
  """
1751 fab9573b Michael Hanselmann
  try:
1752 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1753 fab9573b Michael Hanselmann
  except KeyError:
1754 fab9573b Michael Hanselmann
    return default
1755 fab9573b Michael Hanselmann
  else:
1756 fab9573b Michael Hanselmann
    return node.group
1757 fab9573b Michael Hanselmann
1758 fab9573b Michael Hanselmann
1759 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1760 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1761 fab9573b Michael Hanselmann

1762 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1763 fab9573b Michael Hanselmann
  @param default: Default value
1764 fab9573b Michael Hanselmann
  @type node_name: string
1765 fab9573b Michael Hanselmann
  @param node_name: Node name
1766 fab9573b Michael Hanselmann

1767 fab9573b Michael Hanselmann
  """
1768 fab9573b Michael Hanselmann
  try:
1769 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1770 fab9573b Michael Hanselmann
  except KeyError:
1771 fab9573b Michael Hanselmann
    return default
1772 fab9573b Michael Hanselmann
1773 fab9573b Michael Hanselmann
  try:
1774 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1775 fab9573b Michael Hanselmann
  except KeyError:
1776 fab9573b Michael Hanselmann
    return default
1777 fab9573b Michael Hanselmann
1778 fab9573b Michael Hanselmann
  return group.name
1779 fab9573b Michael Hanselmann
1780 fab9573b Michael Hanselmann
1781 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1782 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1783 1c8addc6 Michael Hanselmann

1784 1c8addc6 Michael Hanselmann
  """
1785 1c8addc6 Michael Hanselmann
  fields = [
1786 111bf531 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", QFT_TEXT, "Primary node"),
1787 111bf531 Michael Hanselmann
     IQ_CONFIG, QFF_HOSTNAME, _GetItemAttr("primary_node")),
1788 fab9573b Michael Hanselmann
    (_MakeField("pnode.group", "PrimaryNodeGroup", QFT_TEXT,
1789 fab9573b Michael Hanselmann
                "Primary node's group"),
1790 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1791 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroupName(ctx, _FS_UNAVAIL,
1792 fab9573b Michael Hanselmann
                                             inst.primary_node)),
1793 fab9573b Michael Hanselmann
    (_MakeField("pnode.group.uuid", "PrimaryNodeGroupUUID", QFT_TEXT,
1794 fab9573b Michael Hanselmann
                "Primary node's group UUID"),
1795 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1796 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroup(ctx, _FS_UNAVAIL, inst.primary_node)),
1797 111bf531 Michael Hanselmann
    # TODO: Allow filtering by secondary node as hostname
1798 79b2ca83 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER,
1799 79b2ca83 Michael Hanselmann
                "Secondary nodes; usually this will just be one node"),
1800 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: list(inst.secondary_nodes)),
1801 fab9573b Michael Hanselmann
    (_MakeField("snodes.group", "SecondaryNodesGroups", QFT_OTHER,
1802 fab9573b Michael Hanselmann
                "Node groups of secondary nodes"),
1803 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1804 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroupName, ctx, None),
1805 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1806 fab9573b Michael Hanselmann
    (_MakeField("snodes.group.uuid", "SecondaryNodesGroupsUUID", QFT_OTHER,
1807 fab9573b Michael Hanselmann
                "Node group UUIDs of secondary nodes"),
1808 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1809 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroup, ctx, None),
1810 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1811 2e04d454 Agata Murawska
    (_MakeField("admin_state", "InstanceState", QFT_TEXT,
1812 2e04d454 Agata Murawska
                "Desired state of instance"),
1813 9ca8a7c5 Agata Murawska
     IQ_CONFIG, 0, _GetItemAttr("admin_state")),
1814 754cc530 Agata Murawska
    (_MakeField("admin_up", "Autostart", QFT_BOOL,
1815 754cc530 Agata Murawska
                "Desired state of instance"),
1816 754cc530 Agata Murawska
     IQ_CONFIG, 0, lambda ctx, inst: inst.admin_state == constants.ADMINST_UP),
1817 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
1818 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
1819 79b2ca83 Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER,
1820 111bf531 Michael Hanselmann
                "Instance console information"), IQ_CONSOLE, 0,
1821 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
1822 1c8addc6 Michael Hanselmann
    ]
1823 1c8addc6 Michael Hanselmann
1824 1c8addc6 Michael Hanselmann
  # Add simple fields
1825 111bf531 Michael Hanselmann
  fields.extend([
1826 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
1827 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()
1828 111bf531 Michael Hanselmann
    ])
1829 1c8addc6 Michael Hanselmann
1830 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1831 1c8addc6 Michael Hanselmann
  fields.extend([
1832 79b2ca83 Michael Hanselmann
    (_MakeField("oper_state", "Running", QFT_BOOL, "Actual state of instance"),
1833 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstOperState),
1834 79b2ca83 Michael Hanselmann
    (_MakeField("oper_ram", "Memory", QFT_UNIT,
1835 79b2ca83 Michael Hanselmann
                "Actual memory usage as seen by hypervisor"),
1836 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("memory")),
1837 79b2ca83 Michael Hanselmann
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER,
1838 79b2ca83 Michael Hanselmann
                "Actual number of VCPUs as seen by hypervisor"),
1839 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("vcpus")),
1840 1c8addc6 Michael Hanselmann
    ])
1841 1c8addc6 Michael Hanselmann
1842 79b2ca83 Michael Hanselmann
  # Status field
1843 79b2ca83 Michael Hanselmann
  status_values = (constants.INSTST_RUNNING, constants.INSTST_ADMINDOWN,
1844 79b2ca83 Michael Hanselmann
                   constants.INSTST_WRONGNODE, constants.INSTST_ERRORUP,
1845 79b2ca83 Michael Hanselmann
                   constants.INSTST_ERRORDOWN, constants.INSTST_NODEDOWN,
1846 2e04d454 Agata Murawska
                   constants.INSTST_NODEOFFLINE, constants.INSTST_ADMINOFFLINE)
1847 79b2ca83 Michael Hanselmann
  status_doc = ("Instance status; \"%s\" if instance is set to be running"
1848 79b2ca83 Michael Hanselmann
                " and actually is, \"%s\" if instance is stopped and"
1849 79b2ca83 Michael Hanselmann
                " is not running, \"%s\" if instance running, but not on its"
1850 79b2ca83 Michael Hanselmann
                " designated primary node, \"%s\" if instance should be"
1851 79b2ca83 Michael Hanselmann
                " stopped, but is actually running, \"%s\" if instance should"
1852 79b2ca83 Michael Hanselmann
                " run, but doesn't, \"%s\" if instance's primary node is down,"
1853 2e04d454 Agata Murawska
                " \"%s\" if instance's primary node is marked offline,"
1854 2e04d454 Agata Murawska
                " \"%s\" if instance is offline and does not use dynamic"
1855 2e04d454 Agata Murawska
                " resources" % status_values)
1856 79b2ca83 Michael Hanselmann
  fields.append((_MakeField("status", "Status", QFT_TEXT, status_doc),
1857 111bf531 Michael Hanselmann
                 IQ_LIVE, 0, _GetInstStatus))
1858 79b2ca83 Michael Hanselmann
  assert set(status_values) == constants.INSTST_ALL, \
1859 79b2ca83 Michael Hanselmann
         "Status documentation mismatch"
1860 79b2ca83 Michael Hanselmann
1861 4cc4d1fa Michael Hanselmann
  (network_fields, network_aliases) = _GetInstanceNetworkFields()
1862 4cc4d1fa Michael Hanselmann
1863 4cc4d1fa Michael Hanselmann
  fields.extend(network_fields)
1864 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1865 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1866 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1867 1c8addc6 Michael Hanselmann
1868 e7e8037b Iustin Pop
  aliases = [
1869 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
1870 31d1791a Guido Trotter
    ("be/memory", "be/maxmem"),
1871 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
1872 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
1873 4cc4d1fa Michael Hanselmann
    ] + network_aliases
1874 e7e8037b Iustin Pop
1875 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
1876 1c8addc6 Michael Hanselmann
1877 1c8addc6 Michael Hanselmann
1878 24d16f76 Michael Hanselmann
class LockQueryData:
1879 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1880 24d16f76 Michael Hanselmann

1881 24d16f76 Michael Hanselmann
  """
1882 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1883 24d16f76 Michael Hanselmann
    """Initializes this class.
1884 24d16f76 Michael Hanselmann

1885 24d16f76 Michael Hanselmann
    """
1886 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1887 24d16f76 Michael Hanselmann
1888 24d16f76 Michael Hanselmann
  def __iter__(self):
1889 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1890 24d16f76 Michael Hanselmann

1891 24d16f76 Michael Hanselmann
    """
1892 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1893 24d16f76 Michael Hanselmann
1894 24d16f76 Michael Hanselmann
1895 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1896 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1897 24d16f76 Michael Hanselmann

1898 24d16f76 Michael Hanselmann
  """
1899 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1900 24d16f76 Michael Hanselmann
1901 24d16f76 Michael Hanselmann
  if owners:
1902 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1903 24d16f76 Michael Hanselmann
1904 e2d188cc Iustin Pop
  return owners
1905 24d16f76 Michael Hanselmann
1906 24d16f76 Michael Hanselmann
1907 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1908 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1909 24d16f76 Michael Hanselmann

1910 24d16f76 Michael Hanselmann
  """
1911 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1912 24d16f76 Michael Hanselmann
1913 24d16f76 Michael Hanselmann
  if pending:
1914 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1915 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1916 24d16f76 Michael Hanselmann
1917 e2d188cc Iustin Pop
  return pending
1918 24d16f76 Michael Hanselmann
1919 24d16f76 Michael Hanselmann
1920 24d16f76 Michael Hanselmann
def _BuildLockFields():
1921 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1922 24d16f76 Michael Hanselmann

1923 24d16f76 Michael Hanselmann
  """
1924 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1925 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
1926 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
1927 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1928 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
1929 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
1930 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
1931 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
1932 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
1933 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
1934 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
1935 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
1936 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
1937 d63bd540 Iustin Pop
    ], [])
1938 24d16f76 Michael Hanselmann
1939 24d16f76 Michael Hanselmann
1940 8e21cfc0 Adeodato Simo
class GroupQueryData:
1941 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1942 8e21cfc0 Adeodato Simo

1943 8e21cfc0 Adeodato Simo
  """
1944 edd49f9b Agata Murawska
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances):
1945 8e21cfc0 Adeodato Simo
    """Initializes this class.
1946 8e21cfc0 Adeodato Simo

1947 edd49f9b Agata Murawska
    @param cluster: Cluster object
1948 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1949 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1950 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1951 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1952 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1953 8e21cfc0 Adeodato Simo

1954 8e21cfc0 Adeodato Simo
    """
1955 8e21cfc0 Adeodato Simo
    self.groups = groups
1956 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1957 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1958 edd49f9b Agata Murawska
    self.cluster = cluster
1959 edd49f9b Agata Murawska
1960 edd49f9b Agata Murawska
    # Used for individual rows
1961 edd49f9b Agata Murawska
    self.group_ipolicy = None
1962 8e21cfc0 Adeodato Simo
1963 8e21cfc0 Adeodato Simo
  def __iter__(self):
1964 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1965 8e21cfc0 Adeodato Simo

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

1969 8e21cfc0 Adeodato Simo
    """
1970 edd49f9b Agata Murawska
    for group in self.groups:
1971 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
1972 edd49f9b Agata Murawska
      yield group
1973 8e21cfc0 Adeodato Simo
1974 8e21cfc0 Adeodato Simo
1975 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1976 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
1977 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
1978 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
1979 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
1980 79b2ca83 Michael Hanselmann
  "ndparams": ("NDParams", QFT_OTHER, "Node parameters"),
1981 8e21cfc0 Adeodato Simo
  }
1982 8e21cfc0 Adeodato Simo
1983 8e21cfc0 Adeodato Simo
1984 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1985 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1986 8e21cfc0 Adeodato Simo

1987 8e21cfc0 Adeodato Simo
  """
1988 8e21cfc0 Adeodato Simo
  # Add simple fields
1989 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
1990 111bf531 Michael Hanselmann
             _GetItemAttr(name))
1991 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
1992 8e21cfc0 Adeodato Simo
1993 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1994 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
1995 8e21cfc0 Adeodato Simo
1996 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1997 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
1998 8e21cfc0 Adeodato Simo
1999 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
2000 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
2001 8e21cfc0 Adeodato Simo
2002 8e21cfc0 Adeodato Simo
  # Add fields for nodes
2003 8e21cfc0 Adeodato Simo
  fields.extend([
2004 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
2005 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
2006 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
2007 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
2008 8e21cfc0 Adeodato Simo
    ])
2009 8e21cfc0 Adeodato Simo
2010 8e21cfc0 Adeodato Simo
  # Add fields for instances
2011 8e21cfc0 Adeodato Simo
  fields.extend([
2012 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
2013 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
2014 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
2015 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
2016 79b2ca83 Michael Hanselmann
                "List of primary instances"),
2017 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
2018 8e21cfc0 Adeodato Simo
    ])
2019 8e21cfc0 Adeodato Simo
2020 1ffd2673 Michael Hanselmann
  # Other fields
2021 1ffd2673 Michael Hanselmann
  fields.extend([
2022 1ffd2673 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
2023 1ffd2673 Michael Hanselmann
     lambda ctx, group: list(group.GetTags())),
2024 edd49f9b Agata Murawska
    (_MakeField("ipolicy", "InstancePolicy", QFT_OTHER,
2025 edd49f9b Agata Murawska
                "Instance policy limitations (merged)"),
2026 edd49f9b Agata Murawska
     GQ_CONFIG, 0, lambda ctx, _: ctx.group_ipolicy),
2027 edd49f9b Agata Murawska
    (_MakeField("custom_ipolicy", "CustomInstancePolicy", QFT_OTHER,
2028 edd49f9b Agata Murawska
                "Custom instance policy limitations"),
2029 edd49f9b Agata Murawska
     GQ_CONFIG, 0, _GetItemAttr("ipolicy")),
2030 1ffd2673 Michael Hanselmann
    ])
2031 1ffd2673 Michael Hanselmann
2032 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
2033 8e21cfc0 Adeodato Simo
2034 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
2035 8e21cfc0 Adeodato Simo
2036 8e21cfc0 Adeodato Simo
2037 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
2038 be3a4b14 Michael Hanselmann
  __slots__ = [
2039 be3a4b14 Michael Hanselmann
    "name",
2040 be3a4b14 Michael Hanselmann
    "valid",
2041 be3a4b14 Michael Hanselmann
    "hidden",
2042 be3a4b14 Michael Hanselmann
    "blacklisted",
2043 be3a4b14 Michael Hanselmann
    "variants",
2044 be3a4b14 Michael Hanselmann
    "api_versions",
2045 be3a4b14 Michael Hanselmann
    "parameters",
2046 be3a4b14 Michael Hanselmann
    "node_status",
2047 be3a4b14 Michael Hanselmann
    ]
2048 be3a4b14 Michael Hanselmann
2049 be3a4b14 Michael Hanselmann
2050 be3a4b14 Michael Hanselmann
def _BuildOsFields():
2051 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
2052 be3a4b14 Michael Hanselmann

2053 be3a4b14 Michael Hanselmann
  """
2054 be3a4b14 Michael Hanselmann
  fields = [
2055 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2056 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2057 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2058 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2059 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2060 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2061 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2062 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2063 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2064 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2065 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2066 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2067 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2068 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2069 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2070 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2071 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2072 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2073 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2074 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2075 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2076 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2077 be3a4b14 Michael Hanselmann
                "Status from node"),
2078 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2079 be3a4b14 Michael Hanselmann
    ]
2080 be3a4b14 Michael Hanselmann
2081 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2082 be3a4b14 Michael Hanselmann
2083 be3a4b14 Michael Hanselmann
2084 8235fe04 Michael Hanselmann
#: Fields available for node queries
2085 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2086 1c8addc6 Michael Hanselmann
2087 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2088 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2089 24d16f76 Michael Hanselmann
2090 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2091 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2092 e571ee44 Adeodato Simo
2093 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2094 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2095 8e21cfc0 Adeodato Simo
2096 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2097 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2098 be3a4b14 Michael Hanselmann
2099 95eb4188 Michael Hanselmann
#: All available resources
2100 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2101 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2102 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2103 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2104 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2105 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2106 95eb4188 Michael Hanselmann
  }
2107 95eb4188 Michael Hanselmann
2108 e571ee44 Adeodato Simo
#: All available field lists
2109 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()