Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 5cfa6c37

History | View | Annotate | Download (78.4 kB)

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

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

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

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

53 8f8ce6d1 Michael Hanselmann
"""
54 4ca96421 Michael Hanselmann
55 8235fe04 Michael Hanselmann
import logging
56 4ca96421 Michael Hanselmann
import operator
57 4ca96421 Michael Hanselmann
import re
58 4ca96421 Michael Hanselmann
59 4ca96421 Michael Hanselmann
from ganeti import constants
60 4ca96421 Michael Hanselmann
from ganeti import errors
61 4ca96421 Michael Hanselmann
from ganeti import utils
62 4ca96421 Michael Hanselmann
from ganeti import compat
63 4ca96421 Michael Hanselmann
from ganeti import objects
64 4ca96421 Michael Hanselmann
from ganeti import ht
65 dff5f600 Michael Hanselmann
from ganeti import runtime
66 fb0be379 Michael Hanselmann
from ganeti import qlang
67 526f866b Michael Hanselmann
from ganeti import jstore
68 4ca96421 Michael Hanselmann
69 82599b3e Iustin Pop
from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
70 82599b3e Iustin Pop
                              QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER,
71 cfb084ae René Nussbaumer
                              RS_NORMAL, RS_UNKNOWN, RS_NODATA,
72 cfb084ae René Nussbaumer
                              RS_UNAVAIL, RS_OFFLINE)
73 82599b3e Iustin Pop
74 306bed0e Apollon Oikonomopoulos
(NETQ_CONFIG,
75 306bed0e Apollon Oikonomopoulos
 NETQ_GROUP,
76 306bed0e Apollon Oikonomopoulos
 NETQ_STATS,
77 306bed0e Apollon Oikonomopoulos
 NETQ_INST) = range(300, 304)
78 4ca96421 Michael Hanselmann
79 8f8ce6d1 Michael Hanselmann
# Constants for requesting data from the caller/data provider. Each property
80 8f8ce6d1 Michael Hanselmann
# collected/computed separately by the data provider should have its own to
81 8f8ce6d1 Michael Hanselmann
# only collect the requested data and not more.
82 8f8ce6d1 Michael Hanselmann
83 8235fe04 Michael Hanselmann
(NQ_CONFIG,
84 8235fe04 Michael Hanselmann
 NQ_INST,
85 8235fe04 Michael Hanselmann
 NQ_LIVE,
86 52b5d286 René Nussbaumer
 NQ_GROUP,
87 52b5d286 René Nussbaumer
 NQ_OOB) = range(1, 6)
88 8235fe04 Michael Hanselmann
89 1c8addc6 Michael Hanselmann
(IQ_CONFIG,
90 1c8addc6 Michael Hanselmann
 IQ_LIVE,
91 5d28cb6f Michael Hanselmann
 IQ_DISKUSAGE,
92 fab9573b Michael Hanselmann
 IQ_CONSOLE,
93 fab9573b Michael Hanselmann
 IQ_NODES) = range(100, 105)
94 1c8addc6 Michael Hanselmann
95 24d16f76 Michael Hanselmann
(LQ_MODE,
96 24d16f76 Michael Hanselmann
 LQ_OWNER,
97 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
98 8235fe04 Michael Hanselmann
99 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
100 8e21cfc0 Adeodato Simo
 GQ_NODE,
101 2c758845 René Nussbaumer
 GQ_INST,
102 2c758845 René Nussbaumer
 GQ_DISKPARAMS) = range(200, 204)
103 8e21cfc0 Adeodato Simo
104 dff5f600 Michael Hanselmann
(CQ_CONFIG,
105 dff5f600 Michael Hanselmann
 CQ_QUEUE_DRAINED,
106 dff5f600 Michael Hanselmann
 CQ_WATCHER_PAUSE) = range(300, 303)
107 dff5f600 Michael Hanselmann
108 0422250e Michael Hanselmann
(JQ_ARCHIVED, ) = range(400, 401)
109 0422250e Michael Hanselmann
110 111bf531 Michael Hanselmann
# Query field flags
111 111bf531 Michael Hanselmann
QFF_HOSTNAME = 0x01
112 111bf531 Michael Hanselmann
QFF_IP_ADDRESS = 0x02
113 526f866b Michael Hanselmann
QFF_JOB_ID = 0x04
114 526f866b Michael Hanselmann
QFF_SPLIT_TIMESTAMP = 0x08
115 526f866b Michael Hanselmann
# Next values: 0x10, 0x20, 0x40, 0x80, 0x100, 0x200
116 526f866b Michael Hanselmann
QFF_ALL = (QFF_HOSTNAME | QFF_IP_ADDRESS | QFF_JOB_ID | QFF_SPLIT_TIMESTAMP)
117 8e21cfc0 Adeodato Simo
118 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
119 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
120 1ae17369 Michael Hanselmann
DOC_RE = re.compile(r"^[A-Z].*[^.,?!]$")
121 4ca96421 Michael Hanselmann
122 4ca96421 Michael Hanselmann
#: Verification function for each field type
123 4ca96421 Michael Hanselmann
_VERIFY_FN = {
124 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
125 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
126 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
127 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
128 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
129 697f49d5 Michael Hanselmann
  QFT_TIMESTAMP: ht.TNumber,
130 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
131 4ca96421 Michael Hanselmann
  }
132 4ca96421 Michael Hanselmann
133 e2d188cc Iustin Pop
# Unique objects for special field statuses
134 e2d188cc Iustin Pop
_FS_UNKNOWN = object()
135 e2d188cc Iustin Pop
_FS_NODATA = object()
136 e2d188cc Iustin Pop
_FS_UNAVAIL = object()
137 e2d188cc Iustin Pop
_FS_OFFLINE = object()
138 e2d188cc Iustin Pop
139 425e5bf0 Michael Hanselmann
#: List of all special status
140 b8028dcf Michael Hanselmann
_FS_ALL = compat.UniqueFrozenset([
141 b8028dcf Michael Hanselmann
  _FS_UNKNOWN,
142 b8028dcf Michael Hanselmann
  _FS_NODATA,
143 b8028dcf Michael Hanselmann
  _FS_UNAVAIL,
144 b8028dcf Michael Hanselmann
  _FS_OFFLINE,
145 b8028dcf Michael Hanselmann
  ])
146 425e5bf0 Michael Hanselmann
147 af58707c Iustin Pop
#: VType to QFT mapping
148 af58707c Iustin Pop
_VTToQFT = {
149 af58707c Iustin Pop
  # TODO: fix validation of empty strings
150 af58707c Iustin Pop
  constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty
151 af58707c Iustin Pop
  constants.VTYPE_MAYBE_STRING: QFT_OTHER,
152 af58707c Iustin Pop
  constants.VTYPE_BOOL: QFT_BOOL,
153 af58707c Iustin Pop
  constants.VTYPE_SIZE: QFT_UNIT,
154 af58707c Iustin Pop
  constants.VTYPE_INT: QFT_NUMBER,
155 af58707c Iustin Pop
  }
156 af58707c Iustin Pop
157 79b2ca83 Michael Hanselmann
_SERIAL_NO_DOC = "%s object serial number, incremented on each modification"
158 79b2ca83 Michael Hanselmann
159 4ca96421 Michael Hanselmann
160 b459a848 Andrea Spadaccini
def _GetUnknownField(ctx, item): # pylint: disable=W0613
161 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
162 4ca96421 Michael Hanselmann

163 4ca96421 Michael Hanselmann
  """
164 e2d188cc Iustin Pop
  return _FS_UNKNOWN
165 4ca96421 Michael Hanselmann
166 4ca96421 Michael Hanselmann
167 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
168 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
169 4ca96421 Michael Hanselmann

170 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
171 4ca96421 Michael Hanselmann

172 4ca96421 Michael Hanselmann
  @type fielddefs: dict
173 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
174 4ca96421 Michael Hanselmann
  @type selected: list of strings
175 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
176 4ca96421 Michael Hanselmann

177 4ca96421 Michael Hanselmann
  """
178 4ca96421 Michael Hanselmann
  result = []
179 4ca96421 Michael Hanselmann
180 4ca96421 Michael Hanselmann
  for name in selected:
181 4ca96421 Michael Hanselmann
    try:
182 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
183 4ca96421 Michael Hanselmann
    except KeyError:
184 79b2ca83 Michael Hanselmann
      fdef = (_MakeField(name, name, QFT_UNKNOWN, "Unknown field '%s'" % name),
185 111bf531 Michael Hanselmann
              None, 0, _GetUnknownField)
186 4ca96421 Michael Hanselmann
187 111bf531 Michael Hanselmann
    assert len(fdef) == 4
188 4ca96421 Michael Hanselmann
189 4ca96421 Michael Hanselmann
    result.append(fdef)
190 4ca96421 Michael Hanselmann
191 4ca96421 Michael Hanselmann
  return result
192 4ca96421 Michael Hanselmann
193 4ca96421 Michael Hanselmann
194 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
195 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
196 4ca96421 Michael Hanselmann

197 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
198 4ca96421 Michael Hanselmann

199 4ca96421 Michael Hanselmann
  """
200 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
201 4ca96421 Michael Hanselmann
202 4ca96421 Michael Hanselmann
203 fb0be379 Michael Hanselmann
class _FilterHints:
204 fb0be379 Michael Hanselmann
  """Class for filter analytics.
205 fb0be379 Michael Hanselmann

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

211 fb0be379 Michael Hanselmann
  There are two ways to optimize this. The first, and simpler, is to assign
212 fb0be379 Michael Hanselmann
  each field a group of data, so that the caller can determine which
213 fb0be379 Michael Hanselmann
  computations are necessary depending on the data groups requested. The list
214 fb0be379 Michael Hanselmann
  of referenced groups must also be computed for fields referenced in the
215 fb0be379 Michael Hanselmann
  filter.
216 fb0be379 Michael Hanselmann

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

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

226 fb0be379 Michael Hanselmann
  """
227 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
228 fb0be379 Michael Hanselmann
    """Initializes this class.
229 fb0be379 Michael Hanselmann

230 fb0be379 Michael Hanselmann
    @type namefield: string
231 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
232 fb0be379 Michael Hanselmann

233 fb0be379 Michael Hanselmann
    """
234 fb0be379 Michael Hanselmann
    self._namefield = namefield
235 fb0be379 Michael Hanselmann
236 fb0be379 Michael Hanselmann
    #: Whether all names need to be requested (e.g. if a non-equality operator
237 fb0be379 Michael Hanselmann
    #: has been used)
238 fb0be379 Michael Hanselmann
    self._allnames = False
239 fb0be379 Michael Hanselmann
240 fb0be379 Michael Hanselmann
    #: Which names to request
241 fb0be379 Michael Hanselmann
    self._names = None
242 fb0be379 Michael Hanselmann
243 fb0be379 Michael Hanselmann
    #: Data kinds referenced by the filter (used by L{Query.RequestedData})
244 fb0be379 Michael Hanselmann
    self._datakinds = set()
245 fb0be379 Michael Hanselmann
246 fb0be379 Michael Hanselmann
  def RequestedNames(self):
247 fb0be379 Michael Hanselmann
    """Returns all requested values.
248 fb0be379 Michael Hanselmann

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

252 fb0be379 Michael Hanselmann
    @rtype: list
253 fb0be379 Michael Hanselmann

254 fb0be379 Michael Hanselmann
    """
255 fb0be379 Michael Hanselmann
    if self._allnames or self._names is None:
256 fb0be379 Michael Hanselmann
      return None
257 fb0be379 Michael Hanselmann
258 fb0be379 Michael Hanselmann
    return utils.UniqueSequence(self._names)
259 fb0be379 Michael Hanselmann
260 fb0be379 Michael Hanselmann
  def ReferencedData(self):
261 fb0be379 Michael Hanselmann
    """Returns all kinds of data referenced by the filter.
262 fb0be379 Michael Hanselmann

263 fb0be379 Michael Hanselmann
    """
264 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
265 fb0be379 Michael Hanselmann
266 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
267 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
268 fb0be379 Michael Hanselmann

269 fb0be379 Michael Hanselmann
    """
270 fb0be379 Michael Hanselmann
    self._allnames = True
271 fb0be379 Michael Hanselmann
    self._names = None
272 fb0be379 Michael Hanselmann
273 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
274 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
275 fb0be379 Michael Hanselmann

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

279 fb0be379 Michael Hanselmann
    """
280 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
281 fb0be379 Michael Hanselmann
      self._NeedAllNames()
282 fb0be379 Michael Hanselmann
283 52aa1efa Michael Hanselmann
  def NoteUnaryOp(self, op, datakind): # pylint: disable=W0613
284 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
285 fb0be379 Michael Hanselmann

286 fb0be379 Michael Hanselmann
    @type op: string
287 fb0be379 Michael Hanselmann
    @param op: Operator
288 fb0be379 Michael Hanselmann

289 fb0be379 Michael Hanselmann
    """
290 52aa1efa Michael Hanselmann
    if datakind is not None:
291 52aa1efa Michael Hanselmann
      self._datakinds.add(datakind)
292 52aa1efa Michael Hanselmann
293 fb0be379 Michael Hanselmann
    self._NeedAllNames()
294 fb0be379 Michael Hanselmann
295 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
296 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
297 fb0be379 Michael Hanselmann

298 fb0be379 Michael Hanselmann
    @type op: string
299 fb0be379 Michael Hanselmann
    @param op: Operator
300 fb0be379 Michael Hanselmann
    @type name: string
301 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
302 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
303 fb0be379 Michael Hanselmann

304 fb0be379 Michael Hanselmann
    """
305 fb0be379 Michael Hanselmann
    if datakind is not None:
306 fb0be379 Michael Hanselmann
      self._datakinds.add(datakind)
307 fb0be379 Michael Hanselmann
308 fb0be379 Michael Hanselmann
    if self._allnames:
309 fb0be379 Michael Hanselmann
      return
310 fb0be379 Michael Hanselmann
311 fb0be379 Michael Hanselmann
    # If any operator other than equality was used, all names need to be
312 fb0be379 Michael Hanselmann
    # retrieved
313 fb0be379 Michael Hanselmann
    if op == qlang.OP_EQUAL and name == self._namefield:
314 fb0be379 Michael Hanselmann
      if self._names is None:
315 fb0be379 Michael Hanselmann
        self._names = []
316 fb0be379 Michael Hanselmann
      self._names.append(value)
317 fb0be379 Michael Hanselmann
    else:
318 fb0be379 Michael Hanselmann
      self._NeedAllNames()
319 fb0be379 Michael Hanselmann
320 fb0be379 Michael Hanselmann
321 fb0be379 Michael Hanselmann
def _WrapLogicOp(op_fn, sentences, ctx, item):
322 fb0be379 Michael Hanselmann
  """Wrapper for logic operator functions.
323 fb0be379 Michael Hanselmann

324 fb0be379 Michael Hanselmann
  """
325 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
326 fb0be379 Michael Hanselmann
327 fb0be379 Michael Hanselmann
328 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
329 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
330 fb0be379 Michael Hanselmann

331 fb0be379 Michael Hanselmann
  """
332 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
333 fb0be379 Michael Hanselmann
334 fb0be379 Michael Hanselmann
335 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
336 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
337 fb0be379 Michael Hanselmann

338 fb0be379 Michael Hanselmann
  """
339 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
340 fb0be379 Michael Hanselmann
341 fb0be379 Michael Hanselmann
342 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
343 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
344 fb0be379 Michael Hanselmann

345 fb0be379 Michael Hanselmann
  """
346 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
347 fb0be379 Michael Hanselmann
348 fb0be379 Michael Hanselmann
349 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
350 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
351 23d0a608 Michael Hanselmann

352 23d0a608 Michael Hanselmann
  """
353 23d0a608 Michael Hanselmann
  try:
354 23d0a608 Michael Hanselmann
    return re.compile(pattern)
355 23d0a608 Michael Hanselmann
  except re.error, err:
356 23d0a608 Michael Hanselmann
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
357 23d0a608 Michael Hanselmann
358 23d0a608 Michael Hanselmann
359 526f866b Michael Hanselmann
def _PrepareSplitTimestamp(value):
360 526f866b Michael Hanselmann
  """Prepares a value for comparison by L{_MakeSplitTimestampComparison}.
361 526f866b Michael Hanselmann

362 526f866b Michael Hanselmann
  """
363 526f866b Michael Hanselmann
  if ht.TNumber(value):
364 526f866b Michael Hanselmann
    return value
365 526f866b Michael Hanselmann
  else:
366 526f866b Michael Hanselmann
    return utils.MergeTime(value)
367 526f866b Michael Hanselmann
368 526f866b Michael Hanselmann
369 526f866b Michael Hanselmann
def _MakeSplitTimestampComparison(fn):
370 526f866b Michael Hanselmann
  """Compares split timestamp values after converting to float.
371 526f866b Michael Hanselmann

372 526f866b Michael Hanselmann
  """
373 526f866b Michael Hanselmann
  return lambda lhs, rhs: fn(utils.MergeTime(lhs), rhs)
374 526f866b Michael Hanselmann
375 526f866b Michael Hanselmann
376 526f866b Michael Hanselmann
def _MakeComparisonChecks(fn):
377 526f866b Michael Hanselmann
  """Prepares flag-specific comparisons using a comparison function.
378 526f866b Michael Hanselmann

379 526f866b Michael Hanselmann
  """
380 526f866b Michael Hanselmann
  return [
381 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(fn),
382 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
383 526f866b Michael Hanselmann
    (QFF_JOB_ID, lambda lhs, rhs: fn(jstore.ParseJobId(lhs), rhs),
384 526f866b Michael Hanselmann
     jstore.ParseJobId),
385 526f866b Michael Hanselmann
    (None, fn, None),
386 526f866b Michael Hanselmann
    ]
387 526f866b Michael Hanselmann
388 526f866b Michael Hanselmann
389 fb0be379 Michael Hanselmann
class _FilterCompilerHelper:
390 fb0be379 Michael Hanselmann
  """Converts a query filter to a callable usable for filtering.
391 fb0be379 Michael Hanselmann

392 fb0be379 Michael Hanselmann
  """
393 b459a848 Andrea Spadaccini
  # String statement has no effect, pylint: disable=W0105
394 fb0be379 Michael Hanselmann
395 fb0be379 Michael Hanselmann
  #: How deep filters can be nested
396 fb0be379 Michael Hanselmann
  _LEVELS_MAX = 10
397 fb0be379 Michael Hanselmann
398 fb0be379 Michael Hanselmann
  # Unique identifiers for operator groups
399 fb0be379 Michael Hanselmann
  (_OPTYPE_LOGIC,
400 fb0be379 Michael Hanselmann
   _OPTYPE_UNARY,
401 fb0be379 Michael Hanselmann
   _OPTYPE_BINARY) = range(1, 4)
402 fb0be379 Michael Hanselmann
403 fb0be379 Michael Hanselmann
  """Functions for equality checks depending on field flags.
404 fb0be379 Michael Hanselmann

405 fb0be379 Michael Hanselmann
  List of tuples containing flags and a callable receiving the left- and
406 fb0be379 Michael Hanselmann
  right-hand side of the operator. The flags are an OR-ed value of C{QFF_*}
407 526f866b Michael Hanselmann
  (e.g. L{QFF_HOSTNAME} or L{QFF_SPLIT_TIMESTAMP}).
408 fb0be379 Michael Hanselmann

409 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
410 fb0be379 Michael Hanselmann
  using binary AND.
411 fb0be379 Michael Hanselmann

412 fb0be379 Michael Hanselmann
  """
413 fb0be379 Michael Hanselmann
  _EQUALITY_CHECKS = [
414 fb0be379 Michael Hanselmann
    (QFF_HOSTNAME,
415 fb0be379 Michael Hanselmann
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
416 23d0a608 Michael Hanselmann
                                               case_sensitive=False),
417 23d0a608 Michael Hanselmann
     None),
418 526f866b Michael Hanselmann
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(operator.eq),
419 526f866b Michael Hanselmann
     _PrepareSplitTimestamp),
420 23d0a608 Michael Hanselmann
    (None, operator.eq, None),
421 fb0be379 Michael Hanselmann
    ]
422 fb0be379 Michael Hanselmann
423 fb0be379 Michael Hanselmann
  """Known operators
424 fb0be379 Michael Hanselmann

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

428 fb0be379 Michael Hanselmann
    - C{_OPTYPE_LOGIC}: Callable taking any number of arguments; used by
429 fb0be379 Michael Hanselmann
      L{_HandleLogicOp}
430 3b877f08 Michael Hanselmann
    - C{_OPTYPE_UNARY}: Always C{None}; details handled by L{_HandleUnaryOp}
431 fb0be379 Michael Hanselmann
    - C{_OPTYPE_BINARY}: Callable taking exactly two parameters, the left- and
432 fb0be379 Michael Hanselmann
      right-hand side of the operator, used by L{_HandleBinaryOp}
433 fb0be379 Michael Hanselmann

434 fb0be379 Michael Hanselmann
  """
435 fb0be379 Michael Hanselmann
  _OPS = {
436 fb0be379 Michael Hanselmann
    # Logic operators
437 fb0be379 Michael Hanselmann
    qlang.OP_OR: (_OPTYPE_LOGIC, compat.any),
438 fb0be379 Michael Hanselmann
    qlang.OP_AND: (_OPTYPE_LOGIC, compat.all),
439 fb0be379 Michael Hanselmann
440 fb0be379 Michael Hanselmann
    # Unary operators
441 3b877f08 Michael Hanselmann
    qlang.OP_NOT: (_OPTYPE_UNARY, None),
442 3b877f08 Michael Hanselmann
    qlang.OP_TRUE: (_OPTYPE_UNARY, None),
443 fb0be379 Michael Hanselmann
444 fb0be379 Michael Hanselmann
    # Binary operators
445 fb0be379 Michael Hanselmann
    qlang.OP_EQUAL: (_OPTYPE_BINARY, _EQUALITY_CHECKS),
446 fb0be379 Michael Hanselmann
    qlang.OP_NOT_EQUAL:
447 23d0a608 Michael Hanselmann
      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn), valprepfn)
448 23d0a608 Michael Hanselmann
                        for (flags, fn, valprepfn) in _EQUALITY_CHECKS]),
449 526f866b Michael Hanselmann
    qlang.OP_LT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.lt)),
450 526f866b Michael Hanselmann
    qlang.OP_LE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.le)),
451 526f866b Michael Hanselmann
    qlang.OP_GT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.gt)),
452 526f866b Michael Hanselmann
    qlang.OP_GE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.ge)),
453 23d0a608 Michael Hanselmann
    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
454 23d0a608 Michael Hanselmann
      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
455 23d0a608 Michael Hanselmann
      ]),
456 fb0be379 Michael Hanselmann
    qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
457 23d0a608 Michael Hanselmann
      (None, operator.contains, None),
458 fb0be379 Michael Hanselmann
      ]),
459 fb0be379 Michael Hanselmann
    }
460 fb0be379 Michael Hanselmann
461 fb0be379 Michael Hanselmann
  def __init__(self, fields):
462 fb0be379 Michael Hanselmann
    """Initializes this class.
463 fb0be379 Michael Hanselmann

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

466 fb0be379 Michael Hanselmann
    """
467 fb0be379 Michael Hanselmann
    self._fields = fields
468 fb0be379 Michael Hanselmann
    self._hints = None
469 fb0be379 Michael Hanselmann
    self._op_handler = None
470 fb0be379 Michael Hanselmann
471 2e5c33db Iustin Pop
  def __call__(self, hints, qfilter):
472 fb0be379 Michael Hanselmann
    """Converts a query filter into a callable function.
473 fb0be379 Michael Hanselmann

474 fb0be379 Michael Hanselmann
    @type hints: L{_FilterHints} or None
475 fb0be379 Michael Hanselmann
    @param hints: Callbacks doing analysis on filter
476 2e5c33db Iustin Pop
    @type qfilter: list
477 2e5c33db Iustin Pop
    @param qfilter: Filter structure
478 fb0be379 Michael Hanselmann
    @rtype: callable
479 fb0be379 Michael Hanselmann
    @return: Function receiving context and item as parameters, returning
480 fb0be379 Michael Hanselmann
             boolean as to whether item matches filter
481 fb0be379 Michael Hanselmann

482 fb0be379 Michael Hanselmann
    """
483 fb0be379 Michael Hanselmann
    self._op_handler = {
484 fb0be379 Michael Hanselmann
      self._OPTYPE_LOGIC:
485 fb0be379 Michael Hanselmann
        (self._HandleLogicOp, getattr(hints, "NoteLogicOp", None)),
486 fb0be379 Michael Hanselmann
      self._OPTYPE_UNARY:
487 fb0be379 Michael Hanselmann
        (self._HandleUnaryOp, getattr(hints, "NoteUnaryOp", None)),
488 fb0be379 Michael Hanselmann
      self._OPTYPE_BINARY:
489 fb0be379 Michael Hanselmann
        (self._HandleBinaryOp, getattr(hints, "NoteBinaryOp", None)),
490 fb0be379 Michael Hanselmann
      }
491 fb0be379 Michael Hanselmann
492 fb0be379 Michael Hanselmann
    try:
493 2e5c33db Iustin Pop
      filter_fn = self._Compile(qfilter, 0)
494 fb0be379 Michael Hanselmann
    finally:
495 fb0be379 Michael Hanselmann
      self._op_handler = None
496 fb0be379 Michael Hanselmann
497 fb0be379 Michael Hanselmann
    return filter_fn
498 fb0be379 Michael Hanselmann
499 2e5c33db Iustin Pop
  def _Compile(self, qfilter, level):
500 fb0be379 Michael Hanselmann
    """Inner function for converting filters.
501 fb0be379 Michael Hanselmann

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

505 fb0be379 Michael Hanselmann
    """
506 2e5c33db Iustin Pop
    if not (isinstance(qfilter, (list, tuple)) and qfilter):
507 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid filter on level %s" % level)
508 fb0be379 Michael Hanselmann
509 fb0be379 Michael Hanselmann
    # Limit recursion
510 fb0be379 Michael Hanselmann
    if level >= self._LEVELS_MAX:
511 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Only up to %s levels are allowed (filter"
512 fb0be379 Michael Hanselmann
                                  " nested too deep)" % self._LEVELS_MAX)
513 fb0be379 Michael Hanselmann
514 fb0be379 Michael Hanselmann
    # Create copy to be modified
515 2e5c33db Iustin Pop
    operands = qfilter[:]
516 fb0be379 Michael Hanselmann
    op = operands.pop(0)
517 fb0be379 Michael Hanselmann
518 fb0be379 Michael Hanselmann
    try:
519 fb0be379 Michael Hanselmann
      (kind, op_data) = self._OPS[op]
520 fb0be379 Michael Hanselmann
    except KeyError:
521 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unknown operator '%s'" % op)
522 fb0be379 Michael Hanselmann
523 fb0be379 Michael Hanselmann
    (handler, hints_cb) = self._op_handler[kind]
524 fb0be379 Michael Hanselmann
525 fb0be379 Michael Hanselmann
    return handler(hints_cb, level, op, op_data, operands)
526 fb0be379 Michael Hanselmann
527 3b877f08 Michael Hanselmann
  def _LookupField(self, name):
528 3b877f08 Michael Hanselmann
    """Returns a field definition by name.
529 3b877f08 Michael Hanselmann

530 3b877f08 Michael Hanselmann
    """
531 3b877f08 Michael Hanselmann
    try:
532 3b877f08 Michael Hanselmann
      return self._fields[name]
533 3b877f08 Michael Hanselmann
    except KeyError:
534 3b877f08 Michael Hanselmann
      raise errors.ParameterError("Unknown field '%s'" % name)
535 3b877f08 Michael Hanselmann
536 fb0be379 Michael Hanselmann
  def _HandleLogicOp(self, hints_fn, level, op, op_fn, operands):
537 fb0be379 Michael Hanselmann
    """Handles logic operators.
538 fb0be379 Michael Hanselmann

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

550 fb0be379 Michael Hanselmann
    """
551 fb0be379 Michael Hanselmann
    if hints_fn:
552 fb0be379 Michael Hanselmann
      hints_fn(op)
553 fb0be379 Michael Hanselmann
554 fb0be379 Michael Hanselmann
    return compat.partial(_WrapLogicOp, op_fn,
555 fb0be379 Michael Hanselmann
                          [self._Compile(op, level + 1) for op in operands])
556 fb0be379 Michael Hanselmann
557 fb0be379 Michael Hanselmann
  def _HandleUnaryOp(self, hints_fn, level, op, op_fn, operands):
558 fb0be379 Michael Hanselmann
    """Handles unary operators.
559 fb0be379 Michael Hanselmann

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

571 fb0be379 Michael Hanselmann
    """
572 3b877f08 Michael Hanselmann
    assert op_fn is None
573 3b877f08 Michael Hanselmann
574 fb0be379 Michael Hanselmann
    if len(operands) != 1:
575 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unary operator '%s' expects exactly one"
576 fb0be379 Michael Hanselmann
                                  " operand" % op)
577 fb0be379 Michael Hanselmann
578 3b877f08 Michael Hanselmann
    if op == qlang.OP_TRUE:
579 52aa1efa Michael Hanselmann
      (_, datakind, _, retrieval_fn) = self._LookupField(operands[0])
580 52aa1efa Michael Hanselmann
581 52aa1efa Michael Hanselmann
      if hints_fn:
582 52aa1efa Michael Hanselmann
        hints_fn(op, datakind)
583 3b877f08 Michael Hanselmann
584 3b877f08 Michael Hanselmann
      op_fn = operator.truth
585 3b877f08 Michael Hanselmann
      arg = retrieval_fn
586 3b877f08 Michael Hanselmann
    elif op == qlang.OP_NOT:
587 52aa1efa Michael Hanselmann
      if hints_fn:
588 52aa1efa Michael Hanselmann
        hints_fn(op, None)
589 52aa1efa Michael Hanselmann
590 3b877f08 Michael Hanselmann
      op_fn = operator.not_
591 3b877f08 Michael Hanselmann
      arg = self._Compile(operands[0], level + 1)
592 3b877f08 Michael Hanselmann
    else:
593 3b877f08 Michael Hanselmann
      raise errors.ProgrammerError("Can't handle operator '%s'" % op)
594 3b877f08 Michael Hanselmann
595 3b877f08 Michael Hanselmann
    return compat.partial(_WrapUnaryOp, op_fn, arg)
596 fb0be379 Michael Hanselmann
597 fb0be379 Michael Hanselmann
  def _HandleBinaryOp(self, hints_fn, level, op, op_data, operands):
598 fb0be379 Michael Hanselmann
    """Handles binary operators.
599 fb0be379 Michael Hanselmann

600 fb0be379 Michael Hanselmann
    @type hints_fn: callable
601 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
602 fb0be379 Michael Hanselmann
    @type level: integer
603 fb0be379 Michael Hanselmann
    @param level: Current depth
604 fb0be379 Michael Hanselmann
    @type op: string
605 fb0be379 Michael Hanselmann
    @param op: Operator
606 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
607 fb0be379 Michael Hanselmann
    @type operands: list
608 fb0be379 Michael Hanselmann
    @param operands: List of operands
609 fb0be379 Michael Hanselmann

610 fb0be379 Michael Hanselmann
    """
611 b459a848 Andrea Spadaccini
    # Unused arguments, pylint: disable=W0613
612 fb0be379 Michael Hanselmann
    try:
613 fb0be379 Michael Hanselmann
      (name, value) = operands
614 fb0be379 Michael Hanselmann
    except (ValueError, TypeError):
615 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Invalid binary operator, expected exactly"
616 fb0be379 Michael Hanselmann
                                  " two operands")
