Statistics
| Branch: | Tag: | Revision:

root / qa / qa_config.py @ f14a8b15

History | View | Annotate | Download (4.9 kB)

1 c68d1f43 Michael Hanselmann
#
2 c68d1f43 Michael Hanselmann
#
3 c68d1f43 Michael Hanselmann
4 3582eef6 Iustin Pop
# Copyright (C) 2007, 2011 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 a705dc05 Michael Hanselmann
from ganeti import utils
29 a705dc05 Michael Hanselmann
from ganeti import serializer
30 7d88f255 Iustin Pop
from ganeti import compat
31 cec9845c Michael Hanselmann
32 cec9845c Michael Hanselmann
import qa_error
33 cec9845c Michael Hanselmann
34 cec9845c Michael Hanselmann
35 c9e05005 Michael Hanselmann
_INSTANCE_CHECK_KEY = "instance-check"
36 c9e05005 Michael Hanselmann
37 c9e05005 Michael Hanselmann
38 cec9845c Michael Hanselmann
cfg = None
39 cec9845c Michael Hanselmann
options = None
40 cec9845c Michael Hanselmann
41 cec9845c Michael Hanselmann
42 cec9845c Michael Hanselmann
def Load(path):
43 cec9845c Michael Hanselmann
  """Loads the passed configuration file.
44 cec9845c Michael Hanselmann

45 cec9845c Michael Hanselmann
  """
46 b459a848 Andrea Spadaccini
  global cfg # pylint: disable=W0603
47 cec9845c Michael Hanselmann
48 a705dc05 Michael Hanselmann
  cfg = serializer.LoadJson(utils.ReadFile(path))
49 cec9845c Michael Hanselmann
50 cec9845c Michael Hanselmann
  Validate()
51 cec9845c Michael Hanselmann
52 cec9845c Michael Hanselmann
53 cec9845c Michael Hanselmann
def Validate():
54 d0c8c01d Iustin Pop
  if len(cfg["nodes"]) < 1:
55 cec9845c Michael Hanselmann
    raise qa_error.Error("Need at least one node")
56 d0c8c01d Iustin Pop
  if len(cfg["instances"]) < 1:
57 cec9845c Michael Hanselmann
    raise qa_error.Error("Need at least one instance")
58 1d693311 Michael Hanselmann
  if len(cfg["disk"]) != len(cfg["disk-growth"]):
59 1d693311 Michael Hanselmann
    raise qa_error.Error("Config options 'disk' and 'disk-growth' must have"
60 1d693311 Michael Hanselmann
                         " the same number of items")
61 cec9845c Michael Hanselmann
62 c9e05005 Michael Hanselmann
  check = GetInstanceCheckScript()
63 c9e05005 Michael Hanselmann
  if check:
64 c9e05005 Michael Hanselmann
    try:
65 c9e05005 Michael Hanselmann
      os.stat(check)
66 c9e05005 Michael Hanselmann
    except EnvironmentError, err:
67 c9e05005 Michael Hanselmann
      raise qa_error.Error("Can't find instance check script '%s': %s" %
68 c9e05005 Michael Hanselmann
                           (check, err))
69 c9e05005 Michael Hanselmann
70 cec9845c Michael Hanselmann
71 cec9845c Michael Hanselmann
def get(name, default=None):
72 cec9845c Michael Hanselmann
  return cfg.get(name, default)
73 cec9845c Michael Hanselmann
74 cec9845c Michael Hanselmann
75 a0c3e726 Michael Hanselmann
class Either:
76 a0c3e726 Michael Hanselmann
  def __init__(self, tests):
77 a0c3e726 Michael Hanselmann
    """Initializes this class.
78 a0c3e726 Michael Hanselmann

79 a0c3e726 Michael Hanselmann
    @type tests: list or string
80 a0c3e726 Michael Hanselmann
    @param tests: List of test names
81 a0c3e726 Michael Hanselmann
    @see: L{TestEnabled} for details
82 a0c3e726 Michael Hanselmann

83 a0c3e726 Michael Hanselmann
    """
84 a0c3e726 Michael Hanselmann
    self.tests = tests
