Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 98dfcaff

History | View | Annotate | Download (59.9 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 fb0be379 Michael Hanselmann
  def __call__(self, hints, filter_):
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 fb0be379 Michael Hanselmann
    @type filter_: list
418 fb0be379 Michael Hanselmann
    @param filter_: 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 fb0be379 Michael Hanselmann
      filter_fn = self._Compile(filter_, 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 fb0be379 Michael Hanselmann
  def _Compile(self, filter_, 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 fb0be379 Michael Hanselmann
    if not (isinstance(filter_, (list, tuple)) and filter_):
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 fb0be379 Michael Hanselmann
    operands = filter_[:]
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 fb0be379 Michael Hanselmann
def _CompileFilter(fields, hints, filter_):
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 fb0be379 Michael Hanselmann
  return _FilterCompilerHelper(fields)(hints, filter_)
593 fb0be379 Michael Hanselmann
594 fb0be379 Michael Hanselmann
595 4ca96421 Michael Hanselmann
class Query:
596 fb0be379 Michael Hanselmann
  def __init__(self, fieldlist, selected, filter_=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 fb0be379 Michael Hanselmann
    if filter_ 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 fb0be379 Michael Hanselmann
      self._filter_fn = _CompileFilter(fieldlist, hints, filter_)
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 d1c3c3b3 Iustin Pop
                    (utils.CommaJoin(errors), row))
767 4ca96421 Michael Hanselmann
768 4ca96421 Michael Hanselmann
769 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
770 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
771 4ca96421 Michael Hanselmann

772 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
773 4ca96421 Michael Hanselmann

774 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
775 d63bd540 Iustin Pop
      kind, retrieval function)
776 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
777 d63bd540 Iustin Pop
      description
778 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
779 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
780 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
781 4ca96421 Michael Hanselmann
  @rtype: dict
782 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
783 4ca96421 Michael Hanselmann

784 4ca96421 Michael Hanselmann
  """
785 89ce4acc Michael Hanselmann
  if __debug__:
786 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
787 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
788 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
789 4ca96421 Michael Hanselmann
790 4ca96421 Michael Hanselmann
  result = {}
791 4ca96421 Michael Hanselmann
792 4ca96421 Michael Hanselmann
  for field in fields:
793 111bf531 Michael Hanselmann
    (fdef, _, flags, fn) = field
794 4ca96421 Michael Hanselmann
795 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
796 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
797 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
798 79b2ca83 Michael Hanselmann
    assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
799 79b2ca83 Michael Hanselmann
            fdef.doc.strip() == fdef.doc), \
800 79b2ca83 Michael Hanselmann
           "Invalid description for field '%s'" % fdef.name
801 4ca96421 Michael Hanselmann
    assert callable(fn)
802 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
803 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
804 111bf531 Michael Hanselmann
    assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
805 4ca96421 Michael Hanselmann
806 4ca96421 Michael Hanselmann
    result[fdef.name] = field
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 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1144 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1145 8235fe04 Michael Hanselmann

1146 8235fe04 Michael Hanselmann
  """
1147 8235fe04 Michael Hanselmann
  fields = [
1148 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1149 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1150 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1151 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1152 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1153 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1154 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1155 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, lambda ctx, node: node.name == ctx.master_name),
1156 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1157 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1158 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1159 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1160 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1161 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1162 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1163 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1164 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1165 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1166 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1167 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1168 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1169 8235fe04 Michael Hanselmann
    ]
1170 8235fe04 Michael Hanselmann
1171 79b2ca83 Michael Hanselmann
  # Node role
1172 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1173 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1174 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1175 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1176 79b2ca83 Michael Hanselmann
              " \"%s\" for regular, \"%s\" for a drained, \"%s\" for offline" %
1177 79b2ca83 Michael Hanselmann
              role_values)
1178 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1179 79b2ca83 Michael Hanselmann
                 lambda ctx, node: _GetNodeRole(node, ctx.master_name)))
1180 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1181 79b2ca83 Michael Hanselmann
1182 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1183 e2d188cc Iustin Pop
    return lambda ctx, node: len(getter(ctx)[node.name])
1184 8235fe04 Michael Hanselmann
1185 8235fe04 Michael Hanselmann
  def _GetList(getter):
1186 e2d188cc Iustin Pop
    return lambda ctx, node: list(getter(ctx)[node.name])
