Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ fe4d3d25

History | View | Annotate | Download (76.8 kB)

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

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

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

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

53 8f8ce6d1 Michael Hanselmann
"""
54 4ca96421 Michael Hanselmann
55 8235fe04 Michael Hanselmann
import logging
56 4ca96421 Michael Hanselmann
import operator
57 4ca96421 Michael Hanselmann
import re
58 4ca96421 Michael Hanselmann
59 4ca96421 Michael Hanselmann
from ganeti import constants
60 4ca96421 Michael Hanselmann
from ganeti import errors
61 4ca96421 Michael Hanselmann
from ganeti import utils
62 4ca96421 Michael Hanselmann
from ganeti import compat
63 4ca96421 Michael Hanselmann
from ganeti import objects
64 4ca96421 Michael Hanselmann
from ganeti import ht
65 dff5f600 Michael Hanselmann
from ganeti import runtime
66 fb0be379 Michael Hanselmann
from ganeti import qlang
67 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 0263c60d Apollon Oikonomopoulos
(NETQ_CONFIG,
75 0263c60d Apollon Oikonomopoulos
 NETQ_GROUP,
76 0263c60d Apollon Oikonomopoulos
 NETQ_STATS,
77 0263c60d 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 111bf531 Michael Hanselmann
# Query field flags
109 111bf531 Michael Hanselmann
QFF_HOSTNAME = 0x01
110 111bf531 Michael Hanselmann
QFF_IP_ADDRESS = 0x02
111 526f866b Michael Hanselmann
QFF_JOB_ID = 0x04
112 526f866b Michael Hanselmann
QFF_SPLIT_TIMESTAMP = 0x08
113 526f866b Michael Hanselmann
# Next values: 0x10, 0x20, 0x40, 0x80, 0x100, 0x200
114 526f866b Michael Hanselmann
QFF_ALL = (QFF_HOSTNAME | QFF_IP_ADDRESS | QFF_JOB_ID | QFF_SPLIT_TIMESTAMP)
115 8e21cfc0 Adeodato Simo
116 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
117 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
118 1ae17369 Michael Hanselmann
DOC_RE = re.compile(r"^[A-Z].*[^.,?!]$")
119 4ca96421 Michael Hanselmann
120 4ca96421 Michael Hanselmann
#: Verification function for each field type
121 4ca96421 Michael Hanselmann
_VERIFY_FN = {
122 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
123 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
124 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
125 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
126 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
127 697f49d5 Michael Hanselmann
  QFT_TIMESTAMP: ht.TNumber,
128 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
129 4ca96421 Michael Hanselmann
  }
130 4ca96421 Michael Hanselmann
131 e2d188cc Iustin Pop
# Unique objects for special field statuses
132 e2d188cc Iustin Pop
_FS_UNKNOWN = object()
133 e2d188cc Iustin Pop
_FS_NODATA = object()
134 e2d188cc Iustin Pop
_FS_UNAVAIL = object()
135 e2d188cc Iustin Pop
_FS_OFFLINE = object()
136 e2d188cc Iustin Pop
137 425e5bf0 Michael Hanselmann
#: List of all special status
138 425e5bf0 Michael Hanselmann
_FS_ALL = frozenset([_FS_UNKNOWN, _FS_NODATA, _FS_UNAVAIL, _FS_OFFLINE])
139 425e5bf0 Michael Hanselmann
140 af58707c Iustin Pop
#: VType to QFT mapping
141 af58707c Iustin Pop
_VTToQFT = {
142 af58707c Iustin Pop
  # TODO: fix validation of empty strings
143 af58707c Iustin Pop
  constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty
144 af58707c Iustin Pop
  constants.VTYPE_MAYBE_STRING: QFT_OTHER,
145 af58707c Iustin Pop
  constants.VTYPE_BOOL: QFT_BOOL,
146 af58707c Iustin Pop
  constants.VTYPE_SIZE: QFT_UNIT,
147 af58707c Iustin Pop
  constants.VTYPE_INT: QFT_NUMBER,
148 af58707c Iustin Pop
  }
149 af58707c Iustin Pop
150 79b2ca83 Michael Hanselmann
_SERIAL_NO_DOC = "%s object serial number, incremented on each modification"
151 79b2ca83 Michael Hanselmann
152 8930b0f0 Iustin Pop
# TODO: Consider moving titles closer to constants
153 8930b0f0 Iustin Pop
NDP_TITLE = {
154 8930b0f0 Iustin Pop
  constants.ND_OOB_PROGRAM: "OutOfBandProgram",
155 8930b0f0 Iustin Pop
  constants.ND_SPINDLE_COUNT: "SpindleCount",
156 8930b0f0 Iustin Pop
  }
157 8930b0f0 Iustin Pop
158 4ca96421 Michael Hanselmann
159 b459a848 Andrea Spadaccini
def _GetUnknownField(ctx, item): # pylint: disable=W0613
160 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
161 4ca96421 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

288 fb0be379 Michael Hanselmann
    """
289 fb0be379 Michael Hanselmann
    self._NeedAllNames()
290 fb0be379 Michael Hanselmann
291 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
292 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
293 fb0be379 Michael Hanselmann

294 fb0be379 Michael Hanselmann
    @type op: string
295 fb0be379 Michael Hanselmann
    @param op: Operator
296 fb0be379 Michael Hanselmann
    @type name: string
297 fb0be379 Michael Hanselmann
    @param name: Left-hand side of operator (field name)
298 fb0be379 Michael Hanselmann
    @param value: Right-hand side of operator
299 fb0be379 Michael Hanselmann

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

320 fb0be379 Michael Hanselmann
  """
321 fb0be379 Michael Hanselmann
  return op_fn(fn(ctx, item) for fn in sentences)
322 fb0be379 Michael Hanselmann
323 fb0be379 Michael Hanselmann
324 fb0be379 Michael Hanselmann
def _WrapUnaryOp(op_fn, inner, ctx, item):
325 fb0be379 Michael Hanselmann
  """Wrapper for unary operator functions.
326 fb0be379 Michael Hanselmann

327 fb0be379 Michael Hanselmann
  """
328 fb0be379 Michael Hanselmann
  return op_fn(inner(ctx, item))
329 fb0be379 Michael Hanselmann
330 fb0be379 Michael Hanselmann
331 fb0be379 Michael Hanselmann
def _WrapBinaryOp(op_fn, retrieval_fn, value, ctx, item):
332 fb0be379 Michael Hanselmann
  """Wrapper for binary operator functions.
333 fb0be379 Michael Hanselmann

334 fb0be379 Michael Hanselmann
  """
335 fb0be379 Michael Hanselmann
  return op_fn(retrieval_fn(ctx, item), value)
336 fb0be379 Michael Hanselmann
337 fb0be379 Michael Hanselmann
338 fb0be379 Michael Hanselmann
def _WrapNot(fn, lhs, rhs):
339 fb0be379 Michael Hanselmann
  """Negates the result of a wrapped function.
340 fb0be379 Michael Hanselmann

341 fb0be379 Michael Hanselmann
  """
342 fb0be379 Michael Hanselmann
  return not fn(lhs, rhs)
343 fb0be379 Michael Hanselmann
344 fb0be379 Michael Hanselmann
345 23d0a608 Michael Hanselmann
def _PrepareRegex(pattern):
346 23d0a608 Michael Hanselmann
  """Compiles a regular expression.
347 23d0a608 Michael Hanselmann

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

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

368 526f866b Michael Hanselmann
  """
369 526f866b Michael Hanselmann
  return lambda lhs, rhs: fn(utils.MergeTime(lhs), rhs)
370 526f866b Michael Hanselmann
371 526f866b Michael Hanselmann
372 526f866b Michael Hanselmann
def _MakeComparisonChecks(fn):
373 526f866b Michael Hanselmann
  """Prepares flag-specific comparisons using a comparison function.
374 526f866b Michael Hanselmann

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

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

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

405 fb0be379 Michael Hanselmann
  Order matters. The first item with flags will be used. Flags are checked
406 fb0be379 Michael Hanselmann
  using binary AND.
407 fb0be379 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

593 fb0be379 Michael Hanselmann
    @type hints_fn: callable
594 fb0be379 Michael Hanselmann
    @param hints_fn: Callback doing some analysis on the filter
595 fb0be379 Michael Hanselmann
    @type level: integer
596 fb0be379 Michael Hanselmann
    @param level: Current depth
597 fb0be379 Michael Hanselmann
    @type op: string
598 fb0be379 Michael Hanselmann
    @param op: Operator
599 fb0be379 Michael Hanselmann
    @param op_data: Functions implementing operators
600 fb0be379 Michael Hanselmann
    @type operands: list
601 fb0be379 Michael Hanselmann
    @param operands: List of operands
602 fb0be379 Michael Hanselmann

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

642 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
643 fb0be379 Michael Hanselmann

644 fb0be379 Michael Hanselmann
  @rtype: callable
645 fb0be379 Michael Hanselmann

