Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ 99bdd139

History | View | Annotate | Download (26.5 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
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 e2212007 Iustin Pop
import time
30 5178f1bc Iustin Pop
import socket
31 5178f1bc Iustin Pop
import urllib2
32 5178f1bc Iustin Pop
import errno
33 175f44c2 Iustin Pop
from itertools import izip, islice, cycle
34 21546b1c Iustin Pop
from cStringIO import StringIO
35 a8083063 Iustin Pop
36 a8083063 Iustin Pop
from ganeti import opcodes
37 a8083063 Iustin Pop
from ganeti import mcpu
38 a8083063 Iustin Pop
from ganeti import constants
39 a8083063 Iustin Pop
from ganeti import cli
40 9f13fc7a Iustin Pop
from ganeti import errors
41 9f13fc7a Iustin Pop
from ganeti import utils
42 a8083063 Iustin Pop
43 01b69ec5 Michael Hanselmann
44 9f13fc7a Iustin Pop
USAGE = ("\tburnin -o OS_NAME [options...] instance_name ...")
45 a8083063 Iustin Pop
46 01b69ec5 Michael Hanselmann
47 5178f1bc Iustin Pop
class InstanceDown(Exception):
48 5178f1bc Iustin Pop
  """The checked instance was not up"""
49 5178f1bc Iustin Pop
50 5178f1bc Iustin Pop
51 a8083063 Iustin Pop
def Usage():
52 a8083063 Iustin Pop
  """Shows program usage information and exits the program."""
53 a8083063 Iustin Pop
54 a8083063 Iustin Pop
  print >> sys.stderr, "Usage:"
55 a8083063 Iustin Pop
  print >> sys.stderr, USAGE
56 a8083063 Iustin Pop
  sys.exit(2)
57 a8083063 Iustin Pop
58 01b69ec5 Michael Hanselmann
59 836d59d7 Iustin Pop
def Log(msg, indent=0):
60 3ecf6786 Iustin Pop
  """Simple function that prints out its argument.
61 3ecf6786 Iustin Pop
62 3ecf6786 Iustin Pop
  """
63 836d59d7 Iustin Pop
  headers = {
64 836d59d7 Iustin Pop
    0: "- ",
65 836d59d7 Iustin Pop
    1: "* ",
66 836d59d7 Iustin Pop
    2: ""
67 836d59d7 Iustin Pop
    }
68 836d59d7 Iustin Pop
  sys.stdout.write("%*s%s%s\n" % (2*indent, "",
69 836d59d7 Iustin Pop
                                   headers.get(indent, "  "), msg))
70 84cc52ab Michael Hanselmann
  sys.stdout.flush()
71 a8083063 Iustin Pop
72 836d59d7 Iustin Pop
def Err(msg, exit_code=1):
73 836d59d7 Iustin Pop
  """Simple error logging that prints to stderr.
74 836d59d7 Iustin Pop
75 836d59d7 Iustin Pop
  """
76 836d59d7 Iustin Pop
  sys.stderr.write(msg + "\n")
77 836d59d7 Iustin Pop
  sys.stderr.flush()
78 836d59d7 Iustin Pop
  sys.exit(exit_code)
79 01b69ec5 Michael Hanselmann
80 175f44c2 Iustin Pop
class Burner(object):
81 175f44c2 Iustin Pop
  """Burner class."""
82 175f44c2 Iustin Pop
83 175f44c2 Iustin Pop
  def __init__(self):
84 175f44c2 Iustin Pop
    """Constructor."""
85 82d9caef Iustin Pop
    utils.SetupLogging(constants.LOG_BURNIN, debug=False, stderr_logging=True)
86 21546b1c Iustin Pop
    self._feed_buf = StringIO()
87 175f44c2 Iustin Pop
    self.nodes = []
88 175f44c2 Iustin Pop
    self.instances = []
89 175f44c2 Iustin Pop
    self.to_rem = []
90 175f44c2 Iustin Pop
    self.opts = None
91 ec5c88dc Iustin Pop
    self.cl = cli.GetClient()
92 175f44c2 Iustin Pop
    self.ParseOptions()
93 175f44c2 Iustin Pop
    self.GetState()
94 175f44c2 Iustin Pop
95 21546b1c Iustin Pop
  def ClearFeedbackBuf(self):
96 21546b1c Iustin Pop
    """Clear the feedback buffer."""
97 21546b1c Iustin Pop
    self._feed_buf.truncate(0)
98 21546b1c Iustin Pop
99 21546b1c Iustin Pop
  def GetFeedbackBuf(self):
100 21546b1c Iustin Pop
    """Return the contents of the buffer."""
101 21546b1c Iustin Pop
    return self._feed_buf.getvalue()
102 21546b1c Iustin Pop
103 21546b1c Iustin Pop
  def Feedback(self, msg):
104 21546b1c Iustin Pop
    """Acumulate feedback in our buffer."""
105 e17188f4 Iustin Pop
    self._feed_buf.write("%s %s\n" % (time.ctime(utils.MergeTime(msg[0])),
106 e17188f4 Iustin Pop
                                      msg[2]))
107 d7b47a77 Iustin Pop
    if self.opts.verbose:
108 836d59d7 Iustin Pop
      Log(msg, indent=3)
109 21546b1c Iustin Pop
110 21546b1c Iustin Pop
  def ExecOp(self, op):
111 21546b1c Iustin Pop
    """Execute an opcode and manage the exec buffer."""
112 21546b1c Iustin Pop
    self.ClearFeedbackBuf()
113 ec5c88dc Iustin Pop
    return cli.SubmitOpCode(op, feedback_fn=self.Feedback, cl=self.cl)
114 ec5c88dc Iustin Pop
115 ec5c88dc Iustin Pop
  def ExecJobSet(self, jobs):
116 ec5c88dc Iustin Pop
    """Execute a set of jobs and return once all are done.
117 ec5c88dc Iustin Pop
118 ec5c88dc Iustin Pop
    The method will return the list of results, if all jobs are
119 ec5c88dc Iustin Pop
    successfull. Otherwise, OpExecError will be raised from within
120 ec5c88dc Iustin Pop
    cli.py.
121 ec5c88dc Iustin Pop
122 ec5c88dc Iustin Pop
    """
123 ec5c88dc Iustin Pop
    self.ClearFeedbackBuf()
124 ec5c88dc Iustin Pop
    job_ids = [cli.SendJob(job, cl=self.cl) for job in jobs]
125 836d59d7 Iustin Pop
    Log("Submitted job IDs %s" % ", ".join(job_ids), indent=1)
126 ec5c88dc Iustin Pop
    results = []
127 ec5c88dc Iustin Pop
    for jid in job_ids:
128 836d59d7 Iustin Pop
      Log("Waiting for job %s" % jid, indent=2)
129 ec5c88dc Iustin Pop
      results.append(cli.PollJob(jid, cl=self.cl, feedback_fn=self.Feedback))
130 ec5c88dc Iustin Pop
131 ec5c88dc Iustin Pop
    return results
132 21546b1c Iustin Pop
133 175f44c2 Iustin Pop
  def ParseOptions(self):
134 175f44c2 Iustin Pop
    """Parses the command line options.
135 175f44c2 Iustin Pop
136 175f44c2 Iustin Pop
    In case of command line errors, it will show the usage and exit the
137 175f44c2 Iustin Pop
    program.
138 175f44c2 Iustin Pop
139 175f44c2 Iustin Pop
    """
140 175f44c2 Iustin Pop
141 175f44c2 Iustin Pop
    parser = optparse.OptionParser(usage="\n%s" % USAGE,
142 175f44c2 Iustin Pop
                                   version="%%prog (ganeti) %s" %
143 175f44c2 Iustin Pop
                                   constants.RELEASE_VERSION,
144 175f44c2 Iustin Pop
                                   option_class=cli.CliOption)
145 175f44c2 Iustin Pop
146 175f44c2 Iustin Pop
    parser.add_option("-o", "--os", dest="os", default=None,
147 175f44c2 Iustin Pop
                      help="OS to use during burnin",
148 175f44c2 Iustin Pop
                      metavar="<OS>")
149 08db7c5c Iustin Pop
    parser.add_option("--disk-size", dest="disk_size",
150 08db7c5c Iustin Pop
                      help="Disk size (determines disk count)",
151 08db7c5c Iustin Pop
                      default="128m", type="string", metavar="<size,size,...>")
152 08db7c5c Iustin Pop
    parser.add_option("--disk-growth", dest="disk_growth", help="Disk growth",
153 f768530c Iustin Pop
                      default="128m", type="string", metavar="<size,size,...>")
154 5e767b34 Iustin Pop
    parser.add_option("--mem-size", dest="mem_size", help="Memory size",
155 5e767b34 Iustin Pop
                      default=128, type="unit", metavar="<size>")
156 175f44c2 Iustin Pop
    parser.add_option("-v", "--verbose",
157 175f44c2 Iustin Pop
                      action="store_true", dest="verbose", default=False,
158 175f44c2 Iustin Pop
                      help="print command execution messages to stdout")
159 175f44c2 Iustin Pop
    parser.add_option("--no-replace1", dest="do_replace1",
160 175f44c2 Iustin Pop
                      help="Skip disk replacement with the same secondary",
161 175f44c2 Iustin Pop
                      action="store_false", default=True)
162 175f44c2 Iustin Pop
    parser.add_option("--no-replace2", dest="do_replace2",
163 175f44c2 Iustin Pop
                      help="Skip disk replacement with a different secondary",
164 175f44c2 Iustin Pop
                      action="store_false", default=True)
165 175f44c2 Iustin Pop
    parser.add_option("--no-failover", dest="do_failover",
166 175f44c2 Iustin Pop
                      help="Skip instance failovers", action="store_false",
167 175f44c2 Iustin Pop
                      default=True)
168 99bdd139 Iustin Pop
    parser.add_option("--no-migrate", dest="do_migrate",
169 99bdd139 Iustin Pop
                      help="Skip instance live migration",
170 99bdd139 Iustin Pop
                      action="store_false", default=True)
171 bd5e77f9 Guido Trotter
    parser.add_option("--no-importexport", dest="do_importexport",
172 bd5e77f9 Guido Trotter
                      help="Skip instance export/import", action="store_false",
173 bd5e77f9 Guido Trotter
                      default=True)
174 d4844f0f Guido Trotter
    parser.add_option("--no-startstop", dest="do_startstop",
175 d4844f0f Guido Trotter
                      help="Skip instance stop/start", action="store_false",
176 d4844f0f Guido Trotter
                      default=True)
177 00f91f29 Iustin Pop
    parser.add_option("--no-reinstall", dest="do_reinstall",
178 00f91f29 Iustin Pop
                      help="Skip instance reinstall", action="store_false",
179 00f91f29 Iustin Pop
                      default=True)
180 00f91f29 Iustin Pop
    parser.add_option("--no-reboot", dest="do_reboot",
181 00f91f29 Iustin Pop
                      help="Skip instance reboot", action="store_false",
182 00f91f29 Iustin Pop
                      default=True)
183 90e722d1 Iustin Pop
    parser.add_option("--no-activate-disks", dest="do_activate_disks",
184 90e722d1 Iustin Pop
                      help="Skip disk activation/deactivation",
185 90e722d1 Iustin Pop
                      action="store_false", default=True)
186 5c22d16e Iustin Pop
    parser.add_option("--no-add-disks", dest="do_addremove_disks",
187 5c22d16e Iustin Pop
                      help="Skip disk addition/removal",
188 5c22d16e Iustin Pop
                      action="store_false", default=True)
189 5c22d16e Iustin Pop
    parser.add_option("--no-add-nics", dest="do_addremove_nics",
190 5c22d16e Iustin Pop
                      help="Skip NIC addition/removal",
191 5c22d16e Iustin Pop
                      action="store_false", default=True)
192 b518a14a Iustin Pop
    parser.add_option("--no-nics", dest="nics",
193 b518a14a Iustin Pop
                      help="No network interfaces", action="store_const",
194 b518a14a Iustin Pop
                      const=[], default=[{}])
195 054a8696 Manuel Franceschini
    parser.add_option("--rename", dest="rename", default=None,
196 054a8696 Manuel Franceschini
                      help="Give one unused instance name which is taken"
197 054a8696 Manuel Franceschini
                           " to start the renaming sequence",
198 054a8696 Manuel Franceschini
                      metavar="<instance_name>")
199 175f44c2 Iustin Pop
    parser.add_option("-t", "--disk-template", dest="disk_template",
200 2f505cb5 Manuel Franceschini
                      choices=("diskless", "file", "plain", "drbd"),
201 f9193417 Iustin Pop
                      default="drbd",
202 2f505cb5 Manuel Franceschini
                      help="Disk template (diskless, file, plain or drbd)"
203 2f505cb5 Manuel Franceschini
                            " [drbd]")
204 175f44c2 Iustin Pop
    parser.add_option("-n", "--nodes", dest="nodes", default="",
205 175f44c2 Iustin Pop
                      help="Comma separated list of nodes to perform"
206 175f44c2 Iustin Pop
                      " the burnin on (defaults to all nodes)")
207 b91bde14 Iustin Pop
    parser.add_option("--iallocator", dest="iallocator",
208 b91bde14 Iustin Pop
                      default=None, type="string",
209 b91bde14 Iustin Pop
                      help="Perform the allocation using an iallocator"
210 b91bde14 Iustin Pop
                      " instead of fixed node spread (node restrictions no"
211 b91bde14 Iustin Pop
                      " longer apply, therefore -n/--nodes must not be used")
212 ec5c88dc Iustin Pop
    parser.add_option("-p", "--parallel", default=False, action="store_true",
213 ec5c88dc Iustin Pop
                      dest="parallel",
214 ec5c88dc Iustin Pop
                      help="Enable parallelization of some operations in"
215 ec5c88dc Iustin Pop
                      " order to speed burnin or to test granular locking")
216 5178f1bc Iustin Pop
    parser.add_option("--net-timeout", default=15, type="int",
217 5178f1bc Iustin Pop
                      dest="net_timeout",
218 5178f1bc Iustin Pop
                      help="The instance check network timeout in seconds"
219 5178f1bc Iustin Pop
                      " (defaults to 15 seconds)")
220 5178f1bc Iustin Pop
    parser.add_option("-C", "--http-check", default=False, action="store_true",
221 5178f1bc Iustin Pop
                      dest="http_check",
222 5178f1bc Iustin Pop
                      help="Enable checking of instance status via http,"
223 5178f1bc Iustin Pop
                      " looking for /hostname.txt that should contain the"
224 5178f1bc Iustin Pop
                      " name of the instance")
225 5178f1bc Iustin Pop
226 175f44c2 Iustin Pop
227 175f44c2 Iustin Pop
    options, args = parser.parse_args()
228 175f44c2 Iustin Pop
    if len(args) < 1 or options.os is None:
229 175f44c2 Iustin Pop
      Usage()
230 175f44c2 Iustin Pop
231 f9193417 Iustin Pop
    supported_disk_templates = (constants.DT_DISKLESS,
232 2f505cb5 Manuel Franceschini
                                constants.DT_FILE,
233 f9193417 Iustin Pop
                                constants.DT_PLAIN,
234 12c3449a Michael Hanselmann
                                constants.DT_DRBD8)
235 12c3449a Michael Hanselmann
    if options.disk_template not in supported_disk_templates:
236 836d59d7 Iustin Pop
      Err("Unknown disk template '%s'" % options.disk_template)
237 175f44c2 Iustin Pop
238 b518a14a Iustin Pop
    if options.disk_template == constants.DT_DISKLESS:
239 b518a14a Iustin Pop
      disk_size = disk_growth = []
240 5178f1bc Iustin Pop
      options.do_addremove_disks = False
241 b518a14a Iustin Pop
    else:
242 b518a14a Iustin Pop
      disk_size = [utils.ParseUnit(v) for v in options.disk_size.split(",")]
243 b518a14a Iustin Pop
      disk_growth = [utils.ParseUnit(v)
244 b518a14a Iustin Pop
                     for v in options.disk_growth.split(",")]
245 b518a14a Iustin Pop
      if len(disk_growth) != len(disk_size):
246 836d59d7 Iustin Pop
        Err("Wrong disk sizes/growth combination")
247 08db7c5c Iustin Pop
    if ((disk_size and options.disk_template == constants.DT_DISKLESS) or
248 08db7c5c Iustin Pop
        (not disk_size and options.disk_template != constants.DT_DISKLESS)):
249 836d59d7 Iustin Pop
      Err("Wrong disk count/disk template combination")
250 08db7c5c Iustin Pop
251 08db7c5c Iustin Pop
    self.disk_size = disk_size
252 08db7c5c Iustin Pop
    self.disk_growth = disk_growth
253 08db7c5c Iustin Pop
    self.disk_count = len(disk_size)
254 08db7c5c Iustin Pop
255 b91bde14 Iustin Pop
    if options.nodes and options.iallocator:
256 836d59d7 Iustin Pop
      Err("Give either the nodes option or the iallocator option, not both")
257 b91bde14 Iustin Pop
258 175f44c2 Iustin Pop
    self.opts = options
259 175f44c2 Iustin Pop
    self.instances = args
260 338e51e8 Iustin Pop
    self.bep = {
261 338e51e8 Iustin Pop
      constants.BE_MEMORY: options.mem_size,
262 338e51e8 Iustin Pop
      constants.BE_VCPUS: 1,
263 338e51e8 Iustin Pop
      }
264 338e51e8 Iustin Pop
    self.hvp = {}
265 175f44c2 Iustin Pop
266 5178f1bc Iustin Pop
    socket.setdefaulttimeout(options.net_timeout)
267 5178f1bc Iustin Pop
268 175f44c2 Iustin Pop
  def GetState(self):
269 175f44c2 Iustin Pop
    """Read the cluster state from the config."""
270 175f44c2 Iustin Pop
    if self.opts.nodes:
271 175f44c2 Iustin Pop
      names = self.opts.nodes.split(",")
272 175f44c2 Iustin Pop
    else:
273 175f44c2 Iustin Pop
      names = []
274 175f44c2 Iustin Pop
    try:
275 729164d0 Iustin Pop
      op = opcodes.OpQueryNodes(output_fields=["name", "offline"], names=names)
276 21546b1c Iustin Pop
      result = self.ExecOp(op)
277 175f44c2 Iustin Pop
    except errors.GenericError, err:
278 175f44c2 Iustin Pop
      err_code, msg = cli.FormatError(err)
279 836d59d7 Iustin Pop
      Err(msg, exit_code=err_code)
280 729164d0 Iustin Pop
    self.nodes = [data[0] for data in result if not data[1]]
281 175f44c2 Iustin Pop
282 1f9430d6 Iustin Pop
    result = self.ExecOp(opcodes.OpDiagnoseOS(output_fields=["name", "valid"],
283 1f9430d6 Iustin Pop
                                              names=[]))
284 175f44c2 Iustin Pop
285 175f44c2 Iustin Pop
    if not result:
286 836d59d7 Iustin Pop
      Err("Can't get the OS list")
287 175f44c2 Iustin Pop
288 175f44c2 Iustin Pop
    # filter non-valid OS-es
289 1f9430d6 Iustin Pop
    os_set = [val[0] for val in result if val[1]]
290 175f44c2 Iustin Pop
291 175f44c2 Iustin Pop
    if self.opts.os not in os_set:
292 836d59d7 Iustin Pop
      Err("OS '%s' not found" % self.opts.os)
293 175f44c2 Iustin Pop
294 175f44c2 Iustin Pop
  def CreateInstances(self):
295 175f44c2 Iustin Pop
    """Create the given instances.
296 175f44c2 Iustin Pop
297 175f44c2 Iustin Pop
    """
298 175f44c2 Iustin Pop
    self.to_rem = []
299 175f44c2 Iustin Pop
    mytor = izip(cycle(self.nodes),
300 175f44c2 Iustin Pop
                 islice(cycle(self.nodes), 1, None),
301 175f44c2 Iustin Pop
                 self.instances)
302 ec5c88dc Iustin Pop
    jobset = []
303 338e51e8 Iustin Pop
304 836d59d7 Iustin Pop
    Log("Creating instances")
305 175f44c2 Iustin Pop
    for pnode, snode, instance in mytor:
306 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
307 b91bde14 Iustin Pop
      if self.opts.iallocator:
308 b91bde14 Iustin Pop
        pnode = snode = None
309 836d59d7 Iustin Pop
        msg = "with iallocator %s" % self.opts.iallocator
310 6d54548e Guido Trotter
      elif self.opts.disk_template not in constants.DTS_NET_MIRROR:
311 6d54548e Guido Trotter
        snode = None
312 836d59d7 Iustin Pop
        msg = "on %s" % pnode
313 6d54548e Guido Trotter
      else:
314 836d59d7 Iustin Pop
        msg = "on %s, %s" % (pnode, snode)
315 836d59d7 Iustin Pop
316 836d59d7 Iustin Pop
      Log(msg, indent=2)
317 6d54548e Guido Trotter
318 175f44c2 Iustin Pop
      op = opcodes.OpCreateInstance(instance_name=instance,
319 08db7c5c Iustin Pop
                                    disks = [ {"size": size}
320 08db7c5c Iustin Pop
                                              for size in self.disk_size],
321 175f44c2 Iustin Pop
                                    disk_template=self.opts.disk_template,
322 b518a14a Iustin Pop
                                    nics=self.opts.nics,
323 a8083063 Iustin Pop
                                    mode=constants.INSTANCE_CREATE,
324 175f44c2 Iustin Pop
                                    os_type=self.opts.os,
325 175f44c2 Iustin Pop
                                    pnode=pnode,
326 175f44c2 Iustin Pop
                                    snode=snode,
327 a8083063 Iustin Pop
                                    start=True,
328 e9f745aa Iustin Pop
                                    ip_check=True,
329 4501af56 Iustin Pop
                                    wait_for_sync=True,
330 2f505cb5 Manuel Franceschini
                                    file_driver="loop",
331 b91bde14 Iustin Pop
                                    file_storage_dir=None,
332 6e2dc934 Alexander Schreiber
                                    iallocator=self.opts.iallocator,
333 338e51e8 Iustin Pop
                                    beparams=self.bep,
334 338e51e8 Iustin Pop
                                    hvparams=self.hvp,
335 338e51e8 Iustin Pop
                                    )
336 6e2dc934 Alexander Schreiber
337 ec5c88dc Iustin Pop
      if self.opts.parallel:
338 ec5c88dc Iustin Pop
        jobset.append([op])
339 ec5c88dc Iustin Pop
        # FIXME: here we should not append to to_rem uncoditionally,
340 ec5c88dc Iustin Pop
        # but only when the job is successful
341 ec5c88dc Iustin Pop
        self.to_rem.append(instance)
342 ec5c88dc Iustin Pop
      else:
343 ec5c88dc Iustin Pop
        self.ExecOp(op)
344 ec5c88dc Iustin Pop
        self.to_rem.append(instance)
345 ec5c88dc Iustin Pop
    if self.opts.parallel:
346 ec5c88dc Iustin Pop
      self.ExecJobSet(jobset)
347 175f44c2 Iustin Pop
348 5178f1bc Iustin Pop
    for instance in self.instances:
349 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
350 5178f1bc Iustin Pop
351 659712c8 Iustin Pop
  def GrowDisks(self):
352 659712c8 Iustin Pop
    """Grow both the os and the swap disks by the requested amount, if any."""
353 836d59d7 Iustin Pop
    Log("Growing disks")
354 659712c8 Iustin Pop
    for instance in self.instances:
355 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
356 08db7c5c Iustin Pop
      for idx, growth in enumerate(self.disk_growth):
357 659712c8 Iustin Pop
        if growth > 0:
358 08db7c5c Iustin Pop
          op = opcodes.OpGrowDisk(instance_name=instance, disk=idx,
359 6605411d Iustin Pop
                                  amount=growth, wait_for_sync=True)
360 836d59d7 Iustin Pop
          Log("increase disk/%s by %s MB" % (idx, growth), indent=2)
361 659712c8 Iustin Pop
          self.ExecOp(op)
362 659712c8 Iustin Pop
363 175f44c2 Iustin Pop
  def ReplaceDisks1D8(self):
364 175f44c2 Iustin Pop
    """Replace disks on primary and secondary for drbd8."""
365 836d59d7 Iustin Pop
    Log("Replacing disks on the same nodes")
366 175f44c2 Iustin Pop
    for instance in self.instances:
367 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
368 175f44c2 Iustin Pop
      for mode in constants.REPLACE_DISK_SEC, constants.REPLACE_DISK_PRI:
369 175f44c2 Iustin Pop
        op = opcodes.OpReplaceDisks(instance_name=instance,
370 175f44c2 Iustin Pop
                                    mode=mode,
371 08db7c5c Iustin Pop
                                    disks=[i for i in range(self.disk_count)])
372 836d59d7 Iustin Pop
        Log("run %s" % mode, indent=2)
373 21546b1c Iustin Pop
        self.ExecOp(op)
374 175f44c2 Iustin Pop
375 175f44c2 Iustin Pop
  def ReplaceDisks2(self):
376 175f44c2 Iustin Pop
    """Replace secondary node."""
377 836d59d7 Iustin Pop
    Log("Changing the secondary node")
378 cfacfd6e Iustin Pop
    mode = constants.REPLACE_DISK_CHG
379 175f44c2 Iustin Pop
380 175f44c2 Iustin Pop
    mytor = izip(islice(cycle(self.nodes), 2, None),
381 175f44c2 Iustin Pop
                 self.instances)
382 175f44c2 Iustin Pop
    for tnode, instance in mytor:
383 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
384 b6e82a65 Iustin Pop
      if self.opts.iallocator:
385 b6e82a65 Iustin Pop
        tnode = None
386 836d59d7 Iustin Pop
        msg = "with iallocator %s" % self.opts.iallocator
387 836d59d7 Iustin Pop
      else:
388 836d59d7 Iustin Pop
        msg = tnode
389 175f44c2 Iustin Pop
      op = opcodes.OpReplaceDisks(instance_name=instance,
390 175f44c2 Iustin Pop
                                  mode=mode,
391 175f44c2 Iustin Pop
                                  remote_node=tnode,
392 b6e82a65 Iustin Pop
                                  iallocator=self.opts.iallocator,
393 08db7c5c Iustin Pop
                                  disks=[i for i in range(self.disk_count)])
394 836d59d7 Iustin Pop
      Log("run %s %s" % (mode, msg), indent=2)
395 21546b1c Iustin Pop
      self.ExecOp(op)
396 175f44c2 Iustin Pop
397 175f44c2 Iustin Pop
  def Failover(self):
398 175f44c2 Iustin Pop
    """Failover the instances."""
399 836d59d7 Iustin Pop
    Log("Failing over instances")
400 175f44c2 Iustin Pop
    for instance in self.instances:
401 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
402 175f44c2 Iustin Pop
      op = opcodes.OpFailoverInstance(instance_name=instance,
403 175f44c2 Iustin Pop
                                      ignore_consistency=False)
404 175f44c2 Iustin Pop
405 21546b1c Iustin Pop
      self.ExecOp(op)
406 5178f1bc Iustin Pop
    for instance in self.instances:
407 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
408 175f44c2 Iustin Pop
409 99bdd139 Iustin Pop
  def Migrate(self):
410 99bdd139 Iustin Pop
    """Migrate the instances."""
411 99bdd139 Iustin Pop
412 99bdd139 Iustin Pop
    for instance in self.instances:
413 99bdd139 Iustin Pop
      op = opcodes.OpMigrateInstance(instance_name=instance, live=True,
414 99bdd139 Iustin Pop
                                     cleanup=False)
415 99bdd139 Iustin Pop
416 99bdd139 Iustin Pop
      Log("- Migrate instance %s" % (instance))
417 99bdd139 Iustin Pop
      self.ExecOp(op)
418 99bdd139 Iustin Pop
    for instance in self.instances:
419 99bdd139 Iustin Pop
      op = opcodes.OpMigrateInstance(instance_name=instance, live=True,
420 99bdd139 Iustin Pop
                                     cleanup=True)
421 99bdd139 Iustin Pop
422 99bdd139 Iustin Pop
      Log("- Testing 'migrate --cleanup' for instance %s" % (instance))
423 99bdd139 Iustin Pop
      self.ExecOp(op)
424 99bdd139 Iustin Pop
425 bd5e77f9 Guido Trotter
  def ImportExport(self):
426 bd5e77f9 Guido Trotter
    """Export the instance, delete it, and import it back.
427 bd5e77f9 Guido Trotter
428 bd5e77f9 Guido Trotter
    """
429 836d59d7 Iustin Pop
    Log("Exporting and re-importing instances")
430 bd5e77f9 Guido Trotter
    mytor = izip(cycle(self.nodes),
431 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 1, None),
432 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 2, None),
433 bd5e77f9 Guido Trotter
                 self.instances)