1187 8235fe04 Michael Hanselmann
1188 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1189 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1190 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1191 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1192 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1193 8235fe04 Michael Hanselmann
    fields.extend([
1194 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1195 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1196 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1197 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1198 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1199 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1200 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1201 8235fe04 Michael Hanselmann
      ])
1202 8235fe04 Michael Hanselmann
1203 8235fe04 Michael Hanselmann
  # Add simple fields
1204 111bf531 Michael Hanselmann
  fields.extend([
1205 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1206 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()
1207 111bf531 Michael Hanselmann
    ])
1208 8235fe04 Michael Hanselmann
1209 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1210 8235fe04 Michael Hanselmann
  fields.extend([
1211 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1212 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1213 79b2ca83 Michael Hanselmann
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()
1214 8235fe04 Michael Hanselmann
    ])
1215 8235fe04 Michael Hanselmann
1216 145bea54 Michael Hanselmann
  # Add timestamps
1217 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1218 145bea54 Michael Hanselmann
1219 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1220 8235fe04 Michael Hanselmann
1221 8235fe04 Michael Hanselmann
1222 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1223 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1224 1c8addc6 Michael Hanselmann

1225 1c8addc6 Michael Hanselmann
  """
1226 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1227 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1228 1c8addc6 Michael Hanselmann
    """Initializes this class.
1229 1c8addc6 Michael Hanselmann

1230 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1231 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1232 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1233 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1234 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1235 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1236 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1237 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1238 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1239 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1240 e431074f René Nussbaumer
    @type wrongnode_inst: set
1241 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1242 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1243 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1244 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1245 fab9573b Michael Hanselmann
    @param nodes: Node objects
1246 1c8addc6 Michael Hanselmann

1247 1c8addc6 Michael Hanselmann
    """
1248 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1249 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1250 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1251 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1252 1c8addc6 Michael Hanselmann
1253 1c8addc6 Michael Hanselmann
    self.instances = instances
1254 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1255 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1256 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1257 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1258 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1259 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1260 5d28cb6f Michael Hanselmann
    self.console = console
1261 fab9573b Michael Hanselmann
    self.nodes = nodes
1262 fab9573b Michael Hanselmann
    self.groups = groups
1263 1c8addc6 Michael Hanselmann
1264 1c8addc6 Michael Hanselmann
    # Used for individual rows
1265 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1266 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1267 7c670076 Michael Hanselmann
    self.inst_osparams = None
1268 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1269 1c8addc6 Michael Hanselmann
1270 1c8addc6 Michael Hanselmann
  def __iter__(self):
1271 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1272 1c8addc6 Michael Hanselmann

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

1276 1c8addc6 Michael Hanselmann
    """
1277 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1278 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1279 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1280 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1281 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1282 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1283 1c8addc6 Michael Hanselmann
1284 1c8addc6 Michael Hanselmann
      yield inst
1285 1c8addc6 Michael Hanselmann
1286 1c8addc6 Michael Hanselmann
1287 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1288 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1289 1c8addc6 Michael Hanselmann

1290 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1291 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1292 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1293 1c8addc6 Michael Hanselmann

1294 1c8addc6 Michael Hanselmann
  """
1295 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1296 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1297 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1298 e2d188cc Iustin Pop
    return _FS_NODATA
1299 1c8addc6 Michael Hanselmann
  else:
1300 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1301 1c8addc6 Michael Hanselmann
1302 1c8addc6 Michael Hanselmann
1303 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1304 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1305 1c8addc6 Michael Hanselmann

1306 1c8addc6 Michael Hanselmann
  @type name: string
1307 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1308 1c8addc6 Michael Hanselmann

1309 1c8addc6 Michael Hanselmann
  """
1310 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1311 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1312 1c8addc6 Michael Hanselmann

1313 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1314 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1315 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1316 1c8addc6 Michael Hanselmann

1317 1c8addc6 Michael Hanselmann
    """
1318 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1319 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1320 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1321 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1322 e2d188cc Iustin Pop
      return _FS_NODATA
1323 1c8addc6 Michael Hanselmann
1324 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1325 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1326 1c8addc6 Michael Hanselmann
      if name in data:
1327 e2d188cc Iustin Pop
        return data[name]
1328 1c8addc6 Michael Hanselmann
1329 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1330 1c8addc6 Michael Hanselmann
1331 1c8addc6 Michael Hanselmann
  return fn
1332 1c8addc6 Michael Hanselmann
1333 1c8addc6 Michael Hanselmann
1334 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1335 1c8addc6 Michael Hanselmann
  """Get instance status.
