Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ d1b1deb4

History | View | Annotate | Download (34.3 kB)

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

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

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

47 8f8ce6d1 Michael Hanselmann
@attention: Retrieval functions must be idempotent. They can be called multiple
48 8f8ce6d1 Michael Hanselmann
  times, in any order and any number of times. This is important to keep in
49 8f8ce6d1 Michael Hanselmann
  mind for implementing filters in the future.
50 8f8ce6d1 Michael Hanselmann

51 8f8ce6d1 Michael Hanselmann
"""
52 4ca96421 Michael Hanselmann
53 8235fe04 Michael Hanselmann
import logging
54 4ca96421 Michael Hanselmann
import operator
55 4ca96421 Michael Hanselmann
import re
56 4ca96421 Michael Hanselmann
57 4ca96421 Michael Hanselmann
from ganeti import constants
58 4ca96421 Michael Hanselmann
from ganeti import errors
59 4ca96421 Michael Hanselmann
from ganeti import utils
60 4ca96421 Michael Hanselmann
from ganeti import compat
61 4ca96421 Michael Hanselmann
from ganeti import objects
62 4ca96421 Michael Hanselmann
from ganeti import ht
63 4ca96421 Michael Hanselmann
64 82599b3e Iustin Pop
from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
65 82599b3e Iustin Pop
                              QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER,
66 cfb084ae René Nussbaumer
                              RS_NORMAL, RS_UNKNOWN, RS_NODATA,
67 cfb084ae René Nussbaumer
                              RS_UNAVAIL, RS_OFFLINE)
68 82599b3e Iustin Pop
69 4ca96421 Michael Hanselmann
70 8f8ce6d1 Michael Hanselmann
# Constants for requesting data from the caller/data provider. Each property
71 8f8ce6d1 Michael Hanselmann
# collected/computed separately by the data provider should have its own to
72 8f8ce6d1 Michael Hanselmann
# only collect the requested data and not more.
73 8f8ce6d1 Michael Hanselmann
74 8235fe04 Michael Hanselmann
(NQ_CONFIG,
75 8235fe04 Michael Hanselmann
 NQ_INST,
76 8235fe04 Michael Hanselmann
 NQ_LIVE,
77 52b5d286 René Nussbaumer
 NQ_GROUP,
78 52b5d286 René Nussbaumer
 NQ_OOB) = range(1, 6)
79 8235fe04 Michael Hanselmann
80 1c8addc6 Michael Hanselmann
(IQ_CONFIG,
81 1c8addc6 Michael Hanselmann
 IQ_LIVE,
82 1c8addc6 Michael Hanselmann
 IQ_DISKUSAGE) = range(100, 103)
83 1c8addc6 Michael Hanselmann
84 24d16f76 Michael Hanselmann
(LQ_MODE,
85 24d16f76 Michael Hanselmann
 LQ_OWNER,
86 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
87 8235fe04 Michael Hanselmann
88 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
89 8e21cfc0 Adeodato Simo
 GQ_NODE,
90 8e21cfc0 Adeodato Simo
 GQ_INST) = range(200, 203)
91 8e21cfc0 Adeodato Simo
92 8e21cfc0 Adeodato Simo
93 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
94 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
95 4ca96421 Michael Hanselmann
96 4ca96421 Michael Hanselmann
#: Verification function for each field type
97 4ca96421 Michael Hanselmann
_VERIFY_FN = {
98 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
99 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
100 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
101 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
102 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
103 82599b3e Iustin Pop
  QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat),
104 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
105 4ca96421 Michael Hanselmann
  }
106 4ca96421 Michael Hanselmann
107 e2d188cc Iustin Pop
# Unique objects for special field statuses
108 e2d188cc Iustin Pop
_FS_UNKNOWN = object()
109 e2d188cc Iustin Pop
_FS_NODATA = object()
110 e2d188cc Iustin Pop
_FS_UNAVAIL = object()
111 e2d188cc Iustin Pop
_FS_OFFLINE = object()
112 e2d188cc Iustin Pop
113 af58707c Iustin Pop
#: VType to QFT mapping
114 af58707c Iustin Pop
_VTToQFT = {
115 af58707c Iustin Pop
  # TODO: fix validation of empty strings
116 af58707c Iustin Pop
  constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty
117 af58707c Iustin Pop
  constants.VTYPE_MAYBE_STRING: QFT_OTHER,
118 af58707c Iustin Pop
  constants.VTYPE_BOOL: QFT_BOOL,
119 af58707c Iustin Pop
  constants.VTYPE_SIZE: QFT_UNIT,
120 af58707c Iustin Pop
  constants.VTYPE_INT: QFT_NUMBER,
121 af58707c Iustin Pop
  }
122 af58707c Iustin Pop
123 4ca96421 Michael Hanselmann
124 4ca96421 Michael Hanselmann
def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
125 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
126 4ca96421 Michael Hanselmann

127 4ca96421 Michael Hanselmann
  """
128 e2d188cc Iustin Pop
  return _FS_UNKNOWN
129 4ca96421 Michael Hanselmann
130 4ca96421 Michael Hanselmann
131 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
132 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
133 4ca96421 Michael Hanselmann

134 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
135 4ca96421 Michael Hanselmann

136 4ca96421 Michael Hanselmann
  @type fielddefs: dict
137 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
138 4ca96421 Michael Hanselmann
  @type selected: list of strings
139 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
140 4ca96421 Michael Hanselmann

141 4ca96421 Michael Hanselmann
  """
142 4ca96421 Michael Hanselmann
  result = []
143 4ca96421 Michael Hanselmann
144 4ca96421 Michael Hanselmann
  for name in selected:
145 4ca96421 Michael Hanselmann
    try:
146 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
147 4ca96421 Michael Hanselmann
    except KeyError:
148 82599b3e Iustin Pop
      fdef = (_MakeField(name, name, QFT_UNKNOWN), None, _GetUnknownField)
149 4ca96421 Michael Hanselmann
150 4ca96421 Michael Hanselmann
    assert len(fdef) == 3
151 4ca96421 Michael Hanselmann
152 4ca96421 Michael Hanselmann
    result.append(fdef)
153 4ca96421 Michael Hanselmann
154 4ca96421 Michael Hanselmann
  return result
155 4ca96421 Michael Hanselmann
156 4ca96421 Michael Hanselmann
157 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
158 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
159 4ca96421 Michael Hanselmann

160 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
161 4ca96421 Michael Hanselmann

162 4ca96421 Michael Hanselmann
  """
163 4ca96421 Michael Hanselmann
  return [fdef for (fdef, _, _) in fielddefs]
164 4ca96421 Michael Hanselmann
165 4ca96421 Michael Hanselmann
166 4ca96421 Michael Hanselmann
class Query:
167 4ca96421 Michael Hanselmann
  def __init__(self, fieldlist, selected):
168 4ca96421 Michael Hanselmann
    """Initializes this class.
169 4ca96421 Michael Hanselmann

170 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
171 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
172 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
173 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
174 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
175 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
176 4ca96421 Michael Hanselmann

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

180 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
181 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
182 4ca96421 Michael Hanselmann
    @type selected: list of strings
183 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
184 4ca96421 Michael Hanselmann

185 4ca96421 Michael Hanselmann
    """
186 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
187 4ca96421 Michael Hanselmann
188 4ca96421 Michael Hanselmann
  def RequestedData(self):
189 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
190 4ca96421 Michael Hanselmann

191 4ca96421 Michael Hanselmann
    @rtype: frozenset
192 4ca96421 Michael Hanselmann