434 bd5e77f9 Guido Trotter
435 bd5e77f9 Guido Trotter
    for pnode, snode, enode, instance in mytor:
436 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
437 f9af35c8 Guido Trotter
      if self.opts.iallocator:
438 f9af35c8 Guido Trotter
        pnode = snode = None
439 836d59d7 Iustin Pop
        import_log_msg = ("import from %s"
440 836d59d7 Iustin Pop
                          " with iallocator %s" %
441 836d59d7 Iustin Pop
                          (enode, self.opts.iallocator))
442 f9af35c8 Guido Trotter
      elif self.opts.disk_template not in constants.DTS_NET_MIRROR:
443 f9af35c8 Guido Trotter
        snode = None
444 836d59d7 Iustin Pop
        import_log_msg = ("import from %s to %s" %
445 836d59d7 Iustin Pop
                          (enode, pnode))
446 f9af35c8 Guido Trotter
      else:
447 836d59d7 Iustin Pop
        import_log_msg = ("import from %s to %s, %s" %
448 836d59d7 Iustin Pop
                          (enode, pnode, snode))
449 f9af35c8 Guido Trotter
450 bd5e77f9 Guido Trotter
      exp_op = opcodes.OpExportInstance(instance_name=instance,
451 bd5e77f9 Guido Trotter
                                           target_node=enode,
452 bd5e77f9 Guido Trotter
                                           shutdown=True)