617 fb0be379 Michael Hanselmann
618 3b877f08 Michael Hanselmann
    (fdef, datakind, field_flags, retrieval_fn) = self._LookupField(name)
619 fb0be379 Michael Hanselmann
620 fb0be379 Michael Hanselmann
    assert fdef.kind != QFT_UNKNOWN
621 fb0be379 Michael Hanselmann
622 fb0be379 Michael Hanselmann
    # TODO: Type conversions?
623 fb0be379 Michael Hanselmann
624 fb0be379 Michael Hanselmann
    verify_fn = _VERIFY_FN[fdef.kind]
625 fb0be379 Michael Hanselmann
    if not verify_fn(value):
626 fb0be379 Michael Hanselmann
      raise errors.ParameterError("Unable to compare field '%s' (type '%s')"
627 fb0be379 Michael Hanselmann
                                  " with '%s', expected %s" %
628 fb0be379 Michael Hanselmann
                                  (name, fdef.kind, value.__class__.__name__,
629 fb0be379 Michael Hanselmann
                                   verify_fn))
630 fb0be379 Michael Hanselmann
631 fb0be379 Michael Hanselmann
    if hints_fn:
632 fb0be379 Michael Hanselmann
      hints_fn(op, datakind, name, value)
633 fb0be379 Michael Hanselmann
634 23d0a608 Michael Hanselmann
    for (fn_flags, fn, valprepfn) in op_data:
635 fb0be379 Michael Hanselmann
      if fn_flags is None or fn_flags & field_flags:
636 23d0a608 Michael Hanselmann
        # Prepare value if necessary (e.g. compile regular expression)
637 23d0a608 Michael Hanselmann
        if valprepfn:
638 23d0a608 Michael Hanselmann
          value = valprepfn(value)
639 23d0a608 Michael Hanselmann
640 fb0be379 Michael Hanselmann
        return compat.partial(_WrapBinaryOp, fn, retrieval_fn, value)
641 fb0be379 Michael Hanselmann
642 fb0be379 Michael Hanselmann
    raise errors.ProgrammerError("Unable to find operator implementation"
643 fb0be379 Michael Hanselmann
                                 " (op '%s', flags %s)" % (op, field_flags))
644 fb0be379 Michael Hanselmann
645 fb0be379 Michael Hanselmann
646 2e5c33db Iustin Pop
def _CompileFilter(fields, hints, qfilter):
647 fb0be379 Michael Hanselmann
  """Converts a query filter into a callable function.
648 fb0be379 Michael Hanselmann

649 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
650 fb0be379 Michael Hanselmann

651 fb0be379 Michael Hanselmann
  @rtype: callable
652 fb0be379 Michael Hanselmann

653 fb0be379 Michael Hanselmann
  """
654 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
655 fb0be379 Michael Hanselmann
656 fb0be379 Michael Hanselmann
657 4ca96421 Michael Hanselmann
class Query:
658 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
659 4ca96421 Michael Hanselmann
    """Initializes this class.
660 4ca96421 Michael Hanselmann

661 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
662 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
663 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
664 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
665 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
666 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
667 4ca96421 Michael Hanselmann

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

671 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
672 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
673 4ca96421 Michael Hanselmann
    @type selected: list of strings
674 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
675 4ca96421 Michael Hanselmann

676 4ca96421 Michael Hanselmann
    """
677 fb0be379 Michael Hanselmann
    assert namefield is None or namefield in fieldlist
678 fb0be379 Michael Hanselmann
679 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
680 4ca96421 Michael Hanselmann
681 fb0be379 Michael Hanselmann
    self._filter_fn = None
682 fb0be379 Michael Hanselmann
    self._requested_names = None
683 fb0be379 Michael Hanselmann
    self._filter_datakinds = frozenset()
684 fb0be379 Michael Hanselmann
685 2e5c33db Iustin Pop
    if qfilter is not None:
686 fb0be379 Michael Hanselmann
      # Collect requested names if wanted
687 fb0be379 Michael Hanselmann
      if namefield:
688 fb0be379 Michael Hanselmann
        hints = _FilterHints(namefield)
689 fb0be379 Michael Hanselmann
      else:
690 fb0be379 Michael Hanselmann
        hints = None
691 fb0be379 Michael Hanselmann
692 fb0be379 Michael Hanselmann
      # Build filter function
693 2e5c33db Iustin Pop
      self._filter_fn = _CompileFilter(fieldlist, hints, qfilter)
694 fb0be379 Michael Hanselmann
      if hints:
695 fb0be379 Michael Hanselmann
        self._requested_names = hints.RequestedNames()
696 fb0be379 Michael Hanselmann
        self._filter_datakinds = hints.ReferencedData()
697 fb0be379 Michael Hanselmann
698 fb0be379 Michael Hanselmann
    if namefield is None:
699 fb0be379 Michael Hanselmann
      self._name_fn = None
700 fb0be379 Michael Hanselmann
    else:
701 fb0be379 Michael Hanselmann
      (_, _, _, self._name_fn) = fieldlist[namefield]
702 fb0be379 Michael Hanselmann
703 fb0be379 Michael Hanselmann
  def RequestedNames(self):
704 fb0be379 Michael Hanselmann
    """Returns all names referenced in the filter.
705 fb0be379 Michael Hanselmann

706 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
707 fb0be379 Michael Hanselmann
    names, C{None} is returned.
708 fb0be379 Michael Hanselmann

709 fb0be379 Michael Hanselmann
    """
710 fb0be379 Michael Hanselmann
    return self._requested_names
711 fb0be379 Michael Hanselmann
712 4ca96421 Michael Hanselmann
  def RequestedData(self):
713 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
714 4ca96421 Michael Hanselmann

715 4ca96421 Michael Hanselmann
    @rtype: frozenset
716 4ca96421 Michael Hanselmann

717 4ca96421 Michael Hanselmann
    """
718 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
719 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
720 fb0be379 Michael Hanselmann
                      if datakind is not None))
721 4ca96421 Michael Hanselmann
722 4ca96421 Michael Hanselmann
  def GetFields(self):
723 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
724 4ca96421 Michael Hanselmann

725 4ca96421 Michael Hanselmann
    Includes unknown fields.
726 4ca96421 Michael Hanselmann

727 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
728 4ca96421 Michael Hanselmann

729 4ca96421 Michael Hanselmann
    """
730 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
731 4ca96421 Michael Hanselmann
732 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
733 4ca96421 Michael Hanselmann
    """Execute a query.
734 4ca96421 Michael Hanselmann

735 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
736 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
737 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
738 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
739 fbc263a9 Michael Hanselmann
      ordering
740 4ca96421 Michael Hanselmann

741 4ca96421 Michael Hanselmann
    """
742 fbc263a9 Michael Hanselmann
    sort = (self._name_fn and sort_by_name)
743 fbc263a9 Michael Hanselmann
744 fb0be379 Michael Hanselmann
    result = []
745 fb0be379 Michael Hanselmann
746 fb0be379 Michael Hanselmann
    for idx, item in enumerate(ctx):
747 fb0be379 Michael Hanselmann
      if not (self._filter_fn is None or self._filter_fn(ctx, item)):
748 fb0be379 Michael Hanselmann
        continue
749 4ca96421 Michael Hanselmann
750 fb0be379 Michael Hanselmann
      row = [_ProcessResult(fn(ctx, item)) for (_, _, _, fn) in self._fields]
751 fb0be379 Michael Hanselmann
752 fb0be379 Michael Hanselmann
      # Verify result
753 fb0be379 Michael Hanselmann
      if __debug__:
754 d1c3c3b3 Iustin Pop
        _VerifyResultRow(self._fields, row)
755 4ca96421 Michael Hanselmann
756 fbc263a9 Michael Hanselmann
      if sort:
757 fb0be379 Michael Hanselmann
        (status, name) = _ProcessResult(self._name_fn(ctx, item))
758 fb0be379 Michael Hanselmann
        assert status == constants.RS_NORMAL
759 fb0be379 Michael Hanselmann
        # TODO: Are there cases where we wouldn't want to use NiceSort?
760 76b62028 Iustin Pop
        # Answer: if the name field is non-string...
761 fbc263a9 Michael Hanselmann
        result.append((utils.NiceSortKey(name), idx, row))
762 fb0be379 Michael Hanselmann
      else:
763 fbc263a9 Michael Hanselmann
        result.append(row)
764 fb0be379 Michael Hanselmann
765 fbc263a9 Michael Hanselmann
    if not sort:
766 fbc263a9 Michael Hanselmann
      return result
767 fb0be379 Michael Hanselmann
768 fb0be379 Michael Hanselmann
    # TODO: Would "heapq" be more efficient than sorting?
769 fb0be379 Michael Hanselmann
770 fb0be379 Michael Hanselmann
    # Sorting in-place instead of using "sorted()"
771 fb0be379 Michael Hanselmann
    result.sort()
772 fb0be379 Michael Hanselmann
773 fb0be379 Michael Hanselmann
    assert not result or (len(result[0]) == 3 and len(result[-1]) == 3)
774 fb0be379 Michael Hanselmann
775 fb0be379 Michael Hanselmann
    return map(operator.itemgetter(2), result)
776 4ca96421 Michael Hanselmann
777 fbc263a9 Michael Hanselmann
  def OldStyleQuery(self, ctx, sort_by_name=True):
778 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
779 4ca96421 Michael Hanselmann

780 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
781 4ca96421 Michael Hanselmann

782 4ca96421 Michael Hanselmann
    """
783 111bf531 Michael Hanselmann
    unknown = set(fdef.name for (fdef, _, _, _) in self._fields
784 111bf531 Michael Hanselmann
                  if fdef.kind == QFT_UNKNOWN)
785 4ca96421 Michael Hanselmann
    if unknown:
786 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
787 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
788 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
789 4ca96421 Michael Hanselmann
790 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
791 fbc263a9 Michael Hanselmann
            for row in self.Query(ctx, sort_by_name=sort_by_name)]
792 4ca96421 Michael Hanselmann
793 4ca96421 Michael Hanselmann
794 e2d188cc Iustin Pop
def _ProcessResult(value):
795 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
796 e2d188cc Iustin Pop

797 e2d188cc Iustin Pop
  """
798 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
799 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
800 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
801 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
802 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
803 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
804 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
805 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
806 e2d188cc Iustin Pop
  else:
807 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
808 e2d188cc Iustin Pop
809 e2d188cc Iustin Pop
810 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
811 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
812 4ca96421 Michael Hanselmann

813 4ca96421 Michael Hanselmann
  @type fields: list
814 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
815 4ca96421 Michael Hanselmann
  @type row: list of tuples
816 4ca96421 Michael Hanselmann
  @param row: Row data
817 4ca96421 Michael Hanselmann

818 4ca96421 Michael Hanselmann
  """
819 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
820 d1c3c3b3 Iustin Pop
  errs = []
821 111bf531 Michael Hanselmann
  for ((status, value), (fdef, _, _, _)) in zip(row, fields):
822 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
823 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
824 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
825 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
826 d1c3c3b3 Iustin Pop
    elif value is not None:
827 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
828 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
829 34598551 Agata Murawska
                    (utils.CommaJoin(errs), row))
830 4ca96421 Michael Hanselmann
831 4ca96421 Michael Hanselmann
832 320e34df Michael Hanselmann
def _FieldDictKey((fdef, _, flags, fn)):
833 320e34df Michael Hanselmann
  """Generates key for field dictionary.
834 320e34df Michael Hanselmann

835 320e34df Michael Hanselmann
  """
836 320e34df Michael Hanselmann
  assert fdef.name and fdef.title, "Name and title are required"
837 320e34df Michael Hanselmann
  assert FIELD_NAME_RE.match(fdef.name)
838 320e34df Michael Hanselmann
  assert TITLE_RE.match(fdef.title)
839 320e34df Michael Hanselmann
  assert (DOC_RE.match(fdef.doc) and len(fdef.doc.splitlines()) == 1 and
840 320e34df Michael Hanselmann
          fdef.doc.strip() == fdef.doc), \
841 320e34df Michael Hanselmann
         "Invalid description for field '%s'" % fdef.name
842 320e34df Michael Hanselmann
  assert callable(fn)
843 320e34df Michael Hanselmann
  assert (flags & ~QFF_ALL) == 0, "Unknown flags for field '%s'" % fdef.name
844 320e34df Michael Hanselmann
845 320e34df Michael Hanselmann
  return fdef.name
846 320e34df Michael Hanselmann
847 320e34df Michael Hanselmann
848 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
849 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
850 4ca96421 Michael Hanselmann

851 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
852 4ca96421 Michael Hanselmann

853 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
854 d63bd540 Iustin Pop
      kind, retrieval function)
855 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
856 d63bd540 Iustin Pop
      description
857 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
858 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
859 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
860 4ca96421 Michael Hanselmann
  @rtype: dict
861 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
862 4ca96421 Michael Hanselmann

863 4ca96421 Michael Hanselmann
  """
864 89ce4acc Michael Hanselmann
  if __debug__:
865 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
866 111bf531 Michael Hanselmann
                                      for (fdef, _, _, _) in fields)
867 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
868 4ca96421 Michael Hanselmann
869 320e34df Michael Hanselmann
  result = utils.SequenceToDict(fields, key=_FieldDictKey)
870 4ca96421 Michael Hanselmann
871 d63bd540 Iustin Pop
  for alias, target in aliases:
872 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
873 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
874 111bf531 Michael Hanselmann
    (fdef, k, flags, fn) = result[target]
875 d63bd540 Iustin Pop
    fdef = fdef.Copy()
876 d63bd540 Iustin Pop
    fdef.name = alias
877 111bf531 Michael Hanselmann
    result[alias] = (fdef, k, flags, fn)
878 d63bd540 Iustin Pop
879 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
880 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
881 111bf531 Michael Hanselmann
                    for (name, (fdef, _, _, _)) in result.items())
882 4ca96421 Michael Hanselmann
883 4ca96421 Michael Hanselmann
  return result
884 4ca96421 Michael Hanselmann
885 4ca96421 Michael Hanselmann
886 fbc263a9 Michael Hanselmann
def GetQueryResponse(query, ctx, sort_by_name=True):
887 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
888 b60fcb6f Michael Hanselmann

889 b60fcb6f Michael Hanselmann
  @type query: L{Query}
890 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
891 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
892 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
893 fbc263a9 Michael Hanselmann
    ordering
894 b60fcb6f Michael Hanselmann

895 b60fcb6f Michael Hanselmann
  """
896 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
897 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
898 b60fcb6f Michael Hanselmann
899 b60fcb6f Michael Hanselmann
900 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
901 aa29e95f Michael Hanselmann
  """Returns list of available fields.
902 aa29e95f Michael Hanselmann

903 aa29e95f Michael Hanselmann
  @type fielddefs: dict
904 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
905 aa29e95f Michael Hanselmann
  @type selected: list of strings
906 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
907 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
908 aa29e95f Michael Hanselmann

909 aa29e95f Michael Hanselmann
  """
910 aa29e95f Michael Hanselmann
  if selected is None:
911 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
912 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
913 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
914 aa29e95f Michael Hanselmann
  else:
915 aa29e95f Michael Hanselmann
    # Keep order as requested by client
916 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
917 aa29e95f Michael Hanselmann
918 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
919 aa29e95f Michael Hanselmann
920 aa29e95f Michael Hanselmann
921 79b2ca83 Michael Hanselmann
def _MakeField(name, title, kind, doc):
922 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
923 4ca96421 Michael Hanselmann

924 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
925 4ca96421 Michael Hanselmann
  @param title: Human-readable title
926 4ca96421 Michael Hanselmann
  @param kind: Field type
927 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
928 4ca96421 Michael Hanselmann

929 4ca96421 Michael Hanselmann
  """
930 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
931 1ae17369 Michael Hanselmann
                                      doc=doc)
932 8235fe04 Michael Hanselmann
933 8235fe04 Michael Hanselmann
934 dff5f600 Michael Hanselmann
def _StaticValueInner(value, ctx, _): # pylint: disable=W0613
935 dff5f600 Michael Hanselmann
  """Returns a static value.
936 dff5f600 Michael Hanselmann

937 dff5f600 Michael Hanselmann
  """
