Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ 43fcf0d3

History | View | Annotate | Download (35.2 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 5d28cb6f Michael Hanselmann
 IQ_DISKUSAGE,
83 5d28cb6f Michael Hanselmann
 IQ_CONSOLE) = range(100, 104)
84 1c8addc6 Michael Hanselmann
85 24d16f76 Michael Hanselmann
(LQ_MODE,
86 24d16f76 Michael Hanselmann
 LQ_OWNER,
87 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
88 8235fe04 Michael Hanselmann
89 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
90 8e21cfc0 Adeodato Simo
 GQ_NODE,
91 8e21cfc0 Adeodato Simo
 GQ_INST) = range(200, 203)
92 8e21cfc0 Adeodato Simo
93 8e21cfc0 Adeodato Simo
94 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
95 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
96 4ca96421 Michael Hanselmann
97 4ca96421 Michael Hanselmann
#: Verification function for each field type
98 4ca96421 Michael Hanselmann
_VERIFY_FN = {
99 82599b3e Iustin Pop
  QFT_UNKNOWN: ht.TNone,
100 82599b3e Iustin Pop
  QFT_TEXT: ht.TString,
101 82599b3e Iustin Pop
  QFT_BOOL: ht.TBool,
102 82599b3e Iustin Pop
  QFT_NUMBER: ht.TInt,
103 82599b3e Iustin Pop
  QFT_UNIT: ht.TInt,
104 82599b3e Iustin Pop
  QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat),
105 82599b3e Iustin Pop
  QFT_OTHER: lambda _: True,
106 4ca96421 Michael Hanselmann
  }
107 4ca96421 Michael Hanselmann
108 e2d188cc Iustin Pop
# Unique objects for special field statuses
109 e2d188cc Iustin Pop
_FS_UNKNOWN = object()
110 e2d188cc Iustin Pop
_FS_NODATA = object()
111 e2d188cc Iustin Pop
_FS_UNAVAIL = object()
112 e2d188cc Iustin Pop
_FS_OFFLINE = object()
113 e2d188cc Iustin Pop
114 af58707c Iustin Pop
#: VType to QFT mapping
115 af58707c Iustin Pop
_VTToQFT = {
116 af58707c Iustin Pop
  # TODO: fix validation of empty strings
117 af58707c Iustin Pop
  constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty
118 af58707c Iustin Pop
  constants.VTYPE_MAYBE_STRING: QFT_OTHER,
119 af58707c Iustin Pop
  constants.VTYPE_BOOL: QFT_BOOL,
120 af58707c Iustin Pop
  constants.VTYPE_SIZE: QFT_UNIT,
121 af58707c Iustin Pop
  constants.VTYPE_INT: QFT_NUMBER,
122 af58707c Iustin Pop
  }
123 af58707c Iustin Pop
124 4ca96421 Michael Hanselmann
125 4ca96421 Michael Hanselmann
def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
126 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
127 4ca96421 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

670 1c8addc6 Michael Hanselmann
  """
671 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
672 5d28cb6f Michael Hanselmann
               live_data, wrongnode_inst, console):
673 1c8addc6 Michael Hanselmann
    """Initializes this class.
674 1c8addc6 Michael Hanselmann

675 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
676 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
677 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
678 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
679 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
680 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
681 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
682 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
683 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
684 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
685 e431074f René Nussbaumer
    @type wrongnode_inst: set
686 e431074f René Nussbaumer
    @param wrongnode_inst: Set of instances running on wrong node(s)
687 5d28cb6f Michael Hanselmann
    @type console: dict; instance name as key
688 5d28cb6f Michael Hanselmann
    @param console: Per-instance console information
689 1c8addc6 Michael Hanselmann

