Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ 79f87a76

History | View | Annotate | Download (6.8 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 a8083063 Iustin Pop
72 a8083063 Iustin Pop
  options, args = parser.parse_args()
73 9f13fc7a Iustin Pop
  if len(args) < 1 or options.os is None:
74 a8083063 Iustin Pop
    Usage()
75 a8083063 Iustin Pop
76 a8083063 Iustin Pop
  return options, args
77 a8083063 Iustin Pop
78 a8083063 Iustin Pop
79 a8083063 Iustin Pop
def BurninCluster(opts, args):
80 a8083063 Iustin Pop
  """Test a cluster intensively.
81 a8083063 Iustin Pop
82 a8083063 Iustin Pop
  This will create instances and then start/stop/failover them.
83 a8083063 Iustin Pop
  It is safe for existing instances but could impact performance.
84 a8083063 Iustin Pop
85 a8083063 Iustin Pop
  """
86 a8083063 Iustin Pop
87 a8083063 Iustin Pop
  logger.SetupLogging(debug=True, program="ganeti/burnin")
88 1a8c0ce1 Iustin Pop
  proc = mcpu.Processor(feedback=Feedback)
89 246e180a Iustin Pop
  result = proc.ExecOpCode(opcodes.OpQueryNodes(output_fields=["name"],
90 1a8c0ce1 Iustin Pop
                                                names=[]))
91 a8083063 Iustin Pop
  nodelist = [data[0] for data in result]
92 a8083063 Iustin Pop
93 a8083063 Iustin Pop
  Feedback("- Testing global parameters")
94 a8083063 Iustin Pop
95 1a8c0ce1 Iustin Pop
  result = proc.ExecOpCode(opcodes.OpDiagnoseOS())
96 a8083063 Iustin Pop
97 a8083063 Iustin Pop
  if not result:
98 a8083063 Iustin Pop
    Feedback("Can't get the OS list")
99 a8083063 Iustin Pop
    return 1
100 a8083063 Iustin Pop
101 a8083063 Iustin Pop
  # filter non-valid OS-es
102 a8083063 Iustin Pop
  oses = {}
103 a8083063 Iustin Pop
  for node_name in result:
104 a8083063 Iustin Pop
    oses[node_name] = [obj for obj in result[node_name]
105 a8083063 Iustin Pop
                       if isinstance(obj, objects.OS)]
106 a8083063 Iustin Pop
107 a8083063 Iustin Pop
  fnode = oses.keys()[0]
108 a8083063 Iustin Pop
  os_set = set([os_inst.name for os_inst in oses[fnode]])
109 a8083063 Iustin Pop
  del oses[fnode]
110 a8083063 Iustin Pop
  for node in oses:
111 a8083063 Iustin Pop
    os_set &= set([os_inst.name for os_inst in oses[node]])
112 a8083063 Iustin Pop
113 a8083063 Iustin Pop
  if opts.os not in os_set:
114 9f13fc7a Iustin Pop
    Feedback("OS '%s' not found" % opts.os)
115 a8083063 Iustin Pop
    return 1
116 a8083063 Iustin Pop
117 a8083063 Iustin Pop
  to_remove = []
118 79f87a76 Iustin Pop
  if opts.disk_template == "remote_raid1":
119 79f87a76 Iustin Pop
    disk_template = constants.DT_REMOTE_RAID1
120 79f87a76 Iustin Pop
  elif opts.disk_template == "drbd8":
121 79f87a76 Iustin Pop
    disk_template = constants.DT_DRBD8
122 79f87a76 Iustin Pop
  else:
123 79f87a76 Iustin Pop
    Feedback("Unknown disk template '%s'" % opts.disk_template)
124 79f87a76 Iustin Pop
    return 1
125 a8083063 Iustin Pop
  try:
126 a8083063 Iustin Pop
    idx = 0
127 a8083063 Iustin Pop
    for instance_name in args:
128 a8083063 Iustin Pop
      next_idx = idx + 1
129 a8083063 Iustin Pop
      if next_idx >= len(nodelist):
130 a8083063 Iustin Pop
        next_idx = 0
131 a8083063 Iustin Pop
      pnode = nodelist[idx]
132 a8083063 Iustin Pop
      snode = nodelist[next_idx]
133 a8083063 Iustin Pop
      if len(nodelist) > 1:
134 79f87a76 Iustin Pop
        tplate = disk_template
135 a8083063 Iustin Pop
      else:
136 a8083063 Iustin Pop
        tplate = constants.DT_PLAIN
137 a8083063 Iustin Pop
138 a8083063 Iustin Pop
      op = opcodes.OpCreateInstance(instance_name=instance_name, mem_size=128,
139 a8083063 Iustin Pop
                                    disk_size=opts.os_size,
140 a8083063 Iustin Pop
                                    swap_size=opts.swap_size,
141 a8083063 Iustin Pop
                                    disk_template=tplate,
142 a8083063 Iustin Pop
                                    mode=constants.INSTANCE_CREATE,
143 a8083063 Iustin Pop
                                    os_type=opts.os, pnode=pnode,
144 a8083063 Iustin Pop
                                    snode=snode, vcpus=1,
145 a8083063 Iustin Pop
                                    start=True,
146 e9f745aa Iustin Pop
                                    ip_check=True,
147 a8083063 Iustin Pop
                                    wait_for_sync=True)
148 a8083063 Iustin Pop
      Feedback("- Add instance %s on node %s" % (instance_name, pnode))
149 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
150 a8083063 Iustin Pop
      to_remove.append(instance_name)
151 a8083063 Iustin Pop
      idx = next_idx
152 a8083063 Iustin Pop
153 a8083063 Iustin Pop
154 9f13fc7a Iustin Pop
    if opts.do_replace1:
155 9f13fc7a Iustin Pop
      if len(nodelist) > 1:
156 9f13fc7a Iustin Pop
        # failover
157 9f13fc7a Iustin Pop
        for instance_name in args:
158 9f13fc7a Iustin Pop
          op = opcodes.OpReplaceDisks(instance_name=instance_name,
159 22d31e49 Michael Hanselmann
                                      remote_node=None,
160 22d31e49 Michael Hanselmann
                                      mode=constants.REPLACE_DISK_ALL,
161 22d31e49 Michael Hanselmann
                                      disks=["sda", "sdb"])
162 9f13fc7a Iustin Pop
163 9f13fc7a Iustin Pop
          Feedback("- Replace disks for instance %s" % (instance_name))
164 1a8c0ce1 Iustin Pop
          result = proc.ExecOpCode(op)
165 9f13fc7a Iustin Pop
      else:
166 9f13fc7a Iustin Pop
        Feedback("- Can't run replace1, not enough nodes")
167 a8083063 Iustin Pop
168 9f13fc7a Iustin Pop
    if opts.do_failover:
169 9f13fc7a Iustin Pop
      if len(nodelist) > 1:
170 9f13fc7a Iustin Pop
        # failover
171 9f13fc7a Iustin Pop
        for instance_name in args:
172 9f13fc7a Iustin Pop
          op = opcodes.OpFailoverInstance(instance_name=instance_name,
173 9f13fc7a Iustin Pop
                                          ignore_consistency=True)
174 9f13fc7a Iustin Pop
175 9f13fc7a Iustin Pop
          Feedback("- Failover 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 failovers, not enough nodes")
179 a8083063 Iustin Pop
180 a8083063 Iustin Pop
    # stop / start
181 a8083063 Iustin Pop
    for instance_name in args:
182 a8083063 Iustin Pop
      op = opcodes.OpShutdownInstance(instance_name=instance_name)
183 a8083063 Iustin Pop
      Feedback("- Shutdown instance %s" % instance_name)
184 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
185 a8083063 Iustin Pop
      op = opcodes.OpStartupInstance(instance_name=instance_name, force=False)
186 a8083063 Iustin Pop
      Feedback("- Start instance %s" % instance_name)
187 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
188 a8083063 Iustin Pop
189 a8083063 Iustin Pop
  finally:
190 a8083063 Iustin Pop
    # remove
191 a8083063 Iustin Pop
    for instance_name in to_remove:
192 a8083063 Iustin Pop
      op = opcodes.OpRemoveInstance(instance_name=instance_name)
193 a8083063 Iustin Pop
      Feedback("- Remove instance %s" % instance_name)
194 1a8c0ce1 Iustin Pop
      result = proc.ExecOpCode(op)
195 a8083063 Iustin Pop
196 a8083063 Iustin Pop
  return 0
197 a8083063 Iustin Pop
198 a8083063 Iustin Pop
def main():
199 3ecf6786 Iustin Pop
  """Main function"""
200 3ecf6786 Iustin Pop
201 3ecf6786 Iustin Pop
  opts, args = ParseOptions()
202 3ecf6786 Iustin Pop
  try:
203 3ecf6786 Iustin Pop
    utils.Lock('cmd', max_retries=15, debug=True)
204 3ecf6786 Iustin Pop
  except errors.LockError, err:
205 3ecf6786 Iustin Pop
    logger.ToStderr(str(err))
206 3ecf6786 Iustin Pop
    return 1
207 3ecf6786 Iustin Pop
  try:
208 3ecf6786 Iustin Pop
    retval = BurninCluster(opts, args)
209 3ecf6786 Iustin Pop
  finally:
210 3ecf6786 Iustin Pop
    utils.Unlock('cmd')
211 3ecf6786 Iustin Pop
    utils.LockCleanup()
212 3ecf6786 Iustin Pop
  return retval
213 a8083063 Iustin Pop
214 a8083063 Iustin Pop
if __name__ == "__main__":
215 3ecf6786 Iustin Pop
  main()