Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ 5c54b832

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