ia64/xen-unstable

view tools/python/xen/xm/main.py @ 7604:28face899030

Catch KeyboardInterrupt, to avoid spewing error messages on Ctrl-C.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Tue Nov 01 15:57:19 2005 +0100 (2005-11-01)
parents f3ebb4d6baab
children 98515ca23ca3
line source
1 # (C) Copyright IBM Corp. 2005
2 # Copyright (C) 2004 Mike Wray
3 # Copyright (c) 2005 XenSource Ltd
4 #
5 # Authors:
6 # Sean Dague <sean at dague dot net>
7 # Mike Wray <mike dot wray at hp dot com>
8 #
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of version 2.1 of the GNU Lesser General Public
11 # License as published by the Free Software Foundation.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 """Grand unified management application for Xen.
23 """
24 import os
25 import os.path
26 import sys
27 import commands
28 import re
29 from getopt import getopt
30 import socket
31 import warnings
32 warnings.filterwarnings('ignore', category=FutureWarning)
34 import xen.xend.XendError
35 import xen.xend.XendProtocol
37 from xen.xend import PrettyPrint
38 from xen.xend import sxp
39 from xen.xm.opts import *
41 import console
44 shorthelp = """Usage: xm <subcommand> [args]
45 Control, list, and manipulate Xen guest instances
47 xm common subcommands:
48 console <DomId> attach to console of DomId
49 create <CfgFile> create a domain based on Config File
50 destroy <DomId> terminate a domain immediately
51 help display this message
52 list [DomId, ...] list information about domains
53 mem-max <DomId> <Mem> set the maximum memory reservation for a domain
54 mem-set <DomId> <Mem> adjust the current memory usage for a domain
55 migrate <DomId> <Host> migrate a domain to another machine
56 pause <DomId> pause execution of a domain
57 reboot <DomId> reboot a domain
58 restore <File> create a domain from a saved state file
59 save <DomId> <File> save domain state (and config) to file
60 shutdown <DomId> shutdown a domain
61 top monitor system and domains in real-time
62 unpause <DomId> unpause a paused domain
64 <DomName> can be substituted for <DomId> in xm subcommands.
66 For a complete list of subcommands run 'xm help --long'
67 For more help on xm see the xm(1) man page
68 For more help on xm create, see the xmdomain.cfg(5) man page"""
70 longhelp = """Usage: xm <subcommand> [args]
71 Control, list, and manipulate Xen guest instances
73 xm full list of subcommands:
75 Domain Commands:
76 console <DomId> attach to console of DomId
77 create <ConfigFile> create a domain
78 destroy <DomId> terminate a domain immediately
79 domid <DomName> convert a domain name to a domain id
80 domname <DomId> convert a domain id to a domain name
81 list list information about domains
82 mem-max <DomId> <Mem> set domain maximum memory limit
83 mem-set <DomId> <Mem> set the domain's memory dynamically
84 migrate <DomId> <Host> migrate a domain to another machine
85 pause <DomId> pause execution of a domain
86 reboot [-w|-a] <DomId> reboot a domain
87 restore <File> create a domain from a saved state file
88 save <DomId> <File> save domain state (and config) to file
89 shutdown [-w|-a] <DomId> shutdown a domain
90 sysrq <DomId> <letter> send a sysrq to a domain
91 unpause <DomId> unpause a paused domain
92 set-vcpus <DomId> <VCPUs> enable the specified number of VCPUs in a domain
93 vcpu-list <DomId> list the VCPUs for a domain
94 vcpu-pin <DomId> <VCPU> <CPUs> set which cpus a VCPU can use.
96 Xen Host Commands:
97 dmesg [--clear] read or clear Xen's message buffer
98 info get information about the xen host
99 log print the xend log
100 top monitor system and domains in real-time
102 Scheduler Commands:
103 sched-bvt <options> set BVT scheduler parameters
104 sched-bvt-ctxallow <Allow>
105 Set the BVT scheduler context switch allowance
106 sched-sedf <options> set simple EDF parameters
108 Virtual Device Commands:
109 block-attach <DomId> <BackDev> <FrontDev> <Mode> [BackDomId]
110 Create a new virtual block device
111 block-detach <DomId> <DevId> Destroy a domain's virtual block device,
112 where <DevId> may either be the device ID
113 or the device name as mounted in the guest.
114 block-list <DomId> List virtual block devices for a domain
116 network-attach <DomID> [script=<script>] [ip=<ip>] [mac=<mac>]
117 [bridge=<bridge>] [backend=<backDomID>]
118 Create a new virtual network device
119 network-detach <DomId> <DevId> Destroy a domain's virtual network
120 device, where <DevId> is the device ID.
121 network-limit <DomId> <Vif> <Credit> <Period>
122 Limit the transmission rate of a virtual network interface
123 network-list <DomId> List virtual network interfaces for a domain
125 Vnet commands:
126 vnet-list [-l|--long] list vnets
127 vnet-create <config> create a vnet from a config file
128 vnet-delete <vnetid> delete a vnet
130 <DomName> can be substituted for <DomId> in xm subcommands.
132 For a short list of subcommands run 'xm help'
133 For more help on xm see the xm(1) man page
134 For more help on xm create, see the xmdomain.cfg(5) man page"""
136 ####################################################################
137 #
138 # Utility functions
139 #
140 ####################################################################
142 def arg_check(args,num,name):
143 if len(args) < num:
144 err("'xm %s' requires %s argument(s)!\n" % (name, num))
145 usage(name)
147 def unit(c):
148 if not c.isalpha():
149 return 0
150 base = 1
151 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
152 elif c == 'M' or c == 'm': base = 1024 * 1024
153 elif c == 'K' or c == 'k': base = 1024
154 else:
155 print 'ignoring unknown unit'
156 return base
158 def int_unit(str, dest):
159 base = unit(str[-1])
160 if not base:
161 return int(str)
163 value = int(str[:-1])
164 dst_base = unit(dest)
165 if dst_base == 0:
166 dst_base = 1
167 if dst_base > base:
168 return value / (dst_base / base)
169 else:
170 return value * (base / dst_base)
172 def err(msg):
173 print >>sys.stderr, "Error:", msg
175 def handle_xend_error(cmd, dom, ex):
176 error = str(ex)
177 if error == "Not found" and dom != None:
178 err("Domain '%s' not found when running 'xm %s'" % (dom, cmd))
179 sys.exit(1)
180 else:
181 err(error)
182 sys.exit(1)
185 #########################################################################
186 #
187 # Main xm functions
188 #
189 #########################################################################
191 def xm_save(args):
192 arg_check(args,2,"save")
194 dom = args[0] # TODO: should check if this exists
195 savefile = os.path.abspath(args[1])
197 if not os.access(os.path.dirname(savefile), os.W_OK):
198 err("xm save: Unable to create file %s" % savefile)
199 sys.exit(1)
201 from xen.xend.XendClient import server
202 server.xend_domain_save(dom, savefile)
204 def xm_restore(args):
205 arg_check(args,1,"restore")
207 savefile = os.path.abspath(args[0])
209 if not os.access(savefile, os.R_OK):
210 err("xm restore: Unable to read file %s" % savefile)
211 sys.exit(1)
213 from xen.xend.XendClient import server
214 info = server.xend_domain_restore(savefile)
215 PrettyPrint.prettyprint(info)
216 id = sxp.child_value(info, 'domid')
217 if id is not None:
218 server.xend_domain_unpause(domid)
221 def getDomains(domain_names):
222 from xen.xend.XendClient import server
223 if domain_names:
224 return map(server.xend_domain, domain_names)
225 else:
226 return server.xend_list_domains()
229 def xm_list(args):
230 use_long = 0
231 show_vcpus = 0
232 try:
233 (options, params) = getopt(args, 'lv', ['long','vcpus'])
234 except GetoptError, opterr:
235 err(opterr)
236 sys.exit(1)
238 for (k, v) in options:
239 if k in ['-l', '--long']:
240 use_long = 1
241 if k in ['-v', '--vcpus']:
242 show_vcpus = 1
244 if show_vcpus:
245 print >>sys.stderr, (
246 "xm list -v is deprecated. Please use xm vcpu-list.")
247 xm_vcpu_list(params)
248 return
250 doms = getDomains(params)
252 if use_long:
253 map(PrettyPrint.prettyprint, doms)
254 else:
255 xm_brief_list(doms)
258 def parse_doms_info(info):
259 def get_info(n, t, d):
260 return t(sxp.child_value(info, n, d))
262 return {
263 'dom' : get_info('domid', int, -1),
264 'name' : get_info('name', str, '??'),
265 'mem' : get_info('memory', int, 0),
266 'vcpus' : get_info('vcpus', int, 0),
267 'state' : get_info('state', str, '??'),
268 'cpu_time' : get_info('cpu_time', float, 0),
269 'ssidref' : get_info('ssidref', int, 0),
270 }
273 def xm_brief_list(doms):
274 print 'Name ID Mem(MiB) VCPUs State Time(s)'
275 for dom in doms:
276 d = parse_doms_info(dom)
277 if (d['ssidref'] != 0):
278 d['ssidstr'] = (" s:%04x/p:%04x" %
279 ((d['ssidref'] >> 16) & 0xffff,
280 d['ssidref'] & 0xffff))
281 else:
282 d['ssidstr'] = ""
283 print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f%(ssidstr)s" % d)
286 def xm_vcpu_list(args):
287 print 'Name ID VCPU CPU State Time(s) CPU Affinity'
289 from xen.xend.XendClient import server
290 if args:
291 dominfo = map(server.xend_domain_vcpuinfo, args)
292 else:
293 doms = server.xend_list_domains()
294 dominfo = map(
295 lambda x: server.xend_domain_vcpuinfo(sxp.child_value(x, 'name')),
296 doms)
298 for dom in dominfo:
299 def get_info(n):
300 return sxp.child_value(dom, n)
302 #
303 # convert a list of integers into a list of pairs indicating
304 # continuous sequences in the list:
305 #
306 # [0,1,2,3] -> [(0,3)]
307 # [1,2,4,5] -> [(1,2),(4,5)]
308 # [0] -> [(0,0)]
309 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
310 #
311 def list_to_rangepairs(cmap):
312 cmap.sort()
313 pairs = []
314 x = y = 0
315 for i in range(0,len(cmap)):
316 try:
317 if ((cmap[y+1] - cmap[i]) > 1):
318 pairs.append((cmap[x],cmap[y]))
319 x = y = i+1
320 else:
321 y = y + 1
322 # if we go off the end, then just add x to y
323 except IndexError:
324 pairs.append((cmap[x],cmap[y]))
326 return pairs
328 #
329 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
330 #
331 def format_pairs(pairs):
332 if not pairs:
333 return "no cpus"
334 out = ""
335 for f,s in pairs:
336 if (f==s):
337 out += '%d'%f
338 else:
339 out += '%d-%d'%(f,s)
340 out += ','
341 # trim trailing ','
342 return out[:-1]
344 def format_cpumap(cpumap):
345 cpumap = map(lambda x: int(x), cpumap)
346 cpumap.sort()
348 from xen.xend.XendClient import server
349 for x in server.xend_node()[1:]:
350 if len(x) > 1 and x[0] == 'nr_cpus':
351 nr_cpus = int(x[1])
352 cpumap = filter(lambda x: x < nr_cpus, cpumap)
353 if len(cpumap) == nr_cpus:
354 return "any cpu"
355 break
357 return format_pairs(list_to_rangepairs(cpumap))
359 name = get_info('name')
360 domid = int(get_info('domid'))
362 for vcpu in sxp.children(dom, 'vcpu'):
363 def vinfo(n, t):
364 return t(sxp.child_value(vcpu, n))
366 number = vinfo('number', int)
367 cpu = vinfo('cpu', int)
368 cpumap = format_cpumap(vinfo('cpumap', list))
369 online = vinfo('online', int)
370 cpu_time = vinfo('cpu_time', float)
371 running = vinfo('running', int)
372 blocked = vinfo('blocked', int)
374 if online:
375 c = str(cpu)
376 if running:
377 s = 'r'
378 else:
379 s = '-'
380 if blocked:
381 s += 'b'
382 else:
383 s += '-'
384 s += '-'
385 else:
386 c = "-"
387 s = "--p"
389 print (
390 "%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
391 locals())
394 def xm_reboot(args):
395 arg_check(args,1,"reboot")
396 from xen.xm import shutdown
397 # ugly hack because the opt parser apparently wants
398 # the subcommand name just to throw it away!
399 shutdown.main(["bogus", "-R"] + args)
401 def xm_pause(args):
402 arg_check(args, 1, "pause")
403 dom = args[0]
405 from xen.xend.XendClient import server
406 server.xend_domain_pause(dom)
408 def xm_unpause(args):
409 arg_check(args, 1, "unpause")
410 dom = args[0]
412 from xen.xend.XendClient import server
413 server.xend_domain_unpause(dom)
415 def xm_subcommand(command, args):
416 cmd = __import__(command, globals(), locals(), 'xen.xm')
417 cmd.main(["bogus"] + args)
420 #############################################################
422 def cpu_make_map(cpulist):
423 cpus = []
424 for c in cpulist.split(','):
425 if c.find('-') != -1:
426 (x,y) = c.split('-')
427 for i in range(int(x),int(y)+1):
428 cpus.append(int(i))
429 else:
430 cpus.append(int(c))
431 cpus.sort()
432 return cpus
434 def xm_vcpu_pin(args):
435 arg_check(args, 3, "vcpu-pin")
437 dom = args[0]
438 vcpu = int(args[1])
439 cpumap = cpu_make_map(args[2])
441 from xen.xend.XendClient import server
442 server.xend_domain_pincpu(dom, vcpu, cpumap)
444 def xm_mem_max(args):
445 arg_check(args, 2, "mem-max")
447 dom = args[0]
448 mem = int_unit(args[1], 'm')
450 from xen.xend.XendClient import server
451 server.xend_domain_maxmem_set(dom, mem)
453 def xm_mem_set(args):
454 arg_check(args, 2, "mem-set")
456 dom = args[0]
457 mem_target = int_unit(args[1], 'm')
459 from xen.xend.XendClient import server
460 server.xend_domain_mem_target_set(dom, mem_target)
462 def xm_set_vcpus(args):
463 from xen.xend.XendClient import server
464 server.xend_domain_set_vcpus(args[0], int(args[1]))
466 def xm_domid(args):
467 name = args[0]
469 from xen.xend.XendClient import server
470 dom = server.xend_domain(name)
471 print sxp.child_value(dom, 'domid')
473 def xm_domname(args):
474 name = args[0]
476 from xen.xend.XendClient import server
477 dom = server.xend_domain(name)
478 print sxp.child_value(dom, 'name')
480 def xm_sched_bvt(args):
481 arg_check(args, 6, "sched-bvt")
482 dom = args[0]
483 v = map(long, args[1:6])
484 from xen.xend.XendClient import server
485 server.xend_domain_cpu_bvt_set(dom, *v)
487 def xm_sched_bvt_ctxallow(args):
488 arg_check(args, 1, "sched-bvt-ctxallow")
490 slice = int(args[0])
491 from xen.xend.XendClient import server
492 server.xend_node_cpu_bvt_slice_set(slice)
494 def xm_sched_sedf(args):
495 arg_check(args, 6, "sched-sedf")
497 dom = args[0]
498 v = map(int, args[1:6])
499 from xen.xend.XendClient import server
500 server.xend_domain_cpu_sedf_set(dom, *v)
502 def xm_info(args):
503 from xen.xend.XendClient import server
504 info = server.xend_node()
506 for x in info[1:]:
507 if len(x) < 2:
508 print "%-23s: (none)" % x[0]
509 else:
510 print "%-23s:" % x[0], x[1]
512 # TODO: remove as soon as console server shows up
513 def xm_console(args):
514 arg_check(args,1,"console")
516 dom = args[0]
517 from xen.xend.XendClient import server
518 info = server.xend_domain(dom)
519 domid = int(sxp.child_value(info, 'domid', '-1'))
520 console.execConsole(domid)
523 def xm_top(args):
524 os.execvp('xentop', ['xentop'])
526 def xm_dmesg(args):
528 gopts = Opts(use="""[-c|--clear]
530 Read Xen's message buffer (boot output, warning and error messages) or clear
531 its contents if the [-c|--clear] flag is specified.
532 """)
534 gopts.opt('clear', short='c',
535 fn=set_true, default=0,
536 use="Clear the contents of the Xen message buffer.")
537 # Work around for gopts
538 myargs = args
539 myargs.insert(0, "bogus")
540 gopts.parse(myargs)
541 if not (1 <= len(myargs) <= 2):
542 err('Invalid arguments: ' + str(myargs))
544 from xen.xend.XendClient import server
545 if not gopts.vals.clear:
546 print server.xend_node_get_dmesg()
547 else:
548 server.xend_node_clear_dmesg()
550 def xm_log(args):
551 from xen.xend.XendClient import server
552 print server.xend_node_log()
554 def xm_network_limit(args):
555 arg_check(args,4,"network-limit")
556 dom = args[0]
557 v = map(int, args[1:4])
558 from xen.xend.XendClient import server
559 server.xend_domain_vif_limit(dom, *v)
561 def xm_network_list(args):
562 arg_check(args,1,"network-list")
563 dom = args[0]
564 from xen.xend.XendClient import server
565 for x in server.xend_domain_devices(dom, 'vif'):
566 sxp.show(x)
567 print
569 def xm_block_list(args):
570 arg_check(args,1,"block-list")
571 dom = args[0]
572 from xen.xend.XendClient import server
573 for x in server.xend_domain_devices(dom, 'vbd'):
574 sxp.show(x)
575 print
577 def xm_block_attach(args):
578 n = len(args)
579 if n == 0:
580 usage("block-attach")
582 if n < 4 or n > 5:
583 err("%s: Invalid argument(s)" % args[0])
584 usage("block-attach")
586 dom = args[0]
587 vbd = ['vbd',
588 ['uname', args[1]],
589 ['dev', args[2]],
590 ['mode', args[3]]]
591 if n == 5:
592 vbd.append(['backend', args[4]])
594 from xen.xend.XendClient import server
595 server.xend_domain_device_create(dom, vbd)
598 def xm_network_attach(args):
599 n = len(args)
600 if n == 0:
601 usage("network-attach")
603 dom = args[0]
604 vif = ['vif']
606 for a in args[1:]:
607 vif.append(a.split("="))
609 from xen.xend.XendClient import server
610 server.xend_domain_device_create(dom, vif)
613 def detach(args, command, deviceClass):
614 arg_check(args, 2, command)
616 dom = args[0]
617 dev = args[1]
619 from xen.xend.XendClient import server
620 server.xend_domain_device_destroy(dom, deviceClass, dev)
623 def xm_block_detach(args):
624 detach(args, 'block-detach', 'vbd')
627 def xm_network_detach(args):
628 detach(args, 'network-detach', 'vif')
631 def xm_vnet_list(args):
632 from xen.xend.XendClient import server
633 try:
634 (options, params) = getopt(args, 'l', ['long'])
635 except GetoptError, opterr:
636 err(opterr)
637 sys.exit(1)
639 use_long = 0
640 for (k, v) in options:
641 if k in ['-l', '--long']:
642 use_long = 1
644 if params:
645 use_long = 1
646 vnets = params
647 else:
648 vnets = server.xend_vnets()
650 for vnet in vnets:
651 try:
652 if use_long:
653 info = server.xend_vnet(vnet)
654 PrettyPrint.prettyprint(info)
655 else:
656 print vnet
657 except Exception, ex:
658 print vnet, ex
660 def xm_vnet_create(args):
661 arg_check(args, 1, "vnet-create")
662 conf = args[0]
663 from xen.xend.XendClient import server
664 server.xend_vnet_create(conf)
666 def xm_vnet_delete(args):
667 arg_check(args, 1, "vnet-delete")
668 vnet = args[0]
669 from xen.xend.XendClient import server
670 server.xend_vnet_delete(vnet)
672 commands = {
673 # console commands
674 "console": xm_console,
675 # xenstat commands
676 "top": xm_top,
677 # domain commands
678 "domid": xm_domid,
679 "domname": xm_domname,
680 "restore": xm_restore,
681 "save": xm_save,
682 "reboot": xm_reboot,
683 "list": xm_list,
684 # memory commands
685 "mem-max": xm_mem_max,
686 "mem-set": xm_mem_set,
687 # cpu commands
688 "vcpu-pin": xm_vcpu_pin,
689 "set-vcpus": xm_set_vcpus,
690 "vcpu-list": xm_vcpu_list,
691 # special
692 "pause": xm_pause,
693 "unpause": xm_unpause,
694 # host commands
695 "dmesg": xm_dmesg,
696 "info": xm_info,
697 "log": xm_log,
698 # scheduler
699 "sched-bvt": xm_sched_bvt,
700 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
701 "sched-sedf": xm_sched_sedf,
702 # block
703 "block-attach": xm_block_attach,
704 "block-detach": xm_block_detach,
705 "block-list": xm_block_list,
706 # network
707 "network-attach": xm_network_attach,
708 "network-detach": xm_network_detach,
709 "network-limit": xm_network_limit,
710 "network-list": xm_network_list,
711 # vnet
712 "vnet-list": xm_vnet_list,
713 "vnet-create": xm_vnet_create,
714 "vnet-delete": xm_vnet_delete,
715 }
717 ## The commands supported by a separate argument parser in xend.xm.
718 subcommands = [
719 'create',
720 'destroy',
721 'migrate',
722 'sysrq',
723 'shutdown'
724 ]
726 for c in subcommands:
727 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
729 aliases = {
730 "balloon": "mem-set",
731 "vif-list": "network-list",
732 "vif-limit": "network-limit",
733 "vbd-create": "block-create",
734 "vbd-destroy": "block-destroy",
735 "vbd-list": "block-list",
736 }
738 help = {
739 "--long": longhelp
740 }
743 def xm_lookup_cmd(cmd):
744 if commands.has_key(cmd):
745 return commands[cmd]
746 elif aliases.has_key(cmd):
747 deprecated(cmd,aliases[cmd])
748 return commands[aliases[cmd]]
749 else:
750 if len( cmd ) > 1:
751 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
752 if len( matched_commands ) == 1:
753 return matched_commands[0][1]
754 err('Sub Command %s not found!' % cmd)
755 usage()
757 def deprecated(old,new):
758 err('Option %s is deprecated, and will be removed in future!!!' % old)
759 err('Option %s is the new replacement, see "xm help %s" for more info' % (new, new))
761 def usage(cmd=None):
762 if help.has_key(cmd):
763 print help[cmd]
764 else:
765 print shorthelp
766 sys.exit(1)
768 def main(argv=sys.argv):
769 if len(argv) < 2:
770 usage()
772 if re.compile('-*help').match(argv[1]):
773 if len(argv) > 2:
774 usage(argv[2])
775 else:
776 usage()
777 sys.exit(0)
779 cmd = xm_lookup_cmd(argv[1])
781 # strip off prog name and subcmd
782 args = argv[2:]
783 if cmd:
784 try:
785 rc = cmd(args)
786 if rc:
787 usage()
788 except socket.error, ex:
789 if os.geteuid() != 0:
790 err("Most commands need root access. Please try again as root.")
791 else:
792 err("Error connecting to xend: %s. Is xend running?" % ex[1])
793 sys.exit(1)
794 except KeyboardInterrupt:
795 print "Interrupted."
796 sys.exit(1)
797 except IOError:
798 if os.geteuid() != 0:
799 err("Most commands need root access. Please try again as root.")
800 else:
801 err("Error connecting to xend: %s." % ex[1])
802 sys.exit(1)
803 except xen.xend.XendError.XendError, ex:
804 if len(args) > 0:
805 handle_xend_error(argv[1], args[0], ex)
806 else:
807 print "Unexpected error:", sys.exc_info()[0]
808 print
809 print "Please report to xen-devel@lists.xensource.com"
810 raise
811 except xen.xend.XendProtocol.XendError, ex:
812 if len(args) > 0:
813 handle_xend_error(argv[1], args[0], ex)
814 else:
815 print "Unexpected error:", sys.exc_info()[0]
816 print
817 print "Please report to xen-devel@lists.xensource.com"
818 raise
819 except SystemExit:
820 sys.exit(1)
821 except:
822 print "Unexpected error:", sys.exc_info()[0]
823 print
824 print "Please report to xen-devel@lists.xensource.com"
825 raise
827 else:
828 usage()
830 if __name__ == "__main__":
831 main()