Statistics
| Branch: | Tag: | Revision:

root / testing / ganeti.qa.py @ 8e587e52

History | View | Annotate | Download (20.2 kB)

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

24 94508060 Michael Hanselmann
You can create the required known_hosts file using ssh-keyscan. It's mandatory
25 94508060 Michael Hanselmann
to use the full name of a node (FQDN). For security reasons, verify the keys
26 94508060 Michael Hanselmann
before using them.
27 94508060 Michael Hanselmann
Example: ssh-keyscan -t rsa node{1,2,3,4}.example.com > known_hosts
28 94508060 Michael Hanselmann
"""
29 a8083063 Iustin Pop
30 a8083063 Iustin Pop
import os
31 a8083063 Iustin Pop
import re
32 a8083063 Iustin Pop
import sys
33 a8083063 Iustin Pop
import yaml
34 a8083063 Iustin Pop
import time
35 180bdd1f Michael Hanselmann
import tempfile
36 a8083063 Iustin Pop
from datetime import datetime
37 a8083063 Iustin Pop
from optparse import OptionParser
38 a8083063 Iustin Pop
39 a8083063 Iustin Pop
# I want more flexibility for testing over SSH, therefore I'm not using
40 a8083063 Iustin Pop
# Ganeti's ssh module.
41 a8083063 Iustin Pop
import subprocess
42 a8083063 Iustin Pop
43 a8083063 Iustin Pop
from ganeti import utils
44 a8083063 Iustin Pop
from ganeti import constants
45 a8083063 Iustin Pop
46 a8083063 Iustin Pop
# {{{ Global variables
47 a8083063 Iustin Pop
cfg = None
48 a8083063 Iustin Pop
options = None
49 a8083063 Iustin Pop
# }}}
50 a8083063 Iustin Pop
51 a8083063 Iustin Pop
# {{{ Errors
52 a8083063 Iustin Pop
class Error(Exception):
53 a8083063 Iustin Pop
  """An error occurred during Q&A testing.
54 a8083063 Iustin Pop

55 a8083063 Iustin Pop
  """
56 a8083063 Iustin Pop
  pass
57 a8083063 Iustin Pop
58 a8083063 Iustin Pop
59 a8083063 Iustin Pop
class OutOfNodesError(Error):
60 a8083063 Iustin Pop
  """Out of nodes.
61 a8083063 Iustin Pop

62 a8083063 Iustin Pop
  """
63 a8083063 Iustin Pop
  pass
64 a8083063 Iustin Pop
65 a8083063 Iustin Pop
66 a8083063 Iustin Pop
class OutOfInstancesError(Error):
67 a8083063 Iustin Pop
  """Out of instances.
68 a8083063 Iustin Pop

69 a8083063 Iustin Pop
  """
70 a8083063 Iustin Pop
  pass
71 a8083063 Iustin Pop
# }}}
72 a8083063 Iustin Pop
73 a8083063 Iustin Pop
# {{{ Utilities
74 a8083063 Iustin Pop
def TestEnabled(test):
75 a8083063 Iustin Pop
  """Returns True if the given test is enabled."""
76 a8083063 Iustin Pop
  return cfg.get('tests', {}).get(test, False)
77 a8083063 Iustin Pop
78 a8083063 Iustin Pop
79 a8083063 Iustin Pop
def RunTest(callable, *args):
80 a8083063 Iustin Pop
  """Runs a test after printing a header.
81 a8083063 Iustin Pop

82 a8083063 Iustin Pop
  """
83 a8083063 Iustin Pop
  if callable.__doc__:
84 a8083063 Iustin Pop
    desc = callable.__doc__.splitlines()[0].strip()
85 a8083063 Iustin Pop
  else:
86 a8083063 Iustin Pop
    desc = '%r' % callable
87 a8083063 Iustin Pop
88 a8083063 Iustin Pop
  now = str(datetime.now())
89 a8083063 Iustin Pop
90 a8083063 Iustin Pop
  print
91 a8083063 Iustin Pop
  print '---', now, ('-' * (55 - len(now)))
92 a8083063 Iustin Pop
  print desc
93 a8083063 Iustin Pop
  print '-' * 60
94 a8083063 Iustin Pop
95 a8083063 Iustin Pop
  return callable(*args)
96 a8083063 Iustin Pop
97 a8083063 Iustin Pop
98 a8083063 Iustin Pop
def AssertEqual(first, second, msg=None):
99 a8083063 Iustin Pop
  """Raises an error when values aren't equal.
100 a8083063 Iustin Pop

101 a8083063 Iustin Pop
  """
102 a8083063 Iustin Pop
  if not first == second:
103 3ecf6786 Iustin Pop
    raise Error(msg or '%r == %r' % (first, second))
104 a8083063 Iustin Pop
105 a8083063 Iustin Pop
106 a8083063 Iustin Pop
def GetSSHCommand(node, cmd, strict=True):
107 a8083063 Iustin Pop
  """Builds SSH command to be executed.
108 a8083063 Iustin Pop

109 a8083063 Iustin Pop
  """
110 a8083063 Iustin Pop
  args = [ 'ssh', '-oEscapeChar=none', '-oBatchMode=yes', '-l', 'root' ]
111 a8083063 Iustin Pop
112 a8083063 Iustin Pop
  if strict:
113 a8083063 Iustin Pop
    tmp = 'yes'
114 a8083063 Iustin Pop
  else:
115 a8083063 Iustin Pop
    tmp = 'no'
116 a8083063 Iustin Pop
  args.append('-oStrictHostKeyChecking=%s' % tmp)
117 807d926c Michael Hanselmann
  args.append('-oClearAllForwardings=yes')
118 807d926c Michael Hanselmann
  args.append('-oForwardAgent=yes')
119 a8083063 Iustin Pop
  args.append(node)
120 a8083063 Iustin Pop
121 a8083063 Iustin Pop
  if options.dry_run:
122 a8083063 Iustin Pop
    prefix = 'exit 0; '
123 a8083063 Iustin Pop
  else:
124 a8083063 Iustin Pop
    prefix = ''
125 a8083063 Iustin Pop
126 a8083063 Iustin Pop
  args.append(prefix + cmd)
127 a8083063 Iustin Pop
128 180bdd1f Michael Hanselmann
  print 'SSH:', utils.ShellQuoteArgs(args)
129 a8083063 Iustin Pop
130 a8083063 Iustin Pop
  return args
131 a8083063 Iustin Pop
132 a8083063 Iustin Pop
133 a8083063 Iustin Pop
def StartSSH(node, cmd, strict=True):
134 a8083063 Iustin Pop
  """Starts SSH.
