Statistics
| Branch: | Tag: | Revision:

root / qa / qa_config.py @ 2ff95e62

History | View | Annotate | Download (3 kB)

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

    
18

    
19
"""QA configuration.
20

21
"""
22

    
23

    
24
import yaml
25

    
26
import qa_error
27

    
28

    
29
cfg = None
30
options = None
31

    
32

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

36
  """
37
  global cfg
38

    
39
  f = open(path, 'r')
40
  try:
41
    cfg = yaml.load(f.read())
42
  finally:
43
    f.close()
44

    
45
  Validate()
46

    
47

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

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

    
59

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

    
63

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

    
68

    
69
def GetMasterNode():
70
  return cfg['nodes'][0]
71

    
72

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

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

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

    
85
  inst = instances[0]
86
  inst['_used'] = True
87
  return inst
88

    
89

    
90
def ReleaseInstance(inst):
91
  inst['_used'] = False
92

    
93

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

97
  """
98
  master = GetMasterNode()
99

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

    
109
  tmp_flt = lambda node: node.get('_added', False) or node == master
110
  nodes = filter(tmp_flt, nodes)
111
  del tmp_flt
112

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

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

    
123
  nodes.sort(cmp=compare)
124

    
125
  node = nodes[0]
126
  node['_count'] = node.get('_count', 0) + 1
127
  return node
128

    
129

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