453 5c54b832 Iustin Pop
      rem_op = opcodes.OpRemoveInstance(instance_name=instance,
454 5c54b832 Iustin Pop
                                        ignore_failures=True)
455 bd5e77f9 Guido Trotter
      nam_op = opcodes.OpQueryInstances(output_fields=["name"],
456 bd5e77f9 Guido Trotter
                                           names=[instance])
457 bd5e77f9 Guido Trotter
      full_name = self.ExecOp(nam_op)[0][0]
458 bd5e77f9 Guido Trotter
      imp_dir = os.path.join(constants.EXPORT_DIR, full_name)
459 bd5e77f9 Guido Trotter
      imp_op = opcodes.OpCreateInstance(instance_name=instance,
460 0ca35d45 Guido Trotter
                                        disks = [ {"size": size}
461 0ca35d45 Guido Trotter
                                                  for size in self.disk_size],
462 bd5e77f9 Guido Trotter
                                        disk_template=self.opts.disk_template,
463 b518a14a Iustin Pop
                                        nics=self.opts.nics,
464 bd5e77f9 Guido Trotter
                                        mode=constants.INSTANCE_IMPORT,
465 bd5e77f9 Guido Trotter
                                        src_node=enode,
466 bd5e77f9 Guido Trotter
                                        src_path=imp_dir,
467 bd5e77f9 Guido Trotter
                                        pnode=pnode,
468 bd5e77f9 Guido Trotter
                                        snode=snode,
469 bd5e77f9 Guido Trotter
                                        start=True,
470 bd5e77f9 Guido Trotter
                                        ip_check=True,
471 bd5e77f9 Guido Trotter
                                        wait_for_sync=True,
472 96bb2f71 Manuel Franceschini
                                        file_storage_dir=None,
473 0ca35d45 Guido Trotter
                                        file_driver="loop",
474 6e2dc934 Alexander Schreiber
                                        iallocator=self.opts.iallocator,
475 338e51e8 Iustin Pop
                                        beparams=self.bep,
476 338e51e8 Iustin Pop
                                        hvparams=self.hvp,
477 338e51e8 Iustin Pop
                                        )
