Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ 320eda24

History | View | Annotate | Download (26.8 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 175f44c2 Iustin Pop
    self.ParseOptions()
92 320eda24 Iustin Pop
    self.cl = cli.GetClient()
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 320eda24 Iustin Pop
    parser.add_option("-K", "--keep-instances", default=False,
226 320eda24 Iustin Pop
                      action="store_true",
227 320eda24 Iustin Pop
                      dest="keep_instances",
228 320eda24 Iustin Pop
                      help="Leave instances on the cluster after burnin,"
229 320eda24 Iustin Pop
                      " for investigation in case of errors or simply"
230 320eda24 Iustin Pop
                      " to use them")
231 5178f1bc Iustin Pop
232 175f44c2 Iustin Pop
233 175f44c2 Iustin Pop
    options, args = parser.parse_args()
234 175f44c2 Iustin Pop
    if len(args) < 1 or options.os is None:
235 175f44c2 Iustin Pop
      Usage()
236 175f44c2 Iustin Pop
237 f9193417 Iustin Pop
    supported_disk_templates = (constants.DT_DISKLESS,
238 2f505cb5 Manuel Franceschini
                                constants.DT_FILE,
239 f9193417 Iustin Pop
                                constants.DT_PLAIN,
240 12c3449a Michael Hanselmann
                                constants.DT_DRBD8)
241 12c3449a Michael Hanselmann
    if options.disk_template not in supported_disk_templates:
242 836d59d7 Iustin Pop
      Err("Unknown disk template '%s'" % options.disk_template)
243 175f44c2 Iustin Pop
244 b518a14a Iustin Pop
    if options.disk_template == constants.DT_DISKLESS:
245 b518a14a Iustin Pop
      disk_size = disk_growth = []
246 5178f1bc Iustin Pop
      options.do_addremove_disks = False
247 b518a14a Iustin Pop
    else:
248 b518a14a Iustin Pop
      disk_size = [utils.ParseUnit(v) for v in options.disk_size.split(",")]
249 b518a14a Iustin Pop
      disk_growth = [utils.ParseUnit(v)
250 b518a14a Iustin Pop
                     for v in options.disk_growth.split(",")]
251 b518a14a Iustin Pop
      if len(disk_growth) != len(disk_size):
252 836d59d7 Iustin Pop
        Err("Wrong disk sizes/growth combination")
253 08db7c5c Iustin Pop
    if ((disk_size and options.disk_template == constants.DT_DISKLESS) or
254 08db7c5c Iustin Pop
        (not disk_size and options.disk_template != constants.DT_DISKLESS)):
255 836d59d7 Iustin Pop
      Err("Wrong disk count/disk template combination")
256 08db7c5c Iustin Pop
257 08db7c5c Iustin Pop
    self.disk_size = disk_size
258 08db7c5c Iustin Pop
    self.disk_growth = disk_growth
259 08db7c5c Iustin Pop
    self.disk_count = len(disk_size)
260 08db7c5c Iustin Pop
261 b91bde14 Iustin Pop
    if options.nodes and options.iallocator:
262 836d59d7 Iustin Pop
      Err("Give either the nodes option or the iallocator option, not both")
263 b91bde14 Iustin Pop
264 175f44c2 Iustin Pop
    self.opts = options
265 175f44c2 Iustin Pop
    self.instances = args
266 338e51e8 Iustin Pop
    self.bep = {
267 338e51e8 Iustin Pop
      constants.BE_MEMORY: options.mem_size,
268 338e51e8 Iustin Pop
      constants.BE_VCPUS: 1,
269 338e51e8 Iustin Pop
      }
270 338e51e8 Iustin Pop
    self.hvp = {}
271 175f44c2 Iustin Pop
272 5178f1bc Iustin Pop
    socket.setdefaulttimeout(options.net_timeout)
273 5178f1bc Iustin Pop
274 175f44c2 Iustin Pop
  def GetState(self):
275 175f44c2 Iustin Pop
    """Read the cluster state from the config."""
276 175f44c2 Iustin Pop
    if self.opts.nodes:
277 175f44c2 Iustin Pop
      names = self.opts.nodes.split(",")
278 175f44c2 Iustin Pop
    else:
279 175f44c2 Iustin Pop
      names = []
280 175f44c2 Iustin Pop
    try:
281 729164d0 Iustin Pop
      op = opcodes.OpQueryNodes(output_fields=["name", "offline"], names=names)
282 21546b1c Iustin Pop
      result = self.ExecOp(op)
283 175f44c2 Iustin Pop
    except errors.GenericError, err:
284 175f44c2 Iustin Pop
      err_code, msg = cli.FormatError(err)
285 836d59d7 Iustin Pop
      Err(msg, exit_code=err_code)
286 729164d0 Iustin Pop
    self.nodes = [data[0] for data in result if not data[1]]
287 175f44c2 Iustin Pop
288 1f9430d6 Iustin Pop
    result = self.ExecOp(opcodes.OpDiagnoseOS(output_fields=["name", "valid"],
289 1f9430d6 Iustin Pop
                                              names=[]))
290 175f44c2 Iustin Pop
291 175f44c2 Iustin Pop
    if not result:
292 836d59d7 Iustin Pop
      Err("Can't get the OS list")
293 175f44c2 Iustin Pop
294 175f44c2 Iustin Pop
    # filter non-valid OS-es
295 1f9430d6 Iustin Pop
    os_set = [val[0] for val in result if val[1]]
296 175f44c2 Iustin Pop
297 175f44c2 Iustin Pop
    if self.opts.os not in os_set:
298 836d59d7 Iustin Pop
      Err("OS '%s' not found" % self.opts.os)
299 175f44c2 Iustin Pop
300 175f44c2 Iustin Pop
  def CreateInstances(self):
301 175f44c2 Iustin Pop
    """Create the given instances.
302 175f44c2 Iustin Pop
303 175f44c2 Iustin Pop
    """
304 175f44c2 Iustin Pop
    self.to_rem = []
305 175f44c2 Iustin Pop
    mytor = izip(cycle(self.nodes),
306 175f44c2 Iustin Pop
                 islice(cycle(self.nodes), 1, None),
307 175f44c2 Iustin Pop
                 self.instances)
308 ec5c88dc Iustin Pop
    jobset = []
309 338e51e8 Iustin Pop
310 836d59d7 Iustin Pop
    Log("Creating instances")
311 175f44c2 Iustin Pop
    for pnode, snode, instance in mytor:
312 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
313 b91bde14 Iustin Pop
      if self.opts.iallocator:
314 b91bde14 Iustin Pop
        pnode = snode = None
315 836d59d7 Iustin Pop
        msg = "with iallocator %s" % self.opts.iallocator
316 6d54548e Guido Trotter
      elif self.opts.disk_template not in constants.DTS_NET_MIRROR:
317 6d54548e Guido Trotter
        snode = None
318 836d59d7 Iustin Pop
        msg = "on %s" % pnode
319 6d54548e Guido Trotter
      else:
320 836d59d7 Iustin Pop
        msg = "on %s, %s" % (pnode, snode)
321 836d59d7 Iustin Pop
322 836d59d7 Iustin Pop
      Log(msg, indent=2)
323 6d54548e Guido Trotter
324 175f44c2 Iustin Pop
      op = opcodes.OpCreateInstance(instance_name=instance,
325 08db7c5c Iustin Pop
                                    disks = [ {"size": size}
326 08db7c5c Iustin Pop
                                              for size in self.disk_size],
327 175f44c2 Iustin Pop
                                    disk_template=self.opts.disk_template,
328 b518a14a Iustin Pop
                                    nics=self.opts.nics,
329 a8083063 Iustin Pop
                                    mode=constants.INSTANCE_CREATE,
330 175f44c2 Iustin Pop
                                    os_type=self.opts.os,
331 175f44c2 Iustin Pop
                                    pnode=pnode,
332 175f44c2 Iustin Pop
                                    snode=snode,
333 a8083063 Iustin Pop
                                    start=True,
334 e9f745aa Iustin Pop
                                    ip_check=True,
335 4501af56 Iustin Pop
                                    wait_for_sync=True,
336 2f505cb5 Manuel Franceschini
                                    file_driver="loop",
337 b91bde14 Iustin Pop
                                    file_storage_dir=None,
338 6e2dc934 Alexander Schreiber
                                    iallocator=self.opts.iallocator,
339 338e51e8 Iustin Pop
                                    beparams=self.bep,
340 338e51e8 Iustin Pop
                                    hvparams=self.hvp,
341 338e51e8 Iustin Pop
                                    )
342 6e2dc934 Alexander Schreiber
343 ec5c88dc Iustin Pop
      if self.opts.parallel:
344 ec5c88dc Iustin Pop
        jobset.append([op])
345 ec5c88dc Iustin Pop
        # FIXME: here we should not append to to_rem uncoditionally,
346 ec5c88dc Iustin Pop
        # but only when the job is successful
347 ec5c88dc Iustin Pop
        self.to_rem.append(instance)
348 ec5c88dc Iustin Pop
      else:
349 ec5c88dc Iustin Pop
        self.ExecOp(op)
350 ec5c88dc Iustin Pop
        self.to_rem.append(instance)
351 ec5c88dc Iustin Pop
    if self.opts.parallel:
352 ec5c88dc Iustin Pop
      self.ExecJobSet(jobset)
353 175f44c2 Iustin Pop
354 5178f1bc Iustin Pop
    for instance in self.instances:
355 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
356 5178f1bc Iustin Pop
357 659712c8 Iustin Pop
  def GrowDisks(self):
358 659712c8 Iustin Pop
    """Grow both the os and the swap disks by the requested amount, if any."""
359 836d59d7 Iustin Pop
    Log("Growing disks")
360 659712c8 Iustin Pop
    for instance in self.instances:
361 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
362 08db7c5c Iustin Pop
      for idx, growth in enumerate(self.disk_growth):
363 659712c8 Iustin Pop
        if growth > 0:
364 08db7c5c Iustin Pop
          op = opcodes.OpGrowDisk(instance_name=instance, disk=idx,
365 6605411d Iustin Pop
                                  amount=growth, wait_for_sync=True)
366 836d59d7 Iustin Pop
          Log("increase disk/%s by %s MB" % (idx, growth), indent=2)
367 659712c8 Iustin Pop
          self.ExecOp(op)
368 659712c8 Iustin Pop
369 175f44c2 Iustin Pop
  def ReplaceDisks1D8(self):
370 175f44c2 Iustin Pop
    """Replace disks on primary and secondary for drbd8."""
371 836d59d7 Iustin Pop
    Log("Replacing disks on the same nodes")
372 175f44c2 Iustin Pop
    for instance in self.instances:
373 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
374 175f44c2 Iustin Pop
      for mode in constants.REPLACE_DISK_SEC, constants.REPLACE_DISK_PRI:
375 175f44c2 Iustin Pop
        op = opcodes.OpReplaceDisks(instance_name=instance,
376 175f44c2 Iustin Pop
                                    mode=mode,
377 08db7c5c Iustin Pop
                                    disks=[i for i in range(self.disk_count)])
378 836d59d7 Iustin Pop
        Log("run %s" % mode, indent=2)
379 21546b1c Iustin Pop
        self.ExecOp(op)
380 175f44c2 Iustin Pop
381 175f44c2 Iustin Pop
  def ReplaceDisks2(self):
382 175f44c2 Iustin Pop
    """Replace secondary node."""
383 836d59d7 Iustin Pop
    Log("Changing the secondary node")
384 cfacfd6e Iustin Pop
    mode = constants.REPLACE_DISK_CHG
385 175f44c2 Iustin Pop
386 175f44c2 Iustin Pop
    mytor = izip(islice(cycle(self.nodes), 2, None),
387 175f44c2 Iustin Pop
                 self.instances)
388 175f44c2 Iustin Pop
    for tnode, instance in mytor:
389 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
390 b6e82a65 Iustin Pop
      if self.opts.iallocator:
391 b6e82a65 Iustin Pop
        tnode = None
392 836d59d7 Iustin Pop
        msg = "with iallocator %s" % self.opts.iallocator
393 836d59d7 Iustin Pop
      else:
394 836d59d7 Iustin Pop
        msg = tnode
395 175f44c2 Iustin Pop
      op = opcodes.OpReplaceDisks(instance_name=instance,
396 175f44c2 Iustin Pop
                                  mode=mode,
397 175f44c2 Iustin Pop
                                  remote_node=tnode,
398 b6e82a65 Iustin Pop
                                  iallocator=self.opts.iallocator,
399 08db7c5c Iustin Pop
                                  disks=[i for i in range(self.disk_count)])
400 836d59d7 Iustin Pop
      Log("run %s %s" % (mode, msg), indent=2)
401 21546b1c Iustin Pop
      self.ExecOp(op)
402 175f44c2 Iustin Pop
403 175f44c2 Iustin Pop
  def Failover(self):
404 175f44c2 Iustin Pop
    """Failover the instances."""
405 836d59d7 Iustin Pop
    Log("Failing over instances")
406 175f44c2 Iustin Pop
    for instance in self.instances:
407 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
408 175f44c2 Iustin Pop
      op = opcodes.OpFailoverInstance(instance_name=instance,
409 175f44c2 Iustin Pop
                                      ignore_consistency=False)
410 175f44c2 Iustin Pop
411 21546b1c Iustin Pop
      self.ExecOp(op)
412 5178f1bc Iustin Pop
    for instance in self.instances:
413 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
414 175f44c2 Iustin Pop
415 99bdd139 Iustin Pop
  def Migrate(self):
416 99bdd139 Iustin Pop
    """Migrate the instances."""
417 801cda94 Iustin Pop
    Log("Migrating instances")
418 99bdd139 Iustin Pop
    for instance in self.instances:
419 801cda94 Iustin Pop
      Log("instance %s" % instance, indent=1)
420 99bdd139 Iustin Pop
      op = opcodes.OpMigrateInstance(instance_name=instance, live=True,
421 99bdd139 Iustin Pop
                                     cleanup=False)
422 99bdd139 Iustin Pop
423 801cda94 Iustin Pop
      Log("migration", indent=2)
424 99bdd139 Iustin Pop
      self.ExecOp(op)
425 99bdd139 Iustin Pop
      op = opcodes.OpMigrateInstance(instance_name=instance, live=True,
426 99bdd139 Iustin Pop
                                     cleanup=True)
427 801cda94 Iustin Pop
      Log("migration cleanup", indent=2)
428 99bdd139 Iustin Pop
      self.ExecOp(op)
429 99bdd139 Iustin Pop
430 bd5e77f9 Guido Trotter
  def ImportExport(self):
431 bd5e77f9 Guido Trotter
    """Export the instance, delete it, and import it back.
432 bd5e77f9 Guido Trotter
433 bd5e77f9 Guido Trotter
    """
434 836d59d7 Iustin Pop
    Log("Exporting and re-importing instances")
435 bd5e77f9 Guido Trotter
    mytor = izip(cycle(self.nodes),
436 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 1, None),
437 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 2, None),
438 bd5e77f9 Guido Trotter
                 self.instances)
