Statistics
| Branch: | Tag: | Revision:

root / qa / qa_config.py @ 02cff8aa

History | View | Annotate | Download (15.8 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 76fda900 Michael Hanselmann
from ganeti import ht
33 cec9845c Michael Hanselmann
34 cec9845c Michael Hanselmann
import qa_error
35 cec9845c Michael Hanselmann
36 cec9845c Michael Hanselmann
37 c9e05005 Michael Hanselmann
_INSTANCE_CHECK_KEY = "instance-check"
38 e7b6183b Michael Hanselmann
_ENABLED_HV_KEY = "enabled-hypervisors"
39 76fda900 Michael Hanselmann
_VCLUSTER_MASTER_KEY = "vcluster-master"
40 76fda900 Michael Hanselmann
_VCLUSTER_BASEDIR_KEY = "vcluster-basedir"
41 2dae8d64 Helga Velroyen
_ENABLED_DISK_TEMPLATES_KEY = "enabled-disk-templates"
42 f9329a6c Michael Hanselmann
43 8a96c5a6 Michael Hanselmann
#: QA configuration (L{_QaConfig})
44 8a96c5a6 Michael Hanselmann
_config = None
45 cec9845c Michael Hanselmann
46 cec9845c Michael Hanselmann
47 6a654276 Michael Hanselmann
class _QaInstance(object):
48 6a654276 Michael Hanselmann
  __slots__ = [
49 6a654276 Michael Hanselmann
    "name",
50 6a654276 Michael Hanselmann
    "nicmac",
51 2176724e Michael Hanselmann
    "_used",
52 02a5fe0e Michael Hanselmann
    "_disk_template",
53 6a654276 Michael Hanselmann
    ]
54 6a654276 Michael Hanselmann
55 6a654276 Michael Hanselmann
  def __init__(self, name, nicmac):
56 6a654276 Michael Hanselmann
    """Initializes instances of this class.
57 6a654276 Michael Hanselmann

58 6a654276 Michael Hanselmann
    """
59 6a654276 Michael Hanselmann
    self.name = name
60 6a654276 Michael Hanselmann
    self.nicmac = nicmac
61 2176724e Michael Hanselmann
    self._used = None
62 02a5fe0e Michael Hanselmann
    self._disk_template = None
63 6a654276 Michael Hanselmann
64 6a654276 Michael Hanselmann
  @classmethod
65 6a654276 Michael Hanselmann
  def FromDict(cls, data):
66 6a654276 Michael Hanselmann
    """Creates instance object from JSON dictionary.
67 6a654276 Michael Hanselmann

68 6a654276 Michael Hanselmann
    """
69 6a654276 Michael Hanselmann
    nicmac = []
70 6a654276 Michael Hanselmann
71 6a654276 Michael Hanselmann
    macaddr = data.get("nic.mac/0")
72 6a654276 Michael Hanselmann
    if macaddr:
73 6a654276 Michael Hanselmann
      nicmac.append(macaddr)
74 6a654276 Michael Hanselmann
75 6a654276 Michael Hanselmann
    return cls(name=data["name"], nicmac=nicmac)
76 6a654276 Michael Hanselmann
77 e80edd3b Michael Hanselmann
  def __repr__(self):
78 e80edd3b Michael Hanselmann
    status = [
79 e80edd3b Michael Hanselmann
      "%s.%s" % (self.__class__.__module__, self.__class__.__name__),
80 e80edd3b Michael Hanselmann
      "name=%s" % self.name,
81 e80edd3b Michael Hanselmann
      "nicmac=%s" % self.nicmac,
82 e80edd3b Michael Hanselmann
      "used=%s" % self._used,
83 e80edd3b Michael Hanselmann
      "disk_template=%s" % self._disk_template,
84 e80edd3b Michael Hanselmann
      ]
85 e80edd3b Michael Hanselmann
86 e80edd3b Michael Hanselmann
    return "<%s at %#x>" % (" ".join(status), id(self))
87 e80edd3b Michael Hanselmann
88 2176724e Michael Hanselmann
  def Use(self):
89 2176724e Michael Hanselmann
    """Marks instance as being in use.
90 2176724e Michael Hanselmann

91 2176724e Michael Hanselmann
    """
92 2176724e Michael Hanselmann
    assert not self._used
93 2176724e Michael Hanselmann
    assert self._disk_template is None
94 2176724e Michael Hanselmann
95 2176724e Michael Hanselmann
    self._used = True
96 2176724e Michael Hanselmann
97 6f88e076 Michael Hanselmann
  def Release(self):
98 6f88e076 Michael Hanselmann
    """Releases instance and makes it available again.
99 6f88e076 Michael Hanselmann

100 6f88e076 Michael Hanselmann
    """
101 2176724e Michael Hanselmann
    assert self._used, \
102 6f88e076 Michael Hanselmann
      ("Instance '%s' was never acquired or released more than once" %
103 6f88e076 Michael Hanselmann
       self.name)
104 6f88e076 Michael Hanselmann
105 2176724e Michael Hanselmann
    self._used = False
106 02a5fe0e Michael Hanselmann
    self._disk_template = None
107 6f88e076 Michael Hanselmann
108 6a654276 Michael Hanselmann
  def GetNicMacAddr(self, idx, default):
109 6a654276 Michael Hanselmann
    """Returns MAC address for NIC.
110 6a654276 Michael Hanselmann

111 6a654276 Michael Hanselmann
    @type idx: int
112 6a654276 Michael Hanselmann
    @param idx: NIC index
113 6a654276 Michael Hanselmann
    @param default: Default value
114 6a654276 Michael Hanselmann

115 6a654276 Michael Hanselmann
    """
116 6a654276 Michael Hanselmann
    if len(self.nicmac) > idx:
117 6a654276 Michael Hanselmann
      return self.nicmac[idx]
118 6a654276 Michael Hanselmann
    else:
119 6a654276 Michael Hanselmann
      return default
120 6a654276 Michael Hanselmann
121 02a5fe0e Michael Hanselmann
  def SetDiskTemplate(self, template):
122 02a5fe0e Michael Hanselmann
    """Set the disk template.
123 02a5fe0e Michael Hanselmann

124 02a5fe0e Michael Hanselmann
    """
125 02a5fe0e Michael Hanselmann
    assert template in constants.DISK_TEMPLATES
126 02a5fe0e Michael Hanselmann
127 02a5fe0e Michael Hanselmann
    self._disk_template = template
128 02a5fe0e Michael Hanselmann
129 02a5fe0e Michael Hanselmann
  @property
130 2176724e Michael Hanselmann
  def used(self):
131 2176724e Michael Hanselmann
    """Returns boolean denoting whether instance is in use.
132 2176724e Michael Hanselmann

133 2176724e Michael Hanselmann
    """
134 2176724e Michael Hanselmann
    return self._used
135 2176724e Michael Hanselmann
136 2176724e Michael Hanselmann
  @property
137 02a5fe0e Michael Hanselmann
  def disk_template(self):
138 02a5fe0e Michael Hanselmann
    """Returns the current disk template.
139 02a5fe0e Michael Hanselmann

140 02a5fe0e Michael Hanselmann
    """
141 02a5fe0e Michael Hanselmann
    return self._disk_template
142 02a5fe0e Michael Hanselmann
143 6a654276 Michael Hanselmann
144 dbdb0594 Michael Hanselmann
class _QaNode(object):
145 dbdb0594 Michael Hanselmann
  __slots__ = [
146 dbdb0594 Michael Hanselmann
    "primary",
147 dbdb0594 Michael Hanselmann
    "secondary",
148 dbdb0594 Michael Hanselmann
    "_added",
149 565cb4bf Michael Hanselmann
    "_use_count",
150 dbdb0594 Michael Hanselmann
    ]
151 dbdb0594 Michael Hanselmann
152 dbdb0594 Michael Hanselmann
  def __init__(self, primary, secondary):
153 dbdb0594 Michael Hanselmann
    """Initializes instances of this class.
154 dbdb0594 Michael Hanselmann

155 dbdb0594 Michael Hanselmann
    """
156 dbdb0594 Michael Hanselmann
    self.primary = primary
157 dbdb0594 Michael Hanselmann
    self.secondary = secondary
158 dbdb0594 Michael Hanselmann
    self._added = False
159 565cb4bf Michael Hanselmann
    self._use_count = 0
160 dbdb0594 Michael Hanselmann
161 dbdb0594 Michael Hanselmann
  @classmethod
162 dbdb0594 Michael Hanselmann
  def FromDict(cls, data):
163 dbdb0594 Michael Hanselmann
    """Creates node object from JSON dictionary.
164 dbdb0594 Michael Hanselmann

165 dbdb0594 Michael Hanselmann
    """
166 dbdb0594 Michael Hanselmann
    return cls(primary=data["primary"], secondary=data.get("secondary"))
167 dbdb0594 Michael Hanselmann
168 e80edd3b Michael Hanselmann
  def __repr__(self):
169 e80edd3b Michael Hanselmann
    status = [
170 e80edd3b Michael Hanselmann
      "%s.%s" % (self.__class__.__module__, self.__class__.__name__),
171 e80edd3b Michael Hanselmann
      "primary=%s" % self.primary,
172 e80edd3b Michael Hanselmann
      "secondary=%s" % self.secondary,
173 e80edd3b Michael Hanselmann
      "added=%s" % self._added,
174 e80edd3b Michael Hanselmann
      "use_count=%s" % self._use_count,
175 e80edd3b Michael Hanselmann
      ]
176 e80edd3b Michael Hanselmann
177 e80edd3b Michael Hanselmann
    return "<%s at %#x>" % (" ".join(status), id(self))
178 e80edd3b Michael Hanselmann
179 dbdb0594 Michael Hanselmann
  def Use(self):
180 dbdb0594 Michael Hanselmann
    """Marks a node as being in use.
181 dbdb0594 Michael Hanselmann

182 dbdb0594 Michael Hanselmann
    """
183 565cb4bf Michael Hanselmann
    assert self._use_count >= 0
184 dbdb0594 Michael Hanselmann
185 565cb4bf Michael Hanselmann
    self._use_count += 1
186 dbdb0594 Michael Hanselmann
187 dbdb0594 Michael Hanselmann
    return self
188 dbdb0594 Michael Hanselmann
189 565cb4bf Michael Hanselmann
  def Release(self):
190 565cb4bf Michael Hanselmann
    """Release a node (opposite of L{Use}).
191 565cb4bf Michael Hanselmann

192 565cb4bf Michael Hanselmann
    """
193 565cb4bf Michael Hanselmann
    assert self.use_count > 0
194 565cb4bf Michael Hanselmann
195 565cb4bf Michael Hanselmann
    self._use_count -= 1
196 565cb4bf Michael Hanselmann
197 dbdb0594 Michael Hanselmann
  def MarkAdded(self):
198 dbdb0594 Michael Hanselmann
    """Marks node as having been added to a cluster.
199 dbdb0594 Michael Hanselmann

200 dbdb0594 Michael Hanselmann
    """
201 dbdb0594 Michael Hanselmann
    assert not self._added
202 dbdb0594 Michael Hanselmann
    self._added = True
203 dbdb0594 Michael Hanselmann
204 dbdb0594 Michael Hanselmann
  def MarkRemoved(self):
205 dbdb0594 Michael Hanselmann
    """Marks node as having been removed from a cluster.
206 dbdb0594 Michael Hanselmann

207 dbdb0594 Michael Hanselmann
    """
208 dbdb0594 Michael Hanselmann
    assert self._added
209 dbdb0594 Michael Hanselmann
    self._added = False
210 dbdb0594 Michael Hanselmann
211 dbdb0594 Michael Hanselmann
  @property
212 dbdb0594 Michael Hanselmann
  def added(self):
213 dbdb0594 Michael Hanselmann
    """Returns whether a node is part of a cluster.
214 dbdb0594 Michael Hanselmann

215 dbdb0594 Michael Hanselmann
    """
216 dbdb0594 Michael Hanselmann
    return self._added
217 dbdb0594 Michael Hanselmann
218 565cb4bf Michael Hanselmann
  @property
219 565cb4bf Michael Hanselmann
  def use_count(self):
220 565cb4bf Michael Hanselmann
    """Returns number of current uses (controlled by L{Use} and L{Release}).
221 565cb4bf Michael Hanselmann

222 565cb4bf Michael Hanselmann
    """
223 565cb4bf Michael Hanselmann
    return self._use_count
224 565cb4bf Michael Hanselmann
225 dbdb0594 Michael Hanselmann
226 6a654276 Michael Hanselmann
_RESOURCE_CONVERTER = {
227 6a654276 Michael Hanselmann
  "instances": _QaInstance.FromDict,
228 dbdb0594 Michael Hanselmann
  "nodes": _QaNode.FromDict,
229 6a654276 Michael Hanselmann
  }
230 6a654276 Michael Hanselmann
231 6a654276 Michael Hanselmann
232 6a654276 Michael Hanselmann
def _ConvertResources((key, value)):
233 6a654276 Michael Hanselmann
  """Converts cluster resources in configuration to Python objects.
234 6a654276 Michael Hanselmann

235 6a654276 Michael Hanselmann
  """
236 6a654276 Michael Hanselmann
  fn = _RESOURCE_CONVERTER.get(key, None)
237 6a654276 Michael Hanselmann
  if fn:
238 6a654276 Michael Hanselmann
    return (key, map(fn, value))
239 6a654276 Michael Hanselmann
  else:
240 6a654276 Michael Hanselmann
    return (key, value)
241 6a654276 Michael Hanselmann
242 6a654276 Michael Hanselmann
243 8a96c5a6 Michael Hanselmann
class _QaConfig(object):
244 8a96c5a6 Michael Hanselmann
  def __init__(self, data):
245 8a96c5a6 Michael Hanselmann
    """Initializes instances of this class.
246 cec9845c Michael Hanselmann

247 8a96c5a6 Michael Hanselmann
    """
248 8a96c5a6 Michael Hanselmann
    self._data = data
249 8a96c5a6 Michael Hanselmann
250 a08e181f Michael Hanselmann
    #: Cluster-wide run-time value of the exclusive storage flag
251 a08e181f Michael Hanselmann
    self._exclusive_storage = None
252 a08e181f Michael Hanselmann
253 8a96c5a6 Michael Hanselmann
  @classmethod
254 8a96c5a6 Michael Hanselmann
  def Load(cls, filename):
255 8a96c5a6 Michael Hanselmann
    """Loads a configuration file and produces a configuration object.
256 8a96c5a6 Michael Hanselmann

257 8a96c5a6 Michael Hanselmann
    @type filename: string
258 8a96c5a6 Michael Hanselmann
    @param filename: Path to configuration file
259 8a96c5a6 Michael Hanselmann
    @rtype: L{_QaConfig}
260 8a96c5a6 Michael Hanselmann

261 8a96c5a6 Michael Hanselmann
    """
262 8a96c5a6 Michael Hanselmann
    data = serializer.LoadJson(utils.ReadFile(filename))
263 8a96c5a6 Michael Hanselmann
264 6a654276 Michael Hanselmann
    result = cls(dict(map(_ConvertResources,
265 6a654276 Michael Hanselmann
                          data.items()))) # pylint: disable=E1103
266 8a96c5a6 Michael Hanselmann
    result.Validate()
267 8a96c5a6 Michael Hanselmann
268 8a96c5a6 Michael Hanselmann
    return result
269 8a96c5a6 Michael Hanselmann
270 8a96c5a6 Michael Hanselmann
  def Validate(self):
271 8a96c5a6 Michael Hanselmann
    """Validates loaded configuration data.
272 8a96c5a6 Michael Hanselmann

273 8a96c5a6 Michael Hanselmann
    """
274 47aa6ec9 Michael Hanselmann
    if not self.get("name"):
275 47aa6ec9 Michael Hanselmann
      raise qa_error.Error("Cluster name is required")
276 47aa6ec9 Michael Hanselmann
277 8a96c5a6 Michael Hanselmann
    if not self.get("nodes"):
278 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Need at least one node")
279 8a96c5a6 Michael Hanselmann
280 8a96c5a6 Michael Hanselmann
    if not self.get("instances"):
281 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Need at least one instance")
282 8a96c5a6 Michael Hanselmann
283 8a96c5a6 Michael Hanselmann
    if (self.get("disk") is None or
284 8a96c5a6 Michael Hanselmann
        self.get("disk-growth") is None or
285 8a96c5a6 Michael Hanselmann
        len(self.get("disk")) != len(self.get("disk-growth"))):
286 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Config options 'disk' and 'disk-growth' must exist"
287 8a96c5a6 Michael Hanselmann
                           " and have the same number of items")