478 6e2dc934 Alexander Schreiber
479 4a7ff493 Guido Trotter
      erem_op = opcodes.OpRemoveExport(instance_name=instance)
480 bd5e77f9 Guido Trotter
481 836d59d7 Iustin Pop
      Log("export to node %s" % enode, indent=2)
482 bd5e77f9 Guido Trotter
      self.ExecOp(exp_op)
483 836d59d7 Iustin Pop
      Log("remove instance", indent=2)
484 bd5e77f9 Guido Trotter
      self.ExecOp(rem_op)
485 bd5e77f9 Guido Trotter
      self.to_rem.remove(instance)
486 836d59d7 Iustin Pop
      Log(import_log_msg, indent=2)
487 bd5e77f9 Guido Trotter
      self.ExecOp(imp_op)
488 836d59d7 Iustin Pop
      Log("remove export", indent=2)
489 4a7ff493 Guido Trotter
      self.ExecOp(erem_op)
490 4a7ff493 Guido Trotter
491 bd5e77f9 Guido Trotter
      self.to_rem.append(instance)
492 bd5e77f9 Guido Trotter
493 5178f1bc Iustin Pop
    for instance in self.instances:
494 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
495 5178f1bc Iustin Pop
496 054a8696 Manuel Franceschini
  def StopInstance(self, instance):
