Statistics
| Branch: | Tag: | Revision:

root / qa / qa_config.py @ 6a654276

History | View | Annotate | Download (11.9 kB)

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

24 cec9845c Michael Hanselmann
"""
25 cec9845c Michael Hanselmann
26 c9e05005 Michael Hanselmann
import os
27 cec9845c Michael Hanselmann
28 e7b6183b Michael Hanselmann
from ganeti import constants
29 a705dc05 Michael Hanselmann
from ganeti import utils
30 a705dc05 Michael Hanselmann
from ganeti import serializer
31 7d88f255 Iustin Pop
from ganeti import compat
32 cec9845c Michael Hanselmann
33 cec9845c Michael Hanselmann
import qa_error
34 cec9845c Michael Hanselmann
35 cec9845c Michael Hanselmann
36 c9e05005 Michael Hanselmann
_INSTANCE_CHECK_KEY = "instance-check"
37 e7b6183b Michael Hanselmann
_ENABLED_HV_KEY = "enabled-hypervisors"
38 f9329a6c Michael Hanselmann
39 8a96c5a6 Michael Hanselmann
#: QA configuration (L{_QaConfig})
40 8a96c5a6 Michael Hanselmann
_config = None
41 cec9845c Michael Hanselmann
42 cec9845c Michael Hanselmann
43 6a654276 Michael Hanselmann
class _QaInstance(object):
44 6a654276 Michael Hanselmann
  __slots__ = [
45 6a654276 Michael Hanselmann
    "name",
46 6a654276 Michael Hanselmann
    "nicmac",
47 6a654276 Michael Hanselmann
    "used",
48 6a654276 Michael Hanselmann
    "disk_template",
49 6a654276 Michael Hanselmann
    ]
50 6a654276 Michael Hanselmann
51 6a654276 Michael Hanselmann
  def __init__(self, name, nicmac):
52 6a654276 Michael Hanselmann
    """Initializes instances of this class.
53 6a654276 Michael Hanselmann

54 6a654276 Michael Hanselmann
    """
55 6a654276 Michael Hanselmann
    self.name = name
56 6a654276 Michael Hanselmann
    self.nicmac = nicmac
57 6a654276 Michael Hanselmann
    self.used = None
58 6a654276 Michael Hanselmann
    self.disk_template = None
59 6a654276 Michael Hanselmann
60 6a654276 Michael Hanselmann
  @classmethod
61 6a654276 Michael Hanselmann
  def FromDict(cls, data):
62 6a654276 Michael Hanselmann
    """Creates instance object from JSON dictionary.
63 6a654276 Michael Hanselmann

64 6a654276 Michael Hanselmann
    """
65 6a654276 Michael Hanselmann
    nicmac = []
66 6a654276 Michael Hanselmann
67 6a654276 Michael Hanselmann
    macaddr = data.get("nic.mac/0")
68 6a654276 Michael Hanselmann
    if macaddr:
69 6a654276 Michael Hanselmann
      nicmac.append(macaddr)
70 6a654276 Michael Hanselmann
71 6a654276 Michael Hanselmann
    return cls(name=data["name"], nicmac=nicmac)
72 6a654276 Michael Hanselmann
73 6a654276 Michael Hanselmann
  def __getitem__(self, key):
74 6a654276 Michael Hanselmann
    """Legacy dict-like interface.
75 6a654276 Michael Hanselmann

76 6a654276 Michael Hanselmann
    """
77 6a654276 Michael Hanselmann
    if key == "name":
78 6a654276 Michael Hanselmann
      return self.name
79 6a654276 Michael Hanselmann
    else:
80 6a654276 Michael Hanselmann
      raise KeyError(key)
81 6a654276 Michael Hanselmann
82 6a654276 Michael Hanselmann
  def get(self, key, default):
83 6a654276 Michael Hanselmann
    """Legacy dict-like interface.
84 6a654276 Michael Hanselmann

85 6a654276 Michael Hanselmann
    """
86 6a654276 Michael Hanselmann
    try:
87 6a654276 Michael Hanselmann
      return self[key]
88 6a654276 Michael Hanselmann
    except KeyError:
89 6a654276 Michael Hanselmann
      return default
90 6a654276 Michael Hanselmann
91 6a654276 Michael Hanselmann
  def GetNicMacAddr(self, idx, default):
92 6a654276 Michael Hanselmann
    """Returns MAC address for NIC.
93 6a654276 Michael Hanselmann

