Statistics
| Branch: | Tag: | Revision:

root / lib / query.py @ f13973c4

History | View | Annotate | Download (36.2 kB)

1 4ca96421 Michael Hanselmann
#
2 4ca96421 Michael Hanselmann
#
3 4ca96421 Michael Hanselmann
4 4ca96421 Michael Hanselmann
# Copyright (C) 2010 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 4ca96421 Michael Hanselmann
65 8f8ce6d1 Michael Hanselmann
# Constants for requesting data from the caller/data provider. Each property
66 8f8ce6d1 Michael Hanselmann
# collected/computed separately by the data provider should have its own to
67 8f8ce6d1 Michael Hanselmann
# only collect the requested data and not more.
68 8f8ce6d1 Michael Hanselmann
69 8235fe04 Michael Hanselmann
(NQ_CONFIG,
70 8235fe04 Michael Hanselmann
 NQ_INST,
71 8235fe04 Michael Hanselmann
 NQ_LIVE,
72 52b5d286 René Nussbaumer
 NQ_GROUP,
73 52b5d286 René Nussbaumer
 NQ_OOB) = range(1, 6)
74 8235fe04 Michael Hanselmann
75 1c8addc6 Michael Hanselmann
(IQ_CONFIG,
76 1c8addc6 Michael Hanselmann
 IQ_LIVE,
77 1c8addc6 Michael Hanselmann
 IQ_DISKUSAGE) = range(100, 103)
78 1c8addc6 Michael Hanselmann
79 24d16f76 Michael Hanselmann
(LQ_MODE,
80 24d16f76 Michael Hanselmann
 LQ_OWNER,
81 24d16f76 Michael Hanselmann
 LQ_PENDING) = range(10, 13)
82 8235fe04 Michael Hanselmann
83 8e21cfc0 Adeodato Simo
(GQ_CONFIG,
84 8e21cfc0 Adeodato Simo
 GQ_NODE,
85 8e21cfc0 Adeodato Simo
 GQ_INST) = range(200, 203)
86 8e21cfc0 Adeodato Simo
87 8e21cfc0 Adeodato Simo
88 4ca96421 Michael Hanselmann
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
89 4ca96421 Michael Hanselmann
TITLE_RE = re.compile(r"^[^\s]+$")
90 4ca96421 Michael Hanselmann
91 4ca96421 Michael Hanselmann
#: Verification function for each field type
92 4ca96421 Michael Hanselmann
_VERIFY_FN = {
93 4ca96421 Michael Hanselmann
  constants.QFT_UNKNOWN: ht.TNone,
94 4ca96421 Michael Hanselmann
  constants.QFT_TEXT: ht.TString,
95 4ca96421 Michael Hanselmann
  constants.QFT_BOOL: ht.TBool,
96 4ca96421 Michael Hanselmann
  constants.QFT_NUMBER: ht.TInt,
97 4ca96421 Michael Hanselmann
  constants.QFT_UNIT: ht.TInt,
98 4ca96421 Michael Hanselmann
  constants.QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat),
99 4ca96421 Michael Hanselmann
  constants.QFT_OTHER: lambda _: True,
100 4ca96421 Michael Hanselmann
  }
101 4ca96421 Michael Hanselmann
102 4ca96421 Michael Hanselmann
103 4ca96421 Michael Hanselmann
def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
104 4ca96421 Michael Hanselmann
  """Gets the contents of an unknown field.
105 4ca96421 Michael Hanselmann

106 4ca96421 Michael Hanselmann
  """
107 4ca96421 Michael Hanselmann
  return (constants.QRFS_UNKNOWN, None)
108 4ca96421 Michael Hanselmann
109 4ca96421 Michael Hanselmann
110 4ca96421 Michael Hanselmann
def _GetQueryFields(fielddefs, selected):
111 4ca96421 Michael Hanselmann
  """Calculates the internal list of selected fields.
112 4ca96421 Michael Hanselmann

113 4ca96421 Michael Hanselmann
  Unknown fields are returned as L{constants.QFT_UNKNOWN}.
114 4ca96421 Michael Hanselmann

115 4ca96421 Michael Hanselmann
  @type fielddefs: dict
116 4ca96421 Michael Hanselmann
  @param fielddefs: Field definitions
117 4ca96421 Michael Hanselmann
  @type selected: list of strings
118 4ca96421 Michael Hanselmann
  @param selected: List of selected fields
119 4ca96421 Michael Hanselmann

120 4ca96421 Michael Hanselmann
  """
121 4ca96421 Michael Hanselmann
  result = []
122 4ca96421 Michael Hanselmann
123 4ca96421 Michael Hanselmann
  for name in selected:
124 4ca96421 Michael Hanselmann
    try:
125 4ca96421 Michael Hanselmann
      fdef = fielddefs[name]
126 4ca96421 Michael Hanselmann
    except KeyError:
127 4ca96421 Michael Hanselmann
      fdef = (_MakeField(name, name, constants.QFT_UNKNOWN),
128 4ca96421 Michael Hanselmann
              None, _GetUnknownField)
129 4ca96421 Michael Hanselmann
130 4ca96421 Michael Hanselmann
    assert len(fdef) == 3
131 4ca96421 Michael Hanselmann
132 4ca96421 Michael Hanselmann
    result.append(fdef)
133 4ca96421 Michael Hanselmann
134 4ca96421 Michael Hanselmann
  return result
135 4ca96421 Michael Hanselmann
136 4ca96421 Michael Hanselmann
137 4ca96421 Michael Hanselmann
def GetAllFields(fielddefs):
138 4ca96421 Michael Hanselmann
  """Extract L{objects.QueryFieldDefinition} from field definitions.
139 4ca96421 Michael Hanselmann

140 4ca96421 Michael Hanselmann
  @rtype: list of L{objects.QueryFieldDefinition}
141 4ca96421 Michael Hanselmann

142 4ca96421 Michael Hanselmann
  """
143 4ca96421 Michael Hanselmann
  return [fdef for (fdef, _, _) in fielddefs]
144 4ca96421 Michael Hanselmann
145 4ca96421 Michael Hanselmann
146 4ca96421 Michael Hanselmann
class Query:
147 4ca96421 Michael Hanselmann
  def __init__(self, fieldlist, selected):
148 4ca96421 Michael Hanselmann
    """Initializes this class.
149 4ca96421 Michael Hanselmann

150 4ca96421 Michael Hanselmann
    The field definition is a dictionary with the field's name as a key and a
151 4ca96421 Michael Hanselmann
    tuple containing, in order, the field definition object
152 4ca96421 Michael Hanselmann
    (L{objects.QueryFieldDefinition}, the data kind to help calling code
153 4ca96421 Michael Hanselmann
    collect data and a retrieval function. The retrieval function is called
154 4ca96421 Michael Hanselmann
    with two parameters, in order, the data container and the item in container
155 4ca96421 Michael Hanselmann
    (see L{Query.Query}).
156 4ca96421 Michael Hanselmann

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

160 4ca96421 Michael Hanselmann
    @type fieldlist: dictionary
161 4ca96421 Michael Hanselmann
    @param fieldlist: Field definitions
162 4ca96421 Michael Hanselmann
    @type selected: list of strings
163 4ca96421 Michael Hanselmann
    @param selected: List of selected fields
164 4ca96421 Michael Hanselmann

165 4ca96421 Michael Hanselmann
    """
166 4ca96421 Michael Hanselmann
    self._fields = _GetQueryFields(fieldlist, selected)
167 4ca96421 Michael Hanselmann
168 4ca96421 Michael Hanselmann
  def RequestedData(self):
169 4ca96421 Michael Hanselmann
    """Gets requested kinds of data.
170 4ca96421 Michael Hanselmann

171 4ca96421 Michael Hanselmann
    @rtype: frozenset
172 4ca96421 Michael Hanselmann

173 4ca96421 Michael Hanselmann
    """
174 4ca96421 Michael Hanselmann
    return frozenset(datakind
175 4ca96421 Michael Hanselmann
                     for (_, datakind, _) in self._fields
176 4ca96421 Michael Hanselmann
                     if datakind is not None)
177 4ca96421 Michael Hanselmann
178 4ca96421 Michael Hanselmann
  def GetFields(self):
179 4ca96421 Michael Hanselmann
    """Returns the list of fields for this query.
180 4ca96421 Michael Hanselmann

181 4ca96421 Michael Hanselmann
    Includes unknown fields.
182 4ca96421 Michael Hanselmann

183 4ca96421 Michael Hanselmann
    @rtype: List of L{objects.QueryFieldDefinition}
184 4ca96421 Michael Hanselmann

185 4ca96421 Michael Hanselmann
    """
186 4ca96421 Michael Hanselmann
    return GetAllFields(self._fields)
187 4ca96421 Michael Hanselmann
188 4ca96421 Michael Hanselmann
  def Query(self, ctx):
189 4ca96421 Michael Hanselmann
    """Execute a query.
190 4ca96421 Michael Hanselmann

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

194 4ca96421 Michael Hanselmann
    """
195 4ca96421 Michael Hanselmann
    result = [[fn(ctx, item) for (_, _, fn) in self._fields]
196 4ca96421 Michael Hanselmann
              for item in ctx]
197 4ca96421 Michael Hanselmann
198 4ca96421 Michael Hanselmann
    # Verify result
199 4ca96421 Michael Hanselmann
    if __debug__:
200 4ca96421 Michael Hanselmann
      for (idx, row) in enumerate(result):
201 4ca96421 Michael Hanselmann
        assert _VerifyResultRow(self._fields, row), \
202 4ca96421 Michael Hanselmann
               ("Inconsistent result for fields %s in row %s: %r" %
203 89ce4acc Michael Hanselmann
                (GetAllFields(self._fields), idx, row))
204 4ca96421 Michael Hanselmann
205 4ca96421 Michael Hanselmann
    return result
206 4ca96421 Michael Hanselmann
207 4ca96421 Michael Hanselmann
  def OldStyleQuery(self, ctx):
208 4ca96421 Michael Hanselmann
    """Query with "old" query result format.
209 4ca96421 Michael Hanselmann

210 4ca96421 Michael Hanselmann
    See L{Query.Query} for arguments.
211 4ca96421 Michael Hanselmann

212 4ca96421 Michael Hanselmann
    """
213 4ca96421 Michael Hanselmann
    unknown = set(fdef.name
214 4ca96421 Michael Hanselmann
                  for (fdef, _, _) in self._fields
215 4ca96421 Michael Hanselmann
                  if fdef.kind == constants.QFT_UNKNOWN)