690 1c8addc6 Michael Hanselmann
    """
691 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
692 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
693 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
694 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
695 1c8addc6 Michael Hanselmann
696 1c8addc6 Michael Hanselmann
    self.instances = instances
697 1c8addc6 Michael Hanselmann
    self.cluster = cluster
698 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
699 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
700 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
701 1c8addc6 Michael Hanselmann
    self.live_data = live_data
702 e431074f René Nussbaumer
    self.wrongnode_inst = wrongnode_inst
703 5d28cb6f Michael Hanselmann
    self.console = console
704 1c8addc6 Michael Hanselmann
705 1c8addc6 Michael Hanselmann
    # Used for individual rows
706 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
707 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
708 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
709 1c8addc6 Michael Hanselmann
710 1c8addc6 Michael Hanselmann
  def __iter__(self):
711 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
712 1c8addc6 Michael Hanselmann

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

716 1c8addc6 Michael Hanselmann
    """
717 1c8addc6 Michael Hanselmann
    for inst in self.instances:
718 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
719 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
720 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
721 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
722 1c8addc6 Michael Hanselmann
723 1c8addc6 Michael Hanselmann
      yield inst
724 1c8addc6 Michael Hanselmann
725 1c8addc6 Michael Hanselmann
726 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
727 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
728 1c8addc6 Michael Hanselmann

729 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
730 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
731 1c8addc6 Michael Hanselmann
  @param inst: Instance object
732 1c8addc6 Michael Hanselmann

733 1c8addc6 Michael Hanselmann
  """
734 cfb084ae René Nussbaumer
  # Can't use RS_OFFLINE here as it would describe the instance to
735 e2d188cc Iustin Pop
  # be offline when we actually don't know due to missing data
736 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
737 e2d188cc Iustin Pop
    return _FS_NODATA
738 1c8addc6 Michael Hanselmann
  else:
739 e2d188cc Iustin Pop
    return bool(ctx.live_data.get(inst.name))
740 1c8addc6 Michael Hanselmann
741 1c8addc6 Michael Hanselmann
742 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
743 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
744 1c8addc6 Michael Hanselmann

745 1c8addc6 Michael Hanselmann
  @type name: string
746 1c8addc6 Michael Hanselmann
  @param name: Live data field name
747 1c8addc6 Michael Hanselmann

748 1c8addc6 Michael Hanselmann
  """
749 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
750 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
751 1c8addc6 Michael Hanselmann

752 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
753 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
754 1c8addc6 Michael Hanselmann
    @param inst: Instance object
755 1c8addc6 Michael Hanselmann

756 1c8addc6 Michael Hanselmann
    """
757 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
758 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
759 cfb084ae René Nussbaumer
      # Can't use RS_OFFLINE here as it would describe the instance to be
760 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
761 e2d188cc Iustin Pop
      return _FS_NODATA
762 1c8addc6 Michael Hanselmann
763 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
764 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
765 1c8addc6 Michael Hanselmann
      if name in data:
766 e2d188cc Iustin Pop
        return data[name]
767 1c8addc6 Michael Hanselmann
768 e2d188cc Iustin Pop
    return _FS_UNAVAIL
769 1c8addc6 Michael Hanselmann
770 1c8addc6 Michael Hanselmann
  return fn
771 1c8addc6 Michael Hanselmann
772 1c8addc6 Michael Hanselmann
773 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
774 1c8addc6 Michael Hanselmann
  """Get instance status.
775 1c8addc6 Michael Hanselmann

776 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
777 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
778 1c8addc6 Michael Hanselmann
  @param inst: Instance object
779 1c8addc6 Michael Hanselmann

780 1c8addc6 Michael Hanselmann
  """
781 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
782 e2d188cc Iustin Pop
    return "ERROR_nodeoffline"
783 1c8addc6 Michael Hanselmann
784 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
785 e2d188cc Iustin Pop
    return "ERROR_nodedown"
786 1c8addc6 Michael Hanselmann
787 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
788 e431074f René Nussbaumer
    if inst.name in ctx.wrongnode_inst:
789 e431074f René Nussbaumer
      return "ERROR_wrongnode"
790 e431074f René Nussbaumer
    elif inst.admin_up:
791 e2d188cc Iustin Pop
      return "running"
792 1c8addc6 Michael Hanselmann
    else:
793 e2d188cc Iustin Pop
      return "ERROR_up"
794 1c8addc6 Michael Hanselmann
795 1c8addc6 Michael Hanselmann
  if inst.admin_up:
796 e2d188cc Iustin Pop
    return "ERROR_down"
797 1c8addc6 Michael Hanselmann
798 e2d188cc Iustin Pop
  return "ADMIN_down"
799 1c8addc6 Michael Hanselmann
800 1c8addc6 Michael Hanselmann
801 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
802 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
803 1c8addc6 Michael Hanselmann

804 1c8addc6 Michael Hanselmann
  @type index: int
805 1c8addc6 Michael Hanselmann
  @param index: Disk index
806 1c8addc6 Michael Hanselmann

807 1c8addc6 Michael Hanselmann
  """