288 8a96c5a6 Michael Hanselmann
289 8a96c5a6 Michael Hanselmann
    check = self.GetInstanceCheckScript()
290 8a96c5a6 Michael Hanselmann
    if check:
291 8a96c5a6 Michael Hanselmann
      try:
292 8a96c5a6 Michael Hanselmann
        os.stat(check)
293 8a96c5a6 Michael Hanselmann
      except EnvironmentError, err:
294 8a96c5a6 Michael Hanselmann
        raise qa_error.Error("Can't find instance check script '%s': %s" %
295 8a96c5a6 Michael Hanselmann
                             (check, err))
296 8a96c5a6 Michael Hanselmann
297 8a96c5a6 Michael Hanselmann
    enabled_hv = frozenset(self.GetEnabledHypervisors())
298 8a96c5a6 Michael Hanselmann
    if not enabled_hv:
299 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("No hypervisor is enabled")
300 8a96c5a6 Michael Hanselmann
301 8a96c5a6 Michael Hanselmann
    difference = enabled_hv - constants.HYPER_TYPES
302 8a96c5a6 Michael Hanselmann
    if difference:
303 8a96c5a6 Michael Hanselmann
      raise qa_error.Error("Unknown hypervisor(s) enabled: %s" %
304 8a96c5a6 Michael Hanselmann
                           utils.CommaJoin(difference))