938 dff5f600 Michael Hanselmann
  return value
939 dff5f600 Michael Hanselmann
940 dff5f600 Michael Hanselmann
941 dff5f600 Michael Hanselmann
def _StaticValue(value):
942 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
943 dff5f600 Michael Hanselmann

944 dff5f600 Michael Hanselmann
  """
945 dff5f600 Michael Hanselmann
  return compat.partial(_StaticValueInner, value)
946 dff5f600 Michael Hanselmann
947 dff5f600 Michael Hanselmann
948 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
949 8235fe04 Michael Hanselmann
  """Determine node role.
950 8235fe04 Michael Hanselmann

951 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
952 8235fe04 Michael Hanselmann
  @param node: Node object
953 8235fe04 Michael Hanselmann
  @type master_name: string
954 8235fe04 Michael Hanselmann
  @param master_name: Master node name
955 8235fe04 Michael Hanselmann

956 8235fe04 Michael Hanselmann
  """
957 8235fe04 Michael Hanselmann
  if node.name == master_name:
958 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
959 8235fe04 Michael Hanselmann
  elif node.master_candidate:
960 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
961 8235fe04 Michael Hanselmann
  elif node.drained:
962 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
963 8235fe04 Michael Hanselmann
  elif node.offline:
964 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
965 8235fe04 Michael Hanselmann
  else:
966 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
967 8235fe04 Michael Hanselmann
968 8235fe04 Michael Hanselmann
969 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
970 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
971 8235fe04 Michael Hanselmann

972 8235fe04 Michael Hanselmann
  @param attr: Attribute name
973 8235fe04 Michael Hanselmann

974 8235fe04 Michael Hanselmann
  """
975 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
976 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
977 8235fe04 Michael Hanselmann
978 8235fe04 Michael Hanselmann
979 8930b0f0 Iustin Pop
def _GetNDParam(name):
980 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
981 8930b0f0 Iustin Pop

982 8930b0f0 Iustin Pop
  """
983 8930b0f0 Iustin Pop
  def _helper(ctx, _):
984 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
985 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
986 8930b0f0 Iustin Pop
    else:
987 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
988 8930b0f0 Iustin Pop
  return _helper
989 8930b0f0 Iustin Pop
990 8930b0f0 Iustin Pop
991 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
992 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
993 8930b0f0 Iustin Pop

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

996 8930b0f0 Iustin Pop
  """
997 8930b0f0 Iustin Pop
  if is_group:
998 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
999 8930b0f0 Iustin Pop
  else:
1000 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
1001 a6c7e2a2 Iustin Pop
  return [(_MakeField("ndp/%s" % name,
1002 a6c7e2a2 Iustin Pop
                      constants.NDS_PARAMETER_TITLES.get(name,
1003 a6c7e2a2 Iustin Pop
                                                         "ndp/%s" % name),
1004 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
1005 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
1006 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
1007 8930b0f0 Iustin Pop
1008 8930b0f0 Iustin Pop
1009 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
1010 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
1011 425e5bf0 Michael Hanselmann

1012 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1013 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1014 425e5bf0 Michael Hanselmann

1015 425e5bf0 Michael Hanselmann
  """
1016 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
1017 425e5bf0 Michael Hanselmann
1018 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
1019 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
1020 425e5bf0 Michael Hanselmann
    # Return right away
1021 425e5bf0 Michael Hanselmann
    return value
1022 425e5bf0 Michael Hanselmann
1023 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
1024 425e5bf0 Michael Hanselmann
  return convert(value)
1025 425e5bf0 Michael Hanselmann
1026 425e5bf0 Michael Hanselmann
1027 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
1028 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
1029 425e5bf0 Michael Hanselmann

1030 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1031 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1032 425e5bf0 Michael Hanselmann

1033 425e5bf0 Michael Hanselmann
  """
1034 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
1035 425e5bf0 Michael Hanselmann
1036 425e5bf0 Michael Hanselmann
1037 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
1038 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
1039 145bea54 Michael Hanselmann

1040 145bea54 Michael Hanselmann
  @type getter: callable
1041 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1042 145bea54 Michael Hanselmann

1043 145bea54 Michael Hanselmann
  """
1044 145bea54 Michael Hanselmann
  def fn(_, item):
1045 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1046 145bea54 Michael Hanselmann

1047 145bea54 Michael Hanselmann
    """
1048 145bea54 Michael Hanselmann
    timestamp = getter(item)
1049 145bea54 Michael Hanselmann
    if timestamp is None:
1050 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
1051 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1052 145bea54 Michael Hanselmann
    else:
1053 e2d188cc Iustin Pop
      return timestamp
1054 145bea54 Michael Hanselmann
1055 145bea54 Michael Hanselmann
  return fn
1056 145bea54 Michael Hanselmann
1057 145bea54 Michael Hanselmann
1058 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
1059 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
1060 145bea54 Michael Hanselmann

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

1063 145bea54 Michael Hanselmann
  """
1064 145bea54 Michael Hanselmann
  return [
1065 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
1066 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
1067 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
1068 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
1069 145bea54 Michael Hanselmann
    ]
1070 145bea54 Michael Hanselmann
1071 145bea54 Michael Hanselmann
1072 8235fe04 Michael Hanselmann
class NodeQueryData:
1073 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1074 8235fe04 Michael Hanselmann

1075 8235fe04 Michael Hanselmann
  """
1076 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1077 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1078 8235fe04 Michael Hanselmann
    """Initializes this class.
1079 8235fe04 Michael Hanselmann

1080 8235fe04 Michael Hanselmann
    """
1081 8235fe04 Michael Hanselmann
    self.nodes = nodes
1082 8235fe04 Michael Hanselmann
    self.live_data = live_data
1083 8235fe04 Michael Hanselmann
    self.master_name = master_name
1084 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1085 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1086 8235fe04 Michael Hanselmann
    self.groups = groups
1087 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1088 8572f1fe René Nussbaumer
    self.cluster = cluster
1089 8235fe04 Michael Hanselmann
1090 8235fe04 Michael Hanselmann
    # Used for individual rows
1091 8235fe04 Michael Hanselmann
    self.curlive_data = None
1092 8930b0f0 Iustin Pop
    self.ndparams = None
1093 8235fe04 Michael Hanselmann
1094 8235fe04 Michael Hanselmann
  def __iter__(self):
1095 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1096 8235fe04 Michael Hanselmann

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

1100 8235fe04 Michael Hanselmann
    """
1101 8235fe04 Michael Hanselmann
    for node in self.nodes:
1102 8930b0f0 Iustin Pop
      group = self.groups.get(node.group, None)
1103 8930b0f0 Iustin Pop
      if group is None:
1104 8930b0f0 Iustin Pop
        self.ndparams = None
1105 8930b0f0 Iustin Pop
      else:
1106 8930b0f0 Iustin Pop
        self.ndparams = self.cluster.FillND(node, group)
1107 8235fe04 Michael Hanselmann
      if self.live_data:
1108 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
1109 8235fe04 Michael Hanselmann
      else:
1110 8235fe04 Michael Hanselmann
        self.curlive_data = None
1111 8235fe04 Michael Hanselmann
      yield node
1112 8235fe04 Michael Hanselmann
1113 8235fe04 Michael Hanselmann
1114 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
1115 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
1116 111bf531 Michael Hanselmann
  "drained": ("Drained", QFT_BOOL, 0, "Whether node is drained"),
1117 111bf531 Michael Hanselmann
  "master_candidate": ("MasterC", QFT_BOOL, 0,
1118 79b2ca83 Michael Hanselmann
                       "Whether node is a master candidate"),
1119 111bf531 Michael Hanselmann
  "master_capable": ("MasterCapable", QFT_BOOL, 0,
1120 79b2ca83 Michael Hanselmann
                     "Whether node can become a master candidate"),
1121 111bf531 Michael Hanselmann
  "name": ("Node", QFT_TEXT, QFF_HOSTNAME, "Node name"),
1122 111bf531 Michael Hanselmann
  "offline": ("Offline", QFT_BOOL, 0, "Whether node is marked offline"),
1123 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Node"),
1124 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Node UUID"),
1125 111bf531 Michael Hanselmann
  "vm_capable": ("VMCapable", QFT_BOOL, 0, "Whether node can host instances"),
1126 8235fe04 Michael Hanselmann
  }
1127 8235fe04 Michael Hanselmann
1128 8235fe04 Michael Hanselmann
1129 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
1130 effab4ca Iustin Pop
# Note that none of these are available for non-vm_capable nodes
1131 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
1132 79b2ca83 Michael Hanselmann
  "bootid": ("BootID", QFT_TEXT, "bootid",
1133 79b2ca83 Michael Hanselmann
             "Random UUID renewed for each system reboot, can be used"
1134 79b2ca83 Michael Hanselmann
             " for detecting reboots by tracking changes"),
1135 79b2ca83 Michael Hanselmann
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes",
1136 79b2ca83 Michael Hanselmann
             "Number of NUMA domains on node (if exported by hypervisor)"),
1137 79b2ca83 Michael Hanselmann
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets",
1138 79b2ca83 Michael Hanselmann
               "Number of physical CPU sockets (if exported by hypervisor)"),
1139 79b2ca83 Michael Hanselmann
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total", "Number of logical processors"),
1140 79b2ca83 Michael Hanselmann
  "dfree": ("DFree", QFT_UNIT, "vg_free",
1141 79b2ca83 Michael Hanselmann
            "Available disk space in volume group"),
1142 79b2ca83 Michael Hanselmann
  "dtotal": ("DTotal", QFT_UNIT, "vg_size",
1143 79b2ca83 Michael Hanselmann
             "Total disk space in volume group used for instance disk"
1144 79b2ca83 Michael Hanselmann
             " allocation"),
1145 79b2ca83 Michael Hanselmann
  "mfree": ("MFree", QFT_UNIT, "memory_free",
1146 79b2ca83 Michael Hanselmann
            "Memory available for instance allocations"),
1147 79b2ca83 Michael Hanselmann
  "mnode": ("MNode", QFT_UNIT, "memory_dom0",
1148 79b2ca83 Michael Hanselmann
            "Amount of memory used by node (dom0 for Xen)"),
1149 79b2ca83 Michael Hanselmann
  "mtotal": ("MTotal", QFT_UNIT, "memory_total",
1150 79b2ca83 Michael Hanselmann
             "Total amount of memory of physical machine"),
1151 8235fe04 Michael Hanselmann
  }
1152 8235fe04 Michael Hanselmann
1153 8235fe04 Michael Hanselmann
1154 8572f1fe René Nussbaumer
def _GetGroup(cb):
1155 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
1156 8572f1fe René Nussbaumer

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

1159 8572f1fe René Nussbaumer
  """
1160 8572f1fe René Nussbaumer
  def fn(ctx, node):
1161 8572f1fe René Nussbaumer
    """Get group data for a node.
1162 8572f1fe René Nussbaumer

1163 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1164 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1165 8572f1fe René Nussbaumer
    @param inst: Node object
1166 8572f1fe René Nussbaumer

1167 8572f1fe René Nussbaumer
    """
1168 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1169 8572f1fe René Nussbaumer
    if ng is None:
1170 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1171 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1172 8572f1fe René Nussbaumer
1173 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1174 8572f1fe René Nussbaumer
1175 8572f1fe René Nussbaumer
  return fn
1176 8572f1fe René Nussbaumer
1177 8572f1fe René Nussbaumer
1178 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1179 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1180 8235fe04 Michael Hanselmann

1181 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1182 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1183 8235fe04 Michael Hanselmann
  @param node: Node object
1184 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1185 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1186 8235fe04 Michael Hanselmann

1187 8235fe04 Michael Hanselmann
  """
1188 e2d188cc Iustin Pop
  return ng.name
1189 8235fe04 Michael Hanselmann
1190 8235fe04 Michael Hanselmann
1191 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1192 52b5d286 René Nussbaumer
  """Returns the node powered state
1193 52b5d286 René Nussbaumer

1194 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1195 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1196 52b5d286 René Nussbaumer
  @param node: Node object
1197 52b5d286 René Nussbaumer

1198 52b5d286 René Nussbaumer
  """
1199 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1200 e2d188cc Iustin Pop
    return node.powered
1201 52b5d286 René Nussbaumer
1202 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1203 52b5d286 René Nussbaumer
1204 52b5d286 René Nussbaumer
1205 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1206 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1207 8572f1fe René Nussbaumer

1208 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1209 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1210 8572f1fe René Nussbaumer
  @param node: Node object
1211 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1212 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1213 8572f1fe René Nussbaumer

1214 8572f1fe René Nussbaumer
  """
1215 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1216 8572f1fe René Nussbaumer
1217 8572f1fe René Nussbaumer
1218 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1219 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1220 8235fe04 Michael Hanselmann

1221 8235fe04 Michael Hanselmann
  @param field: Live field name
1222 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1223 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1224 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1225 a6070ef7 Michael Hanselmann
  @param node: Node object
1226 8235fe04 Michael Hanselmann

1227 8235fe04 Michael Hanselmann
  """
1228 a6070ef7 Michael Hanselmann
  if node.offline:
1229 e2d188cc Iustin Pop
    return _FS_OFFLINE
1230 a6070ef7 Michael Hanselmann
1231 effab4ca Iustin Pop
  if not node.vm_capable:
1232 effab4ca Iustin Pop
    return _FS_UNAVAIL
1233 effab4ca Iustin Pop
1234 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1235 e2d188cc Iustin Pop
    return _FS_NODATA
1236 8235fe04 Michael Hanselmann
1237 b4600d4f Michael Hanselmann
  return _GetStatsField(field, kind, ctx.curlive_data)
1238 b4600d4f Michael Hanselmann
1239 b4600d4f Michael Hanselmann
1240 b4600d4f Michael Hanselmann
def _GetStatsField(field, kind, data):
1241 b4600d4f Michael Hanselmann
  """Gets a value from live statistics.
1242 b4600d4f Michael Hanselmann

1243 b4600d4f Michael Hanselmann
  If the value is not found, L{_FS_UNAVAIL} is returned. If the field kind is
1244 b4600d4f Michael Hanselmann
  numeric a conversion to integer is attempted. If that fails, L{_FS_UNAVAIL}
1245 b4600d4f Michael Hanselmann
  is returned.
1246 b4600d4f Michael Hanselmann

1247 b4600d4f Michael Hanselmann
  @param field: Live field name
1248 b4600d4f Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1249 b4600d4f Michael Hanselmann
  @type data: dict
1250 b4600d4f Michael Hanselmann
  @param data: Statistics
1251 b4600d4f Michael Hanselmann

1252 b4600d4f Michael Hanselmann
  """
1253 8235fe04 Michael Hanselmann
  try:
1254 b4600d4f Michael Hanselmann
    value = data[field]
1255 8235fe04 Michael Hanselmann
  except KeyError:
1256 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1257 8235fe04 Michael Hanselmann
1258 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1259 e2d188cc Iustin Pop
    return value
1260 8235fe04 Michael Hanselmann
1261 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1262 8235fe04 Michael Hanselmann
1263 8235fe04 Michael Hanselmann
  # Try to convert into number
1264 8235fe04 Michael Hanselmann
  try:
1265 e2d188cc Iustin Pop
    return int(value)
1266 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1267 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1268 b4600d4f Michael Hanselmann
                      field, value)
1269 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1270 8235fe04 Michael Hanselmann
1271 8235fe04 Michael Hanselmann
1272 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1273 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1274 54ac87c0 Michael Hanselmann

1275 54ac87c0 Michael Hanselmann
  """
1276 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1277 54ac87c0 Michael Hanselmann
1278 54ac87c0 Michael Hanselmann
  if hv_state is None:
1279 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1280 54ac87c0 Michael Hanselmann
1281 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1282 54ac87c0 Michael Hanselmann
1283 54ac87c0 Michael Hanselmann
1284 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1285 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1286 54ac87c0 Michael Hanselmann

1287 54ac87c0 Michael Hanselmann
  """
1288 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1289 54ac87c0 Michael Hanselmann
1290 54ac87c0 Michael Hanselmann
  if disk_state is None:
1291 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1292 54ac87c0 Michael Hanselmann
1293 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1294 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1295 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1296 54ac87c0 Michael Hanselmann
1297 54ac87c0 Michael Hanselmann
1298 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1299 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1300 8235fe04 Michael Hanselmann

1301 8235fe04 Michael Hanselmann
  """
1302 8235fe04 Michael Hanselmann
  fields = [
1303 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1304 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1305 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1306 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1307 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1308 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1309 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1310 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, lambda ctx, node: node.name == ctx.master_name),
1311 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1312 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1313 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1314 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1315 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1316 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1317 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1318 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1319 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1320 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1321 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1322 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1323 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1324 54ac87c0 Michael Hanselmann
    (_MakeField("hv_state", "HypervisorState", QFT_OTHER, "Hypervisor state"),
1325 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeHvState),
1326 54ac87c0 Michael Hanselmann
    (_MakeField("disk_state", "DiskState", QFT_OTHER, "Disk state"),
1327 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeDiskState),
1328 8235fe04 Michael Hanselmann
    ]
1329 8235fe04 Michael Hanselmann
1330 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(False))
1331 8930b0f0 Iustin Pop
1332 79b2ca83 Michael Hanselmann
  # Node role
1333 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1334 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1335 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1336 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1337 a9310b2f Iustin Pop
              " \"%s\" for regular, \"%s\" for drained, \"%s\" for offline" %
1338 79b2ca83 Michael Hanselmann
              role_values)