646 fb0be379 Michael Hanselmann
  """
647 2e5c33db Iustin Pop
  return _FilterCompilerHelper(fields)(hints, qfilter)
648 fb0be379 Michael Hanselmann
649 fb0be379 Michael Hanselmann
650 4ca96421 Michael Hanselmann
class Query:
651 2e5c33db Iustin Pop
  def __init__(self, fieldlist, selected, qfilter=None, namefield=None):
652 4ca96421 Michael Hanselmann
    """Initializes this class.
653 4ca96421 Michael Hanselmann

654 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
655 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
656 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
657 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
658 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
659 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
660 4ca96421 Michael Hanselmann

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

664 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
665 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
666 4ca96421 Michael Hanselmann
    @type selected: list of strings
667 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
668 4ca96421 Michael Hanselmann

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

699 fb0be379 Michael Hanselmann
    If there is no filter or operators are preventing determining the exact
700 fb0be379 Michael Hanselmann
    names, C{None} is returned.
701 fb0be379 Michael Hanselmann

702 fb0be379 Michael Hanselmann
    """
703 fb0be379 Michael Hanselmann
    return self._requested_names
704 fb0be379 Michael Hanselmann
705 4ca96421 Michael Hanselmann
  def RequestedData(self):
706 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
707 4ca96421 Michael Hanselmann

708 4ca96421 Michael Hanselmann
    @rtype: frozenset
709 4ca96421 Michael Hanselmann

710 4ca96421 Michael Hanselmann
    """
711 fb0be379 Michael Hanselmann
    return (self._filter_datakinds |
712 fb0be379 Michael Hanselmann
            frozenset(datakind for (_, datakind, _, _) in self._fields
713 fb0be379 Michael Hanselmann
                      if datakind is not None))
714 4ca96421 Michael Hanselmann
715 4ca96421 Michael Hanselmann
  def GetFields(self):
716 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
717 4ca96421 Michael Hanselmann

718 4ca96421 Michael Hanselmann
    Includes unknown fields.
719 4ca96421 Michael Hanselmann

720 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
721 4ca96421 Michael Hanselmann

722 4ca96421 Michael Hanselmann
    """
723 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
724 4ca96421 Michael Hanselmann
725 fbc263a9 Michael Hanselmann
  def Query(self, ctx, sort_by_name=True):
726 4ca96421 Michael Hanselmann
    """Execute a query.
727 4ca96421 Michael Hanselmann

728 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
729 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
730 fbc263a9 Michael Hanselmann
    @type sort_by_name: boolean
731 fbc263a9 Michael Hanselmann
    @param sort_by_name: Whether to sort by name or keep the input data's
732 fbc263a9 Michael Hanselmann
      ordering
733 4ca96421 Michael Hanselmann

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

772 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
773 4ca96421 Michael Hanselmann

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

789 e2d188cc Iustin Pop
  """
790 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
791 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
792 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
793 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
794 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
795 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
796 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
797 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
798 e2d188cc Iustin Pop
  else:
799 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
800 e2d188cc Iustin Pop
801 e2d188cc Iustin Pop
802 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
803 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
804 4ca96421 Michael Hanselmann

805 4ca96421 Michael Hanselmann
  @type fields: list
806 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
807 4ca96421 Michael Hanselmann
  @type row: list of tuples
808 4ca96421 Michael Hanselmann
  @param row: Row data
809 4ca96421 Michael Hanselmann

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

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

843 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
844 4ca96421 Michael Hanselmann

845 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
846 d63bd540 Iustin Pop
      kind, retrieval function)
847 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
848 d63bd540 Iustin Pop
      description
849 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
850 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
851 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
852 4ca96421 Michael Hanselmann
  @rtype: dict
853 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
854 4ca96421 Michael Hanselmann

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

881 b60fcb6f Michael Hanselmann
  @type query: L{Query}
882 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
883 fbc263a9 Michael Hanselmann
  @type sort_by_name: boolean
884 fbc263a9 Michael Hanselmann
  @param sort_by_name: Whether to sort by name or keep the input data's
885 fbc263a9 Michael Hanselmann
    ordering
886 b60fcb6f Michael Hanselmann

887 b60fcb6f Michael Hanselmann
  """
888 fbc263a9 Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx, sort_by_name=sort_by_name),
889 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
890 b60fcb6f Michael Hanselmann
891 b60fcb6f Michael Hanselmann
892 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
893 aa29e95f Michael Hanselmann
  """Returns list of available fields.
894 aa29e95f Michael Hanselmann

895 aa29e95f Michael Hanselmann
  @type fielddefs: dict
896 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
897 aa29e95f Michael Hanselmann
  @type selected: list of strings
898 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
899 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
900 aa29e95f Michael Hanselmann

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

916 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
917 4ca96421 Michael Hanselmann
  @param title: Human-readable title
918 4ca96421 Michael Hanselmann
  @param kind: Field type
919 1ae17369 Michael Hanselmann
  @param doc: Human-readable description
920 4ca96421 Michael Hanselmann

921 4ca96421 Michael Hanselmann
  """
922 1ae17369 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind,
923 1ae17369 Michael Hanselmann
                                      doc=doc)
924 8235fe04 Michael Hanselmann
925 8235fe04 Michael Hanselmann
926 dff5f600 Michael Hanselmann
def _StaticValueInner(value, ctx, _): # pylint: disable=W0613
927 dff5f600 Michael Hanselmann
  """Returns a static value.
928 dff5f600 Michael Hanselmann

929 dff5f600 Michael Hanselmann
  """
930 dff5f600 Michael Hanselmann
  return value
931 dff5f600 Michael Hanselmann
932 dff5f600 Michael Hanselmann
933 dff5f600 Michael Hanselmann
def _StaticValue(value):
934 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
935 dff5f600 Michael Hanselmann

936 dff5f600 Michael Hanselmann
  """
937 dff5f600 Michael Hanselmann
  return compat.partial(_StaticValueInner, value)
938 dff5f600 Michael Hanselmann
939 dff5f600 Michael Hanselmann
940 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
941 8235fe04 Michael Hanselmann
  """Determine node role.
942 8235fe04 Michael Hanselmann

943 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
944 8235fe04 Michael Hanselmann
  @param node: Node object
945 8235fe04 Michael Hanselmann
  @type master_name: string
946 8235fe04 Michael Hanselmann
  @param master_name: Master node name
947 8235fe04 Michael Hanselmann

948 8235fe04 Michael Hanselmann
  """
949 8235fe04 Michael Hanselmann
  if node.name == master_name:
950 1e28e3b8 Michael Hanselmann
    return constants.NR_MASTER
951 8235fe04 Michael Hanselmann
  elif node.master_candidate:
952 1e28e3b8 Michael Hanselmann
    return constants.NR_MCANDIDATE
953 8235fe04 Michael Hanselmann
  elif node.drained:
954 1e28e3b8 Michael Hanselmann
    return constants.NR_DRAINED
955 8235fe04 Michael Hanselmann
  elif node.offline:
956 1e28e3b8 Michael Hanselmann
    return constants.NR_OFFLINE
957 8235fe04 Michael Hanselmann
  else:
958 1e28e3b8 Michael Hanselmann
    return constants.NR_REGULAR
959 8235fe04 Michael Hanselmann
960 8235fe04 Michael Hanselmann
961 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
962 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
963 8235fe04 Michael Hanselmann

964 8235fe04 Michael Hanselmann
  @param attr: Attribute name
965 8235fe04 Michael Hanselmann

966 8235fe04 Michael Hanselmann
  """
967 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
968 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
969 8235fe04 Michael Hanselmann
970 8235fe04 Michael Hanselmann
971 8930b0f0 Iustin Pop
def _GetNDParam(name):
972 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
973 8930b0f0 Iustin Pop

974 8930b0f0 Iustin Pop
  """
975 8930b0f0 Iustin Pop
  def _helper(ctx, _):
976 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
977 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
978 8930b0f0 Iustin Pop
    else:
979 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
980 8930b0f0 Iustin Pop
  return _helper
981 8930b0f0 Iustin Pop
982 8930b0f0 Iustin Pop
983 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
984 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
985 8930b0f0 Iustin Pop

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

988 8930b0f0 Iustin Pop
  """
989 8930b0f0 Iustin Pop
  if is_group:
990 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
991 8930b0f0 Iustin Pop
  else:
992 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
993 8930b0f0 Iustin Pop
  return [(_MakeField("ndp/%s" % name, NDP_TITLE.get(name, "ndp/%s" % name),
994 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
995 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
996 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
997 8930b0f0 Iustin Pop
998 8930b0f0 Iustin Pop
999 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
1000 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
1001 425e5bf0 Michael Hanselmann

1002 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1003 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1004 425e5bf0 Michael Hanselmann

1005 425e5bf0 Michael Hanselmann
  """
1006 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
1007 425e5bf0 Michael Hanselmann
1008 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
1009 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
1010 425e5bf0 Michael Hanselmann
    # Return right away
1011 425e5bf0 Michael Hanselmann
    return value
1012 425e5bf0 Michael Hanselmann
1013 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
1014 425e5bf0 Michael Hanselmann
  return convert(value)
1015 425e5bf0 Michael Hanselmann
1016 425e5bf0 Michael Hanselmann
1017 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
1018 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
1019 425e5bf0 Michael Hanselmann

1020 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1021 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1022 425e5bf0 Michael Hanselmann

1023 425e5bf0 Michael Hanselmann
  """
1024 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
1025 425e5bf0 Michael Hanselmann
1026 425e5bf0 Michael Hanselmann
1027 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
1028 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
1029 145bea54 Michael Hanselmann

1030 145bea54 Michael Hanselmann
  @type getter: callable
1031 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1032 145bea54 Michael Hanselmann

1033 145bea54 Michael Hanselmann
  """
1034 145bea54 Michael Hanselmann
  def fn(_, item):
1035 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1036 145bea54 Michael Hanselmann

1037 145bea54 Michael Hanselmann
    """
1038 145bea54 Michael Hanselmann
    timestamp = getter(item)
1039 145bea54 Michael Hanselmann
    if timestamp is None:
1040 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
1041 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1042 145bea54 Michael Hanselmann
    else:
1043 e2d188cc Iustin Pop
      return timestamp
1044 145bea54 Michael Hanselmann
1045 145bea54 Michael Hanselmann
  return fn
1046 145bea54 Michael Hanselmann
1047 145bea54 Michael Hanselmann
1048 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
1049 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
1050 145bea54 Michael Hanselmann

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

1053 145bea54 Michael Hanselmann
  """
1054 145bea54 Michael Hanselmann
  return [
1055 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
1056 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
1057 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
1058 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
1059 145bea54 Michael Hanselmann
    ]
1060 145bea54 Michael Hanselmann
1061 145bea54 Michael Hanselmann
1062 8235fe04 Michael Hanselmann
class NodeQueryData:
1063 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1064 8235fe04 Michael Hanselmann

1065 8235fe04 Michael Hanselmann
  """
1066 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1067 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1068 8235fe04 Michael Hanselmann
    """Initializes this class.
1069 8235fe04 Michael Hanselmann

1070 8235fe04 Michael Hanselmann
    """
1071 8235fe04 Michael Hanselmann
    self.nodes = nodes
1072 8235fe04 Michael Hanselmann
    self.live_data = live_data
1073 8235fe04 Michael Hanselmann
    self.master_name = master_name
1074 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1075 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1076 8235fe04 Michael Hanselmann
    self.groups = groups
1077 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1078 8572f1fe René Nussbaumer
    self.cluster = cluster
1079 8235fe04 Michael Hanselmann
1080 8235fe04 Michael Hanselmann
    # Used for individual rows
1081 8235fe04 Michael Hanselmann
    self.curlive_data = None
1082 8930b0f0 Iustin Pop
    self.ndparams = None
1083 8235fe04 Michael Hanselmann
1084 8235fe04 Michael Hanselmann
  def __iter__(self):
1085 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1086 8235fe04 Michael Hanselmann

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

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

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

1149 8572f1fe René Nussbaumer
  """
1150 8572f1fe René Nussbaumer
  def fn(ctx, node):
1151 8572f1fe René Nussbaumer
    """Get group data for a node.
1152 8572f1fe René Nussbaumer

1153 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1154 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1155 8572f1fe René Nussbaumer
    @param inst: Node object
1156 8572f1fe René Nussbaumer

1157 8572f1fe René Nussbaumer
    """
1158 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1159 8572f1fe René Nussbaumer
    if ng is None:
1160 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1161 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1162 8572f1fe René Nussbaumer
1163 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1164 8572f1fe René Nussbaumer
1165 8572f1fe René Nussbaumer
  return fn
1166 8572f1fe René Nussbaumer
1167 8572f1fe René Nussbaumer
1168 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1169 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1170 8235fe04 Michael Hanselmann

1171 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1172 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1173 8235fe04 Michael Hanselmann
  @param node: Node object
1174 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1175 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1176 8235fe04 Michael Hanselmann

1177 8235fe04 Michael Hanselmann
  """
1178 e2d188cc Iustin Pop
  return ng.name
1179 8235fe04 Michael Hanselmann
1180 8235fe04 Michael Hanselmann
1181 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1182 52b5d286 René Nussbaumer
  """Returns the node powered state
1183 52b5d286 René Nussbaumer

1184 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1185 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1186 52b5d286 René Nussbaumer
  @param node: Node object
1187 52b5d286 René Nussbaumer

1188 52b5d286 René Nussbaumer
  """
1189 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1190 e2d188cc Iustin Pop
    return node.powered
1191 52b5d286 René Nussbaumer
1192 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1193 52b5d286 René Nussbaumer
1194 52b5d286 René Nussbaumer
1195 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1196 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1197 8572f1fe René Nussbaumer

1198 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1199 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1200 8572f1fe René Nussbaumer
  @param node: Node object
1201 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1202 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1203 8572f1fe René Nussbaumer

1204 8572f1fe René Nussbaumer
  """
1205 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1206 8572f1fe René Nussbaumer
1207 8572f1fe René Nussbaumer
1208 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1209 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1210 8235fe04 Michael Hanselmann

1211 8235fe04 Michael Hanselmann
  @param field: Live field name
1212 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1213 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1214 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1215 a6070ef7 Michael Hanselmann
  @param node: Node object
1216 8235fe04 Michael Hanselmann

1217 8235fe04 Michael Hanselmann
  """
1218 a6070ef7 Michael Hanselmann
  if node.offline:
1219 e2d188cc Iustin Pop
    return _FS_OFFLINE
1220 a6070ef7 Michael Hanselmann
1221 effab4ca Iustin Pop
  if not node.vm_capable:
1222 effab4ca Iustin Pop
    return _FS_UNAVAIL
1223 effab4ca Iustin Pop
1224 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1225 e2d188cc Iustin Pop
    return _FS_NODATA
1226 8235fe04 Michael Hanselmann
1227 8235fe04 Michael Hanselmann
  try:
1228 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
1229 8235fe04 Michael Hanselmann
  except KeyError:
1230 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1231 8235fe04 Michael Hanselmann
1232 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1233 e2d188cc Iustin Pop
    return value
1234 8235fe04 Michael Hanselmann
1235 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1236 8235fe04 Michael Hanselmann
1237 8235fe04 Michael Hanselmann
  # Try to convert into number
1238 8235fe04 Michael Hanselmann
  try:
1239 e2d188cc Iustin Pop
    return int(value)
1240 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1241 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1242 8235fe04 Michael Hanselmann
                      value, field)
1243 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1244 8235fe04 Michael Hanselmann
1245 8235fe04 Michael Hanselmann
1246 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1247 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1248 54ac87c0 Michael Hanselmann

1249 54ac87c0 Michael Hanselmann
  """
1250 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1251 54ac87c0 Michael Hanselmann
1252 54ac87c0 Michael Hanselmann
  if hv_state is None:
1253 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1254 54ac87c0 Michael Hanselmann
1255 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1256 54ac87c0 Michael Hanselmann
1257 54ac87c0 Michael Hanselmann
1258 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1259 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1260 54ac87c0 Michael Hanselmann

1261 54ac87c0 Michael Hanselmann
  """
1262 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1263 54ac87c0 Michael Hanselmann
1264 54ac87c0 Michael Hanselmann
  if disk_state is None:
1265 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1266 54ac87c0 Michael Hanselmann
1267 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1268 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1269 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1270 54ac87c0 Michael Hanselmann
1271 54ac87c0 Michael Hanselmann
1272 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1273 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1274 8235fe04 Michael Hanselmann

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

1360 1c8addc6 Michael Hanselmann
  """
1361 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
1362 fab9573b Michael Hanselmann
               live_data, wrongnode_inst, console, nodes, groups):
1363 1c8addc6 Michael Hanselmann
    """Initializes this class.
1364 1c8addc6 Michael Hanselmann

1365 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1366 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1367 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
1368 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1369 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
1370 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
1371 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
1372 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
1373 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
1374 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1375 e431074f René Nussbaumer
    @type wrongnode_inst: set
1376 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1377 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
1378 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1379 fab9573b Michael Hanselmann
    @type nodes: dict; node name as key
1380 fab9573b Michael Hanselmann
    @param nodes: Node objects
1381 1c8addc6 Michael Hanselmann

1382 1c8addc6 Michael Hanselmann
    """
1383 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
1384 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1385 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
1386 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1387 1c8addc6 Michael Hanselmann
1388 1c8addc6 Michael Hanselmann
    self.instances = instances
1389 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1390 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1391 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
1392 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
1393 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1394 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1395 5d28cb6f Michael Hanselmann
    self.console = console
1396 fab9573b Michael Hanselmann
    self.nodes = nodes
1397 fab9573b Michael Hanselmann
    self.groups = groups
1398 1c8addc6 Michael Hanselmann
1399 1c8addc6 Michael Hanselmann
    # Used for individual rows
1400 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1401 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1402 7c670076 Michael Hanselmann
    self.inst_osparams = None
1403 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1404 1c8addc6 Michael Hanselmann
1405 1c8addc6 Michael Hanselmann
  def __iter__(self):
1406 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1407 1c8addc6 Michael Hanselmann

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

1411 1c8addc6 Michael Hanselmann
    """
1412 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1413 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1414 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1415 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1416 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1417 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1418 1c8addc6 Michael Hanselmann
1419 1c8addc6 Michael Hanselmann
      yield inst
1420 1c8addc6 Michael Hanselmann
1421 1c8addc6 Michael Hanselmann
1422 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1423 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1424 1c8addc6 Michael Hanselmann

1425 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1426 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1427 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1428 1c8addc6 Michael Hanselmann

1429 1c8addc6 Michael Hanselmann
  """
1430 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1431 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1432 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1433 e2d188cc Iustin Pop
    return _FS_NODATA
1434 1c8addc6 Michael Hanselmann
  else:
1435 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
1436 1c8addc6 Michael Hanselmann
1437 1c8addc6 Michael Hanselmann
1438 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1439 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1440 1c8addc6 Michael Hanselmann

1441 1c8addc6 Michael Hanselmann
  @type name: string
1442 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1443 1c8addc6 Michael Hanselmann

1444 1c8addc6 Michael Hanselmann
  """
1445 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1446 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1447 1c8addc6 Michael Hanselmann

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

1452 1c8addc6 Michael Hanselmann
    """
1453 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1454 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1455 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1456 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1457 e2d188cc Iustin Pop
      return _FS_NODATA
1458 1c8addc6 Michael Hanselmann
1459 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1460 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1461 1c8addc6 Michael Hanselmann
      if name in data:
1462 e2d188cc Iustin Pop
        return data[name]
1463 1c8addc6 Michael Hanselmann
1464 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1465 1c8addc6 Michael Hanselmann
1466 1c8addc6 Michael Hanselmann
  return fn
1467 1c8addc6 Michael Hanselmann
1468 1c8addc6 Michael Hanselmann
1469 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1470 1c8addc6 Michael Hanselmann
  """Get instance status.
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.offline_nodes:
1478 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1479 1c8addc6 Michael Hanselmann
1480 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1481 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1482 1c8addc6 Michael Hanselmann
1483 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1484 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1485 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1486 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1487 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1488 1c8addc6 Michael Hanselmann
    else:
1489 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1490 1c8addc6 Michael Hanselmann
1491 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1492 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1493 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1494 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1495 1c8addc6 Michael Hanselmann
1496 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1497 1c8addc6 Michael Hanselmann
1498 1c8addc6 Michael Hanselmann
1499 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1500 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1501 1c8addc6 Michael Hanselmann

1502 1c8addc6 Michael Hanselmann
  @type index: int
1503 1c8addc6 Michael Hanselmann
  @param index: Disk index
1504 1c8addc6 Michael Hanselmann

1505 1c8addc6 Michael Hanselmann
  """
1506 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1507 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1508 1c8addc6 Michael Hanselmann

1509 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1510 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1511 1c8addc6 Michael Hanselmann

1512 1c8addc6 Michael Hanselmann
    """
1513 1c8addc6 Michael Hanselmann
    try:
1514 e2d188cc Iustin Pop
      return inst.disks[index].size
1515 1c8addc6 Michael Hanselmann
    except IndexError:
1516 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1517 1c8addc6 Michael Hanselmann
1518 1c8addc6 Michael Hanselmann
  return fn
1519 1c8addc6 Michael Hanselmann
1520 1c8addc6 Michael Hanselmann
1521 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1522 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1523 1c8addc6 Michael Hanselmann

1524 1c8addc6 Michael Hanselmann
  @type index: int
1525 1c8addc6 Michael Hanselmann
  @param index: NIC index
1526 1c8addc6 Michael Hanselmann
  @type cb: callable
1527 1c8addc6 Michael Hanselmann
  @param cb: Callback
1528 1c8addc6 Michael Hanselmann

1529 1c8addc6 Michael Hanselmann
  """
1530 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1531 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1532 1c8addc6 Michael Hanselmann

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

1537 1c8addc6 Michael Hanselmann
    """
1538 1c8addc6 Michael Hanselmann
    try:
1539 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1540 1c8addc6 Michael Hanselmann
    except IndexError:
1541 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1542 1c8addc6 Michael Hanselmann
1543 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1544 1c8addc6 Michael Hanselmann
1545 1c8addc6 Michael Hanselmann
  return fn
1546 1c8addc6 Michael Hanselmann
1547 1c8addc6 Michael Hanselmann
1548 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1549 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1550 1c8addc6 Michael Hanselmann

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

1555 1c8addc6 Michael Hanselmann
  """
1556 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1557 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1558 1c8addc6 Michael Hanselmann
  else:
1559 e2d188cc Iustin Pop
    return nic.ip
1560 1c8addc6 Michael Hanselmann
1561 1c8addc6 Michael Hanselmann
1562 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1563 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1564 1c8addc6 Michael Hanselmann

1565 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1566 1c8addc6 Michael Hanselmann
  @type index: int
1567 1c8addc6 Michael Hanselmann
  @param index: NIC index
1568 1c8addc6 Michael Hanselmann

1569 1c8addc6 Michael Hanselmann
  """
1570 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1571 1c8addc6 Michael Hanselmann
1572 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1573 1c8addc6 Michael Hanselmann
1574 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1575 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1576 1c8addc6 Michael Hanselmann
  else:
1577 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1578 1c8addc6 Michael Hanselmann
1579 1c8addc6 Michael Hanselmann
1580 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1581 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1582 1c8addc6 Michael Hanselmann

1583 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1584 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1585 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1586 1c8addc6 Michael Hanselmann

1587 1c8addc6 Michael Hanselmann
  """
1588 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1589 1c8addc6 Michael Hanselmann
1590 1c8addc6 Michael Hanselmann
  result = []
1591 1c8addc6 Michael Hanselmann
1592 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1593 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1594 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1595 1c8addc6 Michael Hanselmann
    else:
1596 1c8addc6 Michael Hanselmann
      result.append(None)
1597 1c8addc6 Michael Hanselmann
1598 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1599 1c8addc6 Michael Hanselmann
1600 e2d188cc Iustin Pop
  return result
1601 1c8addc6 Michael Hanselmann
1602 1c8addc6 Michael Hanselmann
1603 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1604 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1605 1c8addc6 Michael Hanselmann

1606 1c8addc6 Michael Hanselmann
  @type name: string
1607 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1608 1c8addc6 Michael Hanselmann

1609 1c8addc6 Michael Hanselmann
  """
1610 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1611 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1612 1c8addc6 Michael Hanselmann

1613 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1614 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1615 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1616 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1617 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1618 1c8addc6 Michael Hanselmann

1619 1c8addc6 Michael Hanselmann
    """
1620 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1621 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1622 1c8addc6 Michael Hanselmann
1623 1c8addc6 Michael Hanselmann
  return fn
1624 1c8addc6 Michael Hanselmann
1625 1c8addc6 Michael Hanselmann
1626 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1627 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1628 1c8addc6 Michael Hanselmann

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

1632 1c8addc6 Michael Hanselmann
  """
1633 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1634 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1635 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1636 1c8addc6 Michael Hanselmann
1637 1c8addc6 Michael Hanselmann
  fields = [
1638 1c8addc6 Michael Hanselmann
    # All NICs
1639 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1640 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1641 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1642 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1643 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1644 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1645 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1646 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1647 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1648 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1649 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1650 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1651 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1652 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1653 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1654 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1655 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1656 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1657 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1658 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1659 1c8addc6 Michael Hanselmann
    ]
1660 1c8addc6 Michael Hanselmann
1661 1c8addc6 Michael Hanselmann
  # NICs by number
1662 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1663 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1664 1c8addc6 Michael Hanselmann
    fields.extend([
1665 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1666 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1667 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1668 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1669 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1670 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1671 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1672 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1673 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1674 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1675 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1676 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1677 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1678 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1679 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1680 1c8addc6 Michael Hanselmann
      ])
1681 1c8addc6 Michael Hanselmann
1682 4cc4d1fa Michael Hanselmann
  aliases = [
1683 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1684 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1685 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1686 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1687 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1688 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1689 4cc4d1fa Michael Hanselmann
    ]
1690 4cc4d1fa Michael Hanselmann
1691 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1692 1c8addc6 Michael Hanselmann
1693 1c8addc6 Michael Hanselmann
1694 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1695 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1696 1c8addc6 Michael Hanselmann

1697 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1698 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1699 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1700 1c8addc6 Michael Hanselmann

1701 1c8addc6 Michael Hanselmann
  """
1702 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1703 1c8addc6 Michael Hanselmann
1704 1c8addc6 Michael Hanselmann
  if usage is None:
1705 1c8addc6 Michael Hanselmann
    usage = 0
1706 1c8addc6 Michael Hanselmann
1707 e2d188cc Iustin Pop
  return usage
1708 1c8addc6 Michael Hanselmann
1709 1c8addc6 Michael Hanselmann
1710 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1711 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1712 5d28cb6f Michael Hanselmann

1713 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1714 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1715 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1716 5d28cb6f Michael Hanselmann

1717 5d28cb6f Michael Hanselmann
  """
1718 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1719 5d28cb6f Michael Hanselmann
1720 5d28cb6f Michael Hanselmann
  if consinfo is None:
1721 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1722 5d28cb6f Michael Hanselmann
1723 5d28cb6f Michael Hanselmann
  return consinfo
1724 5d28cb6f Michael Hanselmann
1725 5d28cb6f Michael Hanselmann
1726 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1727 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1728 1c8addc6 Michael Hanselmann

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

1731 1c8addc6 Michael Hanselmann
  """
1732 1c8addc6 Michael Hanselmann
  fields = [
1733 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1734 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1735 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1736 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1737 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1738 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1739 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1740 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1741 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1742 1c8addc6 Michael Hanselmann
    ]
1743 1c8addc6 Michael Hanselmann
1744 1c8addc6 Michael Hanselmann
  # Disks by number
1745 1c8addc6 Michael Hanselmann
  fields.extend([
1746 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1747 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1748 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1749 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1750 1c8addc6 Michael Hanselmann
    ])
1751 1c8addc6 Michael Hanselmann
1752 1c8addc6 Michael Hanselmann
  return fields
1753 1c8addc6 Michael Hanselmann
1754 1c8addc6 Michael Hanselmann
1755 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1756 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1757 1c8addc6 Michael Hanselmann

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

1760 1c8addc6 Michael Hanselmann
  """
1761 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1762 1c8addc6 Michael Hanselmann
  be_title = {
1763 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1764 31d1791a Guido Trotter
    constants.BE_MAXMEM: "ConfigMaxMem",
1765 31d1791a Guido Trotter
    constants.BE_MINMEM: "ConfigMinMem",
1766 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1767 1c8addc6 Michael Hanselmann
    }
1768 1c8addc6 Michael Hanselmann
1769 1c8addc6 Michael Hanselmann
  hv_title = {
1770 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1771 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1772 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1773 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1774 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1775 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1776 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1777 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1778 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1779 87f0aa48 Jack
    constants.HV_PASSTHROUGH: "pci_pass",
1780 1c8addc6 Michael Hanselmann
    }
1781 1c8addc6 Michael Hanselmann
1782 1c8addc6 Michael Hanselmann
  fields = [
1783 1c8addc6 Michael Hanselmann
    # Filled parameters
1784 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
1785 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
1786 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
1787 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
1788 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
1789 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
1790 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
1791 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
1792 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
1793 1c8addc6 Michael Hanselmann
1794 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1795 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
1796 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
1797 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
1798 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
1799 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
1800 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
1801 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
1802 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
1803 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
1804 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
1805 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
1806 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1807 1c8addc6 Michael Hanselmann
    ]
1808 1c8addc6 Michael Hanselmann
1809 1c8addc6 Michael Hanselmann
  # HV params
1810 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1811 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1812 1c8addc6 Michael Hanselmann
1813 1c8addc6 Michael Hanselmann
  fields.extend([
1814 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1815 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
1816 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
1817 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1818 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1819 1c8addc6 Michael Hanselmann
    ])
1820 1c8addc6 Michael Hanselmann
1821 1c8addc6 Michael Hanselmann
  # BE params
1822 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1823 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1824 1c8addc6 Michael Hanselmann
1825 1c8addc6 Michael Hanselmann
  fields.extend([
1826 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1827 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
1828 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
1829 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1830 1c8addc6 Michael Hanselmann
    ])
1831 1c8addc6 Michael Hanselmann
1832 1c8addc6 Michael Hanselmann
  return fields
1833 1c8addc6 Michael Hanselmann
1834 1c8addc6 Michael Hanselmann
1835 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1836 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
1837 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
1838 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
1839 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1840 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
1841 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
1842 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
1843 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
1844 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
1845 1c8addc6 Michael Hanselmann
  }
1846 1c8addc6 Michael Hanselmann
1847 1c8addc6 Michael Hanselmann
1848 fab9573b Michael Hanselmann
def _GetInstNodeGroup(ctx, default, node_name):
1849 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
1850 fab9573b Michael Hanselmann

1851 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1852 fab9573b Michael Hanselmann
  @param default: Default value
1853 fab9573b Michael Hanselmann
  @type node_name: string
1854 fab9573b Michael Hanselmann
  @param node_name: Node name
1855 fab9573b Michael Hanselmann

1856 fab9573b Michael Hanselmann
  """
1857 fab9573b Michael Hanselmann
  try:
1858 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1859 fab9573b Michael Hanselmann
  except KeyError:
1860 fab9573b Michael Hanselmann
    return default
1861 fab9573b Michael Hanselmann
  else:
1862 fab9573b Michael Hanselmann
    return node.group
1863 fab9573b Michael Hanselmann
1864 fab9573b Michael Hanselmann
1865 fab9573b Michael Hanselmann
def _GetInstNodeGroupName(ctx, default, node_name):
1866 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
1867 fab9573b Michael Hanselmann

1868 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1869 fab9573b Michael Hanselmann
  @param default: Default value
1870 fab9573b Michael Hanselmann
  @type node_name: string
1871 fab9573b Michael Hanselmann
  @param node_name: Node name
1872 fab9573b Michael Hanselmann

1873 fab9573b Michael Hanselmann
  """
1874 fab9573b Michael Hanselmann
  try:
1875 fab9573b Michael Hanselmann
    node = ctx.nodes[node_name]
1876 fab9573b Michael Hanselmann
  except KeyError:
1877 fab9573b Michael Hanselmann
    return default
1878 fab9573b Michael Hanselmann
1879 fab9573b Michael Hanselmann
  try:
1880 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
1881 fab9573b Michael Hanselmann
  except KeyError:
1882 fab9573b Michael Hanselmann
    return default
1883 fab9573b Michael Hanselmann
1884 fab9573b Michael Hanselmann
  return group.name
1885 fab9573b Michael Hanselmann
1886 fab9573b Michael Hanselmann
1887 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1888 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1889 1c8addc6 Michael Hanselmann

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

1987 24d16f76 Michael Hanselmann
  """
1988 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1989 24d16f76 Michael Hanselmann
    """Initializes this class.
1990 24d16f76 Michael Hanselmann

1991 24d16f76 Michael Hanselmann
    """
1992 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1993 24d16f76 Michael Hanselmann
1994 24d16f76 Michael Hanselmann
  def __iter__(self):
1995 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1996 24d16f76 Michael Hanselmann

1997 24d16f76 Michael Hanselmann
    """
1998 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1999 24d16f76 Michael Hanselmann
2000 24d16f76 Michael Hanselmann
2001 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
2002 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
2003 24d16f76 Michael Hanselmann

2004 24d16f76 Michael Hanselmann
  """
2005 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
2006 24d16f76 Michael Hanselmann
2007 24d16f76 Michael Hanselmann
  if owners:
2008 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
2009 24d16f76 Michael Hanselmann
2010 e2d188cc Iustin Pop
  return owners
2011 24d16f76 Michael Hanselmann
2012 24d16f76 Michael Hanselmann
2013 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
2014 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
2015 24d16f76 Michael Hanselmann

2016 24d16f76 Michael Hanselmann
  """
2017 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
2018 24d16f76 Michael Hanselmann
2019 24d16f76 Michael Hanselmann
  if pending:
2020 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
2021 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
2022 24d16f76 Michael Hanselmann
2023 e2d188cc Iustin Pop
  return pending
2024 24d16f76 Michael Hanselmann
2025 24d16f76 Michael Hanselmann
2026 24d16f76 Michael Hanselmann
def _BuildLockFields():
2027 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
2028 24d16f76 Michael Hanselmann

2029 24d16f76 Michael Hanselmann
  """
2030 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
2031 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
2032 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
2033 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
2034 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
2035 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
2036 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
2037 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
2038 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
2039 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
2040 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
2041 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
2042 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
2043 d63bd540 Iustin Pop
    ], [])
2044 24d16f76 Michael Hanselmann
2045 24d16f76 Michael Hanselmann
2046 8e21cfc0 Adeodato Simo
class GroupQueryData:
2047 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
2048 8e21cfc0 Adeodato Simo

2049 8e21cfc0 Adeodato Simo
  """
2050 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2051 2c758845 René Nussbaumer
               want_diskparams):