808 1c8addc6 Michael Hanselmann
  def fn(_, inst):
809 1c8addc6 Michael Hanselmann
    """Get size of a disk.
810 1c8addc6 Michael Hanselmann

811 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
812 1c8addc6 Michael Hanselmann
    @param inst: Instance object
813 1c8addc6 Michael Hanselmann

814 1c8addc6 Michael Hanselmann
    """
815 1c8addc6 Michael Hanselmann
    try:
816 e2d188cc Iustin Pop
      return inst.disks[index].size
817 1c8addc6 Michael Hanselmann
    except IndexError:
818 e2d188cc Iustin Pop
      return _FS_UNAVAIL
819 1c8addc6 Michael Hanselmann
820 1c8addc6 Michael Hanselmann
  return fn
821 1c8addc6 Michael Hanselmann
822 1c8addc6 Michael Hanselmann
823 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
824 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
825 1c8addc6 Michael Hanselmann

826 1c8addc6 Michael Hanselmann
  @type index: int
827 1c8addc6 Michael Hanselmann
  @param index: NIC index
828 1c8addc6 Michael Hanselmann
  @type cb: callable
829 1c8addc6 Michael Hanselmann
  @param cb: Callback
830 1c8addc6 Michael Hanselmann

831 1c8addc6 Michael Hanselmann
  """
832 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
833 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
834 1c8addc6 Michael Hanselmann

835 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
836 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
837 1c8addc6 Michael Hanselmann
    @param inst: Instance object
838 1c8addc6 Michael Hanselmann

839 1c8addc6 Michael Hanselmann
    """
840 1c8addc6 Michael Hanselmann
    try:
841 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
842 1c8addc6 Michael Hanselmann
    except IndexError:
843 e2d188cc Iustin Pop
      return _FS_UNAVAIL
844 1c8addc6 Michael Hanselmann
845 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
846 1c8addc6 Michael Hanselmann
847 1c8addc6 Michael Hanselmann
  return fn
848 1c8addc6 Michael Hanselmann
849 1c8addc6 Michael Hanselmann
850 1c8addc6 Michael Hanselmann
def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613
851 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
852 1c8addc6 Michael Hanselmann

853 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
854 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
855 1c8addc6 Michael Hanselmann
  @param nic: NIC object
856 1c8addc6 Michael Hanselmann

857 1c8addc6 Michael Hanselmann
  """
858 1c8addc6 Michael Hanselmann
  if nic.ip is None:
859 e2d188cc Iustin Pop
    return _FS_UNAVAIL
860 1c8addc6 Michael Hanselmann
  else:
861 e2d188cc Iustin Pop
    return nic.ip
862 1c8addc6 Michael Hanselmann
863 1c8addc6 Michael Hanselmann
864 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
865 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
866 1c8addc6 Michael Hanselmann

867 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
868 1c8addc6 Michael Hanselmann
  @type index: int
869 1c8addc6 Michael Hanselmann
  @param index: NIC index
870 1c8addc6 Michael Hanselmann

871 1c8addc6 Michael Hanselmann
  """
872 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
873 1c8addc6 Michael Hanselmann
874 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
875 1c8addc6 Michael Hanselmann
876 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
877 e2d188cc Iustin Pop
    return nicparams[constants.NIC_LINK]
878 1c8addc6 Michael Hanselmann
  else:
879 e2d188cc Iustin Pop
    return _FS_UNAVAIL
880 1c8addc6 Michael Hanselmann
881 1c8addc6 Michael Hanselmann
882 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
883 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
884 1c8addc6 Michael Hanselmann

885 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
886 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
887 1c8addc6 Michael Hanselmann
  @param inst: Instance object
888 1c8addc6 Michael Hanselmann

889 1c8addc6 Michael Hanselmann
  """
890 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
891 1c8addc6 Michael Hanselmann
892 1c8addc6 Michael Hanselmann
  result = []
893 1c8addc6 Michael Hanselmann
894 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
895 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
896 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
897 1c8addc6 Michael Hanselmann
    else:
898 1c8addc6 Michael Hanselmann
      result.append(None)
899 1c8addc6 Michael Hanselmann
900 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
901 1c8addc6 Michael Hanselmann
902 e2d188cc Iustin Pop
  return result
903 1c8addc6 Michael Hanselmann
904 1c8addc6 Michael Hanselmann
905 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
906 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
907 1c8addc6 Michael Hanselmann

908 1c8addc6 Michael Hanselmann
  @type name: string
909 1c8addc6 Michael Hanselmann
  @param name: Parameter name
910 1c8addc6 Michael Hanselmann

911 1c8addc6 Michael Hanselmann
  """
912 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
913 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
914 1c8addc6 Michael Hanselmann

915 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
916 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
917 1c8addc6 Michael Hanselmann
    @param inst: Instance object
918 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
919 1c8addc6 Michael Hanselmann
    @param nic: NIC object
920 1c8addc6 Michael Hanselmann

921 1c8addc6 Michael Hanselmann
    """
922 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
923 e2d188cc Iustin Pop
    return ctx.inst_nicparams[index][name]
924 1c8addc6 Michael Hanselmann
925 1c8addc6 Michael Hanselmann
  return fn
926 1c8addc6 Michael Hanselmann
927 1c8addc6 Michael Hanselmann
928 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
929 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
930 1c8addc6 Michael Hanselmann

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

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

989 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
990 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
991 1c8addc6 Michael Hanselmann
  @param inst: Instance object
992 1c8addc6 Michael Hanselmann

993 1c8addc6 Michael Hanselmann
  """
994 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
995 1c8addc6 Michael Hanselmann
996 1c8addc6 Michael Hanselmann
  if usage is None:
997 1c8addc6 Michael Hanselmann
    usage = 0
998 1c8addc6 Michael Hanselmann
999 e2d188cc Iustin Pop
  return usage
1000 1c8addc6 Michael Hanselmann
1001 1c8addc6 Michael Hanselmann
1002 5d28cb6f Michael Hanselmann
def _GetInstanceConsole(ctx, inst):
1003 5d28cb6f Michael Hanselmann
  """Get console information for instance.
1004 5d28cb6f Michael Hanselmann

1005 5d28cb6f Michael Hanselmann
  @type ctx: L{InstanceQueryData}
1006 5d28cb6f Michael Hanselmann
  @type inst: L{objects.Instance}
1007 5d28cb6f Michael Hanselmann
  @param inst: Instance object
1008 5d28cb6f Michael Hanselmann

1009 5d28cb6f Michael Hanselmann
  """
1010 5d28cb6f Michael Hanselmann
  consinfo = ctx.console[inst.name]
1011 5d28cb6f Michael Hanselmann
1012 5d28cb6f Michael Hanselmann
  if consinfo is None:
1013 5d28cb6f Michael Hanselmann
    return _FS_UNAVAIL
1014 5d28cb6f Michael Hanselmann
1015 5d28cb6f Michael Hanselmann
  return consinfo
1016 5d28cb6f Michael Hanselmann
1017 5d28cb6f Michael Hanselmann
1018 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
1019 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
1020 1c8addc6 Michael Hanselmann

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