1339 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1340 79b2ca83 Michael Hanselmann
                 lambda ctx, node: _GetNodeRole(node, ctx.master_name)))
1341 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1342 79b2ca83 Michael Hanselmann
1343 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1344 e2d188cc Iustin Pop
    return lambda ctx, node: len(getter(ctx)[node.name])
1345 8235fe04 Michael Hanselmann
1346 8235fe04 Michael Hanselmann
  def _GetList(getter):
1347 e2d188cc Iustin Pop
    return lambda ctx, node: list(getter(ctx)[node.name])
1348 8235fe04 Michael Hanselmann
1349 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1350 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1351 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1352 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1353 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1354 8235fe04 Michael Hanselmann
    fields.extend([
1355 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1356 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1357 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1358 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1359 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1360 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1361 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1362 8235fe04 Michael Hanselmann
      ])
1363 8235fe04 Michael Hanselmann
1364 8235fe04 Michael Hanselmann
  # Add simple fields
1365 111bf531 Michael Hanselmann
  fields.extend([
1366 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1367 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()])
1368 8235fe04 Michael Hanselmann
1369 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1370 8235fe04 Michael Hanselmann
  fields.extend([
1371 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1372 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1373 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()])
1374 8235fe04 Michael Hanselmann
1375 145bea54 Michael Hanselmann
  # Add timestamps
1376 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1377 145bea54 Michael Hanselmann
1378 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1379 8235fe04 Michael Hanselmann
1380 8235fe04 Michael Hanselmann
1381 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1382 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1383 1c8addc6 Michael Hanselmann

1384 1c8addc6 Michael Hanselmann
  """
1385 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1386 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1387 1c8addc6 Michael Hanselmann
    """Initializes this class.
1388 1c8addc6 Michael Hanselmann

1389 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1390 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1391 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1392 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1393 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1394 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1395 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1396 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1397 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1398 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1399 e431074f René Nussbaumer
    @type wrongnode_inst: set
1400 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1401 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1402 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1403 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1404 fab9573b Michael Hanselmann
    @param nodes: Node objects
1405 1c8addc6 Michael Hanselmann

1406 1c8addc6 Michael Hanselmann
    """
1407 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1408 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1409 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1410 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1411 1c8addc6 Michael Hanselmann
1412 1c8addc6 Michael Hanselmann
    self.instances = instances
1413 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1414 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1415 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1416 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1417 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1418 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1419 5d28cb6f Michael Hanselmann
    self.console = console
1420 fab9573b Michael Hanselmann
    self.nodes = nodes
1421 fab9573b Michael Hanselmann
    self.groups = groups
1422 1c8addc6 Michael Hanselmann
1423 1c8addc6 Michael Hanselmann
    # Used for individual rows
1424 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1425 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1426 7c670076 Michael Hanselmann
    self.inst_osparams = None
1427 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1428 1c8addc6 Michael Hanselmann
1429 1c8addc6 Michael Hanselmann
  def __iter__(self):
1430 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1431 1c8addc6 Michael Hanselmann

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

1435 1c8addc6 Michael Hanselmann
    """
1436 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1437 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1438 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1439 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1440 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1441 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1442 1c8addc6 Michael Hanselmann
1443 1c8addc6 Michael Hanselmann
      yield inst
1444 1c8addc6 Michael Hanselmann
1445 1c8addc6 Michael Hanselmann
1446 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1447 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1448 1c8addc6 Michael Hanselmann

1449 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1450 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1451 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1452 1c8addc6 Michael Hanselmann

1453 1c8addc6 Michael Hanselmann
  """
1454 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1455 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1456 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1457 e2d188cc Iustin Pop
    return _FS_NODATA
1458 1c8addc6 Michael Hanselmann
  else:
1459 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1460 1c8addc6 Michael Hanselmann
1461 1c8addc6 Michael Hanselmann
1462 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1463 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1464 1c8addc6 Michael Hanselmann

1465 1c8addc6 Michael Hanselmann
  @type name: string
1466 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1467 1c8addc6 Michael Hanselmann

1468 1c8addc6 Michael Hanselmann
  """
1469 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1470 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1471 1c8addc6 Michael Hanselmann

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

1476 1c8addc6 Michael Hanselmann
    """
1477 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1478 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1479 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1480 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1481 e2d188cc Iustin Pop
      return _FS_NODATA
1482 1c8addc6 Michael Hanselmann
1483 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1484 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1485 1c8addc6 Michael Hanselmann
      if name in data:
1486 e2d188cc Iustin Pop
        return data[name]
1487 1c8addc6 Michael Hanselmann
1488 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1489 1c8addc6 Michael Hanselmann
1490 1c8addc6 Michael Hanselmann
  return fn
1491 1c8addc6 Michael Hanselmann
1492 1c8addc6 Michael Hanselmann
1493 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1494 1c8addc6 Michael Hanselmann
  """Get instance status.
1495 1c8addc6 Michael Hanselmann

1496 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1497 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1498 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1499 1c8addc6 Michael Hanselmann

1500 1c8addc6 Michael Hanselmann
  """
1501 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1502 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1503 1c8addc6 Michael Hanselmann
1504 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1505 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1506 1c8addc6 Michael Hanselmann
1507 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1508 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1509 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1510 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1511 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1512 1c8addc6 Michael Hanselmann
    else:
1513 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1514 1c8addc6 Michael Hanselmann
1515 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1516 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1517 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1518 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1519 1c8addc6 Michael Hanselmann
1520 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1521 1c8addc6 Michael Hanselmann
1522 1c8addc6 Michael Hanselmann
1523 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1524 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1525 1c8addc6 Michael Hanselmann

1526 1c8addc6 Michael Hanselmann
  @type index: int
1527 1c8addc6 Michael Hanselmann
  @param index: Disk index
1528 1c8addc6 Michael Hanselmann

1529 1c8addc6 Michael Hanselmann
  """
1530 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1531 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1532 1c8addc6 Michael Hanselmann

1533 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1534 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1535 1c8addc6 Michael Hanselmann

1536 1c8addc6 Michael Hanselmann
    """
1537 1c8addc6 Michael Hanselmann
    try:
1538 e2d188cc Iustin Pop
      return inst.disks[index].size
1539 1c8addc6 Michael Hanselmann
    except IndexError:
1540 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1541 1c8addc6 Michael Hanselmann
1542 1c8addc6 Michael Hanselmann
  return fn
1543 1c8addc6 Michael Hanselmann
1544 1c8addc6 Michael Hanselmann
1545 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1546 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1547 1c8addc6 Michael Hanselmann

1548 1c8addc6 Michael Hanselmann
  @type index: int
1549 1c8addc6 Michael Hanselmann
  @param index: NIC index
1550 1c8addc6 Michael Hanselmann
  @type cb: callable
1551 1c8addc6 Michael Hanselmann
  @param cb: Callback
1552 1c8addc6 Michael Hanselmann

1553 1c8addc6 Michael Hanselmann
  """
1554 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1555 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1556 1c8addc6 Michael Hanselmann

1557 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1558 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1559 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1560 1c8addc6 Michael Hanselmann

1561 1c8addc6 Michael Hanselmann
    """
1562 1c8addc6 Michael Hanselmann
    try:
1563 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1564 1c8addc6 Michael Hanselmann
    except IndexError:
1565 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1566 1c8addc6 Michael Hanselmann
1567 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1568 1c8addc6 Michael Hanselmann
1569 1c8addc6 Michael Hanselmann
  return fn
1570 1c8addc6 Michael Hanselmann
1571 1c8addc6 Michael Hanselmann
1572 d4117a72 Apollon Oikonomopoulos
def _GetInstNicNetwork(ctx, _, nic): # pylint: disable=W0613
1573 d4117a72 Apollon Oikonomopoulos
  """Get a NIC's Network.
1574 d4117a72 Apollon Oikonomopoulos

1575 d4117a72 Apollon Oikonomopoulos
  @type ctx: L{InstanceQueryData}
1576 d4117a72 Apollon Oikonomopoulos
  @type nic: L{objects.NIC}
1577 d4117a72 Apollon Oikonomopoulos
  @param nic: NIC object
1578 d4117a72 Apollon Oikonomopoulos

1579 d4117a72 Apollon Oikonomopoulos
  """
1580 d4117a72 Apollon Oikonomopoulos
  if nic.network is None:
1581 d4117a72 Apollon Oikonomopoulos
    return _FS_UNAVAIL
1582 d4117a72 Apollon Oikonomopoulos
  else:
1583 d4117a72 Apollon Oikonomopoulos
    return nic.network
1584 d4117a72 Apollon Oikonomopoulos
1585 d4117a72 Apollon Oikonomopoulos
1586 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1587 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1588 1c8addc6 Michael Hanselmann

1589 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1590 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1591 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1592 1c8addc6 Michael Hanselmann

1593 1c8addc6 Michael Hanselmann
  """
1594 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1595 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1596 1c8addc6 Michael Hanselmann
  else:
1597 e2d188cc Iustin Pop
    return nic.ip
1598 1c8addc6 Michael Hanselmann
1599 1c8addc6 Michael Hanselmann
1600 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1601 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1602 1c8addc6 Michael Hanselmann

1603 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1604 1c8addc6 Michael Hanselmann
  @type index: int
1605 1c8addc6 Michael Hanselmann
  @param index: NIC index
1606 1c8addc6 Michael Hanselmann

1607 1c8addc6 Michael Hanselmann
  """
1608 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1609 1c8addc6 Michael Hanselmann
1610 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1611 1c8addc6 Michael Hanselmann
1612 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1613 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1614 1c8addc6 Michael Hanselmann
  else:
1615 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1616 1c8addc6 Michael Hanselmann
1617 1c8addc6 Michael Hanselmann
1618 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1619 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1620 1c8addc6 Michael Hanselmann

1621 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1622 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1623 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1624 1c8addc6 Michael Hanselmann

1625 1c8addc6 Michael Hanselmann
  """
1626 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1627 1c8addc6 Michael Hanselmann
1628 1c8addc6 Michael Hanselmann
  result = []
1629 1c8addc6 Michael Hanselmann
1630 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1631 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1632 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1633 1c8addc6 Michael Hanselmann
    else:
1634 1c8addc6 Michael Hanselmann
      result.append(None)
1635 1c8addc6 Michael Hanselmann
1636 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1637 1c8addc6 Michael Hanselmann
1638 e2d188cc Iustin Pop
  return result
1639 1c8addc6 Michael Hanselmann
1640 1c8addc6 Michael Hanselmann
1641 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1642 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1643 1c8addc6 Michael Hanselmann

1644 1c8addc6 Michael Hanselmann
  @type name: string
1645 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1646 1c8addc6 Michael Hanselmann

1647 1c8addc6 Michael Hanselmann
  """
1648 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1649 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1650 1c8addc6 Michael Hanselmann

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

1657 1c8addc6 Michael Hanselmann
    """
1658 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1659 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1660 1c8addc6 Michael Hanselmann
1661 1c8addc6 Michael Hanselmann
  return fn
1662 1c8addc6 Michael Hanselmann
1663 1c8addc6 Michael Hanselmann
1664 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1665 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1666 1c8addc6 Michael Hanselmann

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

1670 1c8addc6 Michael Hanselmann
  """
1671 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1672 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1673 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1674 1c8addc6 Michael Hanselmann
1675 1c8addc6 Michael Hanselmann
  fields = [
1676 1c8addc6 Michael Hanselmann
    # All NICs
1677 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1678 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1679 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1680 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1681 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1682 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1683 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1684 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1685 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1686 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1687 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1688 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1689 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1690 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1691 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1692 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1693 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1694 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1695 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1696 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1697 d4117a72 Apollon Oikonomopoulos
    (_MakeField("nic.networks", "NIC_networks", QFT_OTHER,
1698 d4117a72 Apollon Oikonomopoulos
                "List containing each interface's network"), IQ_CONFIG, 0,
1699 d4117a72 Apollon Oikonomopoulos
     lambda ctx, inst: [nic.network for nic in inst.nics]),
1700 1c8addc6 Michael Hanselmann
    ]
1701 1c8addc6 Michael Hanselmann
1702 1c8addc6 Michael Hanselmann
  # NICs by number
1703 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1704 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1705 1c8addc6 Michael Hanselmann
    fields.extend([
1706 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1707 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1708 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1709 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1710 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1711 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1712 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1713 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1714 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1715 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1716 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1717 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1718 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1719 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1720 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1721 d4117a72 Apollon Oikonomopoulos
      (_MakeField("nic.network/%s" % i, "NicNetwork/%s" % i, QFT_TEXT,
1722 d4117a72 Apollon Oikonomopoulos
                  "Network of %s network interface" % numtext),
1723 d4117a72 Apollon Oikonomopoulos
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicNetwork)),
1724 1c8addc6 Michael Hanselmann
      ])
1725 1c8addc6 Michael Hanselmann
1726 4cc4d1fa Michael Hanselmann
  aliases = [
1727 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1728 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1729 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1730 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1731 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1732 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1733 d4117a72 Apollon Oikonomopoulos
    ("nic_network", "nic.network/0"),
1734 4cc4d1fa Michael Hanselmann
    ]
1735 4cc4d1fa Michael Hanselmann
1736 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1737 1c8addc6 Michael Hanselmann
1738 1c8addc6 Michael Hanselmann
1739 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1740 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1741 1c8addc6 Michael Hanselmann

1742 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1743 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1744 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1745 1c8addc6 Michael Hanselmann

1746 1c8addc6 Michael Hanselmann
  """
1747 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1748 1c8addc6 Michael Hanselmann
1749 1c8addc6 Michael Hanselmann
  if usage is None:
1750 1c8addc6 Michael Hanselmann
    usage = 0
1751 1c8addc6 Michael Hanselmann
1752 e2d188cc Iustin Pop
  return usage
1753 1c8addc6 Michael Hanselmann
1754 1c8addc6 Michael Hanselmann
1755 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1756 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1757 5d28cb6f Michael Hanselmann

1758 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1759 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1760 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1761 5d28cb6f Michael Hanselmann

1762 5d28cb6f Michael Hanselmann
  """
1763 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1764 5d28cb6f Michael Hanselmann
1765 5d28cb6f Michael Hanselmann
  if consinfo is None:
1766 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1767 5d28cb6f Michael Hanselmann
1768 5d28cb6f Michael Hanselmann
  return consinfo
1769 5d28cb6f Michael Hanselmann
1770 5d28cb6f Michael Hanselmann
1771 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1772 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1773 1c8addc6 Michael Hanselmann

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

1776 1c8addc6 Michael Hanselmann
  """
