Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 178ad717

History | View | Annotate | Download (86.3 kB)

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

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

172 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
173 4ca96421 Michael Hanselmann

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

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

199 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
200 4ca96421 Michael Hanselmann

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

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

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

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

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

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

232 fb0be379 Michael Hanselmann
    @type namefield: string
233 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
234 fb0be379 Michael Hanselmann

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

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

254 fb0be379 Michael Hanselmann
    @rtype: list
255 fb0be379 Michael Hanselmann

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

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

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

278 fb0be379 Michael Hanselmann
    @type op: string
279 fb0be379 Michael Hanselmann
    @param op: Operator
280 fb0be379 Michael Hanselmann

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

288 fb0be379 Michael Hanselmann
    @type op: string
289 fb0be379 Michael Hanselmann
    @param op: Operator
290 fb0be379 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

651 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
652 fb0be379 Michael Hanselmann

653 fb0be379 Michael Hanselmann
  @rtype: callable
654 fb0be379 Michael Hanselmann

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

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

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

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

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

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

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

717 4ca96421 Michael Hanselmann
    @rtype: frozenset
718 4ca96421 Michael Hanselmann

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

727 4ca96421 Michael Hanselmann
    Includes unknown fields.
728 4ca96421 Michael Hanselmann

729 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
730 4ca96421 Michael Hanselmann

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

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

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

782 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
783 4ca96421 Michael Hanselmann

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

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

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

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

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

853 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
854 4ca96421 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

974 8235fe04 Michael Hanselmann
  @param attr: Attribute name
975 8235fe04 Michael Hanselmann

976 8235fe04 Michael Hanselmann
  """
977 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
978 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
979 8235fe04 Michael Hanselmann
980 8235fe04 Michael Hanselmann
981 40b118d3 Iustin Pop
def _GetItemMaybeAttr(attr):
982 40b118d3 Iustin Pop
  """Returns a field function to return a not-None attribute of the item.
983 40b118d3 Iustin Pop

984 40b118d3 Iustin Pop
  If the value is None, then C{_FS_UNAVAIL} will be returned instead.
985 40b118d3 Iustin Pop

986 40b118d3 Iustin Pop
  @param attr: Attribute name
987 40b118d3 Iustin Pop

988 40b118d3 Iustin Pop
  """
989 40b118d3 Iustin Pop
  def _helper(_, obj):
990 40b118d3 Iustin Pop
    val = getattr(obj, attr)
991 40b118d3 Iustin Pop
    if val is None:
992 40b118d3 Iustin Pop
      return _FS_UNAVAIL
993 40b118d3 Iustin Pop
    else:
994 40b118d3 Iustin Pop
      return val
995 40b118d3 Iustin Pop
  return _helper
996 40b118d3 Iustin Pop
997 40b118d3 Iustin Pop
998 8930b0f0 Iustin Pop
def _GetNDParam(name):
999 8930b0f0 Iustin Pop
  """Return a field function to return an ND parameter out of the context.
1000 8930b0f0 Iustin Pop

1001 8930b0f0 Iustin Pop
  """
1002 8930b0f0 Iustin Pop
  def _helper(ctx, _):
1003 8930b0f0 Iustin Pop
    if ctx.ndparams is None:
1004 8930b0f0 Iustin Pop
      return _FS_UNAVAIL
1005 8930b0f0 Iustin Pop
    else:
1006 8930b0f0 Iustin Pop
      return ctx.ndparams.get(name, None)
1007 8930b0f0 Iustin Pop
  return _helper
1008 8930b0f0 Iustin Pop
1009 8930b0f0 Iustin Pop
1010 8930b0f0 Iustin Pop
def _BuildNDFields(is_group):
1011 8930b0f0 Iustin Pop
  """Builds all the ndparam fields.
1012 8930b0f0 Iustin Pop

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

1015 8930b0f0 Iustin Pop
  """
1016 8930b0f0 Iustin Pop
  if is_group:
1017 8930b0f0 Iustin Pop
    field_kind = GQ_CONFIG
1018 8930b0f0 Iustin Pop
  else:
1019 8930b0f0 Iustin Pop
    field_kind = NQ_GROUP
1020 a6c7e2a2 Iustin Pop
  return [(_MakeField("ndp/%s" % name,
1021 a6c7e2a2 Iustin Pop
                      constants.NDS_PARAMETER_TITLES.get(name,
1022 a6c7e2a2 Iustin Pop
                                                         "ndp/%s" % name),
1023 8930b0f0 Iustin Pop
                      _VTToQFT[kind], "The \"%s\" node parameter" % name),
1024 8930b0f0 Iustin Pop
           field_kind, 0, _GetNDParam(name))
1025 8930b0f0 Iustin Pop
          for name, kind in constants.NDS_PARAMETER_TYPES.items()]
1026 8930b0f0 Iustin Pop
1027 8930b0f0 Iustin Pop
1028 425e5bf0 Michael Hanselmann
def _ConvWrapInner(convert, fn, ctx, item):
1029 425e5bf0 Michael Hanselmann
  """Wrapper for converting values.
1030 425e5bf0 Michael Hanselmann

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

1034 425e5bf0 Michael Hanselmann
  """
1035 425e5bf0 Michael Hanselmann
  value = fn(ctx, item)
1036 425e5bf0 Michael Hanselmann
1037 425e5bf0 Michael Hanselmann
  # Is the value an abnormal status?
1038 425e5bf0 Michael Hanselmann
  if compat.any(value is fs for fs in _FS_ALL):
1039 425e5bf0 Michael Hanselmann
    # Return right away
1040 425e5bf0 Michael Hanselmann
    return value
1041 425e5bf0 Michael Hanselmann
1042 425e5bf0 Michael Hanselmann
  # TODO: Should conversion function also receive context, item or both?
1043 425e5bf0 Michael Hanselmann
  return convert(value)
1044 425e5bf0 Michael Hanselmann
1045 425e5bf0 Michael Hanselmann
1046 425e5bf0 Michael Hanselmann
def _ConvWrap(convert, fn):
1047 425e5bf0 Michael Hanselmann
  """Convenience wrapper for L{_ConvWrapInner}.
1048 425e5bf0 Michael Hanselmann

1049 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1050 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1051 425e5bf0 Michael Hanselmann

1052 425e5bf0 Michael Hanselmann
  """
1053 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
1054 425e5bf0 Michael Hanselmann
1055 425e5bf0 Michael Hanselmann
1056 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
1057 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
1058 145bea54 Michael Hanselmann

1059 145bea54 Michael Hanselmann
  @type getter: callable
1060 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1061 145bea54 Michael Hanselmann

1062 145bea54 Michael Hanselmann
  """
1063 145bea54 Michael Hanselmann
  def fn(_, item):
1064 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1065 145bea54 Michael Hanselmann

1066 145bea54 Michael Hanselmann
    """
1067 145bea54 Michael Hanselmann
    timestamp = getter(item)
1068 145bea54 Michael Hanselmann
    if timestamp is None:
1069 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
1070 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1071 145bea54 Michael Hanselmann
    else:
1072 e2d188cc Iustin Pop
      return timestamp
1073 145bea54 Michael Hanselmann
1074 145bea54 Michael Hanselmann
  return fn
1075 145bea54 Michael Hanselmann
1076 145bea54 Michael Hanselmann
1077 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
1078 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
1079 145bea54 Michael Hanselmann

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

1082 145bea54 Michael Hanselmann
  """
1083 145bea54 Michael Hanselmann
  return [
1084 79b2ca83 Michael Hanselmann
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP, "Creation timestamp"),
1085 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("ctime"))),
1086 79b2ca83 Michael Hanselmann
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP, "Modification timestamp"),
1087 111bf531 Michael Hanselmann
     datatype, 0, _GetItemTimestamp(operator.attrgetter("mtime"))),
1088 145bea54 Michael Hanselmann
    ]
1089 145bea54 Michael Hanselmann
1090 145bea54 Michael Hanselmann
1091 8235fe04 Michael Hanselmann
class NodeQueryData:
1092 8235fe04 Michael Hanselmann
  """Data container for node data queries.
1093 8235fe04 Michael Hanselmann

1094 8235fe04 Michael Hanselmann
  """
1095 1c3231aa Thomas Thrainer
  def __init__(self, nodes, live_data, master_uuid, node_to_primary,
1096 da4a52a3 Thomas Thrainer
               node_to_secondary, inst_uuid_to_inst_name, groups, oob_support,
1097 da4a52a3 Thomas Thrainer
               cluster):
1098 8235fe04 Michael Hanselmann
    """Initializes this class.
1099 8235fe04 Michael Hanselmann

1100 8235fe04 Michael Hanselmann
    """
1101 8235fe04 Michael Hanselmann
    self.nodes = nodes
1102 8235fe04 Michael Hanselmann
    self.live_data = live_data
1103 1c3231aa Thomas Thrainer
    self.master_uuid = master_uuid
1104 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
1105 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
1106 da4a52a3 Thomas Thrainer
    self.inst_uuid_to_inst_name = inst_uuid_to_inst_name
1107 8235fe04 Michael Hanselmann
    self.groups = groups
1108 52b5d286 René Nussbaumer
    self.oob_support = oob_support
1109 8572f1fe René Nussbaumer
    self.cluster = cluster
1110 8235fe04 Michael Hanselmann
1111 8235fe04 Michael Hanselmann
    # Used for individual rows
1112 8235fe04 Michael Hanselmann
    self.curlive_data = None
1113 8930b0f0 Iustin Pop
    self.ndparams = None
1114 8235fe04 Michael Hanselmann
1115 8235fe04 Michael Hanselmann
  def __iter__(self):
1116 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
1117 8235fe04 Michael Hanselmann

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

1121 8235fe04 Michael Hanselmann
    """
1122 8235fe04 Michael Hanselmann
    for node in self.nodes:
1123 8930b0f0 Iustin Pop
      group = self.groups.get(node.group, None)
1124 8930b0f0 Iustin Pop
      if group is None:
1125 8930b0f0 Iustin Pop
        self.ndparams = None
1126 8930b0f0 Iustin Pop
      else:
1127 8930b0f0 Iustin Pop
        self.ndparams = self.cluster.FillND(node, group)
1128 8235fe04 Michael Hanselmann
      if self.live_data:
1129 1c3231aa Thomas Thrainer
        self.curlive_data = self.live_data.get(node.uuid, None)
1130 8235fe04 Michael Hanselmann
      else:
1131 8235fe04 Michael Hanselmann
        self.curlive_data = None
1132 8235fe04 Michael Hanselmann
      yield node
1133 8235fe04 Michael Hanselmann
1134 8235fe04 Michael Hanselmann
1135 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
1136 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
1137 111bf531 Michael Hanselmann
  "drained": ("Drained", QFT_BOOL, 0, "Whether node is drained"),
1138 111bf531 Michael Hanselmann
  "master_candidate": ("MasterC", QFT_BOOL, 0,
1139 79b2ca83 Michael Hanselmann
                       "Whether node is a master candidate"),
1140 111bf531 Michael Hanselmann
  "master_capable": ("MasterCapable", QFT_BOOL, 0,
1141 79b2ca83 Michael Hanselmann
                     "Whether node can become a master candidate"),
1142 111bf531 Michael Hanselmann
  "name": ("Node", QFT_TEXT, QFF_HOSTNAME, "Node name"),
1143 111bf531 Michael Hanselmann
  "offline": ("Offline", QFT_BOOL, 0, "Whether node is marked offline"),
1144 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Node"),
1145 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Node UUID"),
1146 111bf531 Michael Hanselmann
  "vm_capable": ("VMCapable", QFT_BOOL, 0, "Whether node can host instances"),
1147 8235fe04 Michael Hanselmann
  }
1148 8235fe04 Michael Hanselmann
1149 8235fe04 Michael Hanselmann
1150 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
1151 effab4ca Iustin Pop
# Note that none of these are available for non-vm_capable nodes
1152 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
1153 79b2ca83 Michael Hanselmann
  "bootid": ("BootID", QFT_TEXT, "bootid",
1154 79b2ca83 Michael Hanselmann
             "Random UUID renewed for each system reboot, can be used"
1155 79b2ca83 Michael Hanselmann
             " for detecting reboots by tracking changes"),
1156 79b2ca83 Michael Hanselmann
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes",
1157 79b2ca83 Michael Hanselmann
             "Number of NUMA domains on node (if exported by hypervisor)"),
1158 f43c898d Bernardo Dal Seno
  "cnos": ("CNOs", QFT_NUMBER, "cpu_dom0",
1159 f43c898d Bernardo Dal Seno
            "Number of logical processors used by the node OS (dom0 for Xen)"),
1160 79b2ca83 Michael Hanselmann
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets",
1161 79b2ca83 Michael Hanselmann
               "Number of physical CPU sockets (if exported by hypervisor)"),
1162 79b2ca83 Michael Hanselmann
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total", "Number of logical processors"),
1163 32389d91 Helga Velroyen
  "dfree": ("DFree", QFT_UNIT, "storage_free",
1164 32389d91 Helga Velroyen
            "Available storage space in storage unit"),
1165 32389d91 Helga Velroyen
  "dtotal": ("DTotal", QFT_UNIT, "storage_size",
1166 32389d91 Helga Velroyen
             "Total storage space in storage unit used for instance disk"
1167 79b2ca83 Michael Hanselmann
             " allocation"),
1168 06fb92cf Bernardo Dal Seno
  "spfree": ("SpFree", QFT_NUMBER, "spindles_free",
1169 06fb92cf Bernardo Dal Seno
             "Available spindles in volume group (exclusive storage only)"),
1170 06fb92cf Bernardo Dal Seno
  "sptotal": ("SpTotal", QFT_NUMBER, "spindles_total",
1171 06fb92cf Bernardo Dal Seno
              "Total spindles in volume group (exclusive storage only)"),
1172 79b2ca83 Michael Hanselmann
  "mfree": ("MFree", QFT_UNIT, "memory_free",
1173 79b2ca83 Michael Hanselmann
            "Memory available for instance allocations"),
1174 79b2ca83 Michael Hanselmann
  "mnode": ("MNode", QFT_UNIT, "memory_dom0",
1175 79b2ca83 Michael Hanselmann
            "Amount of memory used by node (dom0 for Xen)"),
1176 79b2ca83 Michael Hanselmann
  "mtotal": ("MTotal", QFT_UNIT, "memory_total",
1177 79b2ca83 Michael Hanselmann
             "Total amount of memory of physical machine"),
1178 8235fe04 Michael Hanselmann
  }
1179 8235fe04 Michael Hanselmann
1180 8235fe04 Michael Hanselmann
1181 8572f1fe René Nussbaumer
def _GetGroup(cb):
1182 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
1183 8572f1fe René Nussbaumer

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

1186 8572f1fe René Nussbaumer
  """
1187 8572f1fe René Nussbaumer
  def fn(ctx, node):
1188 8572f1fe René Nussbaumer
    """Get group data for a node.
1189 8572f1fe René Nussbaumer

1190 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1191 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1192 8572f1fe René Nussbaumer
    @param inst: Node object
1193 8572f1fe René Nussbaumer

1194 8572f1fe René Nussbaumer
    """
1195 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
1196 8572f1fe René Nussbaumer
    if ng is None:
1197 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
1198 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1199 8572f1fe René Nussbaumer
1200 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
1201 8572f1fe René Nussbaumer
1202 8572f1fe René Nussbaumer
  return fn
1203 8572f1fe René Nussbaumer
1204 8572f1fe René Nussbaumer
1205 b459a848 Andrea Spadaccini
def _GetNodeGroup(ctx, node, ng): # pylint: disable=W0613
1206 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
1207 8235fe04 Michael Hanselmann

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