193 4ca96421 Michael Hanselmann
    """
194 4ca96421 Michael Hanselmann
    return frozenset(datakind
195 4ca96421 Michael Hanselmann
                     for (_, datakind, _) in self._fields
196 4ca96421 Michael Hanselmann
                     if datakind is not None)
197 4ca96421 Michael Hanselmann
198 4ca96421 Michael Hanselmann
  def GetFields(self):
199 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
200 4ca96421 Michael Hanselmann

201 4ca96421 Michael Hanselmann
    Includes unknown fields.
202 4ca96421 Michael Hanselmann

203 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
204 4ca96421 Michael Hanselmann

205 4ca96421 Michael Hanselmann
    """
206 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
207 4ca96421 Michael Hanselmann
208 4ca96421 Michael Hanselmann
  def Query(self, ctx):
209 4ca96421 Michael Hanselmann
    """Execute a query.
210 4ca96421 Michael Hanselmann

211 4ca96421 Michael Hanselmann
    @param ctx: Data container passed to field retrieval functions, must
212 4ca96421 Michael Hanselmann
      support iteration using C{__iter__}
213 4ca96421 Michael Hanselmann

214 4ca96421 Michael Hanselmann
    """
215 e2d188cc Iustin Pop
    result = [[_ProcessResult(fn(ctx, item)) for (_, _, fn) in self._fields]
216 4ca96421 Michael Hanselmann
              for item in ctx]
217 4ca96421 Michael Hanselmann
218 4ca96421 Michael Hanselmann
    # Verify result
219 4ca96421 Michael Hanselmann
    if __debug__:
220 d1c3c3b3 Iustin Pop
      for row in result:
221 d1c3c3b3 Iustin Pop
        _VerifyResultRow(self._fields, row)
222 4ca96421 Michael Hanselmann
223 4ca96421 Michael Hanselmann
    return result
224 4ca96421 Michael Hanselmann
225 4ca96421 Michael Hanselmann
  def OldStyleQuery(self, ctx):
226 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
227 4ca96421 Michael Hanselmann

228 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
229 4ca96421 Michael Hanselmann

230 4ca96421 Michael Hanselmann
    """
231 4ca96421 Michael Hanselmann
    unknown = set(fdef.name
232 82599b3e Iustin Pop
                  for (fdef, _, _) in self._fields if fdef.kind == QFT_UNKNOWN)
233 4ca96421 Michael Hanselmann
    if unknown:
234 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
235 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
236 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
237 4ca96421 Michael Hanselmann
238 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
239 4ca96421 Michael Hanselmann
            for row in self.Query(ctx)]
240 4ca96421 Michael Hanselmann
241 4ca96421 Michael Hanselmann
242 e2d188cc Iustin Pop
def _ProcessResult(value):
243 e2d188cc Iustin Pop
  """Converts result values into externally-visible ones.
244 e2d188cc Iustin Pop

245 e2d188cc Iustin Pop
  """
246 e2d188cc Iustin Pop
  if value is _FS_UNKNOWN:
247 cfb084ae René Nussbaumer
    return (RS_UNKNOWN, None)
248 e2d188cc Iustin Pop
  elif value is _FS_NODATA:
249 cfb084ae René Nussbaumer
    return (RS_NODATA, None)
250 e2d188cc Iustin Pop
  elif value is _FS_UNAVAIL:
251 cfb084ae René Nussbaumer
    return (RS_UNAVAIL, None)
252 e2d188cc Iustin Pop
  elif value is _FS_OFFLINE:
253 cfb084ae René Nussbaumer
    return (RS_OFFLINE, None)
254 e2d188cc Iustin Pop
  else:
255 cfb084ae René Nussbaumer
    return (RS_NORMAL, value)
256 e2d188cc Iustin Pop
257 e2d188cc Iustin Pop
258 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
259 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
260 4ca96421 Michael Hanselmann

261 4ca96421 Michael Hanselmann
  @type fields: list
262 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
263 4ca96421 Michael Hanselmann
  @type row: list of tuples
264 4ca96421 Michael Hanselmann
  @param row: Row data
265 4ca96421 Michael Hanselmann

266 4ca96421 Michael Hanselmann
  """
267 d1c3c3b3 Iustin Pop
  assert len(row) == len(fields)
268 d1c3c3b3 Iustin Pop
  errs = []
269 d1c3c3b3 Iustin Pop
  for ((status, value), (fdef, _, _)) in zip(row, fields):
270 cfb084ae René Nussbaumer
    if status == RS_NORMAL:
271 d1c3c3b3 Iustin Pop
      if not _VERIFY_FN[fdef.kind](value):
272 d1c3c3b3 Iustin Pop
        errs.append("normal field %s fails validation (value is %s)" %
273 d1c3c3b3 Iustin Pop
                    (fdef.name, value))
274 d1c3c3b3 Iustin Pop
    elif value is not None:
275 d1c3c3b3 Iustin Pop
      errs.append("abnormal field %s has a non-None value" % fdef.name)
276 d1c3c3b3 Iustin Pop
  assert not errs, ("Failed validation: %s in row %s" %
277 d1c3c3b3 Iustin Pop
                    (utils.CommaJoin(errors), row))
278 4ca96421 Michael Hanselmann
279 4ca96421 Michael Hanselmann
280 d63bd540 Iustin Pop
def _PrepareFieldList(fields, aliases):
281 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
282 4ca96421 Michael Hanselmann

283 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
284 4ca96421 Michael Hanselmann

285 d63bd540 Iustin Pop
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data
286 d63bd540 Iustin Pop
      kind, retrieval function)
287 d63bd540 Iustin Pop
  @param fields: List of fields, see L{Query.__init__} for a better
288 d63bd540 Iustin Pop
      description
289 d63bd540 Iustin Pop
  @type aliases: list of tuples; (alias, target)
290 d63bd540 Iustin Pop
  @param aliases: list of tuples containing aliases; for each
291 d63bd540 Iustin Pop
      alias/target pair, a duplicate will be created in the field list
292 4ca96421 Michael Hanselmann
  @rtype: dict
293 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
294 4ca96421 Michael Hanselmann

295 4ca96421 Michael Hanselmann
  """
296 89ce4acc Michael Hanselmann
  if __debug__:
297 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
298 89ce4acc Michael Hanselmann
                                      for (fdef, _, _) in fields)
299 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
300 4ca96421 Michael Hanselmann
301 4ca96421 Michael Hanselmann
  result = {}
302 4ca96421 Michael Hanselmann
303 4ca96421 Michael Hanselmann
  for field in fields:
304 4ca96421 Michael Hanselmann
    (fdef, _, fn) = field
305 4ca96421 Michael Hanselmann
306 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
307 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
308 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
309 4ca96421 Michael Hanselmann
    assert callable(fn)
310 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
311 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
312 4ca96421 Michael Hanselmann
313 4ca96421 Michael Hanselmann
    result[fdef.name] = field
314 4ca96421 Michael Hanselmann
315 d63bd540 Iustin Pop
  for alias, target in aliases:
316 d63bd540 Iustin Pop
    assert alias not in result, "Alias %s overrides an existing field" % alias
317 d63bd540 Iustin Pop
    assert target in result, "Missing target %s for alias %s" % (target, alias)
318 d63bd540 Iustin Pop
    (fdef, k, fn) = result[target]
319 d63bd540 Iustin Pop
    fdef = fdef.Copy()
320 d63bd540 Iustin Pop
    fdef.name = alias
321 d63bd540 Iustin Pop
    result[alias] = (fdef, k, fn)
322 d63bd540 Iustin Pop
323 d63bd540 Iustin Pop
  assert len(result) == len(fields) + len(aliases)
324 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
325 4ca96421 Michael Hanselmann
                    for (name, (fdef, _, _)) in result.items())
326 4ca96421 Michael Hanselmann
327 4ca96421 Michael Hanselmann
  return result
328 4ca96421 Michael Hanselmann
329 4ca96421 Michael Hanselmann
330 b60fcb6f Michael Hanselmann
def GetQueryResponse(query, ctx):
331 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
332 b60fcb6f Michael Hanselmann

333 b60fcb6f Michael Hanselmann
  @type query: L{Query}
334 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
335 b60fcb6f Michael Hanselmann

336 b60fcb6f Michael Hanselmann
  """