1777 1c8addc6 Michael Hanselmann
  fields = [
1778 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1779 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1780 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1781 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1782 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1783 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1784 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1785 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1786 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1787 1c8addc6 Michael Hanselmann
    ]
1788 1c8addc6 Michael Hanselmann
1789 1c8addc6 Michael Hanselmann
  # Disks by number
1790 1c8addc6 Michael Hanselmann
  fields.extend([
1791 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1792 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1793 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1794 3c286190 Dimitris Aragiorgis
    for i in range(constants.MAX_DISKS)])
1795 1c8addc6 Michael Hanselmann
1796 1c8addc6 Michael Hanselmann
  return fields
1797 1c8addc6 Michael Hanselmann
1798 1c8addc6 Michael Hanselmann
1799 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1800 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1801 1c8addc6 Michael Hanselmann

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

1804 1c8addc6 Michael Hanselmann
  """
1805 1c8addc6 Michael Hanselmann
  fields = [
1806 1c8addc6 Michael Hanselmann
    # Filled parameters
1807 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1808 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1809 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1810 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1811 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1812 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1813 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1814 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1815 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1816 1c8addc6 Michael Hanselmann
1817 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1818 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1819 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1820 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1821 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1822 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1823 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1824 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1825 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1826 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1827 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1828 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1829 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1830 1c8addc6 Michael Hanselmann
    ]
1831 1c8addc6 Michael Hanselmann
1832 1c8addc6 Michael Hanselmann
  # HV params
1833 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1834 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1835 1c8addc6 Michael Hanselmann
1836 1c8addc6 Michael Hanselmann
  fields.extend([
1837 a6c7e2a2 Iustin Pop
    (_MakeField("hv/%s" % name,
1838 a6c7e2a2 Iustin Pop
                constants.HVS_PARAMETER_TITLES.get(name, "hv/%s" % name),
1839 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1840 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1841 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1842 3c286190 Dimitris Aragiorgis
    if name not in constants.HVC_GLOBALS])
1843 1c8addc6 Michael Hanselmann
1844 1c8addc6 Michael Hanselmann
  # BE params
1845 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1846 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1847 1c8addc6 Michael Hanselmann
1848 1c8addc6 Michael Hanselmann
  fields.extend([
1849 a6c7e2a2 Iustin Pop
    (_MakeField("be/%s" % name,
1850 a6c7e2a2 Iustin Pop
                constants.BES_PARAMETER_TITLES.get(name, "be/%s" % name),
1851 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1852 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1853 3c286190 Dimitris Aragiorgis
    for name, kind in constants.BES_PARAMETER_TYPES.items()])
1854 1c8addc6 Michael Hanselmann
1855 1c8addc6 Michael Hanselmann
  return fields
1856 1c8addc6 Michael Hanselmann
1857 1c8addc6 Michael Hanselmann
1858 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1859 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1860 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1861 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1862 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1863 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1864 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1865 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1866 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1867 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1868 1c8addc6 Michael Hanselmann
  }
1869 1c8addc6 Michael Hanselmann
1870 1c8addc6 Michael Hanselmann
1871 fab9573b Michael Hanselmann
def _GetInstNodeGroup(ctx, default, node_name):
1872 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
1873 fab9573b Michael Hanselmann

1874 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1875 fab9573b Michael Hanselmann
  @param default: Default value
1876 fab9573b Michael Hanselmann
  @type node_name: string
1877 fab9573b Michael Hanselmann
  @param node_name: Node name
1878 fab9573b Michael Hanselmann

1879 fab9573b Michael Hanselmann
  """
1880 fab9573b Michael Hanselmann
  try:
1881 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1882 fab9573b Michael Hanselmann
  except KeyError:
1883 fab9573b Michael Hanselmann
    return default
1884 fab9573b Michael Hanselmann
  else:
1885 fab9573b Michael Hanselmann
    return node.group
1886 fab9573b Michael Hanselmann
1887 fab9573b Michael Hanselmann
1888 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1889 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1890 fab9573b Michael Hanselmann

1891 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1892 fab9573b Michael Hanselmann
  @param default: Default value
1893 fab9573b Michael Hanselmann
  @type node_name: string
1894 fab9573b Michael Hanselmann
  @param node_name: Node name
1895 fab9573b Michael Hanselmann

1896 fab9573b Michael Hanselmann
  """
1897 fab9573b Michael Hanselmann
  try:
1898 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1899 fab9573b Michael Hanselmann
  except KeyError:
1900 fab9573b Michael Hanselmann
    return default
1901 fab9573b Michael Hanselmann
1902 fab9573b Michael Hanselmann
  try:
1903 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1904 fab9573b Michael Hanselmann
  except KeyError:
1905 fab9573b Michael Hanselmann
    return default
1906 fab9573b Michael Hanselmann
1907 fab9573b Michael Hanselmann
  return group.name
1908 fab9573b Michael Hanselmann
1909 fab9573b Michael Hanselmann
1910 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1911 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1912 1c8addc6 Michael Hanselmann

1913 1c8addc6 Michael Hanselmann
  """
1914 1c8addc6 Michael Hanselmann
  fields = [
1915 111bf531 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", QFT_TEXT, "Primary node"),
1916 111bf531 Michael Hanselmann
     IQ_CONFIG, QFF_HOSTNAME, _GetItemAttr("primary_node")),
1917 fab9573b Michael Hanselmann
    (_MakeField("pnode.group", "PrimaryNodeGroup", QFT_TEXT,
1918 fab9573b Michael Hanselmann
                "Primary node's group"),
1919 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1920 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroupName(ctx, _FS_UNAVAIL,
1921 fab9573b Michael Hanselmann
                                             inst.primary_node)),
1922 fab9573b Michael Hanselmann
    (_MakeField("pnode.group.uuid", "PrimaryNodeGroupUUID", QFT_TEXT,
1923 fab9573b Michael Hanselmann
                "Primary node's group UUID"),
1924 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1925 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroup(ctx, _FS_UNAVAIL, inst.primary_node)),
1926 111bf531 Michael Hanselmann
    # TODO: Allow filtering by secondary node as hostname
1927 79b2ca83 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER,
1928 79b2ca83 Michael Hanselmann
                "Secondary nodes; usually this will just be one node"),
1929 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: list(inst.secondary_nodes)),
1930 fab9573b Michael Hanselmann
    (_MakeField("snodes.group", "SecondaryNodesGroups", QFT_OTHER,
1931 fab9573b Michael Hanselmann
                "Node groups of secondary nodes"),
1932 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1933 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroupName, ctx, None),
1934 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1935 fab9573b Michael Hanselmann
    (_MakeField("snodes.group.uuid", "SecondaryNodesGroupsUUID", QFT_OTHER,
1936 fab9573b Michael Hanselmann
                "Node group UUIDs of secondary nodes"),
1937 fab9573b Michael Hanselmann
     IQ_NODES, 0,
1938 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroup, ctx, None),
1939 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
1940 2e04d454 Agata Murawska
    (_MakeField("admin_state", "InstanceState", QFT_TEXT,
1941 2e04d454 Agata Murawska
                "Desired state of instance"),
1942 9ca8a7c5 Agata Murawska
     IQ_CONFIG, 0, _GetItemAttr("admin_state")),
1943 754cc530 Agata Murawska
    (_MakeField("admin_up", "Autostart", QFT_BOOL,
1944 754cc530 Agata Murawska
                "Desired state of instance"),
1945 754cc530 Agata Murawska
     IQ_CONFIG, 0, lambda ctx, inst: inst.admin_state == constants.ADMINST_UP),
1946 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
1947 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
1948 79b2ca83 Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER,
1949 111bf531 Michael Hanselmann
                "Instance console information"), IQ_CONSOLE, 0,
1950 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
1951 1c8addc6 Michael Hanselmann
    ]
1952 1c8addc6 Michael Hanselmann
1953 1c8addc6 Michael Hanselmann
  # Add simple fields
1954 111bf531 Michael Hanselmann
  fields.extend([
1955 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
1956 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()])
1957 1c8addc6 Michael Hanselmann
1958 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1959 1c8addc6 Michael Hanselmann
  fields.extend([
1960 79b2ca83 Michael Hanselmann
    (_MakeField("oper_state", "Running", QFT_BOOL, "Actual state of instance"),
1961 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstOperState),
1962 79b2ca83 Michael Hanselmann
    (_MakeField("oper_ram", "Memory", QFT_UNIT,
1963 79b2ca83 Michael Hanselmann
                "Actual memory usage as seen by hypervisor"),
1964 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("memory")),
1965 79b2ca83 Michael Hanselmann
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER,
1966 79b2ca83 Michael Hanselmann
                "Actual number of VCPUs as seen by hypervisor"),
1967 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("vcpus")),
1968 1c8addc6 Michael Hanselmann
    ])
1969 1c8addc6 Michael Hanselmann
1970 79b2ca83 Michael Hanselmann
  # Status field
1971 79b2ca83 Michael Hanselmann
  status_values = (constants.INSTST_RUNNING, constants.INSTST_ADMINDOWN,
1972 79b2ca83 Michael Hanselmann
                   constants.INSTST_WRONGNODE, constants.INSTST_ERRORUP,
1973 79b2ca83 Michael Hanselmann
                   constants.INSTST_ERRORDOWN, constants.INSTST_NODEDOWN,
1974 2e04d454 Agata Murawska
                   constants.INSTST_NODEOFFLINE, constants.INSTST_ADMINOFFLINE)
1975 79b2ca83 Michael Hanselmann
  status_doc = ("Instance status; \"%s\" if instance is set to be running"
1976 79b2ca83 Michael Hanselmann
                " and actually is, \"%s\" if instance is stopped and"
1977 79b2ca83 Michael Hanselmann
                " is not running, \"%s\" if instance running, but not on its"
1978 79b2ca83 Michael Hanselmann
                " designated primary node, \"%s\" if instance should be"
1979 79b2ca83 Michael Hanselmann
                " stopped, but is actually running, \"%s\" if instance should"
1980 79b2ca83 Michael Hanselmann
                " run, but doesn't, \"%s\" if instance's primary node is down,"
1981 2e04d454 Agata Murawska
                " \"%s\" if instance's primary node is marked offline,"
1982 2e04d454 Agata Murawska
                " \"%s\" if instance is offline and does not use dynamic"
1983 2e04d454 Agata Murawska
                " resources" % status_values)
1984 79b2ca83 Michael Hanselmann
  fields.append((_MakeField("status", "Status", QFT_TEXT, status_doc),
1985 111bf531 Michael Hanselmann
                 IQ_LIVE, 0, _GetInstStatus))
1986 79b2ca83 Michael Hanselmann
  assert set(status_values) == constants.INSTST_ALL, \
1987 79b2ca83 Michael Hanselmann
         "Status documentation mismatch"
1988 79b2ca83 Michael Hanselmann
1989 4cc4d1fa Michael Hanselmann
  (network_fields, network_aliases) = _GetInstanceNetworkFields()
1990 4cc4d1fa Michael Hanselmann
1991 4cc4d1fa Michael Hanselmann
  fields.extend(network_fields)
1992 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1993 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1994 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1995 1c8addc6 Michael Hanselmann
1996 e7e8037b Iustin Pop
  aliases = [
1997 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
1998 31d1791a Guido Trotter
    ("be/memory", "be/maxmem"),
1999 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
2000 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
2001 4cc4d1fa Michael Hanselmann
    ] + network_aliases
2002 e7e8037b Iustin Pop
2003 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
2004 1c8addc6 Michael Hanselmann
2005 1c8addc6 Michael Hanselmann
2006 24d16f76 Michael Hanselmann
class LockQueryData:
2007 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
2008 24d16f76 Michael Hanselmann

2009 24d16f76 Michael Hanselmann
  """
2010 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
2011 24d16f76 Michael Hanselmann
    """Initializes this class.
2012 24d16f76 Michael Hanselmann

2013 24d16f76 Michael Hanselmann
    """
2014 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
2015 24d16f76 Michael Hanselmann
2016 24d16f76 Michael Hanselmann
  def __iter__(self):
2017 24d16f76 Michael Hanselmann
    """Iterate over all locks.
2018 24d16f76 Michael Hanselmann

2019 24d16f76 Michael Hanselmann
    """
2020 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
2021 24d16f76 Michael Hanselmann
2022 24d16f76 Michael Hanselmann
2023 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
2024 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
2025 24d16f76 Michael Hanselmann

2026 24d16f76 Michael Hanselmann
  """
2027 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
2028 24d16f76 Michael Hanselmann
2029 24d16f76 Michael Hanselmann
  if owners:
2030 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
2031 24d16f76 Michael Hanselmann
2032 e2d188cc Iustin Pop
  return owners
2033 24d16f76 Michael Hanselmann
2034 24d16f76 Michael Hanselmann
2035 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
2036 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
2037 24d16f76 Michael Hanselmann

2038 24d16f76 Michael Hanselmann
  """
2039 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
2040 24d16f76 Michael Hanselmann
2041 24d16f76 Michael Hanselmann
  if pending:
2042 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
2043 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
2044 24d16f76 Michael Hanselmann
2045 e2d188cc Iustin Pop
  return pending
2046 24d16f76 Michael Hanselmann
2047 24d16f76 Michael Hanselmann
2048 24d16f76 Michael Hanselmann
def _BuildLockFields():
2049 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
2050 24d16f76 Michael Hanselmann

2051 24d16f76 Michael Hanselmann
  """
2052 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
2053 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
2054 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
2055 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
2056 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
2057 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
2058 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
2059 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
2060 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
2061 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
2062 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
2063 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
2064 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
2065 d63bd540 Iustin Pop
    ], [])
2066 24d16f76 Michael Hanselmann
2067 24d16f76 Michael Hanselmann
2068 8e21cfc0 Adeodato Simo
class GroupQueryData:
2069 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
2070 8e21cfc0 Adeodato Simo

2071 8e21cfc0 Adeodato Simo
  """
2072 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2073 2c758845 René Nussbaumer
               want_diskparams):
2074 8e21cfc0 Adeodato Simo
    """Initializes this class.
2075 8e21cfc0 Adeodato Simo

2076 edd49f9b Agata Murawska
    @param cluster: Cluster object
2077 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2078 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2079 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2080 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2081 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2082 2c758845 René Nussbaumer
    @type want_diskparams: bool
2083 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2084 8e21cfc0 Adeodato Simo

2085 8e21cfc0 Adeodato Simo
    """
2086 8e21cfc0 Adeodato Simo
    self.groups = groups
2087 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2088 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2089 edd49f9b Agata Murawska
    self.cluster = cluster
2090 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2091 edd49f9b Agata Murawska
2092 edd49f9b Agata Murawska
    # Used for individual rows
2093 edd49f9b Agata Murawska
    self.group_ipolicy = None
2094 8930b0f0 Iustin Pop
    self.ndparams = None
2095 2c758845 René Nussbaumer
    self.group_dp = None
2096 8e21cfc0 Adeodato Simo
2097 8e21cfc0 Adeodato Simo
  def __iter__(self):
2098 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2099 8e21cfc0 Adeodato Simo

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

2103 8e21cfc0 Adeodato Simo
    """
2104 edd49f9b Agata Murawska
    for group in self.groups:
2105 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2106 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2107 2c758845 René Nussbaumer
      if self.want_diskparams:
2108 2c758845 René Nussbaumer
        self.group_dp = self.cluster.SimpleFillDP(group.diskparams)
2109 2c758845 René Nussbaumer
      else:
2110 2c758845 René Nussbaumer
        self.group_dp = None
2111 edd49f9b Agata Murawska
      yield group
2112 8e21cfc0 Adeodato Simo
2113 8e21cfc0 Adeodato Simo
2114 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2115 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2116 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2117 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2118 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2119 8e21cfc0 Adeodato Simo
  }
