Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ c2b05d85

History | View | Annotate | Download (17.3 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 175f44c2 Iustin Pop
from itertools import izip, islice, cycle
31 21546b1c Iustin Pop
from cStringIO import StringIO
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
from ganeti import opcodes
34 a8083063 Iustin Pop
from ganeti import mcpu
35 a8083063 Iustin Pop
from ganeti import constants
36 a8083063 Iustin Pop
from ganeti import cli
37 a8083063 Iustin Pop
from ganeti import logger
38 9f13fc7a Iustin Pop
from ganeti import errors
39 9f13fc7a Iustin Pop
from ganeti import utils
40 a8083063 Iustin Pop
41 01b69ec5 Michael Hanselmann
42 9f13fc7a Iustin Pop
USAGE = ("\tburnin -o OS_NAME [options...] instance_name ...")
43 a8083063 Iustin Pop
44 01b69ec5 Michael Hanselmann
45 a8083063 Iustin Pop
def Usage():
46 a8083063 Iustin Pop
  """Shows program usage information and exits the program."""
47 a8083063 Iustin Pop
48 a8083063 Iustin Pop
  print >> sys.stderr, "Usage:"
49 a8083063 Iustin Pop
  print >> sys.stderr, USAGE
50 a8083063 Iustin Pop
  sys.exit(2)
51 a8083063 Iustin Pop
52 01b69ec5 Michael Hanselmann
53 21546b1c Iustin Pop
def Log(msg):
54 3ecf6786 Iustin Pop
  """Simple function that prints out its argument.
55 3ecf6786 Iustin Pop
56 3ecf6786 Iustin Pop
  """
57 3ecf6786 Iustin Pop
  print msg
58 84cc52ab Michael Hanselmann
  sys.stdout.flush()
59 a8083063 Iustin Pop
60 01b69ec5 Michael Hanselmann
61 175f44c2 Iustin Pop
class Burner(object):
62 175f44c2 Iustin Pop
  """Burner class."""
63 175f44c2 Iustin Pop
64 175f44c2 Iustin Pop
  def __init__(self):
65 175f44c2 Iustin Pop
    """Constructor."""
66 59f187eb Iustin Pop
    logger.SetupLogging(constants.LOG_BURNIN, debug=False, stderr_logging=True)
67 21546b1c Iustin Pop
    self._feed_buf = StringIO()
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 ec5c88dc Iustin Pop
    self.cl = cli.GetClient()
73 175f44c2 Iustin Pop
    self.ParseOptions()
74 175f44c2 Iustin Pop
    self.GetState()
75 175f44c2 Iustin Pop
76 21546b1c Iustin Pop
  def ClearFeedbackBuf(self):
77 21546b1c Iustin Pop
    """Clear the feedback buffer."""
78 21546b1c Iustin Pop
    self._feed_buf.truncate(0)
79 21546b1c Iustin Pop
80 21546b1c Iustin Pop
  def GetFeedbackBuf(self):
81 21546b1c Iustin Pop
    """Return the contents of the buffer."""
82 21546b1c Iustin Pop
    return self._feed_buf.getvalue()
83 21546b1c Iustin Pop
84 21546b1c Iustin Pop
  def Feedback(self, msg):
85 21546b1c Iustin Pop
    """Acumulate feedback in our buffer."""
86 e17188f4 Iustin Pop
    self._feed_buf.write("%s %s\n" % (time.ctime(utils.MergeTime(msg[0])),
87 e17188f4 Iustin Pop
                                      msg[2]))
88 d7b47a77 Iustin Pop
    if self.opts.verbose:
89 d7b47a77 Iustin Pop
      Log(msg)
90 21546b1c Iustin Pop
91 21546b1c Iustin Pop
  def ExecOp(self, op):
92 21546b1c Iustin Pop
    """Execute an opcode and manage the exec buffer."""
93 21546b1c Iustin Pop
    self.ClearFeedbackBuf()
94 ec5c88dc Iustin Pop
    return cli.SubmitOpCode(op, feedback_fn=self.Feedback, cl=self.cl)
95 ec5c88dc Iustin Pop
96 ec5c88dc Iustin Pop
  def ExecJobSet(self, jobs):
97 ec5c88dc Iustin Pop
    """Execute a set of jobs and return once all are done.
98 ec5c88dc Iustin Pop
99 ec5c88dc Iustin Pop
    The method will return the list of results, if all jobs are
100 ec5c88dc Iustin Pop
    successfull. Otherwise, OpExecError will be raised from within
101 ec5c88dc Iustin Pop
    cli.py.
102 ec5c88dc Iustin Pop
103 ec5c88dc Iustin Pop
    """
104 ec5c88dc Iustin Pop
    self.ClearFeedbackBuf()
105 ec5c88dc Iustin Pop
    job_ids = [cli.SendJob(job, cl=self.cl) for job in jobs]
106 ec5c88dc Iustin Pop
    Log("- Submitted job IDs %s" % ", ".join(job_ids))
107 ec5c88dc Iustin Pop
    results = []
108 ec5c88dc Iustin Pop
    for jid in job_ids:
109 ec5c88dc Iustin Pop
      Log("- Waiting for job %s" % jid)
110 ec5c88dc Iustin Pop
      results.append(cli.PollJob(jid, cl=self.cl, feedback_fn=self.Feedback))
111 ec5c88dc Iustin Pop
112 ec5c88dc Iustin Pop
    return results
113 21546b1c Iustin Pop
114 175f44c2 Iustin Pop
  def ParseOptions(self):
115 175f44c2 Iustin Pop
    """Parses the command line options.
116 175f44c2 Iustin Pop
117 175f44c2 Iustin Pop
    In case of command line errors, it will show the usage and exit the
118 175f44c2 Iustin Pop
    program.
119 175f44c2 Iustin Pop
120 175f44c2 Iustin Pop
    """
121 175f44c2 Iustin Pop
122 175f44c2 Iustin Pop
    parser = optparse.OptionParser(usage="\n%s" % USAGE,
123 175f44c2 Iustin Pop
                                   version="%%prog (ganeti) %s" %
124 175f44c2 Iustin Pop
                                   constants.RELEASE_VERSION,
125 175f44c2 Iustin Pop
                                   option_class=cli.CliOption)
126 175f44c2 Iustin Pop
127 175f44c2 Iustin Pop
    parser.add_option("-o", "--os", dest="os", default=None,
128 175f44c2 Iustin Pop
                      help="OS to use during burnin",
129 175f44c2 Iustin Pop
                      metavar="<OS>")
130 175f44c2 Iustin Pop
    parser.add_option("--os-size", dest="os_size", help="Disk size",
131 175f44c2 Iustin Pop
                      default=4 * 1024, type="unit", metavar="<size>")
132 175f44c2 Iustin Pop
    parser.add_option("--swap-size", dest="swap_size", help="Swap size",
133 175f44c2 Iustin Pop
                      default=4 * 1024, type="unit", metavar="<size>")
134 5e767b34 Iustin Pop
    parser.add_option("--mem-size", dest="mem_size", help="Memory size",
135 5e767b34 Iustin Pop
                      default=128, type="unit", metavar="<size>")
136 175f44c2 Iustin Pop
    parser.add_option("-v", "--verbose",
137 175f44c2 Iustin Pop
                      action="store_true", dest="verbose", default=False,
138 175f44c2 Iustin Pop
                      help="print command execution messages to stdout")
139 175f44c2 Iustin Pop
    parser.add_option("--no-replace1", dest="do_replace1",
140 175f44c2 Iustin Pop
                      help="Skip disk replacement with the same secondary",
141 175f44c2 Iustin Pop
                      action="store_false", default=True)
142 175f44c2 Iustin Pop
    parser.add_option("--no-replace2", dest="do_replace2",
143 175f44c2 Iustin Pop
                      help="Skip disk replacement with a different secondary",
144 175f44c2 Iustin Pop
                      action="store_false", default=True)
145 175f44c2 Iustin Pop
    parser.add_option("--no-failover", dest="do_failover",
146 175f44c2 Iustin Pop
                      help="Skip instance failovers", action="store_false",
147 175f44c2 Iustin Pop
                      default=True)
148 bd5e77f9 Guido Trotter
    parser.add_option("--no-importexport", dest="do_importexport",
149 bd5e77f9 Guido Trotter
                      help="Skip instance export/import", action="store_false",
150 bd5e77f9 Guido Trotter
                      default=True)
151 d4844f0f Guido Trotter
    parser.add_option("--no-startstop", dest="do_startstop",
152 d4844f0f Guido Trotter
                      help="Skip instance stop/start", action="store_false",
153 d4844f0f Guido Trotter
                      default=True)
154 054a8696 Manuel Franceschini
    parser.add_option("--rename", dest="rename", default=None,
155 054a8696 Manuel Franceschini
                      help="Give one unused instance name which is taken"
156 054a8696 Manuel Franceschini
                           " to start the renaming sequence",
157 054a8696 Manuel Franceschini
                      metavar="<instance_name>")
158 175f44c2 Iustin Pop
    parser.add_option("-t", "--disk-template", dest="disk_template",
159 2f505cb5 Manuel Franceschini
                      choices=("diskless", "file", "plain", "drbd"),
160 f9193417 Iustin Pop
                      default="drbd",
161 2f505cb5 Manuel Franceschini
                      help="Disk template (diskless, file, plain or drbd)"
162 2f505cb5 Manuel Franceschini
                            " [drbd]")
163 175f44c2 Iustin Pop
    parser.add_option("-n", "--nodes", dest="nodes", default="",
164 175f44c2 Iustin Pop
                      help="Comma separated list of nodes to perform"
165 175f44c2 Iustin Pop
                      " the burnin on (defaults to all nodes)")
166 b91bde14 Iustin Pop
    parser.add_option("--iallocator", dest="iallocator",
167 b91bde14 Iustin Pop
                      default=None, type="string",
168 b91bde14 Iustin Pop
                      help="Perform the allocation using an iallocator"
169 b91bde14 Iustin Pop
                      " instead of fixed node spread (node restrictions no"
170 b91bde14 Iustin Pop
                      " longer apply, therefore -n/--nodes must not be used")
171 ec5c88dc Iustin Pop
    parser.add_option("-p", "--parallel", default=False, action="store_true",
172 ec5c88dc Iustin Pop
                      dest="parallel",
173 ec5c88dc Iustin Pop
                      help="Enable parallelization of some operations in"
174 ec5c88dc Iustin Pop
                      " order to speed burnin or to test granular locking")
175 175f44c2 Iustin Pop
176 175f44c2 Iustin Pop
    options, args = parser.parse_args()
177 175f44c2 Iustin Pop
    if len(args) < 1 or options.os is None:
178 175f44c2 Iustin Pop
      Usage()
179 175f44c2 Iustin Pop
180 f9193417 Iustin Pop
    supported_disk_templates = (constants.DT_DISKLESS,
181 2f505cb5 Manuel Franceschini
                                constants.DT_FILE,
182 f9193417 Iustin Pop
                                constants.DT_PLAIN,
183 12c3449a Michael Hanselmann
                                constants.DT_DRBD8)
184 12c3449a Michael Hanselmann
    if options.disk_template not in supported_disk_templates:
185 21546b1c Iustin Pop
      Log("Unknown disk template '%s'" % options.disk_template)
186 175f44c2 Iustin Pop
      sys.exit(1)
187 175f44c2 Iustin Pop
188 b91bde14 Iustin Pop
    if options.nodes and options.iallocator:
189 b91bde14 Iustin Pop
      Log("Give either the nodes option or the iallocator option, not both")
190 b91bde14 Iustin Pop
      sys.exit(1)
191 b91bde14 Iustin Pop
192 175f44c2 Iustin Pop
    self.opts = options
193 175f44c2 Iustin Pop
    self.instances = args
194 175f44c2 Iustin Pop
195 175f44c2 Iustin Pop
  def GetState(self):
196 175f44c2 Iustin Pop
    """Read the cluster state from the config."""
197 175f44c2 Iustin Pop
    if self.opts.nodes:
198 175f44c2 Iustin Pop
      names = self.opts.nodes.split(",")
199 175f44c2 Iustin Pop
    else:
200 175f44c2 Iustin Pop
      names = []
201 175f44c2 Iustin Pop
    try:
202 175f44c2 Iustin Pop
      op = opcodes.OpQueryNodes(output_fields=["name"], names=names)
203 21546b1c Iustin Pop
      result = self.ExecOp(op)
204 175f44c2 Iustin Pop
    except errors.GenericError, err:
205 175f44c2 Iustin Pop
      err_code, msg = cli.FormatError(err)
206 21546b1c Iustin Pop
      Log(msg)
207 175f44c2 Iustin Pop
      sys.exit(err_code)
208 175f44c2 Iustin Pop
    self.nodes = [data[0] for data in result]
209 175f44c2 Iustin Pop
210 1f9430d6 Iustin Pop
    result = self.ExecOp(opcodes.OpDiagnoseOS(output_fields=["name", "valid"],
211 1f9430d6 Iustin Pop
                                              names=[]))
212 175f44c2 Iustin Pop
213 175f44c2 Iustin Pop
    if not result:
214 21546b1c Iustin Pop
      Log("Can't get the OS list")
215 175f44c2 Iustin Pop
      sys.exit(1)
216 175f44c2 Iustin Pop
217 175f44c2 Iustin Pop
    # filter non-valid OS-es
218 1f9430d6 Iustin Pop
    os_set = [val[0] for val in result if val[1]]
219 175f44c2 Iustin Pop
220 175f44c2 Iustin Pop
    if self.opts.os not in os_set:
221 21546b1c Iustin Pop
      Log("OS '%s' not found" % self.opts.os)
222 175f44c2 Iustin Pop
      sys.exit(1)
223 175f44c2 Iustin Pop
224 175f44c2 Iustin Pop
  def CreateInstances(self):
225 175f44c2 Iustin Pop
    """Create the given instances.
226 175f44c2 Iustin Pop
227 175f44c2 Iustin Pop
    """
228 175f44c2 Iustin Pop
    self.to_rem = []
229 175f44c2 Iustin Pop
    mytor = izip(cycle(self.nodes),
230 175f44c2 Iustin Pop
                 islice(cycle(self.nodes), 1, None),
231 175f44c2 Iustin Pop
                 self.instances)
232 ec5c88dc Iustin Pop
    jobset = []
233 175f44c2 Iustin Pop
    for pnode, snode, instance in mytor:
234 b91bde14 Iustin Pop
      if self.opts.iallocator:
235 b91bde14 Iustin Pop
        pnode = snode = None
236 6d54548e Guido Trotter
        Log("- Add instance %s (iallocator: %s)" %
237 6d54548e Guido Trotter
              (instance, self.opts.iallocator))
238 6d54548e Guido Trotter
      elif self.opts.disk_template not in constants.DTS_NET_MIRROR:
239 6d54548e Guido Trotter
        snode = None
240 6d54548e Guido Trotter
        Log("- Add instance %s on node %s" % (instance, pnode))
241 6d54548e Guido Trotter
      else:
242 6d54548e Guido Trotter
        Log("- Add instance %s on nodes %s/%s" % (instance, pnode, snode))
243 6d54548e Guido Trotter
244 175f44c2 Iustin Pop
      op = opcodes.OpCreateInstance(instance_name=instance,
245 5e767b34 Iustin Pop
                                    mem_size=self.opts.mem_size,
246 175f44c2 Iustin Pop
                                    disk_size=self.opts.os_size,
247 175f44c2 Iustin Pop
                                    swap_size=self.opts.swap_size,
248 175f44c2 Iustin Pop
                                    disk_template=self.opts.disk_template,
249 a8083063 Iustin Pop
                                    mode=constants.INSTANCE_CREATE,
250 175f44c2 Iustin Pop
                                    os_type=self.opts.os,
251 175f44c2 Iustin Pop
                                    pnode=pnode,
252 175f44c2 Iustin Pop
                                    snode=snode,
253 175f44c2 Iustin Pop
                                    vcpus=1,
254 a8083063 Iustin Pop
                                    start=True,
255 e9f745aa Iustin Pop
                                    ip_check=True,
256 4501af56 Iustin Pop
                                    wait_for_sync=True,
257 4501af56 Iustin Pop
                                    mac="auto",
258 4501af56 Iustin Pop
                                    kernel_path=None,
259 25c5878d Alexander Schreiber
                                    initrd_path=None,
260 2f505cb5 Manuel Franceschini
                                    hvm_boot_order=None,
261 2f505cb5 Manuel Franceschini
                                    file_driver="loop",
262 b91bde14 Iustin Pop
                                    file_storage_dir=None,
263 6e2dc934 Alexander Schreiber
                                    iallocator=self.opts.iallocator,
264 6e2dc934 Alexander Schreiber
                                    hvm_nic_type=constants.HT_HVM_NIC_RTL8139,
265 6e2dc934 Alexander Schreiber
                                    hvm_disk_type=constants.HT_HVM_DEV_IOEMU)
266 6e2dc934 Alexander Schreiber
267 ec5c88dc Iustin Pop
      if self.opts.parallel:
268 ec5c88dc Iustin Pop
        jobset.append([op])
269 ec5c88dc Iustin Pop
        # FIXME: here we should not append to to_rem uncoditionally,
270 ec5c88dc Iustin Pop
        # but only when the job is successful
271 ec5c88dc Iustin Pop
        self.to_rem.append(instance)
272 ec5c88dc Iustin Pop
      else:
273 ec5c88dc Iustin Pop
        self.ExecOp(op)
274 ec5c88dc Iustin Pop
        self.to_rem.append(instance)
275 ec5c88dc Iustin Pop
    if self.opts.parallel:
276 ec5c88dc Iustin Pop
      self.ExecJobSet(jobset)
277 175f44c2 Iustin Pop
278 175f44c2 Iustin Pop
  def ReplaceDisks1D8(self):
279 175f44c2 Iustin Pop
    """Replace disks on primary and secondary for drbd8."""
280 175f44c2 Iustin Pop
    for instance in self.instances:
281 175f44c2 Iustin Pop
      for mode in constants.REPLACE_DISK_SEC, constants.REPLACE_DISK_PRI:
282 175f44c2 Iustin Pop
        op = opcodes.OpReplaceDisks(instance_name=instance,
283 175f44c2 Iustin Pop
                                    mode=mode,
284 175f44c2 Iustin Pop
                                    disks=["sda", "sdb"])
285 21546b1c Iustin Pop
        Log("- Replace disks (%s) for instance %s" % (mode, instance))
286 21546b1c Iustin Pop
        self.ExecOp(op)
287 175f44c2 Iustin Pop
288 175f44c2 Iustin Pop
  def ReplaceDisks2(self):
289 175f44c2 Iustin Pop
    """Replace secondary node."""
290 f9193417 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
291 175f44c2 Iustin Pop
292 175f44c2 Iustin Pop
    mytor = izip(islice(cycle(self.nodes), 2, None),
293 175f44c2 Iustin Pop
                 self.instances)
294 175f44c2 Iustin Pop
    for tnode, instance in mytor:
295 b6e82a65 Iustin Pop
      if self.opts.iallocator:
296 b6e82a65 Iustin Pop
        tnode = None
297 175f44c2 Iustin Pop
      op = opcodes.OpReplaceDisks(instance_name=instance,
298 175f44c2 Iustin Pop
                                  mode=mode,
299 175f44c2 Iustin Pop
                                  remote_node=tnode,
300 b6e82a65 Iustin Pop
                                  iallocator=self.opts.iallocator,
301 175f44c2 Iustin Pop
                                  disks=["sda", "sdb"])
302 21546b1c Iustin Pop
      Log("- Replace secondary (%s) for instance %s" % (mode, instance))
303 21546b1c Iustin Pop
      self.ExecOp(op)
304 175f44c2 Iustin Pop
305 175f44c2 Iustin Pop
  def Failover(self):
306 175f44c2 Iustin Pop
    """Failover the instances."""
307 175f44c2 Iustin Pop
308 175f44c2 Iustin Pop
    for instance in self.instances:
309 175f44c2 Iustin Pop
      op = opcodes.OpFailoverInstance(instance_name=instance,
310 175f44c2 Iustin Pop
                                      ignore_consistency=False)
311 175f44c2 Iustin Pop
312 21546b1c Iustin Pop
      Log("- Failover instance %s" % (instance))
313 21546b1c Iustin Pop
      self.ExecOp(op)
314 175f44c2 Iustin Pop
315 bd5e77f9 Guido Trotter
  def ImportExport(self):
316 bd5e77f9 Guido Trotter
    """Export the instance, delete it, and import it back.
317 bd5e77f9 Guido Trotter
318 bd5e77f9 Guido Trotter
    """
319 bd5e77f9 Guido Trotter
320 bd5e77f9 Guido Trotter
    mytor = izip(cycle(self.nodes),
321 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 1, None),
322 bd5e77f9 Guido Trotter
                 islice(cycle(self.nodes), 2, None),
323 bd5e77f9 Guido Trotter
                 self.instances)