305 8a96c5a6 Michael Hanselmann
306 76fda900 Michael Hanselmann
    (vc_master, vc_basedir) = self.GetVclusterSettings()
307 76fda900 Michael Hanselmann
    if bool(vc_master) != bool(vc_basedir):
308 76fda900 Michael Hanselmann
      raise qa_error.Error("All or none of the config options '%s' and '%s'"
309 76fda900 Michael Hanselmann
                           " must be set" %
310 76fda900 Michael Hanselmann
                           (_VCLUSTER_MASTER_KEY, _VCLUSTER_BASEDIR_KEY))
311 76fda900 Michael Hanselmann
312 76fda900 Michael Hanselmann
    if vc_basedir and not utils.IsNormAbsPath(vc_basedir):
313 76fda900 Michael Hanselmann
      raise qa_error.Error("Path given in option '%s' must be absolute and"
314 76fda900 Michael Hanselmann
                           " normalized" % _VCLUSTER_BASEDIR_KEY)
315 76fda900 Michael Hanselmann
316 8a96c5a6 Michael Hanselmann
  def __getitem__(self, name):
317 8a96c5a6 Michael Hanselmann
    """Returns configuration value.
318 8a96c5a6 Michael Hanselmann

319 8a96c5a6 Michael Hanselmann
    @type name: string
320 8a96c5a6 Michael Hanselmann
    @param name: Name of configuration entry
321 8a96c5a6 Michael Hanselmann

322 8a96c5a6 Michael Hanselmann
    """