1023 1c8addc6 Michael Hanselmann
  """
1024 1c8addc6 Michael Hanselmann
  fields = [
1025 82599b3e Iustin Pop
    (_MakeField("disk_usage", "DiskUsage", QFT_UNIT), IQ_DISKUSAGE,
1026 1c8addc6 Michael Hanselmann
     _GetInstDiskUsage),
1027 82599b3e Iustin Pop
    (_MakeField("disk.count", "Disks", QFT_NUMBER), IQ_CONFIG,
1028 e2d188cc Iustin Pop
     lambda ctx, inst: len(inst.disks)),
1029 82599b3e Iustin Pop
    (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER), IQ_CONFIG,
1030 e2d188cc Iustin Pop
     lambda ctx, inst: [disk.size for disk in inst.disks]),
1031 1c8addc6 Michael Hanselmann
    ]
1032 1c8addc6 Michael Hanselmann
1033 1c8addc6 Michael Hanselmann
  # Disks by number
1034 1c8addc6 Michael Hanselmann
  fields.extend([
1035 82599b3e Iustin Pop
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT),
1036 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstDiskSize(i))
1037 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
1038 1c8addc6 Michael Hanselmann
    ])
1039 1c8addc6 Michael Hanselmann
1040 1c8addc6 Michael Hanselmann
  return fields
1041 1c8addc6 Michael Hanselmann
1042 1c8addc6 Michael Hanselmann
1043 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
1044 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
1045 1c8addc6 Michael Hanselmann

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

1048 1c8addc6 Michael Hanselmann
  """
1049 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
1050 1c8addc6 Michael Hanselmann
  be_title = {
1051 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
1052 0ca7e384 Iustin Pop
    constants.BE_MEMORY: "ConfigMemory",
1053 0ca7e384 Iustin Pop
    constants.BE_VCPUS: "ConfigVCPUs",
1054 1c8addc6 Michael Hanselmann
    }
1055 1c8addc6 Michael Hanselmann
1056 1c8addc6 Michael Hanselmann
  hv_title = {
1057 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
1058 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
1059 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
1060 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
1061 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
1062 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
1063 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
1064 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
1065 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
1066 1c8addc6 Michael Hanselmann
    }
1067 1c8addc6 Michael Hanselmann
1068 1c8addc6 Michael Hanselmann
  fields = [
1069 1c8addc6 Michael Hanselmann
    # Filled parameters
1070 82599b3e Iustin Pop
    (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER),
1071 e2d188cc Iustin Pop
     IQ_CONFIG, lambda ctx, _: ctx.inst_hvparams),
1072 82599b3e Iustin Pop
    (_MakeField("beparams", "BackendParameters", QFT_OTHER),
1073 e2d188cc Iustin Pop
     IQ_CONFIG, lambda ctx, _: ctx.inst_beparams),
1074 1c8addc6 Michael Hanselmann
1075 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1076 82599b3e Iustin Pop
    (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER),
1077 e2d188cc Iustin Pop
     IQ_CONFIG, _GetItemAttr("hvparams")),
1078 82599b3e Iustin Pop
    (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER),
1079 e2d188cc Iustin Pop
     IQ_CONFIG, _GetItemAttr("beparams")),
1080 82599b3e Iustin Pop
    (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER),
1081 e2d188cc Iustin Pop
     IQ_CONFIG, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
1082 1c8addc6 Michael Hanselmann
    ]
1083 1c8addc6 Michael Hanselmann
1084 1c8addc6 Michael Hanselmann
  # HV params
1085 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1086 ff4cd4d2 Iustin Pop
    return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL)
1087 1c8addc6 Michael Hanselmann
1088 1c8addc6 Michael Hanselmann
  fields.extend([
1089 af58707c Iustin Pop
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1090 af58707c Iustin Pop
                _VTToQFT[kind]),
1091 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstHvParam(name))
1092 af58707c Iustin Pop
    for name, kind in constants.HVS_PARAMETER_TYPES.items()
1093 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1094 1c8addc6 Michael Hanselmann
    ])
1095 1c8addc6 Michael Hanselmann
1096 1c8addc6 Michael Hanselmann
  # BE params
1097 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1098 e2d188cc Iustin Pop
    return lambda ctx, _: ctx.inst_beparams.get(name, None)