324 bd5e77f9 Guido Trotter
325 bd5e77f9 Guido Trotter
    for pnode, snode, enode, instance in mytor:
326 f9af35c8 Guido Trotter
327 f9af35c8 Guido Trotter
      if self.opts.iallocator:
328 f9af35c8 Guido Trotter
        pnode = snode = None
329 f9af35c8 Guido Trotter
        import_log_msg = ("- Import instance %s from node %s (iallocator: %s)" %
330 f9af35c8 Guido Trotter
                          (instance, enode, self.opts.iallocator))
331 f9af35c8 Guido Trotter
      elif self.opts.disk_template not in constants.DTS_NET_MIRROR:
332 f9af35c8 Guido Trotter
        snode = None
333 f9af35c8 Guido Trotter
        import_log_msg = ("- Import instance %s from node %s to node %s" %
334 f9af35c8 Guido Trotter
                          (instance, enode, pnode))
335 f9af35c8 Guido Trotter
      else:
336 f9af35c8 Guido Trotter
        import_log_msg = ("- Import instance %s from node %s to nodes %s/%s" %
337 f9af35c8 Guido Trotter
                          (instance, enode, pnode, snode))
338 f9af35c8 Guido Trotter
339 bd5e77f9 Guido Trotter
      exp_op = opcodes.OpExportInstance(instance_name=instance,
340 bd5e77f9 Guido Trotter
                                           target_node=enode,
341 bd5e77f9 Guido Trotter
                                           shutdown=True)