323 8a96c5a6 Michael Hanselmann
    return self._data[name]
324 8a96c5a6 Michael Hanselmann
325 8a96c5a6 Michael Hanselmann
  def get(self, name, default=None):
326 8a96c5a6 Michael Hanselmann
    """Returns configuration value.
327 8a96c5a6 Michael Hanselmann

328 8a96c5a6 Michael Hanselmann
    @type name: string
329 8a96c5a6 Michael Hanselmann
    @param name: Name of configuration entry
330 8a96c5a6 Michael Hanselmann
    @param default: Default value
331 8a96c5a6 Michael Hanselmann

332 8a96c5a6 Michael Hanselmann
    """
333 8a96c5a6 Michael Hanselmann
    return self._data.get(name, default)
334 cec9845c Michael Hanselmann
335 8a96c5a6 Michael Hanselmann
  def GetMasterNode(self):
336 8a96c5a6 Michael Hanselmann
    """Returns the default master node for the cluster.
337 cec9845c Michael Hanselmann

338 8a96c5a6 Michael Hanselmann
    """
339 8a96c5a6 Michael Hanselmann
    return self["nodes"][0]
340 8a96c5a6 Michael Hanselmann
341 8a96c5a6 Michael Hanselmann
  def GetInstanceCheckScript(self):
342 8a96c5a6 Michael Hanselmann
    """Returns path to instance check script or C{None}.
343 8a96c5a6 Michael Hanselmann

344 8a96c5a6 Michael Hanselmann
    """
345 8a96c5a6 Michael Hanselmann
    return self._data.get(_INSTANCE_CHECK_KEY, None)
346 cec9845c Michael Hanselmann
347 8a96c5a6 Michael Hanselmann
  def GetEnabledHypervisors(self):
348 8a96c5a6 Michael Hanselmann
    """Returns list of enabled hypervisors.
349 cec9845c Michael Hanselmann

350 8a96c5a6 Michael Hanselmann
    @rtype: list
351 cec9845c Michael Hanselmann

352 8a96c5a6 Michael Hanselmann
    """
353 dacd8ba4 Helga Velroyen
    return self._GetStringListParameter(
354 dacd8ba4 Helga Velroyen
      _ENABLED_HV_KEY,
355 dacd8ba4 Helga Velroyen
      [constants.DEFAULT_ENABLED_HYPERVISOR])
356 dacd8ba4 Helga Velroyen
357 dacd8ba4 Helga Velroyen
  def GetDefaultHypervisor(self):
358 dacd8ba4 Helga Velroyen
    """Returns the default hypervisor to be used.
359 dacd8ba4 Helga Velroyen

360 dacd8ba4 Helga Velroyen
    """
361 dacd8ba4 Helga Velroyen
    return self.GetEnabledHypervisors()[0]
362 dacd8ba4 Helga Velroyen
363 2dae8d64 Helga Velroyen
  def GetEnabledDiskTemplates(self):
364 2dae8d64 Helga Velroyen
    """Returns the list of enabled disk templates.
365 dacd8ba4 Helga Velroyen

366 dacd8ba4 Helga Velroyen
    @rtype: list
367 dacd8ba4 Helga Velroyen

368 dacd8ba4 Helga Velroyen
    """
369 dacd8ba4 Helga Velroyen
    return self._GetStringListParameter(
370 2dae8d64 Helga Velroyen
      _ENABLED_DISK_TEMPLATES_KEY,
371 2dae8d64 Helga Velroyen
      list(constants.DEFAULT_ENABLED_DISK_TEMPLATES))
372 dacd8ba4 Helga Velroyen
373 2dae8d64 Helga Velroyen
  def GetDefaultDiskTemplate(self):
