Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 61e062dd

History | View | Annotate | Download (77.4 kB)

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

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

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

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

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

158 4ca96421 Michael Hanselmann
  """
159 e2d188cc Iustin Pop
  return _FS_UNKNOWN
160 4ca96421 Michael Hanselmann
161 4ca96421 Michael Hanselmann
162 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
163 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
164 4ca96421 Michael Hanselmann

165 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
166 4ca96421 Michael Hanselmann

167 4ca96421 Michael Hanselmann
  @type fielddefs: dict
168 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
169 4ca96421 Michael Hanselmann
  @type selected: list of strings
170 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
171 4ca96421 Michael Hanselmann

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

192 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
193 4ca96421 Michael Hanselmann

194 4ca96421 Michael Hanselmann
  """
195 111bf531 Michael Hanselmann
  return [fdef for (fdef, _, _, _) in fielddefs]
196 4ca96421 Michael Hanselmann
197 4ca96421 Michael Hanselmann
198 fb0be379 Michael Hanselmann
class _FilterHints:
199 fb0be379 Michael Hanselmann
  """Class for filter analytics.
200 fb0be379 Michael Hanselmann

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

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

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

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

221 fb0be379 Michael Hanselmann
  """
222 fb0be379 Michael Hanselmann
  def __init__(self, namefield):
223 fb0be379 Michael Hanselmann
    """Initializes this class.
224 fb0be379 Michael Hanselmann

225 fb0be379 Michael Hanselmann
    @type namefield: string
226 fb0be379 Michael Hanselmann
    @param namefield: Field caller is interested in
227 fb0be379 Michael Hanselmann

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

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

247 fb0be379 Michael Hanselmann
    @rtype: list
248 fb0be379 Michael Hanselmann

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

258 fb0be379 Michael Hanselmann
    """
259 fb0be379 Michael Hanselmann
    return frozenset(self._datakinds)
260 fb0be379 Michael Hanselmann
261 fb0be379 Michael Hanselmann
  def _NeedAllNames(self):
262 fb0be379 Michael Hanselmann
    """Changes internal state to request all names.
263 fb0be379 Michael Hanselmann

264 fb0be379 Michael Hanselmann
    """
265 fb0be379 Michael Hanselmann
    self._allnames = True
266 fb0be379 Michael Hanselmann
    self._names = None
267 fb0be379 Michael Hanselmann
268 fb0be379 Michael Hanselmann
  def NoteLogicOp(self, op):
269 fb0be379 Michael Hanselmann
    """Called when handling a logic operation.
270 fb0be379 Michael Hanselmann

271 fb0be379 Michael Hanselmann
    @type op: string
272 fb0be379 Michael Hanselmann
    @param op: Operator
273 fb0be379 Michael Hanselmann

274 fb0be379 Michael Hanselmann
    """
275 fb0be379 Michael Hanselmann
    if op != qlang.OP_OR:
276 fb0be379 Michael Hanselmann
      self._NeedAllNames()
277 fb0be379 Michael Hanselmann
278 52aa1efa Michael Hanselmann
  def NoteUnaryOp(self, op, datakind): # pylint: disable=W0613
279 fb0be379 Michael Hanselmann
    """Called when handling an unary operation.
280 fb0be379 Michael Hanselmann

281 fb0be379 Michael Hanselmann
    @type op: string
282 fb0be379 Michael Hanselmann
    @param op: Operator
283 fb0be379 Michael Hanselmann

284 fb0be379 Michael Hanselmann
    """
285 52aa1efa Michael Hanselmann
    if datakind is not None:
286 52aa1efa Michael Hanselmann
      self._datakinds.add(datakind)
287 52aa1efa Michael Hanselmann
288 fb0be379 Michael Hanselmann
    self._NeedAllNames()
289 fb0be379 Michael Hanselmann
290 fb0be379 Michael Hanselmann
  def NoteBinaryOp(self, op, datakind, name, value):