135 a8083063 Iustin Pop

136 a8083063 Iustin Pop
  """
137 a8083063 Iustin Pop
  args = GetSSHCommand(node, cmd, strict=strict)
138 a8083063 Iustin Pop
  return subprocess.Popen(args, shell=False)
139 a8083063 Iustin Pop
140 a8083063 Iustin Pop
141 a8083063 Iustin Pop
def UploadFile(node, file):
142 a8083063 Iustin Pop
  """Uploads a file to a node and returns the filename.
143 a8083063 Iustin Pop

144 180bdd1f Michael Hanselmann
  Caller needs to remove the returned file on the node when it's not needed
145 180bdd1f Michael Hanselmann
  anymore.
146 a8083063 Iustin Pop
  """
147 180bdd1f Michael Hanselmann
  # Make sure nobody else has access to it while preserving local permissions
148 180bdd1f Michael Hanselmann
  mode = os.stat(file).st_mode & 0700
149 a8083063 Iustin Pop
150 180bdd1f Michael Hanselmann
  cmd = ('tmp=$(tempfile --mode %o --prefix gnt) && '
151 a8083063 Iustin Pop
         '[[ -f "${tmp}" ]] && '
152 a8083063 Iustin Pop
         'cat > "${tmp}" && '
153 a8083063 Iustin Pop
         'echo "${tmp}"') % mode
154 a8083063 Iustin Pop
155 a8083063 Iustin Pop
  f = open(file, 'r')
156 a8083063 Iustin Pop
  try:
157 a8083063 Iustin Pop
    p = subprocess.Popen(GetSSHCommand(node, cmd), shell=False, stdin=f,
158 a8083063 Iustin Pop
                         stdout=subprocess.PIPE)
159 a8083063 Iustin Pop
    AssertEqual(p.wait(), 0)
160 a8083063 Iustin Pop
161 180bdd1f Michael Hanselmann
    # Return temporary filename
162 180bdd1f Michael Hanselmann
    return p.stdout.read().strip()
163 a8083063 Iustin Pop
  finally:
164 a8083063 Iustin Pop
    f.close()
165 a8083063 Iustin Pop
# }}}
166 a8083063 Iustin Pop
167 a8083063 Iustin Pop
# {{{ Config helpers
168 a8083063 Iustin Pop
def GetMasterNode():
169 a8083063 Iustin Pop
  return cfg['nodes'][0]
170 a8083063 Iustin Pop
171 a8083063 Iustin Pop
172 a8083063 Iustin Pop
def AcquireInstance():
173 a8083063 Iustin Pop
  """Returns an instance which isn't in use.
174 a8083063 Iustin Pop

175 a8083063 Iustin Pop
  """
176 a8083063 Iustin Pop
  # Filter out unwanted instances
177 a8083063 Iustin Pop
  tmp_flt = lambda inst: not inst.get('_used', False)
178 a8083063 Iustin Pop
  instances = filter(tmp_flt, cfg['instances'])
179 a8083063 Iustin Pop
  del tmp_flt
180 a8083063 Iustin Pop
181 a8083063 Iustin Pop
  if len(instances) == 0:
182 3ecf6786 Iustin Pop
    raise OutOfInstancesError("No instances left")
183 a8083063 Iustin Pop
184 a8083063 Iustin Pop
  inst = instances[0]
185 a8083063 Iustin Pop
  inst['_used'] = True
186 a8083063 Iustin Pop
  return inst
187 a8083063 Iustin Pop
188 a8083063 Iustin Pop
189 a8083063 Iustin Pop
def ReleaseInstance(inst):
190 a8083063 Iustin Pop
  inst['_used'] = False
191 a8083063 Iustin Pop
192 a8083063 Iustin Pop
193 a8083063 Iustin Pop
def AcquireNode(exclude=None):
194 a8083063 Iustin Pop
  """Returns the least used node.
195 a8083063 Iustin Pop

196 a8083063 Iustin Pop
  """
197 a8083063 Iustin Pop
  master = GetMasterNode()
198 a8083063 Iustin Pop
199 a8083063 Iustin Pop
  # Filter out unwanted nodes
200 a8083063 Iustin Pop
  # TODO: Maybe combine filters
201 a8083063 Iustin Pop
  if exclude is None:
202 a8083063 Iustin Pop
    nodes = cfg['nodes'][:]
203 a8083063 Iustin Pop
  else:
204 a8083063 Iustin Pop
    nodes = filter(lambda node: node != exclude, cfg['nodes'])
205 a8083063 Iustin Pop
206 a8083063 Iustin Pop
  tmp_flt = lambda node: node.get('_added', False) or node == master
207 a8083063 Iustin Pop
  nodes = filter(tmp_flt, nodes)
208 a8083063 Iustin Pop
  del tmp_flt
209 a8083063 Iustin Pop
210 a8083063 Iustin Pop
  if len(nodes) == 0:
211 3ecf6786 Iustin Pop
    raise OutOfNodesError("No nodes left")
212 a8083063 Iustin Pop
213 a8083063 Iustin Pop
  # Get node with least number of uses
214 a8083063 Iustin Pop
  def compare(a, b):
215 a8083063 Iustin Pop
    result = cmp(a.get('_count', 0), b.get('_count', 0))
216 a8083063 Iustin Pop
    if result == 0:
217 a8083063 Iustin Pop
      result = cmp(a['primary'], b['primary'])
218 a8083063 Iustin Pop
    return result
219 a8083063 Iustin Pop
220 a8083063 Iustin Pop
  nodes.sort(cmp=compare)
221 a8083063 Iustin Pop
222 a8083063 Iustin Pop
  node = nodes[0]
223 a8083063 Iustin Pop
  node['_count'] = node.get('_count', 0) + 1
224 a8083063 Iustin Pop
  return node
225 a8083063 Iustin Pop
226 a8083063 Iustin Pop
227 a8083063 Iustin Pop
def ReleaseNode(node):
228 a8083063 Iustin Pop
  node['_count'] = node.get('_count', 0) - 1
229 a8083063 Iustin Pop
# }}}
230 a8083063 Iustin Pop
231 a8083063 Iustin Pop
# {{{ Environment tests
232 a8083063 Iustin Pop
def TestConfig():
233 a8083063 Iustin Pop
  """Test configuration for sanity.