337 b60fcb6f Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx),
338 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
339 b60fcb6f Michael Hanselmann
340 b60fcb6f Michael Hanselmann
341 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
342 aa29e95f Michael Hanselmann
  """Returns list of available fields.
343 aa29e95f Michael Hanselmann

344 aa29e95f Michael Hanselmann
  @type fielddefs: dict
345 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
346 aa29e95f Michael Hanselmann
  @type selected: list of strings
347 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
348 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
349 aa29e95f Michael Hanselmann

350 aa29e95f Michael Hanselmann
  """
351 aa29e95f Michael Hanselmann
  if selected is None:
352 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
353 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
354 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
355 aa29e95f Michael Hanselmann
  else:
356 aa29e95f Michael Hanselmann
    # Keep order as requested by client
357 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
358 aa29e95f Michael Hanselmann
359 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
360 aa29e95f Michael Hanselmann
361 aa29e95f Michael Hanselmann
362 4ca96421 Michael Hanselmann
def _MakeField(name, title, kind):
363 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
364 4ca96421 Michael Hanselmann

365 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
366 4ca96421 Michael Hanselmann
  @param title: Human-readable title
367 4ca96421 Michael Hanselmann
  @param kind: Field type
368 4ca96421 Michael Hanselmann

369 4ca96421 Michael Hanselmann
  """
370 4ca96421 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind)
371 8235fe04 Michael Hanselmann
372 8235fe04 Michael Hanselmann
373 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
374 8235fe04 Michael Hanselmann
  """Determine node role.
375 8235fe04 Michael Hanselmann

376 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
377 8235fe04 Michael Hanselmann
  @param node: Node object
378 8235fe04 Michael Hanselmann
  @type master_name: string
379 8235fe04 Michael Hanselmann
  @param master_name: Master node name
380 8235fe04 Michael Hanselmann

381 8235fe04 Michael Hanselmann
  """
382 8235fe04 Michael Hanselmann
  if node.name == master_name:
383 8235fe04 Michael Hanselmann
    return "M"
384 8235fe04 Michael Hanselmann
  elif node.master_candidate:
385 8235fe04 Michael Hanselmann
    return "C"
386 8235fe04 Michael Hanselmann
  elif node.drained:
387 8235fe04 Michael Hanselmann
    return "D"
388 8235fe04 Michael Hanselmann
  elif node.offline:
389 8235fe04 Michael Hanselmann
    return "O"
390 8235fe04 Michael Hanselmann
  else:
391 8235fe04 Michael Hanselmann
    return "R"
392 8235fe04 Michael Hanselmann
393 8235fe04 Michael Hanselmann
394 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
395 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
396 8235fe04 Michael Hanselmann

397 8235fe04 Michael Hanselmann
  @param attr: Attribute name
398 8235fe04 Michael Hanselmann

399 8235fe04 Michael Hanselmann
  """
400 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
401 e2d188cc Iustin Pop
  return lambda _, item: getter(item)
402 8235fe04 Michael Hanselmann
403 8235fe04 Michael Hanselmann
404 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
405 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
406 145bea54 Michael Hanselmann

407 145bea54 Michael Hanselmann
  @type getter: callable
408 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
409 145bea54 Michael Hanselmann

410 145bea54 Michael Hanselmann
  """
411 145bea54 Michael Hanselmann
  def fn(_, item):
412 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
413 145bea54 Michael Hanselmann

414 145bea54 Michael Hanselmann
    """
415 145bea54 Michael Hanselmann
    timestamp = getter(item)
416 145bea54 Michael Hanselmann
    if timestamp is None:
417 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
418 e2d188cc Iustin Pop
      return _FS_UNAVAIL
419 145bea54 Michael Hanselmann
    else:
420 e2d188cc Iustin Pop
      return timestamp
421 145bea54 Michael Hanselmann
422 145bea54 Michael Hanselmann
  return fn
423 145bea54 Michael Hanselmann
424 145bea54 Michael Hanselmann
425 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
426 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
427 145bea54 Michael Hanselmann

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

430 145bea54 Michael Hanselmann
  """
431 145bea54 Michael Hanselmann
  return [
432 82599b3e Iustin Pop
    (_MakeField("ctime", "CTime", QFT_TIMESTAMP), datatype,
433 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("ctime"))),
434 82599b3e Iustin Pop
    (_MakeField("mtime", "MTime", QFT_TIMESTAMP), datatype,
435 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("mtime"))),
436 145bea54 Michael Hanselmann
    ]
437 145bea54 Michael Hanselmann
438 145bea54 Michael Hanselmann
439 8235fe04 Michael Hanselmann
class NodeQueryData:
440 8235fe04 Michael Hanselmann
  """Data container for node data queries.
441 8235fe04 Michael Hanselmann

442 8235fe04 Michael Hanselmann
  """
443 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
444 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
445 8235fe04 Michael Hanselmann
    """Initializes this class.
446 8235fe04 Michael Hanselmann

447 8235fe04 Michael Hanselmann
    """
448 8235fe04 Michael Hanselmann
    self.nodes = nodes
449 8235fe04 Michael Hanselmann
    self.live_data = live_data
450 8235fe04 Michael Hanselmann
    self.master_name = master_name
451 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
452 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
453 8235fe04 Michael Hanselmann
    self.groups = groups
454 52b5d286 René Nussbaumer
    self.oob_support = oob_support
455 8572f1fe René Nussbaumer
    self.cluster = cluster
456 8235fe04 Michael Hanselmann
457 8235fe04 Michael Hanselmann
    # Used for individual rows
458 8235fe04 Michael Hanselmann
    self.curlive_data = None
459 8235fe04 Michael Hanselmann
460 8235fe04 Michael Hanselmann
  def __iter__(self):
461 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
462 8235fe04 Michael Hanselmann

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

466 8235fe04 Michael Hanselmann
    """
467 8235fe04 Michael Hanselmann
    for node in self.nodes:
468 8235fe04 Michael Hanselmann
      if self.live_data:
469 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
470 8235fe04 Michael Hanselmann
      else:
471 8235fe04 Michael Hanselmann
        self.curlive_data = None
472 8235fe04 Michael Hanselmann
      yield node
473 8235fe04 Michael Hanselmann
474 8235fe04 Michael Hanselmann
475 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
476 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
477 82599b3e Iustin Pop
  "drained": ("Drained", QFT_BOOL),
478 82599b3e Iustin Pop
  "master_candidate": ("MasterC", QFT_BOOL),
479 82599b3e Iustin Pop
  "master_capable": ("MasterCapable", QFT_BOOL),
480 82599b3e Iustin Pop
  "name": ("Node", QFT_TEXT),
481 82599b3e Iustin Pop
  "offline": ("Offline", QFT_BOOL),
482 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
483 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
484 82599b3e Iustin Pop
  "vm_capable": ("VMCapable", QFT_BOOL),
485 8235fe04 Michael Hanselmann
  }
486 8235fe04 Michael Hanselmann
487 8235fe04 Michael Hanselmann
488 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
489 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
490 82599b3e Iustin Pop
  "bootid": ("BootID", QFT_TEXT, "bootid"),