2120 8e21cfc0 Adeodato Simo
2121 8e21cfc0 Adeodato Simo
2122 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2123 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2124 8e21cfc0 Adeodato Simo

2125 8e21cfc0 Adeodato Simo
  """
2126 8e21cfc0 Adeodato Simo
  # Add simple fields
2127 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
2128 111bf531 Michael Hanselmann
             _GetItemAttr(name))
2129 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
2130 8e21cfc0 Adeodato Simo
2131 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
2132 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
2133 8e21cfc0 Adeodato Simo
2134 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
2135 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
2136 8e21cfc0 Adeodato Simo
2137 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
2138 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
2139 8e21cfc0 Adeodato Simo
2140 8e21cfc0 Adeodato Simo
  # Add fields for nodes
2141 8e21cfc0 Adeodato Simo
  fields.extend([
2142 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
2143 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
2144 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
2145 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
2146 8e21cfc0 Adeodato Simo
    ])
2147 8e21cfc0 Adeodato Simo
2148 8e21cfc0 Adeodato Simo
  # Add fields for instances
2149 8e21cfc0 Adeodato Simo
  fields.extend([
2150 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
2151 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
2152 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
2153 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
2154 79b2ca83 Michael Hanselmann
                "List of primary instances"),
2155 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
2156 8e21cfc0 Adeodato Simo
    ])
2157 8e21cfc0 Adeodato Simo
2158 1ffd2673 Michael Hanselmann
  # Other fields
2159 1ffd2673 Michael Hanselmann
  fields.extend([
2160 1ffd2673 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
2161 1ffd2673 Michael Hanselmann
     lambda ctx, group: list(group.GetTags())),
2162 edd49f9b Agata Murawska
    (_MakeField("ipolicy", "InstancePolicy", QFT_OTHER,
2163 edd49f9b Agata Murawska
                "Instance policy limitations (merged)"),
2164 edd49f9b Agata Murawska
     GQ_CONFIG, 0, lambda ctx, _: ctx.group_ipolicy),
2165 edd49f9b Agata Murawska
    (_MakeField("custom_ipolicy", "CustomInstancePolicy", QFT_OTHER,
2166 edd49f9b Agata Murawska
                "Custom instance policy limitations"),
2167 edd49f9b Agata Murawska
     GQ_CONFIG, 0, _GetItemAttr("ipolicy")),
2168 8930b0f0 Iustin Pop
    (_MakeField("custom_ndparams", "CustomNDParams", QFT_OTHER,
2169 8930b0f0 Iustin Pop
                "Custom node parameters"),
2170 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, _GetItemAttr("ndparams")),
2171 8930b0f0 Iustin Pop
    (_MakeField("ndparams", "NDParams", QFT_OTHER,
2172 8930b0f0 Iustin Pop
                "Node parameters"),
2173 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, lambda ctx, _: ctx.ndparams),
2174 2c758845 René Nussbaumer
    (_MakeField("diskparams", "DiskParameters", QFT_OTHER,
2175 2c758845 René Nussbaumer
                "Disk parameters (merged)"),
2176 2c758845 René Nussbaumer
     GQ_DISKPARAMS, 0, lambda ctx, _: ctx.group_dp),
2177 2c758845 René Nussbaumer
    (_MakeField("custom_diskparams", "CustomDiskParameters", QFT_OTHER,
2178 2c758845 René Nussbaumer
                "Custom disk parameters"),
2179 2c758845 René Nussbaumer
     GQ_CONFIG, 0, _GetItemAttr("diskparams")),
2180 1ffd2673 Michael Hanselmann
    ])
2181 1ffd2673 Michael Hanselmann
2182 8930b0f0 Iustin Pop
  # ND parameters
2183 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(True))
2184 8930b0f0 Iustin Pop
2185 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
2186 8e21cfc0 Adeodato Simo
2187 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
2188 8e21cfc0 Adeodato Simo
2189 8e21cfc0 Adeodato Simo
2190 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
2191 be3a4b14 Michael Hanselmann
  __slots__ = [
2192 be3a4b14 Michael Hanselmann
    "name",
2193 be3a4b14 Michael Hanselmann
    "valid",
2194 be3a4b14 Michael Hanselmann
    "hidden",
2195 be3a4b14 Michael Hanselmann
    "blacklisted",
2196 be3a4b14 Michael Hanselmann
    "variants",
2197 be3a4b14 Michael Hanselmann
    "api_versions",
2198 be3a4b14 Michael Hanselmann
    "parameters",
2199 be3a4b14 Michael Hanselmann
    "node_status",
2200 be3a4b14 Michael Hanselmann
    ]
2201 be3a4b14 Michael Hanselmann
2202 be3a4b14 Michael Hanselmann
2203 be3a4b14 Michael Hanselmann
def _BuildOsFields():
2204 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
2205 be3a4b14 Michael Hanselmann

2206 be3a4b14 Michael Hanselmann
  """
2207 be3a4b14 Michael Hanselmann
  fields = [
2208 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2209 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2210 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2211 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2212 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2213 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2214 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2215 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2216 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2217 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2218 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2219 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2220 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2221 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2222 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2223 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2224 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2225 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2226 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2227 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2228 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2229 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2230 be3a4b14 Michael Hanselmann
                "Status from node"),
2231 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2232 be3a4b14 Michael Hanselmann
    ]
2233 be3a4b14 Michael Hanselmann
2234 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2235 be3a4b14 Michael Hanselmann
2236 be3a4b14 Michael Hanselmann
2237 b954f097 Constantinos Venetsanopoulos
class ExtStorageInfo(objects.ConfigObject):
2238 b954f097 Constantinos Venetsanopoulos
  __slots__ = [
2239 b954f097 Constantinos Venetsanopoulos
    "name",
2240 b954f097 Constantinos Venetsanopoulos
    "node_status",
2241 b954f097 Constantinos Venetsanopoulos
    "nodegroup_status",
2242 b954f097 Constantinos Venetsanopoulos
    "parameters",
2243 b954f097 Constantinos Venetsanopoulos
    ]
2244 b954f097 Constantinos Venetsanopoulos
2245 b954f097 Constantinos Venetsanopoulos
2246 b954f097 Constantinos Venetsanopoulos
def _BuildExtStorageFields():
2247 b954f097 Constantinos Venetsanopoulos
  """Builds list of fields for extstorage provider queries.
2248 b954f097 Constantinos Venetsanopoulos

2249 b954f097 Constantinos Venetsanopoulos
  """
2250 b954f097 Constantinos Venetsanopoulos
  fields = [
2251 b954f097 Constantinos Venetsanopoulos
    (_MakeField("name", "Name", QFT_TEXT, "ExtStorage provider name"),
2252 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("name")),
2253 b954f097 Constantinos Venetsanopoulos
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2254 b954f097 Constantinos Venetsanopoulos
                "Status from node"),
2255 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("node_status")),
2256 b954f097 Constantinos Venetsanopoulos
    (_MakeField("nodegroup_status", "NodegroupStatus", QFT_OTHER,
2257 b954f097 Constantinos Venetsanopoulos
                "Overall Nodegroup status"),
2258 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("nodegroup_status")),
2259 b954f097 Constantinos Venetsanopoulos
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2260 b954f097 Constantinos Venetsanopoulos
                "ExtStorage provider parameters"),
2261 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("parameters")),
2262 b954f097 Constantinos Venetsanopoulos
    ]
2263 b954f097 Constantinos Venetsanopoulos
2264 b954f097 Constantinos Venetsanopoulos
  return _PrepareFieldList(fields, [])
2265 b954f097 Constantinos Venetsanopoulos
2266 b954f097 Constantinos Venetsanopoulos
2267 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2268 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2269 9665bb3a Michael Hanselmann

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

2273 9665bb3a Michael Hanselmann
  """
2274 9665bb3a Michael Hanselmann
  if job is None:
2275 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2276 9665bb3a Michael Hanselmann
  else:
2277 9665bb3a Michael Hanselmann
    return fn(job)
2278 9665bb3a Michael Hanselmann
2279 9665bb3a Michael Hanselmann
2280 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2281 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2282 9665bb3a Michael Hanselmann

2283 9665bb3a Michael Hanselmann
  """
2284 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2285 9665bb3a Michael Hanselmann
2286 9665bb3a Michael Hanselmann
2287 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2288 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2289 9665bb3a Michael Hanselmann

2290 9665bb3a Michael Hanselmann
  """
2291 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2292 9665bb3a Michael Hanselmann
2293 9665bb3a Michael Hanselmann
2294 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2295 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2296 9665bb3a Michael Hanselmann

2297 9665bb3a Michael Hanselmann
  """
2298 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2299 9665bb3a Michael Hanselmann
2300 9665bb3a Michael Hanselmann
2301 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2302 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2303 9665bb3a Michael Hanselmann

2304 9665bb3a Michael Hanselmann
  """
2305 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2306 9665bb3a Michael Hanselmann
2307 9665bb3a Michael Hanselmann
  if timestamp is None:
2308 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2309 9665bb3a Michael Hanselmann
  else:
2310 9665bb3a Michael Hanselmann
    return timestamp
2311 9665bb3a Michael Hanselmann
2312 9665bb3a Michael Hanselmann
2313 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2314 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2315 9665bb3a Michael Hanselmann

2316 9665bb3a Michael Hanselmann
  """
2317 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2318 9665bb3a Michael Hanselmann
2319 9665bb3a Michael Hanselmann
2320 9665bb3a Michael Hanselmann
def _BuildJobFields():
2321 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2322 9665bb3a Michael Hanselmann

2323 9665bb3a Michael Hanselmann
  """
2324 9665bb3a Michael Hanselmann
  fields = [
2325 76b62028 Iustin Pop
    (_MakeField("id", "ID", QFT_NUMBER, "Job ID"),
2326 526f866b Michael Hanselmann
     None, QFF_JOB_ID, lambda _, (job_id, job): job_id),
2327 9665bb3a Michael Hanselmann
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2328 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2329 9665bb3a Michael Hanselmann
    (_MakeField("priority", "Priority", QFT_NUMBER,
2330 9665bb3a Michael Hanselmann
                ("Current job priority (%s to %s)" %
2331 9665bb3a Michael Hanselmann
                 (constants.OP_PRIO_LOWEST, constants.OP_PRIO_HIGHEST))),
2332 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcPriority())),
2333 0422250e Michael Hanselmann
    (_MakeField("archived", "Archived", QFT_BOOL, "Whether job is archived"),
2334 0422250e Michael Hanselmann
     JQ_ARCHIVED, 0, lambda _, (job_id, job): job.archived),
2335 9665bb3a Michael Hanselmann
    (_MakeField("ops", "OpCodes", QFT_OTHER, "List of all opcodes"),
2336 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.__getstate__())),
2337 9665bb3a Michael Hanselmann
    (_MakeField("opresult", "OpCode_result", QFT_OTHER,
2338 9665bb3a Michael Hanselmann
                "List of opcodes results"),
2339 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("result"))),
2340 9665bb3a Michael Hanselmann
    (_MakeField("opstatus", "OpCode_status", QFT_OTHER,
2341 9665bb3a Michael Hanselmann
                "List of opcodes status"),
2342 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("status"))),
2343 9665bb3a Michael Hanselmann
    (_MakeField("oplog", "OpCode_log", QFT_OTHER,
2344 9665bb3a Michael Hanselmann
                "List of opcode output logs"),
2345 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("log"))),
2346 9665bb3a Michael Hanselmann
    (_MakeField("opstart", "OpCode_start", QFT_OTHER,
2347 9665bb3a Michael Hanselmann
                "List of opcode start timestamps (before acquiring locks)"),
2348 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("start_timestamp"))),
2349 9665bb3a Michael Hanselmann
    (_MakeField("opexec", "OpCode_exec", QFT_OTHER,
2350 9665bb3a Michael Hanselmann
                "List of opcode execution start timestamps (after acquiring"
2351 9665bb3a Michael Hanselmann
                " locks)"),
2352 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("exec_timestamp"))),
2353 9665bb3a Michael Hanselmann
    (_MakeField("opend", "OpCode_end", QFT_OTHER,
2354 9665bb3a Michael Hanselmann
                "List of opcode execution end timestamps"),
2355 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("end_timestamp"))),
2356 9665bb3a Michael Hanselmann
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2357 9665bb3a Michael Hanselmann
                "List of opcode priorities"),
2358 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2359 9665bb3a Michael Hanselmann
    (_MakeField("summary", "Summary", QFT_OTHER,
2360 9665bb3a Michael Hanselmann
                "List of per-opcode summaries"),
2361 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2362 9665bb3a Michael Hanselmann
    ]
2363 9665bb3a Michael Hanselmann
2364 526f866b Michael Hanselmann
  # Timestamp fields
2365 526f866b Michael Hanselmann
  for (name, attr, title, desc) in [
2366 526f866b Michael Hanselmann
    ("received_ts", "received_timestamp", "Received",
2367 526f866b Michael Hanselmann
     "Timestamp of when job was received"),
2368 526f866b Michael Hanselmann
    ("start_ts", "start_timestamp", "Start", "Timestamp of job start"),
2369 526f866b Michael Hanselmann
    ("end_ts", "end_timestamp", "End", "Timestamp of job end"),
2370 526f866b Michael Hanselmann
    ]:
2371 526f866b Michael Hanselmann
    getter = operator.attrgetter(attr)
2372 526f866b Michael Hanselmann
    fields.extend([
2373 526f866b Michael Hanselmann
      (_MakeField(name, title, QFT_OTHER,
2374 526f866b Michael Hanselmann
                  "%s (tuple containing seconds and microseconds)" % desc),
2375 526f866b Michael Hanselmann
       None, QFF_SPLIT_TIMESTAMP, _JobTimestamp(getter)),
2376 526f866b Michael Hanselmann
      ])
2377 526f866b Michael Hanselmann
2378 9665bb3a Michael Hanselmann
  return _PrepareFieldList(fields, [])
2379 9665bb3a Michael Hanselmann
2380 9665bb3a Michael Hanselmann
2381 0fdf247d Michael Hanselmann
def _GetExportName(_, (node_name, expname)): # pylint: disable=W0613
2382 0fdf247d Michael Hanselmann
  """Returns an export name if available.
2383 0fdf247d Michael Hanselmann

2384 0fdf247d Michael Hanselmann
  """
2385 0fdf247d Michael Hanselmann
  if expname is None:
2386 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2387 0fdf247d Michael Hanselmann
  else:
2388 0fdf247d Michael Hanselmann
    return expname
2389 0fdf247d Michael Hanselmann
2390 0fdf247d Michael Hanselmann
2391 0fdf247d Michael Hanselmann
def _BuildExportFields():
2392 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2393 0fdf247d Michael Hanselmann

2394 0fdf247d Michael Hanselmann
  """
2395 0fdf247d Michael Hanselmann
  fields = [
2396 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2397 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2398 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2399 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2400 0fdf247d Michael Hanselmann
    ]
2401 0fdf247d Michael Hanselmann
2402 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2403 0fdf247d Michael Hanselmann
2404 0fdf247d Michael Hanselmann
2405 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2406 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2407 dff5f600 Michael Hanselmann
                       "Software version"),
2408 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2409 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2410 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2411 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2412 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2413 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2414 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2415 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2416 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2417 dff5f600 Michael Hanselmann
  }
2418 dff5f600 Michael Hanselmann
2419 dff5f600 Michael Hanselmann
2420 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2421 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2422 dff5f600 Michael Hanselmann
  "master_node": ("Master", QFT_TEXT, QFF_HOSTNAME, "Master node name"),
2423 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2424 dff5f600 Michael Hanselmann
  }
2425 dff5f600 Michael Hanselmann
2426 dff5f600 Michael Hanselmann
2427 dff5f600 Michael Hanselmann
class ClusterQueryData:
2428 dff5f600 Michael Hanselmann
  def __init__(self, cluster, drain_flag, watcher_pause):