374 2dae8d64 Helga Velroyen
    """Returns the default disk template to be used.
375 dacd8ba4 Helga Velroyen

376 dacd8ba4 Helga Velroyen
    """
377 2dae8d64 Helga Velroyen
    return self.GetEnabledDiskTemplates()[0]
378 dacd8ba4 Helga Velroyen
379 dacd8ba4 Helga Velroyen
  def _GetStringListParameter(self, key, default_values):
380 dacd8ba4 Helga Velroyen
    """Retrieves a parameter's value that is supposed to be a list of strings.
381 dacd8ba4 Helga Velroyen

382 dacd8ba4 Helga Velroyen
    @rtype: list
383 dacd8ba4 Helga Velroyen

384 dacd8ba4 Helga Velroyen
    """
385 c9e05005 Michael Hanselmann
    try:
386 dacd8ba4 Helga Velroyen
      value = self._data[key]
387 8a96c5a6 Michael Hanselmann
    except KeyError:
388 dacd8ba4 Helga Velroyen
      return default_values
389 8a96c5a6 Michael Hanselmann
    else:
390 8a96c5a6 Michael Hanselmann
      if value is None:
391 8a96c5a6 Michael Hanselmann
        return []
392 8a96c5a6 Michael Hanselmann
      elif isinstance(value, basestring):
393 8a96c5a6 Michael Hanselmann
        return value.split(",")
394 8a96c5a6 Michael Hanselmann
      else:
395 8a96c5a6 Michael Hanselmann
        return value
396 8a96c5a6 Michael Hanselmann
397 a08e181f Michael Hanselmann
  def SetExclusiveStorage(self, value):
398 a08e181f Michael Hanselmann
    """Set the expected value of the C{exclusive_storage} flag for the cluster.
399 a08e181f Michael Hanselmann

400 a08e181f Michael Hanselmann
    """
401 a08e181f Michael Hanselmann
    self._exclusive_storage = bool(value)
402 a08e181f Michael Hanselmann
403 a08e181f Michael Hanselmann
  def GetExclusiveStorage(self):
404 a08e181f Michael Hanselmann
    """Get the expected value of the C{exclusive_storage} flag for the cluster.
405 a08e181f Michael Hanselmann

406 a08e181f Michael Hanselmann
    """
407 a08e181f Michael Hanselmann
    value = self._exclusive_storage
408 a08e181f Michael Hanselmann
    assert value is not None
409 a08e181f Michael Hanselmann
    return value
410 a08e181f Michael Hanselmann
411 a08e181f Michael Hanselmann
  def IsTemplateSupported(self, templ):
412 a08e181f Michael Hanselmann
    """Is the given disk template supported by the current configuration?
413 a08e181f Michael Hanselmann

414 a08e181f Michael Hanselmann
    """
415 02cff8aa Bernardo Dal Seno
    enabled = templ in self.GetEnabledDiskTemplates()
416 02cff8aa Bernardo Dal Seno
    return enabled and (not self.GetExclusiveStorage() or
417 02cff8aa Bernardo Dal Seno
                        templ in constants.DTS_EXCL_STORAGE)
418 a08e181f Michael Hanselmann
419 76fda900 Michael Hanselmann
  def GetVclusterSettings(self):
420 76fda900 Michael Hanselmann
    """Returns settings for virtual cluster.
421 76fda900 Michael Hanselmann

422 76fda900 Michael Hanselmann
    """
423 76fda900 Michael Hanselmann
    master = self.get(_VCLUSTER_MASTER_KEY)
424 76fda900 Michael Hanselmann
    basedir = self.get(_VCLUSTER_BASEDIR_KEY)
425 76fda900 Michael Hanselmann
426 76fda900 Michael Hanselmann
    return (master, basedir)
427 76fda900 Michael Hanselmann
428 8a96c5a6 Michael Hanselmann
429 8a96c5a6 Michael Hanselmann
def Load(path):
430 8a96c5a6 Michael Hanselmann
  """Loads the passed configuration file.
431 8a96c5a6 Michael Hanselmann

432 8a96c5a6 Michael Hanselmann
  """
433 8a96c5a6 Michael Hanselmann
  global _config # pylint: disable=W0603
434 8a96c5a6 Michael Hanselmann
435 8a96c5a6 Michael Hanselmann
  _config = _QaConfig.Load(path)
436 c9e05005 Michael Hanselmann
437 e7b6183b Michael Hanselmann
438 8a96c5a6 Michael Hanselmann
def GetConfig():
439 8a96c5a6 Michael Hanselmann
  """Returns the configuration object.
440 8a96c5a6 Michael Hanselmann

441 8a96c5a6 Michael Hanselmann
  """
442 8a96c5a6 Michael Hanselmann
  if _config is None:
443 8a96c5a6 Michael Hanselmann
    raise RuntimeError("Configuration not yet loaded")
444 8a96c5a6 Michael Hanselmann
445 8a96c5a6 Michael Hanselmann
  return _config
446 e7b6183b Michael Hanselmann
447 cec9845c Michael Hanselmann
448 cec9845c Michael Hanselmann
def get(name, default=None):
449 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.get}.
450 8a96c5a6 Michael Hanselmann

451 8a96c5a6 Michael Hanselmann
  """
452 8a96c5a6 Michael Hanselmann
  return GetConfig().get(name, default=default)
453 cec9845c Michael Hanselmann
454 cec9845c Michael Hanselmann
455 a0c3e726 Michael Hanselmann
class Either:
456 a0c3e726 Michael Hanselmann
  def __init__(self, tests):
457 a0c3e726 Michael Hanselmann
    """Initializes this class.
458 a0c3e726 Michael Hanselmann

459 a0c3e726 Michael Hanselmann
    @type tests: list or string
460 a0c3e726 Michael Hanselmann
    @param tests: List of test names
461 a0c3e726 Michael Hanselmann
    @see: L{TestEnabled} for details