216 4ca96421 Michael Hanselmann
    if unknown:
217 4ca96421 Michael Hanselmann
      raise errors.OpPrereqError("Unknown output fields selected: %s" %
218 4ca96421 Michael Hanselmann
                                 (utils.CommaJoin(unknown), ),
219 4ca96421 Michael Hanselmann
                                 errors.ECODE_INVAL)
220 4ca96421 Michael Hanselmann
221 4ca96421 Michael Hanselmann
    return [[value for (_, value) in row]
222 4ca96421 Michael Hanselmann
            for row in self.Query(ctx)]
223 4ca96421 Michael Hanselmann
224 4ca96421 Michael Hanselmann
225 4ca96421 Michael Hanselmann
def _VerifyResultRow(fields, row):
226 4ca96421 Michael Hanselmann
  """Verifies the contents of a query result row.
227 4ca96421 Michael Hanselmann

228 4ca96421 Michael Hanselmann
  @type fields: list
229 4ca96421 Michael Hanselmann
  @param fields: Field definitions for result
230 4ca96421 Michael Hanselmann
  @type row: list of tuples
231 4ca96421 Michael Hanselmann
  @param row: Row data
232 4ca96421 Michael Hanselmann

233 4ca96421 Michael Hanselmann
  """
234 4ca96421 Michael Hanselmann
  return (len(row) == len(fields) and
235 4ca96421 Michael Hanselmann
          compat.all((status == constants.QRFS_NORMAL and
236 4ca96421 Michael Hanselmann
                      _VERIFY_FN[fdef.kind](value)) or
237 4ca96421 Michael Hanselmann
                     # Value for an abnormal status must be None
238 4ca96421 Michael Hanselmann
                     (status != constants.QRFS_NORMAL and value is None)
239 4ca96421 Michael Hanselmann
                     for ((status, value), (fdef, _, _)) in zip(row, fields)))
240 4ca96421 Michael Hanselmann
241 4ca96421 Michael Hanselmann
242 4ca96421 Michael Hanselmann
def _PrepareFieldList(fields):
243 4ca96421 Michael Hanselmann
  """Prepares field list for use by L{Query}.
244 4ca96421 Michael Hanselmann

245 4ca96421 Michael Hanselmann
  Converts the list to a dictionary and does some verification.
246 4ca96421 Michael Hanselmann

247 4ca96421 Michael Hanselmann
  @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data kind,
248 4ca96421 Michael Hanselmann
    retrieval function)
249 8f8ce6d1 Michael Hanselmann
  @param fields: List of fields, see L{Query.__init__} for a better description
250 4ca96421 Michael Hanselmann
  @rtype: dict
251 4ca96421 Michael Hanselmann
  @return: Field dictionary for L{Query}
252 4ca96421 Michael Hanselmann

253 4ca96421 Michael Hanselmann
  """
254 89ce4acc Michael Hanselmann
  if __debug__:
255 89ce4acc Michael Hanselmann
    duplicates = utils.FindDuplicates(fdef.title.lower()
256 89ce4acc Michael Hanselmann
                                      for (fdef, _, _) in fields)
257 89ce4acc Michael Hanselmann
    assert not duplicates, "Duplicate title(s) found: %r" % duplicates
258 4ca96421 Michael Hanselmann
259 4ca96421 Michael Hanselmann
  result = {}
260 4ca96421 Michael Hanselmann
261 4ca96421 Michael Hanselmann
  for field in fields:
262 4ca96421 Michael Hanselmann
    (fdef, _, fn) = field
263 4ca96421 Michael Hanselmann
264 4ca96421 Michael Hanselmann
    assert fdef.name and fdef.title, "Name and title are required"
265 4ca96421 Michael Hanselmann
    assert FIELD_NAME_RE.match(fdef.name)
266 4ca96421 Michael Hanselmann
    assert TITLE_RE.match(fdef.title)
267 4ca96421 Michael Hanselmann
    assert callable(fn)
268 89ce4acc Michael Hanselmann
    assert fdef.name not in result, \
269 89ce4acc Michael Hanselmann
           "Duplicate field name '%s' found" % fdef.name
270 4ca96421 Michael Hanselmann
271 4ca96421 Michael Hanselmann
    result[fdef.name] = field
272 4ca96421 Michael Hanselmann
273 4ca96421 Michael Hanselmann
  assert len(result) == len(fields)
274 4ca96421 Michael Hanselmann
  assert compat.all(name == fdef.name
275 4ca96421 Michael Hanselmann
                    for (name, (fdef, _, _)) in result.items())
276 4ca96421 Michael Hanselmann
277 4ca96421 Michael Hanselmann
  return result
278 4ca96421 Michael Hanselmann
279 4ca96421 Michael Hanselmann
280 b60fcb6f Michael Hanselmann
def GetQueryResponse(query, ctx):
281 b60fcb6f Michael Hanselmann
  """Prepares the response for a query.
282 b60fcb6f Michael Hanselmann

283 b60fcb6f Michael Hanselmann
  @type query: L{Query}
284 b60fcb6f Michael Hanselmann
  @param ctx: Data container, see L{Query.Query}
285 b60fcb6f Michael Hanselmann

286 b60fcb6f Michael Hanselmann
  """
287 b60fcb6f Michael Hanselmann
  return objects.QueryResponse(data=query.Query(ctx),
288 b60fcb6f Michael Hanselmann
                               fields=query.GetFields()).ToDict()
289 b60fcb6f Michael Hanselmann
290 b60fcb6f Michael Hanselmann
291 aa29e95f Michael Hanselmann
def QueryFields(fielddefs, selected):
292 aa29e95f Michael Hanselmann
  """Returns list of available fields.
293 aa29e95f Michael Hanselmann

294 aa29e95f Michael Hanselmann
  @type fielddefs: dict
295 aa29e95f Michael Hanselmann
  @param fielddefs: Field definitions
296 aa29e95f Michael Hanselmann
  @type selected: list of strings
297 aa29e95f Michael Hanselmann
  @param selected: List of selected fields
298 aa29e95f Michael Hanselmann
  @return: List of L{objects.QueryFieldDefinition}
299 aa29e95f Michael Hanselmann

300 aa29e95f Michael Hanselmann
  """
301 aa29e95f Michael Hanselmann
  if selected is None:
302 aa29e95f Michael Hanselmann
    # Client requests all fields, sort by name
303 aa29e95f Michael Hanselmann
    fdefs = utils.NiceSort(GetAllFields(fielddefs.values()),
304 aa29e95f Michael Hanselmann
                           key=operator.attrgetter("name"))
305 aa29e95f Michael Hanselmann
  else:
306 aa29e95f Michael Hanselmann
    # Keep order as requested by client
307 aa29e95f Michael Hanselmann
    fdefs = Query(fielddefs, selected).GetFields()
308 aa29e95f Michael Hanselmann
309 aa29e95f Michael Hanselmann
  return objects.QueryFieldsResponse(fields=fdefs).ToDict()
310 aa29e95f Michael Hanselmann
311 aa29e95f Michael Hanselmann
312 4ca96421 Michael Hanselmann
def _MakeField(name, title, kind):
313 4ca96421 Michael Hanselmann
  """Wrapper for creating L{objects.QueryFieldDefinition} instances.
314 4ca96421 Michael Hanselmann

315 4ca96421 Michael Hanselmann
  @param name: Field name as a regular expression
316 4ca96421 Michael Hanselmann
  @param title: Human-readable title
317 4ca96421 Michael Hanselmann
  @param kind: Field type
318 4ca96421 Michael Hanselmann

319 4ca96421 Michael Hanselmann
  """
320 4ca96421 Michael Hanselmann
  return objects.QueryFieldDefinition(name=name, title=title, kind=kind)
321 8235fe04 Michael Hanselmann
322 8235fe04 Michael Hanselmann
323 8235fe04 Michael Hanselmann
def _GetNodeRole(node, master_name):
324 8235fe04 Michael Hanselmann
  """Determine node role.
325 8235fe04 Michael Hanselmann

326 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
327 8235fe04 Michael Hanselmann
  @param node: Node object
328 8235fe04 Michael Hanselmann
  @type master_name: string
329 8235fe04 Michael Hanselmann
  @param master_name: Master node name
330 8235fe04 Michael Hanselmann

331 8235fe04 Michael Hanselmann
  """
332 8235fe04 Michael Hanselmann
  if node.name == master_name:
333 8235fe04 Michael Hanselmann
    return "M"
334 8235fe04 Michael Hanselmann
  elif node.master_candidate:
335 8235fe04 Michael Hanselmann
    return "C"
336 8235fe04 Michael Hanselmann
  elif node.drained:
337 8235fe04 Michael Hanselmann
    return "D"
338 8235fe04 Michael Hanselmann
  elif node.offline:
339 8235fe04 Michael Hanselmann
    return "O"
340 8235fe04 Michael Hanselmann
  else:
341 8235fe04 Michael Hanselmann
    return "R"
342 8235fe04 Michael Hanselmann
343 8235fe04 Michael Hanselmann
344 8235fe04 Michael Hanselmann
def _GetItemAttr(attr):
345 8235fe04 Michael Hanselmann
  """Returns a field function to return an attribute of the item.
346 8235fe04 Michael Hanselmann

347 8235fe04 Michael Hanselmann
  @param attr: Attribute name
348 8235fe04 Michael Hanselmann

349 8235fe04 Michael Hanselmann
  """
350 8235fe04 Michael Hanselmann
  getter = operator.attrgetter(attr)
351 8235fe04 Michael Hanselmann
  return lambda _, item: (constants.QRFS_NORMAL, getter(item))
352 8235fe04 Michael Hanselmann
353 8235fe04 Michael Hanselmann
354 145bea54 Michael Hanselmann
def _GetItemTimestamp(getter):
355 145bea54 Michael Hanselmann
  """Returns function for getting timestamp of item.
356 145bea54 Michael Hanselmann

357 145bea54 Michael Hanselmann
  @type getter: callable
358 145bea54 Michael Hanselmann
  @param getter: Function to retrieve timestamp attribute
359 145bea54 Michael Hanselmann

360 145bea54 Michael Hanselmann
  """
361 145bea54 Michael Hanselmann
  def fn(_, item):
362 145bea54 Michael Hanselmann
    """Returns a timestamp of item.
363 145bea54 Michael Hanselmann

364 145bea54 Michael Hanselmann
    """
365 145bea54 Michael Hanselmann
    timestamp = getter(item)
366 145bea54 Michael Hanselmann
    if timestamp is None:
367 145bea54 Michael Hanselmann
      # Old configs might not have all timestamps