291 fb0be379 Michael Hanselmann
    """Called when handling a binary operation.
292 fb0be379 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

644 fb0be379 Michael Hanselmann
  See L{_FilterCompilerHelper} for details.
645 fb0be379 Michael Hanselmann

646 fb0be379 Michael Hanselmann
  @rtype: callable
647 fb0be379 Michael Hanselmann

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

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

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

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

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

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

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

710 4ca96421 Michael Hanselmann
    @rtype: frozenset
711 4ca96421 Michael Hanselmann

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

720 4ca96421 Michael Hanselmann
    Includes unknown fields.
721 4ca96421 Michael Hanselmann

722 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
723 4ca96421 Michael Hanselmann

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

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

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

775 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
776 4ca96421 Michael Hanselmann

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

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

808 4ca96421 Michael Hanselmann
  @type fields: list
809 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
810 4ca96421 Michael Hanselmann
  @type row: list of tuples
811 4ca96421 Michael Hanselmann
  @param row: Row data
812 4ca96421 Michael Hanselmann

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

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

846 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
847 4ca96421 Michael Hanselmann

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

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

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

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

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

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

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

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

932 dff5f600 Michael Hanselmann
  """
933 dff5f600 Michael Hanselmann
  return value
934 dff5f600 Michael Hanselmann
935 dff5f600 Michael Hanselmann
936 dff5f600 Michael Hanselmann
def _StaticValue(value):
937 dff5f600 Michael Hanselmann
  """Prepares a function to return a static value.
938 dff5f600 Michael Hanselmann

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

946 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
947 8235fe04 Michael Hanselmann
  @param node: Node object
948 8235fe04 Michael Hanselmann
  @type master_name: string
949 8235fe04 Michael Hanselmann
  @param master_name: Master node name
950 8235fe04 Michael Hanselmann

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

967 8235fe04 Michael Hanselmann
  @param attr: Attribute name
968 8235fe04 Michael Hanselmann

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

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

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

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

1007 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1008 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1009 425e5bf0 Michael Hanselmann

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

1025 425e5bf0 Michael Hanselmann
  @param convert: Conversion function receiving value as single parameter
1026 425e5bf0 Michael Hanselmann
  @param fn: Retrieval function
1027 425e5bf0 Michael Hanselmann

1028 425e5bf0 Michael Hanselmann
  """
1029 425e5bf0 Michael Hanselmann
  return compat.partial(_ConvWrapInner, convert, fn)
1030 425e5bf0 Michael Hanselmann
1031 425e5bf0 Michael Hanselmann
1032 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
1033 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
1034 145bea54 Michael Hanselmann

1035 145bea54 Michael Hanselmann
  @type getter: callable
1036 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
1037 145bea54 Michael Hanselmann

1038 145bea54 Michael Hanselmann
  """
1039 145bea54 Michael Hanselmann
  def fn(_, item):
1040 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
1041 145bea54 Michael Hanselmann

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

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

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

1070 8235fe04 Michael Hanselmann
  """
1071 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
1072 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
1073 8235fe04 Michael Hanselmann
    """Initializes this class.
1074 8235fe04 Michael Hanselmann

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

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

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

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

1154 8572f1fe René Nussbaumer
  """
1155 8572f1fe René Nussbaumer
  def fn(ctx, node):
1156 8572f1fe René Nussbaumer
    """Get group data for a node.
1157 8572f1fe René Nussbaumer

1158 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
1159 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
1160 8572f1fe René Nussbaumer
    @param inst: Node object
1161 8572f1fe René Nussbaumer

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

1176 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1177 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
1178 8235fe04 Michael Hanselmann
  @param node: Node object
1179 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1180 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1181 8235fe04 Michael Hanselmann

1182 8235fe04 Michael Hanselmann
  """
1183 e2d188cc Iustin Pop
  return ng.name
1184 8235fe04 Michael Hanselmann
1185 8235fe04 Michael Hanselmann
1186 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
1187 52b5d286 René Nussbaumer
  """Returns the node powered state
1188 52b5d286 René Nussbaumer

1189 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
1190 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
1191 52b5d286 René Nussbaumer
  @param node: Node object
1192 52b5d286 René Nussbaumer

1193 52b5d286 René Nussbaumer
  """
1194 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
1195 e2d188cc Iustin Pop
    return node.powered
1196 52b5d286 René Nussbaumer
1197 e2d188cc Iustin Pop
  return _FS_UNAVAIL
1198 52b5d286 René Nussbaumer
1199 52b5d286 René Nussbaumer
1200 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
1201 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
1202 8572f1fe René Nussbaumer