1336 1c8addc6 Michael Hanselmann

1337 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1338 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1339 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1340 1c8addc6 Michael Hanselmann

1341 1c8addc6 Michael Hanselmann
  """
1342 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1343 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1344 1c8addc6 Michael Hanselmann
1345 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1346 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1347 1c8addc6 Michael Hanselmann
1348 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1349 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1350 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1351 e431074f René Nussbaumer
    elif inst.admin_up:
1352 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1353 1c8addc6 Michael Hanselmann
    else:
1354 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1355 1c8addc6 Michael Hanselmann
1356 1c8addc6 Michael Hanselmann
  if inst.admin_up:
1357 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1358 1c8addc6 Michael Hanselmann
1359 61a980a9 Michael Hanselmann
  return constants.INSTST_ADMINDOWN
1360 1c8addc6 Michael Hanselmann
1361 1c8addc6 Michael Hanselmann
1362 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1363 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1364 1c8addc6 Michael Hanselmann

1365 1c8addc6 Michael Hanselmann
  @type index: int
1366 1c8addc6 Michael Hanselmann
  @param index: Disk index
1367 1c8addc6 Michael Hanselmann

1368 1c8addc6 Michael Hanselmann
  """
1369 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1370 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1371 1c8addc6 Michael Hanselmann

1372 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1373 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1374 1c8addc6 Michael Hanselmann

1375 1c8addc6 Michael Hanselmann
    """
1376 1c8addc6 Michael Hanselmann
    try:
1377 e2d188cc Iustin Pop
      return inst.disks[index].size
1378 1c8addc6 Michael Hanselmann
    except IndexError:
1379 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1380 1c8addc6 Michael Hanselmann
1381 1c8addc6 Michael Hanselmann
  return fn
1382 1c8addc6 Michael Hanselmann
1383 1c8addc6 Michael Hanselmann
1384 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1385 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1386 1c8addc6 Michael Hanselmann

1387 1c8addc6 Michael Hanselmann
  @type index: int
1388 1c8addc6 Michael Hanselmann
  @param index: NIC index
1389 1c8addc6 Michael Hanselmann
  @type cb: callable
1390 1c8addc6 Michael Hanselmann
  @param cb: Callback
1391 1c8addc6 Michael Hanselmann

1392 1c8addc6 Michael Hanselmann
  """
1393 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1394 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1395 1c8addc6 Michael Hanselmann

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

1400 1c8addc6 Michael Hanselmann
    """
1401 1c8addc6 Michael Hanselmann
    try:
1402 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1403 1c8addc6 Michael Hanselmann
    except IndexError:
1404 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1405 1c8addc6 Michael Hanselmann
1406 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1407 1c8addc6 Michael Hanselmann
1408 1c8addc6 Michael Hanselmann
  return fn
1409 1c8addc6 Michael Hanselmann
1410 1c8addc6 Michael Hanselmann
1411 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1412 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1413 1c8addc6 Michael Hanselmann

1414 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1415 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1416 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1417 1c8addc6 Michael Hanselmann

1418 1c8addc6 Michael Hanselmann
  """
1419 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1420 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1421 1c8addc6 Michael Hanselmann
  else:
1422 e2d188cc Iustin Pop
    return nic.ip
1423 1c8addc6 Michael Hanselmann
1424 1c8addc6 Michael Hanselmann
1425 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1426 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1427 1c8addc6 Michael Hanselmann

1428 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1429 1c8addc6 Michael Hanselmann
  @type index: int
1430 1c8addc6 Michael Hanselmann
  @param index: NIC index
1431 1c8addc6 Michael Hanselmann

1432 1c8addc6 Michael Hanselmann
  """
1433 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1434 1c8addc6 Michael Hanselmann
1435 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1436 1c8addc6 Michael Hanselmann
1437 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1438 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1439 1c8addc6 Michael Hanselmann
  else:
1440 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1441 1c8addc6 Michael Hanselmann
1442 1c8addc6 Michael Hanselmann
1443 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1444 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1445 1c8addc6 Michael Hanselmann

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

1450 1c8addc6 Michael Hanselmann
  """
1451 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1452 1c8addc6 Michael Hanselmann
1453 1c8addc6 Michael Hanselmann
  result = []
1454 1c8addc6 Michael Hanselmann
1455 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1456 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1457 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1458 1c8addc6 Michael Hanselmann
    else:
1459 1c8addc6 Michael Hanselmann
      result.append(None)