368 145bea54 Michael Hanselmann
      return (constants.QRFS_UNAVAIL, None)
369 145bea54 Michael Hanselmann
    else:
370 145bea54 Michael Hanselmann
      return (constants.QRFS_NORMAL, timestamp)
371 145bea54 Michael Hanselmann
372 145bea54 Michael Hanselmann
  return fn
373 145bea54 Michael Hanselmann
374 145bea54 Michael Hanselmann
375 145bea54 Michael Hanselmann
def _GetItemTimestampFields(datatype):
376 145bea54 Michael Hanselmann
  """Returns common timestamp fields.
377 145bea54 Michael Hanselmann

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

380 145bea54 Michael Hanselmann
  """
381 145bea54 Michael Hanselmann
  return [
382 145bea54 Michael Hanselmann
    (_MakeField("ctime", "CTime", constants.QFT_TIMESTAMP), datatype,
383 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("ctime"))),
384 145bea54 Michael Hanselmann
    (_MakeField("mtime", "MTime", constants.QFT_TIMESTAMP), datatype,
385 145bea54 Michael Hanselmann
     _GetItemTimestamp(operator.attrgetter("mtime"))),
386 145bea54 Michael Hanselmann
    ]
387 145bea54 Michael Hanselmann
388 145bea54 Michael Hanselmann
389 8235fe04 Michael Hanselmann
class NodeQueryData:
390 8235fe04 Michael Hanselmann
  """Data container for node data queries.
391 8235fe04 Michael Hanselmann

392 8235fe04 Michael Hanselmann
  """
393 8235fe04 Michael Hanselmann
  def __init__(self, nodes, live_data, master_name, node_to_primary,
394 8572f1fe René Nussbaumer
               node_to_secondary, groups, oob_support, cluster):
395 8235fe04 Michael Hanselmann
    """Initializes this class.
396 8235fe04 Michael Hanselmann

397 8235fe04 Michael Hanselmann
    """
398 8235fe04 Michael Hanselmann
    self.nodes = nodes
399 8235fe04 Michael Hanselmann
    self.live_data = live_data
400 8235fe04 Michael Hanselmann
    self.master_name = master_name
401 8235fe04 Michael Hanselmann
    self.node_to_primary = node_to_primary
402 8235fe04 Michael Hanselmann
    self.node_to_secondary = node_to_secondary
403 8235fe04 Michael Hanselmann
    self.groups = groups
404 52b5d286 René Nussbaumer
    self.oob_support = oob_support
405 8572f1fe René Nussbaumer
    self.cluster = cluster
406 8235fe04 Michael Hanselmann
407 8235fe04 Michael Hanselmann
    # Used for individual rows
408 8235fe04 Michael Hanselmann
    self.curlive_data = None
409 8235fe04 Michael Hanselmann
410 8235fe04 Michael Hanselmann
  def __iter__(self):
411 8235fe04 Michael Hanselmann
    """Iterate over all nodes.
412 8235fe04 Michael Hanselmann

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

416 8235fe04 Michael Hanselmann
    """
417 8235fe04 Michael Hanselmann
    for node in self.nodes:
418 8235fe04 Michael Hanselmann
      if self.live_data:
419 8235fe04 Michael Hanselmann
        self.curlive_data = self.live_data.get(node.name, None)
420 8235fe04 Michael Hanselmann
      else:
421 8235fe04 Michael Hanselmann
        self.curlive_data = None
422 8235fe04 Michael Hanselmann
      yield node
423 8235fe04 Michael Hanselmann
424 8235fe04 Michael Hanselmann
425 8235fe04 Michael Hanselmann
#: Fields that are direct attributes of an L{objects.Node} object
426 8235fe04 Michael Hanselmann
_NODE_SIMPLE_FIELDS = {
427 8235fe04 Michael Hanselmann
  "drained": ("Drained", constants.QFT_BOOL),
428 8235fe04 Michael Hanselmann
  "master_candidate": ("MasterC", constants.QFT_BOOL),
429 8235fe04 Michael Hanselmann
  "master_capable": ("MasterCapable", constants.QFT_BOOL),
430 8235fe04 Michael Hanselmann
  "name": ("Node", constants.QFT_TEXT),
431 8235fe04 Michael Hanselmann
  "offline": ("Offline", constants.QFT_BOOL),
432 8235fe04 Michael Hanselmann
  "serial_no": ("SerialNo", constants.QFT_NUMBER),
433 8235fe04 Michael Hanselmann
  "uuid": ("UUID", constants.QFT_TEXT),
434 8235fe04 Michael Hanselmann
  "vm_capable": ("VMCapable", constants.QFT_BOOL),
435 8235fe04 Michael Hanselmann
  }
436 8235fe04 Michael Hanselmann
437 8235fe04 Michael Hanselmann
438 8235fe04 Michael Hanselmann
#: Fields requiring talking to the node
439 8235fe04 Michael Hanselmann
_NODE_LIVE_FIELDS = {
440 8235fe04 Michael Hanselmann
  "bootid": ("BootID", constants.QFT_TEXT, "bootid"),
441 8235fe04 Michael Hanselmann
  "cnodes": ("CNodes", constants.QFT_NUMBER, "cpu_nodes"),
442 8235fe04 Michael Hanselmann
  "csockets": ("CSockets", constants.QFT_NUMBER, "cpu_sockets"),
443 8235fe04 Michael Hanselmann
  "ctotal": ("CTotal", constants.QFT_NUMBER, "cpu_total"),
444 8235fe04 Michael Hanselmann
  "dfree": ("DFree", constants.QFT_UNIT, "vg_free"),
445 8235fe04 Michael Hanselmann
  "dtotal": ("DTotal", constants.QFT_UNIT, "vg_size"),
446 8235fe04 Michael Hanselmann
  "mfree": ("MFree", constants.QFT_UNIT, "memory_free"),
447 8235fe04 Michael Hanselmann
  "mnode": ("MNode", constants.QFT_UNIT, "memory_dom0"),
448 8235fe04 Michael Hanselmann
  "mtotal": ("MTotal", constants.QFT_UNIT, "memory_total"),
449 8235fe04 Michael Hanselmann
  }
450 8235fe04 Michael Hanselmann
451 8235fe04 Michael Hanselmann
452 8572f1fe René Nussbaumer
def _GetGroup(cb):
453 8572f1fe René Nussbaumer
  """Build function for calling another function with an node group.
454 8572f1fe René Nussbaumer

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

457 8572f1fe René Nussbaumer
  """
458 8572f1fe René Nussbaumer
  def fn(ctx, node):
459 8572f1fe René Nussbaumer
    """Get group data for a node.
460 8572f1fe René Nussbaumer

461 8572f1fe René Nussbaumer
    @type ctx: L{NodeQueryData}
462 8572f1fe René Nussbaumer
    @type inst: L{objects.Node}
463 8572f1fe René Nussbaumer
    @param inst: Node object
464 8572f1fe René Nussbaumer

465 8572f1fe René Nussbaumer
    """
466 8572f1fe René Nussbaumer
    ng = ctx.groups.get(node.group, None)
467 8572f1fe René Nussbaumer
    if ng is None:
468 8572f1fe René Nussbaumer
      # Nodes always have a group, or the configuration is corrupt
469 8572f1fe René Nussbaumer
      return (constants.QRFS_UNAVAIL, None)
470 8572f1fe René Nussbaumer
471 8572f1fe René Nussbaumer
    return cb(ctx, node, ng)
472 8572f1fe René Nussbaumer
473 8572f1fe René Nussbaumer
  return fn
474 8572f1fe René Nussbaumer
475 8572f1fe René Nussbaumer
476 8572f1fe René Nussbaumer
def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613
477 8235fe04 Michael Hanselmann
  """Returns the name of a node's group.
478 8235fe04 Michael Hanselmann

479 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
480 8235fe04 Michael Hanselmann
  @type node: L{objects.Node}
481 8235fe04 Michael Hanselmann
  @param node: Node object
482 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
483 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
484 8235fe04 Michael Hanselmann

485 8235fe04 Michael Hanselmann
  """
486 8235fe04 Michael Hanselmann
  return (constants.QRFS_NORMAL, ng.name)
487 8235fe04 Michael Hanselmann
488 8235fe04 Michael Hanselmann
489 52b5d286 René Nussbaumer
def _GetNodePower(ctx, node):
490 52b5d286 René Nussbaumer
  """Returns the node powered state
491 52b5d286 René Nussbaumer

492 52b5d286 René Nussbaumer
  @type ctx: L{NodeQueryData}
493 52b5d286 René Nussbaumer
  @type node: L{objects.Node}
494 52b5d286 René Nussbaumer
  @param node: Node object
495 52b5d286 René Nussbaumer

496 52b5d286 René Nussbaumer
  """
497 52b5d286 René Nussbaumer
  if ctx.oob_support[node.name]:
498 52b5d286 René Nussbaumer
    return (constants.QRFS_NORMAL, node.powered)
499 52b5d286 René Nussbaumer
500 52b5d286 René Nussbaumer
  return (constants.QRFS_UNAVAIL, None)
501 52b5d286 René Nussbaumer
502 52b5d286 René Nussbaumer
503 8572f1fe René Nussbaumer
def _GetNdParams(ctx, node, ng):
504 8572f1fe René Nussbaumer
  """Returns the ndparams for this node.
505 8572f1fe René Nussbaumer

506 8572f1fe René Nussbaumer
  @type ctx: L{NodeQueryData}
507 8572f1fe René Nussbaumer
  @type node: L{objects.Node}
508 8572f1fe René Nussbaumer
  @param node: Node object
509 8572f1fe René Nussbaumer
  @type ng: L{objects.NodeGroup}
510 8572f1fe René Nussbaumer
  @param ng: The node group this node belongs to
511 8572f1fe René Nussbaumer

512 8572f1fe René Nussbaumer
  """
513 8572f1fe René Nussbaumer
  return (constants.QRFS_NORMAL, ctx.cluster.SimpleFillND(ng.FillND(node)))
514 8572f1fe René Nussbaumer
515 8572f1fe René Nussbaumer
516 a6070ef7 Michael Hanselmann
def _GetLiveNodeField(field, kind, ctx, node):
517 8235fe04 Michael Hanselmann
  """Gets the value of a "live" field from L{NodeQueryData}.
518 8235fe04 Michael Hanselmann

519 8235fe04 Michael Hanselmann
  @param field: Live field name
520 8235fe04 Michael Hanselmann
  @param kind: Data kind, one of L{constants.QFT_ALL}
521 8235fe04 Michael Hanselmann
  @type ctx: L{NodeQueryData}
522 a6070ef7 Michael Hanselmann
  @type node: L{objects.Node}
523 a6070ef7 Michael Hanselmann
  @param node: Node object
524 8235fe04 Michael Hanselmann

525 8235fe04 Michael Hanselmann
  """
