ia64/xen-unstable

view tools/xenmon/xenmon.py @ 16510:7bee812a0397

Fix xenmon.py to work on Solaris

The xenmon.py script does not work on Solaris because of (1) its
assumption that xenbaked is in the users path and, (2) the use of the
killall command. Changed xenmon.py to use pkill instead and provided
the path to xenbaked on Solaris.

Signed-off-by: Tariq Magdon-Ismail <tariqmi@sun.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Dec 04 10:40:48 2007 +0000 (2007-12-04)
parents b28ae5f00553
children
line source
1 #!/usr/bin/env python
3 #####################################################################
4 # xenmon is a front-end for xenbaked.
5 # There is a curses interface for live monitoring. XenMon also allows
6 # logging to a file. For options, run python xenmon.py -h
7 #
8 # Copyright (C) 2005,2006 by Hewlett Packard, Palo Alto and Fort Collins
9 # Authors: Lucy Cherkasova, lucy.cherkasova@hp.com
10 # Rob Gardner, rob.gardner@hp.com
11 # Diwaker Gupta, diwaker.gupta@hp.com
12 #####################################################################
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; under version 2 of the License.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #####################################################################
27 import mmap
28 import struct
29 import os
30 import time
31 import optparse as _o
32 import curses as _c
33 import math
34 import sys
36 # constants
37 NSAMPLES = 100
38 NDOMAINS = 32
39 IDLE_DOMAIN = -1 # idle domain's ID
41 # the struct strings for qos_info
42 ST_DOM_INFO = "6Q3i2H32s"
43 ST_QDATA = "%dQ" % (6*NDOMAINS + 4)
45 # size of mmaped file
46 QOS_DATA_SIZE = struct.calcsize(ST_QDATA)*NSAMPLES + struct.calcsize(ST_DOM_INFO)*NDOMAINS + struct.calcsize("4i")
48 # location of mmaped file, hard coded right now
49 SHM_FILE = "/var/run/xenq-shm"
51 # format strings
52 TOTALS = 15*' ' + "%6.2f%%" + 35*' ' + "%6.2f%%"
54 ALLOCATED = "Allocated"
55 GOTTEN = "Gotten"
56 BLOCKED = "Blocked"
57 WAITED = "Waited"
58 IOCOUNT = "I/O Count"
59 EXCOUNT = "Exec Count"
61 # globals
62 dom_in_use = []
64 # our curses screen
65 stdscr = None
67 # parsed options
68 options, args = None, None
70 # the optparse module is quite smart
71 # to see help, just run xenmon -h
72 def setup_cmdline_parser():
73 parser = _o.OptionParser()
74 parser.add_option("-l", "--live", dest="live", action="store_true",
75 default=True, help = "show the ncurses live monitoring frontend (default)")
76 parser.add_option("-n", "--notlive", dest="live", action="store_false",
77 default="True", help = "write to file instead of live monitoring")
78 parser.add_option("-p", "--prefix", dest="prefix",
79 default = "log", help="prefix to use for output files")
80 parser.add_option("-t", "--time", dest="duration",
81 action="store", type="int", default=10,
82 help="stop logging to file after this much time has elapsed (in seconds). set to 0 to keep logging indefinitely")
83 parser.add_option("-i", "--interval", dest="interval",
84 action="store", type="int", default=1000,
85 help="interval for logging (in ms)")
86 parser.add_option("--ms_per_sample", dest="mspersample",
87 action="store", type="int", default=100,
88 help = "determines how many ms worth of data goes in a sample")
89 parser.add_option("--cpu", dest="cpu", action="store", type="int", default=0,
90 help = "specifies which cpu to display data for")
92 parser.add_option("--allocated", dest="allocated", action="store_true",
93 default=False, help="Display allocated time for each domain")
94 parser.add_option("--noallocated", dest="allocated", action="store_false",
95 default=False, help="Don't display allocated time for each domain")
97 parser.add_option("--blocked", dest="blocked", action="store_true",
98 default=True, help="Display blocked time for each domain")
99 parser.add_option("--noblocked", dest="blocked", action="store_false",
100 default=True, help="Don't display blocked time for each domain")
102 parser.add_option("--waited", dest="waited", action="store_true",
103 default=True, help="Display waiting time for each domain")
104 parser.add_option("--nowaited", dest="waited", action="store_false",
105 default=True, help="Don't display waiting time for each domain")
107 parser.add_option("--excount", dest="excount", action="store_true",
108 default=False, help="Display execution count for each domain")
109 parser.add_option("--noexcount", dest="excount", action="store_false",
110 default=False, help="Don't display execution count for each domain")
111 parser.add_option("--iocount", dest="iocount", action="store_true",
112 default=False, help="Display I/O count for each domain")
113 parser.add_option("--noiocount", dest="iocount", action="store_false",
114 default=False, help="Don't display I/O count for each domain")
116 return parser
118 # encapsulate information about a domain
119 class DomainInfo:
120 def __init__(self):
121 self.allocated_sum = 0
122 self.gotten_sum = 0
123 self.blocked_sum = 0
124 self.waited_sum = 0
125 self.exec_count = 0;
126 self.iocount_sum = 0
127 self.ffp_samples = []
129 def gotten_stats(self, passed):
130 total = float(self.gotten_sum)
131 per = 100*total/passed
132 exs = self.exec_count
133 if exs > 0:
134 avg = total/exs
135 else:
136 avg = 0
137 return [total/(float(passed)/10**9), per, avg]
139 def waited_stats(self, passed):
140 total = float(self.waited_sum)
141 per = 100*total/passed
142 exs = self.exec_count
143 if exs > 0:
144 avg = total/exs
145 else:
146 avg = 0
147 return [total/(float(passed)/10**9), per, avg]
149 def blocked_stats(self, passed):
150 total = float(self.blocked_sum)
151 per = 100*total/passed
152 ios = self.iocount_sum
153 if ios > 0:
154 avg = total/float(ios)
155 else:
156 avg = 0
157 return [total/(float(passed)/10**9), per, avg]
159 def allocated_stats(self, passed):
160 total = self.allocated_sum
161 exs = self.exec_count
162 if exs > 0:
163 return float(total)/exs
164 else:
165 return 0
167 def ec_stats(self, passed):
168 total = float(self.exec_count/(float(passed)/10**9))
169 return total
171 def io_stats(self, passed):
172 total = float(self.iocount_sum)
173 exs = self.exec_count
174 if exs > 0:
175 avg = total/exs
176 else:
177 avg = 0
178 return [total/(float(passed)/10**9), avg]
180 def stats(self, passed):
181 return [self.gotten_stats(passed), self.allocated_stats(passed), self.blocked_stats(passed),
182 self.waited_stats(passed), self.ec_stats(passed), self.io_stats(passed)]
184 # report values over desired interval
185 def summarize(startat, endat, duration, samples):
186 dominfos = {}
187 for i in range(0, NDOMAINS):
188 dominfos[i] = DomainInfo()
190 passed = 1 # to prevent zero division
191 curid = startat
192 numbuckets = 0
193 lost_samples = []
194 ffp_samples = []
196 while passed < duration:
197 for i in range(0, NDOMAINS):
198 if dom_in_use[i]:
199 dominfos[i].gotten_sum += samples[curid][0*NDOMAINS + i]
200 dominfos[i].allocated_sum += samples[curid][1*NDOMAINS + i]
201 dominfos[i].waited_sum += samples[curid][2*NDOMAINS + i]
202 dominfos[i].blocked_sum += samples[curid][3*NDOMAINS + i]
203 dominfos[i].exec_count += samples[curid][4*NDOMAINS + i]
204 dominfos[i].iocount_sum += samples[curid][5*NDOMAINS + i]
206 passed += samples[curid][6*NDOMAINS]
207 lost_samples.append(samples[curid][6*NDOMAINS + 2])
208 ffp_samples.append(samples[curid][6*NDOMAINS + 3])
210 numbuckets += 1
212 if curid > 0:
213 curid -= 1
214 else:
215 curid = NSAMPLES - 1
216 if curid == endat:
217 break
219 lostinfo = [min(lost_samples), sum(lost_samples), max(lost_samples)]
220 ffpinfo = [min(ffp_samples), sum(ffp_samples), max(ffp_samples)]
222 ldoms = []
223 for x in range(0, NDOMAINS):
224 if dom_in_use[x]:
225 ldoms.append(dominfos[x].stats(passed))
226 else:
227 ldoms.append(0)
229 return [ldoms, lostinfo, ffpinfo]
231 # scale microseconds to milliseconds or seconds as necessary
232 def time_scale(ns):
233 if ns < 1000:
234 return "%4.2f ns" % float(ns)
235 elif ns < 1000*1000:
236 return "%4.2f us" % (float(ns)/10**3)
237 elif ns < 10**9:
238 return "%4.2f ms" % (float(ns)/10**6)
239 else:
240 return "%4.2f s" % (float(ns)/10**9)
242 # paint message on curses screen, but detect screen size errors
243 def display(scr, row, col, str, attr=0):
244 try:
245 scr.addstr(row, col, str, attr)
246 except:
247 scr.erase()
248 _c.nocbreak()
249 scr.keypad(0)
250 _c.echo()
251 _c.endwin()
252 print "Your terminal screen is not big enough; Please resize it."
253 print "row=%d, col=%d, str='%s'" % (row, col, str)
254 sys.exit(1)
257 # diplay domain id
258 def display_domain_id(scr, row, col, dom):
259 if dom == IDLE_DOMAIN:
260 display(scr, row, col-1, "Idle")
261 else:
262 display(scr, row, col, "%d" % dom)
265 # the live monitoring code
266 def show_livestats(cpu):
267 ncpu = 1 # number of cpu's on this platform
268 slen = 0 # size of shared data structure, incuding padding
269 cpu_1sec_usage = 0.0
270 cpu_10sec_usage = 0.0
271 heartbeat = 1
272 global dom_in_use, options
274 # mmap the (the first chunk of the) file
275 shmf = open(SHM_FILE, "r+")
276 shm = mmap.mmap(shmf.fileno(), QOS_DATA_SIZE)
278 # initialize curses
279 stdscr = _c.initscr()
280 _c.noecho()
281 _c.cbreak()
283 stdscr.keypad(1)
284 stdscr.timeout(1000)
285 [maxy, maxx] = stdscr.getmaxyx()
287 # display in a loop
288 while True:
290 cpuidx = 0
291 while cpuidx < ncpu:
293 # calculate offset in mmap file to start from
294 idx = cpuidx * slen
297 samples = []
298 doms = []
299 dom_in_use = []
300 domain_id = []
302 # read in data
303 for i in range(0, NSAMPLES):
304 len = struct.calcsize(ST_QDATA)
305 sample = struct.unpack(ST_QDATA, shm[idx:idx+len])
306 samples.append(sample)
307 idx += len
309 for i in range(0, NDOMAINS):
310 len = struct.calcsize(ST_DOM_INFO)
311 dom = struct.unpack(ST_DOM_INFO, shm[idx:idx+len])
312 doms.append(dom)
313 # (last_update_time, start_time, runnable_start_time, blocked_start_time,
314 # ns_since_boot, ns_oncpu_since_boot, runnable_at_last_update,
315 # runnable, in_use, domid, junk, name) = dom
316 # dom_in_use.append(in_use)
317 dom_in_use.append(dom[8])
318 domid = dom[9]
319 if domid == 32767 :
320 domid = IDLE_DOMAIN
321 domain_id.append(domid)
322 idx += len
323 # print "dom_in_use(cpu=%d): " % cpuidx, dom_in_use
326 len = struct.calcsize("4i")
327 oldncpu = ncpu
328 (next, ncpu, slen, freq) = struct.unpack("4i", shm[idx:idx+len])
329 idx += len
331 # xenbaked tells us how many cpu's it's got, so re-do
332 # the mmap if necessary to get multiple cpu data
333 if oldncpu != ncpu:
334 shm = mmap.mmap(shmf.fileno(), ncpu*slen)
336 # if we've just calculated data for the cpu of interest, then
337 # stop examining mmap data and start displaying stuff
338 if cpuidx == cpu:
339 break
341 cpuidx = cpuidx + 1
343 # calculate starting and ending datapoints; never look at "next" since
344 # it represents live data that may be in transition.
345 startat = next - 1
346 if next + 10 < NSAMPLES:
347 endat = next + 10
348 else:
349 endat = 10
351 # get summary over desired interval
352 [h1, l1, f1] = summarize(startat, endat, 10**9, samples)
353 [h2, l2, f2] = summarize(startat, endat, 10 * 10**9, samples)
356 # the actual display code
357 row = 0
358 display(stdscr, row, 1, "CPU = %d" % cpu, _c.A_STANDOUT)
360 display(stdscr, row, 10, "%sLast 10 seconds (%3.2f%%)%sLast 1 second (%3.2f%%)" % (6*' ', cpu_10sec_usage, 30*' ', cpu_1sec_usage), _c.A_BOLD)
361 row +=1
362 display(stdscr, row, 1, "%s" % ((maxx-2)*'='))
364 total_h1_cpu = 0
365 total_h2_cpu = 0
367 cpu_1sec_usage = 0.0
368 cpu_10sec_usage = 0.0
370 for dom in range(0, NDOMAINS):
371 if not dom_in_use[dom]:
372 continue
374 if h1[dom][0][1] > 0 or domain_id[dom] == IDLE_DOMAIN:
375 # display gotten
376 row += 1
377 col = 2
378 display_domain_id(stdscr, row, col, domain_id[dom])
379 col += 4
380 display(stdscr, row, col, "%s" % time_scale(h2[dom][0][0]))
381 col += 12
382 display(stdscr, row, col, "%3.2f%%" % h2[dom][0][1])
383 if dom != IDLE_DOMAIN:
384 cpu_10sec_usage += h2[dom][0][1]
385 col += 12
386 display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][0][2]))
387 col += 18
388 display(stdscr, row, col, "%s" % time_scale(h1[dom][0][0]))
389 col += 12
390 display(stdscr, row, col, "%3.2f%%" % h1[dom][0][1], _c.A_STANDOUT)
391 col += 12
392 display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][0][2]))
393 col += 18
394 display(stdscr, row, col, "Gotten")
396 if dom != IDLE_DOMAIN:
397 cpu_1sec_usage = cpu_1sec_usage + h1[dom][0][1]
399 # display allocated
400 if options.allocated:
401 row += 1
402 col = 2
403 display_domain_id(stdscr, row, col, domain_id[dom])
404 col += 28
405 display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][1]))
406 col += 42
407 display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][1]))
408 col += 18
409 display(stdscr, row, col, "Allocated")
411 # display blocked
412 if options.blocked:
413 row += 1
414 col = 2
415 display_domain_id(stdscr, row, col, domain_id[dom])
416 col += 4
417 display(stdscr, row, col, "%s" % time_scale(h2[dom][2][0]))
418 col += 12
419 display(stdscr, row, col, "%3.2f%%" % h2[dom][2][1])
420 col += 12
421 display(stdscr, row, col, "%s/io" % time_scale(h2[dom][2][2]))
422 col += 18
423 display(stdscr, row, col, "%s" % time_scale(h1[dom][2][0]))
424 col += 12
425 display(stdscr, row, col, "%3.2f%%" % h1[dom][2][1])
426 col += 12
427 display(stdscr, row, col, "%s/io" % time_scale(h1[dom][2][2]))
428 col += 18
429 display(stdscr, row, col, "Blocked")
431 # display waited
432 if options.waited:
433 row += 1
434 col = 2
435 display_domain_id(stdscr, row, col, domain_id[dom])
436 col += 4
437 display(stdscr, row, col, "%s" % time_scale(h2[dom][3][0]))
438 col += 12
439 display(stdscr, row, col, "%3.2f%%" % h2[dom][3][1])
440 col += 12
441 display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][3][2]))
442 col += 18
443 display(stdscr, row, col, "%s" % time_scale(h1[dom][3][0]))
444 col += 12
445 display(stdscr, row, col, "%3.2f%%" % h1[dom][3][1])
446 col += 12
447 display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][3][2]))
448 col += 18
449 display(stdscr, row, col, "Waited")
451 # display ex count
452 if options.excount:
453 row += 1
454 col = 2
455 display_domain_id(stdscr, row, col, domain_id[dom])
457 col += 28
458 display(stdscr, row, col, "%d/s" % h2[dom][4])
459 col += 42
460 display(stdscr, row, col, "%d" % h1[dom][4])
461 col += 18
462 display(stdscr, row, col, "Execution count")
464 # display io count
465 if options.iocount:
466 row += 1
467 col = 2
468 display_domain_id(stdscr, row, col, domain_id[dom])
469 col += 4
470 display(stdscr, row, col, "%d/s" % h2[dom][5][0])
471 col += 24
472 display(stdscr, row, col, "%d/ex" % h2[dom][5][1])
473 col += 18
474 display(stdscr, row, col, "%d" % h1[dom][5][0])
475 col += 24
476 display(stdscr, row, col, "%3.2f/ex" % h1[dom][5][1])
477 col += 18
478 display(stdscr, row, col, "I/O Count")
480 #row += 1
481 #stdscr.hline(row, 1, '-', maxx - 2)
482 total_h1_cpu += h1[dom][0][1]
483 total_h2_cpu += h2[dom][0][1]
486 row += 1
487 star = heartbeat * '*'
488 heartbeat = 1 - heartbeat
489 display(stdscr, row, 1, star)
490 display(stdscr, row, 2, TOTALS % (total_h2_cpu, total_h1_cpu))
491 row += 1
492 # display(stdscr, row, 2,
493 # "\tFFP: %d (Min: %d, Max: %d)\t\t\tFFP: %d (Min: %d, Max %d)" %
494 # (math.ceil(f2[1]), f2[0], f2[2], math.ceil(f1[1]), f1[0], f1[2]), _c.A_BOLD)
496 if l1[1] > 1 :
497 row += 1
498 display(stdscr, row, 2,
499 "\tRecords lost: %d (Min: %d, Max: %d)\t\t\tRecords lost: %d (Min: %d, Max %d)" %
500 (math.ceil(l2[1]), l2[0], l2[2], math.ceil(l1[1]), l1[0], l1[2]), _c.A_BOLD)
502 # grab a char from tty input; exit if interrupt hit
503 try:
504 c = stdscr.getch()
505 except:
506 break
508 # q = quit
509 if c == ord('q'):
510 break
512 # c = cycle to a new cpu of interest
513 if c == ord('c'):
514 cpu = (cpu + 1) % ncpu
516 # n/p = cycle to the next/previous CPU
517 if c == ord('n'):
518 cpu = (cpu + 1) % ncpu
519 if c == ord('p'):
520 cpu = (cpu - 1) % ncpu
522 stdscr.erase()
524 _c.nocbreak()
525 stdscr.keypad(0)
526 _c.echo()
527 _c.endwin()
528 shm.close()
529 shmf.close()
532 # simple functions to allow initialization of log files without actually
533 # physically creating files that are never used; only on the first real
534 # write does the file get created
535 class Delayed(file):
536 def __init__(self, filename, mode):
537 self.filename = filename
538 self.saved_mode = mode
539 self.delay_data = ""
540 self.opened = 0
542 def delayed_write(self, str):
543 self.delay_data = str
545 def write(self, str):
546 if not self.opened:
547 self.file = open(self.filename, self.saved_mode)
548 self.opened = 1
549 self.file.write(self.delay_data)
550 self.file.write(str)
552 def rename(self, name):
553 self.filename = name
555 def flush(self):
556 if self.opened:
557 self.file.flush()
559 def close(self):
560 if self.opened:
561 self.file.close()
564 def writelog():
565 global options
566 global dom_in_use
568 ncpu = 1 # number of cpu's
569 slen = 0 # size of shared structure inc. padding
571 shmf = open(SHM_FILE, "r+")
572 shm = mmap.mmap(shmf.fileno(), QOS_DATA_SIZE)
574 interval = 0
575 curr = last = time.time()
576 outfiles = {}
577 for dom in range(0, NDOMAINS):
578 outfiles[dom] = Delayed("%s-dom%d.log" % (options.prefix, dom), 'w')
579 outfiles[dom].delayed_write("# passed cpu dom cpu(tot) cpu(%) cpu/ex allocated/ex blocked(tot) blocked(%) blocked/io waited(tot) waited(%) waited/ex ex/s io(tot) io/ex\n")
581 while options.duration == 0 or interval < (options.duration * 1000):
582 cpuidx = 0
583 while cpuidx < ncpu:
585 idx = cpuidx * slen # offset needed in mmap file
587 samples = []
588 doms = []
589 dom_in_use = []
590 domain_id = []
592 for i in range(0, NSAMPLES):
593 len = struct.calcsize(ST_QDATA)
594 sample = struct.unpack(ST_QDATA, shm[idx:idx+len])
595 samples.append(sample)
596 idx += len
598 for i in range(0, NDOMAINS):
599 len = struct.calcsize(ST_DOM_INFO)
600 dom = struct.unpack(ST_DOM_INFO, shm[idx:idx+len])
601 # doms.append(dom)
602 # (last_update_time, start_time, runnable_start_time, blocked_start_time,
603 # ns_since_boot, ns_oncpu_since_boot, runnable_at_last_update,
604 # runnable, in_use, domid, junk, name) = dom
605 dom_in_use.append(dom[8])
606 domid = dom[9]
607 if domid == 32767:
608 domid = IDLE_DOMAIN
609 domain_id.append(domid)
610 if domid == IDLE_DOMAIN:
611 outfiles[i].rename("%s-idle.log" % options.prefix)
612 else:
613 outfiles[i].rename("%s-dom%d.log" % (options.prefix, domid))
614 idx += len
616 len = struct.calcsize("4i")
617 oldncpu = ncpu
618 (next, ncpu, slen, freq) = struct.unpack("4i", shm[idx:idx+len])
619 idx += len
621 if oldncpu != ncpu:
622 shm = mmap.mmap(shmf.fileno(), ncpu*slen)
624 startat = next - 1
625 if next + 10 < NSAMPLES:
626 endat = next + 10
627 else:
628 endat = 10
630 [h1,l1, f1] = summarize(startat, endat, options.interval * 10**6, samples)
631 for dom in range(0, NDOMAINS):
632 if not dom_in_use[dom]:
633 continue
634 if h1[dom][0][1] > 0 or dom == IDLE_DOMAIN:
635 outfiles[dom].write("%.3f %d %d %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n" %
636 (interval, cpuidx, domain_id[dom],
637 h1[dom][0][0], h1[dom][0][1], h1[dom][0][2],
638 h1[dom][1],
639 h1[dom][2][0], h1[dom][2][1], h1[dom][2][2],
640 h1[dom][3][0], h1[dom][3][1], h1[dom][3][2],
641 h1[dom][4],
642 h1[dom][5][0], h1[dom][5][1]))
643 outfiles[dom].flush()
644 curr = time.time()
645 interval += (curr - last) * 1000
646 last = curr
647 cpuidx = cpuidx + 1
648 time.sleep(options.interval / 1000.0)
650 for dom in range(0, NDOMAINS):
651 outfiles[dom].close()
653 # start xenbaked
654 def start_xenbaked():
655 global options
656 global kill_cmd
657 global xenbaked_cmd
659 os.system(kill_cmd)
660 os.system(xenbaked_cmd + " --ms_per_sample=%d &" %
661 options.mspersample)
662 time.sleep(1)
664 # stop xenbaked
665 def stop_xenbaked():
666 global stop_cmd
667 os.system(stop_cmd)
669 def main():
670 global options
671 global args
672 global domains
673 global stop_cmd
674 global kill_cmd
675 global xenbaked_cmd
677 if os.uname()[0] == "SunOS":
678 xenbaked_cmd = "/usr/lib/xenbaked"
679 stop_cmd = "/usr/bin/pkill -INT -z global xenbaked"
680 kill_cmd = "/usr/bin/pkill -KILL -z global xenbaked"
681 else:
682 # assumes that xenbaked is in your path
683 xenbaked_cmd = "xenbaked"
684 stop_cmd = "/usr/bin/pkill -INT xenbaked"
685 kill_cmd = "/usr/bin/pkill -KILL xenbaked"
687 parser = setup_cmdline_parser()
688 (options, args) = parser.parse_args()
690 if len(args):
691 parser.error("No parameter required")
692 if options.mspersample < 0:
693 parser.error("option --ms_per_sample: invalid negative value: '%d'" %
694 options.mspersample)
695 # If --ms_per_sample= is too large, no data may be logged.
696 if not options.live and options.duration != 0 and \
697 options.mspersample > options.duration * 1000:
698 parser.error("option --ms_per_sample: too large (> %d ms)" %
699 (options.duration * 1000))
701 start_xenbaked()
702 if options.live:
703 show_livestats(options.cpu)
704 else:
705 try:
706 writelog()
707 except:
708 print 'Quitting.'
709 stop_xenbaked()
711 if __name__ == "__main__":
712 main()