491 82599b3e Iustin Pop
  "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes"),
492 82599b3e Iustin Pop
  "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets"),
493 82599b3e Iustin Pop
  "ctotal": ("CTotal", QFT_NUMBER, "cpu_total"),
494 82599b3e Iustin Pop
  "dfree": ("DFree", QFT_UNIT, "vg_free"),
495 82599b3e Iustin Pop
  "dtotal": ("DTotal", QFT_UNIT, "vg_size"),
496 82599b3e Iustin Pop
  "mfree": ("MFree", QFT_UNIT, "memory_free"),
497 82599b3e Iustin Pop
  "mnode": ("MNode", QFT_UNIT, "memory_dom0"),
498 82599b3e Iustin Pop
  "mtotal": ("MTotal", QFT_UNIT, "memory_total"),
499 8235fe04 Michael Hanselmann
  }
500 8235fe04 Michael Hanselmann
501 8235fe04 Michael Hanselmann
502 8572f1fe René Nussbaumer
def _GetGroup(cb):
503 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
504 8572f1fe René Nussbaumer

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

507 8572f1fe René Nussbaumer
  """
508 8572f1fe René Nussbaumer
  def fn(ctx, node):
509 8572f1fe René Nussbaumer
    """Get group data for a node.
510 8572f1fe René Nussbaumer

511 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
512 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
513 8572f1fe René Nussbaumer
    @param inst: Node object
514 8572f1fe René Nussbaumer

515 8572f1fe René Nussbaumer
    """
516 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
517 8572f1fe René Nussbaumer
    if ng is None:
518 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
519 e2d188cc Iustin Pop
      return _FS_UNAVAIL
520 8572f1fe René Nussbaumer
521 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
522 8572f1fe René Nussbaumer
523 8572f1fe René Nussbaumer
  return fn
524 8572f1fe René Nussbaumer
525 8572f1fe René Nussbaumer
526 8572f1fe René Nussbaumer
def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613
527 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
528 8235fe04 Michael Hanselmann

529 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
530 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
531 8235fe04 Michael Hanselmann
  @param node: Node object
532 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
533 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
534 8235fe04 Michael Hanselmann

535 8235fe04 Michael Hanselmann
  """
536 e2d188cc Iustin Pop
  return ng.name
537 8235fe04 Michael Hanselmann
538 8235fe04 Michael Hanselmann
539 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
540 52b5d286 René Nussbaumer
  """Returns the node powered state
541 52b5d286 René Nussbaumer

542 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
543 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
544 52b5d286 René Nussbaumer
  @param node: Node object
545 52b5d286 René Nussbaumer

546 52b5d286 René Nussbaumer
  """
547 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
548 e2d188cc Iustin Pop
    return node.powered
549 52b5d286 René Nussbaumer
550 e2d188cc Iustin Pop
  return _FS_UNAVAIL
551 52b5d286 René Nussbaumer
552 52b5d286 René Nussbaumer
553 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
554 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
555 8572f1fe René Nussbaumer

556 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
557 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
558 8572f1fe René Nussbaumer
  @param node: Node object
559 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
560 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
561 8572f1fe René Nussbaumer

562 8572f1fe René Nussbaumer
  """
563 e2d188cc Iustin Pop
  return ctx.cluster.SimpleFillND(ng.FillND(node))
564 8572f1fe René Nussbaumer
565 8572f1fe René Nussbaumer
566 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
567 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
568 8235fe04 Michael Hanselmann

569 8235fe04 Michael Hanselmann
  @param field: Live field name
570 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
571 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
572 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
573 a6070ef7 Michael Hanselmann
  @param node: Node object
574 8235fe04 Michael Hanselmann

575 8235fe04 Michael Hanselmann
  """
576 a6070ef7 Michael Hanselmann
  if node.offline:
577 e2d188cc Iustin Pop
    return _FS_OFFLINE
578 a6070ef7 Michael Hanselmann
579 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
580 e2d188cc Iustin Pop
    return _FS_NODATA
581 8235fe04 Michael Hanselmann
582 8235fe04 Michael Hanselmann
  try:
583 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
584 8235fe04 Michael Hanselmann
  except KeyError:
585 e2d188cc Iustin Pop
    return _FS_UNAVAIL
586 8235fe04 Michael Hanselmann
587 82599b3e Iustin Pop
  if kind == QFT_TEXT:
588 e2d188cc Iustin Pop
    return value
589 8235fe04 Michael Hanselmann
590 82599b3e Iustin Pop
  assert kind in (QFT_NUMBER, QFT_UNIT)
591 8235fe04 Michael Hanselmann
592 8235fe04 Michael Hanselmann
  # Try to convert into number
593 8235fe04 Michael Hanselmann
  try:
594 e2d188cc Iustin Pop
    return int(value)
595 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
596 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
597 8235fe04 Michael Hanselmann
                      value, field)
598 e2d188cc Iustin Pop
    return _FS_UNAVAIL
599 8235fe04 Michael Hanselmann
600 8235fe04 Michael Hanselmann
601 8235fe04 Michael Hanselmann
def _BuildNodeFields():
602 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
603 8235fe04 Michael Hanselmann

604 8235fe04 Michael Hanselmann
  """
605 8235fe04 Michael Hanselmann
  fields = [
606 82599b3e Iustin Pop
    (_MakeField("pip", "PrimaryIP", QFT_TEXT), NQ_CONFIG,
607 e2d188cc Iustin Pop
     _GetItemAttr("primary_ip")),
608 82599b3e Iustin Pop
    (_MakeField("sip", "SecondaryIP", QFT_TEXT), NQ_CONFIG,
609 e2d188cc Iustin Pop
     _GetItemAttr("secondary_ip")),
610 82599b3e Iustin Pop
    (_MakeField("tags", "Tags", QFT_OTHER), NQ_CONFIG,
611 e2d188cc Iustin Pop
     lambda ctx, node: list(node.GetTags())),
612 82599b3e Iustin Pop
    (_MakeField("master", "IsMaster", QFT_BOOL), NQ_CONFIG,
613 e2d188cc Iustin Pop
     lambda ctx, node: node.name == ctx.master_name),
614 82599b3e Iustin Pop
    (_MakeField("role", "Role", QFT_TEXT), NQ_CONFIG,
615 e2d188cc Iustin Pop
     lambda ctx, node: _GetNodeRole(node, ctx.master_name)),
616 82599b3e Iustin Pop
    (_MakeField("group", "Group", QFT_TEXT), NQ_GROUP,
617 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
618 82599b3e Iustin Pop
    (_MakeField("group.uuid", "GroupUUID", QFT_TEXT),
619 e2d188cc Iustin Pop
     NQ_CONFIG, _GetItemAttr("group")),
620 82599b3e Iustin Pop
    (_MakeField("powered", "Powered", QFT_BOOL), NQ_OOB, _GetNodePower),
621 82599b3e Iustin Pop
    (_MakeField("ndparams", "NodeParameters", QFT_OTHER), NQ_GROUP,
622 8572f1fe René Nussbaumer
      _GetGroup(_GetNdParams)),
623 82599b3e Iustin Pop
    (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER),
624 e2d188cc Iustin Pop
      NQ_GROUP, _GetItemAttr("ndparams")),
625 8235fe04 Michael Hanselmann
    ]
626 8235fe04 Michael Hanselmann
627 8235fe04 Michael Hanselmann
  def _GetLength(getter):
628 e2d188cc Iustin Pop
    return lambda ctx, node: len(getter(ctx)[node.name])
629 8235fe04 Michael Hanselmann
630 8235fe04 Michael Hanselmann
  def _GetList(getter):
631 e2d188cc Iustin Pop
    return lambda ctx, node: list(getter(ctx)[node.name])
632 8235fe04 Michael Hanselmann
633 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
634 8235fe04 Michael Hanselmann
  for prefix, titleprefix, getter in \
635 8235fe04 Michael Hanselmann
      [("p", "Pri", operator.attrgetter("node_to_primary")),
636 8235fe04 Michael Hanselmann
       ("s", "Sec", operator.attrgetter("node_to_secondary"))]:
637 8235fe04 Michael Hanselmann
    fields.extend([
638 82599b3e Iustin Pop
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER),
639 8235fe04 Michael Hanselmann
       NQ_INST, _GetLength(getter)),
640 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
641 82599b3e Iustin Pop
                  QFT_OTHER),
642 8235fe04 Michael Hanselmann
       NQ_INST, _GetList(getter)),
643 8235fe04 Michael Hanselmann
      ])
644 8235fe04 Michael Hanselmann
645 8235fe04 Michael Hanselmann
  # Add simple fields
646 8235fe04 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), NQ_CONFIG, _GetItemAttr(name))
647 8235fe04 Michael Hanselmann
                 for (name, (title, kind)) in _NODE_SIMPLE_FIELDS.items()])
648 8235fe04 Michael Hanselmann
649 8235fe04 Michael Hanselmann
  # Add fields requiring live data
650 8235fe04 Michael Hanselmann
  fields.extend([
651 8235fe04 Michael Hanselmann
    (_MakeField(name, title, kind), NQ_LIVE,
652 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
653 8235fe04 Michael Hanselmann
    for (name, (title, kind, nfield)) in _NODE_LIVE_FIELDS.items()
654 8235fe04 Michael Hanselmann
    ])
655 8235fe04 Michael Hanselmann
656 145bea54 Michael Hanselmann
  # Add timestamps
657 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
658 145bea54 Michael Hanselmann
659 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
660 8235fe04 Michael Hanselmann
661 8235fe04 Michael Hanselmann
662 1c8addc6 Michael Hanselmann
class InstanceQueryData:
663 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
664 1c8addc6 Michael Hanselmann

665 1c8addc6 Michael Hanselmann
  """