526 a6070ef7 Michael Hanselmann
  if node.offline:
527 a6070ef7 Michael Hanselmann
    return (constants.QRFS_OFFLINE, None)
528 a6070ef7 Michael Hanselmann
529 8235fe04 Michael Hanselmann
  if not ctx.curlive_data:
530 8235fe04 Michael Hanselmann
    return (constants.QRFS_NODATA, None)
531 8235fe04 Michael Hanselmann
532 8235fe04 Michael Hanselmann
  try:
533 8235fe04 Michael Hanselmann
    value = ctx.curlive_data[field]
534 8235fe04 Michael Hanselmann
  except KeyError:
535 8235fe04 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
536 8235fe04 Michael Hanselmann
537 8235fe04 Michael Hanselmann
  if kind == constants.QFT_TEXT:
538 8235fe04 Michael Hanselmann
    return (constants.QRFS_NORMAL, value)
539 8235fe04 Michael Hanselmann
540 8235fe04 Michael Hanselmann
  assert kind in (constants.QFT_NUMBER, constants.QFT_UNIT)
541 8235fe04 Michael Hanselmann
542 8235fe04 Michael Hanselmann
  # Try to convert into number
543 8235fe04 Michael Hanselmann
  try:
544 8235fe04 Michael Hanselmann
    return (constants.QRFS_NORMAL, int(value))
545 8235fe04 Michael Hanselmann
  except (ValueError, TypeError):
546 8235fe04 Michael Hanselmann
    logging.exception("Failed to convert node field '%s' (value %r) to int",
547 8235fe04 Michael Hanselmann
                      value, field)
548 8235fe04 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
549 8235fe04 Michael Hanselmann
550 8235fe04 Michael Hanselmann
551 8235fe04 Michael Hanselmann
def _BuildNodeFields():
552 8235fe04 Michael Hanselmann
  """Builds list of fields for node queries.
553 8235fe04 Michael Hanselmann

554 8235fe04 Michael Hanselmann
  """
555 8235fe04 Michael Hanselmann
  fields = [
556 8235fe04 Michael Hanselmann
    (_MakeField("pip", "PrimaryIP", constants.QFT_TEXT), NQ_CONFIG,
557 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.primary_ip)),
558 8235fe04 Michael Hanselmann
    (_MakeField("sip", "SecondaryIP", constants.QFT_TEXT), NQ_CONFIG,
559 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.secondary_ip)),
560 8235fe04 Michael Hanselmann
    (_MakeField("tags", "Tags", constants.QFT_OTHER), NQ_CONFIG,
561 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, list(node.GetTags()))),
562 8235fe04 Michael Hanselmann
    (_MakeField("master", "IsMaster", constants.QFT_BOOL), NQ_CONFIG,
563 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL, node.name == ctx.master_name)),
564 8235fe04 Michael Hanselmann
    (_MakeField("role", "Role", constants.QFT_TEXT), NQ_CONFIG,
565 8235fe04 Michael Hanselmann
     lambda ctx, node: (constants.QRFS_NORMAL,
566 8235fe04 Michael Hanselmann
                        _GetNodeRole(node, ctx.master_name))),
567 8572f1fe René Nussbaumer
    (_MakeField("group", "Group", constants.QFT_TEXT), NQ_GROUP,
568 8572f1fe René Nussbaumer
     _GetGroup(_GetNodeGroup)),
569 8235fe04 Michael Hanselmann
    (_MakeField("group.uuid", "GroupUUID", constants.QFT_TEXT),
570 8235fe04 Michael Hanselmann
     NQ_CONFIG, lambda ctx, node: (constants.QRFS_NORMAL, node.group)),
571 52b5d286 René Nussbaumer
    (_MakeField("powered", "Powered", constants.QFT_BOOL), NQ_OOB,
572 52b5d286 René Nussbaumer
      _GetNodePower),
573 8572f1fe René Nussbaumer
    (_MakeField("ndparams", "NodeParameters", constants.QFT_OTHER), NQ_GROUP,
574 8572f1fe René Nussbaumer
      _GetGroup(_GetNdParams)),
575 8572f1fe René Nussbaumer
    (_MakeField("custom_ndparams", "CustomNodeParameters", constants.QFT_OTHER),
576 8572f1fe René Nussbaumer
      NQ_GROUP, lambda ctx, node: (constants.QRFS_NORMAL, node.ndparams)),
577 8235fe04 Michael Hanselmann
    ]
578 8235fe04 Michael Hanselmann
579 8235fe04 Michael Hanselmann
  def _GetLength(getter):
580 8235fe04 Michael Hanselmann
    return lambda ctx, node: (constants.QRFS_NORMAL,
581 8235fe04 Michael Hanselmann
                              len(getter(ctx)[node.name]))
582 8235fe04 Michael Hanselmann
583 8235fe04 Michael Hanselmann
  def _GetList(getter):
584 8235fe04 Michael Hanselmann
    return lambda ctx, node: (constants.QRFS_NORMAL,
585 8235fe04 Michael Hanselmann
                              list(getter(ctx)[node.name]))
586 8235fe04 Michael Hanselmann
587 8235fe04 Michael Hanselmann
  # Add fields operating on instance lists
588 8235fe04 Michael Hanselmann
  for prefix, titleprefix, getter in \
589 8235fe04 Michael Hanselmann
      [("p", "Pri", operator.attrgetter("node_to_primary")),
590 8235fe04 Michael Hanselmann
       ("s", "Sec", operator.attrgetter("node_to_secondary"))]:
591 8235fe04 Michael Hanselmann
    fields.extend([
592 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(),
593 8235fe04 Michael Hanselmann
                  constants.QFT_NUMBER),
594 8235fe04 Michael Hanselmann
       NQ_INST, _GetLength(getter)),
595 8235fe04 Michael Hanselmann
      (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix,
596 8235fe04 Michael Hanselmann
                  constants.QFT_OTHER),
597 8235fe04 Michael Hanselmann
       NQ_INST, _GetList(getter)),
598 8235fe04 Michael Hanselmann
      ])
599 8235fe04 Michael Hanselmann
600 8235fe04 Michael Hanselmann
  # Add simple fields
601 8235fe04 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), NQ_CONFIG, _GetItemAttr(name))
602 8235fe04 Michael Hanselmann
                 for (name, (title, kind)) in _NODE_SIMPLE_FIELDS.items()])
603 8235fe04 Michael Hanselmann
604 8235fe04 Michael Hanselmann
  # Add fields requiring live data
605 8235fe04 Michael Hanselmann
  fields.extend([
606 8235fe04 Michael Hanselmann
    (_MakeField(name, title, kind), NQ_LIVE,
607 8235fe04 Michael Hanselmann
     compat.partial(_GetLiveNodeField, nfield, kind))
608 8235fe04 Michael Hanselmann
    for (name, (title, kind, nfield)) in _NODE_LIVE_FIELDS.items()
609 8235fe04 Michael Hanselmann
    ])
610 8235fe04 Michael Hanselmann
611 145bea54 Michael Hanselmann
  # Add timestamps
612 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(NQ_CONFIG))
613 145bea54 Michael Hanselmann
614 8235fe04 Michael Hanselmann
  return _PrepareFieldList(fields)
615 8235fe04 Michael Hanselmann
616 8235fe04 Michael Hanselmann
617 1c8addc6 Michael Hanselmann
class InstanceQueryData:
618 1c8addc6 Michael Hanselmann
  """Data container for instance data queries.
619 1c8addc6 Michael Hanselmann

620 1c8addc6 Michael Hanselmann
  """
621 1c8addc6 Michael Hanselmann
  def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
622 1c8addc6 Michael Hanselmann
               live_data):
623 1c8addc6 Michael Hanselmann
    """Initializes this class.
624 1c8addc6 Michael Hanselmann

625 1c8addc6 Michael Hanselmann
    @param instances: List of instance objects
626 1c8addc6 Michael Hanselmann
    @param cluster: Cluster object
627 1c8addc6 Michael Hanselmann
    @type disk_usage: dict; instance name as key
628 1c8addc6 Michael Hanselmann
    @param disk_usage: Per-instance disk usage
629 1c8addc6 Michael Hanselmann
    @type offline_nodes: list of strings
630 1c8addc6 Michael Hanselmann
    @param offline_nodes: List of offline nodes
631 1c8addc6 Michael Hanselmann
    @type bad_nodes: list of strings
632 1c8addc6 Michael Hanselmann
    @param bad_nodes: List of faulty nodes
633 1c8addc6 Michael Hanselmann
    @type live_data: dict; instance name as key
634 1c8addc6 Michael Hanselmann
    @param live_data: Per-instance live data
635 1c8addc6 Michael Hanselmann

636 1c8addc6 Michael Hanselmann
    """
637 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
638 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
639 1c8addc6 Michael Hanselmann
    assert not (set(live_data.keys()) & set(bad_nodes)), \
640 1c8addc6 Michael Hanselmann
           "Found live data for bad or offline nodes"
641 1c8addc6 Michael Hanselmann
642 1c8addc6 Michael Hanselmann
    self.instances = instances
643 1c8addc6 Michael Hanselmann
    self.cluster = cluster
644 1c8addc6 Michael Hanselmann
    self.disk_usage = disk_usage
645 1c8addc6 Michael Hanselmann
    self.offline_nodes = offline_nodes
646 1c8addc6 Michael Hanselmann
    self.bad_nodes = bad_nodes
647 1c8addc6 Michael Hanselmann
    self.live_data = live_data
648 1c8addc6 Michael Hanselmann
649 1c8addc6 Michael Hanselmann
    # Used for individual rows
650 1c8addc6 Michael Hanselmann
    self.inst_hvparams = None
651 1c8addc6 Michael Hanselmann
    self.inst_beparams = None
652 1c8addc6 Michael Hanselmann
    self.inst_nicparams = None
653 1c8addc6 Michael Hanselmann
654 1c8addc6 Michael Hanselmann
  def __iter__(self):
655 1c8addc6 Michael Hanselmann
    """Iterate over all instances.
656 1c8addc6 Michael Hanselmann

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

660 1c8addc6 Michael Hanselmann
    """
661 1c8addc6 Michael Hanselmann
    for inst in self.instances:
662 1c8addc6 Michael Hanselmann
      self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
663 1c8addc6 Michael Hanselmann
      self.inst_beparams = self.cluster.FillBE(inst)
664 1c8addc6 Michael Hanselmann
      self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
665 1c8addc6 Michael Hanselmann
                             for nic in inst.nics]
666 1c8addc6 Michael Hanselmann
667 1c8addc6 Michael Hanselmann
      yield inst
668 1c8addc6 Michael Hanselmann
669 1c8addc6 Michael Hanselmann
670 1c8addc6 Michael Hanselmann
def _GetInstOperState(ctx, inst):
671 1c8addc6 Michael Hanselmann
  """Get instance's operational status.
672 1c8addc6 Michael Hanselmann

673 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
674 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
675 1c8addc6 Michael Hanselmann
  @param inst: Instance object
676 1c8addc6 Michael Hanselmann

677 1c8addc6 Michael Hanselmann
  """
678 a6070ef7 Michael Hanselmann
  # Can't use QRFS_OFFLINE here as it would describe the instance to be offline
679 a6070ef7 Michael Hanselmann
  # when we actually don't know due to missing data
680 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
681 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NODATA, None)
682 1c8addc6 Michael Hanselmann
  else:
683 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, bool(ctx.live_data.get(inst.name)))
684 1c8addc6 Michael Hanselmann
685 1c8addc6 Michael Hanselmann
686 1c8addc6 Michael Hanselmann
def _GetInstLiveData(name):
687 1c8addc6 Michael Hanselmann
  """Build function for retrieving live data.
688 1c8addc6 Michael Hanselmann

689 1c8addc6 Michael Hanselmann
  @type name: string
690 1c8addc6 Michael Hanselmann
  @param name: Live data field name
691 1c8addc6 Michael Hanselmann

692 1c8addc6 Michael Hanselmann
  """
693 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
694 1c8addc6 Michael Hanselmann
    """Get live data for an instance.
695 1c8addc6 Michael Hanselmann

696 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
697 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
698 1c8addc6 Michael Hanselmann
    @param inst: Instance object
699 1c8addc6 Michael Hanselmann

700 1c8addc6 Michael Hanselmann
    """
701 1c8addc6 Michael Hanselmann
    if (inst.primary_node in ctx.bad_nodes or
702 1c8addc6 Michael Hanselmann
        inst.primary_node in ctx.offline_nodes):
703 a6070ef7 Michael Hanselmann
      # Can't use QRFS_OFFLINE here as it would describe the instance to be
704 a6070ef7 Michael Hanselmann
      # offline when we actually don't know due to missing data
705 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NODATA, None)
706 1c8addc6 Michael Hanselmann
707 1c8addc6 Michael Hanselmann
    if inst.name in ctx.live_data:
708 1c8addc6 Michael Hanselmann
      data = ctx.live_data[inst.name]
709 1c8addc6 Michael Hanselmann
      if name in data:
710 1c8addc6 Michael Hanselmann
        return (constants.QRFS_NORMAL, data[name])
711 1c8addc6 Michael Hanselmann
712 1c8addc6 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
713 1c8addc6 Michael Hanselmann
714 1c8addc6 Michael Hanselmann
  return fn
715 1c8addc6 Michael Hanselmann
716 1c8addc6 Michael Hanselmann
717 1c8addc6 Michael Hanselmann
def _GetInstStatus(ctx, inst):
718 1c8addc6 Michael Hanselmann
  """Get instance status.
719 1c8addc6 Michael Hanselmann

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

724 1c8addc6 Michael Hanselmann
  """
725 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.offline_nodes:
726 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, "ERROR_nodeoffline")
727 1c8addc6 Michael Hanselmann
728 1c8addc6 Michael Hanselmann
  if inst.primary_node in ctx.bad_nodes:
729 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, "ERROR_nodedown")
730 1c8addc6 Michael Hanselmann
731 1c8addc6 Michael Hanselmann
  if bool(ctx.live_data.get(inst.name)):
732 1c8addc6 Michael Hanselmann
    if inst.admin_up:
733 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NORMAL, "running")
734 1c8addc6 Michael Hanselmann
    else:
735 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NORMAL, "ERROR_up")
736 1c8addc6 Michael Hanselmann
737 1c8addc6 Michael Hanselmann
  if inst.admin_up:
738 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, "ERROR_down")
739 1c8addc6 Michael Hanselmann
740 1c8addc6 Michael Hanselmann
  return (constants.QRFS_NORMAL, "ADMIN_down")
741 1c8addc6 Michael Hanselmann
742 1c8addc6 Michael Hanselmann
743 1c8addc6 Michael Hanselmann
def _GetInstDiskSize(index):
744 1c8addc6 Michael Hanselmann
  """Build function for retrieving disk size.
745 1c8addc6 Michael Hanselmann

746 1c8addc6 Michael Hanselmann
  @type index: int
747 1c8addc6 Michael Hanselmann
  @param index: Disk index
748 1c8addc6 Michael Hanselmann

749 1c8addc6 Michael Hanselmann
  """
750 1c8addc6 Michael Hanselmann
  def fn(_, inst):
751 1c8addc6 Michael Hanselmann
    """Get size of a disk.
752 1c8addc6 Michael Hanselmann

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
    try:
758 1c8addc6 Michael Hanselmann
      return (constants.QRFS_NORMAL, inst.disks[index].size)
759 1c8addc6 Michael Hanselmann
    except IndexError:
760 1c8addc6 Michael Hanselmann
      return (constants.QRFS_UNAVAIL, None)
761 1c8addc6 Michael Hanselmann
762 1c8addc6 Michael Hanselmann
  return fn
763 1c8addc6 Michael Hanselmann
764 1c8addc6 Michael Hanselmann
765 1c8addc6 Michael Hanselmann
def _GetInstNic(index, cb):
766 1c8addc6 Michael Hanselmann
  """Build function for calling another function with an instance NIC.
767 1c8addc6 Michael Hanselmann

768 1c8addc6 Michael Hanselmann
  @type index: int
769 1c8addc6 Michael Hanselmann
  @param index: NIC index
770 1c8addc6 Michael Hanselmann
  @type cb: callable
771 1c8addc6 Michael Hanselmann
  @param cb: Callback
772 1c8addc6 Michael Hanselmann

773 1c8addc6 Michael Hanselmann
  """
774 1c8addc6 Michael Hanselmann
  def fn(ctx, inst):
775 1c8addc6 Michael Hanselmann
    """Call helper function with instance NIC.
776 1c8addc6 Michael Hanselmann

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

781 1c8addc6 Michael Hanselmann
    """
782 1c8addc6 Michael Hanselmann
    try:
783 1c8addc6 Michael Hanselmann
      nic = inst.nics[index]
784 1c8addc6 Michael Hanselmann
    except IndexError:
785 1c8addc6 Michael Hanselmann
      return (constants.QRFS_UNAVAIL, None)
786 1c8addc6 Michael Hanselmann
787 1c8addc6 Michael Hanselmann
    return cb(ctx, index, nic)
788 1c8addc6 Michael Hanselmann
789 1c8addc6 Michael Hanselmann
  return fn
790 1c8addc6 Michael Hanselmann
791 1c8addc6 Michael Hanselmann
792 1c8addc6 Michael Hanselmann
def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613
793 1c8addc6 Michael Hanselmann
  """Get a NIC's IP address.
794 1c8addc6 Michael Hanselmann

795 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
796 1c8addc6 Michael Hanselmann
  @type nic: L{objects.NIC}
797 1c8addc6 Michael Hanselmann
  @param nic: NIC object
798 1c8addc6 Michael Hanselmann

799 1c8addc6 Michael Hanselmann
  """
800 1c8addc6 Michael Hanselmann
  if nic.ip is None:
801 1c8addc6 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
802 1c8addc6 Michael Hanselmann
  else:
803 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, nic.ip)
804 1c8addc6 Michael Hanselmann
805 1c8addc6 Michael Hanselmann
806 1c8addc6 Michael Hanselmann
def _GetInstNicBridge(ctx, index, _):
807 1c8addc6 Michael Hanselmann
  """Get a NIC's bridge.
808 1c8addc6 Michael Hanselmann

809 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
810 1c8addc6 Michael Hanselmann
  @type index: int
811 1c8addc6 Michael Hanselmann
  @param index: NIC index
812 1c8addc6 Michael Hanselmann

813 1c8addc6 Michael Hanselmann
  """
814 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) >= index
815 1c8addc6 Michael Hanselmann
816 1c8addc6 Michael Hanselmann
  nicparams = ctx.inst_nicparams[index]
817 1c8addc6 Michael Hanselmann
818 1c8addc6 Michael Hanselmann
  if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
819 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, nicparams[constants.NIC_LINK])
820 1c8addc6 Michael Hanselmann
  else:
821 1c8addc6 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
822 1c8addc6 Michael Hanselmann
823 1c8addc6 Michael Hanselmann
824 1c8addc6 Michael Hanselmann
def _GetInstAllNicBridges(ctx, inst):
825 1c8addc6 Michael Hanselmann
  """Get all network bridges for an instance.
826 1c8addc6 Michael Hanselmann

827 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
828 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
829 1c8addc6 Michael Hanselmann
  @param inst: Instance object
830 1c8addc6 Michael Hanselmann

831 1c8addc6 Michael Hanselmann
  """
832 1c8addc6 Michael Hanselmann
  assert len(ctx.inst_nicparams) == len(inst.nics)
833 1c8addc6 Michael Hanselmann
834 1c8addc6 Michael Hanselmann
  result = []
835 1c8addc6 Michael Hanselmann
836 1c8addc6 Michael Hanselmann
  for nicp in ctx.inst_nicparams:
837 1c8addc6 Michael Hanselmann
    if nicp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
838 1c8addc6 Michael Hanselmann
      result.append(nicp[constants.NIC_LINK])
839 1c8addc6 Michael Hanselmann
    else:
840 1c8addc6 Michael Hanselmann
      result.append(None)
841 1c8addc6 Michael Hanselmann
842 1c8addc6 Michael Hanselmann
  assert len(result) == len(inst.nics)
843 1c8addc6 Michael Hanselmann
844 1c8addc6 Michael Hanselmann
  return (constants.QRFS_NORMAL, result)
845 1c8addc6 Michael Hanselmann
846 1c8addc6 Michael Hanselmann
847 1c8addc6 Michael Hanselmann
def _GetInstNicParam(name):
848 1c8addc6 Michael Hanselmann
  """Build function for retrieving a NIC parameter.
849 1c8addc6 Michael Hanselmann