1099 1c8addc6 Michael Hanselmann
1100 1c8addc6 Michael Hanselmann
  fields.extend([
1101 af58707c Iustin Pop
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1102 af58707c Iustin Pop
                _VTToQFT[kind]), IQ_CONFIG,
1103 af58707c Iustin Pop
     _GetInstBeParam(name))
1104 af58707c Iustin Pop
    for name, kind in constants.BES_PARAMETER_TYPES.items()
1105 1c8addc6 Michael Hanselmann
    ])
1106 1c8addc6 Michael Hanselmann
1107 1c8addc6 Michael Hanselmann
  return fields
1108 1c8addc6 Michael Hanselmann
1109 1c8addc6 Michael Hanselmann
1110 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1111 82599b3e Iustin Pop
  "disk_template": ("Disk_template", QFT_TEXT),
1112 82599b3e Iustin Pop
  "hypervisor": ("Hypervisor", QFT_TEXT),
1113 f5182ecb Michael Hanselmann
  "name": ("Instance", QFT_TEXT),
1114 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1115 82599b3e Iustin Pop
  "network_port": ("Network_port", QFT_OTHER),
1116 82599b3e Iustin Pop
  "os": ("OS", QFT_TEXT),
1117 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
1118 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
1119 1c8addc6 Michael Hanselmann
  }
1120 1c8addc6 Michael Hanselmann
1121 1c8addc6 Michael Hanselmann
1122 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1123 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1124 1c8addc6 Michael Hanselmann

1125 1c8addc6 Michael Hanselmann
  """
1126 1c8addc6 Michael Hanselmann
  fields = [
1127 82599b3e Iustin Pop
    (_MakeField("pnode", "Primary_node", QFT_TEXT), IQ_CONFIG,
1128 e2d188cc Iustin Pop
     _GetItemAttr("primary_node")),
1129 82599b3e Iustin Pop
    (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER), IQ_CONFIG,
1130 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.secondary_nodes)),
1131 82599b3e Iustin Pop
    (_MakeField("admin_state", "Autostart", QFT_BOOL), IQ_CONFIG,
1132 e2d188cc Iustin Pop
     _GetItemAttr("admin_up")),
1133 82599b3e Iustin Pop
    (_MakeField("tags", "Tags", QFT_OTHER), IQ_CONFIG,
1134 e2d188cc Iustin Pop
     lambda ctx, inst: list(inst.GetTags())),
1135 5d28cb6f Michael Hanselmann
    (_MakeField("console", "Console", QFT_OTHER), IQ_CONSOLE,
1136 5d28cb6f Michael Hanselmann
     _GetInstanceConsole),
1137 1c8addc6 Michael Hanselmann
    ]
1138 1c8addc6 Michael Hanselmann
1139 1c8addc6 Michael Hanselmann
  # Add simple fields
1140 1c8addc6 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), IQ_CONFIG, _GetItemAttr(name))
1141 1c8addc6 Michael Hanselmann
                 for (name, (title, kind)) in _INST_SIMPLE_FIELDS.items()])
1142 1c8addc6 Michael Hanselmann
1143 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1144 1c8addc6 Michael Hanselmann
  fields.extend([
1145 82599b3e Iustin Pop
    (_MakeField("oper_state", "Running", QFT_BOOL), IQ_LIVE,
1146 1c8addc6 Michael Hanselmann
     _GetInstOperState),
1147 0ca7e384 Iustin Pop
    (_MakeField("oper_ram", "Memory", QFT_UNIT), IQ_LIVE,
1148 1c8addc6 Michael Hanselmann
     _GetInstLiveData("memory")),
1149 0ca7e384 Iustin Pop
    (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER), IQ_LIVE,
1150 1c8addc6 Michael Hanselmann
     _GetInstLiveData("vcpus")),
1151 82599b3e Iustin Pop
    (_MakeField("status", "Status", QFT_TEXT), IQ_LIVE, _GetInstStatus),
1152 1c8addc6 Michael Hanselmann
    ])
1153 1c8addc6 Michael Hanselmann
1154 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1155 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1156 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceNetworkFields())
1157 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1158 1c8addc6 Michael Hanselmann
1159 e7e8037b Iustin Pop
  aliases = [
1160 e7e8037b Iustin Pop
    ("vcpus", "be/vcpus"),
1161 e7e8037b Iustin Pop
    ("sda_size", "disk.size/0"),
1162 e7e8037b Iustin Pop
    ("sdb_size", "disk.size/1"),
1163 e7e8037b Iustin Pop
    ]
1164 e7e8037b Iustin Pop
1165 e7e8037b Iustin Pop
  return _PrepareFieldList(fields, aliases)
1166 1c8addc6 Michael Hanselmann
1167 1c8addc6 Michael Hanselmann
1168 24d16f76 Michael Hanselmann
class LockQueryData:
1169 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1170 24d16f76 Michael Hanselmann

1171 24d16f76 Michael Hanselmann
  """