439 bd5e77f9 Guido Trotter
440 bd5e77f9 Guido Trotter
    for pnode, snode, enode, instance in mytor:
441 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
442 f9af35c8 Guido Trotter
      if self.opts.iallocator:
443 f9af35c8 Guido Trotter
        pnode = snode = None
444 836d59d7 Iustin Pop
        import_log_msg = ("import from %s"
445 836d59d7 Iustin Pop
                          " with iallocator %s" %
446 836d59d7 Iustin Pop
                          (enode, self.opts.iallocator))
447 f9af35c8 Guido Trotter
      elif self.opts.disk_template not in constants.DTS_NET_MIRROR:
448 f9af35c8 Guido Trotter
        snode = None
449 836d59d7 Iustin Pop
        import_log_msg = ("import from %s to %s" %
450 836d59d7 Iustin Pop
                          (enode, pnode))
451 f9af35c8 Guido Trotter
      else:
452 836d59d7 Iustin Pop
        import_log_msg = ("import from %s to %s, %s" %
453 836d59d7 Iustin Pop
                          (enode, pnode, snode))
454 f9af35c8 Guido Trotter
455 bd5e77f9 Guido Trotter
      exp_op = opcodes.OpExportInstance(instance_name=instance,
456 bd5e77f9 Guido Trotter
                                           target_node=enode,
457 bd5e77f9 Guido Trotter
                                           shutdown=True)