342 5c54b832 Iustin Pop
      rem_op = opcodes.OpRemoveInstance(instance_name=instance,
343 5c54b832 Iustin Pop
                                        ignore_failures=True)
344 bd5e77f9 Guido Trotter
      nam_op = opcodes.OpQueryInstances(output_fields=["name"],
345 bd5e77f9 Guido Trotter
                                           names=[instance])
346 bd5e77f9 Guido Trotter
      full_name = self.ExecOp(nam_op)[0][0]
347 bd5e77f9 Guido Trotter
      imp_dir = os.path.join(constants.EXPORT_DIR, full_name)
348 bd5e77f9 Guido Trotter
      imp_op = opcodes.OpCreateInstance(instance_name=instance,
349 bd5e77f9 Guido Trotter
                                        mem_size=128,
350 bd5e77f9 Guido Trotter
                                        disk_size=self.opts.os_size,
351 bd5e77f9 Guido Trotter
                                        swap_size=self.opts.swap_size,
352 bd5e77f9 Guido Trotter
                                        disk_template=self.opts.disk_template,
353 bd5e77f9 Guido Trotter
                                        mode=constants.INSTANCE_IMPORT,
354 bd5e77f9 Guido Trotter
                                        src_node=enode,
355 bd5e77f9 Guido Trotter
                                        src_path=imp_dir,
356 bd5e77f9 Guido Trotter
                                        pnode=pnode,
357 bd5e77f9 Guido Trotter
                                        snode=snode,
358 bd5e77f9 Guido Trotter
                                        vcpus=1,
359 bd5e77f9 Guido Trotter
                                        start=True,
360 bd5e77f9 Guido Trotter
                                        ip_check=True,
361 bd5e77f9 Guido Trotter
                                        wait_for_sync=True,
362 96bb2f71 Manuel Franceschini
                                        mac="auto",
363 96bb2f71 Manuel Franceschini
                                        file_storage_dir=None,
364 f9af35c8 Guido Trotter
                                        file_driver=None,
365 6e2dc934 Alexander Schreiber
                                        iallocator=self.opts.iallocator,
366 6e2dc934 Alexander Schreiber
                                        hvm_nic_type=
367 6e2dc934 Alexander Schreiber
                                        constants.HT_HVM_NIC_RTL8139,
368 6e2dc934 Alexander Schreiber
                                        hvm_disk_type=
369 6e2dc934 Alexander Schreiber
                                        constants.HT_HVM_DEV_IOEMU)