85 a0c3e726 Michael Hanselmann
86 a0c3e726 Michael Hanselmann
87 a0c3e726 Michael Hanselmann
def _MakeSequence(value):
88 a0c3e726 Michael Hanselmann
  """Make sequence of single argument.
89 a0c3e726 Michael Hanselmann

90 a0c3e726 Michael Hanselmann
  If the single argument is not already a list or tuple, a list with the
91 a0c3e726 Michael Hanselmann
  argument as a single item is returned.
92 a0c3e726 Michael Hanselmann

93 a0c3e726 Michael Hanselmann
  """
94 a0c3e726 Michael Hanselmann
  if isinstance(value, (list, tuple)):
95 a0c3e726 Michael Hanselmann
    return value
96 a0c3e726 Michael Hanselmann
  else:
97 a0c3e726 Michael Hanselmann
    return [value]
98 a0c3e726 Michael Hanselmann
99 a0c3e726 Michael Hanselmann
100 a0c3e726 Michael Hanselmann
def _TestEnabledInner(check_fn, names, fn):
101 a0c3e726 Michael Hanselmann
  """Evaluate test conditions.
102 a0c3e726 Michael Hanselmann

103 a0c3e726 Michael Hanselmann
  @type check_fn: callable
104 a0c3e726 Michael Hanselmann
  @param check_fn: Callback to check whether a test is enabled
105 a0c3e726 Michael Hanselmann
  @type names: sequence or string
106 a0c3e726 Michael Hanselmann
  @param names: Test name(s)
107 a0c3e726 Michael Hanselmann
  @type fn: callable
108 a0c3e726 Michael Hanselmann
  @param fn: Aggregation function
109 a0c3e726 Michael Hanselmann
  @rtype: bool
110 a0c3e726 Michael Hanselmann
  @return: Whether test is enabled
111 a0c3e726 Michael Hanselmann

112 a0c3e726 Michael Hanselmann
  """
113 a0c3e726 Michael Hanselmann
  names = _MakeSequence(names)
114 a0c3e726 Michael Hanselmann
115 a0c3e726 Michael Hanselmann
  result = []
116 a0c3e726 Michael Hanselmann
117 a0c3e726 Michael Hanselmann
  for name in names:
118 a0c3e726 Michael Hanselmann
    if isinstance(name, Either):
119 a0c3e726 Michael Hanselmann
      value = _TestEnabledInner(check_fn, name.tests, compat.any)
120 a0c3e726 Michael Hanselmann
    elif isinstance(name, (list, tuple)):
121 a0c3e726 Michael Hanselmann
      value = _TestEnabledInner(check_fn, name, compat.all)
122 a0c3e726 Michael Hanselmann
    else:
123 a0c3e726 Michael Hanselmann
      value = check_fn(name)
124 a0c3e726 Michael Hanselmann
125 a0c3e726 Michael Hanselmann
    result.append(value)
126 a0c3e726 Michael Hanselmann
127 a0c3e726 Michael Hanselmann
  return fn(result)
128 a0c3e726 Michael Hanselmann
129 a0c3e726 Michael Hanselmann
130 a0c3e726 Michael Hanselmann
def TestEnabled(tests, _cfg=None):
131 7d88f255 Iustin Pop
  """Returns True if the given tests are enabled.
132 7d88f255 Iustin Pop

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

136 1010ec70 Michael Hanselmann
  """
137 a0c3e726 Michael Hanselmann
  if _cfg is None:
138 a0c3e726 Michael Hanselmann
    _cfg = cfg
139 59a8fe48 Michael Hanselmann
140 59a8fe48 Michael Hanselmann
  # Get settings for all tests
141 a0c3e726 Michael Hanselmann
  cfg_tests = _cfg.get("tests", {})
142 59a8fe48 Michael Hanselmann
143 59a8fe48 Michael Hanselmann
  # Get default setting
144 a0c3e726 Michael Hanselmann
  default = cfg_tests.get("default", True)
145 59a8fe48 Michael Hanselmann
146 a0c3e726 Michael Hanselmann
  return _TestEnabledInner(lambda name: cfg_tests.get(name, default),
147 a0c3e726 Michael Hanselmann
                           tests, compat.all)
148 cec9845c Michael Hanselmann
149 cec9845c Michael Hanselmann
150 c9e05005 Michael Hanselmann
def GetInstanceCheckScript():
151 c9e05005 Michael Hanselmann
  """Returns path to instance check script or C{None}.
152 c9e05005 Michael Hanselmann

153 c9e05005 Michael Hanselmann
  """
154 c9e05005 Michael Hanselmann
  return cfg.get(_INSTANCE_CHECK_KEY, None)