497 054a8696 Manuel Franceschini
    """Stop given instance."""
498 054a8696 Manuel Franceschini
    op = opcodes.OpShutdownInstance(instance_name=instance)
499 836d59d7 Iustin Pop
    Log("shutdown", indent=2)
500 054a8696 Manuel Franceschini
    self.ExecOp(op)
501 054a8696 Manuel Franceschini
502 054a8696 Manuel Franceschini
  def StartInstance(self, instance):
503 054a8696 Manuel Franceschini
    """Start given instance."""
504 054a8696 Manuel Franceschini
    op = opcodes.OpStartupInstance(instance_name=instance, force=False)
505 836d59d7 Iustin Pop
    Log("startup", indent=2)
506 054a8696 Manuel Franceschini
    self.ExecOp(op)
507 054a8696 Manuel Franceschini
508 054a8696 Manuel Franceschini
  def RenameInstance(self, instance, instance_new):
509 054a8696 Manuel Franceschini
    """Rename instance."""
510 054a8696 Manuel Franceschini
    op = opcodes.OpRenameInstance(instance_name=instance,
511 054a8696 Manuel Franceschini
                                  new_name=instance_new)
512 836d59d7 Iustin Pop
    Log("rename to %s" % instance_new, indent=2)
513 054a8696 Manuel Franceschini
    self.ExecOp(op)