94 6a654276 Michael Hanselmann
    @type idx: int
95 6a654276 Michael Hanselmann
    @param idx: NIC index
96 6a654276 Michael Hanselmann
    @param default: Default value
97 6a654276 Michael Hanselmann

98 6a654276 Michael Hanselmann
    """
99 6a654276 Michael Hanselmann
    if len(self.nicmac) > idx:
100 6a654276 Michael Hanselmann
      return self.nicmac[idx]
101 6a654276 Michael Hanselmann
    else:
102 6a654276 Michael Hanselmann
      return default
103 6a654276 Michael Hanselmann
104 6a654276 Michael Hanselmann
105 6a654276 Michael Hanselmann
_RESOURCE_CONVERTER = {
106 6a654276 Michael Hanselmann
  "instances": _QaInstance.FromDict,
107 6a654276 Michael Hanselmann
  }
108 6a654276 Michael Hanselmann
109 6a654276 Michael Hanselmann
110 6a654276 Michael Hanselmann
def _ConvertResources((key, value)):
111 6a654276 Michael Hanselmann
  """Converts cluster resources in configuration to Python objects.
112 6a654276 Michael Hanselmann

113 6a654276 Michael Hanselmann
  """
114 6a654276 Michael Hanselmann
  fn = _RESOURCE_CONVERTER.get(key, None)
115 6a654276 Michael Hanselmann
  if fn:
116 6a654276 Michael Hanselmann
    return (key, map(fn, value))
117 6a654276 Michael Hanselmann
  else:
118 6a654276 Michael Hanselmann
    return (key, value)
119 6a654276 Michael Hanselmann
120 6a654276 Michael Hanselmann
121 8a96c5a6 Michael Hanselmann
class _QaConfig(object):
122 8a96c5a6 Michael Hanselmann
  def __init__(self, data):
123 8a96c5a6 Michael Hanselmann
    """Initializes instances of this class.
124 cec9845c Michael Hanselmann

125 8a96c5a6 Michael Hanselmann
    """
126 8a96c5a6 Michael Hanselmann
    self._data = data
127 8a96c5a6 Michael Hanselmann
128 a08e181f Michael Hanselmann
    #: Cluster-wide run-time value of the exclusive storage flag
129 a08e181f Michael Hanselmann
    self._exclusive_storage = None
130 a08e181f Michael Hanselmann
131 8a96c5a6 Michael Hanselmann
  @classmethod
132 8a96c5a6 Michael Hanselmann
  def Load(cls, filename):
133 8a96c5a6 Michael Hanselmann
    """Loads a configuration file and produces a configuration object.
134 8a96c5a6 Michael Hanselmann

135 8a96c5a6 Michael Hanselmann
    @type filename: string
136 8a96c5a6 Michael Hanselmann
    @param filename: Path to configuration file
137 8a96c5a6 Michael Hanselmann
    @rtype: L{_QaConfig}
138 8a96c5a6 Michael Hanselmann

139 8a96c5a6 Michael Hanselmann
    """
140 8a96c5a6 Michael Hanselmann
    data = serializer.LoadJson(utils.ReadFile(filename))
141 8a96c5a6 Michael Hanselmann
142 6a654276 Michael Hanselmann
    result = cls(dict(map(_ConvertResources,
143 6a654276 Michael Hanselmann
                          data.items()))) # pylint: disable=E1103
144 8a96c5a6 Michael Hanselmann
    result.Validate()
145 8a96c5a6 Michael Hanselmann
146 8a96c5a6 Michael Hanselmann
    return result
147 8a96c5a6 Michael Hanselmann
148 8a96c5a6 Michael Hanselmann
  def Validate(self):
149 8a96c5a6 Michael Hanselmann
    """Validates loaded configuration data.
150 8a96c5a6 Michael Hanselmann