458 5c54b832 Iustin Pop
      rem_op = opcodes.OpRemoveInstance(instance_name=instance,
459 5c54b832 Iustin Pop
                                        ignore_failures=True)
460 bd5e77f9 Guido Trotter
      nam_op = opcodes.OpQueryInstances(output_fields=["name"],
461 bd5e77f9 Guido Trotter
                                           names=[instance])
462 bd5e77f9 Guido Trotter
      full_name = self.ExecOp(nam_op)[0][0]
463 bd5e77f9 Guido Trotter
      imp_dir = os.path.join(constants.EXPORT_DIR, full_name)
464 bd5e77f9 Guido Trotter
      imp_op = opcodes.OpCreateInstance(instance_name=instance,
465 0ca35d45 Guido Trotter
                                        disks = [ {"size": size}
466 0ca35d45 Guido Trotter
                                                  for size in self.disk_size],
467 bd5e77f9 Guido Trotter
                                        disk_template=self.opts.disk_template,
468 b518a14a Iustin Pop
                                        nics=self.opts.nics,
469 bd5e77f9 Guido Trotter
                                        mode=constants.INSTANCE_IMPORT,
470 bd5e77f9 Guido Trotter
                                        src_node=enode,
471 bd5e77f9 Guido Trotter
                                        src_path=imp_dir,
472 bd5e77f9 Guido Trotter
                                        pnode=pnode,
473 bd5e77f9 Guido Trotter
                                        snode=snode,
474 bd5e77f9 Guido Trotter
                                        start=True,
475 bd5e77f9 Guido Trotter
                                        ip_check=True,
476 bd5e77f9 Guido Trotter
                                        wait_for_sync=True,
477 96bb2f71 Manuel Franceschini
                                        file_storage_dir=None,
478 0ca35d45 Guido Trotter
                                        file_driver="loop",
479 6e2dc934 Alexander Schreiber
                                        iallocator=self.opts.iallocator,
480 338e51e8 Iustin Pop
                                        beparams=self.bep,
481 338e51e8 Iustin Pop
                                        hvparams=self.hvp,
482 338e51e8 Iustin Pop
                                        )