1214 8235fe04 Michael Hanselmann
  """
1215 e2d188cc Iustin Pop
  return ng.name
1216 8235fe04 Michael Hanselmann
1217 8235fe04 Michael Hanselmann
1218 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1219 52b5d286 René Nussbaumer
  """Returns the node powered state
1220 52b5d286 René Nussbaumer

1221 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1222 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1223 52b5d286 René Nussbaumer
  @param node: Node object
1224 52b5d286 René Nussbaumer

1225 52b5d286 René Nussbaumer
  """
1226 1c3231aa Thomas Thrainer
  if ctx.oob_support[node.uuid]:
1227 e2d188cc Iustin Pop
    return node.powered
1228 52b5d286 René Nussbaumer
1229 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1230 52b5d286 René Nussbaumer
1231 52b5d286 René Nussbaumer
1232 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1233 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1234 8572f1fe René Nussbaumer

1235 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1236 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1237 8572f1fe René Nussbaumer
  @param node: Node object
1238 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1239 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1240 8572f1fe René Nussbaumer

1241 8572f1fe René Nussbaumer
  """
1242 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
1243 8572f1fe René Nussbaumer
1244 8572f1fe René Nussbaumer
1245 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
1246 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
1247 8235fe04 Michael Hanselmann

1248 8235fe04 Michael Hanselmann
  @param field: Live field name
1249 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1250 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1251 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1252 a6070ef7 Michael Hanselmann
  @param node: Node object
1253 8235fe04 Michael Hanselmann

1254 8235fe04 Michael Hanselmann
  """
1255 a6070ef7 Michael Hanselmann
  if node.offline:
1256 e2d188cc Iustin Pop
    return _FS_OFFLINE
1257 a6070ef7 Michael Hanselmann
1258 effab4ca Iustin Pop
  if not node.vm_capable:
1259 effab4ca Iustin Pop
    return _FS_UNAVAIL
1260 effab4ca Iustin Pop
1261 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
1262 e2d188cc Iustin Pop
    return _FS_NODATA
1263 8235fe04 Michael Hanselmann
1264 b4600d4f Michael Hanselmann
  return _GetStatsField(field, kind, ctx.curlive_data)
1265 b4600d4f Michael Hanselmann
1266 b4600d4f Michael Hanselmann
1267 b4600d4f Michael Hanselmann
def _GetStatsField(field, kind, data):
1268 b4600d4f Michael Hanselmann
  """Gets a value from live statistics.
1269 b4600d4f Michael Hanselmann

1270 b4600d4f Michael Hanselmann
  If the value is not found, L{_FS_UNAVAIL} is returned. If the field kind is
1271 b4600d4f Michael Hanselmann
  numeric a conversion to integer is attempted. If that fails, L{_FS_UNAVAIL}
1272 b4600d4f Michael Hanselmann
  is returned.
1273 b4600d4f Michael Hanselmann

1274 b4600d4f Michael Hanselmann
  @param field: Live field name
1275 b4600d4f Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1276 b4600d4f Michael Hanselmann
  @type data: dict
1277 b4600d4f Michael Hanselmann
  @param data: Statistics
1278 b4600d4f Michael Hanselmann

1279 b4600d4f Michael Hanselmann
  """
1280 8235fe04 Michael Hanselmann
  try:
1281 b4600d4f Michael Hanselmann
    value = data[field]
1282 8235fe04 Michael Hanselmann
  except KeyError:
1283 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1284 8235fe04 Michael Hanselmann
1285 82599b3e Iustin Pop
  if kind == QFT_TEXT:
1286 e2d188cc Iustin Pop
    return value
1287 8235fe04 Michael Hanselmann
1288 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
1289 8235fe04 Michael Hanselmann
1290 8235fe04 Michael Hanselmann
  # Try to convert into number
1291 8235fe04 Michael Hanselmann
  try:
1292 e2d188cc Iustin Pop
    return int(value)
1293 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
1294 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
1295 b4600d4f Michael Hanselmann
                      field, value)
1296 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1297 8235fe04 Michael Hanselmann
1298 8235fe04 Michael Hanselmann
1299 54ac87c0 Michael Hanselmann
def _GetNodeHvState(_, node):
1300 54ac87c0 Michael Hanselmann
  """Converts node's hypervisor state for query result.
1301 54ac87c0 Michael Hanselmann

1302 54ac87c0 Michael Hanselmann
  """
1303 54ac87c0 Michael Hanselmann
  hv_state = node.hv_state
1304 54ac87c0 Michael Hanselmann
1305 54ac87c0 Michael Hanselmann
  if hv_state is None:
1306 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1307 54ac87c0 Michael Hanselmann
1308 54ac87c0 Michael Hanselmann
  return dict((name, value.ToDict()) for (name, value) in hv_state.items())
1309 54ac87c0 Michael Hanselmann
1310 54ac87c0 Michael Hanselmann
1311 54ac87c0 Michael Hanselmann
def _GetNodeDiskState(_, node):
1312 54ac87c0 Michael Hanselmann
  """Converts node's disk state for query result.
1313 54ac87c0 Michael Hanselmann

1314 54ac87c0 Michael Hanselmann
  """
1315 54ac87c0 Michael Hanselmann
  disk_state = node.disk_state
1316 54ac87c0 Michael Hanselmann
1317 54ac87c0 Michael Hanselmann
  if disk_state is None:
1318 54ac87c0 Michael Hanselmann
    return _FS_UNAVAIL
1319 54ac87c0 Michael Hanselmann
1320 54ac87c0 Michael Hanselmann
  return dict((disk_kind, dict((name, value.ToDict())
1321 54ac87c0 Michael Hanselmann
                               for (name, value) in kind_state.items()))
1322 54ac87c0 Michael Hanselmann
              for (disk_kind, kind_state) in disk_state.items())
1323 54ac87c0 Michael Hanselmann
1324 54ac87c0 Michael Hanselmann
1325 8235fe04 Michael Hanselmann
def _BuildNodeFields():
1326 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
1327 8235fe04 Michael Hanselmann

1328 8235fe04 Michael Hanselmann
  """
1329 8235fe04 Michael Hanselmann
  fields = [
1330 79b2ca83 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", QFT_TEXT, "Primary IP address"),
1331 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("primary_ip")),
1332 79b2ca83 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", QFT_TEXT, "Secondary IP address"),
1333 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("secondary_ip")),
1334 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), NQ_CONFIG, 0,
1335 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
1336 79b2ca83 Michael Hanselmann
    (_MakeField("master", "IsMaster", QFT_BOOL, "Whether node is master"),
1337 1c3231aa Thomas Thrainer
     NQ_CONFIG, 0, lambda ctx, node: node.uuid == ctx.master_uuid),
1338 111bf531 Michael Hanselmann
    (_MakeField("group", "Group", QFT_TEXT, "Node group"), NQ_GROUP, 0,
1339 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
1340 79b2ca83 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT, "UUID of node group"),
1341 111bf531 Michael Hanselmann
     NQ_CONFIG, 0, _GetItemAttr("group")),
1342 79b2ca83 Michael Hanselmann
    (_MakeField("powered", "Powered", QFT_BOOL,
1343 79b2ca83 Michael Hanselmann
                "Whether node is thought to be powered on"),
1344 111bf531 Michael Hanselmann
     NQ_OOB, 0, _GetNodePower),
1345 79b2ca83 Michael Hanselmann
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER,
1346 79b2ca83 Michael Hanselmann
                "Merged node parameters"),
1347 111bf531 Michael Hanselmann
     NQ_GROUP, 0, _GetGroup(_GetNdParams)),
1348 79b2ca83 Michael Hanselmann
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER,
1349 79b2ca83 Michael Hanselmann
                "Custom node parameters"),
1350 111bf531 Michael Hanselmann
      NQ_GROUP, 0, _GetItemAttr("ndparams")),
1351 54ac87c0 Michael Hanselmann
    (_MakeField("hv_state", "HypervisorState", QFT_OTHER, "Hypervisor state"),
1352 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeHvState),
1353 54ac87c0 Michael Hanselmann
    (_MakeField("disk_state", "DiskState", QFT_OTHER, "Disk state"),
1354 54ac87c0 Michael Hanselmann
     NQ_CONFIG, 0, _GetNodeDiskState),
1355 8235fe04 Michael Hanselmann
    ]
1356 8235fe04 Michael Hanselmann
1357 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(False))
1358 8930b0f0 Iustin Pop
1359 79b2ca83 Michael Hanselmann
  # Node role
1360 79b2ca83 Michael Hanselmann
  role_values = (constants.NR_MASTER, constants.NR_MCANDIDATE,
1361 79b2ca83 Michael Hanselmann
                 constants.NR_REGULAR, constants.NR_DRAINED,
1362 79b2ca83 Michael Hanselmann
                 constants.NR_OFFLINE)
1363 79b2ca83 Michael Hanselmann
  role_doc = ("Node role; \"%s\" for master, \"%s\" for master candidate,"
1364 a9310b2f Iustin Pop
              " \"%s\" for regular, \"%s\" for drained, \"%s\" for offline" %
1365 79b2ca83 Michael Hanselmann
              role_values)
1366 111bf531 Michael Hanselmann
  fields.append((_MakeField("role", "Role", QFT_TEXT, role_doc), NQ_CONFIG, 0,
1367 1c3231aa Thomas Thrainer
                 lambda ctx, node: _GetNodeRole(node, ctx.master_uuid)))
1368 79b2ca83 Michael Hanselmann
  assert set(role_values) == constants.NR_ALL
1369 79b2ca83 Michael Hanselmann
1370 8235fe04 Michael Hanselmann
  def _GetLength(getter):
1371 1c3231aa Thomas Thrainer
    return lambda ctx, node: len(getter(ctx)[node.uuid])
1372 8235fe04 Michael Hanselmann
1373 8235fe04 Michael Hanselmann
  def _GetList(getter):
1374 da4a52a3 Thomas Thrainer
    return lambda ctx, node: utils.NiceSort(
1375 da4a52a3 Thomas Thrainer
                               [ctx.inst_uuid_to_inst_name[uuid]
1376 da4a52a3 Thomas Thrainer
                                for uuid in getter(ctx)[node.uuid]])
1377 8235fe04 Michael Hanselmann
1378 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
1379 79b2ca83 Michael Hanselmann
  for prefix, titleprefix, docword, getter in \
1380 79b2ca83 Michael Hanselmann
      [("p", "Pri", "primary", operator.attrgetter("node_to_primary")),
1381 79b2ca83 Michael Hanselmann
       ("s", "Sec", "secondary", operator.attrgetter("node_to_secondary"))]:
1382 111bf531 Michael Hanselmann
    # TODO: Allow filterting by hostname in list
1383 8235fe04 Michael Hanselmann
    fields.extend([
1384 79b2ca83 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER,
1385 79b2ca83 Michael Hanselmann
                  "Number of instances with this node as %s" % docword),
1386 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetLength(getter)),
1387 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
1388 79b2ca83 Michael Hanselmann
                  QFT_OTHER,
1389 79b2ca83 Michael Hanselmann
                  "List of instances with this node as %s" % docword),
1390 111bf531 Michael Hanselmann
       NQ_INST, 0, _GetList(getter)),
1391 8235fe04 Michael Hanselmann
      ])
1392 8235fe04 Michael Hanselmann
1393 8235fe04 Michael Hanselmann
  # Add simple fields
1394 111bf531 Michael Hanselmann
  fields.extend([
1395 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
1396 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()])
1397 8235fe04 Michael Hanselmann
1398 8235fe04 Michael Hanselmann
  # Add fields requiring live data
1399 8235fe04 Michael Hanselmann
  fields.extend([
1400 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), NQ_LIVE, 0,
1401 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
1402 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()])
1403 8235fe04 Michael Hanselmann
1404 145bea54 Michael Hanselmann
  # Add timestamps
1405 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
1406 145bea54 Michael Hanselmann
1407 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1408 8235fe04 Michael Hanselmann
1409 8235fe04 Michael Hanselmann
1410 1c8addc6 Michael Hanselmann
class InstanceQueryData:
1411 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
1412 1c8addc6 Michael Hanselmann

1413 1c8addc6 Michael Hanselmann
  """
1414 1c3231aa Thomas Thrainer
  def __init__(self, instances, cluster, disk_usage, offline_node_uuids,
1415 1c3231aa Thomas Thrainer
               bad_node_uuids, live_data, wrongnode_inst, console, nodes,
1416 1c3231aa Thomas Thrainer
               groups, networks):
1417 1c8addc6 Michael Hanselmann
    """Initializes this class.
1418 1c8addc6 Michael Hanselmann

1419 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
1420 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
1421 da4a52a3 Thomas Thrainer
    @type disk_usage: dict; instance UUID as key
1422 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
1423 1c3231aa Thomas Thrainer
    @type offline_node_uuids: list of strings
1424 1c3231aa Thomas Thrainer
    @param offline_node_uuids: List of offline nodes
1425 1c3231aa Thomas Thrainer
    @type bad_node_uuids: list of strings
1426 1c3231aa Thomas Thrainer
    @param bad_node_uuids: List of faulty nodes
1427 da4a52a3 Thomas Thrainer
    @type live_data: dict; instance UUID as key
1428 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
1429 e431074f René Nussbaumer
    @type wrongnode_inst: set
1430 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
1431 da4a52a3 Thomas Thrainer
    @type console: dict; instance UUID as key
1432 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
1433 1c3231aa Thomas Thrainer
    @type nodes: dict; node UUID as key
1434 fab9573b Michael Hanselmann
    @param nodes: Node objects
1435 f98e1175 Dimitris Aragiorgis
    @type networks: dict; net_uuid as key
1436 f98e1175 Dimitris Aragiorgis
    @param networks: Network objects
1437 1c8addc6 Michael Hanselmann

1438 1c8addc6 Michael Hanselmann
    """
1439 1c3231aa Thomas Thrainer
    assert len(set(bad_node_uuids) & set(offline_node_uuids)) == \
1440 1c3231aa Thomas Thrainer
           len(offline_node_uuids), \
1441 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
1442 1c3231aa Thomas Thrainer
    assert not (set(live_data.keys()) & set(bad_node_uuids)), \
1443 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
1444 1c8addc6 Michael Hanselmann
1445 1c8addc6 Michael Hanselmann
    self.instances = instances
1446 1c8addc6 Michael Hanselmann
    self.cluster = cluster
1447 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
1448 1c3231aa Thomas Thrainer
    self.offline_nodes = offline_node_uuids
1449 1c3231aa Thomas Thrainer
    self.bad_nodes = bad_node_uuids
1450 1c8addc6 Michael Hanselmann
    self.live_data = live_data
1451 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
1452 5d28cb6f Michael Hanselmann
    self.console = console
1453 fab9573b Michael Hanselmann
    self.nodes = nodes
1454 fab9573b Michael Hanselmann
    self.groups = groups
1455 f98e1175 Dimitris Aragiorgis
    self.networks = networks
1456 1c8addc6 Michael Hanselmann
1457 1c8addc6 Michael Hanselmann
    # Used for individual rows
1458 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
1459 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
1460 7c670076 Michael Hanselmann
    self.inst_osparams = None
1461 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
1462 1c8addc6 Michael Hanselmann
1463 1c8addc6 Michael Hanselmann
  def __iter__(self):
1464 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
1465 1c8addc6 Michael Hanselmann

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

1469 1c8addc6 Michael Hanselmann
    """
1470 1c8addc6 Michael Hanselmann
    for inst in self.instances:
1471 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
1472 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
1473 7c670076 Michael Hanselmann
      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
1474 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
1475 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
1476 1c8addc6 Michael Hanselmann
1477 1c8addc6 Michael Hanselmann
      yield inst