234 a8083063 Iustin Pop

235 a8083063 Iustin Pop
  """
236 a8083063 Iustin Pop
  if len(cfg['nodes']) < 1:
237 3ecf6786 Iustin Pop
    raise Error("Need at least one node")
238 a8083063 Iustin Pop
  if len(cfg['instances']) < 1:
239 3ecf6786 Iustin Pop
    raise Error("Need at least one instance")
240 a8083063 Iustin Pop
  # TODO: Add more checks
241 a8083063 Iustin Pop
242 a8083063 Iustin Pop
243 a8083063 Iustin Pop
def TestSshConnection():
244 a8083063 Iustin Pop
  """Test SSH connection.
245 a8083063 Iustin Pop

246 a8083063 Iustin Pop
  """
247 a8083063 Iustin Pop
  for node in cfg['nodes']:
248 a8083063 Iustin Pop
    AssertEqual(StartSSH(node['primary'], 'exit').wait(), 0)
249 a8083063 Iustin Pop
250 a8083063 Iustin Pop
251 a8083063 Iustin Pop
def TestGanetiCommands():
252 a8083063 Iustin Pop
  """Test availibility of Ganeti commands.
253 a8083063 Iustin Pop

254 a8083063 Iustin Pop
  """
255 a8083063 Iustin Pop
  cmds = ( ['gnt-cluster', '--version'],
256 a8083063 Iustin Pop
           ['gnt-os', '--version'],
257 a8083063 Iustin Pop
           ['gnt-node', '--version'],
258 a8083063 Iustin Pop
           ['gnt-instance', '--version'],
259 a8083063 Iustin Pop
           ['gnt-backup', '--version'],
260 a8083063 Iustin Pop
           ['ganeti-noded', '--version'],
261 a8083063 Iustin Pop
           ['ganeti-watcher', '--version'] )
262 a8083063 Iustin Pop
263 e9e35aaa Michael Hanselmann
  cmd = ' && '.join([utils.ShellQuoteArgs(i) for i in cmds])
264 a8083063 Iustin Pop
265 a8083063 Iustin Pop
  for node in cfg['nodes']:
266 a8083063 Iustin Pop
    AssertEqual(StartSSH(node['primary'], cmd).wait(), 0)
267 a8083063 Iustin Pop
268 a8083063 Iustin Pop
269 a8083063 Iustin Pop
def TestIcmpPing():
270 a8083063 Iustin Pop
  """ICMP ping each node.
271 a8083063 Iustin Pop