483 6e2dc934 Alexander Schreiber
484 4a7ff493 Guido Trotter
      erem_op = opcodes.OpRemoveExport(instance_name=instance)
485 bd5e77f9 Guido Trotter
486 836d59d7 Iustin Pop
      Log("export to node %s" % enode, indent=2)
487 bd5e77f9 Guido Trotter
      self.ExecOp(exp_op)
488 836d59d7 Iustin Pop
      Log("remove instance", indent=2)
489 bd5e77f9 Guido Trotter
      self.ExecOp(rem_op)
490 bd5e77f9 Guido Trotter
      self.to_rem.remove(instance)
491 836d59d7 Iustin Pop
      Log(import_log_msg, indent=2)
492 bd5e77f9 Guido Trotter
      self.ExecOp(imp_op)
493 836d59d7 Iustin Pop
      Log("remove export", indent=2)
494 4a7ff493 Guido Trotter
      self.ExecOp(erem_op)
495 4a7ff493 Guido Trotter
496 bd5e77f9 Guido Trotter
      self.to_rem.append(instance)
497 bd5e77f9 Guido Trotter
498 5178f1bc Iustin Pop
    for instance in self.instances:
499 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
500 5178f1bc Iustin Pop
501 054a8696 Manuel Franceschini
  def StopInstance(self, instance):