1478 1c8addc6 Michael Hanselmann
1479 1c8addc6 Michael Hanselmann
1480 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
1481 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
1482 1c8addc6 Michael Hanselmann

1483 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1484 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1485 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1486 1c8addc6 Michael Hanselmann

1487 1c8addc6 Michael Hanselmann
  """
1488 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
1489 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
1490 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1491 e2d188cc Iustin Pop
    return _FS_NODATA
1492 1c8addc6 Michael Hanselmann
  else:
1493 da4a52a3 Thomas Thrainer
    return bool(ctx.live_data.get(inst.uuid))
1494 1c8addc6 Michael Hanselmann
1495 1c8addc6 Michael Hanselmann
1496 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
1497 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
1498 1c8addc6 Michael Hanselmann

1499 1c8addc6 Michael Hanselmann
  @type name: string
1500 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1501 1c8addc6 Michael Hanselmann

1502 1c8addc6 Michael Hanselmann
  """
1503 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1504 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1505 1c8addc6 Michael Hanselmann

1506 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1507 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1508 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1509 1c8addc6 Michael Hanselmann

1510 1c8addc6 Michael Hanselmann
    """
1511 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1512 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1513 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1514 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1515 e2d188cc Iustin Pop
      return _FS_NODATA
1516 1c8addc6 Michael Hanselmann
1517 da4a52a3 Thomas Thrainer
    if inst.uuid in ctx.live_data:
1518 da4a52a3 Thomas Thrainer
      data = ctx.live_data[inst.uuid]
1519 1c8addc6 Michael Hanselmann
      if name in data:
1520 e2d188cc Iustin Pop
        return data[name]
1521 1c8addc6 Michael Hanselmann
1522 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1523 1c8addc6 Michael Hanselmann
1524 1c8addc6 Michael Hanselmann
  return fn
1525 1c8addc6 Michael Hanselmann
1526 1c8addc6 Michael Hanselmann
1527 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1528 1c8addc6 Michael Hanselmann
  """Get instance status.
1529 1c8addc6 Michael Hanselmann

1530 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1531 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1532 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1533 1c8addc6 Michael Hanselmann

1534 1c8addc6 Michael Hanselmann
  """
1535 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1536 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1537 1c8addc6 Michael Hanselmann
1538 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1539 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1540 1c8addc6 Michael Hanselmann
1541 9982754c Jose A. Lopes
  instance_live_data = ctx.live_data.get(inst.uuid)
1542 9982754c Jose A. Lopes
1543 9982754c Jose A. Lopes
  if bool(instance_live_data):
1544 9982754c Jose A. Lopes
    instance_state = instance_live_data["state"]
1545 9982754c Jose A. Lopes
1546 da4a52a3 Thomas Thrainer
    if inst.uuid in ctx.wrongnode_inst:
1547 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1548 1c8addc6 Michael Hanselmann
    else:
1549 9982754c Jose A. Lopes
      if hv_base.HvInstanceState.IsShutdown(instance_state):
1550 9982754c Jose A. Lopes
        if inst.admin_state == constants.ADMINST_UP:
1551 9982754c Jose A. Lopes
          return constants.INSTST_USERDOWN
1552 9982754c Jose A. Lopes
        else:
1553 9982754c Jose A. Lopes
          return constants.INSTST_ADMINDOWN
1554 9982754c Jose A. Lopes
      else:
1555 9982754c Jose A. Lopes
        if inst.admin_state == constants.ADMINST_UP:
1556 9982754c Jose A. Lopes
          return constants.INSTST_RUNNING
1557 9982754c Jose A. Lopes
        else:
1558 9982754c Jose A. Lopes
          return constants.INSTST_ERRORUP
1559 1c8addc6 Michael Hanselmann
1560 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1561 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1562 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1563 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1564 1c8addc6 Michael Hanselmann
1565 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1566 1c8addc6 Michael Hanselmann
1567 1c8addc6 Michael Hanselmann
1568 3fe22abd Christos Stavrakakis
def _GetInstDisk(index, cb):
1569 3fe22abd Christos Stavrakakis
  """Build function for calling another function with an instance Disk.
1570 1c8addc6 Michael Hanselmann

1571 1c8addc6 Michael Hanselmann
  @type index: int
1572 1c8addc6 Michael Hanselmann
  @param index: Disk index
1573 3fe22abd Christos Stavrakakis
  @type cb: callable
1574 3fe22abd Christos Stavrakakis
  @param cb: Callback
1575 1c8addc6 Michael Hanselmann

1576 1c8addc6 Michael Hanselmann
  """
1577 3fe22abd Christos Stavrakakis
  def fn(ctx, inst):
1578 3fe22abd Christos Stavrakakis
    """Call helper function with instance Disk.
1579 1c8addc6 Michael Hanselmann

1580 3fe22abd Christos Stavrakakis
    @type ctx: L{InstanceQueryData}
1581 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1582 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1583 1c8addc6 Michael Hanselmann

1584 1c8addc6 Michael Hanselmann
    """
1585 1c8addc6 Michael Hanselmann
    try:
1586 3fe22abd Christos Stavrakakis
      nic = inst.disks[index]
1587 1c8addc6 Michael Hanselmann
    except IndexError:
1588 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1589 1c8addc6 Michael Hanselmann
1590 3fe22abd Christos Stavrakakis
    return cb(ctx, index, nic)
1591 3fe22abd Christos Stavrakakis
1592 1c8addc6 Michael Hanselmann
  return fn
1593 1c8addc6 Michael Hanselmann
1594 1c8addc6 Michael Hanselmann
1595 3fe22abd Christos Stavrakakis
def _GetInstDiskSize(ctx, _, disk): # pylint: disable=W0613
1596 3fe22abd Christos Stavrakakis
  """Get a Disk's size.
1597 3fe22abd Christos Stavrakakis

1598 3fe22abd Christos Stavrakakis
  @type ctx: L{InstanceQueryData}
1599 3fe22abd Christos Stavrakakis
  @type disk: L{objects.Disk}
1600 3fe22abd Christos Stavrakakis
  @param disk: The Disk object
1601 3fe22abd Christos Stavrakakis

1602 3fe22abd Christos Stavrakakis
  """
1603 3fe22abd Christos Stavrakakis
  if disk.size is None:
1604 3fe22abd Christos Stavrakakis
    return _FS_UNAVAIL
1605 3fe22abd Christos Stavrakakis
  else:
1606 3fe22abd Christos Stavrakakis
    return disk.size
1607 3fe22abd Christos Stavrakakis
1608 3fe22abd Christos Stavrakakis
1609 0e514de1 Bernardo Dal Seno
def _GetInstDiskSpindles(ctx, _, disk): # pylint: disable=W0613
1610 0e514de1 Bernardo Dal Seno
  """Get a Disk's spindles.
1611 0e514de1 Bernardo Dal Seno

1612 0e514de1 Bernardo Dal Seno
  @type disk: L{objects.Disk}
1613 0e514de1 Bernardo Dal Seno
  @param disk: The Disk object
1614 0e514de1 Bernardo Dal Seno

1615 0e514de1 Bernardo Dal Seno
  """
1616 0e514de1 Bernardo Dal Seno
  if disk.spindles is None:
1617 0e514de1 Bernardo Dal Seno
    return _FS_UNAVAIL
1618 0e514de1 Bernardo Dal Seno
  else:
1619 0e514de1 Bernardo Dal Seno
    return disk.spindles
1620 0e514de1 Bernardo Dal Seno
1621 0e514de1 Bernardo Dal Seno
1622 3fe22abd Christos Stavrakakis
def _GetInstDeviceName(ctx, _, device): # pylint: disable=W0613
1623 3fe22abd Christos Stavrakakis
  """Get a Device's Name.
1624 3fe22abd Christos Stavrakakis

1625 3fe22abd Christos Stavrakakis
  @type ctx: L{InstanceQueryData}
1626 3fe22abd Christos Stavrakakis
  @type device: L{objects.NIC} or L{objects.Disk}
1627 3fe22abd Christos Stavrakakis
  @param device: The NIC or Disk object
1628 3fe22abd Christos Stavrakakis

1629 3fe22abd Christos Stavrakakis
  """
1630 3fe22abd Christos Stavrakakis
  if device.name is None:
1631 3fe22abd Christos Stavrakakis
    return _FS_UNAVAIL
1632 3fe22abd Christos Stavrakakis
  else:
1633 3fe22abd Christos Stavrakakis
    return device.name
1634 3fe22abd Christos Stavrakakis
1635 3fe22abd Christos Stavrakakis
1636 3fe22abd Christos Stavrakakis
def _GetInstDeviceUUID(ctx, _, device): # pylint: disable=W0613
1637 3fe22abd Christos Stavrakakis
  """Get a Device's UUID.
1638 3fe22abd Christos Stavrakakis

1639 3fe22abd Christos Stavrakakis
  @type ctx: L{InstanceQueryData}
1640 3fe22abd Christos Stavrakakis
  @type device: L{objects.NIC} or L{objects.Disk}
1641 3fe22abd Christos Stavrakakis
  @param device: The NIC or Disk object
1642 3fe22abd Christos Stavrakakis

1643 3fe22abd Christos Stavrakakis
  """
1644 3fe22abd Christos Stavrakakis
  if device.uuid is None:
1645 3fe22abd Christos Stavrakakis
    return _FS_UNAVAIL
1646 3fe22abd Christos Stavrakakis
  else:
1647 3fe22abd Christos Stavrakakis
    return device.uuid
1648 3fe22abd Christos Stavrakakis
1649 3fe22abd Christos Stavrakakis
1650 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
1651 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
1652 1c8addc6 Michael Hanselmann

1653 1c8addc6 Michael Hanselmann
  @type index: int
1654 1c8addc6 Michael Hanselmann
  @param index: NIC index
1655 1c8addc6 Michael Hanselmann
  @type cb: callable
1656 1c8addc6 Michael Hanselmann
  @param cb: Callback
1657 1c8addc6 Michael Hanselmann

1658 1c8addc6 Michael Hanselmann
  """
1659 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1660 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1661 1c8addc6 Michael Hanselmann

1662 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1663 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1664 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1665 1c8addc6 Michael Hanselmann

1666 1c8addc6 Michael Hanselmann
    """
1667 1c8addc6 Michael Hanselmann
    try:
1668 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1669 1c8addc6 Michael Hanselmann
    except IndexError:
1670 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1671 1c8addc6 Michael Hanselmann
1672 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1673 1c8addc6 Michael Hanselmann
1674 1c8addc6 Michael Hanselmann
  return fn
1675 1c8addc6 Michael Hanselmann
1676 1c8addc6 Michael Hanselmann
1677 f98e1175 Dimitris Aragiorgis
def _GetInstNicNetworkName(ctx, _, nic): # pylint: disable=W0613
1678 f98e1175 Dimitris Aragiorgis
  """Get a NIC's Network.
1679 f98e1175 Dimitris Aragiorgis

1680 f98e1175 Dimitris Aragiorgis
  @type ctx: L{InstanceQueryData}
1681 f98e1175 Dimitris Aragiorgis
  @type nic: L{objects.NIC}
1682 f98e1175 Dimitris Aragiorgis
  @param nic: NIC object
1683 f98e1175 Dimitris Aragiorgis

1684 f98e1175 Dimitris Aragiorgis
  """
1685 f98e1175 Dimitris Aragiorgis
  if nic.network is None:
1686 f98e1175 Dimitris Aragiorgis
    return _FS_UNAVAIL
1687 f98e1175 Dimitris Aragiorgis
  else:
1688 f98e1175 Dimitris Aragiorgis
    return ctx.networks[nic.network].name
1689 f98e1175 Dimitris Aragiorgis
1690 f98e1175 Dimitris Aragiorgis
1691 d4117a72 Apollon Oikonomopoulos
def _GetInstNicNetwork(ctx, _, nic): # pylint: disable=W0613
1692 d4117a72 Apollon Oikonomopoulos
  """Get a NIC's Network.
1693 d4117a72 Apollon Oikonomopoulos

1694 d4117a72 Apollon Oikonomopoulos
  @type ctx: L{InstanceQueryData}
1695 d4117a72 Apollon Oikonomopoulos
  @type nic: L{objects.NIC}
1696 d4117a72 Apollon Oikonomopoulos
  @param nic: NIC object
1697 d4117a72 Apollon Oikonomopoulos

1698 d4117a72 Apollon Oikonomopoulos
  """
1699 d4117a72 Apollon Oikonomopoulos
  if nic.network is None:
1700 d4117a72 Apollon Oikonomopoulos
    return _FS_UNAVAIL
1701 d4117a72 Apollon Oikonomopoulos
  else:
1702 d4117a72 Apollon Oikonomopoulos
    return nic.network
1703 d4117a72 Apollon Oikonomopoulos
1704 d4117a72 Apollon Oikonomopoulos
1705 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1706 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1707 1c8addc6 Michael Hanselmann

1708 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1709 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1710 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1711 1c8addc6 Michael Hanselmann

1712 1c8addc6 Michael Hanselmann
  """
1713 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1714 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1715 1c8addc6 Michael Hanselmann
  else:
1716 e2d188cc Iustin Pop
    return nic.ip
1717 1c8addc6 Michael Hanselmann
1718 1c8addc6 Michael Hanselmann
1719 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1720 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1721 1c8addc6 Michael Hanselmann

1722 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1723 1c8addc6 Michael Hanselmann
  @type index: int
1724 1c8addc6 Michael Hanselmann
  @param index: NIC index
1725 1c8addc6 Michael Hanselmann

1726 1c8addc6 Michael Hanselmann
  """
1727 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1728 1c8addc6 Michael Hanselmann
1729 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1730 1c8addc6 Michael Hanselmann
1731 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1732 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1733 1c8addc6 Michael Hanselmann
  else:
1734 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1735 1c8addc6 Michael Hanselmann
1736 1c8addc6 Michael Hanselmann
1737 9a03cffb Thomas Thrainer
def _GetInstNicVLan(ctx, index, _):
1738 9a03cffb Thomas Thrainer
  """Get a NIC's VLAN.
1739 9a03cffb Thomas Thrainer

1740 9a03cffb Thomas Thrainer
  @type ctx: L{InstanceQueryData}
1741 9a03cffb Thomas Thrainer
  @type index: int
1742 9a03cffb Thomas Thrainer
  @param index: NIC index
1743 9a03cffb Thomas Thrainer

1744 9a03cffb Thomas Thrainer
  """
1745 9a03cffb Thomas Thrainer
  assert len(ctx.inst_nicparams) >= index
1746 9a03cffb Thomas Thrainer
1747 9a03cffb Thomas Thrainer
  nicparams = ctx.inst_nicparams[index]
1748 9a03cffb Thomas Thrainer
1749 9a03cffb Thomas Thrainer
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_OVS:
1750 9a03cffb Thomas Thrainer
    return nicparams[constants.NIC_VLAN]
1751 9a03cffb Thomas Thrainer
  else:
1752 9a03cffb Thomas Thrainer
    return _FS_UNAVAIL
1753 9a03cffb Thomas Thrainer
1754 9a03cffb Thomas Thrainer
1755 f98e1175 Dimitris Aragiorgis
def _GetInstAllNicNetworkNames(ctx, inst):
1756 f98e1175 Dimitris Aragiorgis
  """Get all network names for an instance.
1757 f98e1175 Dimitris Aragiorgis

1758 f98e1175 Dimitris Aragiorgis
  @type ctx: L{InstanceQueryData}
1759 f98e1175 Dimitris Aragiorgis
  @type inst: L{objects.Instance}
1760 f98e1175 Dimitris Aragiorgis
  @param inst: Instance object
1761 f98e1175 Dimitris Aragiorgis