370 6e2dc934 Alexander Schreiber
371 4a7ff493 Guido Trotter
      erem_op = opcodes.OpRemoveExport(instance_name=instance)
372 bd5e77f9 Guido Trotter
373 bd5e77f9 Guido Trotter
      Log("- Export instance %s to node %s" % (instance, enode))
374 bd5e77f9 Guido Trotter
      self.ExecOp(exp_op)
375 bd5e77f9 Guido Trotter
      Log("- Remove instance %s" % (instance))
376 bd5e77f9 Guido Trotter
      self.ExecOp(rem_op)
377 bd5e77f9 Guido Trotter
      self.to_rem.remove(instance)
378 f9af35c8 Guido Trotter
      Log(import_log_msg)
379 bd5e77f9 Guido Trotter
      self.ExecOp(imp_op)
380 4a7ff493 Guido Trotter
      Log("- Remove export of instance %s" % (instance))
381 4a7ff493 Guido Trotter
      self.ExecOp(erem_op)
382 4a7ff493 Guido Trotter
383 bd5e77f9 Guido Trotter
      self.to_rem.append(instance)
384 bd5e77f9 Guido Trotter
385 054a8696 Manuel Franceschini
  def StopInstance(self, instance):
386 054a8696 Manuel Franceschini
    """Stop given instance."""