502 054a8696 Manuel Franceschini
    """Stop given instance."""
503 054a8696 Manuel Franceschini
    op = opcodes.OpShutdownInstance(instance_name=instance)
504 836d59d7 Iustin Pop
    Log("shutdown", indent=2)
505 054a8696 Manuel Franceschini
    self.ExecOp(op)
506 054a8696 Manuel Franceschini
507 054a8696 Manuel Franceschini
  def StartInstance(self, instance):
508 054a8696 Manuel Franceschini
    """Start given instance."""
509 054a8696 Manuel Franceschini
    op = opcodes.OpStartupInstance(instance_name=instance, force=False)
510 836d59d7 Iustin Pop
    Log("startup", indent=2)
511 054a8696 Manuel Franceschini
    self.ExecOp(op)
512 054a8696 Manuel Franceschini
513 054a8696 Manuel Franceschini
  def RenameInstance(self, instance, instance_new):
514 054a8696 Manuel Franceschini
    """Rename instance."""
515 054a8696 Manuel Franceschini
    op = opcodes.OpRenameInstance(instance_name=instance,
516 054a8696 Manuel Franceschini
                                  new_name=instance_new)
517 836d59d7 Iustin Pop
    Log("rename to %s" % instance_new, indent=2)
518 054a8696 Manuel Franceschini
    self.ExecOp(op)
519 054a8696 Manuel Franceschini
520 175f44c2 Iustin Pop
  def StopStart(self):
521 175f44c2 Iustin Pop
    """Stop/start the instances."""
522 836d59d7 Iustin Pop
    Log("Stopping and starting instances")
523 175f44c2 Iustin Pop
    for instance in self.instances:
524 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
525 054a8696 Manuel Franceschini
      self.StopInstance(instance)
526 054a8696 Manuel Franceschini
      self.StartInstance(instance)
527 175f44c2 Iustin Pop
528 5178f1bc Iustin Pop
    for instance in self.instances:
529 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
530 5178f1bc Iustin Pop
531 175f44c2 Iustin Pop
  def Remove(self):
532 175f44c2 Iustin Pop
    """Remove the instances."""
533 836d59d7 Iustin Pop
    Log("Removing instances")
534 175f44c2 Iustin Pop
    for instance in self.to_rem:
535 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
536 5c54b832 Iustin Pop
      op = opcodes.OpRemoveInstance(instance_name=instance,
537 5c54b832 Iustin Pop
                                    ignore_failures=True)
538 21546b1c Iustin Pop
      self.ExecOp(op)
539 175f44c2 Iustin Pop
540 054a8696 Manuel Franceschini
  def Rename(self):
541 054a8696 Manuel Franceschini
    """Rename the instances."""
542 836d59d7 Iustin Pop
    Log("Renaming instances")
543 054a8696 Manuel Franceschini
    rename = self.opts.rename
544 054a8696 Manuel Franceschini
    for instance in self.instances:
545 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
546 054a8696 Manuel Franceschini
      self.StopInstance(instance)
547 054a8696 Manuel Franceschini
      self.RenameInstance(instance, rename)
548 054a8696 Manuel Franceschini
      self.StartInstance(rename)