151 8a96c5a6 Michael Hanselmann
    """
152 8a96c5a6 Michael Hanselmann
    if not self.get("nodes"):
153 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Need at least one node")
154 8a96c5a6 Michael Hanselmann
155 8a96c5a6 Michael Hanselmann
    if not self.get("instances"):
156 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Need at least one instance")
157 8a96c5a6 Michael Hanselmann
158 8a96c5a6 Michael Hanselmann
    if (self.get("disk") is None or
159 8a96c5a6 Michael Hanselmann
        self.get("disk-growth") is None or
160 8a96c5a6 Michael Hanselmann
        len(self.get("disk")) != len(self.get("disk-growth"))):
161 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Config options 'disk' and 'disk-growth' must exist"
162 8a96c5a6 Michael Hanselmann
                           " and have the same number of items")
163 8a96c5a6 Michael Hanselmann
164 8a96c5a6 Michael Hanselmann
    check = self.GetInstanceCheckScript()
165 8a96c5a6 Michael Hanselmann
    if check:
166 8a96c5a6 Michael Hanselmann
      try:
167 8a96c5a6 Michael Hanselmann
        os.stat(check)
168 8a96c5a6 Michael Hanselmann
      except EnvironmentError, err:
169 8a96c5a6 Michael Hanselmann
        raise qa_error.Error("Can't find instance check script '%s': %s" %
170 8a96c5a6 Michael Hanselmann
                             (check, err))
171 8a96c5a6 Michael Hanselmann
172 8a96c5a6 Michael Hanselmann
    enabled_hv = frozenset(self.GetEnabledHypervisors())
173 8a96c5a6 Michael Hanselmann
    if not enabled_hv:
174 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("No hypervisor is enabled")
175 8a96c5a6 Michael Hanselmann
176 8a96c5a6 Michael Hanselmann
    difference = enabled_hv - constants.HYPER_TYPES
177 8a96c5a6 Michael Hanselmann
    if difference:
178 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Unknown hypervisor(s) enabled: %s" %
179 8a96c5a6 Michael Hanselmann
                           utils.CommaJoin(difference))
180 8a96c5a6 Michael Hanselmann
181 8a96c5a6 Michael Hanselmann
  def __getitem__(self, name):
182 8a96c5a6 Michael Hanselmann
    """Returns configuration value.
183 8a96c5a6 Michael Hanselmann

184 8a96c5a6 Michael Hanselmann
    @type name: string
185 8a96c5a6 Michael Hanselmann
    @param name: Name of configuration entry
186 8a96c5a6 Michael Hanselmann

187 8a96c5a6 Michael Hanselmann
    """
188 8a96c5a6 Michael Hanselmann
    return self._data[name]
189 8a96c5a6 Michael Hanselmann
190 8a96c5a6 Michael Hanselmann
  def get(self, name, default=None):
191 8a96c5a6 Michael Hanselmann
    """Returns configuration value.
192 8a96c5a6 Michael Hanselmann

193 8a96c5a6 Michael Hanselmann
    @type name: string
194 8a96c5a6 Michael Hanselmann
    @param name: Name of configuration entry
195 8a96c5a6 Michael Hanselmann
    @param default: Default value
196 8a96c5a6 Michael Hanselmann

197 8a96c5a6 Michael Hanselmann
    """
198 8a96c5a6 Michael Hanselmann
    return self._data.get(name, default)
199 cec9845c Michael Hanselmann
200 8a96c5a6 Michael Hanselmann
  def GetMasterNode(self):
201 8a96c5a6 Michael Hanselmann
    """Returns the default master node for the cluster.
202 cec9845c Michael Hanselmann

203 8a96c5a6 Michael Hanselmann
    """
204 8a96c5a6 Michael Hanselmann
    return self["nodes"][0]
205 8a96c5a6 Michael Hanselmann
206 8a96c5a6 Michael Hanselmann
  def GetInstanceCheckScript(self):
207 8a96c5a6 Michael Hanselmann
    """Returns path to instance check script or C{None}.
208 8a96c5a6 Michael Hanselmann

209 8a96c5a6 Michael Hanselmann
    """
210 8a96c5a6 Michael Hanselmann
    return self._data.get(_INSTANCE_CHECK_KEY, None)
211 cec9845c Michael Hanselmann
212 8a96c5a6 Michael Hanselmann
  def GetEnabledHypervisors(self):
213 8a96c5a6 Michael Hanselmann
    """Returns list of enabled hypervisors.
214 cec9845c Michael Hanselmann

215 8a96c5a6 Michael Hanselmann
    @rtype: list
216 cec9845c Michael Hanselmann

