| Branch: | Tag: | Revision:

root / tools / burnin @ a4af651e

History | View | Annotate | Download (15 kB)

1 a8083063 Iustin Pop
2 a8083063 Iustin Pop
3 a8083063 Iustin Pop
4 01b69ec5 Michael Hanselmann
# Copyright (C) 2006, 2007 Google Inc.
5 01b69ec5 Michael Hanselmann
6 01b69ec5 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 01b69ec5 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 01b69ec5 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 01b69ec5 Michael Hanselmann
# (at your option) any later version.
10 01b69ec5 Michael Hanselmann
11 01b69ec5 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 01b69ec5 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 01b69ec5 Michael Hanselmann
14 01b69ec5 Michael Hanselmann
# General Public License for more details.
15 01b69ec5 Michael Hanselmann
16 01b69ec5 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 01b69ec5 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 01b69ec5 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 01b69ec5 Michael Hanselmann
# 02110-1301, USA.
20 01b69ec5 Michael Hanselmann
21 01b69ec5 Michael Hanselmann
22 01b69ec5 Michael Hanselmann
"""Burnin program
23 01b69ec5 Michael Hanselmann
24 01b69ec5 Michael Hanselmann
25 175f44c2 Iustin Pop
26 bd5e77f9 Guido Trotter
import os
27 a8083063 Iustin Pop
import sys
28 a8083063 Iustin Pop
import optparse
29 175f44c2 Iustin Pop
from itertools import izip, islice, cycle
30 21546b1c Iustin Pop
from cStringIO import StringIO
31 a8083063 Iustin Pop
32 a8083063 Iustin Pop
from ganeti import opcodes
33 a8083063 Iustin Pop
from ganeti import mcpu
34 a8083063 Iustin Pop
from ganeti import constants
35 a8083063 Iustin Pop
from ganeti import cli
36 a8083063 Iustin Pop
from ganeti import logger
37 9f13fc7a Iustin Pop
from ganeti import errors
38 9f13fc7a Iustin Pop
from ganeti import utils
39 a8083063 Iustin Pop
40 01b69ec5 Michael Hanselmann
41 9f13fc7a Iustin Pop
USAGE = ("\tburnin -o OS_NAME [options...] instance_name ...")
42 a8083063 Iustin Pop
43 01b69ec5 Michael Hanselmann
44 a8083063 Iustin Pop
def Usage():
45 a8083063 Iustin Pop
  """Shows program usage information and exits the program."""
46 a8083063 Iustin Pop
47 a8083063 Iustin Pop
  print >> sys.stderr, "Usage:"
48 a8083063 Iustin Pop
  print >> sys.stderr, USAGE
49 a8083063 Iustin Pop
50 a8083063 Iustin Pop
51 01b69ec5 Michael Hanselmann
52 21546b1c Iustin Pop
def Log(msg):
53 3ecf6786 Iustin Pop
  """Simple function that prints out its argument.
54 3ecf6786 Iustin Pop
55 3ecf6786 Iustin Pop
56 3ecf6786 Iustin Pop
  print msg
57 84cc52ab Michael Hanselmann
58 a8083063 Iustin Pop
59 01b69ec5 Michael Hanselmann
60 175f44c2 Iustin Pop
class Burner(object):
61 175f44c2 Iustin Pop
  """Burner class."""
62 175f44c2 Iustin Pop
63 175f44c2 Iustin Pop
  def __init__(self):
64 175f44c2 Iustin Pop
65 21546b1c Iustin Pop
    logger.SetupLogging(debug=False, program="ganeti/burnin")
66 21546b1c Iustin Pop
    self._feed_buf = StringIO()
67 21546b1c Iustin Pop
    self.proc = mcpu.Processor(feedback=self.Feedback)
68 175f44c2 Iustin Pop
    self.nodes = []
69 175f44c2 Iustin Pop
    self.instances = []
70 175f44c2 Iustin Pop
    self.to_rem = []