2052 8e21cfc0 Adeodato Simo
    """Initializes this class.
2053 8e21cfc0 Adeodato Simo

2054 edd49f9b Agata Murawska
    @param cluster: Cluster object
2055 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2056 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2057 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2058 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2059 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2060 2c758845 René Nussbaumer
    @type want_diskparams: bool
2061 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2062 8e21cfc0 Adeodato Simo

2063 8e21cfc0 Adeodato Simo
    """
2064 8e21cfc0 Adeodato Simo
    self.groups = groups
2065 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2066 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2067 edd49f9b Agata Murawska
    self.cluster = cluster
2068 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2069 edd49f9b Agata Murawska
2070 edd49f9b Agata Murawska
    # Used for individual rows
2071 edd49f9b Agata Murawska
    self.group_ipolicy = None
2072 8930b0f0 Iustin Pop
    self.ndparams = None
2073 2c758845 René Nussbaumer
    self.group_dp = None
2074 8e21cfc0 Adeodato Simo
2075 8e21cfc0 Adeodato Simo
  def __iter__(self):
2076 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2077 8e21cfc0 Adeodato Simo

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

2081 8e21cfc0 Adeodato Simo
    """
2082 edd49f9b Agata Murawska
    for group in self.groups:
2083 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2084 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2085 2c758845 René Nussbaumer
      if self.want_diskparams:
2086 2c758845 René Nussbaumer
        self.group_dp = self.cluster.SimpleFillDP(group.diskparams)
2087 2c758845 René Nussbaumer
      else:
2088 2c758845 René Nussbaumer
        self.group_dp = None
2089 edd49f9b Agata Murawska
      yield group
2090 8e21cfc0 Adeodato Simo
2091 8e21cfc0 Adeodato Simo
2092 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2093 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2094 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2095 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2096 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2097 8e21cfc0 Adeodato Simo
  }
2098 8e21cfc0 Adeodato Simo
2099 8e21cfc0 Adeodato Simo
2100 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2101 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2102 8e21cfc0 Adeodato Simo

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

2184 be3a4b14 Michael Hanselmann
  """