272 a8083063 Iustin Pop
  """
273 a8083063 Iustin Pop
  for node in cfg['nodes']:
274 a8083063 Iustin Pop
    check = []
275 a8083063 Iustin Pop
    for i in cfg['nodes']:
276 a8083063 Iustin Pop
      check.append(i['primary'])
277 a8083063 Iustin Pop
      if i.has_key('secondary'):
278 a8083063 Iustin Pop
        check.append(i['secondary'])
279 a8083063 Iustin Pop
280 a8083063 Iustin Pop
    ping = lambda ip: utils.ShellQuoteArgs(['ping', '-w', '3', '-c', '1', ip])
281 e9e35aaa Michael Hanselmann
    cmd = ' && '.join([ping(i) for i in check])
282 a8083063 Iustin Pop
283 a8083063 Iustin Pop
    AssertEqual(StartSSH(node['primary'], cmd).wait(), 0)
284 a8083063 Iustin Pop
# }}}
285 a8083063 Iustin Pop
286 a8083063 Iustin Pop
# {{{ Cluster tests
287 a8083063 Iustin Pop
def TestClusterInit():
288 a8083063 Iustin Pop
  """gnt-cluster init"""
289 a8083063 Iustin Pop
  master = GetMasterNode()
290 a8083063 Iustin Pop
291 a8083063 Iustin Pop
  cmd = ['gnt-cluster', 'init']
292 a8083063 Iustin Pop
  if master.get('secondary', None):
293 a8083063 Iustin Pop
    cmd.append('--secondary-ip=%s' % master['secondary'])
294 6f11f250 Michael Hanselmann
  if cfg.get('bridge', None):
295 6f11f250 Michael Hanselmann
    cmd.append('--bridge=%s' % cfg['bridge'])
296 e9e35aaa Michael Hanselmann
    cmd.append('--master-netdev=%s' % cfg['bridge'])
297 a8083063 Iustin Pop
  cmd.append(cfg['name'])
298 a8083063 Iustin Pop
299 a8083063 Iustin Pop
  AssertEqual(StartSSH(master['primary'],
300 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
301 a8083063 Iustin Pop
302 a8083063 Iustin Pop
303 a8083063 Iustin Pop
def TestClusterVerify():
304 a8083063 Iustin Pop
  """gnt-cluster verify"""
305 a8083063 Iustin Pop
  cmd = ['gnt-cluster', 'verify']
306 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
307 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
308 a8083063 Iustin Pop
309 a8083063 Iustin Pop
310 a8083063 Iustin Pop
def TestClusterInfo():
311 a8083063 Iustin Pop
  """gnt-cluster info"""
312 a8083063 Iustin Pop
  cmd = ['gnt-cluster', 'info']
313 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
314 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
315 a8083063 Iustin Pop
316 a8083063 Iustin Pop
317 a8083063 Iustin Pop
def TestClusterBurnin():
318 a8083063 Iustin Pop
  """Burnin"""
319 a8083063 Iustin Pop
  master = GetMasterNode()
320 a8083063 Iustin Pop
321 a8083063 Iustin Pop
  # Get as many instances as we need
322 a8083063 Iustin Pop
  instances = []
323 a8083063 Iustin Pop
  try:
324 a8083063 Iustin Pop
    for _ in xrange(0, cfg.get('options', {}).get('burnin-instances', 1)):
325 a8083063 Iustin Pop
      instances.append(AcquireInstance())
326 a8083063 Iustin Pop
  except OutOfInstancesError:
327 a8083063 Iustin Pop
    print "Not enough instances, continuing anyway."
328 a8083063 Iustin Pop
329 a8083063 Iustin Pop
  if len(instances) < 1:
330 3ecf6786 Iustin Pop
    raise Error("Burnin needs at least one instance")
331 a8083063 Iustin Pop
332 a8083063 Iustin Pop
  # Run burnin
333 a8083063 Iustin Pop
  try:
334 a8083063 Iustin Pop
    script = UploadFile(master['primary'], '../tools/burnin')
335 a8083063 Iustin Pop
    try:
336 a0e7cec8 Michael Hanselmann
      cmd = [script,
337 a0e7cec8 Michael Hanselmann
             '--os=%s' % cfg['os'],
338 a0e7cec8 Michael Hanselmann
             '--os-size=%s' % cfg['os-size'],
339 a0e7cec8 Michael Hanselmann
             '--swap-size=%s' % cfg['swap-size']]
340 e9e35aaa Michael Hanselmann
      cmd += [inst['name'] for inst in instances]
341 a8083063 Iustin Pop
      AssertEqual(StartSSH(master['primary'],
342 a8083063 Iustin Pop
                           utils.ShellQuoteArgs(cmd)).wait(), 0)
343 a8083063 Iustin Pop
    finally:
344 a8083063 Iustin Pop
      cmd = ['rm', '-f', script]
345 a8083063 Iustin Pop
      AssertEqual(StartSSH(master['primary'],
346 a8083063 Iustin Pop
                           utils.ShellQuoteArgs(cmd)).wait(), 0)
347 a8083063 Iustin Pop
  finally:
348 a8083063 Iustin Pop
    for inst in instances:
349 a8083063 Iustin Pop
      ReleaseInstance(inst)
350 a8083063 Iustin Pop
351 a8083063 Iustin Pop
352 a8083063 Iustin Pop
def TestClusterMasterFailover():
353 a8083063 Iustin Pop
  """gnt-cluster masterfailover"""
354 a8083063 Iustin Pop
  master = GetMasterNode()
355 a8083063 Iustin Pop
356 a8083063 Iustin Pop
  failovermaster = AcquireNode(exclude=master)
357 a8083063 Iustin Pop
  try:
358 a8083063 Iustin Pop
    cmd = ['gnt-cluster', 'masterfailover']
359 a8083063 Iustin Pop
    AssertEqual(StartSSH(failovermaster['primary'],
360 a8083063 Iustin Pop
                         utils.ShellQuoteArgs(cmd)).wait(), 0)
361 a8083063 Iustin Pop
362 a8083063 Iustin Pop
    cmd = ['gnt-cluster', 'masterfailover']
363 a8083063 Iustin Pop
    AssertEqual(StartSSH(master['primary'],
364 a8083063 Iustin Pop
                         utils.ShellQuoteArgs(cmd)).wait(), 0)
365 a8083063 Iustin Pop
  finally:
366 a8083063 Iustin Pop
    ReleaseNode(failovermaster)
367 a8083063 Iustin Pop
368 a8083063 Iustin Pop
369 180bdd1f Michael Hanselmann
def TestClusterCopyfile():
370 180bdd1f Michael Hanselmann
  """gnt-cluster copyfile"""
371 180bdd1f Michael Hanselmann
  master = GetMasterNode()
372 180bdd1f Michael Hanselmann
373 180bdd1f Michael Hanselmann
  # Create temporary file
374 180bdd1f Michael Hanselmann
  f = tempfile.NamedTemporaryFile()
375 180bdd1f Michael Hanselmann
  f.write("I'm a testfile.\n")
376 180bdd1f Michael Hanselmann
  f.flush()
377 180bdd1f Michael Hanselmann
  f.seek(0)
378 180bdd1f Michael Hanselmann
379 180bdd1f Michael Hanselmann
  # Upload file to master node
380 180bdd1f Michael Hanselmann
  testname = UploadFile(master['primary'], f.name)
381 180bdd1f Michael Hanselmann
  try:
382 180bdd1f Michael Hanselmann
    # Copy file to all nodes
383 180bdd1f Michael Hanselmann
    cmd = ['gnt-cluster', 'copyfile', testname]
384 180bdd1f Michael Hanselmann
    AssertEqual(StartSSH(master['primary'],
385 180bdd1f Michael Hanselmann
                         utils.ShellQuoteArgs(cmd)).wait(), 0)
386 180bdd1f Michael Hanselmann
  finally:
387 180bdd1f Michael Hanselmann
    # Remove file from all nodes
388 180bdd1f Michael Hanselmann
    for node in cfg['nodes']:
389 180bdd1f Michael Hanselmann
      cmd = ['rm', '-f', testname]
390 180bdd1f Michael Hanselmann
      AssertEqual(StartSSH(node['primary'],
391 180bdd1f Michael Hanselmann
                           utils.ShellQuoteArgs(cmd)).wait(), 0)
392 180bdd1f Michael Hanselmann
393 180bdd1f Michael Hanselmann
394 a8083063 Iustin Pop
def TestClusterDestroy():
395 a8083063 Iustin Pop
  """gnt-cluster destroy"""
396 a8083063 Iustin Pop
  cmd = ['gnt-cluster', 'destroy', '--yes-do-it']
397 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
398 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
399 a8083063 Iustin Pop
# }}}
400 a8083063 Iustin Pop
401 a8083063 Iustin Pop
# {{{ Node tests
402 a8083063 Iustin Pop
def _NodeAdd(node):
403 a8083063 Iustin Pop
  if node.get('_added', False):
404 3ecf6786 Iustin Pop
    raise Error("Node %s already in cluster" % node['primary'])
405 a8083063 Iustin Pop
406 a8083063 Iustin Pop
  cmd = ['gnt-node', 'add']
407 a8083063 Iustin Pop
  if node.get('secondary', None):
408 a8083063 Iustin Pop
    cmd.append('--secondary-ip=%s' % node['secondary'])
409 a8083063 Iustin Pop
  cmd.append(node['primary'])
410 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
411 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
412 a8083063 Iustin Pop
413 a8083063 Iustin Pop
  node['_added'] = True
414 a8083063 Iustin Pop
415 a8083063 Iustin Pop
416 a8083063 Iustin Pop
def TestNodeAddAll():
417 a8083063 Iustin Pop
  """Adding all nodes to cluster."""
418 a8083063 Iustin Pop
  master = GetMasterNode()
419 a8083063 Iustin Pop
  for node in cfg['nodes']:
420 a8083063 Iustin Pop
    if node != master:
421 a8083063 Iustin Pop
      _NodeAdd(node)
422 a8083063 Iustin Pop
423 a8083063 Iustin Pop
424 a8083063 Iustin Pop
def _NodeRemove(node):
425 a8083063 Iustin Pop
  cmd = ['gnt-node', 'remove', node['primary']]
426 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
427 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
428 a8083063 Iustin Pop
  node['_added'] = False
429 a8083063 Iustin Pop
430 a8083063 Iustin Pop
431 a8083063 Iustin Pop
def TestNodeRemoveAll():
432 a8083063 Iustin Pop
  """Removing all nodes from cluster."""
433 a8083063 Iustin Pop
  master = GetMasterNode()
434 a8083063 Iustin Pop
  for node in cfg['nodes']:
435 a8083063 Iustin Pop
    if node != master:
436 a8083063 Iustin Pop
      _NodeRemove(node)
437 e9e35aaa Michael Hanselmann
438 e9e35aaa Michael Hanselmann
439 e9e35aaa Michael Hanselmann
def TestNodeInfo():
440 e9e35aaa Michael Hanselmann
  """gnt-node info"""
441 e9e35aaa Michael Hanselmann
  cmd = ['gnt-node', 'info']
442 e9e35aaa Michael Hanselmann
  AssertEqual(StartSSH(GetMasterNode()['primary'],
443 e9e35aaa Michael Hanselmann
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
444 9df6d173 Michael Hanselmann
445 9df6d173 Michael Hanselmann
446 9df6d173 Michael Hanselmann
def TestNodeVolumes():
447 9df6d173 Michael Hanselmann
  """gnt-node volumes"""
448 9df6d173 Michael Hanselmann
  cmd = ['gnt-node', 'volumes']
449 9df6d173 Michael Hanselmann
  AssertEqual(StartSSH(GetMasterNode()['primary'],
450 9df6d173 Michael Hanselmann
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
451 a8083063 Iustin Pop
# }}}
452 a8083063 Iustin Pop
453 a8083063 Iustin Pop
# {{{ Instance tests
454 a8083063 Iustin Pop
def _DiskTest(node, instance, args):
455 a8083063 Iustin Pop
  cmd = ['gnt-instance', 'add',
456 a8083063 Iustin Pop
         '--os-type=%s' % cfg['os'],
457 a8083063 Iustin Pop
         '--os-size=%s' % cfg['os-size'],
458 a8083063 Iustin Pop
         '--swap-size=%s' % cfg['swap-size'],
459 a8083063 Iustin Pop
         '--memory=%s' % cfg['mem'],
460 a8083063 Iustin Pop
         '--node=%s' % node['primary']]
461 a8083063 Iustin Pop
  if args:
462 a8083063 Iustin Pop
    cmd += args
463 a8083063 Iustin Pop
  cmd.append(instance['name'])
464 a8083063 Iustin Pop
465 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
466 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
467 a8083063 Iustin Pop
  return instance
468 a8083063 Iustin Pop
469 a8083063 Iustin Pop
470 a8083063 Iustin Pop
def TestInstanceAddWithPlainDisk(node):
471 a8083063 Iustin Pop
  """gnt-instance add -t plain"""
472 a8083063 Iustin Pop
  return _DiskTest(node, AcquireInstance(), ['--disk-template=plain'])
473 a8083063 Iustin Pop
474 a8083063 Iustin Pop
475 a8083063 Iustin Pop
def TestInstanceAddWithLocalMirrorDisk(node):
476 a8083063 Iustin Pop
  """gnt-instance add -t local_raid1"""
477 a8083063 Iustin Pop
  return _DiskTest(node, AcquireInstance(), ['--disk-template=local_raid1'])
478 a8083063 Iustin Pop
479 a8083063 Iustin Pop
480 a8083063 Iustin Pop
def TestInstanceAddWithRemoteRaidDisk(node, node2):
481 a8083063 Iustin Pop
  """gnt-instance add -t remote_raid1"""
482 a8083063 Iustin Pop
  return _DiskTest(node, AcquireInstance(),
483 a8083063 Iustin Pop
                   ['--disk-template=remote_raid1',
484 a8083063 Iustin Pop
                    '--secondary-node=%s' % node2['primary']])
485 a8083063 Iustin Pop
486 a8083063 Iustin Pop
487 a8083063 Iustin Pop
def TestInstanceRemove(instance):
488 a8083063 Iustin Pop
  """gnt-instance remove"""
489 a8083063 Iustin Pop
  cmd = ['gnt-instance', 'remove', '-f', instance['name']]
490 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
491 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
492 a8083063 Iustin Pop
493 a8083063 Iustin Pop
  ReleaseInstance(instance)
494 a8083063 Iustin Pop
495 a8083063 Iustin Pop
496 a8083063 Iustin Pop
def TestInstanceStartup(instance):
497 a8083063 Iustin Pop
  """gnt-instance startup"""
498 a8083063 Iustin Pop
  cmd = ['gnt-instance', 'startup', instance['name']]
499 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
500 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
501 a8083063 Iustin Pop
502 a8083063 Iustin Pop
503 a8083063 Iustin Pop
def TestInstanceShutdown(instance):
504 a8083063 Iustin Pop
  """gnt-instance shutdown"""
505 a8083063 Iustin Pop
  cmd = ['gnt-instance', 'shutdown', instance['name']]
506 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
507 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
508 a8083063 Iustin Pop
509 a8083063 Iustin Pop
510 a8083063 Iustin Pop
def TestInstanceFailover(instance):
511 a8083063 Iustin Pop
  """gnt-instance failover"""
512 a8083063 Iustin Pop
  cmd = ['gnt-instance', 'failover', '--force', instance['name']]
513 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
514 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
515 e9e35aaa Michael Hanselmann
516 e9e35aaa Michael Hanselmann
517 e9e35aaa Michael Hanselmann
def TestInstanceInfo(instance):
518 e9e35aaa Michael Hanselmann
  """gnt-instance info"""
519 e9e35aaa Michael Hanselmann
  cmd = ['gnt-instance', 'info', instance['name']]
520 e9e35aaa Michael Hanselmann
  AssertEqual(StartSSH(GetMasterNode()['primary'],
521 e9e35aaa Michael Hanselmann
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
522 a8083063 Iustin Pop
# }}}
523 a8083063 Iustin Pop
524 a8083063 Iustin Pop
# {{{ Daemon tests
525 a8083063 Iustin Pop
def _ResolveInstanceName(instance):
526 a8083063 Iustin Pop
  """Gets the full Xen name of an instance.