549 5178f1bc Iustin Pop
      self._CheckInstanceAlive(rename)
550 054a8696 Manuel Franceschini
      self.StopInstance(rename)
551 054a8696 Manuel Franceschini
      self.RenameInstance(rename, instance)
552 054a8696 Manuel Franceschini
      self.StartInstance(instance)
553 054a8696 Manuel Franceschini
554 5178f1bc Iustin Pop
    for instance in self.instances:
555 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
556 5178f1bc Iustin Pop
557 00f91f29 Iustin Pop
  def Reinstall(self):
558 00f91f29 Iustin Pop
    """Reinstall the instances."""
559 836d59d7 Iustin Pop
    Log("Reinstalling instances")
560 00f91f29 Iustin Pop
    for instance in self.instances:
561 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
562 00f91f29 Iustin Pop
      self.StopInstance(instance)
563 00f91f29 Iustin Pop
      op = opcodes.OpReinstallInstance(instance_name=instance)
564 836d59d7 Iustin Pop
      Log("reinstall without passing the OS", indent=2)
565 00f91f29 Iustin Pop
      self.ExecOp(op)
566 00f91f29 Iustin Pop
      op = opcodes.OpReinstallInstance(instance_name=instance,
567 00f91f29 Iustin Pop
                                       os_type=self.opts.os)
568 836d59d7 Iustin Pop
      Log("reinstall specifying the OS", indent=2)
569 00f91f29 Iustin Pop
      self.ExecOp(op)
570 00f91f29 Iustin Pop
      self.StartInstance(instance)
571 5178f1bc Iustin Pop
    for instance in self.instances:
572 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
573 00f91f29 Iustin Pop
574 00f91f29 Iustin Pop
  def Reboot(self):
575 836d59d7 Iustin Pop
    """Reboot the instances."""
576 836d59d7 Iustin Pop
    Log("Rebooting instances")
577 00f91f29 Iustin Pop
    for instance in self.instances:
578 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
579 00f91f29 Iustin Pop
      for reboot_type in constants.REBOOT_TYPES:
580 00f91f29 Iustin Pop
        op = opcodes.OpRebootInstance(instance_name=instance,
581 00f91f29 Iustin Pop
                                      reboot_type=reboot_type,
582 00f91f29 Iustin Pop
                                      ignore_secondaries=False)
583 836d59d7 Iustin Pop
        Log("reboot with type '%s'" % reboot_type, indent=2)
584 00f91f29 Iustin Pop
        self.ExecOp(op)
585 5178f1bc Iustin Pop
        self._CheckInstanceAlive(instance)
586 00f91f29 Iustin Pop
587 90e722d1 Iustin Pop
  def ActivateDisks(self):
588 90e722d1 Iustin Pop
    """Activate and deactivate disks of the instances."""
589 836d59d7 Iustin Pop
    Log("Activating/deactivating disks")
590 90e722d1 Iustin Pop
    for instance in self.instances:
591 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
592 90e722d1 Iustin Pop
      op_act = opcodes.OpActivateInstanceDisks(instance_name=instance)
593 90e722d1 Iustin Pop
      op_deact = opcodes.OpDeactivateInstanceDisks(instance_name=instance)
594 836d59d7 Iustin Pop
      Log("activate disks when online", indent=2)
595 90e722d1 Iustin Pop
      self.ExecOp(op_act)
596 90e722d1 Iustin Pop
      self.StopInstance(instance)
597 836d59d7 Iustin Pop
      Log("activate disks when offline", indent=2)
598 90e722d1 Iustin Pop
      self.ExecOp(op_act)
599 836d59d7 Iustin Pop
      Log("deactivate disks (when offline)", indent=2)
600 90e722d1 Iustin Pop
      self.ExecOp(op_deact)
601 90e722d1 Iustin Pop
      self.StartInstance(instance)
602 5178f1bc Iustin Pop
    for instance in self.instances:
603 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
604 90e722d1 Iustin Pop
605 5c22d16e Iustin Pop
  def AddRemoveDisks(self):
606 5c22d16e Iustin Pop
    """Add and remove an extra disk for the instances."""
607 836d59d7 Iustin Pop
    Log("Adding and removing disks")
608 5c22d16e Iustin Pop
    for instance in self.instances:
609 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
610 5c22d16e Iustin Pop
      op_add = opcodes.OpSetInstanceParams(\
611 5c22d16e Iustin Pop
        instance_name=instance,
612 5c22d16e Iustin Pop
        disks=[(constants.DDM_ADD, {"size": self.disk_size[0]})])
613 5c22d16e Iustin Pop
      op_rem = opcodes.OpSetInstanceParams(\
614 5c22d16e Iustin Pop
        instance_name=instance, disks=[(constants.DDM_REMOVE, {})])