2185 be3a4b14 Michael Hanselmann
  fields = [
2186 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2187 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2188 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2189 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2190 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2191 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2192 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2193 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2194 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2195 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2196 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2197 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2198 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2199 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2200 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2201 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2202 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2203 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2204 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2205 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2206 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2207 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2208 be3a4b14 Michael Hanselmann
                "Status from node"),
2209 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2210 be3a4b14 Michael Hanselmann
    ]
2211 be3a4b14 Michael Hanselmann
2212 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2213 be3a4b14 Michael Hanselmann
2214 be3a4b14 Michael Hanselmann
2215 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2216 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2217 9665bb3a Michael Hanselmann

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

2221 9665bb3a Michael Hanselmann
  """
2222 9665bb3a Michael Hanselmann
  if job is None:
2223 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2224 9665bb3a Michael Hanselmann
  else:
2225 9665bb3a Michael Hanselmann
    return fn(job)
2226 9665bb3a Michael Hanselmann
2227 9665bb3a Michael Hanselmann
2228 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2229 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2230 9665bb3a Michael Hanselmann

2231 9665bb3a Michael Hanselmann
  """
2232 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2233 9665bb3a Michael Hanselmann
2234 9665bb3a Michael Hanselmann
2235 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2236 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2237 9665bb3a Michael Hanselmann