527 a8083063 Iustin Pop

528 a8083063 Iustin Pop
  """
529 a8083063 Iustin Pop
  master = GetMasterNode()
530 a8083063 Iustin Pop
531 a8083063 Iustin Pop
  info_cmd = utils.ShellQuoteArgs(['gnt-instance', 'info', instance['name']])
532 a8083063 Iustin Pop
  sed_cmd = utils.ShellQuoteArgs(['sed', '-n', '-e', 's/^Instance name: *//p'])
533 a8083063 Iustin Pop
534 a8083063 Iustin Pop
  cmd = '%s | %s' % (info_cmd, sed_cmd)
535 a8083063 Iustin Pop
  p = subprocess.Popen(GetSSHCommand(master['primary'], cmd), shell=False,
536 a8083063 Iustin Pop
                       stdout=subprocess.PIPE)
537 a8083063 Iustin Pop
  AssertEqual(p.wait(), 0)
538 a8083063 Iustin Pop
539 a8083063 Iustin Pop
  return p.stdout.read().strip()
540 a8083063 Iustin Pop
541 a8083063 Iustin Pop
542 a8083063 Iustin Pop
def _InstanceRunning(node, name):
543 a8083063 Iustin Pop
  """Checks whether an instance is running.
544 a8083063 Iustin Pop