462 a0c3e726 Michael Hanselmann

463 a0c3e726 Michael Hanselmann
    """
464 a0c3e726 Michael Hanselmann
    self.tests = tests
465 a0c3e726 Michael Hanselmann
466 a0c3e726 Michael Hanselmann
467 a0c3e726 Michael Hanselmann
def _MakeSequence(value):
468 a0c3e726 Michael Hanselmann
  """Make sequence of single argument.
469 a0c3e726 Michael Hanselmann

470 a0c3e726 Michael Hanselmann
  If the single argument is not already a list or tuple, a list with the
471 a0c3e726 Michael Hanselmann
  argument as a single item is returned.
472 a0c3e726 Michael Hanselmann

473 a0c3e726 Michael Hanselmann
  """
474 a0c3e726 Michael Hanselmann
  if isinstance(value, (list, tuple)):
475 a0c3e726 Michael Hanselmann
    return value
476 a0c3e726 Michael Hanselmann
  else:
477 a0c3e726 Michael Hanselmann
    return [value]
478 a0c3e726 Michael Hanselmann
479 a0c3e726 Michael Hanselmann
480 a0c3e726 Michael Hanselmann
def _TestEnabledInner(check_fn, names, fn):
481 a0c3e726 Michael Hanselmann
  """Evaluate test conditions.
482 a0c3e726 Michael Hanselmann

483 a0c3e726 Michael Hanselmann
  @type check_fn: callable
484 a0c3e726 Michael Hanselmann
  @param check_fn: Callback to check whether a test is enabled
485 a0c3e726 Michael Hanselmann
  @type names: sequence or string
486 a0c3e726 Michael Hanselmann
  @param names: Test name(s)
487 a0c3e726 Michael Hanselmann
  @type fn: callable
488 a0c3e726 Michael Hanselmann
  @param fn: Aggregation function
489 a0c3e726 Michael Hanselmann
  @rtype: bool
490 a0c3e726 Michael Hanselmann
  @return: Whether test is enabled
491 a0c3e726 Michael Hanselmann

492 a0c3e726 Michael Hanselmann
  """
493 a0c3e726 Michael Hanselmann
  names = _MakeSequence(names)
494 a0c3e726 Michael Hanselmann
495 a0c3e726 Michael Hanselmann
  result = []
496 a0c3e726 Michael Hanselmann
497 a0c3e726 Michael Hanselmann
  for name in names:
498 a0c3e726 Michael Hanselmann
    if isinstance(name, Either):
499 a0c3e726 Michael Hanselmann
      value = _TestEnabledInner(check_fn, name.tests, compat.any)
500 a0c3e726 Michael Hanselmann
    elif isinstance(name, (list, tuple)):
501 a0c3e726 Michael Hanselmann
      value = _TestEnabledInner(check_fn, name, compat.all)
502 c072e788 Michael Hanselmann
    elif callable(name):
503 c072e788 Michael Hanselmann
      value = name()
504 a0c3e726 Michael Hanselmann
    else:
505 a0c3e726 Michael Hanselmann
      value = check_fn(name)
506 a0c3e726 Michael Hanselmann
507 a0c3e726 Michael Hanselmann
    result.append(value)
508 a0c3e726 Michael Hanselmann
509 a0c3e726 Michael Hanselmann
  return fn(result)
510 a0c3e726 Michael Hanselmann
511 a0c3e726 Michael Hanselmann
512 a0c3e726 Michael Hanselmann
def TestEnabled(tests, _cfg=None):
513 7d88f255 Iustin Pop
  """Returns True if the given tests are enabled.
514 7d88f255 Iustin Pop

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

518 1010ec70 Michael Hanselmann
  """
519 a0c3e726 Michael Hanselmann
  if _cfg is None:
520 8a96c5a6 Michael Hanselmann
    cfg = GetConfig()
521 8a96c5a6 Michael Hanselmann
  else:
522 8a96c5a6 Michael Hanselmann
    cfg = _cfg
523 59a8fe48 Michael Hanselmann
524 59a8fe48 Michael Hanselmann
  # Get settings for all tests
525 8a96c5a6 Michael Hanselmann
  cfg_tests = cfg.get("tests", {})
526 59a8fe48 Michael Hanselmann
527 59a8fe48 Michael Hanselmann
  # Get default setting
528 a0c3e726 Michael Hanselmann
  default = cfg_tests.get("default", True)
529 59a8fe48 Michael Hanselmann
530 a0c3e726 Michael Hanselmann
  return _TestEnabledInner(lambda name: cfg_tests.get(name, default),
531 a0c3e726 Michael Hanselmann
                           tests, compat.all)
532 cec9845c Michael Hanselmann
533 cec9845c Michael Hanselmann
534 8a96c5a6 Michael Hanselmann
def GetInstanceCheckScript(*args):
535 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetInstanceCheckScript}.
536 c9e05005 Michael Hanselmann

537 c9e05005 Michael Hanselmann
  """
538 8a96c5a6 Michael Hanselmann
  return GetConfig().GetInstanceCheckScript(*args)
539 c9e05005 Michael Hanselmann
540 e7b6183b Michael Hanselmann
541 8a96c5a6 Michael Hanselmann
def GetEnabledHypervisors(*args):
542 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetEnabledHypervisors}.
543 e7b6183b Michael Hanselmann

544 e7b6183b Michael Hanselmann
  """
545 8a96c5a6 Michael Hanselmann
  return GetConfig().GetEnabledHypervisors(*args)
546 e7b6183b Michael Hanselmann
547 e7b6183b Michael Hanselmann
548 8a96c5a6 Michael Hanselmann
def GetDefaultHypervisor(*args):
549 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetDefaultHypervisor}.
550 e7b6183b Michael Hanselmann

551 e7b6183b Michael Hanselmann
  """