1762 f98e1175 Dimitris Aragiorgis
  """
1763 f98e1175 Dimitris Aragiorgis
  result = []
1764 f98e1175 Dimitris Aragiorgis
1765 f98e1175 Dimitris Aragiorgis
  for nic in inst.nics:
1766 f98e1175 Dimitris Aragiorgis
    name = None
1767 f98e1175 Dimitris Aragiorgis
    if nic.network:
1768 f98e1175 Dimitris Aragiorgis
      name = ctx.networks[nic.network].name
1769 f98e1175 Dimitris Aragiorgis
    result.append(name)
1770 f98e1175 Dimitris Aragiorgis
1771 f98e1175 Dimitris Aragiorgis
  assert len(result) == len(inst.nics)
1772 f98e1175 Dimitris Aragiorgis
1773 f98e1175 Dimitris Aragiorgis
  return result
1774 f98e1175 Dimitris Aragiorgis
1775 f98e1175 Dimitris Aragiorgis
1776 602db636 Klaus Aehlig
def _GetInstAllNicVlans(ctx, inst):
1777 602db636 Klaus Aehlig
  """Get all network VLANs for an instance.
1778 602db636 Klaus Aehlig

1779 602db636 Klaus Aehlig
  @type ctx: L{InstanceQueryData}
1780 602db636 Klaus Aehlig
  @type inst: L{objects.Instance}
1781 602db636 Klaus Aehlig
  @param inst: Instance object
1782 602db636 Klaus Aehlig

1783 602db636 Klaus Aehlig
  """
1784 602db636 Klaus Aehlig
  assert len(ctx.inst_nicparams) == len(inst.nics)
1785 602db636 Klaus Aehlig
1786 602db636 Klaus Aehlig
  result = []
1787 602db636 Klaus Aehlig
1788 602db636 Klaus Aehlig
  for nicp in ctx.inst_nicparams:
1789 f3ac6f36 Klaus Aehlig
    if nicp[constants.NIC_MODE] in \
1790 f3ac6f36 Klaus Aehlig
          [constants.NIC_MODE_BRIDGED, constants.NIC_MODE_OVS]:
1791 602db636 Klaus Aehlig
      result.append(nicp[constants.NIC_VLAN])
1792 602db636 Klaus Aehlig
    else:
1793 602db636 Klaus Aehlig
      result.append(None)
1794 602db636 Klaus Aehlig
1795 602db636 Klaus Aehlig
  assert len(result) == len(inst.nics)
1796 602db636 Klaus Aehlig
1797 602db636 Klaus Aehlig
  return result
1798 602db636 Klaus Aehlig
1799 602db636 Klaus Aehlig
1800 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1801 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1802 1c8addc6 Michael Hanselmann

1803 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1804 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1805 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1806 1c8addc6 Michael Hanselmann

1807 1c8addc6 Michael Hanselmann
  """
1808 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1809 1c8addc6 Michael Hanselmann
1810 1c8addc6 Michael Hanselmann
  result = []
1811 1c8addc6 Michael Hanselmann
1812 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1813 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1814 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1815 1c8addc6 Michael Hanselmann
    else:
1816 1c8addc6 Michael Hanselmann
      result.append(None)
1817 1c8addc6 Michael Hanselmann
1818 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1819 1c8addc6 Michael Hanselmann
1820 e2d188cc Iustin Pop
  return result
1821 1c8addc6 Michael Hanselmann
1822 1c8addc6 Michael Hanselmann
1823 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1824 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1825 1c8addc6 Michael Hanselmann

1826 1c8addc6 Michael Hanselmann
  @type name: string
1827 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1828 1c8addc6 Michael Hanselmann

1829 1c8addc6 Michael Hanselmann
  """
1830 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1831 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1832 1c8addc6 Michael Hanselmann

1833 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1834 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1835 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1836 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1837 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1838 1c8addc6 Michael Hanselmann

1839 1c8addc6 Michael Hanselmann
    """
1840 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1841 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1842 1c8addc6 Michael Hanselmann
1843 1c8addc6 Michael Hanselmann
  return fn
1844 1c8addc6 Michael Hanselmann
1845 1c8addc6 Michael Hanselmann
1846 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1847 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1848 1c8addc6 Michael Hanselmann

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

1852 1c8addc6 Michael Hanselmann
  """
1853 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
1854 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
1855 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
1856 1c8addc6 Michael Hanselmann
1857 1c8addc6 Michael Hanselmann
  fields = [
1858 1c8addc6 Michael Hanselmann
    # All NICs
1859 79b2ca83 Michael Hanselmann
    (_MakeField("nic.count", "NICs", QFT_NUMBER,
1860 79b2ca83 Michael Hanselmann
                "Number of network interfaces"),
1861 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.nics)),
1862 79b2ca83 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER,
1863 79b2ca83 Michael Hanselmann
                "List containing each network interface's MAC address"),
1864 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.mac for nic in inst.nics]),
1865 79b2ca83 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER,
1866 79b2ca83 Michael Hanselmann
                "List containing each network interface's IP address"),
1867 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.ip for nic in inst.nics]),
1868 3fe22abd Christos Stavrakakis
    (_MakeField("nic.names", "NIC_Names", QFT_OTHER,
1869 3fe22abd Christos Stavrakakis
                "List containing each network interface's name"),
1870 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [nic.name for nic in inst.nics]),
1871 3fe22abd Christos Stavrakakis
    (_MakeField("nic.uuids", "NIC_UUIDs", QFT_OTHER,
1872 3fe22abd Christos Stavrakakis
                "List containing each network interface's UUID"),
1873 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [nic.uuid for nic in inst.nics]),
1874 79b2ca83 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER,
1875 111bf531 Michael Hanselmann
                "List containing each network interface's mode"), IQ_CONFIG, 0,
1876 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
1877 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1878 79b2ca83 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", QFT_OTHER,
1879 111bf531 Michael Hanselmann
                "List containing each network interface's link"), IQ_CONFIG, 0,
1880 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
1881 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
1882 602db636 Klaus Aehlig
    (_MakeField("nic.vlans", "NIC_VLANs", QFT_OTHER,
1883 602db636 Klaus Aehlig
                "List containing each network interface's VLAN"),
1884 602db636 Klaus Aehlig
     IQ_CONFIG, 0, _GetInstAllNicVlans),
1885 79b2ca83 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
1886 111bf531 Michael Hanselmann
                "List containing each network interface's bridge"),
1887 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstAllNicBridges),
1888 d4117a72 Apollon Oikonomopoulos
    (_MakeField("nic.networks", "NIC_networks", QFT_OTHER,
1889 d4117a72 Apollon Oikonomopoulos
                "List containing each interface's network"), IQ_CONFIG, 0,
1890 d4117a72 Apollon Oikonomopoulos
     lambda ctx, inst: [nic.network for nic in inst.nics]),
1891 f98e1175 Dimitris Aragiorgis
    (_MakeField("nic.networks.names", "NIC_networks_names", QFT_OTHER,
1892 f98e1175 Dimitris Aragiorgis
                "List containing each interface's network"),
1893 f98e1175 Dimitris Aragiorgis
     IQ_NETWORKS, 0, _GetInstAllNicNetworkNames)
1894 1c8addc6 Michael Hanselmann
    ]
1895 1c8addc6 Michael Hanselmann
1896 1c8addc6 Michael Hanselmann
  # NICs by number
1897 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
1898 79b2ca83 Michael Hanselmann
    numtext = utils.FormatOrdinal(i + 1)
1899 1c8addc6 Michael Hanselmann
    fields.extend([
1900 79b2ca83 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT,
1901 79b2ca83 Michael Hanselmann
                  "IP address of %s network interface" % numtext),
1902 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicIp)),
1903 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT,
1904 79b2ca83 Michael Hanselmann
                  "MAC address of %s network interface" % numtext),
1905 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mac_fn)),
1906 3fe22abd Christos Stavrakakis
      (_MakeField("nic.name/%s" % i, "NicName/%s" % i, QFT_TEXT,
1907 3fe22abd Christos Stavrakakis
                  "Name address of %s network interface" % numtext),
1908 3fe22abd Christos Stavrakakis
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstDeviceName)),
1909 3fe22abd Christos Stavrakakis
      (_MakeField("nic.uuid/%s" % i, "NicUUID/%s" % i, QFT_TEXT,
1910 3fe22abd Christos Stavrakakis
                  "UUID address of %s network interface" % numtext),
1911 3fe22abd Christos Stavrakakis
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstDeviceUUID)),
1912 79b2ca83 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT,
1913 79b2ca83 Michael Hanselmann
                  "Mode of %s network interface" % numtext),
1914 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_mode_fn)),
1915 79b2ca83 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT,
1916 79b2ca83 Michael Hanselmann
                  "Link of %s network interface" % numtext),
1917 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, nic_link_fn)),
1918 79b2ca83 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
1919 79b2ca83 Michael Hanselmann
                  "Bridge of %s network interface" % numtext),
1920 111bf531 Michael Hanselmann
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
1921 9a03cffb Thomas Thrainer
      (_MakeField("nic.vlan/%s" % i, "NicVLAN/%s" % i, QFT_TEXT,
1922 9a03cffb Thomas Thrainer
                  "VLAN of %s network interface" % numtext),
1923 9a03cffb Thomas Thrainer
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicVLan)),
1924 d4117a72 Apollon Oikonomopoulos
      (_MakeField("nic.network/%s" % i, "NicNetwork/%s" % i, QFT_TEXT,
1925 d4117a72 Apollon Oikonomopoulos
                  "Network of %s network interface" % numtext),
1926 d4117a72 Apollon Oikonomopoulos
       IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicNetwork)),
1927 f98e1175 Dimitris Aragiorgis
      (_MakeField("nic.network.name/%s" % i, "NicNetworkName/%s" % i, QFT_TEXT,
1928 f98e1175 Dimitris Aragiorgis
                  "Network name of %s network interface" % numtext),
1929 f98e1175 Dimitris Aragiorgis
       IQ_NETWORKS, 0, _GetInstNic(i, _GetInstNicNetworkName)),
1930 1c8addc6 Michael Hanselmann
      ])
1931 1c8addc6 Michael Hanselmann
1932 4cc4d1fa Michael Hanselmann
  aliases = [
1933 4cc4d1fa Michael Hanselmann
    # Legacy fields for first NIC
1934 4cc4d1fa Michael Hanselmann
    ("ip", "nic.ip/0"),
1935 4cc4d1fa Michael Hanselmann
    ("mac", "nic.mac/0"),
1936 4cc4d1fa Michael Hanselmann
    ("bridge", "nic.bridge/0"),
1937 4cc4d1fa Michael Hanselmann
    ("nic_mode", "nic.mode/0"),
1938 4cc4d1fa Michael Hanselmann
    ("nic_link", "nic.link/0"),
1939 d4117a72 Apollon Oikonomopoulos
    ("nic_network", "nic.network/0"),
1940 4cc4d1fa Michael Hanselmann
    ]
1941 4cc4d1fa Michael Hanselmann
1942 4cc4d1fa Michael Hanselmann
  return (fields, aliases)
1943 1c8addc6 Michael Hanselmann
1944 1c8addc6 Michael Hanselmann
1945 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
1946 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
1947 1c8addc6 Michael Hanselmann

1948 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1949 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1950 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1951 1c8addc6 Michael Hanselmann

1952 1c8addc6 Michael Hanselmann
  """
1953 da4a52a3 Thomas Thrainer
  usage = ctx.disk_usage[inst.uuid]
1954 1c8addc6 Michael Hanselmann
1955 1c8addc6 Michael Hanselmann
  if usage is None:
1956 1c8addc6 Michael Hanselmann
    usage = 0
1957 1c8addc6 Michael Hanselmann
1958 e2d188cc Iustin Pop
  return usage
1959 1c8addc6 Michael Hanselmann
1960 1c8addc6 Michael Hanselmann
1961 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1962 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1963 5d28cb6f Michael Hanselmann

1964 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1965 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1966 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1967 5d28cb6f Michael Hanselmann

1968 5d28cb6f Michael Hanselmann
  """
1969 da4a52a3 Thomas Thrainer
  consinfo = ctx.console[inst.uuid]
1970 5d28cb6f Michael Hanselmann
1971 5d28cb6f Michael Hanselmann
  if consinfo is None:
1972 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1973 5d28cb6f Michael Hanselmann
1974 5d28cb6f Michael Hanselmann
  return consinfo
1975 5d28cb6f Michael Hanselmann
1976 5d28cb6f Michael Hanselmann
1977 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1978 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1979 1c8addc6 Michael Hanselmann

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

1982 1c8addc6 Michael Hanselmann
  """
1983 1c8addc6 Michael Hanselmann
  fields = [
1984 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1985 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1986 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1987 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1988 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1989 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1990 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1991 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1992 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1993 0e514de1 Bernardo Dal Seno
    (_MakeField("disk.spindles", "Disk_spindles", QFT_OTHER,
1994 0e514de1 Bernardo Dal Seno
                "List of disk spindles"),
1995 0e514de1 Bernardo Dal Seno
     IQ_CONFIG, 0, lambda ctx, inst: [disk.spindles for disk in inst.disks]),
1996 3fe22abd Christos Stavrakakis
    (_MakeField("disk.names", "Disk_names", QFT_OTHER, "List of disk names"),
1997 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [disk.name for disk in inst.disks]),
1998 3fe22abd Christos Stavrakakis
    (_MakeField("disk.uuids", "Disk_UUIDs", QFT_OTHER, "List of disk UUIDs"),
1999 3fe22abd Christos Stavrakakis
     IQ_CONFIG, 0, lambda ctx, inst: [disk.uuid for disk in inst.disks]),
2000 1c8addc6 Michael Hanselmann
    ]
2001 1c8addc6 Michael Hanselmann
2002 1c8addc6 Michael Hanselmann
  # Disks by number
2003 3fe22abd Christos Stavrakakis
  for i in range(constants.MAX_DISKS):
2004 3fe22abd Christos Stavrakakis
    numtext = utils.FormatOrdinal(i + 1)
2005 3fe22abd Christos Stavrakakis
    fields.extend([
2006 3fe22abd Christos Stavrakakis
        (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
2007 3fe22abd Christos Stavrakakis
                    "Disk size of %s disk" % numtext),
2008 e0e44476 Michele Tartara
         IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDiskSize)),
2009 0e514de1 Bernardo Dal Seno
        (_MakeField("disk.spindles/%s" % i, "DiskSpindles/%s" % i, QFT_NUMBER,
2010 0e514de1 Bernardo Dal Seno
                    "Spindles of %s disk" % numtext),
2011 0e514de1 Bernardo Dal Seno
         IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDiskSpindles)),
2012 3fe22abd Christos Stavrakakis
        (_MakeField("disk.name/%s" % i, "DiskName/%s" % i, QFT_TEXT,
2013 3fe22abd Christos Stavrakakis
                    "Name of %s disk" % numtext),
2014 e0e44476 Michele Tartara
         IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDeviceName)),
2015 3fe22abd Christos Stavrakakis
        (_MakeField("disk.uuid/%s" % i, "DiskUUID/%s" % i, QFT_TEXT,
2016 3fe22abd Christos Stavrakakis
                    "UUID of %s disk" % numtext),
2017 e0e44476 Michele Tartara
         IQ_CONFIG, 0, _GetInstDisk(i, _GetInstDeviceUUID))])
2018 1c8addc6 Michael Hanselmann
2019 1c8addc6 Michael Hanselmann
  return fields
2020 1c8addc6 Michael Hanselmann
2021 1c8addc6 Michael Hanselmann
2022 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
2023 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
2024 1c8addc6 Michael Hanselmann

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