850 1c8addc6 Michael Hanselmann
  @type name: string
851 1c8addc6 Michael Hanselmann
  @param name: Parameter name
852 1c8addc6 Michael Hanselmann

853 1c8addc6 Michael Hanselmann
  """
854 1c8addc6 Michael Hanselmann
  def fn(ctx, index, _):
855 1c8addc6 Michael Hanselmann
    """Get a NIC's bridge.
856 1c8addc6 Michael Hanselmann

857 1c8addc6 Michael Hanselmann
    @type ctx: L{InstanceQueryData}
858 1c8addc6 Michael Hanselmann
    @type inst: L{objects.Instance}
859 1c8addc6 Michael Hanselmann
    @param inst: Instance object
860 1c8addc6 Michael Hanselmann
    @type nic: L{objects.NIC}
861 1c8addc6 Michael Hanselmann
    @param nic: NIC object
862 1c8addc6 Michael Hanselmann

863 1c8addc6 Michael Hanselmann
    """
864 1c8addc6 Michael Hanselmann
    assert len(ctx.inst_nicparams) >= index
865 1c8addc6 Michael Hanselmann
    return (constants.QRFS_NORMAL, ctx.inst_nicparams[index][name])
866 1c8addc6 Michael Hanselmann
867 1c8addc6 Michael Hanselmann
  return fn
868 1c8addc6 Michael Hanselmann
869 1c8addc6 Michael Hanselmann
870 1c8addc6 Michael Hanselmann
def _GetInstanceNetworkFields():
871 1c8addc6 Michael Hanselmann
  """Get instance fields involving network interfaces.
872 1c8addc6 Michael Hanselmann

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

875 1c8addc6 Michael Hanselmann
  """
876 1c8addc6 Michael Hanselmann
  nic_mac_fn = lambda ctx, _, nic: (constants.QRFS_NORMAL, nic.mac)
877 1c8addc6 Michael Hanselmann
  nic_mode_fn = _GetInstNicParam(constants.NIC_MODE)
878 1c8addc6 Michael Hanselmann
  nic_link_fn = _GetInstNicParam(constants.NIC_LINK)
879 1c8addc6 Michael Hanselmann
880 1c8addc6 Michael Hanselmann
  fields = [
881 1c8addc6 Michael Hanselmann
    # First NIC (legacy)
882 1c8addc6 Michael Hanselmann
    (_MakeField("ip", "IP_address", constants.QFT_TEXT), IQ_CONFIG,
883 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicIp)),
884 1c8addc6 Michael Hanselmann
    (_MakeField("mac", "MAC_address", constants.QFT_TEXT), IQ_CONFIG,
885 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mac_fn)),
886 1c8addc6 Michael Hanselmann
    (_MakeField("bridge", "Bridge", constants.QFT_TEXT), IQ_CONFIG,
887 1c8addc6 Michael Hanselmann
     _GetInstNic(0, _GetInstNicBridge)),
888 1c8addc6 Michael Hanselmann
    (_MakeField("nic_mode", "NIC_Mode", constants.QFT_TEXT), IQ_CONFIG,
889 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_mode_fn)),
890 1c8addc6 Michael Hanselmann
    (_MakeField("nic_link", "NIC_Link", constants.QFT_TEXT), IQ_CONFIG,
891 1c8addc6 Michael Hanselmann
     _GetInstNic(0, nic_link_fn)),
892 1c8addc6 Michael Hanselmann
893 1c8addc6 Michael Hanselmann
    # All NICs
894 1c8addc6 Michael Hanselmann
    (_MakeField("nic.count", "NICs", constants.QFT_NUMBER), IQ_CONFIG,
895 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, len(inst.nics))),
896 1c8addc6 Michael Hanselmann
    (_MakeField("nic.macs", "NIC_MACs", constants.QFT_OTHER), IQ_CONFIG,
897 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, [nic.mac for nic in inst.nics])),
898 1c8addc6 Michael Hanselmann
    (_MakeField("nic.ips", "NIC_IPs", constants.QFT_OTHER), IQ_CONFIG,
899 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, [nic.ip for nic in inst.nics])),
900 1c8addc6 Michael Hanselmann
    (_MakeField("nic.modes", "NIC_modes", constants.QFT_OTHER), IQ_CONFIG,
901 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL,
902 1c8addc6 Michael Hanselmann
                        [nicp[constants.NIC_MODE]
903 1c8addc6 Michael Hanselmann
                         for nicp in ctx.inst_nicparams])),
904 1c8addc6 Michael Hanselmann
    (_MakeField("nic.links", "NIC_links", constants.QFT_OTHER), IQ_CONFIG,
905 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL,
906 1c8addc6 Michael Hanselmann
                        [nicp[constants.NIC_LINK]
907 1c8addc6 Michael Hanselmann
                         for nicp in ctx.inst_nicparams])),
908 1c8addc6 Michael Hanselmann
    (_MakeField("nic.bridges", "NIC_bridges", constants.QFT_OTHER), IQ_CONFIG,
909 1c8addc6 Michael Hanselmann
     _GetInstAllNicBridges),
910 1c8addc6 Michael Hanselmann
    ]
911 1c8addc6 Michael Hanselmann
912 1c8addc6 Michael Hanselmann
  # NICs by number
913 1c8addc6 Michael Hanselmann
  for i in range(constants.MAX_NICS):
914 1c8addc6 Michael Hanselmann
    fields.extend([
915 1c8addc6 Michael Hanselmann
      (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, constants.QFT_TEXT),
916 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicIp)),
917 1c8addc6 Michael Hanselmann
      (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, constants.QFT_TEXT),
918 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mac_fn)),
919 1c8addc6 Michael Hanselmann
      (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, constants.QFT_TEXT),
920 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_mode_fn)),
921 1c8addc6 Michael Hanselmann
      (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, constants.QFT_TEXT),
922 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, nic_link_fn)),
923 1c8addc6 Michael Hanselmann
      (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, constants.QFT_TEXT),
924 1c8addc6 Michael Hanselmann
       IQ_CONFIG, _GetInstNic(i, _GetInstNicBridge)),
925 1c8addc6 Michael Hanselmann
      ])
926 1c8addc6 Michael Hanselmann
927 1c8addc6 Michael Hanselmann
  return fields
928 1c8addc6 Michael Hanselmann
929 1c8addc6 Michael Hanselmann
930 1c8addc6 Michael Hanselmann
def _GetInstDiskUsage(ctx, inst):
931 1c8addc6 Michael Hanselmann
  """Get disk usage for an instance.
932 1c8addc6 Michael Hanselmann

933 1c8addc6 Michael Hanselmann
  @type ctx: L{InstanceQueryData}
934 1c8addc6 Michael Hanselmann
  @type inst: L{objects.Instance}
935 1c8addc6 Michael Hanselmann
  @param inst: Instance object
936 1c8addc6 Michael Hanselmann

937 1c8addc6 Michael Hanselmann
  """
938 1c8addc6 Michael Hanselmann
  usage = ctx.disk_usage[inst.name]
939 1c8addc6 Michael Hanselmann
940 1c8addc6 Michael Hanselmann
  if usage is None:
941 1c8addc6 Michael Hanselmann
    usage = 0
942 1c8addc6 Michael Hanselmann
943 1c8addc6 Michael Hanselmann
  return (constants.QRFS_NORMAL, usage)
944 1c8addc6 Michael Hanselmann
945 1c8addc6 Michael Hanselmann
946 1c8addc6 Michael Hanselmann
def _GetInstanceDiskFields():
947 1c8addc6 Michael Hanselmann
  """Get instance fields involving disks.
948 1c8addc6 Michael Hanselmann

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

951 1c8addc6 Michael Hanselmann
  """
952 1c8addc6 Michael Hanselmann
  fields = [
953 1c8addc6 Michael Hanselmann
    (_MakeField("disk_usage", "DiskUsage", constants.QFT_UNIT), IQ_DISKUSAGE,
954 1c8addc6 Michael Hanselmann
     _GetInstDiskUsage),
955 1c8addc6 Michael Hanselmann
    (_MakeField("sda_size", "LegacyDisk/0", constants.QFT_UNIT), IQ_CONFIG,
956 1c8addc6 Michael Hanselmann
     _GetInstDiskSize(0)),
957 1c8addc6 Michael Hanselmann
    (_MakeField("sdb_size", "LegacyDisk/1", constants.QFT_UNIT), IQ_CONFIG,
958 1c8addc6 Michael Hanselmann
     _GetInstDiskSize(1)),
959 1c8addc6 Michael Hanselmann
    (_MakeField("disk.count", "Disks", constants.QFT_NUMBER), IQ_CONFIG,
960 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, len(inst.disks))),
961 1c8addc6 Michael Hanselmann
    (_MakeField("disk.sizes", "Disk_sizes", constants.QFT_OTHER), IQ_CONFIG,
962 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL,
963 1c8addc6 Michael Hanselmann
                        [disk.size for disk in inst.disks])),
964 1c8addc6 Michael Hanselmann
    ]
965 1c8addc6 Michael Hanselmann
966 1c8addc6 Michael Hanselmann
  # Disks by number
967 1c8addc6 Michael Hanselmann
  fields.extend([
968 1c8addc6 Michael Hanselmann
    (_MakeField("disk.size/%s" % i, "Disk/%s" % i, constants.QFT_UNIT),
969 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstDiskSize(i))
970 1c8addc6 Michael Hanselmann
    for i in range(constants.MAX_DISKS)
971 1c8addc6 Michael Hanselmann
    ])
972 1c8addc6 Michael Hanselmann
973 1c8addc6 Michael Hanselmann
  return fields
974 1c8addc6 Michael Hanselmann
975 1c8addc6 Michael Hanselmann
976 1c8addc6 Michael Hanselmann
def _GetInstanceParameterFields():
977 1c8addc6 Michael Hanselmann
  """Get instance fields involving parameters.
978 1c8addc6 Michael Hanselmann

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