217 8a96c5a6 Michael Hanselmann
    """
218 c9e05005 Michael Hanselmann
    try:
219 8a96c5a6 Michael Hanselmann
      value = self._data[_ENABLED_HV_KEY]
220 8a96c5a6 Michael Hanselmann
    except KeyError:
221 8a96c5a6 Michael Hanselmann
      return [constants.DEFAULT_ENABLED_HYPERVISOR]
222 8a96c5a6 Michael Hanselmann
    else:
223 8a96c5a6 Michael Hanselmann
      if value is None:
224 8a96c5a6 Michael Hanselmann
        return []
225 8a96c5a6 Michael Hanselmann
      elif isinstance(value, basestring):
226 8a96c5a6 Michael Hanselmann
        # The configuration key ("enabled-hypervisors") implies there can be
227 8a96c5a6 Michael Hanselmann
        # multiple values. Multiple hypervisors are comma-separated on the
228 8a96c5a6 Michael Hanselmann
        # command line option to "gnt-cluster init", so we need to handle them
229 8a96c5a6 Michael Hanselmann
        # equally here.
230 8a96c5a6 Michael Hanselmann
        return value.split(",")
231 8a96c5a6 Michael Hanselmann
      else:
232 8a96c5a6 Michael Hanselmann
        return value
233 8a96c5a6 Michael Hanselmann
234 8a96c5a6 Michael Hanselmann
  def GetDefaultHypervisor(self):
235 8a96c5a6 Michael Hanselmann
    """Returns the default hypervisor to be used.
236 8a96c5a6 Michael Hanselmann

237 8a96c5a6 Michael Hanselmann
    """
238 8a96c5a6 Michael Hanselmann
    return self.GetEnabledHypervisors()[0]
239 8a96c5a6 Michael Hanselmann
240 a08e181f Michael Hanselmann
  def SetExclusiveStorage(self, value):
241 a08e181f Michael Hanselmann
    """Set the expected value of the C{exclusive_storage} flag for the cluster.
242 a08e181f Michael Hanselmann

243 a08e181f Michael Hanselmann
    """
244 a08e181f Michael Hanselmann
    self._exclusive_storage = bool(value)
245 a08e181f Michael Hanselmann
246 a08e181f Michael Hanselmann
  def GetExclusiveStorage(self):
247 a08e181f Michael Hanselmann
    """Get the expected value of the C{exclusive_storage} flag for the cluster.
248 a08e181f Michael Hanselmann

249 a08e181f Michael Hanselmann
    """
250 a08e181f Michael Hanselmann
    value = self._exclusive_storage
251 a08e181f Michael Hanselmann
    assert value is not None
252 a08e181f Michael Hanselmann
    return value
253 a08e181f Michael Hanselmann
254 a08e181f Michael Hanselmann
  def IsTemplateSupported(self, templ):
255 a08e181f Michael Hanselmann
    """Is the given disk template supported by the current configuration?
256 a08e181f Michael Hanselmann

257 a08e181f Michael Hanselmann
    """
258 cf62af3a Michael Hanselmann
    return (not self.GetExclusiveStorage() or
259 cf62af3a Michael Hanselmann
            templ in constants.DTS_EXCL_STORAGE)
260 a08e181f Michael Hanselmann
261 8a96c5a6 Michael Hanselmann
262 8a96c5a6 Michael Hanselmann
def Load(path):
263 8a96c5a6 Michael Hanselmann
  """Loads the passed configuration file.
264 8a96c5a6 Michael Hanselmann

265 8a96c5a6 Michael Hanselmann
  """
266 8a96c5a6 Michael Hanselmann
  global _config # pylint: disable=W0603
267 8a96c5a6 Michael Hanselmann
268 8a96c5a6 Michael Hanselmann
  _config = _QaConfig.Load(path)
269 c9e05005 Michael Hanselmann
270 e7b6183b Michael Hanselmann
271 8a96c5a6 Michael Hanselmann
def GetConfig():
272 8a96c5a6 Michael Hanselmann
  """Returns the configuration object.
273 8a96c5a6 Michael Hanselmann

274 8a96c5a6 Michael Hanselmann
  """
275 8a96c5a6 Michael Hanselmann
  if _config is None:
276 8a96c5a6 Michael Hanselmann
    raise RuntimeError("Configuration not yet loaded")
277 8a96c5a6 Michael Hanselmann
278 8a96c5a6 Michael Hanselmann
  return _config
279 e7b6183b Michael Hanselmann
280 cec9845c Michael Hanselmann
281 cec9845c Michael Hanselmann
def get(name, default=None):
282 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.get}.
283 8a96c5a6 Michael Hanselmann

284 8a96c5a6 Michael Hanselmann
  """
285 8a96c5a6 Michael Hanselmann
  return GetConfig().get(name, default=default)