615 836d59d7 Iustin Pop
      Log("adding a disk", indent=2)
616 5c22d16e Iustin Pop
      self.ExecOp(op_add)
617 5c22d16e Iustin Pop
      self.StopInstance(instance)
618 836d59d7 Iustin Pop
      Log("removing last disk", indent=2)
619 5c22d16e Iustin Pop
      self.ExecOp(op_rem)
620 5c22d16e Iustin Pop
      self.StartInstance(instance)
621 5178f1bc Iustin Pop
    for instance in self.instances:
622 5178f1bc Iustin Pop
      self._CheckInstanceAlive(instance)
623 5c22d16e Iustin Pop
624 5c22d16e Iustin Pop
  def AddRemoveNICs(self):
625 5c22d16e Iustin Pop
    """Add and remove an extra NIC for the instances."""
626 836d59d7 Iustin Pop
    Log("Adding and removing NICs")
627 5c22d16e Iustin Pop
    for instance in self.instances:
628 836d59d7 Iustin Pop
      Log("instance %s" % instance, indent=1)
629 5c22d16e Iustin Pop
      op_add = opcodes.OpSetInstanceParams(\
630 5c22d16e Iustin Pop
        instance_name=instance, nics=[(constants.DDM_ADD, {})])
631 5c22d16e Iustin Pop
      op_rem = opcodes.OpSetInstanceParams(\
632 5c22d16e Iustin Pop
        instance_name=instance, nics=[(constants.DDM_REMOVE, {})])
633 836d59d7 Iustin Pop
      Log("adding a NIC", indent=2)
634 5c22d16e Iustin Pop
      self.ExecOp(op_add)
635 836d59d7 Iustin Pop
      Log("removing last NIC", indent=2)
636 5c22d16e Iustin Pop
      self.ExecOp(op_rem)
637 5c22d16e Iustin Pop
638 5178f1bc Iustin Pop
  def _CheckInstanceAlive(self, instance):
639 5178f1bc Iustin Pop
    """Check if an instance is alive by doing http checks.
640 5178f1bc Iustin Pop
641 5178f1bc Iustin Pop
    This will try to retrieve the url on the instance /hostname.txt
642 5178f1bc Iustin Pop
    and check that it contains the hostname of the instance. In case
643 5178f1bc Iustin Pop
    we get ECONNREFUSED, we retry up to the net timeout seconds, for
644 5178f1bc Iustin Pop
    any other error we abort.
645 5178f1bc Iustin Pop
646 5178f1bc Iustin Pop
    """
647 5178f1bc Iustin Pop
    if not self.opts.http_check:
648 5178f1bc Iustin Pop
      return
649 5178f1bc Iustin Pop
    try:
650 5178f1bc Iustin Pop
      for retries in range(self.opts.net_timeout):
651 5178f1bc Iustin Pop
        try:
652 5178f1bc Iustin Pop
          url = urllib2.urlopen("http://%s/hostname.txt" % instance)
653 5178f1bc Iustin Pop
        except urllib2.URLError, err:
654 5178f1bc Iustin Pop
          if err.args[0][0] == errno.ECONNREFUSED:
655 5178f1bc Iustin Pop
            time.sleep(1)
656 5178f1bc Iustin Pop
            continue
657 5178f1bc Iustin Pop
          raise
658 5178f1bc Iustin Pop
    except urllib2.URLError, err:
659 5178f1bc Iustin Pop
      raise InstanceDown(instance, str(err))
660 5178f1bc Iustin Pop
    hostname = url.read().strip()
661 5178f1bc Iustin Pop
    if hostname != instance:
662 5178f1bc Iustin Pop
      raise InstanceDown(instance, ("Hostname mismatch, expected %s, got %s" %
663 5178f1bc Iustin Pop
                                    (instance, hostname)))
664 5178f1bc Iustin Pop
665 175f44c2 Iustin Pop
  def BurninCluster(self):
666 175f44c2 Iustin Pop
    """Test a cluster intensively.
667 175f44c2 Iustin Pop
668 175f44c2 Iustin Pop
    This will create instances and then start/stop/failover them.
669 175f44c2 Iustin Pop
    It is safe for existing instances but could impact performance.
670 175f44c2 Iustin Pop
671 175f44c2 Iustin Pop
    """
672 175f44c2 Iustin Pop
673 175f44c2 Iustin Pop
    opts = self.opts
674 175f44c2 Iustin Pop
675 836d59d7 Iustin Pop
    Log("Testing global parameters")
