Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ 65fe4693

History | View | Annotate | Download (7.1 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
import sys
5 a8083063 Iustin Pop
import optparse
6 a8083063 Iustin Pop
7 a8083063 Iustin Pop
from ganeti import opcodes
8 a8083063 Iustin Pop
from ganeti import mcpu
9 a8083063 Iustin Pop
from ganeti import objects
10 a8083063 Iustin Pop
from ganeti import constants
11 a8083063 Iustin Pop
from ganeti import cli
12 a8083063 Iustin Pop
from ganeti import logger
13 9f13fc7a Iustin Pop
from ganeti import errors
14 9f13fc7a Iustin Pop
from ganeti import utils
15 a8083063 Iustin Pop
16 9f13fc7a Iustin Pop
USAGE = ("\tburnin -o OS_NAME [options...] instance_name ...")
17 a8083063 Iustin Pop
18 a8083063 Iustin Pop
def Usage():
19 a8083063 Iustin Pop
  """Shows program usage information and exits the program."""
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
  print >> sys.stderr, "Usage:"
22 a8083063 Iustin Pop
  print >> sys.stderr, USAGE
23 a8083063 Iustin Pop
  sys.exit(2)
24 a8083063 Iustin Pop
25 a8083063 Iustin Pop
26 a8083063 Iustin Pop
def Feedback(msg):
27 3ecf6786 Iustin Pop
  """Simple function that prints out its argument.
28 3ecf6786 Iustin Pop
29 3ecf6786 Iustin Pop
  """
30 3ecf6786 Iustin Pop
  print msg
31 a8083063 Iustin Pop
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
def ParseOptions():
34 a8083063 Iustin Pop
  """Parses the command line options.
35 a8083063 Iustin Pop
36 a8083063 Iustin Pop
  In case of command line errors, it will show the usage and exit the
37 a8083063 Iustin Pop
  program.
38 a8083063 Iustin Pop
39 a8083063 Iustin Pop
  Returns:
40 a8083063 Iustin Pop
    (options, args), as returned by OptionParser.parse_args
41 a8083063 Iustin Pop
  """
42 a8083063 Iustin Pop
43 a8083063 Iustin Pop
  parser = optparse.OptionParser(usage="\n%s" % USAGE,
44 a8083063 Iustin Pop
                                 version="%%prog (ganeti) %s" %
45 a8083063 Iustin Pop
                                 constants.RELEASE_VERSION,
46 a8083063 Iustin Pop
                                 option_class=cli.CliOption)
47 a8083063 Iustin Pop
48 a8083063 Iustin Pop
  parser.add_option("-o", "--os", dest="os", default=None,
49 a8083063 Iustin Pop
                    help="OS to use during burnin",
50 a8083063 Iustin Pop
                    metavar="<OS>")
51 a8083063 Iustin Pop
  parser.add_option("--os-size", dest="os_size", help="Disk size",
52 a8083063 Iustin Pop
                    default=4 * 1024, type="unit", metavar="<size>")
53 a8083063 Iustin Pop
  parser.add_option("--swap-size", dest="swap_size", help="Swap size",
54 a8083063 Iustin Pop
                    default=4 * 1024, type="unit", metavar="<size>")
55 a8083063 Iustin Pop
  parser.add_option("-v", "--verbose",
56 a8083063 Iustin Pop
                    action="store_true", dest="verbose", default=False,
57 a8083063 Iustin Pop
                    help="print command execution messages to stdout")
58 79f87a76 Iustin Pop
  parser.add_option("--no-replace1", dest="do_replace1",
59 9f13fc7a Iustin Pop
                    help="Do disk replacement with the same secondary",
60 9f13fc7a Iustin Pop
                    action="store_false", default=True)
61 79f87a76 Iustin Pop
  parser.add_option("--no-replace2", dest="do_replace2",
62 9f13fc7a Iustin Pop
                    help="Do disk replacement with a different secondary",
63 9f13fc7a Iustin Pop
                    action="store_false", default=True)
64 79f87a76 Iustin Pop
  parser.add_option("--no-failover", dest="do_failover",
65 9f13fc7a Iustin Pop
                    help="Do instance failovers", action="store_false",
66 9f13fc7a Iustin Pop
                    default=True)
67 79f87a76 Iustin Pop
  parser.add_option("-t", "--disk-template", dest="disk_template",
68 79f87a76 Iustin Pop
                    choices=("remote_raid1", "drbd8"), default="remote_raid1",
69 79f87a76 Iustin Pop
                    help="Template type for network mirroring (remote_raid1"
70 79f87a76 Iustin Pop
                    " or drbd8) [remote_raid1]")
71 519bfbae Iustin Pop
  parser.add_option("-n", "--nodes", dest="nodes", default="",
72 519bfbae Iustin Pop
                    help="Comma separated list of nodes to perform the burnin"
73 519bfbae Iustin Pop
                    " on (defaults to all nodes)")
74 a8083063 Iustin Pop
75 a8083063 Iustin Pop
  options, args = parser.parse_args()
76 9f13fc7a Iustin Pop
  if len(args) < 1 or options.os is None:
77 a8083063 Iustin Pop
    Usage()
78 a8083063 Iustin Pop
79 a8083063 Iustin Pop
  return options, args
80 a8083063 Iustin Pop
81 a8083063 Iustin Pop
82 a8083063 Iustin Pop
def BurninCluster(opts, args):
83 a8083063 Iustin Pop
  """Test a cluster intensively.
84 a8083063 Iustin Pop
85 a8083063 Iustin Pop
  This will create instances and then start/stop/failover them.
86 a8083063 Iustin Pop
  It is safe for existing instances but could impact performance.
87 a8083063 Iustin Pop
88 a8083063 Iustin Pop
  """
89 a8083063 Iustin Pop
90 a8083063 Iustin Pop
  logger.SetupLogging(debug=True, program="ganeti/burnin")
91 1a8c0ce1 Iustin Pop
  proc = mcpu.Processor(feedback=Feedback)
92 519bfbae Iustin Pop
  if opts.nodes:
93 519bfbae Iustin Pop
    names = opts.nodes.split(",")
94 519bfbae Iustin Pop
  else:
95 519bfbae Iustin Pop
    names = []
96 519bfbae Iustin Pop
  try:
97 519bfbae Iustin Pop
    result = proc.ExecOpCode(opcodes.OpQueryNodes(output_fields=["name"],
98 519bfbae Iustin Pop
                                                  names=names))
99 519bfbae Iustin Pop
  except errors.GenericError, err:
100 519bfbae Iustin Pop
    err_code, msg = cli.FormatError(err)
101 519bfbae Iustin Pop
    Feedback(msg)
102 519bfbae Iustin Pop
    return err_code
103 a8083063 Iustin Pop
  nodelist = [data[0] for data in result]
104 a8083063 Iustin Pop
105 a8083063 Iustin Pop
  Feedback("- Testing global parameters")
106 a8083063 Iustin Pop
107 1a8c0ce1 Iustin Pop
  result = proc.ExecOpCode(opcodes.OpDiagnoseOS())
108 a8083063 Iustin Pop
109 a8083063 Iustin Pop
  if not result:
110 a8083063 Iustin Pop
    Feedback("Can't get the OS list")
111 a8083063 Iustin Pop
    return 1
112 a8083063 Iustin Pop
113 a8083063 Iustin Pop
  # filter non-valid OS-es
114 a8083063 Iustin Pop
  oses = {}
115 a8083063 Iustin Pop
  for node_name in result:
116 a8083063 Iustin Pop
    oses[node_name] = [obj for obj in result[node_name]
117 a8083063 Iustin Pop
                       if isinstance(obj, objects.OS)]
118 a8083063 Iustin Pop
119 a8083063 Iustin Pop
  fnode = oses.keys()[0]
120 a8083063 Iustin Pop
  os_set = set([os_inst.name for os_inst in oses[fnode]])
121 a8083063 Iustin Pop
  del oses[fnode]
122 a8083063 Iustin Pop
  for node in oses:
123 a8083063 Iustin Pop
    os_set &= set([os_inst.name for os_inst in oses[node]])
124 a8083063 Iustin Pop
125 a8083063 Iustin Pop
  if opts.os not in os_set:
126 9f13fc7a Iustin Pop
    Feedback("OS '%s' not found" % opts.os)
127 a8083063 Iustin Pop
    return 1
128 a8083063 Iustin Pop
129 a8083063 Iustin Pop
  to_remove = []
130 79f87a76 Iustin Pop
  if opts.disk_template == "remote_raid1":
131 79f87a76 Iustin Pop
    disk_template = constants.DT_REMOTE_RAID1
132 79f87a76 Iustin Pop
  elif opts.disk_template == "drbd8":
133 79f87a76 Iustin Pop
    disk_template = constants.DT_DRBD8
134 79f87a76 Iustin Pop
  else:
135 79f87a76 Iustin Pop
    Feedback("Unknown disk template '%s'" % opts.disk_template)
136 79f87a76 Iustin Pop
    return 1
137 a8083063 Iustin Pop
  try:
138 a8083063 Iustin Pop
    idx = 0
139 a8083063 Iustin Pop
    for instance_name in args:
140 a8083063 Iustin Pop
      next_idx = idx + 1
141 a8083063 Iustin Pop
      if next_idx >= len(nodelist):
142 a8083063 Iustin Pop
        next_idx = 0
143 a8083063 Iustin Pop
      pnode = nodelist[idx]
144 a8083063 Iustin Pop
      snode = nodelist[next_idx]
145 a8083063 Iustin Pop
      if len(nodelist) > 1:
146 79f87a76 Iustin Pop
        tplate = disk_template
147 a8083063 Iustin Pop
      else:
148 a8083063 Iustin Pop
        tplate = constants.DT_PLAIN
149 a8083063 Iustin Pop
150 a8083063 Iustin Pop
      op = opcodes.OpCreateInstance(instance_name=instance_name, mem_size=128,
151 a8083063 Iustin Pop
                                    disk_size=opts.os_size,
152 a8083063 Iustin Pop
                                    swap_size=opts.swap_size,
153 a8083063 Iustin Pop
                                    disk_template=tplate,
154 a8083063 Iustin Pop
                                    mode=constants.INSTANCE_CREATE,
155 a8083063 Iustin Pop
                                    os_type=opts.os, pnode=pnode,
156 a8083063 Iustin Pop
                                    snode=snode, vcpus=1,
157 a8083063 Iustin Pop
                                    start=True,
158 e9f745aa Iustin Pop
                                    ip_check=True,
159 a8083063 Iustin Pop
                                    wait_for_sync=True)
160 a8083063 Iustin Pop
      Feedback("- Add instance %s on node %s" % (instance_name, pnode))
161 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
162 a8083063 Iustin Pop
      to_remove.append(instance_name)
163 a8083063 Iustin Pop
      idx = next_idx
164 a8083063 Iustin Pop
165 a8083063 Iustin Pop
166 9f13fc7a Iustin Pop
    if opts.do_replace1:
167 9f13fc7a Iustin Pop
      if len(nodelist) > 1:
168 9f13fc7a Iustin Pop
        # failover
169 9f13fc7a Iustin Pop
        for instance_name in args:
170 9f13fc7a Iustin Pop
          op = opcodes.OpReplaceDisks(instance_name=instance_name,
171 22d31e49 Michael Hanselmann
                                      remote_node=None,
172 22d31e49 Michael Hanselmann
                                      mode=constants.REPLACE_DISK_ALL,
173 22d31e49 Michael Hanselmann
                                      disks=["sda", "sdb"])
174 9f13fc7a Iustin Pop
175 9f13fc7a Iustin Pop
          Feedback("- Replace disks for instance %s" % (instance_name))
176 1a8c0ce1 Iustin Pop
          result = proc.ExecOpCode(op)
177 9f13fc7a Iustin Pop
      else:
178 9f13fc7a Iustin Pop
        Feedback("- Can't run replace1, not enough nodes")
179 a8083063 Iustin Pop
180 9f13fc7a Iustin Pop
    if opts.do_failover:
181 9f13fc7a Iustin Pop
      if len(nodelist) > 1:
182 9f13fc7a Iustin Pop
        # failover
183 9f13fc7a Iustin Pop
        for instance_name in args:
184 9f13fc7a Iustin Pop
          op = opcodes.OpFailoverInstance(instance_name=instance_name,
185 9f13fc7a Iustin Pop
                                          ignore_consistency=True)
186 9f13fc7a Iustin Pop
187 9f13fc7a Iustin Pop
          Feedback("- Failover instance %s" % (instance_name))
188 1a8c0ce1 Iustin Pop
          result = proc.ExecOpCode(op)
189 9f13fc7a Iustin Pop
      else:
190 9f13fc7a Iustin Pop
        Feedback("- Can't run failovers, not enough nodes")
191 a8083063 Iustin Pop
192 a8083063 Iustin Pop
    # stop / start
193 a8083063 Iustin Pop
    for instance_name in args:
194 a8083063 Iustin Pop
      op = opcodes.OpShutdownInstance(instance_name=instance_name)
195 a8083063 Iustin Pop
      Feedback("- Shutdown instance %s" % instance_name)
196 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
197 a8083063 Iustin Pop
      op = opcodes.OpStartupInstance(instance_name=instance_name, force=False)
198 a8083063 Iustin Pop
      Feedback("- Start instance %s" % instance_name)
199 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
200 a8083063 Iustin Pop
201 a8083063 Iustin Pop
  finally:
202 a8083063 Iustin Pop
    # remove
203 a8083063 Iustin Pop
    for instance_name in to_remove:
204 a8083063 Iustin Pop
      op = opcodes.OpRemoveInstance(instance_name=instance_name)
205 a8083063 Iustin Pop
      Feedback("- Remove instance %s" % instance_name)
206 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
207 a8083063 Iustin Pop
208 a8083063 Iustin Pop
  return 0
209 a8083063 Iustin Pop
210 a8083063 Iustin Pop
def main():
211 3ecf6786 Iustin Pop
  """Main function"""
212 3ecf6786 Iustin Pop
213 3ecf6786 Iustin Pop
  opts, args = ParseOptions()
214 3ecf6786 Iustin Pop
  try:
215 3ecf6786 Iustin Pop
    utils.Lock('cmd', max_retries=15, debug=True)
216 3ecf6786 Iustin Pop
  except errors.LockError, err:
217 3ecf6786 Iustin Pop
    logger.ToStderr(str(err))
218 3ecf6786 Iustin Pop
    return 1
219 3ecf6786 Iustin Pop
  try:
220 3ecf6786 Iustin Pop
    retval = BurninCluster(opts, args)
221 3ecf6786 Iustin Pop
  finally:
222 3ecf6786 Iustin Pop
    utils.Unlock('cmd')
223 3ecf6786 Iustin Pop
    utils.LockCleanup()
224 3ecf6786 Iustin Pop
  return retval
225 a8083063 Iustin Pop
226 a8083063 Iustin Pop
if __name__ == "__main__":
227 3ecf6786 Iustin Pop
  main()