Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ 64381ad7

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