545 a8083063 Iustin Pop
  Args:
546 a8083063 Iustin Pop
    node: Node the instance runs on
547 a8083063 Iustin Pop
    name: Full name of Xen instance
548 a8083063 Iustin Pop
  """
549 a8083063 Iustin Pop
  cmd = utils.ShellQuoteArgs(['xm', 'list', name]) + ' >/dev/null'
550 a8083063 Iustin Pop
  ret = StartSSH(node['primary'], cmd).wait()
551 a8083063 Iustin Pop
  return ret == 0
552 a8083063 Iustin Pop
553 a8083063 Iustin Pop
554 a8083063 Iustin Pop
def _XmShutdownInstance(node, name):
555 a8083063 Iustin Pop
  """Shuts down instance using "xm" and waits for completion.
556 a8083063 Iustin Pop

557 a8083063 Iustin Pop
  Args:
558 a8083063 Iustin Pop
    node: Node the instance runs on
559 a8083063 Iustin Pop
    name: Full name of Xen instance
560 a8083063 Iustin Pop
  """
561 a8083063 Iustin Pop
  cmd = ['xm', 'shutdown', name]
562 a8083063 Iustin Pop
  AssertEqual(StartSSH(GetMasterNode()['primary'],
563 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
564 a8083063 Iustin Pop
565 a8083063 Iustin Pop
  # Wait up to a minute
566 a8083063 Iustin Pop
  end = time.time() + 60
567 a8083063 Iustin Pop
  while time.time() <= end:
568 a8083063 Iustin Pop
    if not _InstanceRunning(node, name):
569 a8083063 Iustin Pop
      break
570 a8083063 Iustin Pop
    time.sleep(5)
571 a8083063 Iustin Pop
  else:
572 3ecf6786 Iustin Pop
    raise Error("xm shutdown failed")
573 a8083063 Iustin Pop
574 a8083063 Iustin Pop
575 a8083063 Iustin Pop
def _ResetWatcherDaemon(node):
576 a8083063 Iustin Pop
  """Removes the watcher daemon's state file.
577 a8083063 Iustin Pop

578 a8083063 Iustin Pop
  Args:
579 a8083063 Iustin Pop
    node: Node to be reset
580 a8083063 Iustin Pop
  """
581 a8083063 Iustin Pop
  cmd = ['rm', '-f', constants.WATCHER_STATEFILE]
582 a8083063 Iustin Pop
  AssertEqual(StartSSH(node['primary'],
583 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
584 a8083063 Iustin Pop
585 a8083063 Iustin Pop
586 a8083063 Iustin Pop
def TestInstanceAutomaticRestart(node, instance):
587 a8083063 Iustin Pop
  """Test automatic restart of instance by ganeti-watcher.
588 a8083063 Iustin Pop

589 a8083063 Iustin Pop
  Note: takes up to 6 minutes to complete.
590 a8083063 Iustin Pop
  """
591 a8083063 Iustin Pop
  master = GetMasterNode()
592 a8083063 Iustin Pop
  inst_name = _ResolveInstanceName(instance)
593 a8083063 Iustin Pop
594 a8083063 Iustin Pop
  _ResetWatcherDaemon(node)
595 a8083063 Iustin Pop
  _XmShutdownInstance(node, inst_name)
596 a8083063 Iustin Pop
597 a8083063 Iustin Pop
  # Give it a bit more than five minutes to start again
598 a8083063 Iustin Pop
  restart_at = time.time() + 330
599 a8083063 Iustin Pop
600 a8083063 Iustin Pop
  # Wait until it's running again
601 a8083063 Iustin Pop
  while time.time() <= restart_at:
602 a8083063 Iustin Pop
    if _InstanceRunning(node, inst_name):
603 a8083063 Iustin Pop
      break
604 a8083063 Iustin Pop
    time.sleep(15)
605 a8083063 Iustin Pop
  else:
606 3ecf6786 Iustin Pop
    raise Error("Daemon didn't restart instance in time")
607 a8083063 Iustin Pop
608 a8083063 Iustin Pop
  cmd = ['gnt-instance', 'info', inst_name]
609 a8083063 Iustin Pop
  AssertEqual(StartSSH(master['primary'],
610 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
611 a8083063 Iustin Pop
612 a8083063 Iustin Pop
613 a8083063 Iustin Pop
def TestInstanceConsecutiveFailures(node, instance):
614 a8083063 Iustin Pop
  """Test five consecutive instance failures.