2027 1c8addc6 Michael Hanselmann
  """
2028 1c8addc6 Michael Hanselmann
  fields = [
2029 1c8addc6 Michael Hanselmann
    # Filled parameters
2030 79b2ca83 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
2031 7c670076 Michael Hanselmann
                "Hypervisor parameters (merged)"),
2032 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
2033 79b2ca83 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", QFT_OTHER,
2034 7c670076 Michael Hanselmann
                "Backend parameters (merged)"),
2035 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
2036 7c670076 Michael Hanselmann
    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
2037 7c670076 Michael Hanselmann
                "Operating system parameters (merged)"),
2038 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
2039 1c8addc6 Michael Hanselmann
2040 1c8addc6 Michael Hanselmann
    # Unfilled parameters
2041 79b2ca83 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
2042 79b2ca83 Michael Hanselmann
                "Custom hypervisor parameters"),
2043 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("hvparams")),
2044 79b2ca83 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
2045 79b2ca83 Michael Hanselmann
                "Custom backend parameters",),
2046 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("beparams")),
2047 7c670076 Michael Hanselmann
    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
2048 7c670076 Michael Hanselmann
                "Custom operating system parameters",),
2049 7c670076 Michael Hanselmann
     IQ_CONFIG, 0, _GetItemAttr("osparams")),
2050 79b2ca83 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
2051 79b2ca83 Michael Hanselmann
                "Custom network interface parameters"),
2052 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
2053 1c8addc6 Michael Hanselmann
    ]
2054 1c8addc6 Michael Hanselmann
2055 1c8addc6 Michael Hanselmann
  # HV params
2056 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
2057 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
2058 1c8addc6 Michael Hanselmann
2059 1c8addc6 Michael Hanselmann
  fields.extend([
2060 a6c7e2a2 Iustin Pop
    (_MakeField("hv/%s" % name,
2061 a6c7e2a2 Iustin Pop
                constants.HVS_PARAMETER_TITLES.get(name, "hv/%s" % name),
2062 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
2063 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstHvParam(name))
2064 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
2065 3c286190 Dimitris Aragiorgis
    if name not in constants.HVC_GLOBALS])
2066 1c8addc6 Michael Hanselmann
2067 1c8addc6 Michael Hanselmann
  # BE params
2068 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
2069 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
2070 1c8addc6 Michael Hanselmann
2071 1c8addc6 Michael Hanselmann
  fields.extend([
2072 a6c7e2a2 Iustin Pop
    (_MakeField("be/%s" % name,
2073 a6c7e2a2 Iustin Pop
                constants.BES_PARAMETER_TITLES.get(name, "be/%s" % name),
2074 79b2ca83 Michael Hanselmann
                _VTToQFT[kind], "The \"%s\" backend parameter" % name),
2075 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstBeParam(name))
2076 3c286190 Dimitris Aragiorgis
    for name, kind in constants.BES_PARAMETER_TYPES.items()])
2077 1c8addc6 Michael Hanselmann
2078 1c8addc6 Michael Hanselmann
  return fields
2079 1c8addc6 Michael Hanselmann
2080 1c8addc6 Michael Hanselmann
2081 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
2082 111bf531 Michael Hanselmann
  "disk_template": ("Disk_template", QFT_TEXT, 0, "Instance disk template"),
2083 111bf531 Michael Hanselmann
  "hypervisor": ("Hypervisor", QFT_TEXT, 0, "Hypervisor name"),
2084 111bf531 Michael Hanselmann
  "name": ("Instance", QFT_TEXT, QFF_HOSTNAME, "Instance name"),
2085 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
2086 111bf531 Michael Hanselmann
  "network_port": ("Network_port", QFT_OTHER, 0,
2087 79b2ca83 Michael Hanselmann
                   "Instance network port if available (e.g. for VNC console)"),
2088 111bf531 Michael Hanselmann
  "os": ("OS", QFT_TEXT, 0, "Operating system"),
2089 111bf531 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Instance"),
2090 111bf531 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, 0, "Instance UUID"),
2091 1c8addc6 Michael Hanselmann
  }
2092 1c8addc6 Michael Hanselmann
2093 1c8addc6 Michael Hanselmann
2094 1c3231aa Thomas Thrainer
def _GetNodeName(ctx, default, node_uuid):
2095 1c3231aa Thomas Thrainer
  """Gets node name of a node.
2096 1c3231aa Thomas Thrainer

2097 1c3231aa Thomas Thrainer
  @type ctx: L{InstanceQueryData}
2098 1c3231aa Thomas Thrainer
  @param default: Default value
2099 1c3231aa Thomas Thrainer
  @type node_uuid: string
2100 1c3231aa Thomas Thrainer
  @param node_uuid: Node UUID
2101 1c3231aa Thomas Thrainer

2102 1c3231aa Thomas Thrainer
  """
2103 1c3231aa Thomas Thrainer
  try:
2104 1c3231aa Thomas Thrainer
    node = ctx.nodes[node_uuid]
2105 1c3231aa Thomas Thrainer
  except KeyError:
2106 1c3231aa Thomas Thrainer
    return default
2107 1c3231aa Thomas Thrainer
  else:
2108 1c3231aa Thomas Thrainer
    return node.name
2109 1c3231aa Thomas Thrainer
2110 1c3231aa Thomas Thrainer
2111 1c3231aa Thomas Thrainer
def _GetInstNodeGroup(ctx, default, node_uuid):
2112 fab9573b Michael Hanselmann
  """Gets group UUID of an instance node.
2113 fab9573b Michael Hanselmann

2114 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
2115 fab9573b Michael Hanselmann
  @param default: Default value
2116 1c3231aa Thomas Thrainer
  @type node_uuid: string
2117 1c3231aa Thomas Thrainer
  @param node_uuid: Node UUID
2118 fab9573b Michael Hanselmann

2119 fab9573b Michael Hanselmann
  """
2120 fab9573b Michael Hanselmann
  try:
2121 1c3231aa Thomas Thrainer
    node = ctx.nodes[node_uuid]
2122 fab9573b Michael Hanselmann
  except KeyError:
2123 fab9573b Michael Hanselmann
    return default
2124 fab9573b Michael Hanselmann
  else:
2125 fab9573b Michael Hanselmann
    return node.group
2126 fab9573b Michael Hanselmann
2127 fab9573b Michael Hanselmann
2128 1c3231aa Thomas Thrainer
def _GetInstNodeGroupName(ctx, default, node_uuid):
2129 fab9573b Michael Hanselmann
  """Gets group name of an instance node.
2130 fab9573b Michael Hanselmann

2131 fab9573b Michael Hanselmann
  @type ctx: L{InstanceQueryData}
2132 fab9573b Michael Hanselmann
  @param default: Default value
2133 1c3231aa Thomas Thrainer
  @type node_uuid: string
2134 1c3231aa Thomas Thrainer
  @param node_uuid: Node UUID
2135 fab9573b Michael Hanselmann

2136 fab9573b Michael Hanselmann
  """
2137 fab9573b Michael Hanselmann
  try:
2138 1c3231aa Thomas Thrainer
    node = ctx.nodes[node_uuid]
2139 fab9573b Michael Hanselmann
  except KeyError:
2140 fab9573b Michael Hanselmann
    return default
2141 fab9573b Michael Hanselmann
2142 fab9573b Michael Hanselmann
  try:
2143 fab9573b Michael Hanselmann
    group = ctx.groups[node.group]
2144 fab9573b Michael Hanselmann
  except KeyError:
2145 fab9573b Michael Hanselmann
    return default
2146 fab9573b Michael Hanselmann
2147 fab9573b Michael Hanselmann
  return group.name
2148 fab9573b Michael Hanselmann
2149 fab9573b Michael Hanselmann
2150 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
2151 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
2152 1c8addc6 Michael Hanselmann

2153 1c8addc6 Michael Hanselmann
  """
2154 1c8addc6 Michael Hanselmann
  fields = [
2155 111bf531 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", QFT_TEXT, "Primary node"),
2156 1c3231aa Thomas Thrainer
     IQ_NODES, QFF_HOSTNAME,
2157 1c3231aa Thomas Thrainer
     lambda ctx, inst: _GetNodeName(ctx, None, inst.primary_node)),
2158 fab9573b Michael Hanselmann
    (_MakeField("pnode.group", "PrimaryNodeGroup", QFT_TEXT,
2159 fab9573b Michael Hanselmann
                "Primary node's group"),
2160 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2161 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroupName(ctx, _FS_UNAVAIL,
2162 fab9573b Michael Hanselmann
                                             inst.primary_node)),
2163 fab9573b Michael Hanselmann
    (_MakeField("pnode.group.uuid", "PrimaryNodeGroupUUID", QFT_TEXT,
2164 fab9573b Michael Hanselmann
                "Primary node's group UUID"),
2165 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2166 fab9573b Michael Hanselmann
     lambda ctx, inst: _GetInstNodeGroup(ctx, _FS_UNAVAIL, inst.primary_node)),
2167 111bf531 Michael Hanselmann
    # TODO: Allow filtering by secondary node as hostname
2168 79b2ca83 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER,
2169 79b2ca83 Michael Hanselmann
                "Secondary nodes; usually this will just be one node"),
2170 1c3231aa Thomas Thrainer
     IQ_NODES, 0,
2171 1c3231aa Thomas Thrainer
     lambda ctx, inst: map(compat.partial(_GetNodeName, ctx, None),
2172 1c3231aa Thomas Thrainer
                           inst.secondary_nodes)),
2173 fab9573b Michael Hanselmann
    (_MakeField("snodes.group", "SecondaryNodesGroups", QFT_OTHER,
2174 fab9573b Michael Hanselmann
                "Node groups of secondary nodes"),
2175 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2176 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroupName, ctx, None),
2177 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
2178 fab9573b Michael Hanselmann
    (_MakeField("snodes.group.uuid", "SecondaryNodesGroupsUUID", QFT_OTHER,
2179 fab9573b Michael Hanselmann
                "Node group UUIDs of secondary nodes"),
2180 fab9573b Michael Hanselmann
     IQ_NODES, 0,
2181 fab9573b Michael Hanselmann
     lambda ctx, inst: map(compat.partial(_GetInstNodeGroup, ctx, None),
2182 fab9573b Michael Hanselmann
                           inst.secondary_nodes)),
2183 2e04d454 Agata Murawska
    (_MakeField("admin_state", "InstanceState", QFT_TEXT,
2184 2e04d454 Agata Murawska
                "Desired state of instance"),
2185 9ca8a7c5 Agata Murawska
     IQ_CONFIG, 0, _GetItemAttr("admin_state")),
2186 754cc530 Agata Murawska
    (_MakeField("admin_up", "Autostart", QFT_BOOL,
2187 754cc530 Agata Murawska
                "Desired state of instance"),
2188 754cc530 Agata Murawska
     IQ_CONFIG, 0, lambda ctx, inst: inst.admin_state == constants.ADMINST_UP),
2189 ca83454f Thomas Thrainer
    (_MakeField("disks_active", "DisksActive", QFT_BOOL,
2190 ca83454f Thomas Thrainer
                "Desired state of instance disks"),
2191 ca83454f Thomas Thrainer
     IQ_CONFIG, 0, _GetItemAttr("disks_active")),
2192 111bf531 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
2193 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
2194 79b2ca83 Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER,
2195 111bf531 Michael Hanselmann
                "Instance console information"), IQ_CONSOLE, 0,
2196 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
2197 1c8addc6 Michael Hanselmann
    ]
2198 1c8addc6 Michael Hanselmann
2199 1c8addc6 Michael Hanselmann
  # Add simple fields
2200 111bf531 Michael Hanselmann
  fields.extend([
2201 111bf531 Michael Hanselmann
    (_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
2202 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()])
2203 1c8addc6 Michael Hanselmann
2204 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
2205 1c8addc6 Michael Hanselmann
  fields.extend([
2206 79b2ca83 Michael Hanselmann
    (_MakeField("oper_state", "Running", QFT_BOOL, "Actual state of instance"),
2207 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstOperState),
2208 79b2ca83 Michael Hanselmann
    (_MakeField("oper_ram", "Memory", QFT_UNIT,
2209 79b2ca83 Michael Hanselmann
                "Actual memory usage as seen by hypervisor"),
2210 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("memory")),
2211 79b2ca83 Michael Hanselmann
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER,
2212 79b2ca83 Michael Hanselmann
                "Actual number of VCPUs as seen by hypervisor"),
2213 111bf531 Michael Hanselmann
     IQ_LIVE, 0, _GetInstLiveData("vcpus")),
2214 1c8addc6 Michael Hanselmann
    ])
2215 1c8addc6 Michael Hanselmann
2216 79b2ca83 Michael Hanselmann
  # Status field
2217 79b2ca83 Michael Hanselmann
  status_values = (constants.INSTST_RUNNING, constants.INSTST_ADMINDOWN,
2218 79b2ca83 Michael Hanselmann
                   constants.INSTST_WRONGNODE, constants.INSTST_ERRORUP,
2219 79b2ca83 Michael Hanselmann
                   constants.INSTST_ERRORDOWN, constants.INSTST_NODEDOWN,
2220 9982754c Jose A. Lopes
                   constants.INSTST_NODEOFFLINE, constants.INSTST_ADMINOFFLINE,
2221 9982754c Jose A. Lopes
                   constants.INSTST_USERDOWN)
2222 79b2ca83 Michael Hanselmann
  status_doc = ("Instance status; \"%s\" if instance is set to be running"
2223 79b2ca83 Michael Hanselmann
                " and actually is, \"%s\" if instance is stopped and"
2224 79b2ca83 Michael Hanselmann
                " is not running, \"%s\" if instance running, but not on its"
2225 79b2ca83 Michael Hanselmann
                " designated primary node, \"%s\" if instance should be"
2226 79b2ca83 Michael Hanselmann
                " stopped, but is actually running, \"%s\" if instance should"
2227 79b2ca83 Michael Hanselmann
                " run, but doesn't, \"%s\" if instance's primary node is down,"
2228 2e04d454 Agata Murawska
                " \"%s\" if instance's primary node is marked offline,"
2229 9982754c Jose A. Lopes
                " \"%s\" if instance is offline and does not use dynamic,"
2230 9982754c Jose A. Lopes
                " \"%s\" if the user shutdown the instance"
2231 2e04d454 Agata Murawska
                " resources" % status_values)
2232 79b2ca83 Michael Hanselmann
  fields.append((_MakeField("status", "Status", QFT_TEXT, status_doc),
2233 111bf531 Michael Hanselmann
                 IQ_LIVE, 0, _GetInstStatus))
2234 9982754c Jose A. Lopes
2235 79b2ca83 Michael Hanselmann
  assert set(status_values) == constants.INSTST_ALL, \
2236 79b2ca83 Michael Hanselmann
         "Status documentation mismatch"
2237 79b2ca83 Michael Hanselmann
2238 4cc4d1fa Michael Hanselmann
  (network_fields, network_aliases) = _GetInstanceNetworkFields()
2239 4cc4d1fa Michael Hanselmann
2240 4cc4d1fa Michael Hanselmann
  fields.extend(network_fields)
2241 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
2242 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
2243 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
2244 1c8addc6 Michael Hanselmann
2245 e7e8037b Iustin Pop
  aliases = [
2246 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
2247 31d1791a Guido Trotter
    ("be/memory", "be/maxmem"),
2248 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
2249 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
2250 4cc4d1fa Michael Hanselmann
    ] + network_aliases
2251 e7e8037b Iustin Pop
2252 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
2253 1c8addc6 Michael Hanselmann
2254 1c8addc6 Michael Hanselmann
2255 24d16f76 Michael Hanselmann
class LockQueryData:
2256 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
2257 24d16f76 Michael Hanselmann

2258 24d16f76 Michael Hanselmann
  """
2259 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
2260 24d16f76 Michael Hanselmann
    """Initializes this class.
