qa_config.py 3.14 KB
Newer Older
1
2
3
#
#

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


"""QA configuration.

"""


27
28
from ganeti import utils
from ganeti import serializer
Iustin Pop's avatar
Iustin Pop committed
29
from ganeti import compat
30
31
32
33
34
35
36
37
38
39
40
41

import qa_error


cfg = None
options = None


def Load(path):
  """Loads the passed configuration file.

  """
Iustin Pop's avatar
Iustin Pop committed
42
  global cfg # pylint: disable-msg=W0603
43

44
  cfg = serializer.LoadJson(utils.ReadFile(path))
45
46
47
48
49

  Validate()


def Validate():
Iustin Pop's avatar
Iustin Pop committed
50
  if len(cfg["nodes"]) < 1:
51
    raise qa_error.Error("Need at least one node")
Iustin Pop's avatar
Iustin Pop committed
52
  if len(cfg["instances"]) < 1:
53
    raise qa_error.Error("Need at least one instance")
54
55
56
  if len(cfg["disk"]) != len(cfg["disk-growth"]):
    raise qa_error.Error("Config options 'disk' and 'disk-growth' must have"
                         " the same number of items")
57
58
59
60
61
62


def get(name, default=None):
  return cfg.get(name, default)


Iustin Pop's avatar
Iustin Pop committed
63
64
65
66
def TestEnabled(tests):
  """Returns True if the given tests are enabled.

  @param tests: a single test, or a list of tests to check
67
68

  """
Iustin Pop's avatar
Iustin Pop committed
69
70
71
  if isinstance(tests, basestring):
    tests = [tests]
  return compat.all(cfg.get("tests", {}).get(t, True) for t in tests)
72
73
74


def GetMasterNode():
Iustin Pop's avatar
Iustin Pop committed
75
  return cfg["nodes"][0]
76
77
78
79
80
81
82


def AcquireInstance():
  """Returns an instance which isn't in use.

  """
  # Filter out unwanted instances
Iustin Pop's avatar
Iustin Pop committed
83
84
  tmp_flt = lambda inst: not inst.get("_used", False)
  instances = filter(tmp_flt, cfg["instances"])
85
86
87
88
89
90
  del tmp_flt

  if len(instances) == 0:
    raise qa_error.OutOfInstancesError("No instances left")

  inst = instances[0]
Iustin Pop's avatar
Iustin Pop committed
91
  inst["_used"] = True
92
93
94
95
  return inst


def ReleaseInstance(inst):
Iustin Pop's avatar
Iustin Pop committed
96
  inst["_used"] = False
97
98
99
100
101
102
103
104
105
106
107


def AcquireNode(exclude=None):
  """Returns the least used node.

  """
  master = GetMasterNode()

  # Filter out unwanted nodes
  # TODO: Maybe combine filters
  if exclude is None:
Iustin Pop's avatar
Iustin Pop committed
108
    nodes = cfg["nodes"][:]
109
  elif isinstance(exclude, (list, tuple)):
Iustin Pop's avatar
Iustin Pop committed
110
    nodes = filter(lambda node: node not in exclude, cfg["nodes"])
111
  else:
Iustin Pop's avatar
Iustin Pop committed
112
    nodes = filter(lambda node: node != exclude, cfg["nodes"])
113

Iustin Pop's avatar
Iustin Pop committed
114
  tmp_flt = lambda node: node.get("_added", False) or node == master
115
116
117
118
119
120
121
122
  nodes = filter(tmp_flt, nodes)
  del tmp_flt

  if len(nodes) == 0:
    raise qa_error.OutOfNodesError("No nodes left")

  # Get node with least number of uses
  def compare(a, b):
Iustin Pop's avatar
Iustin Pop committed
123
    result = cmp(a.get("_count", 0), b.get("_count", 0))
124
    if result == 0:
Iustin Pop's avatar
Iustin Pop committed
125
      result = cmp(a["primary"], b["primary"])
126
127
128
129
130
    return result

  nodes.sort(cmp=compare)

  node = nodes[0]
Iustin Pop's avatar
Iustin Pop committed
131
  node["_count"] = node.get("_count", 0) + 1
132
133
134
135
  return node


def ReleaseNode(node):
Iustin Pop's avatar
Iustin Pop committed
136
  node["_count"] = node.get("_count", 0) - 1