Revision 21546b1c tools/burnin
b/tools/burnin | ||
---|---|---|
6 | 6 |
import sys |
7 | 7 |
import optparse |
8 | 8 |
from itertools import izip, islice, cycle |
9 |
from cStringIO import StringIO |
|
9 | 10 |
|
10 | 11 |
from ganeti import opcodes |
11 | 12 |
from ganeti import mcpu |
... | ... | |
24 | 25 |
print >> sys.stderr, USAGE |
25 | 26 |
sys.exit(2) |
26 | 27 |
|
27 |
def Feedback(msg):
|
|
28 |
def Log(msg):
|
|
28 | 29 |
"""Simple function that prints out its argument. |
29 | 30 |
|
30 | 31 |
""" |
... | ... | |
35 | 36 |
|
36 | 37 |
def __init__(self): |
37 | 38 |
"""Constructor.""" |
38 |
logger.SetupLogging(debug=True, program="ganeti/burnin") |
|
39 |
self.proc = mcpu.Processor(feedback=Feedback) |
|
39 |
logger.SetupLogging(debug=False, program="ganeti/burnin") |
|
40 |
self._feed_buf = StringIO() |
|
41 |
self.proc = mcpu.Processor(feedback=self.Feedback) |
|
40 | 42 |
self.nodes = [] |
41 | 43 |
self.instances = [] |
42 | 44 |
self.to_rem = [] |
... | ... | |
44 | 46 |
self.ParseOptions() |
45 | 47 |
self.GetState() |
46 | 48 |
|
49 |
def ClearFeedbackBuf(self): |
|
50 |
"""Clear the feedback buffer.""" |
|
51 |
self._feed_buf.truncate(0) |
|
52 |
|
|
53 |
def GetFeedbackBuf(self): |
|
54 |
"""Return the contents of the buffer.""" |
|
55 |
return self._feed_buf.getvalue() |
|
56 |
|
|
57 |
def Feedback(self, msg): |
|
58 |
"""Acumulate feedback in our buffer.""" |
|
59 |
self._feed_buf.write(msg) |
|
60 |
self._feed_buf.write("\n") |
|
61 |
|
|
62 |
def ExecOp(self, op): |
|
63 |
"""Execute an opcode and manage the exec buffer.""" |
|
64 |
self.ClearFeedbackBuf() |
|
65 |
return self.proc.ExecOpCode(op) |
|
66 |
|
|
47 | 67 |
def ParseOptions(self): |
48 | 68 |
"""Parses the command line options. |
49 | 69 |
|
... | ... | |
96 | 116 |
elif options.disk_template == "drbd8": |
97 | 117 |
disk_template = constants.DT_DRBD8 |
98 | 118 |
else: |
99 |
Feedback("Unknown disk template '%s'" % options.disk_template)
|
|
119 |
Log("Unknown disk template '%s'" % options.disk_template)
|
|
100 | 120 |
sys.exit(1) |
101 | 121 |
|
102 | 122 |
options.disk_template = disk_template |
... | ... | |
111 | 131 |
names = [] |
112 | 132 |
try: |
113 | 133 |
op = opcodes.OpQueryNodes(output_fields=["name"], names=names) |
114 |
result = self.proc.ExecOpCode(op)
|
|
134 |
result = self.ExecOp(op)
|
|
115 | 135 |
except errors.GenericError, err: |
116 | 136 |
err_code, msg = cli.FormatError(err) |
117 |
Feedback(msg)
|
|
137 |
Log(msg)
|
|
118 | 138 |
sys.exit(err_code) |
119 | 139 |
self.nodes = [data[0] for data in result] |
120 | 140 |
|
121 |
result = self.proc.ExecOpCode(opcodes.OpDiagnoseOS())
|
|
141 |
result = self.ExecOp(opcodes.OpDiagnoseOS())
|
|
122 | 142 |
|
123 | 143 |
if not result: |
124 |
Feedback("Can't get the OS list")
|
|
144 |
Log("Can't get the OS list")
|
|
125 | 145 |
sys.exit(1) |
126 | 146 |
|
127 | 147 |
# filter non-valid OS-es |
... | ... | |
136 | 156 |
os_set &= set([os_inst.name for os_inst in oses[node]]) |
137 | 157 |
|
138 | 158 |
if self.opts.os not in os_set: |
139 |
Feedback("OS '%s' not found" % self.opts.os)
|
|
159 |
Log("OS '%s' not found" % self.opts.os)
|
|
140 | 160 |
sys.exit(1) |
141 | 161 |
|
142 | 162 |
def CreateInstances(self): |
... | ... | |
161 | 181 |
start=True, |
162 | 182 |
ip_check=True, |
163 | 183 |
wait_for_sync=True) |
164 |
Feedback("- Add instance %s on node %s" % (instance, pnode))
|
|
165 |
self.proc.ExecOpCode(op)
|
|
184 |
Log("- Add instance %s on node %s" % (instance, pnode))
|
|
185 |
self.ExecOp(op)
|
|
166 | 186 |
self.to_rem.append(instance) |
167 | 187 |
|
168 | 188 |
def ReplaceDisks1R1(self): |
... | ... | |
174 | 194 |
mode=constants.REPLACE_DISK_ALL, |
175 | 195 |
disks=["sda", "sdb"]) |
176 | 196 |
|
177 |
Feedback("- Replace disks for instance %s" % (instance))
|
|
178 |
self.proc.ExecOpCode(op)
|
|
197 |
Log("- Replace disks for instance %s" % (instance))
|
|
198 |
self.ExecOp(op)
|
|
179 | 199 |
|
180 | 200 |
def ReplaceDisks1D8(self): |
181 | 201 |
"""Replace disks on primary and secondary for drbd8.""" |
... | ... | |
184 | 204 |
op = opcodes.OpReplaceDisks(instance_name=instance, |
185 | 205 |
mode=mode, |
186 | 206 |
disks=["sda", "sdb"]) |
187 |
Feedback("- Replace disks (%s) for instance %s" % (mode, instance))
|
|
188 |
self.proc.ExecOpCode(op)
|
|
207 |
Log("- Replace disks (%s) for instance %s" % (mode, instance))
|
|
208 |
self.ExecOp(op)
|
|
189 | 209 |
|
190 | 210 |
def ReplaceDisks2(self): |
191 | 211 |
"""Replace secondary node.""" |
... | ... | |
201 | 221 |
mode=mode, |
202 | 222 |
remote_node=tnode, |
203 | 223 |
disks=["sda", "sdb"]) |
204 |
Feedback("- Replace secondary (%s) for instance %s" % (mode, instance))
|
|
205 |
self.proc.ExecOpCode(op)
|
|
224 |
Log("- Replace secondary (%s) for instance %s" % (mode, instance))
|
|
225 |
self.ExecOp(op)
|
|
206 | 226 |
|
207 | 227 |
def Failover(self): |
208 | 228 |
"""Failover the instances.""" |
... | ... | |
211 | 231 |
op = opcodes.OpFailoverInstance(instance_name=instance, |
212 | 232 |
ignore_consistency=False) |
213 | 233 |
|
214 |
Feedback("- Failover instance %s" % (instance))
|
|
215 |
self.proc.ExecOpCode(op)
|
|
234 |
Log("- Failover instance %s" % (instance))
|
|
235 |
self.ExecOp(op)
|
|
216 | 236 |
|
217 | 237 |
def StopStart(self): |
218 | 238 |
"""Stop/start the instances.""" |
219 | 239 |
for instance in self.instances: |
220 | 240 |
op = opcodes.OpShutdownInstance(instance_name=instance) |
221 |
Feedback("- Shutdown instance %s" % instance)
|
|
222 |
self.proc.ExecOpCode(op)
|
|
241 |
Log("- Shutdown instance %s" % instance)
|
|
242 |
self.ExecOp(op)
|
|
223 | 243 |
op = opcodes.OpStartupInstance(instance_name=instance, force=False) |
224 |
Feedback("- Start instance %s" % instance)
|
|
225 |
self.proc.ExecOpCode(op)
|
|
244 |
Log("- Start instance %s" % instance)
|
|
245 |
self.ExecOp(op)
|
|
226 | 246 |
|
227 | 247 |
def Remove(self): |
228 | 248 |
"""Remove the instances.""" |
229 | 249 |
for instance in self.to_rem: |
230 | 250 |
op = opcodes.OpRemoveInstance(instance_name=instance) |
231 |
Feedback("- Remove instance %s" % instance)
|
|
232 |
self.proc.ExecOpCode(op)
|
|
251 |
Log("- Remove instance %s" % instance)
|
|
252 |
self.ExecOp(op)
|
|
233 | 253 |
|
234 | 254 |
def BurninCluster(self): |
235 | 255 |
"""Test a cluster intensively. |
... | ... | |
241 | 261 |
|
242 | 262 |
opts = self.opts |
243 | 263 |
|
244 |
Feedback("- Testing global parameters")
|
|
264 |
Log("- Testing global parameters")
|
|
245 | 265 |
|
246 | 266 |
if len(self.nodes) == 1 and opts.disk_template != constants.DT_PLAIN: |
247 |
Feedback("When one node is available/selected the disk template must"
|
|
267 |
Log("When one node is available/selected the disk template must"
|
|
248 | 268 |
" be 'plain'") |
249 | 269 |
sys.exit(1) |
250 | 270 |
|
271 |
has_err = True |
|
251 | 272 |
try: |
252 | 273 |
self.CreateInstances() |
253 | 274 |
if opts.do_replace1 and opts.disk_template in constants.DTS_NET_MIRROR: |
... | ... | |
263 | 284 |
self.Failover() |
264 | 285 |
|
265 | 286 |
self.StopStart() |
266 |
|
|
287 |
has_err = False |
|
267 | 288 |
finally: |
289 |
if has_err: |
|
290 |
Log("Error detected: opcode buffer follows:\n\n") |
|
291 |
Log(self.GetFeedbackBuf()) |
|
292 |
Log("\n\n") |
|
268 | 293 |
self.Remove() |
269 | 294 |
|
270 | 295 |
return 0 |
Also available in: Unified diff