676 175f44c2 Iustin Pop
677 bd249e2f Iustin Pop
    if (len(self.nodes) == 1 and
678 2f505cb5 Manuel Franceschini
        opts.disk_template not in (constants.DT_DISKLESS, constants.DT_PLAIN,
679 2f505cb5 Manuel Franceschini
                                   constants.DT_FILE)):
680 836d59d7 Iustin Pop
      Err("When one node is available/selected the disk template must"
681 2f505cb5 Manuel Franceschini
          " be 'diskless', 'file' or 'plain'")
682 175f44c2 Iustin Pop
683 21546b1c Iustin Pop
    has_err = True
684 175f44c2 Iustin Pop
    try:
685 175f44c2 Iustin Pop
      self.CreateInstances()
686 175f44c2 Iustin Pop
      if opts.do_replace1 and opts.disk_template in constants.DTS_NET_MIRROR:
687 f9193417 Iustin Pop
        self.ReplaceDisks1D8()
688 175f44c2 Iustin Pop
      if (opts.do_replace2 and len(self.nodes) > 2 and
689 175f44c2 Iustin Pop
          opts.disk_template in constants.DTS_NET_MIRROR) :
690 175f44c2 Iustin Pop
        self.ReplaceDisks2()
691 175f44c2 Iustin Pop
692 659712c8 Iustin Pop
      if opts.disk_template != constants.DT_DISKLESS:
693 659712c8 Iustin Pop
        self.GrowDisks()
694 659712c8 Iustin Pop
695 175f44c2 Iustin Pop
      if opts.do_failover and opts.disk_template in constants.DTS_NET_MIRROR:
696 175f44c2 Iustin Pop
        self.Failover()
697 175f44c2 Iustin Pop
698 99bdd139 Iustin Pop
      if opts.do_migrate and opts.disk_template == constants.DT_DRBD8:
699 99bdd139 Iustin Pop
        self.Migrate()
700 99bdd139 Iustin Pop
701 a5e7be6b Iustin Pop
      if (opts.do_importexport and
702 a5e7be6b Iustin Pop
          opts.disk_template not in (constants.DT_DISKLESS,
703 a5e7be6b Iustin Pop
                                     constants.DT_FILE)):
704 bd5e77f9 Guido Trotter
        self.ImportExport()
705 bd5e77f9 Guido Trotter
706 00f91f29 Iustin Pop
      if opts.do_reinstall:
707 00f91f29 Iustin Pop
        self.Reinstall()
708 00f91f29 Iustin Pop
709 00f91f29 Iustin Pop
      if opts.do_reboot:
710 00f91f29 Iustin Pop
        self.Reboot()
711 00f91f29 Iustin Pop
712 5c22d16e Iustin Pop
      if opts.do_addremove_disks:
713 5c22d16e Iustin Pop
        self.AddRemoveDisks()
714 5c22d16e Iustin Pop
715 5c22d16e Iustin Pop
      if opts.do_addremove_nics:
716 5c22d16e Iustin Pop
        self.AddRemoveNICs()
717 5c22d16e Iustin Pop
718 90e722d1 Iustin Pop
      if opts.do_activate_disks:
719 90e722d1 Iustin Pop
        self.ActivateDisks()
720 90e722d1 Iustin Pop
721 054a8696 Manuel Franceschini
      if opts.rename:
722 054a8696 Manuel Franceschini
        self.Rename()
723 054a8696 Manuel Franceschini
724 eb61f8d3 Iustin Pop
      if opts.do_startstop:
725 eb61f8d3 Iustin Pop
        self.StopStart()
726 eb61f8d3 Iustin Pop
727 21546b1c Iustin Pop
      has_err = False
728 175f44c2 Iustin Pop
    finally:
729 21546b1c Iustin Pop
      if has_err:
730 21546b1c Iustin Pop
        Log("Error detected: opcode buffer follows:\n\n")
731 21546b1c Iustin Pop
        Log(self.GetFeedbackBuf())
732 21546b1c Iustin Pop
        Log("\n\n")
733 320eda24 Iustin Pop
      if not self.opts.keep_instances:
734 320eda24 Iustin Pop
        self.Remove()
735 175f44c2 Iustin Pop
736 175f44c2 Iustin Pop
    return 0
737 a8083063 Iustin Pop
738 01b69ec5 Michael Hanselmann
739 a8083063 Iustin Pop
def main():
740 3ecf6786 Iustin Pop
  """Main function"""
741 3ecf6786 Iustin Pop
742 175f44c2 Iustin Pop
  burner = Burner()
743 a4af651e Iustin Pop
  return burner.BurninCluster()
744 a8083063 Iustin Pop
745 01b69ec5 Michael Hanselmann
746 a8083063 Iustin Pop
if __name__ == "__main__":
747 3ecf6786 Iustin Pop
  main()