1460 1c8addc6 Michael Hanselmann
1461 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1462 1c8addc6 Michael Hanselmann
1463 e2d188cc Iustin Pop
  return result
1464 1c8addc6 Michael Hanselmann
1465 1c8addc6 Michael Hanselmann
1466 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1467 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1468 1c8addc6 Michael Hanselmann

1469 1c8addc6 Michael Hanselmann
  @type name: string
1470 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1471 1c8addc6 Michael Hanselmann

1472 1c8addc6 Michael Hanselmann
  """
1473 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1474 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1475 1c8addc6 Michael Hanselmann

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

1482 1c8addc6 Michael Hanselmann
    """
1483 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1484 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1485 1c8addc6 Michael Hanselmann
1486 1c8addc6 Michael Hanselmann
  return fn
1487 1c8addc6 Michael Hanselmann
1488 1c8addc6 Michael Hanselmann
1489 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1490 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1491 1c8addc6 Michael Hanselmann

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

1495 1c8addc6 Michael Hanselmann
  """
1496 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1497 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1498 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1499 1c8addc6 Michael Hanselmann
1500 1c8addc6 Michael Hanselmann
  fields = [
1501 1c8addc6 Michael Hanselmann
    # All NICs
1502 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1503 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1504 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1505 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1506 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1507 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1508 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1509 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1510 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1511 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1512 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1513 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1514 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1515 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1516 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1517 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1518 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1519 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1520 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1521 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1522 1c8addc6 Michael Hanselmann
    ]
1523 1c8addc6 Michael Hanselmann
1524 1c8addc6 Michael Hanselmann
  # NICs by number
1525 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1526 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1527 1c8addc6 Michael Hanselmann
    fields.extend([
1528 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1529 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1530 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1531 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1532 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1533 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1534 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1535 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1536 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1537 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1538 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1539 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1540 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1541 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1542 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1543 1c8addc6 Michael Hanselmann
      ])
1544 1c8addc6 Michael Hanselmann
1545 4cc4d1fa Michael Hanselmann
  aliases = [
1546 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1547 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1548 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1549 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1550 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1551 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1552 4cc4d1fa Michael Hanselmann
    ]
1553 4cc4d1fa Michael Hanselmann
1554 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1555 1c8addc6 Michael Hanselmann
1556 1c8addc6 Michael Hanselmann
1557 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1558 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1559 1c8addc6 Michael Hanselmann

1560 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1561 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1562 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1563 1c8addc6 Michael Hanselmann

1564 1c8addc6 Michael Hanselmann
  """
1565 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1566 1c8addc6 Michael Hanselmann
1567 1c8addc6 Michael Hanselmann
  if usage is None:
1568 1c8addc6 Michael Hanselmann
    usage = 0
1569 1c8addc6 Michael Hanselmann
1570 e2d188cc Iustin Pop
  return usage
1571 1c8addc6 Michael Hanselmann
1572 1c8addc6 Michael Hanselmann
1573 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1574 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1575 5d28cb6f Michael Hanselmann

1576 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1577 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1578 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1579 5d28cb6f Michael Hanselmann

1580 5d28cb6f Michael Hanselmann
  """
1581 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1582 5d28cb6f Michael Hanselmann
1583 5d28cb6f Michael Hanselmann
  if consinfo is None:
1584 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1585 5d28cb6f Michael Hanselmann
1586 5d28cb6f Michael Hanselmann
  return consinfo
1587 5d28cb6f Michael Hanselmann
1588 5d28cb6f Michael Hanselmann
1589 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1590 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1591 1c8addc6 Michael Hanselmann

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

1594 1c8addc6 Michael Hanselmann
  """
1595 1c8addc6 Michael Hanselmann
  fields = [
1596 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1597 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1598 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1599 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1600 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1601 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1602 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1603 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1604 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1605 1c8addc6 Michael Hanselmann
    ]
1606 1c8addc6 Michael Hanselmann
1607 1c8addc6 Michael Hanselmann
  # Disks by number
1608 1c8addc6 Michael Hanselmann
  fields.extend([
1609 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1610 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1611 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1612 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1613 1c8addc6 Michael Hanselmann
    ])
1614 1c8addc6 Michael Hanselmann
1615 1c8addc6 Michael Hanselmann
  return fields
1616 1c8addc6 Michael Hanselmann
1617 1c8addc6 Michael Hanselmann
1618 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1619 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1620 1c8addc6 Michael Hanselmann

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

