Statistics
| Branch: | Tag: | Revision:

root / qa / qa_config.py @ c68d1f43

History | View | Annotate | Download (3 kB)

1
#
2
#
3

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

    
21

    
22
"""QA configuration.
23

24
"""
25

    
26

    
27
import yaml
28

    
29
import qa_error
30

    
31

    
32
cfg = None
33
options = None
34

    
35

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

39
  """
40
  global cfg
41

    
42
  f = open(path, 'r')
43
  try:
44
    cfg = yaml.load(f.read())
45
  finally:
46
    f.close()
47

    
48
  Validate()
49

    
50

    
51
def Validate():
52
  if len(cfg['nodes']) < 1:
53
    raise qa_error.Error("Need at least one node")
54
  if len(cfg['instances']) < 1:
55
    raise qa_error.Error("Need at least one instance")
56

    
57
  if (TestEnabled('instance-add-remote-raid-disk') and
58
      TestEnabled('instance-add-drbd-disk')):
59
    raise qa_error.Error('Tests for disk templates remote_raid1 and drbd'
60
                         ' cannot be enabled at the same time.')
61

    
62

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

    
66

    
67
def TestEnabled(test):
68
  """Returns True if the given test is enabled."""
69
  return cfg.get('tests', {}).get(test, False)
70

    
71

    
72
def GetMasterNode():
73
  return cfg['nodes'][0]
74

    
75

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

79
  """
80
  # Filter out unwanted instances
81
  tmp_flt = lambda inst: not inst.get('_used', False)
82
  instances = filter(tmp_flt, cfg['instances'])
83
  del tmp_flt
84

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

    
88
  inst = instances[0]
89
  inst['_used'] = True
90
  return inst
91

    
92

    
93
def ReleaseInstance(inst):
94
  inst['_used'] = False
95

    
96

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

100
  """
101
  master = GetMasterNode()
102

    
103
  # Filter out unwanted nodes
104
  # TODO: Maybe combine filters
105
  if exclude is None:
106
    nodes = cfg['nodes'][:]
107
  elif isinstance(exclude, (list, tuple)):
108
    nodes = filter(lambda node: node not in exclude, cfg['nodes'])
109
  else:
110
    nodes = filter(lambda node: node != exclude, cfg['nodes'])
111

    
112
  tmp_flt = lambda node: node.get('_added', False) or node == master
113
  nodes = filter(tmp_flt, nodes)
114
  del tmp_flt
115

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

    
119
  # Get node with least number of uses
120
  def compare(a, b):
121
    result = cmp(a.get('_count', 0), b.get('_count', 0))
122
    if result == 0:
123
      result = cmp(a['primary'], b['primary'])
124
    return result
125

    
126
  nodes.sort(cmp=compare)
127

    
128
  node = nodes[0]
129
  node['_count'] = node.get('_count', 0) + 1
130
  return node
131

    
132

    
133
def ReleaseNode(node):
134
  node['_count'] = node.get('_count', 0) - 1