666 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
667 1c8addc6 Michael Hanselmann
               live_data):
668 1c8addc6 Michael Hanselmann
    """Initializes this class.
669 1c8addc6 Michael Hanselmann

670 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
671 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
672 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
673 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
674 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
675 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
676 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
677 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
678 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
679 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
680 1c8addc6 Michael Hanselmann

681 1c8addc6 Michael Hanselmann
    """
682 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
683 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
684 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
685 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
686 1c8addc6 Michael Hanselmann
687 1c8addc6 Michael Hanselmann
    self.instances = instances
688 1c8addc6 Michael Hanselmann
    self.cluster = cluster
689 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
690 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
691 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
692 1c8addc6 Michael Hanselmann
    self.live_data = live_data
693 1c8addc6 Michael Hanselmann
694 1c8addc6 Michael Hanselmann
    # Used for individual rows
695 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
696 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
697 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
698 1c8addc6 Michael Hanselmann
699 1c8addc6 Michael Hanselmann
  def __iter__(self):
700 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
701 1c8addc6 Michael Hanselmann

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

705 1c8addc6 Michael Hanselmann
    """
706 1c8addc6 Michael Hanselmann
    for inst in self.instances:
707 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
708 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
709 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
710 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
711 1c8addc6 Michael Hanselmann
712 1c8addc6 Michael Hanselmann
      yield inst
713 1c8addc6 Michael Hanselmann
714 1c8addc6 Michael Hanselmann
715 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
716 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
717 1c8addc6 Michael Hanselmann

718 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
719 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
720 1c8addc6 Michael Hanselmann
  @param inst: Instance object
721 1c8addc6 Michael Hanselmann

722 1c8addc6 Michael Hanselmann
  """
723 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
724 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
725 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
726 e2d188cc Iustin Pop
    return _FS_NODATA
727 1c8addc6 Michael Hanselmann
  else:
728 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
729 1c8addc6 Michael Hanselmann
730 1c8addc6 Michael Hanselmann
731 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
732 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
733 1c8addc6 Michael Hanselmann

734 1c8addc6 Michael Hanselmann
  @type name: string
735 1c8addc6 Michael Hanselmann
  @param name: Live data field name
736 1c8addc6 Michael Hanselmann

737 1c8addc6 Michael Hanselmann
  """
738 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
739 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
740 1c8addc6 Michael Hanselmann

741 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
742 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
743 1c8addc6 Michael Hanselmann
    @param inst: Instance object
744 1c8addc6 Michael Hanselmann

745 1c8addc6 Michael Hanselmann
    """
746 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
747 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
748 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
749 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
750 e2d188cc Iustin Pop
      return _FS_NODATA
751 1c8addc6 Michael Hanselmann
752 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
753 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
754 1c8addc6 Michael Hanselmann
      if name in data:
755 e2d188cc Iustin Pop
        return data[name]
756 1c8addc6 Michael Hanselmann
757 e2d188cc Iustin Pop
    return _FS_UNAVAIL
758 1c8addc6 Michael Hanselmann
759 1c8addc6 Michael Hanselmann
  return fn
760 1c8addc6 Michael Hanselmann
761 1c8addc6 Michael Hanselmann
762 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
763 1c8addc6 Michael Hanselmann
  """Get instance status.
764 1c8addc6 Michael Hanselmann

765 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
766 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
767 1c8addc6 Michael Hanselmann
  @param inst: Instance object
768 1c8addc6 Michael Hanselmann

769 1c8addc6 Michael Hanselmann
  """
770 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
771 e2d188cc Iustin Pop
    return "ERROR_nodeoffline"
772 1c8addc6 Michael Hanselmann
773 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
774 e2d188cc Iustin Pop
    return "ERROR_nodedown"
775 1c8addc6 Michael Hanselmann
776 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
777 1c8addc6 Michael Hanselmann
    if inst.admin_up:
778 e2d188cc Iustin Pop
      return "running"
779 1c8addc6 Michael Hanselmann
    else:
780 e2d188cc Iustin Pop
      return "ERROR_up"
781 1c8addc6 Michael Hanselmann
782 1c8addc6 Michael Hanselmann
  if inst.admin_up:
783 e2d188cc Iustin Pop
    return "ERROR_down"
784 1c8addc6 Michael Hanselmann
785 e2d188cc Iustin Pop
  return "ADMIN_down"
786 1c8addc6 Michael Hanselmann
787 1c8addc6 Michael Hanselmann
788 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
789 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
790 1c8addc6 Michael Hanselmann

791 1c8addc6 Michael Hanselmann
  @type index: int
792 1c8addc6 Michael Hanselmann
  @param index: Disk index
793 1c8addc6 Michael Hanselmann

794 1c8addc6 Michael Hanselmann
  """
795 1c8addc6 Michael Hanselmann
  def fn(_, inst):
796 1c8addc6 Michael Hanselmann
    """Get size of a disk.
797 1c8addc6 Michael Hanselmann

798 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
799 1c8addc6 Michael Hanselmann
    @param inst: Instance object
800 1c8addc6 Michael Hanselmann