1623 1c8addc6 Michael Hanselmann
  """
1624 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1625 1c8addc6 Michael Hanselmann
  be_title = {
1626 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1627 0ca7e384 Iustin Pop
    constants.BE_MEMORY: "ConfigMemory",
1628 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1629 1c8addc6 Michael Hanselmann
    }
1630 1c8addc6 Michael Hanselmann
1631 1c8addc6 Michael Hanselmann
  hv_title = {
1632 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1633 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1634 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1635 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1636 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1637 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1638 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1639 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1640 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1641 1c8addc6 Michael Hanselmann
    }
1642 1c8addc6 Michael Hanselmann
1643 1c8addc6 Michael Hanselmann
  fields = [
1644 1c8addc6 Michael Hanselmann
    # Filled parameters
1645 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1646 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1647 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1648 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1649 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1650 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1651 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1652 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1653 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1654 1c8addc6 Michael Hanselmann
1655 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1656 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1657 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1658 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1659 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1660 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1661 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1662 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1663 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1664 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1665 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1666 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1667 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1668 1c8addc6 Michael Hanselmann
    ]
1669 1c8addc6 Michael Hanselmann
1670 1c8addc6 Michael Hanselmann
  # HV params
1671 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1672 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1673 1c8addc6 Michael Hanselmann
1674 1c8addc6 Michael Hanselmann
  fields.extend([
1675 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1676 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1677 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1678 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1679 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1680 1c8addc6 Michael Hanselmann
    ])
1681 1c8addc6 Michael Hanselmann
1682 1c8addc6 Michael Hanselmann
  # BE params
1683 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1684 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1685 1c8addc6 Michael Hanselmann
1686 1c8addc6 Michael Hanselmann
  fields.extend([
1687 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1688 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1689 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1690 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1691 1c8addc6 Michael Hanselmann
    ])
1692 1c8addc6 Michael Hanselmann
1693 1c8addc6 Michael Hanselmann
  return fields
1694 1c8addc6 Michael Hanselmann
1695 1c8addc6 Michael Hanselmann
1696 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1697 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1698 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1699 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1700 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1701 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1702 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1703 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1704 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1705 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1706 1c8addc6 Michael Hanselmann
  }
1707 1c8addc6 Michael Hanselmann
1708 1c8addc6 Michael Hanselmann
1709 fab9573b Michael Hanselmann
def _GetInstNodeGroup(ctx, default, node_name):
1710 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
1711 fab9573b Michael Hanselmann

1712 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1713 fab9573b Michael Hanselmann
  @param default: Default value
1714 fab9573b Michael Hanselmann
  @type node_name: string
1715 fab9573b Michael Hanselmann
  @param node_name: Node name
1716 fab9573b Michael Hanselmann

1717 fab9573b Michael Hanselmann
  """
1718 fab9573b Michael Hanselmann
  try:
1719 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1720 fab9573b Michael Hanselmann
  except KeyError:
1721 fab9573b Michael Hanselmann
    return default
1722 fab9573b Michael Hanselmann
  else:
1723 fab9573b Michael Hanselmann
    return node.group
1724 fab9573b Michael Hanselmann
1725 fab9573b Michael Hanselmann
1726 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1727 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1728 fab9573b Michael Hanselmann

1729 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1730 fab9573b Michael Hanselmann
  @param default: Default value
1731 fab9573b Michael Hanselmann
  @type node_name: string
1732 fab9573b Michael Hanselmann
  @param node_name: Node name
1733 fab9573b Michael Hanselmann

1734 fab9573b Michael Hanselmann
  """
1735 fab9573b Michael Hanselmann
  try:
1736 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1737 fab9573b Michael Hanselmann
  except KeyError:
1738 fab9573b Michael Hanselmann
    return default
1739 fab9573b Michael Hanselmann
1740 fab9573b Michael Hanselmann
  try:
1741 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1742 fab9573b Michael Hanselmann
  except KeyError:
1743 fab9573b Michael Hanselmann
    return default
1744 fab9573b Michael Hanselmann
1745 fab9573b Michael Hanselmann
  return group.name
1746 fab9573b Michael Hanselmann
1747 fab9573b Michael Hanselmann
1748 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1749 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1750 1c8addc6 Michael Hanselmann

1751 1c8addc6 Michael Hanselmann
  """
1752 1c8addc6 Michael Hanselmann
  fields = [
1753 111bf531 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", QFT_TEXT, "Primary node"),
1754 111bf531 Michael Hanselmann
     IQ_CONFIG, QFF_HOSTNAME, _GetItemAttr("primary_node")),