387 054a8696 Manuel Franceschini
    op = opcodes.OpShutdownInstance(instance_name=instance)
388 054a8696 Manuel Franceschini
    Log("- Shutdown instance %s" % instance)
389 054a8696 Manuel Franceschini
    self.ExecOp(op)
390 054a8696 Manuel Franceschini
391 054a8696 Manuel Franceschini
  def StartInstance(self, instance):
392 054a8696 Manuel Franceschini
    """Start given instance."""
393 054a8696 Manuel Franceschini
    op = opcodes.OpStartupInstance(instance_name=instance, force=False)
394 054a8696 Manuel Franceschini
    Log("- Start instance %s" % instance)
395 054a8696 Manuel Franceschini
    self.ExecOp(op)
396 054a8696 Manuel Franceschini
397 054a8696 Manuel Franceschini
  def RenameInstance(self, instance, instance_new):
398 054a8696 Manuel Franceschini
    """Rename instance."""
399 054a8696 Manuel Franceschini
    op = opcodes.OpRenameInstance(instance_name=instance,
400 054a8696 Manuel Franceschini
                                  new_name=instance_new)
401 054a8696 Manuel Franceschini
    Log("- Rename instance %s to %s" % (instance, instance_new))
402 054a8696 Manuel Franceschini
    self.ExecOp(op)
