source: trunk/packages/xen-common/xen-common/tools/xenmon/xenmon.py @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

  • Property svn:mime-type set to text/script
File size: 24.0 KB
Line 
1#!/usr/bin/env python
2
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#####################################################################
26
27import mmap
28import struct
29import os
30import time
31import optparse as _o
32import curses as _c
33import math
34import sys
35
36# constants
37NSAMPLES = 100
38NDOMAINS = 32
39IDLE_DOMAIN = -1 # idle domain's ID
40
41# the struct strings for qos_info
42ST_DOM_INFO = "6Q3i2H32s"
43ST_QDATA = "%dQ" % (6*NDOMAINS + 4)
44
45# size of mmaped file
46QOS_DATA_SIZE = struct.calcsize(ST_QDATA)*NSAMPLES + struct.calcsize(ST_DOM_INFO)*NDOMAINS + struct.calcsize("4i")
47
48# location of mmaped file, hard coded right now
49SHM_FILE = "/tmp/xenq-shm"
50
51# format strings
52TOTALS = 15*' ' + "%6.2f%%" + 35*' ' + "%6.2f%%"
53
54ALLOCATED = "Allocated"
55GOTTEN = "Gotten"
56BLOCKED = "Blocked"
57WAITED = "Waited"
58IOCOUNT = "I/O Count"
59EXCOUNT = "Exec Count"
60
61# globals
62dom_in_use = []
63
64# our curses screen
65stdscr = None
66
67# parsed options
68options, args = None, None
69
70# the optparse module is quite smart
71# to see help, just run xenmon -h
72def 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")
91
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")
96
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")
101
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")
106
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")
115
116    return parser
117
118# encapsulate information about a domain
119class 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 = []
128
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]
138
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]
148
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]
158
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
166
167    def ec_stats(self, passed):
168        total = float(self.exec_count/(float(passed)/10**9))
169        return total
170
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]
179
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)]
183
184# report values over desired interval
185def summarize(startat, endat, duration, samples):
186    dominfos = {}
187    for i in range(0, NDOMAINS):
188        dominfos[i] = DomainInfo()
189       
190    passed = 1              # to prevent zero division
191    curid = startat
192    numbuckets = 0
193    lost_samples = []
194    ffp_samples = []
195   
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]
205   
206        passed += samples[curid][6*NDOMAINS]
207        lost_samples.append(samples[curid][6*NDOMAINS + 2])
208        ffp_samples.append(samples[curid][6*NDOMAINS + 3])
209
210        numbuckets += 1
211
212        if curid > 0:
213            curid -= 1
214        else:
215            curid = NSAMPLES - 1
216        if curid == endat:
217            break
218
219    lostinfo = [min(lost_samples), sum(lost_samples), max(lost_samples)]
220    ffpinfo = [min(ffp_samples), sum(ffp_samples), max(ffp_samples)]
221
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)
228
229    return [ldoms, lostinfo, ffpinfo]
230
231# scale microseconds to milliseconds or seconds as necessary
232def 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)
241
242# paint message on curses screen, but detect screen size errors
243def 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)
255
256
257# diplay domain id
258def 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)
263
264
265# the live monitoring code
266def 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
273   
274    # mmap the (the first chunk of the) file
275    shmf = open(SHM_FILE, "r+")
276    shm = mmap.mmap(shmf.fileno(), QOS_DATA_SIZE)
277
278    # initialize curses
279    stdscr = _c.initscr()
280    _c.noecho()
281    _c.cbreak()
282
283    stdscr.keypad(1)
284    stdscr.timeout(1000)
285    [maxy, maxx] = stdscr.getmaxyx()
286   
287    # display in a loop
288    while True:
289
290        cpuidx = 0
291        while cpuidx < ncpu:
292
293            # calculate offset in mmap file to start from
294            idx = cpuidx * slen
295
296
297            samples = []
298            doms = []
299            dom_in_use = []
300            domain_id = []
301
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
308
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
324
325
326            len = struct.calcsize("4i")
327            oldncpu = ncpu
328            (next, ncpu, slen, freq) = struct.unpack("4i", shm[idx:idx+len])
329            idx += len
330
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)
335
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
340
341            cpuidx = cpuidx + 1
342
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
350
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)
354
355
356        # the actual display code
357        row = 0
358        display(stdscr, row, 1, "CPU = %d" % cpu, _c.A_STANDOUT)
359
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)*'='))
363
364        total_h1_cpu = 0
365        total_h2_cpu = 0
366
367        cpu_1sec_usage = 0.0
368        cpu_10sec_usage = 0.0
369
370        for dom in range(0, NDOMAINS):
371            if not dom_in_use[dom]:
372                continue
373
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")
395
396                if dom != IDLE_DOMAIN:
397                    cpu_1sec_usage = cpu_1sec_usage + h1[dom][0][1]
398   
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")
410
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")
430
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")
450
451                # display ex count
452                if options.excount:
453                    row += 1
454                    col = 2
455                    display_domain_id(stdscr, row, col, domain_id[dom])
456                   
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")
463
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")
479
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]
484
485
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)
495
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)
501
502        # grab a char from tty input; exit if interrupt hit
503        try:
504            c = stdscr.getch()
505        except:
506            break
507       
508        # q = quit
509        if c == ord('q'):
510            break
511   
512        # c = cycle to a new cpu of interest
513        if c == ord('c'):
514            cpu = (cpu + 1) % ncpu
515
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
521
522        stdscr.erase()
523
524    _c.nocbreak()
525    stdscr.keypad(0)
526    _c.echo()
527    _c.endwin()
528    shm.close()
529    shmf.close()
530
531
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
535class 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
541
542    def delayed_write(self, str):
543        self.delay_data = str
544
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)
551
552    def rename(self, name):
553        self.filename = name
554
555    def flush(self):
556        if  self.opened:
557            self.file.flush()
558
559    def close(self):
560        if  self.opened:
561            self.file.close()
562           
563
564def writelog():
565    global options
566    global dom_in_use
567
568    ncpu = 1        # number of cpu's
569    slen = 0        # size of shared structure inc. padding
570
571    shmf = open(SHM_FILE, "r+")
572    shm = mmap.mmap(shmf.fileno(), QOS_DATA_SIZE)
573
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")
580
581    while options.duration == 0 or interval < (options.duration * 1000):
582        cpuidx = 0
583        while cpuidx < ncpu:
584
585            idx = cpuidx * slen      # offset needed in mmap file
586
587            samples = []
588            doms = []
589            dom_in_use = []
590            domain_id = []
591
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
597
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
615
616            len = struct.calcsize("4i")
617            oldncpu = ncpu
618            (next, ncpu, slen, freq) = struct.unpack("4i", shm[idx:idx+len])
619            idx += len
620
621            if oldncpu != ncpu:
622                shm = mmap.mmap(shmf.fileno(), ncpu*slen)
623
624            startat = next - 1
625            if next + 10 < NSAMPLES:
626                endat = next + 10
627            else:
628                endat = 10
629
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)
649
650    for dom in range(0, NDOMAINS):
651        outfiles[dom].close()
652
653# start xenbaked
654def start_xenbaked():
655    global options
656   
657    os.system("killall -9 xenbaked")
658    # assumes that xenbaked is in your path
659    os.system("xenbaked --ms_per_sample=%d &" %
660              options.mspersample)
661    time.sleep(1)
662
663# stop xenbaked
664def stop_xenbaked():
665    os.system("killall -s INT xenbaked")
666
667def main():
668    global options
669    global args
670    global domains
671
672    parser = setup_cmdline_parser()
673    (options, args) = parser.parse_args()
674
675    if len(args):
676        parser.error("No parameter required")
677    if options.mspersample < 0:
678        parser.error("option --ms_per_sample: invalid negative value: '%d'" %
679                     options.mspersample)
680    # If --ms_per_sample= is too large, no data may be logged.
681    if not options.live and options.duration != 0 and \
682       options.mspersample > options.duration * 1000:
683        parser.error("option --ms_per_sample: too large (> %d ms)" %
684                     (options.duration * 1000))
685   
686    start_xenbaked()
687    if options.live:
688        show_livestats(options.cpu)
689    else:
690        try:
691            writelog()
692        except:
693            print 'Quitting.'
694    stop_xenbaked()
695
696if __name__ == "__main__":
697    main()
Note: See TracBrowser for help on using the repository browser.