1203 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
1204 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
1205 8572f1fe René Nussbaumer
  @param node: Node object
1206 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
1207 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
1208 8572f1fe René Nussbaumer

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

1216 8235fe04 Michael Hanselmann
  @param field: Live field name
1217 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
1218 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
1219 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
1220 a6070ef7 Michael Hanselmann
  @param node: Node object
1221 8235fe04 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

1444 1c8addc6 Michael Hanselmann
  @type name: string
1445 1c8addc6 Michael Hanselmann
  @param name: Live data field name
1446 1c8addc6 Michael Hanselmann

1447 1c8addc6 Michael Hanselmann
  """
1448 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1449 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
1450 1c8addc6 Michael Hanselmann

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

1455 1c8addc6 Michael Hanselmann
    """
1456 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
1457 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
1458 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
1459 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
1460 e2d188cc Iustin Pop
      return _FS_NODATA
1461 1c8addc6 Michael Hanselmann
1462 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
1463 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
1464 1c8addc6 Michael Hanselmann
      if name in data:
1465 e2d188cc Iustin Pop
        return data[name]
1466 1c8addc6 Michael Hanselmann
1467 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1468 1c8addc6 Michael Hanselmann
1469 1c8addc6 Michael Hanselmann
  return fn
1470 1c8addc6 Michael Hanselmann
1471 1c8addc6 Michael Hanselmann
1472 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
1473 1c8addc6 Michael Hanselmann
  """Get instance status.
1474 1c8addc6 Michael Hanselmann

1475 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1476 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1477 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1478 1c8addc6 Michael Hanselmann

1479 1c8addc6 Michael Hanselmann
  """
1480 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
1481 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEOFFLINE
1482 1c8addc6 Michael Hanselmann
1483 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
1484 61a980a9 Michael Hanselmann
    return constants.INSTST_NODEDOWN
1485 1c8addc6 Michael Hanselmann
1486 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
1487 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
1488 61a980a9 Michael Hanselmann
      return constants.INSTST_WRONGNODE
1489 2e04d454 Agata Murawska
    elif inst.admin_state == constants.ADMINST_UP:
1490 61a980a9 Michael Hanselmann
      return constants.INSTST_RUNNING
1491 1c8addc6 Michael Hanselmann
    else:
1492 61a980a9 Michael Hanselmann
      return constants.INSTST_ERRORUP
1493 1c8addc6 Michael Hanselmann
1494 2e04d454 Agata Murawska
  if inst.admin_state == constants.ADMINST_UP:
1495 61a980a9 Michael Hanselmann
    return constants.INSTST_ERRORDOWN
1496 2e04d454 Agata Murawska
  elif inst.admin_state == constants.ADMINST_DOWN:
1497 2e04d454 Agata Murawska
    return constants.INSTST_ADMINDOWN
1498 1c8addc6 Michael Hanselmann
1499 2e04d454 Agata Murawska
  return constants.INSTST_ADMINOFFLINE
1500 1c8addc6 Michael Hanselmann
1501 1c8addc6 Michael Hanselmann
1502 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
1503 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
1504 1c8addc6 Michael Hanselmann

1505 1c8addc6 Michael Hanselmann
  @type index: int
1506 1c8addc6 Michael Hanselmann
  @param index: Disk index
1507 1c8addc6 Michael Hanselmann

1508 1c8addc6 Michael Hanselmann
  """
1509 1c8addc6 Michael Hanselmann
  def fn(_, inst):
1510 1c8addc6 Michael Hanselmann
    """Get size of a disk.
1511 1c8addc6 Michael Hanselmann

1512 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1513 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1514 1c8addc6 Michael Hanselmann

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

1527 1c8addc6 Michael Hanselmann
  @type index: int
1528 1c8addc6 Michael Hanselmann
  @param index: NIC index
1529 1c8addc6 Michael Hanselmann
  @type cb: callable
1530 1c8addc6 Michael Hanselmann
  @param cb: Callback
1531 1c8addc6 Michael Hanselmann

1532 1c8addc6 Michael Hanselmann
  """
1533 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
1534 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
1535 1c8addc6 Michael Hanselmann

1536 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1537 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1538 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1539 1c8addc6 Michael Hanselmann

1540 1c8addc6 Michael Hanselmann
    """
1541 1c8addc6 Michael Hanselmann
    try:
1542 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
1543 1c8addc6 Michael Hanselmann
    except IndexError:
1544 e2d188cc Iustin Pop
      return _FS_UNAVAIL
1545 1c8addc6 Michael Hanselmann
1546 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
1547 1c8addc6 Michael Hanselmann
1548 1c8addc6 Michael Hanselmann
  return fn
1549 1c8addc6 Michael Hanselmann
1550 1c8addc6 Michael Hanselmann
1551 d4117a72 Apollon Oikonomopoulos
def _GetInstNicNetwork(ctx, _, nic): # pylint: disable=W0613
1552 d4117a72 Apollon Oikonomopoulos
  """Get a NIC's Network.
1553 d4117a72 Apollon Oikonomopoulos

1554 d4117a72 Apollon Oikonomopoulos
  @type ctx: L{InstanceQueryData}
1555 d4117a72 Apollon Oikonomopoulos
  @type nic: L{objects.NIC}
1556 d4117a72 Apollon Oikonomopoulos
  @param nic: NIC object
1557 d4117a72 Apollon Oikonomopoulos

1558 d4117a72 Apollon Oikonomopoulos
  """
1559 d4117a72 Apollon Oikonomopoulos
  if nic.network is None:
1560 d4117a72 Apollon Oikonomopoulos
    return _FS_UNAVAIL
1561 d4117a72 Apollon Oikonomopoulos
  else:
1562 d4117a72 Apollon Oikonomopoulos
    return nic.network
1563 d4117a72 Apollon Oikonomopoulos
1564 d4117a72 Apollon Oikonomopoulos
1565 b459a848 Andrea Spadaccini
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
1566 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
1567 1c8addc6 Michael Hanselmann

1568 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1569 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
1570 1c8addc6 Michael Hanselmann
  @param nic: NIC object
1571 1c8addc6 Michael Hanselmann

1572 1c8addc6 Michael Hanselmann
  """
1573 1c8addc6 Michael Hanselmann
  if nic.ip is None:
1574 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1575 1c8addc6 Michael Hanselmann
  else:
1576 e2d188cc Iustin Pop
    return nic.ip
1577 1c8addc6 Michael Hanselmann
1578 1c8addc6 Michael Hanselmann
1579 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
1580 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
1581 1c8addc6 Michael Hanselmann

1582 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1583 1c8addc6 Michael Hanselmann
  @type index: int
1584 1c8addc6 Michael Hanselmann
  @param index: NIC index
1585 1c8addc6 Michael Hanselmann

1586 1c8addc6 Michael Hanselmann
  """
1587 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
1588 1c8addc6 Michael Hanselmann
1589 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
1590 1c8addc6 Michael Hanselmann
1591 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1592 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
1593 1c8addc6 Michael Hanselmann
  else:
1594 e2d188cc Iustin Pop
    return _FS_UNAVAIL
1595 1c8addc6 Michael Hanselmann
1596 1c8addc6 Michael Hanselmann
1597 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
1598 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
1599 1c8addc6 Michael Hanselmann

1600 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1601 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1602 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1603 1c8addc6 Michael Hanselmann

1604 1c8addc6 Michael Hanselmann
  """
1605 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
1606 1c8addc6 Michael Hanselmann
1607 1c8addc6 Michael Hanselmann
  result = []
1608 1c8addc6 Michael Hanselmann
1609 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
1610 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1611 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
1612 1c8addc6 Michael Hanselmann
    else:
1613 1c8addc6 Michael Hanselmann
      result.append(None)
1614 1c8addc6 Michael Hanselmann
1615 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
1616 1c8addc6 Michael Hanselmann
1617 e2d188cc Iustin Pop
  return result
1618 1c8addc6 Michael Hanselmann
1619 1c8addc6 Michael Hanselmann
1620 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
1621 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
1622 1c8addc6 Michael Hanselmann

1623 1c8addc6 Michael Hanselmann
  @type name: string
1624 1c8addc6 Michael Hanselmann
  @param name: Parameter name
1625 1c8addc6 Michael Hanselmann

1626 1c8addc6 Michael Hanselmann
  """
1627 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
1628 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
1629 1c8addc6 Michael Hanselmann

1630 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
1631 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
1632 1c8addc6 Michael Hanselmann
    @param inst: Instance object