801 1c8addc6 Michael Hanselmann
    """
802 1c8addc6 Michael Hanselmann
    try:
803 e2d188cc Iustin Pop
      return inst.disks[index].size
804 1c8addc6 Michael Hanselmann
    except IndexError:
805 e2d188cc Iustin Pop
      return _FS_UNAVAIL
806 1c8addc6 Michael Hanselmann
807 1c8addc6 Michael Hanselmann
  return fn
808 1c8addc6 Michael Hanselmann
809 1c8addc6 Michael Hanselmann
810 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
811 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
812 1c8addc6 Michael Hanselmann

813 1c8addc6 Michael Hanselmann
  @type index: int
814 1c8addc6 Michael Hanselmann
  @param index: NIC index
815 1c8addc6 Michael Hanselmann
  @type cb: callable
816 1c8addc6 Michael Hanselmann
  @param cb: Callback
817 1c8addc6 Michael Hanselmann

818 1c8addc6 Michael Hanselmann
  """
819 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
820 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
821 1c8addc6 Michael Hanselmann

822 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
823 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
824 1c8addc6 Michael Hanselmann
    @param inst: Instance object
825 1c8addc6 Michael Hanselmann

826 1c8addc6 Michael Hanselmann
    """
827 1c8addc6 Michael Hanselmann
    try:
828 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
829 1c8addc6 Michael Hanselmann
    except IndexError:
830 e2d188cc Iustin Pop
      return _FS_UNAVAIL
831 1c8addc6 Michael Hanselmann
832 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
833 1c8addc6 Michael Hanselmann
834 1c8addc6 Michael Hanselmann
  return fn
835 1c8addc6 Michael Hanselmann
836 1c8addc6 Michael Hanselmann
837 1c8addc6 Michael Hanselmann
def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613
838 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
839 1c8addc6 Michael Hanselmann

840 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
841 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
842 1c8addc6 Michael Hanselmann
  @param nic: NIC object
843 1c8addc6 Michael Hanselmann

844 1c8addc6 Michael Hanselmann
  """
845 1c8addc6 Michael Hanselmann
  if nic.ip is None:
846 e2d188cc Iustin Pop
    return _FS_UNAVAIL
847 1c8addc6 Michael Hanselmann
  else:
848 e2d188cc Iustin Pop
    return nic.ip
849 1c8addc6 Michael Hanselmann
850 1c8addc6 Michael Hanselmann
851 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
852 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
853 1c8addc6 Michael Hanselmann

854 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
855 1c8addc6 Michael Hanselmann
  @type index: int
856 1c8addc6 Michael Hanselmann
  @param index: NIC index
857 1c8addc6 Michael Hanselmann

858 1c8addc6 Michael Hanselmann
  """
859 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
860 1c8addc6 Michael Hanselmann
861 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
862 1c8addc6 Michael Hanselmann
863 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
864 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
865 1c8addc6 Michael Hanselmann
  else:
866 e2d188cc Iustin Pop
    return _FS_UNAVAIL
867 1c8addc6 Michael Hanselmann
868 1c8addc6 Michael Hanselmann
869 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
870 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
871 1c8addc6 Michael Hanselmann

872 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
873 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
874 1c8addc6 Michael Hanselmann
  @param inst: Instance object
875 1c8addc6 Michael Hanselmann

876 1c8addc6 Michael Hanselmann
  """
877 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
878 1c8addc6 Michael Hanselmann
879 1c8addc6 Michael Hanselmann
  result = []
880 1c8addc6 Michael Hanselmann
881 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
882 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
883 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
884 1c8addc6 Michael Hanselmann
    else:
885 1c8addc6 Michael Hanselmann
      result.append(None)
886 1c8addc6 Michael Hanselmann
887 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
888 1c8addc6 Michael Hanselmann
889 e2d188cc Iustin Pop
  return result
890 1c8addc6 Michael Hanselmann
891 1c8addc6 Michael Hanselmann
892 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
893 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
894 1c8addc6 Michael Hanselmann

895 1c8addc6 Michael Hanselmann
  @type name: string
896 1c8addc6 Michael Hanselmann
  @param name: Parameter name
897 1c8addc6 Michael Hanselmann

898 1c8addc6 Michael Hanselmann
  """
899 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
900 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
901 1c8addc6 Michael Hanselmann

902 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
903 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
904 1c8addc6 Michael Hanselmann
    @param inst: Instance object
905 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
906 1c8addc6 Michael Hanselmann
    @param nic: NIC object
907 1c8addc6 Michael Hanselmann

908 1c8addc6 Michael Hanselmann
    """
909 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
910 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
911 1c8addc6 Michael Hanselmann
912 1c8addc6 Michael Hanselmann
  return fn
913 1c8addc6 Michael Hanselmann
914 1c8addc6 Michael Hanselmann
915 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
916 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
917 1c8addc6 Michael Hanselmann

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

920 1c8addc6 Michael Hanselmann
  """
921 e2d188cc Iustin Pop
  nic_mac_fn = lambda ctx, _, nic: nic.mac
922 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
923 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
924 1c8addc6 Michael Hanselmann
925 1c8addc6 Michael Hanselmann
  fields = [
926 1c8addc6 Michael Hanselmann
    # First NIC (legacy)
927 82599b3e Iustin Pop
    (_MakeField("ip", "IP_address", QFT_TEXT), IQ_CONFIG,
928 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicIp)),
929 82599b3e Iustin Pop
    (_MakeField("mac", "MAC_address", QFT_TEXT), IQ_CONFIG,
930 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mac_fn)),
931 82599b3e Iustin Pop
    (_MakeField("bridge", "Bridge", QFT_TEXT), IQ_CONFIG,
932 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicBridge)),
933 82599b3e Iustin Pop
    (_MakeField("nic_mode", "NIC_Mode", QFT_TEXT), IQ_CONFIG,
934 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mode_fn)),
935 82599b3e Iustin Pop
    (_MakeField("nic_link", "NIC_Link", QFT_TEXT), IQ_CONFIG,
936 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_link_fn)),
937 1c8addc6 Michael Hanselmann
938 1c8addc6 Michael Hanselmann
    # All NICs
939 82599b3e Iustin Pop
    (_MakeField("nic.count", "NICs", QFT_NUMBER), IQ_CONFIG,
940 e2d188cc Iustin Pop
     lambda ctx, inst: len(inst.nics)),
941 82599b3e Iustin Pop
    (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER), IQ_CONFIG,
942 e2d188cc Iustin Pop
     lambda ctx, inst: [nic.mac for nic in inst.nics]),
943 82599b3e Iustin Pop
    (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER), IQ_CONFIG,
944 e2d188cc Iustin Pop
     lambda ctx, inst: [nic.ip for nic in inst.nics]),
945 82599b3e Iustin Pop
    (_MakeField("nic.modes", "NIC_modes", QFT_OTHER), IQ_CONFIG,
946 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_MODE]
947 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
948 82599b3e Iustin Pop
    (_MakeField("nic.links", "NIC_links", QFT_OTHER), IQ_CONFIG,
949 e2d188cc Iustin Pop
     lambda ctx, inst: [nicp[constants.NIC_LINK]
950 e2d188cc Iustin Pop
                        for nicp in ctx.inst_nicparams]),
951 82599b3e Iustin Pop
    (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER), IQ_CONFIG,
952 1c8addc6 Michael Hanselmann
     _GetInstAllNicBridges),
953 1c8addc6 Michael Hanselmann
    ]
954 1c8addc6 Michael Hanselmann
955 1c8addc6 Michael Hanselmann
  # NICs by number
956 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
957 1c8addc6 Michael Hanselmann
    fields.extend([
958 82599b3e Iustin Pop
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT),
959 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicIp)),
960 82599b3e Iustin Pop
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT),
961 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mac_fn)),
962 82599b3e Iustin Pop
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT),
963 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mode_fn)),
964 82599b3e Iustin Pop
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT),
965 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_link_fn)),
966 82599b3e Iustin Pop
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT),
967 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicBridge)),
968 1c8addc6 Michael Hanselmann
      ])
969 1c8addc6 Michael Hanselmann
970 1c8addc6 Michael Hanselmann
  return fields
971 1c8addc6 Michael Hanselmann
972 1c8addc6 Michael Hanselmann
973 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
974 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
975 1c8addc6 Michael Hanselmann

976 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
977 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
978 1c8addc6 Michael Hanselmann
  @param inst: Instance object
979 1c8addc6 Michael Hanselmann

980 1c8addc6 Michael Hanselmann
  """