1172 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1173 24d16f76 Michael Hanselmann
    """Initializes this class.
1174 24d16f76 Michael Hanselmann

1175 24d16f76 Michael Hanselmann
    """
1176 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1177 24d16f76 Michael Hanselmann
1178 24d16f76 Michael Hanselmann
  def __iter__(self):
1179 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1180 24d16f76 Michael Hanselmann

1181 24d16f76 Michael Hanselmann
    """
1182 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1183 24d16f76 Michael Hanselmann
1184 24d16f76 Michael Hanselmann
1185 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1186 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1187 24d16f76 Michael Hanselmann

1188 24d16f76 Michael Hanselmann
  """
1189 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1190 24d16f76 Michael Hanselmann
1191 24d16f76 Michael Hanselmann
  if owners:
1192 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1193 24d16f76 Michael Hanselmann
1194 e2d188cc Iustin Pop
  return owners
1195 24d16f76 Michael Hanselmann
1196 24d16f76 Michael Hanselmann
1197 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1198 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1199 24d16f76 Michael Hanselmann

1200 24d16f76 Michael Hanselmann
  """
1201 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1202 24d16f76 Michael Hanselmann
1203 24d16f76 Michael Hanselmann
  if pending:
1204 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1205 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1206 24d16f76 Michael Hanselmann
1207 e2d188cc Iustin Pop
  return pending
1208 24d16f76 Michael Hanselmann
1209 24d16f76 Michael Hanselmann
1210 24d16f76 Michael Hanselmann
def _BuildLockFields():
1211 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1212 24d16f76 Michael Hanselmann

1213 24d16f76 Michael Hanselmann
  """
1214 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1215 82599b3e Iustin Pop
    (_MakeField("name", "Name", QFT_TEXT), None,
1216 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): name),
1217 82599b3e Iustin Pop
    (_MakeField("mode", "Mode", QFT_OTHER), LQ_MODE,
1218 e2d188cc Iustin Pop
     lambda ctx, (name, mode, owners, pending): mode),
1219 82599b3e Iustin Pop
    (_MakeField("owner", "Owner", QFT_OTHER), LQ_OWNER, _GetLockOwners),
1220 82599b3e Iustin Pop
    (_MakeField("pending", "Pending", QFT_OTHER), LQ_PENDING, _GetLockPending),
1221 d63bd540 Iustin Pop
    ], [])
1222 24d16f76 Michael Hanselmann
1223 24d16f76 Michael Hanselmann
1224 8e21cfc0 Adeodato Simo
class GroupQueryData:
1225 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1226 8e21cfc0 Adeodato Simo

1227 8e21cfc0 Adeodato Simo
  """
1228 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1229 8e21cfc0 Adeodato Simo
    """Initializes this class.
1230 8e21cfc0 Adeodato Simo

1231 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1232 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1233 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1234 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1235 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1236 8e21cfc0 Adeodato Simo

1237 8e21cfc0 Adeodato Simo
    """
1238 8e21cfc0 Adeodato Simo
    self.groups = groups
1239 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1240 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1241 8e21cfc0 Adeodato Simo
1242 8e21cfc0 Adeodato Simo
  def __iter__(self):
1243 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1244 8e21cfc0 Adeodato Simo

1245 8e21cfc0 Adeodato Simo
    """