1633 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
1634 1c8addc6 Michael Hanselmann
    @param nic: NIC object
1635 1c8addc6 Michael Hanselmann

1636 1c8addc6 Michael Hanselmann
    """
1637 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
1638 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
1639 1c8addc6 Michael Hanselmann
1640 1c8addc6 Michael Hanselmann
  return fn
1641 1c8addc6 Michael Hanselmann
1642 1c8addc6 Michael Hanselmann
1643 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
1644 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
1645 1c8addc6 Michael Hanselmann

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

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

1721 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1722 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
1723 1c8addc6 Michael Hanselmann
  @param inst: Instance object
1724 1c8addc6 Michael Hanselmann

1725 1c8addc6 Michael Hanselmann
  """
1726 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
1727 1c8addc6 Michael Hanselmann
1728 1c8addc6 Michael Hanselmann
  if usage is None:
1729 1c8addc6 Michael Hanselmann
    usage = 0
1730 1c8addc6 Michael Hanselmann
1731 e2d188cc Iustin Pop
  return usage
1732 1c8addc6 Michael Hanselmann
1733 1c8addc6 Michael Hanselmann
1734 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1735 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1736 5d28cb6f Michael Hanselmann

1737 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1738 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1739 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1740 5d28cb6f Michael Hanselmann

1741 5d28cb6f Michael Hanselmann
  """
1742 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1743 5d28cb6f Michael Hanselmann
1744 5d28cb6f Michael Hanselmann
  if consinfo is None:
1745 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1746 5d28cb6f Michael Hanselmann
1747 5d28cb6f Michael Hanselmann
  return consinfo
1748 5d28cb6f Michael Hanselmann
1749 5d28cb6f Michael Hanselmann
1750 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1751 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1752 1c8addc6 Michael Hanselmann

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

1755 1c8addc6 Michael Hanselmann
  """
1756 1c8addc6 Michael Hanselmann
  fields = [
1757 79b2ca83 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT,
1758 79b2ca83 Michael Hanselmann
                "Total disk space used by instance on each of its nodes;"
1759 79b2ca83 Michael Hanselmann
                " this is not the disk size visible to the instance, but"
1760 79b2ca83 Michael Hanselmann
                " the usage on the node"),
1761 111bf531 Michael Hanselmann
     IQ_DISKUSAGE, 0, _GetInstDiskUsage),
1762 79b2ca83 Michael Hanselmann
    (_MakeField("disk.count", "Disks", QFT_NUMBER, "Number of disks"),
1763 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: len(inst.disks)),
1764 79b2ca83 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER, "List of disk sizes"),
1765 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, lambda ctx, inst: [disk.size for disk in inst.disks]),
1766 1c8addc6 Michael Hanselmann
    ]
1767 1c8addc6 Michael Hanselmann
1768 1c8addc6 Michael Hanselmann
  # Disks by number
1769 1c8addc6 Michael Hanselmann
  fields.extend([
1770 79b2ca83 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
1771 79b2ca83 Michael Hanselmann
                "Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
1772 111bf531 Michael Hanselmann
     IQ_CONFIG, 0, _GetInstDiskSize(i))
1773 3c286190 Dimitris Aragiorgis
    for i in range(constants.MAX_DISKS)])
1774 1c8addc6 Michael Hanselmann
1775 1c8addc6 Michael Hanselmann
  return fields
1776 1c8addc6 Michael Hanselmann
1777 1c8addc6 Michael Hanselmann
1778 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1779 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1780 1c8addc6 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2445 306bed0e Apollon Oikonomopoulos
  """
2446 306bed0e Apollon Oikonomopoulos
  def __init__(self, networks, network_to_groups,
2447 306bed0e Apollon Oikonomopoulos
               network_to_instances, stats):
2448 306bed0e Apollon Oikonomopoulos
    """Initializes this class.
2449 306bed0e Apollon Oikonomopoulos

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

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

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

2502 306bed0e Apollon Oikonomopoulos
  @param field: Field name
2503 306bed0e Apollon Oikonomopoulos
  @param kind: Data kind, one of L{constants.QFT_ALL}
2504 306bed0e Apollon Oikonomopoulos
  @type ctx: L{NetworkQueryData}
2505 306bed0e Apollon Oikonomopoulos

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

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