981 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
982 1c8addc6 Michael Hanselmann
983 1c8addc6 Michael Hanselmann
  if usage is None:
984 1c8addc6 Michael Hanselmann
    usage = 0
985 1c8addc6 Michael Hanselmann
986 e2d188cc Iustin Pop
  return usage
987 1c8addc6 Michael Hanselmann
988 1c8addc6 Michael Hanselmann
989 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
990 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
991 1c8addc6 Michael Hanselmann

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

994 1c8addc6 Michael Hanselmann
  """
995 1c8addc6 Michael Hanselmann
  fields = [
996 82599b3e Iustin Pop
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT), IQ_DISKUSAGE,
997 1c8addc6 Michael Hanselmann
     _GetInstDiskUsage),
998 82599b3e Iustin Pop
    (_MakeField("disk.count", "Disks", QFT_NUMBER), IQ_CONFIG,
999 e2d188cc Iustin Pop
     lambda ctx, inst: len(inst.disks)),
1000 82599b3e Iustin Pop
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER), IQ_CONFIG,
1001 e2d188cc Iustin Pop
     lambda ctx, inst: [disk.size for disk in inst.disks]),
1002 1c8addc6 Michael Hanselmann
    ]
1003 1c8addc6 Michael Hanselmann
1004 1c8addc6 Michael Hanselmann
  # Disks by number
1005 1c8addc6 Michael Hanselmann
  fields.extend([
1006 82599b3e Iustin Pop
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT),
1007 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstDiskSize(i))
1008 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1009 1c8addc6 Michael Hanselmann
    ])
1010 1c8addc6 Michael Hanselmann
1011 1c8addc6 Michael Hanselmann
  return fields
1012 1c8addc6 Michael Hanselmann
1013 1c8addc6 Michael Hanselmann
1014 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1015 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1016 1c8addc6 Michael Hanselmann

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

1019 1c8addc6 Michael Hanselmann
  """
1020 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1021 1c8addc6 Michael Hanselmann
  be_title = {
1022 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1023 0ca7e384 Iustin Pop
    constants.BE_MEMORY: "ConfigMemory",
1024 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1025 1c8addc6 Michael Hanselmann
    }
1026 1c8addc6 Michael Hanselmann
1027 1c8addc6 Michael Hanselmann
  hv_title = {
1028 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1029 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1030 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1031 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1032 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1033 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1034 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1035 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1036 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1037 1c8addc6 Michael Hanselmann
    }
1038 1c8addc6 Michael Hanselmann
1039 1c8addc6 Michael Hanselmann
  fields = [
1040 1c8addc6 Michael Hanselmann
    # Filled parameters
1041 82599b3e Iustin Pop
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER),
1042 e2d188cc Iustin Pop
     IQ_CONFIG, lambda ctx, _: ctx.inst_hvparams),
1043 82599b3e Iustin Pop
    (_MakeField("beparams", "BackendParameters", QFT_OTHER),
1044 e2d188cc Iustin Pop
     IQ_CONFIG, lambda ctx, _: ctx.inst_beparams),
1045 1c8addc6 Michael Hanselmann
1046 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1047 82599b3e Iustin Pop
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER),
1048 e2d188cc Iustin Pop
     IQ_CONFIG, _GetItemAttr("hvparams")),
1049 82599b3e Iustin Pop
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER),
1050 e2d188cc Iustin Pop
     IQ_CONFIG, _GetItemAttr("beparams")),
1051 82599b3e Iustin Pop
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER),
1052 e2d188cc Iustin Pop
     IQ_CONFIG, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1053 1c8addc6 Michael Hanselmann
    ]
1054 1c8addc6 Michael Hanselmann
1055 1c8addc6 Michael Hanselmann
  # HV params
1056 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1057 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1058 1c8addc6 Michael Hanselmann
1059 1c8addc6 Michael Hanselmann
  fields.extend([
1060 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1061 af58707c Iustin Pop
                _VTToQFT[kind]),
1062 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstHvParam(name))
1063 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1064 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1065 1c8addc6 Michael Hanselmann
    ])
1066 1c8addc6 Michael Hanselmann
1067 1c8addc6 Michael Hanselmann
  # BE params
1068 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1069 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1070 1c8addc6 Michael Hanselmann
1071 1c8addc6 Michael Hanselmann
  fields.extend([
1072 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1073 af58707c Iustin Pop
                _VTToQFT[kind]), IQ_CONFIG,
1074 af58707c Iustin Pop
     _GetInstBeParam(name))
1075 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1076 1c8addc6 Michael Hanselmann
    ])
1077 1c8addc6 Michael Hanselmann
1078 1c8addc6 Michael Hanselmann
  return fields
1079 1c8addc6 Michael Hanselmann
1080 1c8addc6 Michael Hanselmann
1081 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1082 82599b3e Iustin Pop
  "disk_template": ("Disk_template", QFT_TEXT),
1083 82599b3e Iustin Pop
  "hypervisor": ("Hypervisor", QFT_TEXT),
1084 82599b3e Iustin Pop
  "name": ("Node", QFT_TEXT),
1085 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1086 82599b3e Iustin Pop
  "network_port": ("Network_port", QFT_OTHER),
1087 82599b3e Iustin Pop
  "os": ("OS", QFT_TEXT),
1088 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
1089 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
1090 1c8addc6 Michael Hanselmann
  }
1091 1c8addc6 Michael Hanselmann
1092 1c8addc6 Michael Hanselmann
1093 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1094 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1095 1c8addc6 Michael Hanselmann

1096 1c8addc6 Michael Hanselmann
  """
1097 1c8addc6 Michael Hanselmann
  fields = [
1098 82599b3e Iustin Pop
    (_MakeField("pnode", "Primary_node", QFT_TEXT), IQ_CONFIG,
1099 e2d188cc Iustin Pop
     _GetItemAttr("primary_node")),
1100 82599b3e Iustin Pop
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER), IQ_CONFIG,
1101 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.secondary_nodes)),
1102 82599b3e Iustin Pop
    (_MakeField("admin_state", "Autostart", QFT_BOOL), IQ_CONFIG,
1103 e2d188cc Iustin Pop
     _GetItemAttr("admin_up")),
1104 82599b3e Iustin Pop
    (_MakeField("tags", "Tags", QFT_OTHER), IQ_CONFIG,
1105 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
1106 1c8addc6 Michael Hanselmann
    ]
1107 1c8addc6 Michael Hanselmann
1108 1c8addc6 Michael Hanselmann
  # Add simple fields
1109 1c8addc6 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), IQ_CONFIG, _GetItemAttr(name))
1110 1c8addc6 Michael Hanselmann
                 for (name, (title, kind)) in _INST_SIMPLE_FIELDS.items()])
1111 1c8addc6 Michael Hanselmann
1112 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1113 1c8addc6 Michael Hanselmann
  fields.extend([
1114 82599b3e Iustin Pop
    (_MakeField("oper_state", "Running", QFT_BOOL), IQ_LIVE,
1115 1c8addc6 Michael Hanselmann
     _GetInstOperState),
1116 0ca7e384 Iustin Pop
    (_MakeField("oper_ram", "Memory", QFT_UNIT), IQ_LIVE,
1117 1c8addc6 Michael Hanselmann
     _GetInstLiveData("memory")),
1118 0ca7e384 Iustin Pop
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER), IQ_LIVE,
1119 1c8addc6 Michael Hanselmann
     _GetInstLiveData("vcpus")),
1120 82599b3e Iustin Pop
    (_MakeField("status", "Status", QFT_TEXT), IQ_LIVE, _GetInstStatus),
1121 1c8addc6 Michael Hanselmann
    ])
1122 1c8addc6 Michael Hanselmann
1123 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1124 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1125 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceNetworkFields())
1126 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1127 1c8addc6 Michael Hanselmann
1128 e7e8037b Iustin Pop
  aliases = [
1129 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
1130 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
1131 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
1132 e7e8037b Iustin Pop
    ]
1133 e7e8037b Iustin Pop
1134 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
1135 1c8addc6 Michael Hanselmann
1136 1c8addc6 Michael Hanselmann
1137 24d16f76 Michael Hanselmann
class LockQueryData:
1138 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1139 24d16f76 Michael Hanselmann

1140 24d16f76 Michael Hanselmann
  """