552 8a96c5a6 Michael Hanselmann
  return GetConfig().GetDefaultHypervisor(*args)
553 dacd8ba4 Helga Velroyen
554 dacd8ba4 Helga Velroyen
555 2dae8d64 Helga Velroyen
def GetEnabledDiskTemplates(*args):
556 2dae8d64 Helga Velroyen
  """Wrapper for L{_QaConfig.GetEnabledDiskTemplates}.
557 dacd8ba4 Helga Velroyen

558 dacd8ba4 Helga Velroyen
  """
559 2dae8d64 Helga Velroyen
  return GetConfig().GetEnabledDiskTemplates(*args)
560 dacd8ba4 Helga Velroyen
561 dacd8ba4 Helga Velroyen
562 2dae8d64 Helga Velroyen
def GetDefaultDiskTemplate(*args):
563 2dae8d64 Helga Velroyen
  """Wrapper for L{_QaConfig.GetDefaultDiskTemplate}.
564 dacd8ba4 Helga Velroyen

565 dacd8ba4 Helga Velroyen
  """
566 2dae8d64 Helga Velroyen
  return GetConfig().GetDefaultDiskTemplate(*args)
567 e7b6183b Michael Hanselmann
568 e7b6183b Michael Hanselmann
569 cec9845c Michael Hanselmann
def GetMasterNode():
570 8a96c5a6 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetMasterNode}.
571 8a96c5a6 Michael Hanselmann

572 8a96c5a6 Michael Hanselmann
  """
573 8a96c5a6 Michael Hanselmann
  return GetConfig().GetMasterNode()
574 cec9845c Michael Hanselmann
575 cec9845c Michael Hanselmann
576 6a654276 Michael Hanselmann
def AcquireInstance(_cfg=None):
577 cec9845c Michael Hanselmann
  """Returns an instance which isn't in use.
578 cec9845c Michael Hanselmann

579 cec9845c Michael Hanselmann
  """
580 6a654276 Michael Hanselmann
  if _cfg is None:
581 6a654276 Michael Hanselmann
    cfg = GetConfig()
582 6a654276 Michael Hanselmann
  else:
583 6a654276 Michael Hanselmann
    cfg = _cfg
584 6a654276 Michael Hanselmann
585 cec9845c Michael Hanselmann
  # Filter out unwanted instances
586 6a654276 Michael Hanselmann
  instances = filter(lambda inst: not inst.used, cfg["instances"])
587 cec9845c Michael Hanselmann
588 6a654276 Michael Hanselmann
  if not instances:
589 cec9845c Michael Hanselmann
    raise qa_error.OutOfInstancesError("No instances left")
590 cec9845c Michael Hanselmann
591 2176724e Michael Hanselmann
  instance = instances[0]
592 2176724e Michael Hanselmann
  instance.Use()
593 6a654276 Michael Hanselmann
594 2176724e Michael Hanselmann
  return instance
595 cec9845c Michael Hanselmann
596 cec9845c Michael Hanselmann
597 6a0f22e1 Bernardo Dal Seno
def SetExclusiveStorage(value):
598 a08e181f Michael Hanselmann
  """Wrapper for L{_QaConfig.SetExclusiveStorage}.
599 6a0f22e1 Bernardo Dal Seno

600 6a0f22e1 Bernardo Dal Seno
  """
601 a08e181f Michael Hanselmann
  return GetConfig().SetExclusiveStorage(value)
602 6a0f22e1 Bernardo Dal Seno
603 6a0f22e1 Bernardo Dal Seno
604 6a0f22e1 Bernardo Dal Seno
def GetExclusiveStorage():
605 a08e181f Michael Hanselmann
  """Wrapper for L{_QaConfig.GetExclusiveStorage}.
606 6a0f22e1 Bernardo Dal Seno

607 6a0f22e1 Bernardo Dal Seno
  """
608 a08e181f Michael Hanselmann
  return GetConfig().GetExclusiveStorage()
609 6a0f22e1 Bernardo Dal Seno
610 6a0f22e1 Bernardo Dal Seno
611 27eba428 Bernardo Dal Seno
def IsTemplateSupported(templ):
612 02cff8aa Bernardo Dal Seno
  """Wrapper for L{_QaConfig.IsTemplateSupported}.
613 27eba428 Bernardo Dal Seno

614 27eba428 Bernardo Dal Seno
  """
615 a08e181f Michael Hanselmann
  return GetConfig().IsTemplateSupported(templ)
616 27eba428 Bernardo Dal Seno
617 27eba428 Bernardo Dal Seno
618 41be279f Michael Hanselmann
def _NodeSortKey(node):
619 41be279f Michael Hanselmann
  """Returns sort key for a node.
620 41be279f Michael Hanselmann

621 41be279f Michael Hanselmann
  @type node: L{_QaNode}
622 41be279f Michael Hanselmann

623 41be279f Michael Hanselmann
  """
624 41be279f Michael Hanselmann
  return (node.use_count, utils.NiceSortKey(node.primary))
625 41be279f Michael Hanselmann
626 41be279f Michael Hanselmann
627 dbdb0594 Michael Hanselmann
def AcquireNode(exclude=None, _cfg=None):
628 cec9845c Michael Hanselmann
  """Returns the least used node.
629 cec9845c Michael Hanselmann