981 1c8addc6 Michael Hanselmann
  """
982 1c8addc6 Michael Hanselmann
  # TODO: Consider moving titles closer to constants
983 1c8addc6 Michael Hanselmann
  be_title = {
984 1c8addc6 Michael Hanselmann
    constants.BE_AUTO_BALANCE: "Auto_balance",
985 1c8addc6 Michael Hanselmann
    constants.BE_MEMORY: "Configured_memory",
986 1c8addc6 Michael Hanselmann
    constants.BE_VCPUS: "VCPUs",
987 1c8addc6 Michael Hanselmann
    }
988 1c8addc6 Michael Hanselmann
989 1c8addc6 Michael Hanselmann
  hv_title = {
990 1c8addc6 Michael Hanselmann
    constants.HV_ACPI: "ACPI",
991 1c8addc6 Michael Hanselmann
    constants.HV_BOOT_ORDER: "Boot_order",
992 1c8addc6 Michael Hanselmann
    constants.HV_CDROM_IMAGE_PATH: "CDROM_image_path",
993 1c8addc6 Michael Hanselmann
    constants.HV_DISK_TYPE: "Disk_type",
994 1c8addc6 Michael Hanselmann
    constants.HV_INITRD_PATH: "Initrd_path",
995 1c8addc6 Michael Hanselmann
    constants.HV_KERNEL_PATH: "Kernel_path",
996 1c8addc6 Michael Hanselmann
    constants.HV_NIC_TYPE: "NIC_type",
997 1c8addc6 Michael Hanselmann
    constants.HV_PAE: "PAE",
998 1c8addc6 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS: "VNC_bind_address",
999 1c8addc6 Michael Hanselmann
    }
1000 1c8addc6 Michael Hanselmann
1001 1c8addc6 Michael Hanselmann
  fields = [
1002 1c8addc6 Michael Hanselmann
    # Filled parameters
1003 1c8addc6 Michael Hanselmann
    (_MakeField("hvparams", "HypervisorParameters", constants.QFT_OTHER),
1004 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, _: (constants.QRFS_NORMAL, ctx.inst_hvparams)),
1005 1c8addc6 Michael Hanselmann
    (_MakeField("beparams", "BackendParameters", constants.QFT_OTHER),
1006 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, _: (constants.QRFS_NORMAL, ctx.inst_beparams)),
1007 1c8addc6 Michael Hanselmann
    (_MakeField("vcpus", "LegacyVCPUs", constants.QFT_NUMBER), IQ_CONFIG,
1008 1c8addc6 Michael Hanselmann
     lambda ctx, _: (constants.QRFS_NORMAL,
1009 1c8addc6 Michael Hanselmann
                     ctx.inst_beparams[constants.BE_VCPUS])),
1010 1c8addc6 Michael Hanselmann
1011 1c8addc6 Michael Hanselmann
    # Unfilled parameters
1012 1c8addc6 Michael Hanselmann
    (_MakeField("custom_hvparams", "CustomHypervisorParameters",
1013 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
1014 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL, inst.hvparams)),
1015 1c8addc6 Michael Hanselmann
    (_MakeField("custom_beparams", "CustomBackendParameters",
1016 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
1017 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL, inst.beparams)),
1018 1c8addc6 Michael Hanselmann
    (_MakeField("custom_nicparams", "CustomNicParameters",
1019 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
1020 1c8addc6 Michael Hanselmann
     IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL,
1021 1c8addc6 Michael Hanselmann
                                   [nic.nicparams for nic in inst.nics])),
1022 1c8addc6 Michael Hanselmann
    ]
1023 1c8addc6 Michael Hanselmann
1024 1c8addc6 Michael Hanselmann
  # HV params
1025 1c8addc6 Michael Hanselmann
  def _GetInstHvParam(name):
1026 1c8addc6 Michael Hanselmann
    return lambda ctx, _: (constants.QRFS_NORMAL,
1027 1c8addc6 Michael Hanselmann
                           ctx.inst_hvparams.get(name, None))
1028 1c8addc6 Michael Hanselmann
1029 1c8addc6 Michael Hanselmann
  fields.extend([
1030 1c8addc6 Michael Hanselmann
    # For now all hypervisor parameters are exported as QFT_OTHER
1031 1c8addc6 Michael Hanselmann
    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
1032 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
1033 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstHvParam(name))
1034 1c8addc6 Michael Hanselmann
    for name in constants.HVS_PARAMETERS
1035 1c8addc6 Michael Hanselmann
    if name not in constants.HVC_GLOBALS
1036 1c8addc6 Michael Hanselmann
    ])
1037 1c8addc6 Michael Hanselmann
1038 1c8addc6 Michael Hanselmann
  # BE params
1039 1c8addc6 Michael Hanselmann
  def _GetInstBeParam(name):
1040 1c8addc6 Michael Hanselmann
    return lambda ctx, _: (constants.QRFS_NORMAL,
1041 1c8addc6 Michael Hanselmann
                           ctx.inst_beparams.get(name, None))
1042 1c8addc6 Michael Hanselmann
1043 1c8addc6 Michael Hanselmann
  fields.extend([
1044 1c8addc6 Michael Hanselmann
    # For now all backend parameters are exported as QFT_OTHER
1045 1c8addc6 Michael Hanselmann
    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
1046 1c8addc6 Michael Hanselmann
                constants.QFT_OTHER),
1047 1c8addc6 Michael Hanselmann
     IQ_CONFIG, _GetInstBeParam(name))
1048 1c8addc6 Michael Hanselmann
    for name in constants.BES_PARAMETERS
1049 1c8addc6 Michael Hanselmann
    ])
1050 1c8addc6 Michael Hanselmann
1051 1c8addc6 Michael Hanselmann
  return fields
1052 1c8addc6 Michael Hanselmann
1053 1c8addc6 Michael Hanselmann
1054 1c8addc6 Michael Hanselmann
_INST_SIMPLE_FIELDS = {
1055 1c8addc6 Michael Hanselmann
  "disk_template": ("Disk_template", constants.QFT_TEXT),
1056 1c8addc6 Michael Hanselmann
  "hypervisor": ("Hypervisor", constants.QFT_TEXT),
1057 1c8addc6 Michael Hanselmann
  "name": ("Node", constants.QFT_TEXT),
1058 1c8addc6 Michael Hanselmann
  # Depending on the hypervisor, the port can be None
1059 1c8addc6 Michael Hanselmann
  "network_port": ("Network_port", constants.QFT_OTHER),
1060 1c8addc6 Michael Hanselmann
  "os": ("OS", constants.QFT_TEXT),
1061 1c8addc6 Michael Hanselmann
  "serial_no": ("SerialNo", constants.QFT_NUMBER),
1062 1c8addc6 Michael Hanselmann
  "uuid": ("UUID", constants.QFT_TEXT),
1063 1c8addc6 Michael Hanselmann
  }
1064 1c8addc6 Michael Hanselmann
1065 1c8addc6 Michael Hanselmann
1066 1c8addc6 Michael Hanselmann
def _BuildInstanceFields():
1067 1c8addc6 Michael Hanselmann
  """Builds list of fields for instance queries.
1068 1c8addc6 Michael Hanselmann

1069 1c8addc6 Michael Hanselmann
  """
1070 1c8addc6 Michael Hanselmann
  fields = [
1071 1c8addc6 Michael Hanselmann
    (_MakeField("pnode", "Primary_node", constants.QFT_TEXT), IQ_CONFIG,
1072 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, inst.primary_node)),
1073 1c8addc6 Michael Hanselmann
    (_MakeField("snodes", "Secondary_Nodes", constants.QFT_OTHER), IQ_CONFIG,
1074 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, list(inst.secondary_nodes))),
1075 1c8addc6 Michael Hanselmann
    (_MakeField("admin_state", "Autostart", constants.QFT_BOOL), IQ_CONFIG,
1076 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, inst.admin_up)),
1077 1c8addc6 Michael Hanselmann
    (_MakeField("tags", "Tags", constants.QFT_OTHER), IQ_CONFIG,
1078 1c8addc6 Michael Hanselmann
     lambda ctx, inst: (constants.QRFS_NORMAL, list(inst.GetTags()))),
1079 1c8addc6 Michael Hanselmann
    ]
1080 1c8addc6 Michael Hanselmann
1081 1c8addc6 Michael Hanselmann
  # Add simple fields
1082 1c8addc6 Michael Hanselmann
  fields.extend([(_MakeField(name, title, kind), IQ_CONFIG, _GetItemAttr(name))
1083 1c8addc6 Michael Hanselmann
                 for (name, (title, kind)) in _INST_SIMPLE_FIELDS.items()])
1084 1c8addc6 Michael Hanselmann
1085 1c8addc6 Michael Hanselmann
  # Fields requiring talking to the node
1086 1c8addc6 Michael Hanselmann
  fields.extend([
1087 1c8addc6 Michael Hanselmann
    (_MakeField("oper_state", "Running", constants.QFT_BOOL), IQ_LIVE,
1088 1c8addc6 Michael Hanselmann
     _GetInstOperState),
1089 1c8addc6 Michael Hanselmann
    (_MakeField("oper_ram", "RuntimeMemory", constants.QFT_UNIT), IQ_LIVE,
1090 1c8addc6 Michael Hanselmann
     _GetInstLiveData("memory")),
1091 1c8addc6 Michael Hanselmann
    (_MakeField("oper_vcpus", "RuntimeVCPUs", constants.QFT_NUMBER), IQ_LIVE,
1092 1c8addc6 Michael Hanselmann
     _GetInstLiveData("vcpus")),
1093 1c8addc6 Michael Hanselmann
    (_MakeField("status", "Status", constants.QFT_TEXT), IQ_LIVE,
1094 1c8addc6 Michael Hanselmann
     _GetInstStatus),
1095 1c8addc6 Michael Hanselmann
    ])
1096 1c8addc6 Michael Hanselmann
1097 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceParameterFields())
1098 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceDiskFields())
1099 1c8addc6 Michael Hanselmann
  fields.extend(_GetInstanceNetworkFields())
1100 145bea54 Michael Hanselmann
  fields.extend(_GetItemTimestampFields(IQ_CONFIG))
1101 1c8addc6 Michael Hanselmann
1102 1c8addc6 Michael Hanselmann
  return _PrepareFieldList(fields)
1103 1c8addc6 Michael Hanselmann
1104 1c8addc6 Michael Hanselmann
1105 24d16f76 Michael Hanselmann
class LockQueryData:
1106 24d16f76 Michael Hanselmann
  """Data container for lock data queries.
1107 24d16f76 Michael Hanselmann

1108 24d16f76 Michael Hanselmann
  """
1109 24d16f76 Michael Hanselmann
  def __init__(self, lockdata):
1110 24d16f76 Michael Hanselmann
    """Initializes this class.
1111 24d16f76 Michael Hanselmann

1112 24d16f76 Michael Hanselmann
    """
1113 24d16f76 Michael Hanselmann
    self.lockdata = lockdata
1114 24d16f76 Michael Hanselmann
1115 24d16f76 Michael Hanselmann
  def __iter__(self):
1116 24d16f76 Michael Hanselmann
    """Iterate over all locks.