1755 fab9573b Michael Hanselmann
    (_MakeField("pnode.group", "PrimaryNodeGroup", QFT_TEXT,
1756 fab9573b Michael Hanselmann
                "Primary node's group"),
1757 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1758 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroupName(ctx, _FS_UNAVAIL,
1759 fab9573b Michael Hanselmann
                                             inst.primary_node)),
1760 fab9573b Michael Hanselmann
    (_MakeField("pnode.group.uuid", "PrimaryNodeGroupUUID", QFT_TEXT,
1761 fab9573b Michael Hanselmann
                "Primary node's group UUID"),
1762 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1763 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroup(ctx, _FS_UNAVAIL, inst.primary_node)),
1764 111bf531 Michael Hanselmann
    # TODO: Allow filtering by secondary node as hostname
1765 79b2ca83 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER,
1766 79b2ca83 Michael Hanselmann
                "Secondary nodes; usually this will just be one node"),
1767 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: list(inst.secondary_nodes)),
1768 fab9573b Michael Hanselmann
    (_MakeField("snodes.group", "SecondaryNodesGroups", QFT_OTHER,
1769 fab9573b Michael Hanselmann
                "Node groups of secondary nodes"),
1770 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1771 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroupName, ctx, None),
1772 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1773 fab9573b Michael Hanselmann
    (_MakeField("snodes.group.uuid", "SecondaryNodesGroupsUUID", QFT_OTHER,
1774 fab9573b Michael Hanselmann
                "Node group UUIDs of secondary nodes"),
1775 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1776 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroup, ctx, None),
1777 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1778 79b2ca83 Michael Hanselmann
    (_MakeField("admin_state", "Autostart", QFT_BOOL,
1779 79b2ca83 Michael Hanselmann
                "Desired state of instance (if set, the instance should be"
1780 79b2ca83 Michael Hanselmann
                " up)"),
1781 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("admin_up")),
1782 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
1783 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
1784 79b2ca83 Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER,
1785 111bf531 Michael Hanselmann
                "Instance console information"), IQ_CONSOLE, 0,
1786 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
1787 1c8addc6 Michael Hanselmann
    ]
1788 1c8addc6 Michael Hanselmann
1789 1c8addc6 Michael Hanselmann
  # Add simple fields
1790 111bf531 Michael Hanselmann
  fields.extend([
1791 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
1792 111bf531 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()
1793 111bf531 Michael Hanselmann
    ])
1794 1c8addc6 Michael Hanselmann
1795 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1796 1c8addc6 Michael Hanselmann
  fields.extend([
1797 79b2ca83 Michael Hanselmann
    (_MakeField("oper_state", "Running", QFT_BOOL, "Actual state of instance"),
1798 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstOperState),
1799 79b2ca83 Michael Hanselmann
    (_MakeField("oper_ram", "Memory", QFT_UNIT,
1800 79b2ca83 Michael Hanselmann
                "Actual memory usage as seen by hypervisor"),
1801 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("memory")),
1802 79b2ca83 Michael Hanselmann
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER,
1803 79b2ca83 Michael Hanselmann
                "Actual number of VCPUs as seen by hypervisor"),
1804 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("vcpus")),
1805 1c8addc6 Michael Hanselmann
    ])
1806 1c8addc6 Michael Hanselmann
1807 79b2ca83 Michael Hanselmann
  # Status field
1808 79b2ca83 Michael Hanselmann
  status_values = (constants.INSTST_RUNNING, constants.INSTST_ADMINDOWN,
1809 79b2ca83 Michael Hanselmann
                   constants.INSTST_WRONGNODE, constants.INSTST_ERRORUP,
1810 79b2ca83 Michael Hanselmann
                   constants.INSTST_ERRORDOWN, constants.INSTST_NODEDOWN,
1811 79b2ca83 Michael Hanselmann
                   constants.INSTST_NODEOFFLINE)
1812 79b2ca83 Michael Hanselmann
  status_doc = ("Instance status; \"%s\" if instance is set to be running"
1813 79b2ca83 Michael Hanselmann
                " and actually is, \"%s\" if instance is stopped and"
1814 79b2ca83 Michael Hanselmann
                " is not running, \"%s\" if instance running, but not on its"
1815 79b2ca83 Michael Hanselmann
                " designated primary node, \"%s\" if instance should be"
1816 79b2ca83 Michael Hanselmann
                " stopped, but is actually running, \"%s\" if instance should"
1817 79b2ca83 Michael Hanselmann
                " run, but doesn't, \"%s\" if instance's primary node is down,"
1818 79b2ca83 Michael Hanselmann
                " \"%s\" if instance's primary node is marked offline" %
1819 79b2ca83 Michael Hanselmann
                status_values)