403 054a8696 Manuel Franceschini
404 175f44c2 Iustin Pop
  def StopStart(self):
405 175f44c2 Iustin Pop
    """Stop/start the instances."""
406 175f44c2 Iustin Pop
    for instance in self.instances:
407 054a8696 Manuel Franceschini
      self.StopInstance(instance)
408 054a8696 Manuel Franceschini
      self.StartInstance(instance)
409 175f44c2 Iustin Pop
410 175f44c2 Iustin Pop
  def Remove(self):
411 175f44c2 Iustin Pop
    """Remove the instances."""
412 175f44c2 Iustin Pop
    for instance in self.to_rem:
413 5c54b832 Iustin Pop
      op = opcodes.OpRemoveInstance(instance_name=instance,
414 5c54b832 Iustin Pop
                                    ignore_failures=True)
415 21546b1c Iustin Pop
      Log("- Remove instance %s" % instance)
416 21546b1c Iustin Pop
      self.ExecOp(op)
417 175f44c2 Iustin Pop
418 054a8696 Manuel Franceschini
419 054a8696 Manuel Franceschini
  def Rename(self):
420 054a8696 Manuel Franceschini
    """Rename the instances."""
421 054a8696 Manuel Franceschini
    rename = self.opts.rename
422 054a8696 Manuel Franceschini
    for instance in self.instances:
423 054a8696 Manuel Franceschini
      self.StopInstance(instance)
424 054a8696 Manuel Franceschini
      self.RenameInstance(instance, rename)
425 054a8696 Manuel Franceschini
      self.StartInstance(rename)
426 054a8696 Manuel Franceschini
      self.StopInstance(rename)
427 054a8696 Manuel Franceschini
      self.RenameInstance(rename, instance)
428 054a8696 Manuel Franceschini
      self.StartInstance(instance)
429 054a8696 Manuel Franceschini
430 175f44c2 Iustin Pop
  def BurninCluster(self):
431 175f44c2 Iustin Pop
    """Test a cluster intensively.
432 175f44c2 Iustin Pop
433 175f44c2 Iustin Pop
    This will create instances and then start/stop/failover them.
434 175f44c2 Iustin Pop
    It is safe for existing instances but could impact performance.
435 175f44c2 Iustin Pop
436 175f44c2 Iustin Pop
    """
437 175f44c2 Iustin Pop
438 175f44c2 Iustin Pop
    opts = self.opts
439 175f44c2 Iustin Pop
440 21546b1c Iustin Pop
    Log("- Testing global parameters")
441 175f44c2 Iustin Pop
442 bd249e2f Iustin Pop
    if (len(self.nodes) == 1 and
443 2f505cb5 Manuel Franceschini
        opts.disk_template not in (constants.DT_DISKLESS, constants.DT_PLAIN,
444 2f505cb5 Manuel Franceschini
                                   constants.DT_FILE)):