286 cec9845c Michael Hanselmann
287 cec9845c Michael Hanselmann
288 a0c3e726 Michael Hanselmann
class Either:
289 a0c3e726 Michael Hanselmann
  def __init__(self, tests):
290 a0c3e726 Michael Hanselmann
    """Initializes this class.
291 a0c3e726 Michael Hanselmann

292 a0c3e726 Michael Hanselmann
    @type tests: list or string
293 a0c3e726 Michael Hanselmann
    @param tests: List of test names
294 a0c3e726 Michael Hanselmann
    @see: L{TestEnabled} for details
295 a0c3e726 Michael Hanselmann

296 a0c3e726 Michael Hanselmann
    """
297 a0c3e726 Michael Hanselmann
    self.tests = tests
298 a0c3e726 Michael Hanselmann
299 a0c3e726 Michael Hanselmann
300 a0c3e726 Michael Hanselmann
def _MakeSequence(value):
301 a0c3e726 Michael Hanselmann
  """Make sequence of single argument.
302 a0c3e726 Michael Hanselmann

303 a0c3e726 Michael Hanselmann
  If the single argument is not already a list or tuple, a list with the
304 a0c3e726 Michael Hanselmann
  argument as a single item is returned.
305 a0c3e726 Michael Hanselmann

306 a0c3e726 Michael Hanselmann
  """
307 a0c3e726 Michael Hanselmann
  if isinstance(value, (list, tuple)):
308 a0c3e726 Michael Hanselmann
    return value
309 a0c3e726 Michael Hanselmann
  else:
310 a0c3e726 Michael Hanselmann
    return [value]
311 a0c3e726 Michael Hanselmann
312 a0c3e726 Michael Hanselmann
313 a0c3e726 Michael Hanselmann
def _TestEnabledInner(check_fn, names, fn):
314 a0c3e726 Michael Hanselmann
  """Evaluate test conditions.
315 a0c3e726 Michael Hanselmann

316 a0c3e726 Michael Hanselmann
  @type check_fn: callable
317 a0c3e726 Michael Hanselmann
  @param check_fn: Callback to check whether a test is enabled
318 a0c3e726 Michael Hanselmann
  @type names: sequence or string
319 a0c3e726 Michael Hanselmann
  @param names: Test name(s)
320 a0c3e726 Michael Hanselmann
  @type fn: callable
321 a0c3e726 Michael Hanselmann
  @param fn: Aggregation function
322 a0c3e726 Michael Hanselmann
  @rtype: bool
323 a0c3e726 Michael Hanselmann
  @return: Whether test is enabled
324 a0c3e726 Michael Hanselmann

325 a0c3e726 Michael Hanselmann
  """
326 a0c3e726 Michael Hanselmann
  names = _MakeSequence(names)
327 a0c3e726 Michael Hanselmann
328 a0c3e726 Michael Hanselmann
  result = []
329 a0c3e726 Michael Hanselmann
330 a0c3e726 Michael Hanselmann
  for name in names:
331 a0c3e726 Michael Hanselmann
    if isinstance(name, Either):
332 a0c3e726 Michael Hanselmann
      value = _TestEnabledInner(check_fn, name.tests, compat.any)
333 a0c3e726 Michael Hanselmann
    elif isinstance(name, (list, tuple)):
334 a0c3e726 Michael Hanselmann
      value = _TestEnabledInner(check_fn, name, compat.all)
335 a0c3e726 Michael Hanselmann
    else:
336 a0c3e726 Michael Hanselmann
      value = check_fn(name)
337 a0c3e726 Michael Hanselmann
338 a0c3e726 Michael Hanselmann
    result.append(value)
339 a0c3e726 Michael Hanselmann
340 a0c3e726 Michael Hanselmann
  return fn(result)
341 a0c3e726 Michael Hanselmann
342 a0c3e726 Michael Hanselmann
343 a0c3e726 Michael Hanselmann
def TestEnabled(tests, _cfg=None):
344 7d88f255 Iustin Pop
  """Returns True if the given tests are enabled.
345 7d88f255 Iustin Pop

346 a0c3e726 Michael Hanselmann
  @param tests: A single test as a string, or a list of tests to check; can
347 a0c3e726 Michael Hanselmann
    contain L{Either} for OR conditions, AND is default
348 1010ec70 Michael Hanselmann

349 1010ec70 Michael Hanselmann
  """
350 a0c3e726 Michael Hanselmann
  if _cfg is None:
351 8a96c5a6 Michael Hanselmann
    cfg = GetConfig()
352 8a96c5a6 Michael Hanselmann
  else:
353 8a96c5a6 Michael Hanselmann
    cfg = _cfg
354 59a8fe48 Michael Hanselmann
355 59a8fe48 Michael Hanselmann
  # Get settings for all tests
356 8a96c5a6 Michael Hanselmann
  cfg_tests = cfg.get("tests", {})
357 59a8fe48 Michael Hanselmann
358 59a8fe48 Michael Hanselmann
  # Get default setting
359 a0c3e726 Michael Hanselmann
  default = cfg_tests.get("default", True)
360 59a8fe48 Michael Hanselmann
361 a0c3e726 Michael Hanselmann
  return _TestEnabledInner(lambda name: cfg_tests.get(name, default),
362 a0c3e726 Michael Hanselmann
                           tests, compat.all)
363 cec9845c Michael Hanselmann
364 cec9845c Michael Hanselmann
365 8a96c5a6 Michael Hanselmann
def GetInstanceCheckScript(*args):
366 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetInstanceCheckScript}.
367 c9e05005 Michael Hanselmann

368 c9e05005 Michael Hanselmann
  """
369 8a96c5a6 Michael Hanselmann
  return GetConfig().GetInstanceCheckScript(*args)
370 c9e05005 Michael Hanselmann
371 e7b6183b Michael Hanselmann
372 8a96c5a6 Michael Hanselmann
def GetEnabledHypervisors(*args):
373 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetEnabledHypervisors}.
374 e7b6183b Michael Hanselmann

375 e7b6183b Michael Hanselmann
  """
376 8a96c5a6 Michael Hanselmann
  return GetConfig().GetEnabledHypervisors(*args)
377 e7b6183b Michael Hanselmann
378 e7b6183b Michael Hanselmann
379 8a96c5a6 Michael Hanselmann
def GetDefaultHypervisor(*args):
380 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetDefaultHypervisor}.
381 e7b6183b Michael Hanselmann

382 e7b6183b Michael Hanselmann
  """
383 8a96c5a6 Michael Hanselmann
  return GetConfig().GetDefaultHypervisor(*args)
384 e7b6183b Michael Hanselmann
385 e7b6183b Michael Hanselmann
386 f346a7d9 Michael Hanselmann
def GetInstanceNicMac(inst, default=None):
387 f346a7d9 Michael Hanselmann
  """Returns MAC address for instance's network interface.
388 f346a7d9 Michael Hanselmann

389 f346a7d9 Michael Hanselmann
  """
390 6a654276 Michael Hanselmann
  return inst.GetNicMacAddr(0, default)
391 f346a7d9 Michael Hanselmann
392 f346a7d9 Michael Hanselmann
393 cec9845c Michael Hanselmann
def GetMasterNode():
394 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetMasterNode}.
395 8a96c5a6 Michael Hanselmann

396 8a96c5a6 Michael Hanselmann
  """
397 8a96c5a6 Michael Hanselmann
  return GetConfig().GetMasterNode()
398 cec9845c Michael Hanselmann
399 cec9845c Michael Hanselmann
400 6a654276 Michael Hanselmann
def AcquireInstance(_cfg=None):
401 cec9845c Michael Hanselmann
  """Returns an instance which isn't in use.
402 cec9845c Michael Hanselmann

403 cec9845c Michael Hanselmann
  """
404 6a654276 Michael Hanselmann
  if _cfg is None:
405 6a654276 Michael Hanselmann
    cfg = GetConfig()
406 6a654276 Michael Hanselmann
  else:
407 6a654276 Michael Hanselmann
    cfg = _cfg
408 6a654276 Michael Hanselmann
409 cec9845c Michael Hanselmann
  # Filter out unwanted instances
410 6a654276 Michael Hanselmann
  instances = filter(lambda inst: not inst.used, cfg["instances"])
411 cec9845c Michael Hanselmann
412 6a654276 Michael Hanselmann
  if not instances:
413 cec9845c Michael Hanselmann
    raise qa_error.OutOfInstancesError("No instances left")
414 cec9845c Michael Hanselmann
415 cec9845c Michael Hanselmann
  inst = instances[0]
416 6a654276 Michael Hanselmann
417 6a654276 Michael Hanselmann
  assert not inst.used
418 6a654276 Michael Hanselmann
  assert inst.disk_template is None