514 054a8696 Manuel Franceschini
515 175f44c2 Iustin Pop
  def StopStart(self):
516 175f44c2 Iustin Pop
    """Stop/start the instances."""
517 836d59d7 Iustin Pop
    Log("Stopping and starting instances")
518 175f44c2 Iustin Pop
    for instance in self.instances:
519 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
520 054a8696 Manuel Franceschini
      self.StopInstance(instance)
521 054a8696 Manuel Franceschini
      self.StartInstance(instance)
522 175f44c2 Iustin Pop
523 5178f1bc Iustin Pop
    for instance in self.instances:
524 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
525 5178f1bc Iustin Pop
526 175f44c2 Iustin Pop
  def Remove(self):
527 175f44c2 Iustin Pop
    """Remove the instances."""
528 836d59d7 Iustin Pop
    Log("Removing instances")
529 175f44c2 Iustin Pop
    for instance in self.to_rem:
530 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
531 5c54b832 Iustin Pop
      op = opcodes.OpRemoveInstance(instance_name=instance,
532 5c54b832 Iustin Pop
                                    ignore_failures=True)
533 21546b1c Iustin Pop
      self.ExecOp(op)
534 175f44c2 Iustin Pop
535 054a8696 Manuel Franceschini
  def Rename(self):
536 054a8696 Manuel Franceschini
    """Rename the instances."""
537 836d59d7 Iustin Pop
    Log("Renaming instances")
538 054a8696 Manuel Franceschini
    rename = self.opts.rename
539 054a8696 Manuel Franceschini
    for instance in self.instances:
540 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
541 054a8696 Manuel Franceschini
      self.StopInstance(instance)
542 054a8696 Manuel Franceschini
      self.RenameInstance(instance, rename)
543 054a8696 Manuel Franceschini
      self.StartInstance(rename)
544 5178f1bc Iustin Pop
      self._CheckInstanceAlive(rename)
545 054a8696 Manuel Franceschini
      self.StopInstance(rename)
546 054a8696 Manuel Franceschini
      self.RenameInstance(rename, instance)
547 054a8696 Manuel Franceschini
      self.StartInstance(instance)
548 054a8696 Manuel Franceschini
549 5178f1bc Iustin Pop
    for instance in self.instances:
550 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
551 5178f1bc Iustin Pop
552 00f91f29 Iustin Pop
  def Reinstall(self):
553 00f91f29 Iustin Pop
    """Reinstall the instances."""
554 836d59d7 Iustin Pop
    Log("Reinstalling instances")
555 00f91f29 Iustin Pop
    for instance in self.instances:
556 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
557 00f91f29 Iustin Pop
      self.StopInstance(instance)
558 00f91f29 Iustin Pop
      op = opcodes.OpReinstallInstance(instance_name=instance)