1117 24d16f76 Michael Hanselmann

1118 24d16f76 Michael Hanselmann
    """
1119 24d16f76 Michael Hanselmann
    return iter(self.lockdata)
1120 24d16f76 Michael Hanselmann
1121 24d16f76 Michael Hanselmann
1122 24d16f76 Michael Hanselmann
def _GetLockOwners(_, data):
1123 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's current owners.
1124 24d16f76 Michael Hanselmann

1125 24d16f76 Michael Hanselmann
  """
1126 24d16f76 Michael Hanselmann
  (_, _, owners, _) = data
1127 24d16f76 Michael Hanselmann
1128 24d16f76 Michael Hanselmann
  if owners:
1129 24d16f76 Michael Hanselmann
    owners = utils.NiceSort(owners)
1130 24d16f76 Michael Hanselmann
1131 24d16f76 Michael Hanselmann
  return (constants.QRFS_NORMAL, owners)
1132 24d16f76 Michael Hanselmann
1133 24d16f76 Michael Hanselmann
1134 24d16f76 Michael Hanselmann
def _GetLockPending(_, data):
1135 24d16f76 Michael Hanselmann
  """Returns a sorted list of a lock's pending acquires.
1136 24d16f76 Michael Hanselmann

1137 24d16f76 Michael Hanselmann
  """
1138 24d16f76 Michael Hanselmann
  (_, _, _, pending) = data
1139 24d16f76 Michael Hanselmann
1140 24d16f76 Michael Hanselmann
  if pending:
1141 24d16f76 Michael Hanselmann
    pending = [(mode, utils.NiceSort(names))
1142 24d16f76 Michael Hanselmann
               for (mode, names) in pending]
1143 24d16f76 Michael Hanselmann
1144 24d16f76 Michael Hanselmann
  return (constants.QRFS_NORMAL, pending)
1145 24d16f76 Michael Hanselmann
1146 24d16f76 Michael Hanselmann
1147 24d16f76 Michael Hanselmann
def _BuildLockFields():
1148 24d16f76 Michael Hanselmann
  """Builds list of fields for lock queries.
1149 24d16f76 Michael Hanselmann

1150 24d16f76 Michael Hanselmann
  """
1151 24d16f76 Michael Hanselmann
  return _PrepareFieldList([
1152 24d16f76 Michael Hanselmann
    (_MakeField("name", "Name", constants.QFT_TEXT), None,
1153 24d16f76 Michael Hanselmann
     lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, name)),
1154 24d16f76 Michael Hanselmann
    (_MakeField("mode", "Mode", constants.QFT_OTHER), LQ_MODE,
1155 24d16f76 Michael Hanselmann
     lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, mode)),
1156 24d16f76 Michael Hanselmann
    (_MakeField("owner", "Owner", constants.QFT_OTHER), LQ_OWNER,
1157 24d16f76 Michael Hanselmann
     _GetLockOwners),
1158 24d16f76 Michael Hanselmann
    (_MakeField("pending", "Pending", constants.QFT_OTHER), LQ_PENDING,
1159 24d16f76 Michael Hanselmann
     _GetLockPending),
1160 24d16f76 Michael Hanselmann
    ])
1161 24d16f76 Michael Hanselmann
1162 24d16f76 Michael Hanselmann
1163 8e21cfc0 Adeodato Simo
class GroupQueryData:
1164 8e21cfc0 Adeodato Simo
  """Data container for node group data queries.
1165 8e21cfc0 Adeodato Simo

1166 8e21cfc0 Adeodato Simo
  """
1167 8e21cfc0 Adeodato Simo
  def __init__(self, groups, group_to_nodes, group_to_instances):
1168 8e21cfc0 Adeodato Simo
    """Initializes this class.
1169 8e21cfc0 Adeodato Simo

1170 8e21cfc0 Adeodato Simo
    @param groups: List of node group objects
1171 8e21cfc0 Adeodato Simo
    @type group_to_nodes: dict; group UUID as key
1172 8e21cfc0 Adeodato Simo
    @param group_to_nodes: Per-group list of nodes
1173 8e21cfc0 Adeodato Simo
    @type group_to_instances: dict; group UUID as key
1174 8e21cfc0 Adeodato Simo
    @param group_to_instances: Per-group list of (primary) instances
1175 8e21cfc0 Adeodato Simo

1176 8e21cfc0 Adeodato Simo
    """
1177 8e21cfc0 Adeodato Simo
    self.groups = groups
1178 8e21cfc0 Adeodato Simo
    self.group_to_nodes = group_to_nodes
1179 8e21cfc0 Adeodato Simo
    self.group_to_instances = group_to_instances
1180 8e21cfc0 Adeodato Simo
1181 8e21cfc0 Adeodato Simo
  def __iter__(self):
1182 8e21cfc0 Adeodato Simo
    """Iterate over all node groups.
1183 8e21cfc0 Adeodato Simo

1184 8e21cfc0 Adeodato Simo
    """
1185 8e21cfc0 Adeodato Simo
    return iter(self.groups)
1186 8e21cfc0 Adeodato Simo
1187 8e21cfc0 Adeodato Simo
1188 8e21cfc0 Adeodato Simo
_GROUP_SIMPLE_FIELDS = {
1189 8e21cfc0 Adeodato Simo
  "alloc_policy": ("AllocPolicy", constants.QFT_TEXT),
1190 8e21cfc0 Adeodato Simo
  "name": ("Group", constants.QFT_TEXT),
1191 8e21cfc0 Adeodato Simo
  "serial_no": ("SerialNo", constants.QFT_NUMBER),
1192 8e21cfc0 Adeodato Simo
  "uuid": ("UUID", constants.QFT_TEXT),
1193 b288b6f3 René Nussbaumer
  "ndparams": ("NDParams", constants.QFT_OTHER),
1194 8e21cfc0 Adeodato Simo
  }
1195 8e21cfc0 Adeodato Simo
1196 8e21cfc0 Adeodato Simo
1197 8e21cfc0 Adeodato Simo
def _BuildGroupFields():
1198 8e21cfc0 Adeodato Simo
  """Builds list of fields for node group queries.
1199 8e21cfc0 Adeodato Simo

1200 8e21cfc0 Adeodato Simo
  """
1201 8e21cfc0 Adeodato Simo
  # Add simple fields
1202 8e21cfc0 Adeodato Simo
  fields = [(_MakeField(name, title, kind), GQ_CONFIG, _GetItemAttr(name))
1203 8e21cfc0 Adeodato Simo
            for (name, (title, kind)) in _GROUP_SIMPLE_FIELDS.items()]
1204 8e21cfc0 Adeodato Simo
1205 8e21cfc0 Adeodato Simo
  def _GetLength(getter):
1206 8e21cfc0 Adeodato Simo
    return lambda ctx, group: (constants.QRFS_NORMAL,
1207 8e21cfc0 Adeodato Simo
                               len(getter(ctx)[group.uuid]))
1208 8e21cfc0 Adeodato Simo
1209 8e21cfc0 Adeodato Simo
  def _GetSortedList(getter):
1210 8e21cfc0 Adeodato Simo
    return lambda ctx, group: (constants.QRFS_NORMAL,
1211 8e21cfc0 Adeodato Simo
                               utils.NiceSort(getter(ctx)[group.uuid]))
1212 8e21cfc0 Adeodato Simo
1213 8e21cfc0 Adeodato Simo
  group_to_nodes = operator.attrgetter("group_to_nodes")
1214 8e21cfc0 Adeodato Simo
  group_to_instances = operator.attrgetter("group_to_instances")
1215 8e21cfc0 Adeodato Simo
1216 8e21cfc0 Adeodato Simo
  # Add fields for nodes
1217 8e21cfc0 Adeodato Simo
  fields.extend([
1218 8e21cfc0 Adeodato Simo
    (_MakeField("node_cnt", "Nodes", constants.QFT_NUMBER),
1219 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetLength(group_to_nodes)),
1220 8e21cfc0 Adeodato Simo
    (_MakeField("node_list", "NodeList", constants.QFT_OTHER),
1221 8e21cfc0 Adeodato Simo
     GQ_NODE, _GetSortedList(group_to_nodes)),
1222 8e21cfc0 Adeodato Simo
    ])
1223 8e21cfc0 Adeodato Simo
1224 8e21cfc0 Adeodato Simo
  # Add fields for instances
1225 8e21cfc0 Adeodato Simo
  fields.extend([
1226 8e21cfc0 Adeodato Simo
    (_MakeField("pinst_cnt", "Instances", constants.QFT_NUMBER),
1227 8e21cfc0 Adeodato Simo
     GQ_INST, _GetLength(group_to_instances)),
1228 8e21cfc0 Adeodato Simo
    (_MakeField("pinst_list", "InstanceList", constants.QFT_OTHER),
1229 8e21cfc0 Adeodato Simo
     GQ_INST, _GetSortedList(group_to_instances)),
1230 8e21cfc0 Adeodato Simo
    ])
1231 8e21cfc0 Adeodato Simo
1232 8e21cfc0 Adeodato Simo
  fields.extend(_GetItemTimestampFields(GQ_CONFIG))
1233 8e21cfc0 Adeodato Simo
1234 8e21cfc0 Adeodato Simo
  return _PrepareFieldList(fields)
1235 8e21cfc0 Adeodato Simo
1236 8e21cfc0 Adeodato Simo
1237 8235fe04 Michael Hanselmann
#: Fields available for node queries
1238 8235fe04 Michael Hanselmann
NODE_FIELDS = _BuildNodeFields()
1239 1c8addc6 Michael Hanselmann
1240 1c8addc6 Michael Hanselmann
#: Fields available for instance queries
1241 1c8addc6 Michael Hanselmann
INSTANCE_FIELDS = _BuildInstanceFields()
1242 24d16f76 Michael Hanselmann
1243 24d16f76 Michael Hanselmann
#: Fields available for lock queries
1244 24d16f76 Michael Hanselmann
LOCK_FIELDS = _BuildLockFields()
1245 e571ee44 Adeodato Simo
1246 8e21cfc0 Adeodato Simo
#: Fields available for node group queries
1247 8e21cfc0 Adeodato Simo
GROUP_FIELDS = _BuildGroupFields()
1248 8e21cfc0 Adeodato Simo
1249 e571ee44 Adeodato Simo
#: All available field lists
1250 8e21cfc0 Adeodato Simo
ALL_FIELD_LISTS = [NODE_FIELDS, INSTANCE_FIELDS, LOCK_FIELDS, GROUP_FIELDS]