615 a8083063 Iustin Pop

616 a8083063 Iustin Pop
  Note: takes at least 35 minutes to complete.
617 a8083063 Iustin Pop
  """
618 a8083063 Iustin Pop
  master = GetMasterNode()
619 a8083063 Iustin Pop
  inst_name = _ResolveInstanceName(instance)
620 a8083063 Iustin Pop
621 a8083063 Iustin Pop
  _ResetWatcherDaemon(node)
622 a8083063 Iustin Pop
  _XmShutdownInstance(node, inst_name)
623 a8083063 Iustin Pop
624 a8083063 Iustin Pop
  # Do shutdowns for 30 minutes
625 a8083063 Iustin Pop
  finished_at = time.time() + (35 * 60)
626 a8083063 Iustin Pop
627 a8083063 Iustin Pop
  while time.time() <= finished_at:
628 a8083063 Iustin Pop
    if _InstanceRunning(node, inst_name):
629 a8083063 Iustin Pop
      _XmShutdownInstance(node, inst_name)
630 a8083063 Iustin Pop
    time.sleep(30)
631 a8083063 Iustin Pop
632 a8083063 Iustin Pop
  # Check for some time whether the instance doesn't start again
633 a8083063 Iustin Pop
  check_until = time.time() + 330
634 a8083063 Iustin Pop
  while time.time() <= check_until:
635 a8083063 Iustin Pop
    if _InstanceRunning(node, inst_name):
636 3ecf6786 Iustin Pop
      raise Error("Instance started when it shouldn't")
637 a8083063 Iustin Pop
    time.sleep(30)
638 a8083063 Iustin Pop
639 a8083063 Iustin Pop
  cmd = ['gnt-instance', 'info', inst_name]
640 a8083063 Iustin Pop
  AssertEqual(StartSSH(master['primary'],
641 a8083063 Iustin Pop
                       utils.ShellQuoteArgs(cmd)).wait(), 0)
642 a8083063 Iustin Pop
# }}}
643 a8083063 Iustin Pop
644 94508060 Michael Hanselmann
# {{{ Other tests
645 94508060 Michael Hanselmann
def TestUploadKnownHostsFile(localpath):
646 94508060 Michael Hanselmann
  """Uploading known_hosts file.
647 94508060 Michael Hanselmann

