Statistics
| Branch: | Tag: | Revision:

root / qa / qa_config.py @ 2dae8d64

History | View | Annotate | Download (15.7 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 cf62af3a Michael Hanselmann
    return (not self.GetExclusiveStorage() or
416 cf62af3a Michael Hanselmann
            templ in constants.DTS_EXCL_STORAGE)
417 a08e181f Michael Hanselmann
418 76fda900 Michael Hanselmann
  def GetVclusterSettings(self):
419 76fda900 Michael Hanselmann
    """Returns settings for virtual cluster.
420 76fda900 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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