559 836d59d7 Iustin Pop
      Log("reinstall without passing the OS", indent=2)
560 00f91f29 Iustin Pop
      self.ExecOp(op)
561 00f91f29 Iustin Pop
      op = opcodes.OpReinstallInstance(instance_name=instance,
562 00f91f29 Iustin Pop
                                       os_type=self.opts.os)
563 836d59d7 Iustin Pop
      Log("reinstall specifying the OS", indent=2)
564 00f91f29 Iustin Pop
      self.ExecOp(op)
565 00f91f29 Iustin Pop
      self.StartInstance(instance)
566 5178f1bc Iustin Pop
    for instance in self.instances:
567 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
568 00f91f29 Iustin Pop
569 00f91f29 Iustin Pop
  def Reboot(self):
570 836d59d7 Iustin Pop
    """Reboot the instances."""
571 836d59d7 Iustin Pop
    Log("Rebooting instances")
572 00f91f29 Iustin Pop
    for instance in self.instances:
573 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
574 00f91f29 Iustin Pop
      for reboot_type in constants.REBOOT_TYPES:
575 00f91f29 Iustin Pop
        op = opcodes.OpRebootInstance(instance_name=instance,
576 00f91f29 Iustin Pop
                                      reboot_type=reboot_type,
577 00f91f29 Iustin Pop
                                      ignore_secondaries=False)
578 836d59d7 Iustin Pop
        Log("reboot with type '%s'" % reboot_type, indent=2)
579 00f91f29 Iustin Pop
        self.ExecOp(op)
580 5178f1bc Iustin Pop
        self._CheckInstanceAlive(instance)
581 00f91f29 Iustin Pop
582 90e722d1 Iustin Pop
  def ActivateDisks(self):
583 90e722d1 Iustin Pop
    """Activate and deactivate disks of the instances."""
584 836d59d7 Iustin Pop
    Log("Activating/deactivating disks")
585 90e722d1 Iustin Pop
    for instance in self.instances:
586 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
587 90e722d1 Iustin Pop
      op_act = opcodes.OpActivateInstanceDisks(instance_name=instance)
588 90e722d1 Iustin Pop
      op_deact = opcodes.OpDeactivateInstanceDisks(instance_name=instance)
589 836d59d7 Iustin Pop
      Log("activate disks when online", indent=2)
590 90e722d1 Iustin Pop
      self.ExecOp(op_act)
591 90e722d1 Iustin Pop
      self.StopInstance(instance)
592 836d59d7 Iustin Pop
      Log("activate disks when offline", indent=2)
593 90e722d1 Iustin Pop
      self.ExecOp(op_act)
594 836d59d7 Iustin Pop
      Log("deactivate disks (when offline)", indent=2)
595 90e722d1 Iustin Pop
      self.ExecOp(op_deact)
596 90e722d1 Iustin Pop
      self.StartInstance(instance)
597 5178f1bc Iustin Pop
    for instance in self.instances:
598 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
599 90e722d1 Iustin Pop
600 5c22d16e Iustin Pop
  def AddRemoveDisks(self):
601 5c22d16e Iustin Pop
    """Add and remove an extra disk for the instances."""
602 836d59d7 Iustin Pop
    Log("Adding and removing disks")
603 5c22d16e Iustin Pop
    for instance in self.instances:
604 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
605 5c22d16e Iustin Pop
      op_add = opcodes.OpSetInstanceParams(\
606 5c22d16e Iustin Pop
        instance_name=instance,
607 5c22d16e Iustin Pop
        disks=[(constants.DDM_ADD, {"size": self.disk_size[0]})])
608 5c22d16e Iustin Pop
      op_rem = opcodes.OpSetInstanceParams(\
609 5c22d16e Iustin Pop
        instance_name=instance, disks=[(constants.DDM_REMOVE, {})])
610 836d59d7 Iustin Pop
      Log("adding a disk", indent=2)
611 5c22d16e Iustin Pop
      self.ExecOp(op_add)
612 5c22d16e Iustin Pop
      self.StopInstance(instance)
613 836d59d7 Iustin Pop
      Log("removing last disk", indent=2)
614 5c22d16e Iustin Pop
      self.ExecOp(op_rem)
615 5c22d16e Iustin Pop
      self.StartInstance(instance)
616 5178f1bc Iustin Pop
    for instance in self.instances:
617 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
618 5c22d16e Iustin Pop
619 5c22d16e Iustin Pop
  def AddRemoveNICs(self):
620 5c22d16e Iustin Pop
    """Add and remove an extra NIC for the instances."""
621 836d59d7 Iustin Pop
    Log("Adding and removing NICs")
622 5c22d16e Iustin Pop
    for instance in self.instances:
623 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
624 5c22d16e Iustin Pop
      op_add = opcodes.OpSetInstanceParams(\
625 5c22d16e Iustin Pop
        instance_name=instance, nics=[(constants.DDM_ADD, {})])
626 5c22d16e Iustin Pop
      op_rem = opcodes.OpSetInstanceParams(\
627 5c22d16e Iustin Pop
        instance_name=instance, nics=[(constants.DDM_REMOVE, {})])
628 836d59d7 Iustin Pop
      Log("adding a NIC", indent=2)
629 5c22d16e Iustin Pop
      self.ExecOp(op_add)
630 836d59d7 Iustin Pop
      Log("removing last NIC", indent=2)
631 5c22d16e Iustin Pop
      self.ExecOp(op_rem)
632 5c22d16e Iustin Pop
633 5178f1bc Iustin Pop
  def _CheckInstanceAlive(self, instance):
634 5178f1bc Iustin Pop
    """Check if an instance is alive by doing http checks.
635 5178f1bc Iustin Pop
636 5178f1bc Iustin Pop
    This will try to retrieve the url on the instance /hostname.txt
637 5178f1bc Iustin Pop
    and check that it contains the hostname of the instance. In case
638 5178f1bc Iustin Pop
    we get ECONNREFUSED, we retry up to the net timeout seconds, for
639 5178f1bc Iustin Pop
    any other error we abort.
640 5178f1bc Iustin Pop
641 5178f1bc Iustin Pop
    """
642 5178f1bc Iustin Pop
    if not self.opts.http_check:
643 5178f1bc Iustin Pop
      return
644 5178f1bc Iustin Pop
    try:
645 5178f1bc Iustin Pop
      for retries in range(self.opts.net_timeout):