2261 24d16f76 Michael Hanselmann

2262 24d16f76 Michael Hanselmann
    """
2263 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
2264 24d16f76 Michael Hanselmann
2265 24d16f76 Michael Hanselmann
  def __iter__(self):
2266 24d16f76 Michael Hanselmann
    """Iterate over all locks.
2267 24d16f76 Michael Hanselmann

2268 24d16f76 Michael Hanselmann
    """
2269 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
2270 24d16f76 Michael Hanselmann
2271 24d16f76 Michael Hanselmann
2272 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
2273 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
2274 24d16f76 Michael Hanselmann

2275 24d16f76 Michael Hanselmann
  """
2276 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
2277 24d16f76 Michael Hanselmann
2278 24d16f76 Michael Hanselmann
  if owners:
2279 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
2280 24d16f76 Michael Hanselmann
2281 e2d188cc Iustin Pop
  return owners
2282 24d16f76 Michael Hanselmann
2283 24d16f76 Michael Hanselmann
2284 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
2285 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
2286 24d16f76 Michael Hanselmann

2287 24d16f76 Michael Hanselmann
  """
2288 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
2289 24d16f76 Michael Hanselmann
2290 24d16f76 Michael Hanselmann
  if pending:
2291 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
2292 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
2293 24d16f76 Michael Hanselmann
2294 e2d188cc Iustin Pop
  return pending
2295 24d16f76 Michael Hanselmann
2296 24d16f76 Michael Hanselmann
2297 24d16f76 Michael Hanselmann
def _BuildLockFields():
2298 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
2299 24d16f76 Michael Hanselmann

2300 24d16f76 Michael Hanselmann
  """
2301 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
2302 111bf531 Michael Hanselmann
    # TODO: Lock names are not always hostnames. Should QFF_HOSTNAME be used?
2303 111bf531 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Lock name"), None, 0,
2304 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
2305 79b2ca83 Michael Hanselmann
    (_MakeField("mode", "Mode", QFT_OTHER,
2306 79b2ca83 Michael Hanselmann
                "Mode in which the lock is currently acquired"
2307 79b2ca83 Michael Hanselmann
                " (exclusive or shared)"),
2308 111bf531 Michael Hanselmann
     LQ_MODE, 0, lambda ctx, (name, mode, owners, pending): mode),
2309 79b2ca83 Michael Hanselmann
    (_MakeField("owner", "Owner", QFT_OTHER, "Current lock owner(s)"),
2310 111bf531 Michael Hanselmann
     LQ_OWNER, 0, _GetLockOwners),
2311 79b2ca83 Michael Hanselmann
    (_MakeField("pending", "Pending", QFT_OTHER,
2312 79b2ca83 Michael Hanselmann
                "Threads waiting for the lock"),
2313 111bf531 Michael Hanselmann
     LQ_PENDING, 0, _GetLockPending),
2314 d63bd540 Iustin Pop
    ], [])
2315 24d16f76 Michael Hanselmann
2316 24d16f76 Michael Hanselmann
2317 8e21cfc0 Adeodato Simo
class GroupQueryData:
2318 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
2319 8e21cfc0 Adeodato Simo

2320 8e21cfc0 Adeodato Simo
  """
2321 2c758845 René Nussbaumer
  def __init__(self, cluster, groups, group_to_nodes, group_to_instances,
2322 2c758845 René Nussbaumer
               want_diskparams):
2323 8e21cfc0 Adeodato Simo
    """Initializes this class.
2324 8e21cfc0 Adeodato Simo

2325 edd49f9b Agata Murawska
    @param cluster: Cluster object
2326 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
2327 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
2328 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
2329 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
2330 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
2331 2c758845 René Nussbaumer
    @type want_diskparams: bool
2332 2c758845 René Nussbaumer
    @param want_diskparams: Whether diskparamters should be calculated
2333 8e21cfc0 Adeodato Simo

2334 8e21cfc0 Adeodato Simo
    """
2335 8e21cfc0 Adeodato Simo
    self.groups = groups
2336 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
2337 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
2338 edd49f9b Agata Murawska
    self.cluster = cluster
2339 2c758845 René Nussbaumer
    self.want_diskparams = want_diskparams
2340 edd49f9b Agata Murawska
2341 edd49f9b Agata Murawska
    # Used for individual rows
2342 edd49f9b Agata Murawska
    self.group_ipolicy = None
2343 8930b0f0 Iustin Pop
    self.ndparams = None
2344 2c758845 René Nussbaumer
    self.group_dp = None
2345 8e21cfc0 Adeodato Simo
2346 8e21cfc0 Adeodato Simo
  def __iter__(self):
2347 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
2348 8e21cfc0 Adeodato Simo

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

2352 8e21cfc0 Adeodato Simo
    """
2353 edd49f9b Agata Murawska
    for group in self.groups:
2354 edd49f9b Agata Murawska
      self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy)
2355 8930b0f0 Iustin Pop
      self.ndparams = self.cluster.SimpleFillND(group.ndparams)
2356 2c758845 René Nussbaumer
      if self.want_diskparams:
2357 2c758845 René Nussbaumer
        self.group_dp = self.cluster.SimpleFillDP(group.diskparams)
2358 2c758845 René Nussbaumer
      else:
2359 2c758845 René Nussbaumer
        self.group_dp = None
2360 edd49f9b Agata Murawska
      yield group
2361 8e21cfc0 Adeodato Simo
2362 8e21cfc0 Adeodato Simo
2363 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
2364 79b2ca83 Michael Hanselmann
  "alloc_policy": ("AllocPolicy", QFT_TEXT, "Allocation policy for group"),
2365 79b2ca83 Michael Hanselmann
  "name": ("Group", QFT_TEXT, "Group name"),
2366 79b2ca83 Michael Hanselmann
  "serial_no": ("SerialNo", QFT_NUMBER, _SERIAL_NO_DOC % "Group"),
2367 79b2ca83 Michael Hanselmann
  "uuid": ("UUID", QFT_TEXT, "Group UUID"),
2368 8e21cfc0 Adeodato Simo
  }
2369 8e21cfc0 Adeodato Simo
2370 8e21cfc0 Adeodato Simo
2371 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
2372 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
2373 8e21cfc0 Adeodato Simo

2374 8e21cfc0 Adeodato Simo
  """
2375 8e21cfc0 Adeodato Simo
  # Add simple fields
2376 111bf531 Michael Hanselmann
  fields = [(_MakeField(name, title, kind, doc), GQ_CONFIG, 0,
2377 111bf531 Michael Hanselmann
             _GetItemAttr(name))
2378 79b2ca83 Michael Hanselmann
            for (name, (title, kind, doc)) in _GROUP_SIMPLE_FIELDS.items()]
2379 8e21cfc0 Adeodato Simo
2380 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
2381 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
2382 8e21cfc0 Adeodato Simo
2383 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
2384 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
2385 8e21cfc0 Adeodato Simo
2386 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
2387 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
2388 8e21cfc0 Adeodato Simo
2389 8e21cfc0 Adeodato Simo
  # Add fields for nodes
2390 8e21cfc0 Adeodato Simo
  fields.extend([
2391 79b2ca83 Michael Hanselmann
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER, "Number of nodes"),
2392 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetLength(group_to_nodes)),
2393 79b2ca83 Michael Hanselmann
    (_MakeField("node_list", "NodeList", QFT_OTHER, "List of nodes"),
2394 111bf531 Michael Hanselmann
     GQ_NODE, 0, _GetSortedList(group_to_nodes)),
2395 8e21cfc0 Adeodato Simo
    ])
2396 8e21cfc0 Adeodato Simo
2397 8e21cfc0 Adeodato Simo
  # Add fields for instances
2398 8e21cfc0 Adeodato Simo
  fields.extend([
2399 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER,
2400 79b2ca83 Michael Hanselmann
                "Number of primary instances"),
2401 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetLength(group_to_instances)),
2402 79b2ca83 Michael Hanselmann
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER,
2403 79b2ca83 Michael Hanselmann
                "List of primary instances"),
2404 111bf531 Michael Hanselmann
     GQ_INST, 0, _GetSortedList(group_to_instances)),
2405 8e21cfc0 Adeodato Simo
    ])
2406 8e21cfc0 Adeodato Simo
2407 1ffd2673 Michael Hanselmann
  # Other fields
2408 1ffd2673 Michael Hanselmann
  fields.extend([
2409 1ffd2673 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
2410 1ffd2673 Michael Hanselmann
     lambda ctx, group: list(group.GetTags())),
2411 edd49f9b Agata Murawska
    (_MakeField("ipolicy", "InstancePolicy", QFT_OTHER,
2412 edd49f9b Agata Murawska
                "Instance policy limitations (merged)"),
2413 edd49f9b Agata Murawska
     GQ_CONFIG, 0, lambda ctx, _: ctx.group_ipolicy),
2414 edd49f9b Agata Murawska
    (_MakeField("custom_ipolicy", "CustomInstancePolicy", QFT_OTHER,
2415 edd49f9b Agata Murawska
                "Custom instance policy limitations"),
2416 edd49f9b Agata Murawska
     GQ_CONFIG, 0, _GetItemAttr("ipolicy")),
2417 8930b0f0 Iustin Pop
    (_MakeField("custom_ndparams", "CustomNDParams", QFT_OTHER,
2418 8930b0f0 Iustin Pop
                "Custom node parameters"),
2419 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, _GetItemAttr("ndparams")),
2420 8930b0f0 Iustin Pop
    (_MakeField("ndparams", "NDParams", QFT_OTHER,
2421 8930b0f0 Iustin Pop
                "Node parameters"),
2422 8930b0f0 Iustin Pop
     GQ_CONFIG, 0, lambda ctx, _: ctx.ndparams),
2423 2c758845 René Nussbaumer
    (_MakeField("diskparams", "DiskParameters", QFT_OTHER,
2424 2c758845 René Nussbaumer
                "Disk parameters (merged)"),
2425 2c758845 René Nussbaumer
     GQ_DISKPARAMS, 0, lambda ctx, _: ctx.group_dp),
2426 2c758845 René Nussbaumer
    (_MakeField("custom_diskparams", "CustomDiskParameters", QFT_OTHER,
2427 2c758845 René Nussbaumer
                "Custom disk parameters"),
2428 2c758845 René Nussbaumer
     GQ_CONFIG, 0, _GetItemAttr("diskparams")),
2429 1ffd2673 Michael Hanselmann
    ])
2430 1ffd2673 Michael Hanselmann
2431 8930b0f0 Iustin Pop
  # ND parameters
2432 8930b0f0 Iustin Pop
  fields.extend(_BuildNDFields(True))
2433 8930b0f0 Iustin Pop
2434 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
2435 8e21cfc0 Adeodato Simo
2436 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
2437 8e21cfc0 Adeodato Simo
2438 8e21cfc0 Adeodato Simo
2439 be3a4b14 Michael Hanselmann
class OsInfo(objects.ConfigObject):
2440 be3a4b14 Michael Hanselmann
  __slots__ = [
2441 be3a4b14 Michael Hanselmann
    "name",
2442 be3a4b14 Michael Hanselmann
    "valid",
2443 be3a4b14 Michael Hanselmann
    "hidden",
2444 be3a4b14 Michael Hanselmann
    "blacklisted",
2445 be3a4b14 Michael Hanselmann
    "variants",
2446 be3a4b14 Michael Hanselmann
    "api_versions",
2447 be3a4b14 Michael Hanselmann
    "parameters",
2448 be3a4b14 Michael Hanselmann
    "node_status",
2449 be3a4b14 Michael Hanselmann
    ]
2450 be3a4b14 Michael Hanselmann
2451 be3a4b14 Michael Hanselmann
2452 be3a4b14 Michael Hanselmann
def _BuildOsFields():
2453 be3a4b14 Michael Hanselmann
  """Builds list of fields for operating system queries.
2454 be3a4b14 Michael Hanselmann

2455 be3a4b14 Michael Hanselmann
  """
2456 be3a4b14 Michael Hanselmann
  fields = [
2457 be3a4b14 Michael Hanselmann
    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
2458 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("name")),
2459 be3a4b14 Michael Hanselmann
    (_MakeField("valid", "Valid", QFT_BOOL,
2460 be3a4b14 Michael Hanselmann
                "Whether operating system definition is valid"),
2461 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("valid")),
2462 be3a4b14 Michael Hanselmann
    (_MakeField("hidden", "Hidden", QFT_BOOL,
2463 be3a4b14 Michael Hanselmann
                "Whether operating system is hidden"),
2464 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("hidden")),
2465 be3a4b14 Michael Hanselmann
    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
2466 be3a4b14 Michael Hanselmann
                "Whether operating system is blacklisted"),
2467 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("blacklisted")),
2468 be3a4b14 Michael Hanselmann
    (_MakeField("variants", "Variants", QFT_OTHER,
2469 be3a4b14 Michael Hanselmann
                "Operating system variants"),
2470 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
2471 be3a4b14 Michael Hanselmann
    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
2472 be3a4b14 Michael Hanselmann
                "Operating system API versions"),
2473 be3a4b14 Michael Hanselmann
     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
2474 be3a4b14 Michael Hanselmann
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2475 be3a4b14 Michael Hanselmann
                "Operating system parameters"),
2476 eb62069e Iustin Pop
     None, 0, _ConvWrap(compat.partial(utils.NiceSort, key=compat.fst),
2477 6ae1fade Iustin Pop
                        _GetItemAttr("parameters"))),
2478 be3a4b14 Michael Hanselmann
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2479 be3a4b14 Michael Hanselmann
                "Status from node"),
2480 be3a4b14 Michael Hanselmann
     None, 0, _GetItemAttr("node_status")),
2481 be3a4b14 Michael Hanselmann
    ]
2482 be3a4b14 Michael Hanselmann
2483 be3a4b14 Michael Hanselmann
  return _PrepareFieldList(fields, [])
2484 be3a4b14 Michael Hanselmann
2485 be3a4b14 Michael Hanselmann
2486 b954f097 Constantinos Venetsanopoulos
class ExtStorageInfo(objects.ConfigObject):
2487 b954f097 Constantinos Venetsanopoulos
  __slots__ = [
2488 b954f097 Constantinos Venetsanopoulos
    "name",
2489 b954f097 Constantinos Venetsanopoulos
    "node_status",
2490 b954f097 Constantinos Venetsanopoulos
    "nodegroup_status",
2491 b954f097 Constantinos Venetsanopoulos
    "parameters",
2492 b954f097 Constantinos Venetsanopoulos
    ]
2493 b954f097 Constantinos Venetsanopoulos
2494 b954f097 Constantinos Venetsanopoulos
2495 b954f097 Constantinos Venetsanopoulos
def _BuildExtStorageFields():
2496 b954f097 Constantinos Venetsanopoulos
  """Builds list of fields for extstorage provider queries.
2497 b954f097 Constantinos Venetsanopoulos

2498 b954f097 Constantinos Venetsanopoulos
  """
2499 b954f097 Constantinos Venetsanopoulos
  fields = [
2500 b954f097 Constantinos Venetsanopoulos
    (_MakeField("name", "Name", QFT_TEXT, "ExtStorage provider name"),
2501 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("name")),
2502 b954f097 Constantinos Venetsanopoulos
    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
2503 b954f097 Constantinos Venetsanopoulos
                "Status from node"),
2504 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("node_status")),
2505 b954f097 Constantinos Venetsanopoulos
    (_MakeField("nodegroup_status", "NodegroupStatus", QFT_OTHER,
2506 b954f097 Constantinos Venetsanopoulos
                "Overall Nodegroup status"),
2507 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("nodegroup_status")),
2508 b954f097 Constantinos Venetsanopoulos
    (_MakeField("parameters", "Parameters", QFT_OTHER,
2509 b954f097 Constantinos Venetsanopoulos
                "ExtStorage provider parameters"),
2510 b954f097 Constantinos Venetsanopoulos
     None, 0, _GetItemAttr("parameters")),
2511 b954f097 Constantinos Venetsanopoulos
    ]
2512 b954f097 Constantinos Venetsanopoulos
2513 b954f097 Constantinos Venetsanopoulos
  return _PrepareFieldList(fields, [])
2514 b954f097 Constantinos Venetsanopoulos
2515 b954f097 Constantinos Venetsanopoulos
2516 9665bb3a Michael Hanselmann
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613
2517 9665bb3a Michael Hanselmann
  """Return L{_FS_UNAVAIL} if job is None.