419 6a654276 Michael Hanselmann
420 6a654276 Michael Hanselmann
  inst.used = True
421 6a654276 Michael Hanselmann
422 cec9845c Michael Hanselmann
  return inst
423 cec9845c Michael Hanselmann
424 cec9845c Michael Hanselmann
425 cec9845c Michael Hanselmann
def ReleaseInstance(inst):
426 6a654276 Michael Hanselmann
  inst.used = False
427 6a654276 Michael Hanselmann
  inst.disk_template = None
428 cec9845c Michael Hanselmann
429 cec9845c Michael Hanselmann
430 906a0346 Bernardo Dal Seno
def GetInstanceTemplate(inst):
431 906a0346 Bernardo Dal Seno
  """Return the disk template of an instance.
432 906a0346 Bernardo Dal Seno

433 906a0346 Bernardo Dal Seno
  """
434 6a654276 Michael Hanselmann
  templ = inst.disk_template
435 906a0346 Bernardo Dal Seno
  assert templ is not None
436 906a0346 Bernardo Dal Seno
  return templ
437 906a0346 Bernardo Dal Seno
438 906a0346 Bernardo Dal Seno
439 906a0346 Bernardo Dal Seno
def SetInstanceTemplate(inst, template):
440 906a0346 Bernardo Dal Seno
  """Set the disk template for an instance.
441 906a0346 Bernardo Dal Seno

442 906a0346 Bernardo Dal Seno
  """
443 6a654276 Michael Hanselmann
  inst.disk_template = template
444 906a0346 Bernardo Dal Seno
445 906a0346 Bernardo Dal Seno
446 6a0f22e1 Bernardo Dal Seno
def SetExclusiveStorage(value):
447 a08e181f Michael Hanselmann
  """Wrapper for L{_QaConfig.SetExclusiveStorage}.
448 6a0f22e1 Bernardo Dal Seno

449 6a0f22e1 Bernardo Dal Seno
  """
450 a08e181f Michael Hanselmann
  return GetConfig().SetExclusiveStorage(value)
451 6a0f22e1 Bernardo Dal Seno
452 6a0f22e1 Bernardo Dal Seno
453 6a0f22e1 Bernardo Dal Seno
def GetExclusiveStorage():
454 a08e181f Michael Hanselmann
  """Wrapper for L{_QaConfig.GetExclusiveStorage}.
455 6a0f22e1 Bernardo Dal Seno

456 6a0f22e1 Bernardo Dal Seno
  """
457 a08e181f Michael Hanselmann
  return GetConfig().GetExclusiveStorage()
458 6a0f22e1 Bernardo Dal Seno
459 6a0f22e1 Bernardo Dal Seno
460 27eba428 Bernardo Dal Seno
def IsTemplateSupported(templ):
461 a08e181f Michael Hanselmann
  """Wrapper for L{_QaConfig.GetExclusiveStorage}.
462 27eba428 Bernardo Dal Seno

463 27eba428 Bernardo Dal Seno
  """
464 a08e181f Michael Hanselmann
  return GetConfig().IsTemplateSupported(templ)
465 27eba428 Bernardo Dal Seno
466 27eba428 Bernardo Dal Seno
467 cec9845c Michael Hanselmann
def AcquireNode(exclude=None):
468 cec9845c Michael Hanselmann
  """Returns the least used node.
469 cec9845c Michael Hanselmann

470 cec9845c Michael Hanselmann
  """
471 cec9845c Michael Hanselmann
  master = GetMasterNode()
472 8a96c5a6 Michael Hanselmann
  cfg = GetConfig()
473 cec9845c Michael Hanselmann
474 cec9845c Michael Hanselmann
  # Filter out unwanted nodes
475 cec9845c Michael Hanselmann
  # TODO: Maybe combine filters
476 cec9845c Michael Hanselmann
  if exclude is None:
477 d0c8c01d Iustin Pop
    nodes = cfg["nodes"][:]
478 4b62db14 Michael Hanselmann
  elif isinstance(exclude, (list, tuple)):
479 d0c8c01d Iustin Pop
    nodes = filter(lambda node: node not in exclude, cfg["nodes"])
480 cec9845c Michael Hanselmann
  else:
481 d0c8c01d Iustin Pop
    nodes = filter(lambda node: node != exclude, cfg["nodes"])
482 cec9845c Michael Hanselmann
483 d0c8c01d Iustin Pop
  tmp_flt = lambda node: node.get("_added", False) or node == master