2429 dff5f600 Michael Hanselmann
    """Initializes this class.
2430 dff5f600 Michael Hanselmann

2431 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2432 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2433 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2434 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2435 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2436 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2437 dff5f600 Michael Hanselmann

2438 dff5f600 Michael Hanselmann
    """
2439 dff5f600 Michael Hanselmann
    self._cluster = cluster
2440 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2441 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2442 dff5f600 Michael Hanselmann
2443 dff5f600 Michael Hanselmann
  def __iter__(self):
2444 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2445 dff5f600 Michael Hanselmann
2446 dff5f600 Michael Hanselmann
2447 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2448 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2449 dff5f600 Michael Hanselmann

2450 dff5f600 Michael Hanselmann
  """
2451 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2452 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2453 dff5f600 Michael Hanselmann
  else:
2454 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2455 dff5f600 Michael Hanselmann
2456 dff5f600 Michael Hanselmann
2457 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2458 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2459 dff5f600 Michael Hanselmann

2460 dff5f600 Michael Hanselmann
  """
2461 dff5f600 Michael Hanselmann
  fields = [
2462 dff5f600 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), CQ_CONFIG, 0,
2463 dff5f600 Michael Hanselmann
     lambda ctx, cluster: list(cluster.GetTags())),
2464 dff5f600 Michael Hanselmann
    (_MakeField("architecture", "ArchInfo", QFT_OTHER,
2465 dff5f600 Michael Hanselmann
                "Architecture information"), None, 0,
2466 dff5f600 Michael Hanselmann
     lambda ctx, _: runtime.GetArchInfo()),
2467 dff5f600 Michael Hanselmann
    (_MakeField("drain_flag", "QueueDrained", QFT_BOOL,
2468 dff5f600 Michael Hanselmann
                "Flag whether job queue is drained"), CQ_QUEUE_DRAINED, 0,
2469 dff5f600 Michael Hanselmann
     lambda ctx, _: ctx.drain_flag),
2470 dff5f600 Michael Hanselmann
    (_MakeField("watcher_pause", "WatcherPause", QFT_TIMESTAMP,
2471 dff5f600 Michael Hanselmann
                "Until when watcher is paused"), CQ_WATCHER_PAUSE, 0,
2472 dff5f600 Michael Hanselmann
     _ClusterWatcherPause),
2473 dff5f600 Michael Hanselmann
    ]
2474 dff5f600 Michael Hanselmann
2475 dff5f600 Michael Hanselmann
  # Simple fields
2476 dff5f600 Michael Hanselmann
  fields.extend([
2477 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), CQ_CONFIG, flags, _GetItemAttr(name))
2478 dff5f600 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _CLUSTER_SIMPLE_FIELDS.items()
2479 3c286190 Dimitris Aragiorgis
    ],)
2480 dff5f600 Michael Hanselmann
2481 dff5f600 Michael Hanselmann
  # Version fields
2482 dff5f600 Michael Hanselmann
  fields.extend([
2483 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), None, 0, _StaticValue(value))
2484 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, value, doc)) in _CLUSTER_VERSION_FIELDS.items()])
2485 dff5f600 Michael Hanselmann
2486 dff5f600 Michael Hanselmann
  # Add timestamps
2487 dff5f600 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(CQ_CONFIG))
2488 dff5f600 Michael Hanselmann
2489 dff5f600 Michael Hanselmann
  return _PrepareFieldList(fields, [
2490 3c286190 Dimitris Aragiorgis
    ("name", "cluster_name")])
2491 dff5f600 Michael Hanselmann
2492 dff5f600 Michael Hanselmann
2493 306bed0e Apollon Oikonomopoulos
class NetworkQueryData:
2494 306bed0e Apollon Oikonomopoulos
  """Data container for network data queries.
2495 306bed0e Apollon Oikonomopoulos

2496 306bed0e Apollon Oikonomopoulos
  """
2497 306bed0e Apollon Oikonomopoulos
  def __init__(self, networks, network_to_groups,
2498 306bed0e Apollon Oikonomopoulos
               network_to_instances, stats):
2499 306bed0e Apollon Oikonomopoulos
    """Initializes this class.
2500 306bed0e Apollon Oikonomopoulos

2501 306bed0e Apollon Oikonomopoulos
    @param networks: List of network objects
2502 306bed0e Apollon Oikonomopoulos
    @type network_to_groups: dict; network UUID as key
2503 306bed0e Apollon Oikonomopoulos
    @param network_to_groups: Per-network list of groups
2504 306bed0e Apollon Oikonomopoulos
    @type network_to_instances: dict; network UUID as key
2505 306bed0e Apollon Oikonomopoulos
    @param network_to_instances: Per-network list of instances
2506 306bed0e Apollon Oikonomopoulos
    @type stats: dict; network UUID as key
2507 306bed0e Apollon Oikonomopoulos
    @param stats: Per-network usage statistics
2508 306bed0e Apollon Oikonomopoulos

2509 306bed0e Apollon Oikonomopoulos
    """
2510 306bed0e Apollon Oikonomopoulos
    self.networks = networks
2511 306bed0e Apollon Oikonomopoulos
    self.network_to_groups = network_to_groups
2512 306bed0e Apollon Oikonomopoulos
    self.network_to_instances = network_to_instances
2513 306bed0e Apollon Oikonomopoulos
    self.stats = stats
2514 306bed0e Apollon Oikonomopoulos
2515 306bed0e Apollon Oikonomopoulos
  def __iter__(self):
2516 306bed0e Apollon Oikonomopoulos
    """Iterate over all networks.
2517 306bed0e Apollon Oikonomopoulos

2518 306bed0e Apollon Oikonomopoulos
    """
2519 306bed0e Apollon Oikonomopoulos
    for net in self.networks:
2520 306bed0e Apollon Oikonomopoulos
      if self.stats:
2521 306bed0e Apollon Oikonomopoulos
        self.curstats = self.stats.get(net.uuid, None)
2522 306bed0e Apollon Oikonomopoulos
      else:
2523 306bed0e Apollon Oikonomopoulos
        self.curstats = None
2524 306bed0e Apollon Oikonomopoulos
      yield net
2525 306bed0e Apollon Oikonomopoulos
2526 306bed0e Apollon Oikonomopoulos
2527 306bed0e Apollon Oikonomopoulos
_NETWORK_SIMPLE_FIELDS = {
2528 0b3f2215 Michael Hanselmann
  "name": ("Network", QFT_TEXT, 0, "Name"),
2529 0b3f2215 Michael Hanselmann
  "network": ("Subnet", QFT_TEXT, 0, "IPv4 subnet"),
2530 0b3f2215 Michael Hanselmann
  "gateway": ("Gateway", QFT_OTHER, 0, "IPv4 gateway"),
2531 0b3f2215 Michael Hanselmann
  "network6": ("IPv6Subnet", QFT_OTHER, 0, "IPv6 subnet"),
2532 0b3f2215 Michael Hanselmann
  "gateway6": ("IPv6Gateway", QFT_OTHER, 0, "IPv6 gateway"),
2533 0b3f2215 Michael Hanselmann
  "mac_prefix": ("MacPrefix", QFT_OTHER, 0, "MAC address prefix"),
2534 9675661c Dimitris Aragiorgis
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Network"),
2535 9675661c Dimitris Aragiorgis
  "uuid": ("UUID", QFT_TEXT, 0, "Network UUID"),
2536 306bed0e Apollon Oikonomopoulos
  }
2537 306bed0e Apollon Oikonomopoulos
2538 306bed0e Apollon Oikonomopoulos
2539 306bed0e Apollon Oikonomopoulos
_NETWORK_STATS_FIELDS = {
2540 0b3f2215 Michael Hanselmann
  "free_count": ("FreeCount", QFT_NUMBER, 0, "Number of available addresses"),
2541 0b3f2215 Michael Hanselmann
  "reserved_count":
2542 0b3f2215 Michael Hanselmann
    ("ReservedCount", QFT_NUMBER, 0, "Number of reserved addresses"),
2543 0b3f2215 Michael Hanselmann
  "map": ("Map", QFT_TEXT, 0, "Actual mapping"),
2544 0b3f2215 Michael Hanselmann
  "external_reservations":
2545 0b3f2215 Michael Hanselmann
    ("ExternalReservations", QFT_TEXT, 0, "External reservations"),
2546 306bed0e Apollon Oikonomopoulos
  }
2547 306bed0e Apollon Oikonomopoulos
2548 3c286190 Dimitris Aragiorgis
2549 83a14695 Helga Velroyen
def _GetNetworkStatsField(field, kind, ctx, _):
2550 306bed0e Apollon Oikonomopoulos
  """Gets the value of a "stats" field from L{NetworkQueryData}.
2551 306bed0e Apollon Oikonomopoulos

2552 306bed0e Apollon Oikonomopoulos
  @param field: Field name
2553 306bed0e Apollon Oikonomopoulos
  @param kind: Data kind, one of L{constants.QFT_ALL}
2554 306bed0e Apollon Oikonomopoulos
  @type ctx: L{NetworkQueryData}
2555 306bed0e Apollon Oikonomopoulos

2556 306bed0e Apollon Oikonomopoulos
  """
2557 b4600d4f Michael Hanselmann
  return _GetStatsField(field, kind, ctx.curstats)
2558 306bed0e Apollon Oikonomopoulos
2559 306bed0e Apollon Oikonomopoulos
2560 306bed0e Apollon Oikonomopoulos
def _BuildNetworkFields():
2561 306bed0e Apollon Oikonomopoulos
  """Builds list of fields for network queries.
2562 306bed0e Apollon Oikonomopoulos

2563 306bed0e Apollon Oikonomopoulos
  """
2564 306bed0e Apollon Oikonomopoulos
  fields = [
2565 8140e24f Dimitris Aragiorgis
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
2566 8140e24f Dimitris Aragiorgis
     lambda ctx, inst: list(inst.GetTags())),
2567 8140e24f Dimitris Aragiorgis
    ]
2568 8140e24f Dimitris Aragiorgis
2569 8140e24f Dimitris Aragiorgis
  # Add simple fields
2570 8140e24f Dimitris Aragiorgis
  fields.extend([
2571 306bed0e Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc),
2572 306bed0e Apollon Oikonomopoulos
     NETQ_CONFIG, 0, _GetItemAttr(name))
2573 3c286190 Dimitris Aragiorgis
     for (name, (title, kind, _, doc)) in _NETWORK_SIMPLE_FIELDS.items()])
2574 306bed0e Apollon Oikonomopoulos
2575 306bed0e Apollon Oikonomopoulos
  def _GetLength(getter):
2576 306bed0e Apollon Oikonomopoulos
    return lambda ctx, network: len(getter(ctx)[network.uuid])
2577 306bed0e Apollon Oikonomopoulos
2578 306bed0e Apollon Oikonomopoulos
  def _GetSortedList(getter):
2579 306bed0e Apollon Oikonomopoulos
    return lambda ctx, network: utils.NiceSort(getter(ctx)[network.uuid])
2580 306bed0e Apollon Oikonomopoulos
2581 306bed0e Apollon Oikonomopoulos
  network_to_groups = operator.attrgetter("network_to_groups")
2582 306bed0e Apollon Oikonomopoulos
  network_to_instances = operator.attrgetter("network_to_instances")
2583 306bed0e Apollon Oikonomopoulos
2584 306bed0e Apollon Oikonomopoulos
  # Add fields for node groups
2585 306bed0e Apollon Oikonomopoulos
  fields.extend([
2586 306bed0e Apollon Oikonomopoulos
    (_MakeField("group_cnt", "NodeGroups", QFT_NUMBER, "Number of nodegroups"),
2587 306bed0e Apollon Oikonomopoulos
     NETQ_GROUP, 0, _GetLength(network_to_groups)),
2588 503574ec Michael Hanselmann
    (_MakeField("group_list", "GroupList", QFT_OTHER,
2589 503574ec Michael Hanselmann
     "List of nodegroups (group name, NIC mode, NIC link)"),
2590 503574ec Michael Hanselmann
     NETQ_GROUP, 0, lambda ctx, network: network_to_groups(ctx)[network.uuid]),
2591 306bed0e Apollon Oikonomopoulos
    ])
2592 306bed0e Apollon Oikonomopoulos
2593 306bed0e Apollon Oikonomopoulos
  # Add fields for instances
2594 306bed0e Apollon Oikonomopoulos
  fields.extend([
2595 306bed0e Apollon Oikonomopoulos
    (_MakeField("inst_cnt", "Instances", QFT_NUMBER, "Number of instances"),
2596 306bed0e Apollon Oikonomopoulos
     NETQ_INST, 0, _GetLength(network_to_instances)),
2597 306bed0e Apollon Oikonomopoulos
    (_MakeField("inst_list", "InstanceList", QFT_OTHER, "List of instances"),
2598 306bed0e Apollon Oikonomopoulos
     NETQ_INST, 0, _GetSortedList(network_to_instances)),
2599 306bed0e Apollon Oikonomopoulos
    ])
2600 306bed0e Apollon Oikonomopoulos
2601 306bed0e Apollon Oikonomopoulos
  # Add fields for usage statistics
2602 306bed0e Apollon Oikonomopoulos
  fields.extend([
2603 306bed0e Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc), NETQ_STATS, 0,
2604 306bed0e Apollon Oikonomopoulos
    compat.partial(_GetNetworkStatsField, name, kind))
2605 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, _, doc)) in _NETWORK_STATS_FIELDS.items()])
2606 306bed0e Apollon Oikonomopoulos
2607 306bed0e Apollon Oikonomopoulos
  return _PrepareFieldList(fields, [])
2608 306bed0e Apollon Oikonomopoulos
2609 dff5f600 Michael Hanselmann
#: Fields for cluster information
2610 dff5f600 Michael Hanselmann
CLUSTER_FIELDS = _BuildClusterFields()
2611 dff5f600 Michael Hanselmann
2612 8235fe04 Michael Hanselmann
#: Fields available for node queries
2613 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2614 1c8addc6 Michael Hanselmann
2615 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2616 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2617 24d16f76 Michael Hanselmann
2618 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2619 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2620 e571ee44 Adeodato Simo
2621 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2622 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2623 8e21cfc0 Adeodato Simo
2624 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2625 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2626 be3a4b14 Michael Hanselmann
2627 b954f097 Constantinos Venetsanopoulos
#: Fields available for extstorage provider queries
2628 b954f097 Constantinos Venetsanopoulos
EXTSTORAGE_FIELDS = _BuildExtStorageFields()
2629 b954f097 Constantinos Venetsanopoulos
2630 9665bb3a Michael Hanselmann
#: Fields available for job queries
2631 9665bb3a Michael Hanselmann
JOB_FIELDS = _BuildJobFields()
2632 9665bb3a Michael Hanselmann
2633 0fdf247d Michael Hanselmann
#: Fields available for exports
2634 0fdf247d Michael Hanselmann
EXPORT_FIELDS = _BuildExportFields()
2635 0fdf247d Michael Hanselmann
2636 306bed0e Apollon Oikonomopoulos
#: Fields available for network queries
2637 306bed0e Apollon Oikonomopoulos
NETWORK_FIELDS = _BuildNetworkFields()
2638 306bed0e Apollon Oikonomopoulos
2639 95eb4188 Michael Hanselmann
#: All available resources
2640 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2641 dff5f600 Michael Hanselmann
  constants.QR_CLUSTER: CLUSTER_FIELDS,
2642 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2643 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2644 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2645 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2646 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2647 b954f097 Constantinos Venetsanopoulos
  constants.QR_EXTSTORAGE: EXTSTORAGE_FIELDS,
2648 9665bb3a Michael Hanselmann
  constants.QR_JOB: JOB_FIELDS,
2649 0fdf247d Michael Hanselmann
  constants.QR_EXPORT: EXPORT_FIELDS,
2650 306bed0e Apollon Oikonomopoulos
  constants.QR_NETWORK: NETWORK_FIELDS,
2651 95eb4188 Michael Hanselmann
  }
2652 95eb4188 Michael Hanselmann
2653 e571ee44 Adeodato Simo
#: All available field lists
2654 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()