2238 9665bb3a Michael Hanselmann
  """
2239 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2240 9665bb3a Michael Hanselmann
2241 9665bb3a Michael Hanselmann
2242 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2243 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2244 9665bb3a Michael Hanselmann

2245 9665bb3a Michael Hanselmann
  """
2246 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2247 9665bb3a Michael Hanselmann
2248 9665bb3a Michael Hanselmann
2249 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2250 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2251 9665bb3a Michael Hanselmann

2252 9665bb3a Michael Hanselmann
  """
2253 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2254 9665bb3a Michael Hanselmann
2255 9665bb3a Michael Hanselmann
  if timestamp is None:
2256 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2257 9665bb3a Michael Hanselmann
  else:
2258 9665bb3a Michael Hanselmann
    return timestamp
2259 9665bb3a Michael Hanselmann
2260 9665bb3a Michael Hanselmann
2261 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2262 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2263 9665bb3a Michael Hanselmann

2264 9665bb3a Michael Hanselmann
  """
2265 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2266 9665bb3a Michael Hanselmann
2267 9665bb3a Michael Hanselmann
2268 9665bb3a Michael Hanselmann
def _BuildJobFields():
2269 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2270 9665bb3a Michael Hanselmann

2271 9665bb3a Michael Hanselmann
  """
2272 9665bb3a Michael Hanselmann
  fields = [
2273 9665bb3a Michael Hanselmann
    (_MakeField("id", "ID", QFT_TEXT, "Job ID"),
2274 526f866b Michael Hanselmann
     None, QFF_JOB_ID, lambda _, (job_id, job): job_id),
2275 9665bb3a Michael Hanselmann
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2276 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2277 9665bb3a Michael Hanselmann
    (_MakeField("priority", "Priority", QFT_NUMBER,
2278 9665bb3a Michael Hanselmann
                ("Current job priority (%s to %s)" %
2279 9665bb3a Michael Hanselmann
                 (constants.OP_PRIO_LOWEST, constants.OP_PRIO_HIGHEST))),
2280 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcPriority())),
2281 9665bb3a Michael Hanselmann
    (_MakeField("ops", "OpCodes", QFT_OTHER, "List of all opcodes"),
2282 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.__getstate__())),
2283 9665bb3a Michael Hanselmann
    (_MakeField("opresult", "OpCode_result", QFT_OTHER,
2284 9665bb3a Michael Hanselmann
                "List of opcodes results"),
2285 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("result"))),
2286 9665bb3a Michael Hanselmann
    (_MakeField("opstatus", "OpCode_status", QFT_OTHER,
2287 9665bb3a Michael Hanselmann
                "List of opcodes status"),
2288 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("status"))),
2289 9665bb3a Michael Hanselmann
    (_MakeField("oplog", "OpCode_log", QFT_OTHER,
2290 9665bb3a Michael Hanselmann
                "List of opcode output logs"),
2291 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("log"))),
2292 9665bb3a Michael Hanselmann
    (_MakeField("opstart", "OpCode_start", QFT_OTHER,
2293 9665bb3a Michael Hanselmann
                "List of opcode start timestamps (before acquiring locks)"),
2294 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("start_timestamp"))),
2295 9665bb3a Michael Hanselmann
    (_MakeField("opexec", "OpCode_exec", QFT_OTHER,
2296 9665bb3a Michael Hanselmann
                "List of opcode execution start timestamps (after acquiring"
2297 9665bb3a Michael Hanselmann
                " locks)"),
2298 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("exec_timestamp"))),
2299 9665bb3a Michael Hanselmann
    (_MakeField("opend", "OpCode_end", QFT_OTHER,
2300 9665bb3a Michael Hanselmann
                "List of opcode execution end timestamps"),
2301 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("end_timestamp"))),
2302 9665bb3a Michael Hanselmann
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2303 9665bb3a Michael Hanselmann
                "List of opcode priorities"),
2304 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2305 9665bb3a Michael Hanselmann
    (_MakeField("summary", "Summary", QFT_OTHER,
2306 9665bb3a Michael Hanselmann
                "List of per-opcode summaries"),
2307 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2308 9665bb3a Michael Hanselmann
    ]
2309 9665bb3a Michael Hanselmann
2310 526f866b Michael Hanselmann
  # Timestamp fields
2311 526f866b Michael Hanselmann
  for (name, attr, title, desc) in [
2312 526f866b Michael Hanselmann
    ("received_ts", "received_timestamp", "Received",
2313 526f866b Michael Hanselmann
     "Timestamp of when job was received"),
2314 526f866b Michael Hanselmann
    ("start_ts", "start_timestamp", "Start", "Timestamp of job start"),
2315 526f866b Michael Hanselmann
    ("end_ts", "end_timestamp", "End", "Timestamp of job end"),
2316 526f866b Michael Hanselmann
    ]:
2317 526f866b Michael Hanselmann
    getter = operator.attrgetter(attr)
2318 526f866b Michael Hanselmann
    fields.extend([
2319 526f866b Michael Hanselmann
      (_MakeField(name, title, QFT_OTHER,
2320 526f866b Michael Hanselmann
                  "%s (tuple containing seconds and microseconds)" % desc),
2321 526f866b Michael Hanselmann
       None, QFF_SPLIT_TIMESTAMP, _JobTimestamp(getter)),
2322 526f866b Michael Hanselmann
      ])
2323 526f866b Michael Hanselmann
2324 9665bb3a Michael Hanselmann
  return _PrepareFieldList(fields, [])
2325 9665bb3a Michael Hanselmann
2326 9665bb3a Michael Hanselmann
2327 0fdf247d Michael Hanselmann
def _GetExportName(_, (node_name, expname)): # pylint: disable=W0613
2328 0fdf247d Michael Hanselmann
  """Returns an export name if available.
2329 0fdf247d Michael Hanselmann

2330 0fdf247d Michael Hanselmann
  """
2331 0fdf247d Michael Hanselmann
  if expname is None:
2332 0fdf247d Michael Hanselmann
    return _FS_UNAVAIL
2333 0fdf247d Michael Hanselmann
  else:
2334 0fdf247d Michael Hanselmann
    return expname
2335 0fdf247d Michael Hanselmann
2336 0fdf247d Michael Hanselmann
2337 0fdf247d Michael Hanselmann
def _BuildExportFields():
2338 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2339 0fdf247d Michael Hanselmann

2340 0fdf247d Michael Hanselmann
  """