630 cec9845c Michael Hanselmann
  """
631 dbdb0594 Michael Hanselmann
  if _cfg is None:
632 dbdb0594 Michael Hanselmann
    cfg = GetConfig()
633 dbdb0594 Michael Hanselmann
  else:
634 dbdb0594 Michael Hanselmann
    cfg = _cfg
635 dbdb0594 Michael Hanselmann
636 dbdb0594 Michael Hanselmann
  master = cfg.GetMasterNode()
637 cec9845c Michael Hanselmann
638 cec9845c Michael Hanselmann
  # Filter out unwanted nodes
639 cec9845c Michael Hanselmann
  # TODO: Maybe combine filters
640 cec9845c Michael Hanselmann
  if exclude is None:
641 d0c8c01d Iustin Pop
    nodes = cfg["nodes"][:]
642 4b62db14 Michael Hanselmann
  elif isinstance(exclude, (list, tuple)):
643 d0c8c01d Iustin Pop
    nodes = filter(lambda node: node not in exclude, cfg["nodes"])
644 cec9845c Michael Hanselmann
  else:
645 d0c8c01d Iustin Pop
    nodes = filter(lambda node: node != exclude, cfg["nodes"])
646 cec9845c Michael Hanselmann
647 dbdb0594 Michael Hanselmann
  nodes = filter(lambda node: node.added or node == master, nodes)
648 cec9845c Michael Hanselmann
649 dbdb0594 Michael Hanselmann
  if not nodes:
650 cec9845c Michael Hanselmann
    raise qa_error.OutOfNodesError("No nodes left")
651 cec9845c Michael Hanselmann
652 41be279f Michael Hanselmann
  # Return node with least number of uses
653 41be279f Michael Hanselmann
  return sorted(nodes, key=_NodeSortKey)[0].Use()
654 cec9845c Michael Hanselmann
655 cec9845c Michael Hanselmann
656 7d4f1b45 Bernardo Dal Seno
def AcquireManyNodes(num, exclude=None):
657 7d4f1b45 Bernardo Dal Seno
  """Return the least used nodes.
658 7d4f1b45 Bernardo Dal Seno

659 7d4f1b45 Bernardo Dal Seno
  @type num: int
660 7d4f1b45 Bernardo Dal Seno
  @param num: Number of nodes; can be 0.
661 7d4f1b45 Bernardo Dal Seno
  @type exclude: list of nodes or C{None}
662 7d4f1b45 Bernardo Dal Seno
  @param exclude: nodes to be excluded from the choice
663 7d4f1b45 Bernardo Dal Seno
  @rtype: list of nodes
664 7d4f1b45 Bernardo Dal Seno
  @return: C{num} different nodes
665 7d4f1b45 Bernardo Dal Seno

666 7d4f1b45 Bernardo Dal Seno
  """
667 7d4f1b45 Bernardo Dal Seno
  nodes = []
668 7d4f1b45 Bernardo Dal Seno
  if exclude is None:
669 7d4f1b45 Bernardo Dal Seno
    exclude = []
670 7d4f1b45 Bernardo Dal Seno
  elif isinstance(exclude, (list, tuple)):
671 7d4f1b45 Bernardo Dal Seno
    # Don't modify the incoming argument
672 7d4f1b45 Bernardo Dal Seno
    exclude = list(exclude)
673 7d4f1b45 Bernardo Dal Seno
  else:
674 7d4f1b45 Bernardo Dal Seno
    exclude = [exclude]
675 7d4f1b45 Bernardo Dal Seno
676 7d4f1b45 Bernardo Dal Seno
  try:
677 7d4f1b45 Bernardo Dal Seno
    for _ in range(0, num):
678 7d4f1b45 Bernardo Dal Seno
      n = AcquireNode(exclude=exclude)
679 7d4f1b45 Bernardo Dal Seno
      nodes.append(n)
680 7d4f1b45 Bernardo Dal Seno
      exclude.append(n)
681 7d4f1b45 Bernardo Dal Seno
  except qa_error.OutOfNodesError:
682 7d4f1b45 Bernardo Dal Seno
    ReleaseManyNodes(nodes)
683 7d4f1b45 Bernardo Dal Seno
    raise
684 7d4f1b45 Bernardo Dal Seno
  return nodes
685 7d4f1b45 Bernardo Dal Seno
686 7d4f1b45 Bernardo Dal Seno
687 7d4f1b45 Bernardo Dal Seno
def ReleaseManyNodes(nodes):
688 565cb4bf Michael Hanselmann
  for node in nodes:
689 565cb4bf Michael Hanselmann
    node.Release()
690 76fda900 Michael Hanselmann
691 76fda900 Michael Hanselmann
692 76fda900 Michael Hanselmann
def GetVclusterSettings():
693 76fda900 Michael Hanselmann
  """Wrapper for L{_QaConfig.GetVclusterSettings}.
694 76fda900 Michael Hanselmann

695 76fda900 Michael Hanselmann
  """
696 76fda900 Michael Hanselmann
  return GetConfig().GetVclusterSettings()
697 76fda900 Michael Hanselmann
698 76fda900 Michael Hanselmann
699 76fda900 Michael Hanselmann
def UseVirtualCluster(_cfg=None):
700 76fda900 Michael Hanselmann
  """Returns whether a virtual cluster is used.
701 76fda900 Michael Hanselmann

702 76fda900 Michael Hanselmann
  @rtype: bool
703 76fda900 Michael Hanselmann

704 76fda900 Michael Hanselmann
  """
705 76fda900 Michael Hanselmann
  if _cfg is None:
706 76fda900 Michael Hanselmann
    cfg = GetConfig()
707 76fda900 Michael Hanselmann
  else:
708 76fda900 Michael Hanselmann
    cfg = _cfg
709 76fda900 Michael Hanselmann
710 76fda900 Michael Hanselmann
  (master, _) = cfg.GetVclusterSettings()
711 76fda900 Michael Hanselmann
712 76fda900 Michael Hanselmann
  return bool(master)
713 76fda900 Michael Hanselmann
714 76fda900 Michael Hanselmann
715 76fda900 Michael Hanselmann
@ht.WithDesc("No virtual cluster")
716 76fda900 Michael Hanselmann
def NoVirtualCluster():
717 76fda900 Michael Hanselmann
  """Used to disable tests for virtual clusters.
718 76fda900 Michael Hanselmann

719 76fda900 Michael Hanselmann
  """
720 76fda900 Michael Hanselmann
  return not UseVirtualCluster()