648 94508060 Michael Hanselmann
  """
649 94508060 Michael Hanselmann
  master = GetMasterNode()
650 94508060 Michael Hanselmann
651 94508060 Michael Hanselmann
  tmpfile = UploadFile(master['primary'], localpath)
652 94508060 Michael Hanselmann
  try:
653 94508060 Michael Hanselmann
    cmd = ['mv', tmpfile, constants.SSH_KNOWN_HOSTS_FILE]
654 94508060 Michael Hanselmann
    AssertEqual(StartSSH(master['primary'],
655 94508060 Michael Hanselmann
                         utils.ShellQuoteArgs(cmd)).wait(), 0)
656 94508060 Michael Hanselmann
  except:
657 94508060 Michael Hanselmann
    cmd = ['rm', '-f', tmpfile]
658 94508060 Michael Hanselmann
    AssertEqual(StartSSH(master['primary'],
659 94508060 Michael Hanselmann
                         utils.ShellQuoteArgs(cmd)).wait(), 0)
660 94508060 Michael Hanselmann
    raise
661 94508060 Michael Hanselmann
# }}}
662 94508060 Michael Hanselmann
663 a8083063 Iustin Pop
# {{{ Main program
664 a8083063 Iustin Pop
if __name__ == '__main__':
665 a8083063 Iustin Pop
  # {{{ Option parsing
666 94508060 Michael Hanselmann
  parser = OptionParser(usage="%prog [options] <config-file> "
667 94508060 Michael Hanselmann
                              "<known-hosts-file>")
668 a8083063 Iustin Pop
  parser.add_option('--dry-run', dest='dry_run',
669 a8083063 Iustin Pop
      action="store_true",
670 a8083063 Iustin Pop
      help="Show what would be done")
671 a8083063 Iustin Pop
  parser.add_option('--yes-do-it', dest='yes_do_it',
672 a8083063 Iustin Pop
      action="store_true",
673 a8083063 Iustin Pop
      help="Really execute the tests")
674 a8083063 Iustin Pop
  (options, args) = parser.parse_args()
675 a8083063 Iustin Pop
  # }}}
676 a8083063 Iustin Pop
677 94508060 Michael Hanselmann
  if len(args) == 2:
678 94508060 Michael Hanselmann
    (config_file, known_hosts_file) = args
679 a8083063 Iustin Pop
  else:
680 94508060 Michael Hanselmann
    parser.error("Not enough arguments.")
681 a8083063 Iustin Pop
682 a8083063 Iustin Pop
  if not options.yes_do_it:
683 a8083063 Iustin Pop
    print ("Executing this script irreversibly destroys any Ganeti\n"
684 a8083063 Iustin Pop
           "configuration on all nodes involved. If you really want\n"
685 a8083063 Iustin Pop
           "to start testing, supply the --yes-do-it option.")
686 a8083063 Iustin Pop
    sys.exit(1)
687 a8083063 Iustin Pop
688 a8083063 Iustin Pop
  f = open(config_file, 'r')
689 a8083063 Iustin Pop
  try:
690 a8083063 Iustin Pop
    cfg = yaml.load(f.read())
691 a8083063 Iustin Pop
  finally:
692 a8083063 Iustin Pop
    f.close()
693 a8083063 Iustin Pop
694 a8083063 Iustin Pop
  RunTest(TestConfig)
695 a8083063 Iustin Pop
696 94508060 Michael Hanselmann
  RunTest(TestUploadKnownHostsFile, known_hosts_file)
697 94508060 Michael Hanselmann
698 a8083063 Iustin Pop
  if TestEnabled('env'):
699 a8083063 Iustin Pop
    RunTest(TestSshConnection)
700 a8083063 Iustin Pop
    RunTest(TestIcmpPing)
701 a8083063 Iustin Pop
    RunTest(TestGanetiCommands)
702 a8083063 Iustin Pop
703 a8083063 Iustin Pop
  RunTest(TestClusterInit)
704 a8083063 Iustin Pop
705 180bdd1f Michael Hanselmann
  RunTest(TestNodeAddAll)
706 180bdd1f Michael Hanselmann
707 a8083063 Iustin Pop
  if TestEnabled('cluster-verify'):
708 a8083063 Iustin Pop
    RunTest(TestClusterVerify)
709 e9e35aaa Michael Hanselmann
710 e9e35aaa Michael Hanselmann
  if TestEnabled('cluster-info'):
711 a8083063 Iustin Pop
    RunTest(TestClusterInfo)
712 a8083063 Iustin Pop
713 180bdd1f Michael Hanselmann
  if TestEnabled('cluster-copyfile'):
714 180bdd1f Michael Hanselmann
    RunTest(TestClusterCopyfile)
715 a8083063 Iustin Pop
716 e9e35aaa Michael Hanselmann
  if TestEnabled('node-info'):
717 e9e35aaa Michael Hanselmann
    RunTest(TestNodeInfo)
718 e9e35aaa Michael Hanselmann
719 a8083063 Iustin Pop
  if TestEnabled('cluster-burnin'):
720 a8083063 Iustin Pop
    RunTest(TestClusterBurnin)
721 a8083063 Iustin Pop
722 a8083063 Iustin Pop
  if TestEnabled('cluster-master-failover'):
723 a8083063 Iustin Pop
    RunTest(TestClusterMasterFailover)
724 a8083063 Iustin Pop
725 a8083063 Iustin Pop
  node = AcquireNode()
726 a8083063 Iustin Pop
  try:
727 a8083063 Iustin Pop
    if TestEnabled('instance-add-plain-disk'):
728 a8083063 Iustin Pop
      instance = RunTest(TestInstanceAddWithPlainDisk, node)
729 a8083063 Iustin Pop
      RunTest(TestInstanceShutdown, instance)
730 a8083063 Iustin Pop
      RunTest(TestInstanceStartup, instance)
731 a8083063 Iustin Pop
732 e9e35aaa Michael Hanselmann
      if TestEnabled('instance-info'):
733 e9e35aaa Michael Hanselmann
        RunTest(TestInstanceInfo, instance)
734 e9e35aaa Michael Hanselmann
735 a8083063 Iustin Pop
      if TestEnabled('instance-automatic-restart'):
736 a8083063 Iustin Pop
        RunTest(TestInstanceAutomaticRestart, node, instance)
737 a8083063 Iustin Pop
738 a8083063 Iustin Pop
      if TestEnabled('instance-consecutive-failures'):
739 a8083063 Iustin Pop
        RunTest(TestInstanceConsecutiveFailures, node, instance)
740 a8083063 Iustin Pop
741 9df6d173 Michael Hanselmann
      if TestEnabled('node-volumes'):
742 9df6d173 Michael Hanselmann
        RunTest(TestNodeVolumes)
743 9df6d173 Michael Hanselmann
744 a8083063 Iustin Pop
      RunTest(TestInstanceRemove, instance)
745 a8083063 Iustin Pop
      del instance
746 a8083063 Iustin Pop
747 a8083063 Iustin Pop
    if TestEnabled('instance-add-local-mirror-disk'):
748 a8083063 Iustin Pop
      instance = RunTest(TestInstanceAddWithLocalMirrorDisk, node)
749 a8083063 Iustin Pop
      RunTest(TestInstanceShutdown, instance)
750 a8083063 Iustin Pop
      RunTest(TestInstanceStartup, instance)
751 e9e35aaa Michael Hanselmann
752 e9e35aaa Michael Hanselmann
      if TestEnabled('instance-info'):
753 e9e35aaa Michael Hanselmann
        RunTest(TestInstanceInfo, instance)
754 e9e35aaa Michael Hanselmann
755 9df6d173 Michael Hanselmann
      if TestEnabled('node-volumes'):
756 9df6d173 Michael Hanselmann
        RunTest(TestNodeVolumes)
757 9df6d173 Michael Hanselmann
758 a8083063 Iustin Pop
      RunTest(TestInstanceRemove, instance)
759 a8083063 Iustin Pop
      del instance
760 a8083063 Iustin Pop
761 a8083063 Iustin Pop
    if TestEnabled('instance-add-remote-raid-disk'):
762 a8083063 Iustin Pop
      node2 = AcquireNode(exclude=node)
763 a8083063 Iustin Pop
      try:
764 a8083063 Iustin Pop
        instance = RunTest(TestInstanceAddWithRemoteRaidDisk, node, node2)
765 a8083063 Iustin Pop
        RunTest(TestInstanceShutdown, instance)
766 a8083063 Iustin Pop
        RunTest(TestInstanceStartup, instance)
767 a8083063 Iustin Pop
768 e9e35aaa Michael Hanselmann
        if TestEnabled('instance-info'):
769 e9e35aaa Michael Hanselmann
          RunTest(TestInstanceInfo, instance)
770 e9e35aaa Michael Hanselmann
771 a8083063 Iustin Pop
        if TestEnabled('instance-failover'):
772 a8083063 Iustin Pop
          RunTest(TestInstanceFailover, instance)
773 a8083063 Iustin Pop
774 9df6d173 Michael Hanselmann
        if TestEnabled('node-volumes'):
775 9df6d173 Michael Hanselmann
          RunTest(TestNodeVolumes)
776 9df6d173 Michael Hanselmann
777 a8083063 Iustin Pop
        RunTest(TestInstanceRemove, instance)
778 a8083063 Iustin Pop
        del instance
779 a8083063 Iustin Pop
      finally:
780 a8083063 Iustin Pop
        ReleaseNode(node2)
781 a8083063 Iustin Pop
782 a8083063 Iustin Pop
  finally:
783 a8083063 Iustin Pop
    ReleaseNode(node)
784 a8083063 Iustin Pop
785 a8083063 Iustin Pop
  RunTest(TestNodeRemoveAll)
786 a8083063 Iustin Pop
787 a8083063 Iustin Pop
  if TestEnabled('cluster-destroy'):
788 a8083063 Iustin Pop
    RunTest(TestClusterDestroy)
789 a8083063 Iustin Pop
# }}}
790 a8083063 Iustin Pop
791 a8083063 Iustin Pop
# vim: foldmethod=marker :