71 175f44c2 Iustin Pop
    self.opts = None
72 175f44c2 Iustin Pop
73 175f44c2 Iustin Pop
74 175f44c2 Iustin Pop
75 21546b1c Iustin Pop
  def ClearFeedbackBuf(self):
76 21546b1c Iustin Pop
    """Clear the feedback buffer."""
77 21546b1c Iustin Pop
78 21546b1c Iustin Pop
79 21546b1c Iustin Pop
  def GetFeedbackBuf(self):
80 21546b1c Iustin Pop
    """Return the contents of the buffer."""
81 21546b1c Iustin Pop
    return self._feed_buf.getvalue()
82 21546b1c Iustin Pop
83 21546b1c Iustin Pop
  def Feedback(self, msg):
84 21546b1c Iustin Pop
    """Acumulate feedback in our buffer."""
85 21546b1c Iustin Pop
86 21546b1c Iustin Pop
87 d7b47a77 Iustin Pop
    if self.opts.verbose:
88 d7b47a77 Iustin Pop
89 21546b1c Iustin Pop
90 21546b1c Iustin Pop
  def ExecOp(self, op):
91 21546b1c Iustin Pop
    """Execute an opcode and manage the exec buffer."""
92 21546b1c Iustin Pop
93 685ee993 Iustin Pop
    return cli.SubmitOpCode(op)
94 21546b1c Iustin Pop
95 175f44c2 Iustin Pop
  def ParseOptions(self):