1246 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1247 8e21cfc0 Adeodato Simo
1248 8e21cfc0 Adeodato Simo
1249 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1250 82599b3e Iustin Pop
  "alloc_policy": ("AllocPolicy", QFT_TEXT),
1251 82599b3e Iustin Pop
  "name": ("Group", QFT_TEXT),
1252 82599b3e Iustin Pop
  "serial_no": ("SerialNo", QFT_NUMBER),
1253 82599b3e Iustin Pop
  "uuid": ("UUID", QFT_TEXT),
1254 82599b3e Iustin Pop
  "ndparams": ("NDParams", QFT_OTHER),
1255 8e21cfc0 Adeodato Simo
  }
1256 8e21cfc0 Adeodato Simo
1257 8e21cfc0 Adeodato Simo
1258 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1259 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1260 8e21cfc0 Adeodato Simo

1261 8e21cfc0 Adeodato Simo
  """
1262 8e21cfc0 Adeodato Simo
  # Add simple fields
1263 8e21cfc0 Adeodato Simo
  fields = [(_MakeField(name, title, kind), GQ_CONFIG, _GetItemAttr(name))
1264 8e21cfc0 Adeodato Simo
            for (name, (title, kind)) in _GROUP_SIMPLE_FIELDS.items()]
1265 8e21cfc0 Adeodato Simo
1266 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1267 e2d188cc Iustin Pop
    return lambda ctx, group: len(getter(ctx)[group.uuid])
1268 8e21cfc0 Adeodato Simo
1269 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1270 e2d188cc Iustin Pop
    return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid])
1271 8e21cfc0 Adeodato Simo
1272 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1273 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1274 8e21cfc0 Adeodato Simo
1275 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1276 8e21cfc0 Adeodato Simo
  fields.extend([
1277 82599b3e Iustin Pop
    (_MakeField("node_cnt", "Nodes", QFT_NUMBER),
1278 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetLength(group_to_nodes)),
1279 82599b3e Iustin Pop
    (_MakeField("node_list", "NodeList", QFT_OTHER),
1280 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetSortedList(group_to_nodes)),
1281 8e21cfc0 Adeodato Simo
    ])
1282 8e21cfc0 Adeodato Simo
1283 8e21cfc0 Adeodato Simo
  # Add fields for instances
1284 8e21cfc0 Adeodato Simo
  fields.extend([
1285 82599b3e Iustin Pop
    (_MakeField("pinst_cnt", "Instances", QFT_NUMBER),
1286 8e21cfc0 Adeodato Simo
     GQ_INST, _GetLength(group_to_instances)),
1287 82599b3e Iustin Pop
    (_MakeField("pinst_list", "InstanceList", QFT_OTHER),
1288 8e21cfc0 Adeodato Simo
     GQ_INST, _GetSortedList(group_to_instances)),
1289 8e21cfc0 Adeodato Simo
    ])
1290 8e21cfc0 Adeodato Simo
1291 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1292 8e21cfc0 Adeodato Simo
1293 d63bd540 Iustin Pop
  return _PrepareFieldList(fields, [])
1294 8e21cfc0 Adeodato Simo
1295 8e21cfc0 Adeodato Simo
1296 8235fe04 Michael Hanselmann
#: Fields available for node queries
1297 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
1298 1c8addc6 Michael Hanselmann
1299 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
1300 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
1301 24d16f76 Michael Hanselmann
1302 24d16f76 Michael Hanselmann
#: Fields available for lock queries
1303 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
1304 e571ee44 Adeodato Simo
1305 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
1306 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
1307 8e21cfc0 Adeodato Simo
1308 e571ee44 Adeodato Simo
#: All available field lists
1309 8e21cfc0 Adeodato Simo
ALL_FIELD_LISTS = [NODE_FIELDS, INSTANCE_FIELDS, LOCK_FIELDS, GROUP_FIELDS]