484 cec9845c Michael Hanselmann
  nodes = filter(tmp_flt, nodes)
485 cec9845c Michael Hanselmann
  del tmp_flt
486 cec9845c Michael Hanselmann
487 cec9845c Michael Hanselmann
  if len(nodes) == 0:
488 cec9845c Michael Hanselmann
    raise qa_error.OutOfNodesError("No nodes left")
489 cec9845c Michael Hanselmann
490 cec9845c Michael Hanselmann
  # Get node with least number of uses
491 cec9845c Michael Hanselmann
  def compare(a, b):
492 d0c8c01d Iustin Pop
    result = cmp(a.get("_count", 0), b.get("_count", 0))
493 cec9845c Michael Hanselmann
    if result == 0:
494 d0c8c01d Iustin Pop
      result = cmp(a["primary"], b["primary"])
495 cec9845c Michael Hanselmann
    return result
496 cec9845c Michael Hanselmann
497 cec9845c Michael Hanselmann
  nodes.sort(cmp=compare)
498 cec9845c Michael Hanselmann
499 cec9845c Michael Hanselmann
  node = nodes[0]
500 d0c8c01d Iustin Pop
  node["_count"] = node.get("_count", 0) + 1
501 cec9845c Michael Hanselmann
  return node
502 cec9845c Michael Hanselmann
503 cec9845c Michael Hanselmann
504 7d4f1b45 Bernardo Dal Seno
def AcquireManyNodes(num, exclude=None):
505 7d4f1b45 Bernardo Dal Seno
  """Return the least used nodes.
506 7d4f1b45 Bernardo Dal Seno

507 7d4f1b45 Bernardo Dal Seno
  @type num: int
508 7d4f1b45 Bernardo Dal Seno
  @param num: Number of nodes; can be 0.
509 7d4f1b45 Bernardo Dal Seno
  @type exclude: list of nodes or C{None}
510 7d4f1b45 Bernardo Dal Seno
  @param exclude: nodes to be excluded from the choice
511 7d4f1b45 Bernardo Dal Seno
  @rtype: list of nodes
512 7d4f1b45 Bernardo Dal Seno
  @return: C{num} different nodes
513 7d4f1b45 Bernardo Dal Seno

514 7d4f1b45 Bernardo Dal Seno
  """
515 7d4f1b45 Bernardo Dal Seno
  nodes = []
516 7d4f1b45 Bernardo Dal Seno
  if exclude is None:
517 7d4f1b45 Bernardo Dal Seno
    exclude = []
518 7d4f1b45 Bernardo Dal Seno
  elif isinstance(exclude, (list, tuple)):
519 7d4f1b45 Bernardo Dal Seno
    # Don't modify the incoming argument
520 7d4f1b45 Bernardo Dal Seno
    exclude = list(exclude)
521 7d4f1b45 Bernardo Dal Seno
  else:
522 7d4f1b45 Bernardo Dal Seno
    exclude = [exclude]
523 7d4f1b45 Bernardo Dal Seno
524 7d4f1b45 Bernardo Dal Seno
  try:
525 7d4f1b45 Bernardo Dal Seno
    for _ in range(0, num):
526 7d4f1b45 Bernardo Dal Seno
      n = AcquireNode(exclude=exclude)
527 7d4f1b45 Bernardo Dal Seno
      nodes.append(n)
528 7d4f1b45 Bernardo Dal Seno
      exclude.append(n)
529 7d4f1b45 Bernardo Dal Seno
  except qa_error.OutOfNodesError:
530 7d4f1b45 Bernardo Dal Seno
    ReleaseManyNodes(nodes)
531 7d4f1b45 Bernardo Dal Seno
    raise
532 7d4f1b45 Bernardo Dal Seno
  return nodes
533 7d4f1b45 Bernardo Dal Seno
534 7d4f1b45 Bernardo Dal Seno
535 cec9845c Michael Hanselmann
def ReleaseNode(node):
536 d0c8c01d Iustin Pop
  node["_count"] = node.get("_count", 0) - 1
537 7d4f1b45 Bernardo Dal Seno
538 7d4f1b45 Bernardo Dal Seno
539 7d4f1b45 Bernardo Dal Seno
def ReleaseManyNodes(nodes):
540 7d4f1b45 Bernardo Dal Seno
  for n in nodes:
541 7d4f1b45 Bernardo Dal Seno
    ReleaseNode(n)