646 5178f1bc Iustin Pop
        try:
647 5178f1bc Iustin Pop
          url = urllib2.urlopen("http://%s/hostname.txt" % instance)
648 5178f1bc Iustin Pop
        except urllib2.URLError, err:
649 5178f1bc Iustin Pop
          if err.args[0][0] == errno.ECONNREFUSED:
650 5178f1bc Iustin Pop
            time.sleep(1)
651 5178f1bc Iustin Pop
            continue
652 5178f1bc Iustin Pop
          raise
653 5178f1bc Iustin Pop
    except urllib2.URLError, err:
654 5178f1bc Iustin Pop
      raise InstanceDown(instance, str(err))
655 5178f1bc Iustin Pop
    hostname = url.read().strip()
656 5178f1bc Iustin Pop
    if hostname != instance:
657 5178f1bc Iustin Pop
      raise InstanceDown(instance, ("Hostname mismatch, expected %s, got %s" %
658 5178f1bc Iustin Pop
                                    (instance, hostname)))
659 5178f1bc Iustin Pop
660 175f44c2 Iustin Pop
  def BurninCluster(self):
661 175f44c2 Iustin Pop
    """Test a cluster intensively.
662 175f44c2 Iustin Pop
663 175f44c2 Iustin Pop
    This will create instances and then start/stop/failover them.
664 175f44c2 Iustin Pop
    It is safe for existing instances but could impact performance.
665 175f44c2 Iustin Pop
666 175f44c2 Iustin Pop
    """
667 175f44c2 Iustin Pop
668 175f44c2 Iustin Pop
    opts = self.opts
669 175f44c2 Iustin Pop
670 836d59d7 Iustin Pop
    Log("Testing global parameters")
671 175f44c2 Iustin Pop
672 bd249e2f Iustin Pop
    if (len(self.nodes) == 1 and
673 2f505cb5 Manuel Franceschini
        opts.disk_template not in (constants.DT_DISKLESS, constants.DT_PLAIN,
674 2f505cb5 Manuel Franceschini
                                   constants.DT_FILE)):
675 836d59d7 Iustin Pop
      Err("When one node is available/selected the disk template must"
676 2f505cb5 Manuel Franceschini
          " be 'diskless', 'file' or 'plain'")
677 175f44c2 Iustin Pop
678 21546b1c Iustin Pop
    has_err = True
679 175f44c2 Iustin Pop
    try:
680 175f44c2 Iustin Pop
      self.CreateInstances()
681 175f44c2 Iustin Pop
      if opts.do_replace1 and opts.disk_template in constants.DTS_NET_MIRROR:
682 f9193417 Iustin Pop
        self.ReplaceDisks1D8()
683 175f44c2 Iustin Pop
      if (opts.do_replace2 and len(self.nodes) > 2 and
684 175f44c2 Iustin Pop
          opts.disk_template in constants.DTS_NET_MIRROR) :
685 175f44c2 Iustin Pop
        self.ReplaceDisks2()
686 175f44c2 Iustin Pop
687 659712c8 Iustin Pop
      if opts.disk_template != constants.DT_DISKLESS:
688 659712c8 Iustin Pop
        self.GrowDisks()
689 659712c8 Iustin Pop
690 175f44c2 Iustin Pop
      if opts.do_failover and opts.disk_template in constants.DTS_NET_MIRROR:
691 175f44c2 Iustin Pop
        self.Failover()
692 175f44c2 Iustin Pop
693 99bdd139 Iustin Pop
      if opts.do_migrate and opts.disk_template == constants.DT_DRBD8:
694 99bdd139 Iustin Pop
        self.Migrate()
695 99bdd139 Iustin Pop
696 a5e7be6b Iustin Pop
      if (opts.do_importexport and
697 a5e7be6b Iustin Pop
          opts.disk_template not in (constants.DT_DISKLESS,
698 a5e7be6b Iustin Pop
                                     constants.DT_FILE)):
699 bd5e77f9 Guido Trotter
        self.ImportExport()
700 bd5e77f9 Guido Trotter
701 00f91f29 Iustin Pop
      if opts.do_reinstall:
702 00f91f29 Iustin Pop
        self.Reinstall()
703 00f91f29 Iustin Pop
704 00f91f29 Iustin Pop
      if opts.do_reboot:
705 00f91f29 Iustin Pop
        self.Reboot()
706 00f91f29 Iustin Pop
707 5c22d16e Iustin Pop
      if opts.do_addremove_disks:
708 5c22d16e Iustin Pop
        self.AddRemoveDisks()
709 5c22d16e Iustin Pop
710 5c22d16e Iustin Pop
      if opts.do_addremove_nics:
711 5c22d16e Iustin Pop
        self.AddRemoveNICs()
712 5c22d16e Iustin Pop
713 90e722d1 Iustin Pop
      if opts.do_activate_disks:
714 90e722d1 Iustin Pop
        self.ActivateDisks()
715 90e722d1 Iustin Pop
716 054a8696 Manuel Franceschini
      if opts.rename:
717 054a8696 Manuel Franceschini
        self.Rename()
718 054a8696 Manuel Franceschini
719 eb61f8d3 Iustin Pop
      if opts.do_startstop:
720 eb61f8d3 Iustin Pop
        self.StopStart()
721 eb61f8d3 Iustin Pop
722 21546b1c Iustin Pop
      has_err = False
723 175f44c2 Iustin Pop
    finally:
724 21546b1c Iustin Pop
      if has_err:
725 21546b1c Iustin Pop
        Log("Error detected: opcode buffer follows:\n\n")
726 21546b1c Iustin Pop
        Log(self.GetFeedbackBuf())
727 21546b1c Iustin Pop
        Log("\n\n")
728 175f44c2 Iustin Pop
      self.Remove()
729 175f44c2 Iustin Pop
730 175f44c2 Iustin Pop
    return 0
731 a8083063 Iustin Pop
732 01b69ec5 Michael Hanselmann
733 a8083063 Iustin Pop
def main():
734 3ecf6786 Iustin Pop
  """Main function"""
735 3ecf6786 Iustin Pop
736 175f44c2 Iustin Pop
  burner = Burner()
737 a4af651e Iustin Pop
  return burner.BurninCluster()
738 a8083063 Iustin Pop
739 01b69ec5 Michael Hanselmann
740 a8083063 Iustin Pop
if __name__ == "__main__":
741 3ecf6786 Iustin Pop
  main()