Statistics
| Branch: | Tag: | Revision:

root / tools / burnin @ 1a8c0ce1

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