1820 79b2ca83 Michael Hanselmann
  fields.append((_MakeField("status", "Status", QFT_TEXT, status_doc),
1821 111bf531 Michael Hanselmann
                 IQ_LIVE, 0, _GetInstStatus))
1822 79b2ca83 Michael Hanselmann
  assert set(status_values) == constants.INSTST_ALL, \
1823 79b2ca83 Michael Hanselmann
         "Status documentation mismatch"
1824 79b2ca83 Michael Hanselmann
1825 4cc4d1fa Michael Hanselmann
  (network_fields, network_aliases) = _GetInstanceNetworkFields()
1826 4cc4d1fa Michael Hanselmann
1827 4cc4d1fa Michael Hanselmann
  fields.extend(network_fields)
1828 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1829 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1830 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1831 1c8addc6 Michael Hanselmann
1832 e7e8037b Iustin Pop
  aliases = [
1833 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
1834 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
1835 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
1836 4cc4d1fa Michael Hanselmann
    ] + network_aliases
1837 e7e8037b Iustin Pop
1838 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
1839 1c8addc6 Michael Hanselmann
1840 1c8addc6 Michael Hanselmann
1841 24d16f76 Michael Hanselmann
class LockQueryData:
1842 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1843 24d16f76 Michael Hanselmann

1844 24d16f76 Michael Hanselmann
  """
1845 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1846 24d16f76 Michael Hanselmann
    """Initializes this class.
1847 24d16f76 Michael Hanselmann

1848 24d16f76 Michael Hanselmann
    """
1849 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1850 24d16f76 Michael Hanselmann
1851 24d16f76 Michael Hanselmann
  def __iter__(self):
1852 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1853 24d16f76 Michael Hanselmann

1854 24d16f76 Michael Hanselmann
    """
1855 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1856 24d16f76 Michael Hanselmann
1857 24d16f76 Michael Hanselmann
1858 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1859 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1860 24d16f76 Michael Hanselmann

1861 24d16f76 Michael Hanselmann
  """
1862 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1863 24d16f76 Michael Hanselmann
1864 24d16f76 Michael Hanselmann
  if owners:
1865 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1866 24d16f76 Michael Hanselmann
1867 e2d188cc Iustin Pop
  return owners
1868 24d16f76 Michael Hanselmann
1869 24d16f76 Michael Hanselmann
1870 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1871 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1872 24d16f76 Michael Hanselmann

1873 24d16f76 Michael Hanselmann
  """
1874 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1875 24d16f76 Michael Hanselmann
1876 24d16f76 Michael Hanselmann
  if pending:
1877 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1878 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1879 24d16f76 Michael Hanselmann
1880 e2d188cc Iustin Pop
  return pending
1881 24d16f76 Michael Hanselmann
1882 24d16f76 Michael Hanselmann
1883 24d16f76 Michael Hanselmann
def _BuildLockFields():
1884 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1885 24d16f76 Michael Hanselmann

1886 24d16f76 Michael Hanselmann
  """
1887 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1888 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
1889 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
1890 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1891 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
1892 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
1893 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
1894 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
1895 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
1896 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
1897 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
1898 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
1899 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
1900 d63bd540 Iustin Pop
    ], [])
1901 24d16f76 Michael Hanselmann
1902 24d16f76 Michael Hanselmann
1903 8e21cfc0 Adeodato Simo
class GroupQueryData:
1904 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1905 8e21cfc0 Adeodato Simo

1906 8e21cfc0 Adeodato Simo
  """
1907 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1908 8e21cfc0 Adeodato Simo
    """Initializes this class.
1909 8e21cfc0 Adeodato Simo

1910 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1911 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1912 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1913 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1914 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1915 8e21cfc0 Adeodato Simo

1916 8e21cfc0 Adeodato Simo
    """
1917 8e21cfc0 Adeodato Simo
    self.groups = groups
1918 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1919 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1920 8e21cfc0 Adeodato Simo
1921 8e21cfc0 Adeodato Simo
  def __iter__(self):
1922 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1923 8e21cfc0 Adeodato Simo