2518 9665bb3a Michael Hanselmann

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

2522 9665bb3a Michael Hanselmann
  """
2523 9665bb3a Michael Hanselmann
  if job is None:
2524 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2525 9665bb3a Michael Hanselmann
  else:
2526 9665bb3a Michael Hanselmann
    return fn(job)
2527 9665bb3a Michael Hanselmann
2528 9665bb3a Michael Hanselmann
2529 9665bb3a Michael Hanselmann
def _JobUnavail(inner):
2530 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobUnavailInner}.
2531 9665bb3a Michael Hanselmann

2532 9665bb3a Michael Hanselmann
  """
2533 9665bb3a Michael Hanselmann
  return compat.partial(_JobUnavailInner, inner)
2534 9665bb3a Michael Hanselmann
2535 9665bb3a Michael Hanselmann
2536 9665bb3a Michael Hanselmann
def _PerJobOpInner(fn, job):
2537 9665bb3a Michael Hanselmann
  """Executes a function per opcode in a job.
2538 9665bb3a Michael Hanselmann

2539 9665bb3a Michael Hanselmann
  """
2540 9665bb3a Michael Hanselmann
  return map(fn, job.ops)
2541 9665bb3a Michael Hanselmann
2542 9665bb3a Michael Hanselmann
2543 9665bb3a Michael Hanselmann
def _PerJobOp(fn):
2544 9665bb3a Michael Hanselmann
  """Wrapper for L{_PerJobOpInner}.
2545 9665bb3a Michael Hanselmann

2546 9665bb3a Michael Hanselmann
  """
2547 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_PerJobOpInner, fn))
2548 9665bb3a Michael Hanselmann
2549 9665bb3a Michael Hanselmann
2550 9665bb3a Michael Hanselmann
def _JobTimestampInner(fn, job):
2551 9665bb3a Michael Hanselmann
  """Converts unavailable timestamp to L{_FS_UNAVAIL}.
2552 9665bb3a Michael Hanselmann

2553 9665bb3a Michael Hanselmann
  """
2554 9665bb3a Michael Hanselmann
  timestamp = fn(job)
2555 9665bb3a Michael Hanselmann
2556 9665bb3a Michael Hanselmann
  if timestamp is None:
2557 9665bb3a Michael Hanselmann
    return _FS_UNAVAIL
2558 9665bb3a Michael Hanselmann
  else:
2559 9665bb3a Michael Hanselmann
    return timestamp
2560 9665bb3a Michael Hanselmann
2561 9665bb3a Michael Hanselmann
2562 9665bb3a Michael Hanselmann
def _JobTimestamp(fn):
2563 9665bb3a Michael Hanselmann
  """Wrapper for L{_JobTimestampInner}.
2564 9665bb3a Michael Hanselmann

2565 9665bb3a Michael Hanselmann
  """
2566 9665bb3a Michael Hanselmann
  return _JobUnavail(compat.partial(_JobTimestampInner, fn))
2567 9665bb3a Michael Hanselmann
2568 9665bb3a Michael Hanselmann
2569 9665bb3a Michael Hanselmann
def _BuildJobFields():
2570 9665bb3a Michael Hanselmann
  """Builds list of fields for job queries.
2571 9665bb3a Michael Hanselmann

2572 9665bb3a Michael Hanselmann
  """
2573 9665bb3a Michael Hanselmann
  fields = [
2574 76b62028 Iustin Pop
    (_MakeField("id", "ID", QFT_NUMBER, "Job ID"),
2575 526f866b Michael Hanselmann
     None, QFF_JOB_ID, lambda _, (job_id, job): job_id),
2576 9665bb3a Michael Hanselmann
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2577 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2578 9665bb3a Michael Hanselmann
    (_MakeField("priority", "Priority", QFT_NUMBER,
2579 9665bb3a Michael Hanselmann
                ("Current job priority (%s to %s)" %
2580 9665bb3a Michael Hanselmann
                 (constants.OP_PRIO_LOWEST, constants.OP_PRIO_HIGHEST))),
2581 9665bb3a Michael Hanselmann
     None, 0, _JobUnavail(lambda job: job.CalcPriority())),
2582 0422250e Michael Hanselmann
    (_MakeField("archived", "Archived", QFT_BOOL, "Whether job is archived"),
2583 0422250e Michael Hanselmann
     JQ_ARCHIVED, 0, lambda _, (job_id, job): job.archived),
2584 9665bb3a Michael Hanselmann
    (_MakeField("ops", "OpCodes", QFT_OTHER, "List of all opcodes"),
2585 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.__getstate__())),
2586 9665bb3a Michael Hanselmann
    (_MakeField("opresult", "OpCode_result", QFT_OTHER,
2587 9665bb3a Michael Hanselmann
                "List of opcodes results"),
2588 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("result"))),
2589 9665bb3a Michael Hanselmann
    (_MakeField("opstatus", "OpCode_status", QFT_OTHER,
2590 9665bb3a Michael Hanselmann
                "List of opcodes status"),
2591 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("status"))),
2592 9665bb3a Michael Hanselmann
    (_MakeField("oplog", "OpCode_log", QFT_OTHER,
2593 9665bb3a Michael Hanselmann
                "List of opcode output logs"),
2594 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("log"))),
2595 9665bb3a Michael Hanselmann
    (_MakeField("opstart", "OpCode_start", QFT_OTHER,
2596 9665bb3a Michael Hanselmann
                "List of opcode start timestamps (before acquiring locks)"),
2597 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("start_timestamp"))),
2598 9665bb3a Michael Hanselmann
    (_MakeField("opexec", "OpCode_exec", QFT_OTHER,
2599 9665bb3a Michael Hanselmann
                "List of opcode execution start timestamps (after acquiring"
2600 9665bb3a Michael Hanselmann
                " locks)"),
2601 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("exec_timestamp"))),
2602 9665bb3a Michael Hanselmann
    (_MakeField("opend", "OpCode_end", QFT_OTHER,
2603 9665bb3a Michael Hanselmann
                "List of opcode execution end timestamps"),
2604 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("end_timestamp"))),
2605 9665bb3a Michael Hanselmann
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2606 9665bb3a Michael Hanselmann
                "List of opcode priorities"),
2607 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2608 9665bb3a Michael Hanselmann
    (_MakeField("summary", "Summary", QFT_OTHER,
2609 9665bb3a Michael Hanselmann
                "List of per-opcode summaries"),
2610 9665bb3a Michael Hanselmann
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2611 9665bb3a Michael Hanselmann
    ]
2612 9665bb3a Michael Hanselmann
2613 526f866b Michael Hanselmann
  # Timestamp fields
2614 526f866b Michael Hanselmann
  for (name, attr, title, desc) in [
2615 526f866b Michael Hanselmann
    ("received_ts", "received_timestamp", "Received",
2616 526f866b Michael Hanselmann
     "Timestamp of when job was received"),
2617 526f866b Michael Hanselmann
    ("start_ts", "start_timestamp", "Start", "Timestamp of job start"),
2618 526f866b Michael Hanselmann
    ("end_ts", "end_timestamp", "End", "Timestamp of job end"),
2619 526f866b Michael Hanselmann
    ]:
2620 526f866b Michael Hanselmann
    getter = operator.attrgetter(attr)
2621 526f866b Michael Hanselmann
    fields.extend([
2622 526f866b Michael Hanselmann
      (_MakeField(name, title, QFT_OTHER,
2623 526f866b Michael Hanselmann
                  "%s (tuple containing seconds and microseconds)" % desc),
2624 526f866b Michael Hanselmann
       None, QFF_SPLIT_TIMESTAMP, _JobTimestamp(getter)),
2625 526f866b Michael Hanselmann
      ])
2626 526f866b Michael Hanselmann
2627 9665bb3a Michael Hanselmann
  return _PrepareFieldList(fields, [])
2628 9665bb3a Michael Hanselmann
2629 9665bb3a Michael Hanselmann
2630 0fdf247d Michael Hanselmann
def _GetExportName(_, (node_name, expname)): # pylint: disable=W0613
2631 0fdf247d Michael Hanselmann
  """Returns an export name if available.
2632 0fdf247d Michael Hanselmann

2633 0fdf247d Michael Hanselmann
  """
2634 0fdf247d Michael Hanselmann
  if expname is None:
2635 0b1c7a55 Iustin Pop
    return _FS_NODATA
2636 0fdf247d Michael Hanselmann
  else:
2637 0fdf247d Michael Hanselmann
    return expname
2638 0fdf247d Michael Hanselmann
2639 0fdf247d Michael Hanselmann
2640 0fdf247d Michael Hanselmann
def _BuildExportFields():
2641 0fdf247d Michael Hanselmann
  """Builds list of fields for exports.
2642 0fdf247d Michael Hanselmann

2643 0fdf247d Michael Hanselmann
  """
2644 0fdf247d Michael Hanselmann
  fields = [
2645 0fdf247d Michael Hanselmann
    (_MakeField("node", "Node", QFT_TEXT, "Node name"),
2646 0fdf247d Michael Hanselmann
     None, QFF_HOSTNAME, lambda _, (node_name, expname): node_name),
2647 0fdf247d Michael Hanselmann
    (_MakeField("export", "Export", QFT_TEXT, "Export name"),
2648 0fdf247d Michael Hanselmann
     None, 0, _GetExportName),
2649 0fdf247d Michael Hanselmann
    ]
2650 0fdf247d Michael Hanselmann
2651 0fdf247d Michael Hanselmann
  return _PrepareFieldList(fields, [])
2652 0fdf247d Michael Hanselmann
2653 0fdf247d Michael Hanselmann
2654 dff5f600 Michael Hanselmann
_CLUSTER_VERSION_FIELDS = {
2655 dff5f600 Michael Hanselmann
  "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION,
2656 dff5f600 Michael Hanselmann
                       "Software version"),
2657 dff5f600 Michael Hanselmann
  "protocol_version": ("ProtocolVersion", QFT_NUMBER,
2658 dff5f600 Michael Hanselmann
                       constants.PROTOCOL_VERSION,
2659 dff5f600 Michael Hanselmann
                       "RPC protocol version"),
2660 dff5f600 Michael Hanselmann
  "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION,
2661 dff5f600 Michael Hanselmann
                     "Configuration format version"),
2662 dff5f600 Michael Hanselmann
  "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS),
2663 dff5f600 Michael Hanselmann
                     "API version for OS template scripts"),
2664 dff5f600 Michael Hanselmann
  "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION,
2665 dff5f600 Michael Hanselmann
                     "Import/export file format version"),
2666 026f444f Thomas Thrainer
  "vcs_version": ("VCSVersion", QFT_TEXT, constants.VCS_VERSION,
2667 026f444f Thomas Thrainer
                     "VCS version"),
2668 dff5f600 Michael Hanselmann
  }
2669 dff5f600 Michael Hanselmann
2670 dff5f600 Michael Hanselmann
2671 dff5f600 Michael Hanselmann
_CLUSTER_SIMPLE_FIELDS = {
2672 dff5f600 Michael Hanselmann
  "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"),
2673 dff5f600 Michael Hanselmann
  "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"),
2674 dff5f600 Michael Hanselmann
  }
2675 dff5f600 Michael Hanselmann
2676 dff5f600 Michael Hanselmann
2677 dff5f600 Michael Hanselmann
class ClusterQueryData:
2678 1c3231aa Thomas Thrainer
  def __init__(self, cluster, nodes, drain_flag, watcher_pause):
2679 dff5f600 Michael Hanselmann
    """Initializes this class.
2680 dff5f600 Michael Hanselmann

2681 dff5f600 Michael Hanselmann
    @type cluster: L{objects.Cluster}
2682 dff5f600 Michael Hanselmann
    @param cluster: Instance of cluster object
2683 1c3231aa Thomas Thrainer
    @type nodes: dict; node UUID as key
2684 1c3231aa Thomas Thrainer
    @param nodes: Node objects
2685 dff5f600 Michael Hanselmann
    @type drain_flag: bool
2686 dff5f600 Michael Hanselmann
    @param drain_flag: Whether job queue is drained
2687 dff5f600 Michael Hanselmann
    @type watcher_pause: number
2688 dff5f600 Michael Hanselmann
    @param watcher_pause: Until when watcher is paused (Unix timestamp)
2689 dff5f600 Michael Hanselmann

2690 dff5f600 Michael Hanselmann
    """
2691 dff5f600 Michael Hanselmann
    self._cluster = cluster
2692 1c3231aa Thomas Thrainer
    self.nodes = nodes
2693 dff5f600 Michael Hanselmann
    self.drain_flag = drain_flag
2694 dff5f600 Michael Hanselmann
    self.watcher_pause = watcher_pause
2695 dff5f600 Michael Hanselmann
2696 dff5f600 Michael Hanselmann
  def __iter__(self):
2697 dff5f600 Michael Hanselmann
    return iter([self._cluster])
2698 dff5f600 Michael Hanselmann
2699 dff5f600 Michael Hanselmann
2700 dff5f600 Michael Hanselmann
def _ClusterWatcherPause(ctx, _):
2701 dff5f600 Michael Hanselmann
  """Returns until when watcher is paused (if available).
2702 dff5f600 Michael Hanselmann

2703 dff5f600 Michael Hanselmann
  """
2704 dff5f600 Michael Hanselmann
  if ctx.watcher_pause is None:
2705 dff5f600 Michael Hanselmann
    return _FS_UNAVAIL
2706 dff5f600 Michael Hanselmann
  else:
2707 dff5f600 Michael Hanselmann
    return ctx.watcher_pause
2708 dff5f600 Michael Hanselmann
2709 dff5f600 Michael Hanselmann
2710 dff5f600 Michael Hanselmann
def _BuildClusterFields():
2711 dff5f600 Michael Hanselmann
  """Builds list of fields for cluster information.
2712 dff5f600 Michael Hanselmann

2713 dff5f600 Michael Hanselmann
  """
2714 dff5f600 Michael Hanselmann
  fields = [
2715 dff5f600 Michael Hanselmann
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), CQ_CONFIG, 0,
2716 dff5f600 Michael Hanselmann
     lambda ctx, cluster: list(cluster.GetTags())),
2717 dff5f600 Michael Hanselmann
    (_MakeField("architecture", "ArchInfo", QFT_OTHER,
2718 dff5f600 Michael Hanselmann
                "Architecture information"), None, 0,
2719 dff5f600 Michael Hanselmann
     lambda ctx, _: runtime.GetArchInfo()),
2720 dff5f600 Michael Hanselmann
    (_MakeField("drain_flag", "QueueDrained", QFT_BOOL,
2721 dff5f600 Michael Hanselmann
                "Flag whether job queue is drained"), CQ_QUEUE_DRAINED, 0,
2722 dff5f600 Michael Hanselmann
     lambda ctx, _: ctx.drain_flag),
2723 dff5f600 Michael Hanselmann
    (_MakeField("watcher_pause", "WatcherPause", QFT_TIMESTAMP,
2724 dff5f600 Michael Hanselmann
                "Until when watcher is paused"), CQ_WATCHER_PAUSE, 0,
2725 dff5f600 Michael Hanselmann
     _ClusterWatcherPause),