1141 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1142 24d16f76 Michael Hanselmann
    """Initializes this class.
1143 24d16f76 Michael Hanselmann

1144 24d16f76 Michael Hanselmann
    """
1145 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1146 24d16f76 Michael Hanselmann
1147 24d16f76 Michael Hanselmann
  def __iter__(self):
1148 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1149 24d16f76 Michael Hanselmann

1150 24d16f76 Michael Hanselmann
    """
1151 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1152 24d16f76 Michael Hanselmann
1153 24d16f76 Michael Hanselmann
1154 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1155 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1156 24d16f76 Michael Hanselmann

1157 24d16f76 Michael Hanselmann
  """
1158 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1159 24d16f76 Michael Hanselmann
1160 24d16f76 Michael Hanselmann
  if owners:
1161 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1162 24d16f76 Michael Hanselmann
1163 e2d188cc Iustin Pop
  return owners
1164 24d16f76 Michael Hanselmann
1165 24d16f76 Michael Hanselmann
1166 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1167 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1168 24d16f76 Michael Hanselmann

1169 24d16f76 Michael Hanselmann
  """
1170 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1171 24d16f76 Michael Hanselmann
1172 24d16f76 Michael Hanselmann
  if pending:
1173 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1174 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1175 24d16f76 Michael Hanselmann
1176 e2d188cc Iustin Pop
  return pending
1177 24d16f76 Michael Hanselmann
1178 24d16f76 Michael Hanselmann
1179 24d16f76 Michael Hanselmann
def _BuildLockFields():
1180 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1181 24d16f76 Michael Hanselmann

1182 24d16f76 Michael Hanselmann
  """
1183 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1184 82599b3e Iustin Pop
    (_MakeField("name", "Name", QFT_TEXT), None,
1185 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1186 82599b3e Iustin Pop
    (_MakeField("mode", "Mode", QFT_OTHER), LQ_MODE,
1187 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): mode),
1188 82599b3e Iustin Pop
    (_MakeField("owner", "Owner", QFT_OTHER), LQ_OWNER, _GetLockOwners),
1189 82599b3e Iustin Pop
    (_MakeField("pending", "Pending", QFT_OTHER), LQ_PENDING, _GetLockPending),
1190 d63bd540 Iustin Pop
    ], [])
1191 24d16f76 Michael Hanselmann
1192 24d16f76 Michael Hanselmann
1193 8e21cfc0 Adeodato Simo
class GroupQueryData:
1194 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1195 8e21cfc0 Adeodato Simo

1196 8e21cfc0 Adeodato Simo
  """
1197 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1198 8e21cfc0 Adeodato Simo
    """Initializes this class.
1199 8e21cfc0 Adeodato Simo

1200 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1201 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1202 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1203 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1204 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1205 8e21cfc0 Adeodato Simo

1206 8e21cfc0 Adeodato Simo
    """
1207 8e21cfc0 Adeodato Simo
    self.groups = groups
1208 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1209 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1210 8e21cfc0 Adeodato Simo
1211 8e21cfc0 Adeodato Simo
  def __iter__(self):
1212 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1213 8e21cfc0 Adeodato Simo

1214 8e21cfc0 Adeodato Simo
    """
1215 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1216 8e21cfc0 Adeodato Simo
1217 8e21cfc0 Adeodato Simo
1218 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1219 82599b3e Iustin Pop
  "alloc_policy": ("AllocPolicy", QFT_TEXT),
1220 82599b3e Iustin Pop
  "name": ("Group", QFT_TEXT),
1221 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
1222 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
1223 82599b3e Iustin Pop
  "ndparams": ("NDParams", QFT_OTHER),
1224 8e21cfc0 Adeodato Simo
  }
1225 8e21cfc0 Adeodato Simo
1226 8e21cfc0 Adeodato Simo
1227 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1228 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1229 8e21cfc0 Adeodato Simo

1230 8e21cfc0 Adeodato Simo
  """
1231 8e21cfc0 Adeodato Simo
  # Add simple fields
1232 8e21cfc0 Adeodato Simo
  fields = [(_MakeField(name, title, kind), GQ_CONFIG, _GetItemAttr(name))
1233 8e21cfc0 Adeodato Simo
            for (name, (title, kind)) in _GROUP_SIMPLE_FIELDS.items()]
1234 8e21cfc0 Adeodato Simo
1235 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1236 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
1237 8e21cfc0 Adeodato Simo
1238 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1239 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
1240 8e21cfc0 Adeodato Simo
1241 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1242 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1243 8e21cfc0 Adeodato Simo
1244 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1245 8e21cfc0 Adeodato Simo
  fields.extend([
1246 82599b3e Iustin Pop
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER),
1247 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetLength(group_to_nodes)),
1248 82599b3e Iustin Pop
    (_MakeField("node_list", "NodeList", QFT_OTHER),
1249 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetSortedList(group_to_nodes)),
1250 8e21cfc0 Adeodato Simo
    ])
1251 8e21cfc0 Adeodato Simo
1252 8e21cfc0 Adeodato Simo
  # Add fields for instances
1253 8e21cfc0 Adeodato Simo
  fields.extend([
1254 82599b3e Iustin Pop
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER),
1255 8e21cfc0 Adeodato Simo
     GQ_INST, _GetLength(group_to_instances)),
1256 82599b3e Iustin Pop
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER),
1257 8e21cfc0 Adeodato Simo
     GQ_INST, _GetSortedList(group_to_instances)),
1258 8e21cfc0 Adeodato Simo
    ])
1259 8e21cfc0 Adeodato Simo
1260 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1261 8e21cfc0 Adeodato Simo
1262 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1263 8e21cfc0 Adeodato Simo
1264 8e21cfc0 Adeodato Simo
1265 8235fe04 Michael Hanselmann
#: Fields available for node queries
1266 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
1267 1c8addc6 Michael Hanselmann
1268 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
1269 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
1270 24d16f76 Michael Hanselmann
1271 24d16f76 Michael Hanselmann
#: Fields available for lock queries
1272 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
1273 e571ee44 Adeodato Simo
1274 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
1275 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
1276 8e21cfc0 Adeodato Simo
1277 e571ee44 Adeodato Simo
#: All available field lists
1278 8e21cfc0 Adeodato Simo
ALL_FIELD_LISTS = [NODE_FIELDS, INSTANCE_FIELDS, LOCK_FIELDS, GROUP_FIELDS]