2341 0fdf247d Michael Hanselmann
  fields = [
2342 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2343 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2344 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2345 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2346 0fdf247d Michael Hanselmann
    ]
2347 0fdf247d Michael Hanselmann
2348 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2349 0fdf247d Michael Hanselmann
2350 0fdf247d Michael Hanselmann
2351 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2352 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2353 dff5f600 Michael Hanselmann
                       "Software version"),
2354 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2355 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2356 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2357 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2358 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2359 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2360 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2361 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2362 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2363 dff5f600 Michael Hanselmann
  }
2364 dff5f600 Michael Hanselmann
2365 dff5f600 Michael Hanselmann
2366 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2367 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2368 dff5f600 Michael Hanselmann
  "master_node": ("Master", QFT_TEXT, QFF_HOSTNAME, "Master node name"),
2369 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2370 dff5f600 Michael Hanselmann
  }
2371 dff5f600 Michael Hanselmann
2372 dff5f600 Michael Hanselmann
2373 dff5f600 Michael Hanselmann
class ClusterQueryData:
2374 dff5f600 Michael Hanselmann
  def __init__(self, cluster, drain_flag, watcher_pause):
2375 dff5f600 Michael Hanselmann
    """Initializes this class.
2376 dff5f600 Michael Hanselmann

2377 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2378 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2379 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2380 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2381 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2382 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2383 dff5f600 Michael Hanselmann

2384 dff5f600 Michael Hanselmann
    """
2385 dff5f600 Michael Hanselmann
    self._cluster = cluster
2386 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2387 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2388 dff5f600 Michael Hanselmann
2389 dff5f600 Michael Hanselmann
  def __iter__(self):
2390 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2391 dff5f600 Michael Hanselmann
2392 dff5f600 Michael Hanselmann
2393 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2394 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2395 dff5f600 Michael Hanselmann

2396 dff5f600 Michael Hanselmann
  """
2397 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2398 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2399 dff5f600 Michael Hanselmann
  else:
2400 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2401 dff5f600 Michael Hanselmann
2402 dff5f600 Michael Hanselmann
2403 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2404 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2405 dff5f600 Michael Hanselmann

2406 dff5f600 Michael Hanselmann
  """
2407 dff5f600 Michael Hanselmann
  fields = [
2408 dff5f600 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), CQ_CONFIG, 0,
2409 dff5f600 Michael Hanselmann
     lambda ctx, cluster: list(cluster.GetTags())),
2410 dff5f600 Michael Hanselmann
    (_MakeField("architecture", "ArchInfo", QFT_OTHER,
2411 dff5f600 Michael Hanselmann
                "Architecture information"), None, 0,
2412 dff5f600 Michael Hanselmann
     lambda ctx, _: runtime.GetArchInfo()),
2413 dff5f600 Michael Hanselmann
    (_MakeField("drain_flag", "QueueDrained", QFT_BOOL,
2414 dff5f600 Michael Hanselmann
                "Flag whether job queue is drained"), CQ_QUEUE_DRAINED, 0,
2415 dff5f600 Michael Hanselmann
     lambda ctx, _: ctx.drain_flag),
2416 dff5f600 Michael Hanselmann
    (_MakeField("watcher_pause", "WatcherPause", QFT_TIMESTAMP,
2417 dff5f600 Michael Hanselmann
                "Until when watcher is paused"), CQ_WATCHER_PAUSE, 0,
2418 dff5f600 Michael Hanselmann
     _ClusterWatcherPause),
2419 dff5f600 Michael Hanselmann
    ]
2420 dff5f600 Michael Hanselmann
2421 dff5f600 Michael Hanselmann
  # Simple fields
2422 dff5f600 Michael Hanselmann
  fields.extend([
2423 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), CQ_CONFIG, flags, _GetItemAttr(name))
2424 dff5f600 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _CLUSTER_SIMPLE_FIELDS.items()
2425 dff5f600 Michael Hanselmann
    ])
2426 dff5f600 Michael Hanselmann
2427 dff5f600 Michael Hanselmann
  # Version fields
2428 dff5f600 Michael Hanselmann
  fields.extend([
2429 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), None, 0, _StaticValue(value))
2430 dff5f600 Michael Hanselmann
    for (name, (title, kind, value, doc)) in _CLUSTER_VERSION_FIELDS.items()
2431 dff5f600 Michael Hanselmann
    ])
2432 dff5f600 Michael Hanselmann
2433 dff5f600 Michael Hanselmann
  # Add timestamps
2434 dff5f600 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(CQ_CONFIG))
2435 dff5f600 Michael Hanselmann
2436 dff5f600 Michael Hanselmann
  return _PrepareFieldList(fields, [
2437 dff5f600 Michael Hanselmann
    ("name", "cluster_name"),
2438 dff5f600 Michael Hanselmann
    ])
2439 dff5f600 Michael Hanselmann
2440 dff5f600 Michael Hanselmann
2441 0263c60d Apollon Oikonomopoulos
class NetworkQueryData:
2442 0263c60d Apollon Oikonomopoulos
  """Data container for network data queries.
2443 0263c60d Apollon Oikonomopoulos

2444 0263c60d Apollon Oikonomopoulos
  """
2445 0263c60d Apollon Oikonomopoulos
  def __init__(self, networks, network_to_groups,
2446 0263c60d Apollon Oikonomopoulos
               network_to_instances, stats):
2447 0263c60d Apollon Oikonomopoulos
    """Initializes this class.
2448 0263c60d Apollon Oikonomopoulos

2449 0263c60d Apollon Oikonomopoulos
    @param networks: List of network objects
2450 0263c60d Apollon Oikonomopoulos
    @type network_to_groups: dict; network UUID as key
2451 0263c60d Apollon Oikonomopoulos
    @param network_to_groups: Per-network list of groups
2452 0263c60d Apollon Oikonomopoulos
    @type network_to_instances: dict; network UUID as key
2453 0263c60d Apollon Oikonomopoulos
    @param network_to_instances: Per-network list of instances
2454 0263c60d Apollon Oikonomopoulos
    @type stats: dict; network UUID as key
2455 0263c60d Apollon Oikonomopoulos
    @param stats: Per-network usage statistics
2456 0263c60d Apollon Oikonomopoulos

2457 0263c60d Apollon Oikonomopoulos
    """
2458 0263c60d Apollon Oikonomopoulos
    self.networks = networks
2459 0263c60d Apollon Oikonomopoulos
    self.network_to_groups = network_to_groups
2460 0263c60d Apollon Oikonomopoulos
    self.network_to_instances = network_to_instances
2461 0263c60d Apollon Oikonomopoulos
    self.stats = stats
2462 0263c60d Apollon Oikonomopoulos
2463 0263c60d Apollon Oikonomopoulos
  def __iter__(self):
2464 0263c60d Apollon Oikonomopoulos
    """Iterate over all networks.
2465 0263c60d Apollon Oikonomopoulos

2466 0263c60d Apollon Oikonomopoulos
    """
2467 0263c60d Apollon Oikonomopoulos
    for net in self.networks:
2468 0263c60d Apollon Oikonomopoulos
      if self.stats:
2469 0263c60d Apollon Oikonomopoulos
        self.curstats = self.stats.get(net.uuid, None)
2470 0263c60d Apollon Oikonomopoulos
      else:
2471 0263c60d Apollon Oikonomopoulos
        self.curstats = None
2472 0263c60d Apollon Oikonomopoulos
      yield net
2473 0263c60d Apollon Oikonomopoulos
2474 0263c60d Apollon Oikonomopoulos
2475 0263c60d Apollon Oikonomopoulos
_NETWORK_SIMPLE_FIELDS = {
2476 0263c60d Apollon Oikonomopoulos
  "name": ("Network", QFT_TEXT, 0, "The network"),
2477 0263c60d Apollon Oikonomopoulos
  "network": ("Subnet", QFT_TEXT, 0, "The subnet"),
2478 0263c60d Apollon Oikonomopoulos
  "gateway": ("Gateway", QFT_OTHER, 0, "The gateway"),
2479 0263c60d Apollon Oikonomopoulos
  "network6": ("IPv6Subnet", QFT_OTHER, 0, "The ipv6 subnet"),
2480 0263c60d Apollon Oikonomopoulos
  "gateway6": ("IPv6Gateway", QFT_OTHER, 0, "The ipv6 gateway"),
2481 0263c60d Apollon Oikonomopoulos
  "mac_prefix": ("MacPrefix", QFT_OTHER, 0, "The mac prefix"),
2482 0263c60d Apollon Oikonomopoulos
  "network_type": ("NetworkType", QFT_OTHER, 0, "The network type"),
2483 0263c60d Apollon Oikonomopoulos
  }