96 175f44c2 Iustin Pop
    """Parses the command line options.
97 175f44c2 Iustin Pop
98 175f44c2 Iustin Pop
    In case of command line errors, it will show the usage and exit the
99 175f44c2 Iustin Pop
100 175f44c2 Iustin Pop
101 175f44c2 Iustin Pop
102 175f44c2 Iustin Pop
103 175f44c2 Iustin Pop
    parser = optparse.OptionParser(usage="\n%s" % USAGE,
104 175f44c2 Iustin Pop
                                   version="%%prog (ganeti) %s" %
105 175f44c2 Iustin Pop
106 175f44c2 Iustin Pop
107 175f44c2 Iustin Pop
108 175f44c2 Iustin Pop
    parser.add_option("-o", "--os", dest="os", default=None,
109 175f44c2 Iustin Pop
                      help="OS to use during burnin",
110 175f44c2 Iustin Pop
111 175f44c2 Iustin Pop
    parser.add_option("--os-size", dest="os_size", help="Disk size",
112 175f44c2 Iustin Pop
                      default=4 * 1024, type="unit", metavar="<size>")
113 175f44c2 Iustin Pop
    parser.add_option("--swap-size", dest="swap_size", help="Swap size",
114 175f44c2 Iustin Pop
                      default=4 * 1024, type="unit", metavar="<size>")
115 5e767b34 Iustin Pop
    parser.add_option("--mem-size", dest="mem_size", help="Memory size",
116 5e767b34 Iustin Pop
                      default=128, type="unit", metavar="<size>")
117 175f44c2 Iustin Pop
    parser.add_option("-v", "--verbose",
118 175f44c2 Iustin Pop
                      action="store_true", dest="verbose", default=False,
119 175f44c2 Iustin Pop
                      help="print command execution messages to stdout")
120 175f44c2 Iustin Pop
    parser.add_option("--no-replace1", dest="do_replace1",
121 175f44c2 Iustin Pop
                      help="Skip disk replacement with the same secondary",
122 175f44c2 Iustin Pop
                      action="store_false", default=True)
123 175f44c2 Iustin Pop
    parser.add_option("--no-replace2", dest="do_replace2",
124 175f44c2 Iustin Pop
                      help="Skip disk replacement with a different secondary",
125 175f44c2 Iustin Pop
                      action="store_false", default=True)
126 175f44c2 Iustin Pop
    parser.add_option("--no-failover", dest="do_failover",
127 175f44c2 Iustin Pop
                      help="Skip instance failovers", action="store_false",
128 175f44c2 Iustin Pop
129 bd5e77f9 Guido Trotter
    parser.add_option("--no-importexport", dest="do_importexport",
130 bd5e77f9 Guido Trotter
                      help="Skip instance export/import", action="store_false",
131 bd5e77f9 Guido Trotter
132 d4844f0f Guido Trotter
    parser.add_option("--no-startstop", dest="do_startstop",
133 d4844f0f Guido Trotter
                      help="Skip instance stop/start", action="store_false",
134 d4844f0f Guido Trotter
135 054a8696 Manuel Franceschini
    parser.add_option("--rename", dest="rename", default=None,
136 054a8696 Manuel Franceschini
                      help="Give one unused instance name which is taken"
137 054a8696 Manuel Franceschini
                           " to start the renaming sequence",
138 054a8696 Manuel Franceschini
139 175f44c2 Iustin Pop
    parser.add_option("-t", "--disk-template", dest="disk_template",
140 2f505cb5 Manuel Franceschini
                      choices=("diskless", "file", "plain", "drbd"),
141 f9193417 Iustin Pop
142 2f505cb5 Manuel Franceschini
                      help="Disk template (diskless, file, plain or drbd)"
143 2f505cb5 Manuel Franceschini
                            " [drbd]")
144 175f44c2 Iustin Pop
    parser.add_option("-n", "--nodes", dest="nodes", default="",
145 175f44c2 Iustin Pop
                      help="Comma separated list of nodes to perform"
146 175f44c2 Iustin Pop
                      " the burnin on (defaults to all nodes)")
147 b91bde14 Iustin Pop
    parser.add_option("--iallocator", dest="iallocator",
148 b91bde14 Iustin Pop
                      default=None, type="string",
149 b91bde14 Iustin Pop
                      help="Perform the allocation using an iallocator"
150 b91bde14 Iustin Pop
                      " instead of fixed node spread (node restrictions no"
151 b91bde14 Iustin Pop
                      " longer apply, therefore -n/--nodes must not be used")
152 175f44c2 Iustin Pop
153 175f44c2 Iustin Pop
    options, args = parser.parse_args()
154 175f44c2 Iustin Pop
    if len(args) < 1 or options.os is None:
155 175f44c2 Iustin Pop
156 175f44c2 Iustin Pop
157 f9193417 Iustin Pop
    supported_disk_templates = (constants.DT_DISKLESS,
158 2f505cb5 Manuel Franceschini
159 f9193417 Iustin Pop
160 12c3449a Michael Hanselmann
161 12c3449a Michael Hanselmann
    if options.disk_template not in supported_disk_templates:
162 21546b1c Iustin Pop
      Log("Unknown disk template '%s'" % options.disk_template)
163 175f44c2 Iustin Pop
164 175f44c2 Iustin Pop
165 b91bde14 Iustin Pop
    if options.nodes and options.iallocator:
166 b91bde14 Iustin Pop
      Log("Give either the nodes option or the iallocator option, not both")
167 b91bde14 Iustin Pop
168 b91bde14 Iustin Pop
169 175f44c2 Iustin Pop
    self.opts = options
170 175f44c2 Iustin Pop
    self.instances = args
171 175f44c2 Iustin Pop
172 175f44c2 Iustin Pop
  def GetState(self):
173 175f44c2 Iustin Pop
    """Read the cluster state from the config."""
174 175f44c2 Iustin Pop
    if self.opts.nodes:
175 175f44c2 Iustin Pop
      names = self.opts.nodes.split(",")
176 175f44c2 Iustin Pop
177 175f44c2 Iustin Pop
      names = []
178 175f44c2 Iustin Pop
179 175f44c2 Iustin Pop
      op = opcodes.OpQueryNodes(output_fields=["name"], names=names)
180 21546b1c Iustin Pop
      result = self.ExecOp(op)
181 175f44c2 Iustin Pop
    except errors.GenericError, err:
182 175f44c2 Iustin Pop
      err_code, msg = cli.FormatError(err)
183 21546b1c Iustin Pop
184 175f44c2 Iustin Pop
185 175f44c2 Iustin Pop
    self.nodes = [data[0] for data in result]
186 175f44c2 Iustin Pop
187 1f9430d6 Iustin Pop
    result = self.ExecOp(opcodes.OpDiagnoseOS(output_fields=["name", "valid"],
188 1f9430d6 Iustin Pop
189 175f44c2 Iustin Pop
190 175f44c2 Iustin Pop
    if not result:
191 21546b1c Iustin Pop
      Log("Can't get the OS list")
192 175f44c2 Iustin Pop
193 175f44c2 Iustin Pop
194 175f44c2 Iustin Pop
    # filter non-valid OS-es
195 1f9430d6 Iustin Pop
    os_set = [val[0] for val in result if val[1]]
196 175f44c2 Iustin Pop
197 175f44c2 Iustin Pop
    if self.opts.os not in os_set:
198 21546b1c Iustin Pop
      Log("OS '%s' not found" % self.opts.os)
199 175f44c2 Iustin Pop
200 175f44c2 Iustin Pop
201 175f44c2 Iustin Pop
  def CreateInstances(self):
202 175f44c2 Iustin Pop
    """Create the given instances.