2726 1c3231aa Thomas Thrainer
    (_MakeField("master_node", "Master", QFT_TEXT, "Master node name"),
2727 1c3231aa Thomas Thrainer
     CQ_CONFIG, QFF_HOSTNAME,
2728 1c3231aa Thomas Thrainer
     lambda ctx, cluster: _GetNodeName(ctx, None, cluster.master_node)),
2729 dff5f600 Michael Hanselmann
    ]
2730 dff5f600 Michael Hanselmann
2731 dff5f600 Michael Hanselmann
  # Simple fields
2732 dff5f600 Michael Hanselmann
  fields.extend([
2733 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), CQ_CONFIG, flags, _GetItemAttr(name))
2734 dff5f600 Michael Hanselmann
    for (name, (title, kind, flags, doc)) in _CLUSTER_SIMPLE_FIELDS.items()
2735 3c286190 Dimitris Aragiorgis
    ],)
2736 dff5f600 Michael Hanselmann
2737 dff5f600 Michael Hanselmann
  # Version fields
2738 dff5f600 Michael Hanselmann
  fields.extend([
2739 dff5f600 Michael Hanselmann
    (_MakeField(name, title, kind, doc), None, 0, _StaticValue(value))
2740 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, value, doc)) in _CLUSTER_VERSION_FIELDS.items()])
2741 dff5f600 Michael Hanselmann
2742 dff5f600 Michael Hanselmann
  # Add timestamps
2743 dff5f600 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(CQ_CONFIG))
2744 dff5f600 Michael Hanselmann
2745 dff5f600 Michael Hanselmann
  return _PrepareFieldList(fields, [
2746 3c286190 Dimitris Aragiorgis
    ("name", "cluster_name")])
2747 dff5f600 Michael Hanselmann
2748 dff5f600 Michael Hanselmann
2749 306bed0e Apollon Oikonomopoulos
class NetworkQueryData:
2750 306bed0e Apollon Oikonomopoulos
  """Data container for network data queries.
2751 306bed0e Apollon Oikonomopoulos

2752 306bed0e Apollon Oikonomopoulos
  """
2753 306bed0e Apollon Oikonomopoulos
  def __init__(self, networks, network_to_groups,
2754 306bed0e Apollon Oikonomopoulos
               network_to_instances, stats):
2755 306bed0e Apollon Oikonomopoulos
    """Initializes this class.
2756 306bed0e Apollon Oikonomopoulos

2757 306bed0e Apollon Oikonomopoulos
    @param networks: List of network objects
2758 306bed0e Apollon Oikonomopoulos
    @type network_to_groups: dict; network UUID as key
2759 306bed0e Apollon Oikonomopoulos
    @param network_to_groups: Per-network list of groups
2760 306bed0e Apollon Oikonomopoulos
    @type network_to_instances: dict; network UUID as key
2761 306bed0e Apollon Oikonomopoulos
    @param network_to_instances: Per-network list of instances
2762 306bed0e Apollon Oikonomopoulos
    @type stats: dict; network UUID as key
2763 306bed0e Apollon Oikonomopoulos
    @param stats: Per-network usage statistics
2764 306bed0e Apollon Oikonomopoulos

2765 306bed0e Apollon Oikonomopoulos
    """
2766 306bed0e Apollon Oikonomopoulos
    self.networks = networks
2767 306bed0e Apollon Oikonomopoulos
    self.network_to_groups = network_to_groups
2768 306bed0e Apollon Oikonomopoulos
    self.network_to_instances = network_to_instances
2769 306bed0e Apollon Oikonomopoulos
    self.stats = stats
2770 306bed0e Apollon Oikonomopoulos
2771 306bed0e Apollon Oikonomopoulos
  def __iter__(self):
2772 306bed0e Apollon Oikonomopoulos
    """Iterate over all networks.
2773 306bed0e Apollon Oikonomopoulos

2774 306bed0e Apollon Oikonomopoulos
    """
2775 306bed0e Apollon Oikonomopoulos
    for net in self.networks:
2776 306bed0e Apollon Oikonomopoulos
      if self.stats:
2777 306bed0e Apollon Oikonomopoulos
        self.curstats = self.stats.get(net.uuid, None)
2778 306bed0e Apollon Oikonomopoulos
      else:
2779 306bed0e Apollon Oikonomopoulos
        self.curstats = None
2780 306bed0e Apollon Oikonomopoulos
      yield net
2781 306bed0e Apollon Oikonomopoulos
2782 306bed0e Apollon Oikonomopoulos
2783 306bed0e Apollon Oikonomopoulos
_NETWORK_SIMPLE_FIELDS = {
2784 0b3f2215 Michael Hanselmann
  "name": ("Network", QFT_TEXT, 0, "Name"),
2785 0b3f2215 Michael Hanselmann
  "network": ("Subnet", QFT_TEXT, 0, "IPv4 subnet"),
2786 0b3f2215 Michael Hanselmann
  "gateway": ("Gateway", QFT_OTHER, 0, "IPv4 gateway"),
2787 0b3f2215 Michael Hanselmann
  "network6": ("IPv6Subnet", QFT_OTHER, 0, "IPv6 subnet"),
2788 0b3f2215 Michael Hanselmann
  "gateway6": ("IPv6Gateway", QFT_OTHER, 0, "IPv6 gateway"),
2789 0b3f2215 Michael Hanselmann
  "mac_prefix": ("MacPrefix", QFT_OTHER, 0, "MAC address prefix"),
2790 9675661c Dimitris Aragiorgis
  "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Network"),
2791 9675661c Dimitris Aragiorgis
  "uuid": ("UUID", QFT_TEXT, 0, "Network UUID"),
2792 306bed0e Apollon Oikonomopoulos
  }
2793 306bed0e Apollon Oikonomopoulos
2794 306bed0e Apollon Oikonomopoulos
2795 306bed0e Apollon Oikonomopoulos
_NETWORK_STATS_FIELDS = {
2796 0b3f2215 Michael Hanselmann
  "free_count": ("FreeCount", QFT_NUMBER, 0, "Number of available addresses"),
2797 0b3f2215 Michael Hanselmann
  "reserved_count":
2798 0b3f2215 Michael Hanselmann
    ("ReservedCount", QFT_NUMBER, 0, "Number of reserved addresses"),
2799 0b3f2215 Michael Hanselmann
  "map": ("Map", QFT_TEXT, 0, "Actual mapping"),
2800 0b3f2215 Michael Hanselmann
  "external_reservations":
2801 0b3f2215 Michael Hanselmann
    ("ExternalReservations", QFT_TEXT, 0, "External reservations"),
2802 306bed0e Apollon Oikonomopoulos
  }
2803 306bed0e Apollon Oikonomopoulos
2804 3c286190 Dimitris Aragiorgis
2805 83a14695 Helga Velroyen
def _GetNetworkStatsField(field, kind, ctx, _):
2806 306bed0e Apollon Oikonomopoulos
  """Gets the value of a "stats" field from L{NetworkQueryData}.
2807 306bed0e Apollon Oikonomopoulos

2808 306bed0e Apollon Oikonomopoulos
  @param field: Field name
2809 306bed0e Apollon Oikonomopoulos
  @param kind: Data kind, one of L{constants.QFT_ALL}
2810 306bed0e Apollon Oikonomopoulos
  @type ctx: L{NetworkQueryData}
2811 306bed0e Apollon Oikonomopoulos

2812 306bed0e Apollon Oikonomopoulos
  """
2813 b4600d4f Michael Hanselmann
  return _GetStatsField(field, kind, ctx.curstats)
2814 306bed0e Apollon Oikonomopoulos
2815 306bed0e Apollon Oikonomopoulos
2816 306bed0e Apollon Oikonomopoulos
def _BuildNetworkFields():
2817 306bed0e Apollon Oikonomopoulos
  """Builds list of fields for network queries.
2818 306bed0e Apollon Oikonomopoulos

2819 306bed0e Apollon Oikonomopoulos
  """
2820 306bed0e Apollon Oikonomopoulos
  fields = [
2821 8140e24f Dimitris Aragiorgis
    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
2822 8140e24f Dimitris Aragiorgis
     lambda ctx, inst: list(inst.GetTags())),
2823 8140e24f Dimitris Aragiorgis
    ]
2824 8140e24f Dimitris Aragiorgis
2825 8140e24f Dimitris Aragiorgis
  # Add simple fields
2826 8140e24f Dimitris Aragiorgis
  fields.extend([
2827 306bed0e Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc),
2828 40b118d3 Iustin Pop
     NETQ_CONFIG, 0, _GetItemMaybeAttr(name))
2829 3c286190 Dimitris Aragiorgis
     for (name, (title, kind, _, doc)) in _NETWORK_SIMPLE_FIELDS.items()])
2830 306bed0e Apollon Oikonomopoulos
2831 306bed0e Apollon Oikonomopoulos
  def _GetLength(getter):
2832 306bed0e Apollon Oikonomopoulos
    return lambda ctx, network: len(getter(ctx)[network.uuid])
2833 306bed0e Apollon Oikonomopoulos
2834 306bed0e Apollon Oikonomopoulos
  def _GetSortedList(getter):
2835 306bed0e Apollon Oikonomopoulos
    return lambda ctx, network: utils.NiceSort(getter(ctx)[network.uuid])
2836 306bed0e Apollon Oikonomopoulos
2837 306bed0e Apollon Oikonomopoulos
  network_to_groups = operator.attrgetter("network_to_groups")
2838 306bed0e Apollon Oikonomopoulos
  network_to_instances = operator.attrgetter("network_to_instances")
2839 306bed0e Apollon Oikonomopoulos
2840 306bed0e Apollon Oikonomopoulos
  # Add fields for node groups
2841 306bed0e Apollon Oikonomopoulos
  fields.extend([
2842 306bed0e Apollon Oikonomopoulos
    (_MakeField("group_cnt", "NodeGroups", QFT_NUMBER, "Number of nodegroups"),
2843 306bed0e Apollon Oikonomopoulos
     NETQ_GROUP, 0, _GetLength(network_to_groups)),
2844 503574ec Michael Hanselmann
    (_MakeField("group_list", "GroupList", QFT_OTHER,
2845 503574ec Michael Hanselmann
     "List of nodegroups (group name, NIC mode, NIC link)"),
2846 503574ec Michael Hanselmann
     NETQ_GROUP, 0, lambda ctx, network: network_to_groups(ctx)[network.uuid]),
2847 306bed0e Apollon Oikonomopoulos
    ])
2848 306bed0e Apollon Oikonomopoulos
2849 306bed0e Apollon Oikonomopoulos
  # Add fields for instances
2850 306bed0e Apollon Oikonomopoulos
  fields.extend([
2851 306bed0e Apollon Oikonomopoulos
    (_MakeField("inst_cnt", "Instances", QFT_NUMBER, "Number of instances"),
2852 306bed0e Apollon Oikonomopoulos
     NETQ_INST, 0, _GetLength(network_to_instances)),
2853 306bed0e Apollon Oikonomopoulos
    (_MakeField("inst_list", "InstanceList", QFT_OTHER, "List of instances"),
2854 306bed0e Apollon Oikonomopoulos
     NETQ_INST, 0, _GetSortedList(network_to_instances)),
2855 306bed0e Apollon Oikonomopoulos
    ])
2856 306bed0e Apollon Oikonomopoulos
2857 306bed0e Apollon Oikonomopoulos
  # Add fields for usage statistics
2858 306bed0e Apollon Oikonomopoulos
  fields.extend([
2859 306bed0e Apollon Oikonomopoulos
    (_MakeField(name, title, kind, doc), NETQ_STATS, 0,
2860 e0e44476 Michele Tartara
     compat.partial(_GetNetworkStatsField, name, kind))
2861 3c286190 Dimitris Aragiorgis
    for (name, (title, kind, _, doc)) in _NETWORK_STATS_FIELDS.items()])
2862 306bed0e Apollon Oikonomopoulos
2863 22ff02a7 Christos Stavrakakis
  # Add timestamps
2864 22ff02a7 Christos Stavrakakis
  fields.extend(_GetItemTimestampFields(IQ_NETWORKS))
2865 22ff02a7 Christos Stavrakakis
2866 306bed0e Apollon Oikonomopoulos
  return _PrepareFieldList(fields, [])
2867 306bed0e Apollon Oikonomopoulos
2868 dff5f600 Michael Hanselmann
#: Fields for cluster information
2869 dff5f600 Michael Hanselmann
CLUSTER_FIELDS = _BuildClusterFields()
2870 dff5f600 Michael Hanselmann
2871 8235fe04 Michael Hanselmann
#: Fields available for node queries
2872 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
2873 1c8addc6 Michael Hanselmann
2874 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
2875 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
2876 24d16f76 Michael Hanselmann
2877 24d16f76 Michael Hanselmann
#: Fields available for lock queries
2878 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
2879 e571ee44 Adeodato Simo
2880 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
2881 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
2882 8e21cfc0 Adeodato Simo
2883 be3a4b14 Michael Hanselmann
#: Fields available for operating system queries
2884 be3a4b14 Michael Hanselmann
OS_FIELDS = _BuildOsFields()
2885 be3a4b14 Michael Hanselmann
2886 b954f097 Constantinos Venetsanopoulos
#: Fields available for extstorage provider queries
2887 b954f097 Constantinos Venetsanopoulos
EXTSTORAGE_FIELDS = _BuildExtStorageFields()
2888 b954f097 Constantinos Venetsanopoulos
2889 9665bb3a Michael Hanselmann
#: Fields available for job queries
2890 9665bb3a Michael Hanselmann
JOB_FIELDS = _BuildJobFields()
2891 9665bb3a Michael Hanselmann
2892 0fdf247d Michael Hanselmann
#: Fields available for exports
2893 0fdf247d Michael Hanselmann
EXPORT_FIELDS = _BuildExportFields()
2894 0fdf247d Michael Hanselmann
2895 306bed0e Apollon Oikonomopoulos
#: Fields available for network queries
2896 306bed0e Apollon Oikonomopoulos
NETWORK_FIELDS = _BuildNetworkFields()
2897 306bed0e Apollon Oikonomopoulos
2898 95eb4188 Michael Hanselmann
#: All available resources
2899 95eb4188 Michael Hanselmann
ALL_FIELDS = {
2900 dff5f600 Michael Hanselmann
  constants.QR_CLUSTER: CLUSTER_FIELDS,
2901 95eb4188 Michael Hanselmann
  constants.QR_INSTANCE: INSTANCE_FIELDS,
2902 95eb4188 Michael Hanselmann
  constants.QR_NODE: NODE_FIELDS,
2903 95eb4188 Michael Hanselmann
  constants.QR_LOCK: LOCK_FIELDS,
2904 95eb4188 Michael Hanselmann
  constants.QR_GROUP: GROUP_FIELDS,
2905 be3a4b14 Michael Hanselmann
  constants.QR_OS: OS_FIELDS,
2906 b954f097 Constantinos Venetsanopoulos
  constants.QR_EXTSTORAGE: EXTSTORAGE_FIELDS,
2907 9665bb3a Michael Hanselmann
  constants.QR_JOB: JOB_FIELDS,
2908 0fdf247d Michael Hanselmann
  constants.QR_EXPORT: EXPORT_FIELDS,
2909 306bed0e Apollon Oikonomopoulos
  constants.QR_NETWORK: NETWORK_FIELDS,
2910 95eb4188 Michael Hanselmann
  }
2911 95eb4188 Michael Hanselmann
2912 e571ee44 Adeodato Simo
#: All available field lists
2913 95eb4188 Michael Hanselmann
ALL_FIELD_LISTS = ALL_FIELDS.values()