155 c9e05005 Michael Hanselmann
156 c9e05005 Michael Hanselmann
157 cec9845c Michael Hanselmann
def GetMasterNode():
158 d0c8c01d Iustin Pop
  return cfg["nodes"][0]
159 cec9845c Michael Hanselmann
160 cec9845c Michael Hanselmann
161 cec9845c Michael Hanselmann
def AcquireInstance():
162 cec9845c Michael Hanselmann
  """Returns an instance which isn't in use.
163 cec9845c Michael Hanselmann

164 cec9845c Michael Hanselmann
  """
165 cec9845c Michael Hanselmann
  # Filter out unwanted instances
166 d0c8c01d Iustin Pop
  tmp_flt = lambda inst: not inst.get("_used", False)
167 d0c8c01d Iustin Pop
  instances = filter(tmp_flt, cfg["instances"])
168 cec9845c Michael Hanselmann
  del tmp_flt
169 cec9845c Michael Hanselmann
170 cec9845c Michael Hanselmann
  if len(instances) == 0:
171 cec9845c Michael Hanselmann
    raise qa_error.OutOfInstancesError("No instances left")
172 cec9845c Michael Hanselmann
173 cec9845c Michael Hanselmann
  inst = instances[0]
174 d0c8c01d Iustin Pop
  inst["_used"] = True
175 cec9845c Michael Hanselmann
  return inst
176 cec9845c Michael Hanselmann
177 cec9845c Michael Hanselmann
178 cec9845c Michael Hanselmann
def ReleaseInstance(inst):
179 d0c8c01d Iustin Pop
  inst["_used"] = False
180 cec9845c Michael Hanselmann
181 cec9845c Michael Hanselmann
182 cec9845c Michael Hanselmann
def AcquireNode(exclude=None):
183 cec9845c Michael Hanselmann
  """Returns the least used node.
184 cec9845c Michael Hanselmann

185 cec9845c Michael Hanselmann
  """
186 cec9845c Michael Hanselmann
  master = GetMasterNode()
187 cec9845c Michael Hanselmann
188 cec9845c Michael Hanselmann
  # Filter out unwanted nodes
189 cec9845c Michael Hanselmann
  # TODO: Maybe combine filters
190 cec9845c Michael Hanselmann
  if exclude is None:
191 d0c8c01d Iustin Pop
    nodes = cfg["nodes"][:]
192 4b62db14 Michael Hanselmann
  elif isinstance(exclude, (list, tuple)):
193 d0c8c01d Iustin Pop
    nodes = filter(lambda node: node not in exclude, cfg["nodes"])
194 cec9845c Michael Hanselmann
  else:
195 d0c8c01d Iustin Pop
    nodes = filter(lambda node: node != exclude, cfg["nodes"])
196 cec9845c Michael Hanselmann
197 d0c8c01d Iustin Pop
  tmp_flt = lambda node: node.get("_added", False) or node == master
198 cec9845c Michael Hanselmann
  nodes = filter(tmp_flt, nodes)
199 cec9845c Michael Hanselmann
  del tmp_flt
200 cec9845c Michael Hanselmann
201 cec9845c Michael Hanselmann
  if len(nodes) == 0:
202 cec9845c Michael Hanselmann
    raise qa_error.OutOfNodesError("No nodes left")
203 cec9845c Michael Hanselmann
204 cec9845c Michael Hanselmann
  # Get node with least number of uses
205 cec9845c Michael Hanselmann
  def compare(a, b):
206 d0c8c01d Iustin Pop
    result = cmp(a.get("_count", 0), b.get("_count", 0))
207 cec9845c Michael Hanselmann
    if result == 0:
208 d0c8c01d Iustin Pop
      result = cmp(a["primary"], b["primary"])
209 cec9845c Michael Hanselmann
    return result
210 cec9845c Michael Hanselmann
211 cec9845c Michael Hanselmann
  nodes.sort(cmp=compare)
212 cec9845c Michael Hanselmann
213 cec9845c Michael Hanselmann
  node = nodes[0]
214 d0c8c01d Iustin Pop
  node["_count"] = node.get("_count", 0) + 1
215 cec9845c Michael Hanselmann
  return node
216 cec9845c Michael Hanselmann
217 cec9845c Michael Hanselmann
218 cec9845c Michael Hanselmann
def ReleaseNode(node):
219 d0c8c01d Iustin Pop
  node["_count"] = node.get("_count", 0) - 1