2484 0263c60d Apollon Oikonomopoulos
2485 0263c60d Apollon Oikonomopoulos
2486 0263c60d Apollon Oikonomopoulos
_NETWORK_STATS_FIELDS = {
2487 0263c60d Apollon Oikonomopoulos
  "free_count": ("FreeCount", QFT_NUMBER, 0, "How many addresses are free"),
2488 0263c60d Apollon Oikonomopoulos
  "reserved_count": ("ReservedCount", QFT_NUMBER, 0, "How many addresses are reserved"),
2489 0263c60d Apollon Oikonomopoulos
  "map": ("Map", QFT_TEXT, 0, "The actual mapping"),
2490 0263c60d Apollon Oikonomopoulos
  "external_reservations": ("ExternalReservations", QFT_TEXT, 0, "The external reservations"),
2491 0263c60d Apollon Oikonomopoulos
  }
2492 0263c60d Apollon Oikonomopoulos
2493 0263c60d Apollon Oikonomopoulos
2494 0263c60d Apollon Oikonomopoulos
def _GetNetworkStatsField(field, kind, ctx, net):
2495 0263c60d Apollon Oikonomopoulos
  """Gets the value of a "stats" field from L{NetworkQueryData}.
2496 0263c60d Apollon Oikonomopoulos

2497 0263c60d Apollon Oikonomopoulos
  @param field: Field name
2498 0263c60d Apollon Oikonomopoulos
  @param kind: Data kind, one of L{constants.QFT_ALL}
2499 0263c60d Apollon Oikonomopoulos
  @type ctx: L{NetworkQueryData}
2500 0263c60d Apollon Oikonomopoulos

2501 0263c60d Apollon Oikonomopoulos
  """
2502 0263c60d Apollon Oikonomopoulos
2503 0263c60d Apollon Oikonomopoulos
  try:
2504 0263c60d Apollon Oikonomopoulos
    value = ctx.curstats[field]
2505 0263c60d Apollon Oikonomopoulos
  except KeyError:
2506 0263c60d Apollon Oikonomopoulos
    return _FS_UNAVAIL
2507 0263c60d Apollon Oikonomopoulos
2508 0263c60d Apollon Oikonomopoulos
  if kind == QFT_TEXT:
2509 0263c60d Apollon Oikonomopoulos
    return value
2510 0263c60d Apollon Oikonomopoulos
2511 0263c60d Apollon Oikonomopoulos
  assert kind in (QFT_NUMBER, QFT_UNIT)
2512 0263c60d Apollon Oikonomopoulos
2513 0263c60d Apollon Oikonomopoulos
  # Try to convert into number
2514 0263c60d Apollon Oikonomopoulos
  try:
2515 0263c60d Apollon Oikonomopoulos
    return int(value)
2516 0263c60d Apollon Oikonomopoulos
  except (ValueError, TypeError):
2517 0263c60d Apollon Oikonomopoulos
    logging.exception("Failed to convert network field '%s' (value %r) to int",
2518 0263c60d Apollon Oikonomopoulos
                      value, field)
2519 0263c60d Apollon Oikonomopoulos
    return _FS_UNAVAIL
2520 0263c60d Apollon Oikonomopoulos
2521 0263c60d Apollon Oikonomopoulos
2522 0263c60d Apollon Oikonomopoulos
def _BuildNetworkFields():
2523 0263c60d Apollon Oikonomopoulos
  """Builds list of fields for network queries.
2524 0263c60d Apollon Oikonomopoulos

2525 0263c60d Apollon Oikonomopoulos
  """
2526 0263c60d Apollon Oikonomopoulos
  # Add simple fields
2527 0263c60d Apollon Oikonomopoulos
  fields = [
2528 0263c60d Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc),
2529 0263c60d Apollon Oikonomopoulos
     NETQ_CONFIG, 0, _GetItemAttr(name))
2530 0263c60d Apollon Oikonomopoulos
    for (name, (title, kind, flags, doc)) in _NETWORK_SIMPLE_FIELDS.items()]
2531 0263c60d Apollon Oikonomopoulos
2532 0263c60d Apollon Oikonomopoulos
  def _GetLength(getter):
2533 0263c60d Apollon Oikonomopoulos
    return lambda ctx, network: len(getter(ctx)[network.uuid])
2534 0263c60d Apollon Oikonomopoulos
2535 0263c60d Apollon Oikonomopoulos
  def _GetSortedList(getter):
2536 0263c60d Apollon Oikonomopoulos
    return lambda ctx, network: utils.NiceSort(getter(ctx)[network.uuid])
2537 0263c60d Apollon Oikonomopoulos
2538 0263c60d Apollon Oikonomopoulos
  network_to_groups = operator.attrgetter("network_to_groups")
2539 0263c60d Apollon Oikonomopoulos
  network_to_instances = operator.attrgetter("network_to_instances")
2540 0263c60d Apollon Oikonomopoulos
2541 0263c60d Apollon Oikonomopoulos
  # Add fields for node groups
2542 0263c60d Apollon Oikonomopoulos
  fields.extend([
2543 0263c60d Apollon Oikonomopoulos
    (_MakeField("group_cnt", "NodeGroups", QFT_NUMBER, "Number of nodegroups"),
2544 0263c60d Apollon Oikonomopoulos
     NETQ_GROUP, 0, _GetLength(network_to_groups)),
2545 0263c60d Apollon Oikonomopoulos
        (_MakeField("group_list", "GroupList", QFT_OTHER, "List of nodegroups"),
2546 0263c60d Apollon Oikonomopoulos
     NETQ_GROUP, 0, _GetSortedList(network_to_groups)),
2547 0263c60d Apollon Oikonomopoulos
    ])
2548 0263c60d Apollon Oikonomopoulos
2549 0263c60d Apollon Oikonomopoulos
  # Add fields for instances
2550 0263c60d Apollon Oikonomopoulos
  fields.extend([
2551 0263c60d Apollon Oikonomopoulos
    (_MakeField("inst_cnt", "Instances", QFT_NUMBER, "Number of instances"),
2552 0263c60d Apollon Oikonomopoulos
     NETQ_INST, 0, _GetLength(network_to_instances)),
2553 0263c60d Apollon Oikonomopoulos
    (_MakeField("inst_list", "InstanceList", QFT_OTHER, "List of instances"),
2554 0263c60d Apollon Oikonomopoulos
     NETQ_INST, 0, _GetSortedList(network_to_instances)),
2555 0263c60d Apollon Oikonomopoulos
    ])
2556 0263c60d Apollon Oikonomopoulos
2557 0263c60d Apollon Oikonomopoulos
  # Add fields for usage statistics
2558 0263c60d Apollon Oikonomopoulos
  fields.extend([
2559 0263c60d Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc), NETQ_STATS, 0,
2560 0263c60d Apollon Oikonomopoulos
    compat.partial(_GetNetworkStatsField, name, kind))
2561 0263c60d Apollon Oikonomopoulos
    for (name, (title, kind, flags, doc)) in _NETWORK_STATS_FIELDS.items()
2562 0263c60d Apollon Oikonomopoulos
    ])
2563 0263c60d Apollon Oikonomopoulos
2564 0263c60d Apollon Oikonomopoulos
  return _PrepareFieldList(fields, [])
2565 0263c60d Apollon Oikonomopoulos
2566 dff5f600 Michael Hanselmann
#: Fields for cluster information
2567 dff5f600 Michael Hanselmann
CLUSTER_FIELDS = _BuildClusterFields()
2568 dff5f600 Michael Hanselmann
2569 8235fe04 Michael Hanselmann
#: Fields available for node queries
2570 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2571 1c8addc6 Michael Hanselmann
2572 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2573 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2574 24d16f76 Michael Hanselmann
2575 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2576 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2577 e571ee44 Adeodato Simo
2578 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2579 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2580 8e21cfc0 Adeodato Simo
2581 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2582 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2583 be3a4b14 Michael Hanselmann
2584 9665bb3a Michael Hanselmann
#: Fields available for job queries
2585 9665bb3a Michael Hanselmann
JOB_FIELDS = _BuildJobFields()
2586 9665bb3a Michael Hanselmann
2587 0fdf247d Michael Hanselmann
#: Fields available for exports
2588 0fdf247d Michael Hanselmann
EXPORT_FIELDS = _BuildExportFields()
2589 0fdf247d Michael Hanselmann
2590 0263c60d Apollon Oikonomopoulos
#: Fields available for network queries
2591 0263c60d Apollon Oikonomopoulos
NETWORK_FIELDS = _BuildNetworkFields()
2592 0263c60d Apollon Oikonomopoulos
2593 95eb4188 Michael Hanselmann
#: All available resources
2594 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2595 dff5f600 Michael Hanselmann
  constants.QR_CLUSTER: CLUSTER_FIELDS,
2596 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2597 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2598 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2599 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2600 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2601 9665bb3a Michael Hanselmann
  constants.QR_JOB: JOB_FIELDS,
2602 0fdf247d Michael Hanselmann
  constants.QR_EXPORT: EXPORT_FIELDS,
2603 0263c60d Apollon Oikonomopoulos
  constants.QR_NETWORK: NETWORK_FIELDS,
2604 95eb4188 Michael Hanselmann
  }
2605 95eb4188 Michael Hanselmann
2606 e571ee44 Adeodato Simo
#: All available field lists
2607 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()