203 175f44c2 Iustin Pop
204 175f44c2 Iustin Pop
205 175f44c2 Iustin Pop
    self.to_rem = []
206 175f44c2 Iustin Pop
    mytor = izip(cycle(self.nodes),
207 175f44c2 Iustin Pop
                 islice(cycle(self.nodes), 1, None),
208 175f44c2 Iustin Pop
209 175f44c2 Iustin Pop
    for pnode, snode, instance in mytor:
210 b91bde14 Iustin Pop
      if self.opts.iallocator:
211 b91bde14 Iustin Pop
        pnode = snode = None
212 6d54548e Guido Trotter
        Log("- Add instance %s (iallocator: %s)" %
213 6d54548e Guido Trotter
              (instance, self.opts.iallocator))
214 6d54548e Guido Trotter
      elif self.opts.disk_template not in constants.DTS_NET_MIRROR:
215 6d54548e Guido Trotter
        snode = None
216 6d54548e Guido Trotter
        Log("- Add instance %s on node %s" % (instance, pnode))
217 6d54548e Guido Trotter
218 6d54548e Guido Trotter
        Log("- Add instance %s on nodes %s/%s" % (instance, pnode, snode))
219 6d54548e Guido Trotter
220 175f44c2 Iustin Pop
      op = opcodes.OpCreateInstance(instance_name=instance,
221 5e767b34 Iustin Pop
222 175f44c2 Iustin Pop
223 175f44c2 Iustin Pop
224 175f44c2 Iustin Pop
225 a8083063 Iustin Pop
226 175f44c2 Iustin Pop
227 175f44c2 Iustin Pop
228 175f44c2 Iustin Pop
229 175f44c2 Iustin Pop
230 a8083063 Iustin Pop
231 e9f745aa Iustin Pop
232 4501af56 Iustin Pop
233 4501af56 Iustin Pop
234 4501af56 Iustin Pop
235 25c5878d Alexander Schreiber
236 2f505cb5 Manuel Franceschini
237 2f505cb5 Manuel Franceschini
238 b91bde14 Iustin Pop
239 b91bde14 Iustin Pop
240 21546b1c Iustin Pop
241 175f44c2 Iustin Pop
242 175f44c2 Iustin Pop
243 175f44c2 Iustin Pop
  def ReplaceDisks1D8(self):
244 175f44c2 Iustin Pop
    """Replace disks on primary and secondary for drbd8."""
245 175f44c2 Iustin Pop
    for instance in self.instances:
246 175f44c2 Iustin Pop
      for mode in constants.REPLACE_DISK_SEC, constants.REPLACE_DISK_PRI:
247 175f44c2 Iustin Pop
        op = opcodes.OpReplaceDisks(instance_name=instance,
248 175f44c2 Iustin Pop
249 175f44c2 Iustin Pop
                                    disks=["sda", "sdb"])
250 21546b1c Iustin Pop
        Log("- Replace disks (%s) for instance %s" % (mode, instance))
251 21546b1c Iustin Pop
252 175f44c2 Iustin Pop
253 175f44c2 Iustin Pop
  def ReplaceDisks2(self):
254 175f44c2 Iustin Pop
    """Replace secondary node."""
255 f9193417 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
256 175f44c2 Iustin Pop
257 175f44c2 Iustin Pop
    mytor = izip(islice(cycle(self.nodes), 2, None),
258 175f44c2 Iustin Pop
259 175f44c2 Iustin Pop
    for tnode, instance in mytor:
260 b6e82a65 Iustin Pop
      if self.opts.iallocator:
261 b6e82a65 Iustin Pop
        tnode = None
262 175f44c2 Iustin Pop
      op = opcodes.OpReplaceDisks(instance_name=instance,
263 175f44c2 Iustin Pop
264 175f44c2 Iustin Pop
265 b6e82a65 Iustin Pop
266 175f44c2 Iustin Pop
                                  disks=["sda", "sdb"])
267 21546b1c Iustin Pop
      Log("- Replace secondary (%s) for instance %s" % (mode, instance))
268 21546b1c Iustin Pop
269 175f44c2 Iustin Pop
270 175f44c2 Iustin Pop
  def Failover(self):
271 175f44c2 Iustin Pop
    """Failover the instances."""
272 175f44c2 Iustin Pop
273 175f44c2 Iustin Pop
    for instance in self.instances:
274 175f44c2 Iustin Pop
      op = opcodes.OpFailoverInstance(instance_name=instance,
275 175f44c2 Iustin Pop
276 175f44c2 Iustin Pop
277 21546b1c Iustin Pop
      Log("- Failover instance %s" % (instance))
278 21546b1c Iustin Pop
279 175f44c2 Iustin Pop
280 bd5e77f9 Guido Trotter
  def ImportExport(self):
281 bd5e77f9 Guido Trotter
    """Export the instance, delete it, and import it back.
282 bd5e77f9 Guido Trotter
283 bd5e77f9 Guido Trotter
284 bd5e77f9 Guido Trotter
285 bd5e77f9 Guido Trotter
    mytor = izip(cycle(self.nodes),
286 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 1, None),
287 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 2, None),
288 bd5e77f9 Guido Trotter
289 bd5e77f9 Guido Trotter
290 bd5e77f9 Guido Trotter
    for pnode, snode, enode, instance in mytor:
291 bd5e77f9 Guido Trotter
      exp_op = opcodes.OpExportInstance(instance_name=instance,
292 bd5e77f9 Guido Trotter
293 bd5e77f9 Guido Trotter
294 bd5e77f9 Guido Trotter
      rem_op = opcodes.OpRemoveInstance(instance_name=instance)
295 bd5e77f9 Guido Trotter
      nam_op = opcodes.OpQueryInstances(output_fields=["name"],
296 bd5e77f9 Guido Trotter
297 bd5e77f9 Guido Trotter
      full_name = self.ExecOp(nam_op)[0][0]
298 bd5e77f9 Guido Trotter
      imp_dir = os.path.join(constants.EXPORT_DIR, full_name)
299 bd5e77f9 Guido Trotter
      imp_op = opcodes.OpCreateInstance(instance_name=instance,
300 bd5e77f9 Guido Trotter
301 bd5e77f9 Guido Trotter
302 bd5e77f9 Guido Trotter
303 bd5e77f9 Guido Trotter
304 bd5e77f9 Guido Trotter
305 bd5e77f9 Guido Trotter
306 bd5e77f9 Guido Trotter
307 bd5e77f9 Guido Trotter
308 bd5e77f9 Guido Trotter
309 bd5e77f9 Guido Trotter
310 bd5e77f9 Guido Trotter
311 bd5e77f9 Guido Trotter
312 bd5e77f9 Guido Trotter
313 96bb2f71 Manuel Franceschini
314 96bb2f71 Manuel Franceschini
315 96bb2f71 Manuel Franceschini
316 4a7ff493 Guido Trotter
      erem_op = opcodes.OpRemoveExport(instance_name=instance)
317 bd5e77f9 Guido Trotter
318 bd5e77f9 Guido Trotter
      Log("- Export instance %s to node %s" % (instance, enode))
319 bd5e77f9 Guido Trotter
320 bd5e77f9 Guido Trotter
      Log("- Remove instance %s" % (instance))
321 bd5e77f9 Guido Trotter
322 bd5e77f9 Guido Trotter
323 bd5e77f9 Guido Trotter
      Log("- Import instance %s from node %s to node %s" %
324 bd5e77f9 Guido Trotter
          (instance, enode, pnode))
325 bd5e77f9 Guido Trotter
326 4a7ff493 Guido Trotter
      Log("- Remove export of instance %s" % (instance))
327 4a7ff493 Guido Trotter
328 4a7ff493 Guido Trotter
329 bd5e77f9 Guido Trotter
330 bd5e77f9 Guido Trotter
331 054a8696 Manuel Franceschini
  def StopInstance(self, instance):
332 054a8696 Manuel Franceschini
    """Stop given instance."""
333 054a8696 Manuel Franceschini
    op = opcodes.OpShutdownInstance(instance_name=instance)
334 054a8696 Manuel Franceschini
    Log("- Shutdown instance %s" % instance)
335 054a8696 Manuel Franceschini
336 054a8696 Manuel Franceschini
337 054a8696 Manuel Franceschini
  def StartInstance(self, instance):
338 054a8696 Manuel Franceschini
    """Start given instance."""
339 054a8696 Manuel Franceschini
    op = opcodes.OpStartupInstance(instance_name=instance, force=False)
340 054a8696 Manuel Franceschini
    Log("- Start instance %s" % instance)
341 054a8696 Manuel Franceschini
342 054a8696 Manuel Franceschini
343 054a8696 Manuel Franceschini
  def RenameInstance(self, instance, instance_new):
344 054a8696 Manuel Franceschini
    """Rename instance."""
345 054a8696 Manuel Franceschini
    op = opcodes.OpRenameInstance(instance_name=instance,
346 054a8696 Manuel Franceschini
347 054a8696 Manuel Franceschini
    Log("- Rename instance %s to %s" % (instance, instance_new))
348 054a8696 Manuel Franceschini
349 054a8696 Manuel Franceschini
350 175f44c2 Iustin Pop
  def StopStart(self):
351 175f44c2 Iustin Pop
    """Stop/start the instances."""
352 175f44c2 Iustin Pop
    for instance in self.instances:
353 054a8696 Manuel Franceschini
354 054a8696 Manuel Franceschini
355 175f44c2 Iustin Pop
356 175f44c2 Iustin Pop
  def Remove(self):
357 175f44c2 Iustin Pop
    """Remove the instances."""
358 175f44c2 Iustin Pop
    for instance in self.to_rem:
359 175f44c2 Iustin Pop
      op = opcodes.OpRemoveInstance(instance_name=instance)
360 21546b1c Iustin Pop
      Log("- Remove instance %s" % instance)
361 21546b1c Iustin Pop
362 175f44c2 Iustin Pop
363 054a8696 Manuel Franceschini
364 054a8696 Manuel Franceschini
  def Rename(self):
365 054a8696 Manuel Franceschini
    """Rename the instances."""
366 054a8696 Manuel Franceschini
    rename = self.opts.rename
367 054a8696 Manuel Franceschini
    for instance in self.instances:
368 054a8696 Manuel Franceschini
369 054a8696 Manuel Franceschini
      self.RenameInstance(instance, rename)
370 054a8696 Manuel Franceschini
371 054a8696 Manuel Franceschini
372 054a8696 Manuel Franceschini
      self.RenameInstance(rename, instance)
373 054a8696 Manuel Franceschini
374 054a8696 Manuel Franceschini
375 175f44c2 Iustin Pop
  def BurninCluster(self):
376 175f44c2 Iustin Pop
    """Test a cluster intensively.
377 175f44c2 Iustin Pop
378 175f44c2 Iustin Pop
    This will create instances and then start/stop/failover them.
379 175f44c2 Iustin Pop
    It is safe for existing instances but could impact performance.
380 175f44c2 Iustin Pop
381 175f44c2 Iustin Pop
382 175f44c2 Iustin Pop
383 175f44c2 Iustin Pop
    opts = self.opts
384 175f44c2 Iustin Pop
385 21546b1c Iustin Pop
    Log("- Testing global parameters")
386 175f44c2 Iustin Pop
387 bd249e2f Iustin Pop
    if (len(self.nodes) == 1 and
388 2f505cb5 Manuel Franceschini
        opts.disk_template not in (constants.DT_DISKLESS, constants.DT_PLAIN,
389 2f505cb5 Manuel Franceschini
390 21546b1c Iustin Pop
      Log("When one node is available/selected the disk template must"
391 2f505cb5 Manuel Franceschini
          " be 'diskless', 'file' or 'plain'")
392 175f44c2 Iustin Pop
393 175f44c2 Iustin Pop
394 21546b1c Iustin Pop
    has_err = True
395 175f44c2 Iustin Pop
396 175f44c2 Iustin Pop
397 175f44c2 Iustin Pop
      if opts.do_replace1 and opts.disk_template in constants.DTS_NET_MIRROR:
398 f9193417 Iustin Pop
399 175f44c2 Iustin Pop
      if (opts.do_replace2 and len(self.nodes) > 2 and
400 175f44c2 Iustin Pop
          opts.disk_template in constants.DTS_NET_MIRROR) :
401 175f44c2 Iustin Pop
402 175f44c2 Iustin Pop
403 175f44c2 Iustin Pop
      if opts.do_failover and opts.disk_template in constants.DTS_NET_MIRROR:
404 175f44c2 Iustin Pop
405 175f44c2 Iustin Pop
406 bd5e77f9 Guido Trotter
      if opts.do_importexport:
407 bd5e77f9 Guido Trotter
408 bd5e77f9 Guido Trotter
409 d4844f0f Guido Trotter
      if opts.do_startstop:
410 d4844f0f Guido Trotter
411 d4844f0f Guido Trotter
412 054a8696 Manuel Franceschini
      if opts.rename:
413 054a8696 Manuel Franceschini
414 054a8696 Manuel Franceschini
415 21546b1c Iustin Pop
      has_err = False
416 175f44c2 Iustin Pop
417 21546b1c Iustin Pop
      if has_err:
418 21546b1c Iustin Pop
        Log("Error detected: opcode buffer follows:\n\n")
419 21546b1c Iustin Pop
420 21546b1c Iustin Pop
421 175f44c2 Iustin Pop
422 175f44c2 Iustin Pop
423 175f44c2 Iustin Pop
    return 0
424 a8083063 Iustin Pop
425 01b69ec5 Michael Hanselmann
426 a8083063 Iustin Pop
def main():
427 3ecf6786 Iustin Pop
  """Main function"""
428 3ecf6786 Iustin Pop
429 175f44c2 Iustin Pop
  burner = Burner()
430 a4af651e Iustin Pop
  return burner.BurninCluster()
431 a8083063 Iustin Pop
432 01b69ec5 Michael Hanselmann
433 a8083063 Iustin Pop
if __name__ == "__main__":
434 3ecf6786 Iustin Pop