1924 8e21cfc0 Adeodato Simo
    """
1925 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1926 8e21cfc0 Adeodato Simo
1927 8e21cfc0 Adeodato Simo
1928 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1929 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
1930 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
1931 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
1932 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
1933 79b2ca83 Michael Hanselmann
  "ndparams": ("NDParams", QFT_OTHER, "Node parameters"),
1934 8e21cfc0 Adeodato Simo
  }
1935 8e21cfc0 Adeodato Simo
1936 8e21cfc0 Adeodato Simo
1937 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1938 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1939 8e21cfc0 Adeodato Simo

1940 8e21cfc0 Adeodato Simo
  """
1941 8e21cfc0 Adeodato Simo
  # Add simple fields
1942 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
1943 111bf531 Michael Hanselmann
             _GetItemAttr(name))
1944 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
1945 8e21cfc0 Adeodato Simo
1946 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1947 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
1948 8e21cfc0 Adeodato Simo
1949 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1950 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
1951 8e21cfc0 Adeodato Simo
1952 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1953 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1954 8e21cfc0 Adeodato Simo
1955 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1956 8e21cfc0 Adeodato Simo
  fields.extend([
1957 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
1958 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
1959 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
1960 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
1961 8e21cfc0 Adeodato Simo
    ])
1962 8e21cfc0 Adeodato Simo
1963 8e21cfc0 Adeodato Simo
  # Add fields for instances
1964 8e21cfc0 Adeodato Simo
  fields.extend([
1965 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
1966 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
1967 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
1968 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
1969 79b2ca83 Michael Hanselmann
                "List of primary instances"),
1970 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
1971 8e21cfc0 Adeodato Simo
    ])
1972 8e21cfc0 Adeodato Simo
1973 1ffd2673 Michael Hanselmann
  # Other fields
1974 1ffd2673 Michael Hanselmann
  fields.extend([
1975 1ffd2673 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
1976 1ffd2673 Michael Hanselmann
     lambda ctx, group: list(group.GetTags())),
1977 1ffd2673 Michael Hanselmann
    ])
1978 1ffd2673 Michael Hanselmann
1979 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1980 8e21cfc0 Adeodato Simo
1981 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1982 8e21cfc0 Adeodato Simo
1983 8e21cfc0 Adeodato Simo
1984 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
1985 be3a4b14 Michael Hanselmann
  __slots__ = [
1986 be3a4b14 Michael Hanselmann
    "name",
1987 be3a4b14 Michael Hanselmann
    "valid",
1988 be3a4b14 Michael Hanselmann
    "hidden",
1989 be3a4b14 Michael Hanselmann
    "blacklisted",
1990 be3a4b14 Michael Hanselmann
    "variants",
1991 be3a4b14 Michael Hanselmann
    "api_versions",
1992 be3a4b14 Michael Hanselmann
    "parameters",
1993 be3a4b14 Michael Hanselmann
    "node_status",
1994 be3a4b14 Michael Hanselmann
    ]
1995 be3a4b14 Michael Hanselmann
1996 be3a4b14 Michael Hanselmann
1997 be3a4b14 Michael Hanselmann
def _BuildOsFields():
1998 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
1999 be3a4b14 Michael Hanselmann

2000 be3a4b14 Michael Hanselmann
  """
2001 be3a4b14 Michael Hanselmann
  fields = [
2002 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2003 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2004 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2005 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2006 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2007 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2008 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2009 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2010 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2011 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2012 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2013 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2014 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2015 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2016 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2017 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2018 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2019 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2020 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2021 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2022 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2023 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2024 be3a4b14 Michael Hanselmann
                "Status from node"),
2025 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2026 be3a4b14 Michael Hanselmann
    ]
2027 be3a4b14 Michael Hanselmann
2028 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2029 be3a4b14 Michael Hanselmann
2030 be3a4b14 Michael Hanselmann
2031 8235fe04 Michael Hanselmann
#: Fields available for node queries
2032 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2033 1c8addc6 Michael Hanselmann
2034 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2035 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2036 24d16f76 Michael Hanselmann
2037 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2038 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2039 e571ee44 Adeodato Simo
2040 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2041 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2042 8e21cfc0 Adeodato Simo
2043 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2044 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2045 be3a4b14 Michael Hanselmann
2046 95eb4188 Michael Hanselmann
#: All available resources
2047 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2048 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2049 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2050 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2051 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2052 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2053 95eb4188 Michael Hanselmann
  }
2054 95eb4188 Michael Hanselmann
2055 e571ee44 Adeodato Simo
#: All available field lists
2056 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()