445 21546b1c Iustin Pop
      Log("When one node is available/selected the disk template must"
446 2f505cb5 Manuel Franceschini
          " be 'diskless', 'file' or 'plain'")
447 175f44c2 Iustin Pop
      sys.exit(1)
448 175f44c2 Iustin Pop
449 21546b1c Iustin Pop
    has_err = True
450 175f44c2 Iustin Pop
    try:
451 175f44c2 Iustin Pop
      self.CreateInstances()
452 175f44c2 Iustin Pop
      if opts.do_replace1 and opts.disk_template in constants.DTS_NET_MIRROR:
453 f9193417 Iustin Pop
        self.ReplaceDisks1D8()
454 175f44c2 Iustin Pop
      if (opts.do_replace2 and len(self.nodes) > 2 and
455 175f44c2 Iustin Pop
          opts.disk_template in constants.DTS_NET_MIRROR) :
456 175f44c2 Iustin Pop
        self.ReplaceDisks2()
457 175f44c2 Iustin Pop
458 175f44c2 Iustin Pop
      if opts.do_failover and opts.disk_template in constants.DTS_NET_MIRROR:
459 175f44c2 Iustin Pop
        self.Failover()
460 175f44c2 Iustin Pop
461 bd5e77f9 Guido Trotter
      if opts.do_importexport:
462 bd5e77f9 Guido Trotter
        self.ImportExport()
463 bd5e77f9 Guido Trotter
464 d4844f0f Guido Trotter
      if opts.do_startstop:
465 d4844f0f Guido Trotter
        self.StopStart()
466 d4844f0f Guido Trotter
467 054a8696 Manuel Franceschini
      if opts.rename:
468 054a8696 Manuel Franceschini
        self.Rename()
469 054a8696 Manuel Franceschini
470 21546b1c Iustin Pop
      has_err = False
471 175f44c2 Iustin Pop
    finally:
472 21546b1c Iustin Pop
      if has_err:
473 21546b1c Iustin Pop
        Log("Error detected: opcode buffer follows:\n\n")
474 21546b1c Iustin Pop
        Log(self.GetFeedbackBuf())
475 21546b1c Iustin Pop
        Log("\n\n")
476 175f44c2 Iustin Pop
      self.Remove()
477 175f44c2 Iustin Pop
478 175f44c2 Iustin Pop
    return 0
479 a8083063 Iustin Pop
480 01b69ec5 Michael Hanselmann
481 a8083063 Iustin Pop
def main():
482 3ecf6786 Iustin Pop
  """Main function"""
483 3ecf6786 Iustin Pop
484 175f44c2 Iustin Pop
  burner = Burner()
485 a4af651e Iustin Pop
  return burner.BurninCluster()
486 a8083063 Iustin Pop
487 01b69ec5 Michael Hanselmann
488 a8083063 Iustin Pop
if __name__ == "__main__":
489 3ecf6786 Iustin Pop
  main()