ia64/xen-unstable

view tools/python/xen/xm/main.py @ 7979:f612aec588e2

Fix syntax error.

Signed-off-by: Steven Hand <steven@xensource.com>
author smh22@firebug.cl.cam.ac.uk
date Mon Nov 21 19:28:50 2005 +0100 (2005-11-21)
parents b2364dc83d1f
children 6ab21a197549
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
43 # Strings for shorthelp
44 console_help = "console <DomId> Attach to domain DomId's console."
45 create_help = """create [-c] <ConfigFile>
46 [Name=Value].. Create a domain based on Config File"""
47 destroy_help = "destroy <DomId> Terminate a domain immediately"
48 help_help = "help Display this message"
49 list_help = "list [--long] [DomId, ...] List information about domains"
50 mem_max_help = "mem-max <DomId> <Mem> Set maximum memory reservation for a domain"
51 mem_set_help = "mem-set <DomId> <Mem> Adjust the current memory usage for a domain"
52 migrate_help = "migrate <DomId> <Host> Migrate a domain to another machine"
53 pause_help = "pause <DomId> Pause execution of a domain"
54 reboot_help = "reboot <DomId> [-w][-a] Reboot a domain"
55 restore_help = "restore <File> Create a domain from a saved state file"
56 save_help = "save <DomId> <File> Save domain state (and config) to file"
57 shutdown_help ="shutdown <DomId> [-w][-a][-R|-H] Shutdown a domain"
58 top_help = "top Monitor system and domains in real-time"
59 unpause_help = "unpause <DomId> Unpause a paused domain"
61 help_spacer = """
62 """
64 # Strings for longhelp
65 sysrq_help = "sysrq <DomId> <letter> Send a sysrq to a domain"
66 domid_help = "domid <DomName> Converts a domain name to a domain id"
67 domname_help = "domname <DomId> Convert a domain id to a domain name"
68 set_vcpus_help = """set-vcpus <DomId> <VCPUs> Enable the specified number of VCPUs in a
69 domain"""
70 vcpu_list_help = "vcpu-list <DomId> List the VCPUs for a domain (or all domains)"
71 vcpu_pin_help = "vcpu-pin <DomId> <VCPU> <CPUs> Set which cpus a VCPU can use"
72 dmesg_help = "dmesg [--clear] Read or clear Xen's message buffer"
73 info_help = "info Get information about the xen host"
74 log_help = "log Print the xend log"
75 sched_bvt_help = """sched-bvt <Parameters> Set Borrowed Virtual Time scheduler
76 parameters"""
77 sched_bvt_ctxallow_help = """sched-bvt-ctxallow <Allow> Set the BVT scheduler context switch
78 allowance"""
79 sched_sedf_help = "sched-sedf <Parameters> Set simple EDF parameters"
80 block_attach_help = """block-attach <DomId> <BackDev> <FrontDev> <Mode>
81 [BackDomId] Create a new virtual block device"""
82 block_detach_help = """block-detach <DomId> <DevId> Destroy a domain's virtual block device,
83 where <DevId> may either be the device ID
84 or the device name as mounted in the guest"""
86 block_list_help = "block-list <DomId> List virtual block devices for a domain"
87 network_attach_help = """network-attach <DomID> [script=<script>] [ip=<ip>] [mac=<mac>]
88 [bridge=<bridge>] [backend=<backDomID>]
89 Create a new virtual network device """
90 network_detach_help = """network-detach <DomId> <DevId> Destroy a domain's virtual network
91 device, where <DevId> is the device ID."""
93 network_list_help = "network-list <DomId> List virtual network interfaces for a domain"
94 vnet_list_help = "vnet-list [-l|--long] list vnets"
95 vnet_create_help = "vnet-create <config> create a vnet from a config file"
96 vnet_delete_help = "vnet-delete <vnetid> delete a vnet"
99 shorthelp = """Usage: xm <subcommand> [args]
100 Control, list, and manipulate Xen guest instances
102 xm common subcommands:""" + help_spacer \
103 + console_help + help_spacer \
104 + create_help + help_spacer \
105 + destroy_help + help_spacer \
106 + help_help + help_spacer \
107 + list_help + help_spacer \
108 + mem_max_help + help_spacer \
109 + mem_set_help + help_spacer \
110 + migrate_help + help_spacer \
111 + pause_help + help_spacer \
112 + reboot_help + help_spacer \
113 + restore_help + help_spacer \
114 + save_help + help_spacer \
115 + shutdown_help + help_spacer \
116 + top_help + help_spacer \
117 + unpause_help + """
119 <DomName> can be substituted for <DomId> in xm subcommands.
121 For a complete list of subcommands run 'xm help --long'
122 For more help on xm see the xm(1) man page
123 For more help on xm create, see the xmdomain.cfg(5) man page"""
125 longhelp = """Usage: xm <subcommand> [args]
126 Control, list, and manipulate Xen guest instances
128 xm full list of subcommands:
130 Domain Commands: """ + help_spacer \
131 + console_help + help_spacer \
132 + create_help + help_spacer \
133 + destroy_help + help_spacer \
134 + domid_help + help_spacer \
135 + domname_help + help_spacer \
136 + list_help + help_spacer \
137 + mem_max_help + help_spacer \
138 + mem_set_help + help_spacer \
139 + migrate_help + help_spacer \
140 + pause_help + help_spacer \
141 + reboot_help + help_spacer \
142 + restore_help + help_spacer \
143 + save_help + help_spacer \
144 + shutdown_help + help_spacer \
145 + sysrq_help + help_spacer \
146 + top_help + help_spacer \
147 + unpause_help + help_spacer \
148 + set_vcpus_help + help_spacer \
149 + vcpu_pin_help + """
151 Xen Host Commands: """ + help_spacer \
152 + dmesg_help + help_spacer \
153 + info_help + help_spacer \
154 + log_help + help_spacer \
155 + top_help + """
157 Scheduler Commands: """ + help_spacer \
158 + sched_bvt_help + help_spacer \
159 + sched_bvt_ctxallow_help + help_spacer \
160 + sched_sedf_help + """
162 Virtual Device Commands:""" + help_spacer \
163 + block_attach_help + help_spacer \
164 + block_detach_help + help_spacer \
165 + block_list_help + help_spacer \
166 + network_attach_help + help_spacer \
167 + network_detach_help + help_spacer \
168 + network_list_help + """
170 Vnet commands: """ + help_spacer \
171 + vnet_list_help + help_spacer \
172 + vnet_create_help + help_spacer \
173 + vnet_delete_help + """
175 <DomName> can be substituted for <DomId> in xm subcommands.
177 For a short list of subcommands run 'xm help'
178 For more help on xm see the xm(1) man page
179 For more help on xm create, see the xmdomain.cfg(5) man page"""
181 # array for xm help <command>
182 help = {
183 "--long": longhelp,
184 "console": console_help,
185 # create is handled specially
186 "destroy": destroy_help,
187 "domid ": domid_help,
188 "domname": domname_help,
189 "list": list_help,
190 "mem-max": mem_max_help,
191 "mem-set": mem_set_help,
192 "migrate": migrate_help,
193 "pause": pause_help,
194 "reboot": reboot_help,
195 "restore": restore_help,
196 "save": save_help,
197 "shutdown": shutdown_help,
198 "sysrq": sysrq_help,
199 "unpause": unpause_help,
200 "set-vcpus": set_vcpus_help,
201 "vcpu-list": vcpu_list_help,
202 "vcpu-pin": vcpu_pin_help,
203 # Xen Host Commands:
204 "dmesg": dmesg_help,
205 "info": info_help,
206 "log": log_help,
207 "top": top_help,
208 # Scheduler Commands:
209 "sched-bvt": sched_bvt_help,
210 "sched-bvt-ctxallow": sched_bvt_ctxallow_help,
211 "sched-sedf": sched_sedf_help,
213 # Virtual Device Commands:
214 "block-attach": block_attach_help,
215 "block-detach": block_detach_help,
216 "block-list": block_list_help,
217 "network-attach": network_attach_help,
218 "network-detach": network_detach_help,
219 "network-list": network_list_help,
220 # Vnet commands:
221 "vnet-list": vnet_list_help,
222 "vnet-create": vnet_create_help,
223 "vnet-delete": vnet_delete_help
224 }
226 ####################################################################
227 #
228 # Utility functions
229 #
230 ####################################################################
232 def arg_check(args,num,name):
233 if len(args) < num:
234 err("'xm %s' requires %s argument(s)!\n" % (name, num))
235 usage(name)
237 def unit(c):
238 if not c.isalpha():
239 return 0
240 base = 1
241 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
242 elif c == 'M' or c == 'm': base = 1024 * 1024
243 elif c == 'K' or c == 'k': base = 1024
244 else:
245 print 'ignoring unknown unit'
246 return base
248 def int_unit(str, dest):
249 base = unit(str[-1])
250 if not base:
251 return int(str)
253 value = int(str[:-1])
254 dst_base = unit(dest)
255 if dst_base == 0:
256 dst_base = 1
257 if dst_base > base:
258 return value / (dst_base / base)
259 else:
260 return value * (base / dst_base)
262 def err(msg):
263 print >>sys.stderr, "Error:", msg
265 def handle_xend_error(cmd, dom, ex):
266 error = str(ex)
267 if error == "Not found" and dom != None:
268 err("Domain '%s' not found when running 'xm %s'" % (dom, cmd))
269 sys.exit(1)
270 else:
271 err(error)
272 sys.exit(1)
275 #########################################################################
276 #
277 # Main xm functions
278 #
279 #########################################################################
281 def xm_save(args):
282 arg_check(args,2,"save")
284 dom = args[0] # TODO: should check if this exists
285 savefile = os.path.abspath(args[1])
287 if not os.access(os.path.dirname(savefile), os.W_OK):
288 err("xm save: Unable to create file %s" % savefile)
289 sys.exit(1)
291 from xen.xend.XendClient import server
292 server.xend_domain_save(dom, savefile)
294 def xm_restore(args):
295 arg_check(args,1,"restore")
297 savefile = os.path.abspath(args[0])
299 if not os.access(savefile, os.R_OK):
300 err("xm restore: Unable to read file %s" % savefile)
301 sys.exit(1)
303 from xen.xend.XendClient import server
304 info = server.xend_domain_restore(savefile)
305 PrettyPrint.prettyprint(info)
306 id = sxp.child_value(info, 'domid')
307 if id is not None:
308 server.xend_domain_unpause(domid)
311 def getDomains(domain_names):
312 from xen.xend.XendClient import server
313 if domain_names:
314 return map(server.xend_domain, domain_names)
315 else:
316 return server.xend_list_domains()
319 def xm_list(args):
320 use_long = 0
321 show_vcpus = 0
322 try:
323 (options, params) = getopt(args, 'lv', ['long','vcpus'])
324 except GetoptError, opterr:
325 err(opterr)
326 sys.exit(1)
328 for (k, v) in options:
329 if k in ['-l', '--long']:
330 use_long = 1
331 if k in ['-v', '--vcpus']:
332 show_vcpus = 1
334 if show_vcpus:
335 print >>sys.stderr, (
336 "xm list -v is deprecated. Please use xm vcpu-list.")
337 xm_vcpu_list(params)
338 return
340 doms = getDomains(params)
342 if use_long:
343 map(PrettyPrint.prettyprint, doms)
344 else:
345 xm_brief_list(doms)
348 def parse_doms_info(info):
349 def get_info(n, t, d):
350 return t(sxp.child_value(info, n, d))
352 return {
353 'dom' : get_info('domid', int, -1),
354 'name' : get_info('name', str, '??'),
355 'mem' : get_info('memory', int, 0),
356 'vcpus' : get_info('online_vcpus', int, 0),
357 'state' : get_info('state', str, '??'),
358 'cpu_time' : get_info('cpu_time', float, 0),
359 'ssidref' : get_info('ssidref', int, 0),
360 }
363 def xm_brief_list(doms):
364 print 'Name ID Mem(MiB) VCPUs State Time(s)'
365 for dom in doms:
366 d = parse_doms_info(dom)
367 if (d['ssidref'] != 0):
368 d['ssidstr'] = (" s:%04x/p:%04x" %
369 ((d['ssidref'] >> 16) & 0xffff,
370 d['ssidref'] & 0xffff))
371 else:
372 d['ssidstr'] = ""
373 print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f%(ssidstr)s" % d)
376 def xm_vcpu_list(args):
377 print 'Name ID VCPU CPU State Time(s) CPU Affinity'
379 from xen.xend.XendClient import server
380 if args:
381 dominfo = map(server.xend_domain_vcpuinfo, args)
382 else:
383 doms = server.xend_list_domains()
384 dominfo = map(
385 lambda x: server.xend_domain_vcpuinfo(sxp.child_value(x, 'name')),
386 doms)
388 for dom in dominfo:
389 def get_info(n):
390 return sxp.child_value(dom, n)
392 #
393 # convert a list of integers into a list of pairs indicating
394 # continuous sequences in the list:
395 #
396 # [0,1,2,3] -> [(0,3)]
397 # [1,2,4,5] -> [(1,2),(4,5)]
398 # [0] -> [(0,0)]
399 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
400 #
401 def list_to_rangepairs(cmap):
402 cmap.sort()
403 pairs = []
404 x = y = 0
405 for i in range(0,len(cmap)):
406 try:
407 if ((cmap[y+1] - cmap[i]) > 1):
408 pairs.append((cmap[x],cmap[y]))
409 x = y = i+1
410 else:
411 y = y + 1
412 # if we go off the end, then just add x to y
413 except IndexError:
414 pairs.append((cmap[x],cmap[y]))
416 return pairs
418 #
419 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
420 #
421 def format_pairs(pairs):
422 if not pairs:
423 return "no cpus"
424 out = ""
425 for f,s in pairs:
426 if (f==s):
427 out += '%d'%f
428 else:
429 out += '%d-%d'%(f,s)
430 out += ','
431 # trim trailing ','
432 return out[:-1]
434 def format_cpumap(cpumap):
435 cpumap = map(lambda x: int(x), cpumap)
436 cpumap.sort()
438 from xen.xend.XendClient import server
439 for x in server.xend_node()[1:]:
440 if len(x) > 1 and x[0] == 'nr_cpus':
441 nr_cpus = int(x[1])
442 cpumap = filter(lambda x: x < nr_cpus, cpumap)
443 if len(cpumap) == nr_cpus:
444 return "any cpu"
445 break
447 return format_pairs(list_to_rangepairs(cpumap))
449 name = get_info('name')
450 domid = int(get_info('domid'))
452 for vcpu in sxp.children(dom, 'vcpu'):
453 def vinfo(n, t):
454 return t(sxp.child_value(vcpu, n))
456 number = vinfo('number', int)
457 cpu = vinfo('cpu', int)
458 cpumap = format_cpumap(vinfo('cpumap', list))
459 online = vinfo('online', int)
460 cpu_time = vinfo('cpu_time', float)
461 running = vinfo('running', int)
462 blocked = vinfo('blocked', int)
464 if online:
465 c = str(cpu)
466 if running:
467 s = 'r'
468 else:
469 s = '-'
470 if blocked:
471 s += 'b'
472 else:
473 s += '-'
474 s += '-'
475 else:
476 c = "-"
477 s = "--p"
479 print (
480 "%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
481 locals())
484 def xm_reboot(args):
485 arg_check(args,1,"reboot")
486 from xen.xm import shutdown
487 # ugly hack because the opt parser apparently wants
488 # the subcommand name just to throw it away!
489 shutdown.main(["bogus", "-R"] + args)
491 def xm_pause(args):
492 arg_check(args, 1, "pause")
493 dom = args[0]
495 from xen.xend.XendClient import server
496 server.xend_domain_pause(dom)
498 def xm_unpause(args):
499 arg_check(args, 1, "unpause")
500 dom = args[0]
502 from xen.xend.XendClient import server
503 server.xend_domain_unpause(dom)
505 def xm_subcommand(command, args):
506 cmd = __import__(command, globals(), locals(), 'xen.xm')
507 cmd.main(["bogus"] + args)
510 #############################################################
512 def cpu_make_map(cpulist):
513 cpus = []
514 for c in cpulist.split(','):
515 if c.find('-') != -1:
516 (x,y) = c.split('-')
517 for i in range(int(x),int(y)+1):
518 cpus.append(int(i))
519 else:
520 cpus.append(int(c))
521 cpus.sort()
522 return cpus
524 def xm_vcpu_pin(args):
525 arg_check(args, 3, "vcpu-pin")
527 dom = args[0]
528 vcpu = int(args[1])
529 cpumap = cpu_make_map(args[2])
531 from xen.xend.XendClient import server
532 server.xend_domain_pincpu(dom, vcpu, cpumap)
534 def xm_mem_max(args):
535 arg_check(args, 2, "mem-max")
537 dom = args[0]
538 mem = int_unit(args[1], 'm')
540 from xen.xend.XendClient import server
541 server.xend_domain_maxmem_set(dom, mem)
543 def xm_mem_set(args):
544 arg_check(args, 2, "mem-set")
546 dom = args[0]
547 mem_target = int_unit(args[1], 'm')
549 from xen.xend.XendClient import server
550 server.xend_domain_mem_target_set(dom, mem_target)
552 def xm_set_vcpus(args):
553 arg_check(args, 2, "set-vcpus")
555 from xen.xend.XendClient import server
556 server.xend_domain_set_vcpus(args[0], int(args[1]))
558 def xm_domid(args):
559 arg_check(args, 1, "domid")
561 name = args[0]
563 from xen.xend.XendClient import server
564 dom = server.xend_domain(name)
565 print sxp.child_value(dom, 'domid')
567 def xm_domname(args):
568 arg_check(args, 1, "domname")
570 name = args[0]
572 from xen.xend.XendClient import server
573 dom = server.xend_domain(name)
574 print sxp.child_value(dom, 'name')
576 def xm_sched_bvt(args):
577 arg_check(args, 6, "sched-bvt")
578 dom = args[0]
579 v = map(long, args[1:6])
580 from xen.xend.XendClient import server
581 server.xend_domain_cpu_bvt_set(dom, *v)
583 def xm_sched_bvt_ctxallow(args):
584 arg_check(args, 1, "sched-bvt-ctxallow")
586 slice = int(args[0])
587 from xen.xend.XendClient import server
588 server.xend_node_cpu_bvt_slice_set(slice)
590 def xm_sched_sedf(args):
591 arg_check(args, 6, "sched-sedf")
593 dom = args[0]
594 v = map(int, args[1:6])
595 from xen.xend.XendClient import server
596 server.xend_domain_cpu_sedf_set(dom, *v)
598 def xm_info(args):
599 from xen.xend.XendClient import server
600 info = server.xend_node()
602 for x in info[1:]:
603 if len(x) < 2:
604 print "%-23s: (none)" % x[0]
605 else:
606 print "%-23s:" % x[0], x[1]
608 # TODO: remove as soon as console server shows up
609 def xm_console(args):
610 arg_check(args,1,"console")
612 dom = args[0]
613 from xen.xend.XendClient import server
614 info = server.xend_domain(dom)
615 domid = int(sxp.child_value(info, 'domid', '-1'))
616 console.execConsole(domid)
619 def xm_top(args):
620 os.execvp('xentop', ['xentop'])
622 def xm_dmesg(args):
624 gopts = Opts(use="""[-c|--clear]
626 Read Xen's message buffer (boot output, warning and error messages) or clear
627 its contents if the [-c|--clear] flag is specified.
628 """)
630 gopts.opt('clear', short='c',
631 fn=set_true, default=0,
632 use="Clear the contents of the Xen message buffer.")
633 # Work around for gopts
634 myargs = args
635 myargs.insert(0, "bogus")
636 gopts.parse(myargs)
637 if not (1 <= len(myargs) <= 2):
638 err('Invalid arguments: ' + str(myargs))
640 from xen.xend.XendClient import server
641 if not gopts.vals.clear:
642 print server.xend_node_get_dmesg()
643 else:
644 server.xend_node_clear_dmesg()
646 def xm_log(args):
647 from xen.xend.XendClient import server
648 print server.xend_node_log()
650 def xm_network_list(args):
651 arg_check(args,1,"network-list")
652 dom = args[0]
653 from xen.xend.XendClient import server
654 for x in server.xend_domain_devices(dom, 'vif'):
655 sxp.show(x)
656 print
658 def xm_block_list(args):
659 arg_check(args,1,"block-list")
660 dom = args[0]
661 from xen.xend.XendClient import server
662 for x in server.xend_domain_devices(dom, 'vbd'):
663 sxp.show(x)
664 print
666 def xm_block_attach(args):
667 n = len(args)
668 if n == 0:
669 usage("block-attach")
671 if n < 4 or n > 5:
672 err("%s: Invalid argument(s)" % args[0])
673 usage("block-attach")
675 dom = args[0]
676 vbd = ['vbd',
677 ['uname', args[1]],
678 ['dev', args[2]],
679 ['mode', args[3]]]
680 if n == 5:
681 vbd.append(['backend', args[4]])
683 from xen.xend.XendClient import server
684 server.xend_domain_device_create(dom, vbd)
687 def xm_network_attach(args):
688 n = len(args)
689 if n == 0:
690 usage("network-attach")
692 dom = args[0]
693 vif = ['vif']
695 for a in args[1:]:
696 vif.append(a.split("="))
698 from xen.xend.XendClient import server
699 server.xend_domain_device_create(dom, vif)
702 def detach(args, command, deviceClass):
703 arg_check(args, 2, command)
705 dom = args[0]
706 dev = args[1]
708 from xen.xend.XendClient import server
709 server.xend_domain_device_destroy(dom, deviceClass, dev)
712 def xm_block_detach(args):
713 detach(args, 'block-detach', 'vbd')
716 def xm_network_detach(args):
717 detach(args, 'network-detach', 'vif')
720 def xm_vnet_list(args):
721 from xen.xend.XendClient import server
722 try:
723 (options, params) = getopt(args, 'l', ['long'])
724 except GetoptError, opterr:
725 err(opterr)
726 sys.exit(1)
728 use_long = 0
729 for (k, v) in options:
730 if k in ['-l', '--long']:
731 use_long = 1
733 if params:
734 use_long = 1
735 vnets = params
736 else:
737 vnets = server.xend_vnets()
739 for vnet in vnets:
740 try:
741 if use_long:
742 info = server.xend_vnet(vnet)
743 PrettyPrint.prettyprint(info)
744 else:
745 print vnet
746 except Exception, ex:
747 print vnet, ex
749 def xm_vnet_create(args):
750 arg_check(args, 1, "vnet-create")
751 conf = args[0]
752 if not os.access(conf, os.R_OK):
753 print "File not found: %s" % conf
754 sys.exit(1)
756 from xen.xend.XendClient import server
757 server.xend_vnet_create(conf)
759 def xm_vnet_delete(args):
760 arg_check(args, 1, "vnet-delete")
761 vnet = args[0]
762 from xen.xend.XendClient import server
763 server.xend_vnet_delete(vnet)
765 commands = {
766 # console commands
767 "console": xm_console,
768 # xenstat commands
769 "top": xm_top,
770 # domain commands
771 "domid": xm_domid,
772 "domname": xm_domname,
773 "restore": xm_restore,
774 "save": xm_save,
775 "reboot": xm_reboot,
776 "list": xm_list,
777 # memory commands
778 "mem-max": xm_mem_max,
779 "mem-set": xm_mem_set,
780 # cpu commands
781 "vcpu-pin": xm_vcpu_pin,
782 "set-vcpus": xm_set_vcpus,
783 "vcpu-list": xm_vcpu_list,
784 # special
785 "pause": xm_pause,
786 "unpause": xm_unpause,
787 # host commands
788 "dmesg": xm_dmesg,
789 "info": xm_info,
790 "log": xm_log,
791 # scheduler
792 "sched-bvt": xm_sched_bvt,
793 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
794 "sched-sedf": xm_sched_sedf,
795 # block
796 "block-attach": xm_block_attach,
797 "block-detach": xm_block_detach,
798 "block-list": xm_block_list,
799 # network
800 "network-attach": xm_network_attach,
801 "network-detach": xm_network_detach,
802 "network-list": xm_network_list,
803 # vnet
804 "vnet-list": xm_vnet_list,
805 "vnet-create": xm_vnet_create,
806 "vnet-delete": xm_vnet_delete,
807 }
809 ## The commands supported by a separate argument parser in xend.xm.
810 subcommands = [
811 'create',
812 'destroy',
813 'migrate',
814 'sysrq',
815 'shutdown'
816 ]
818 for c in subcommands:
819 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
821 aliases = {
822 "balloon": "mem-set",
823 "vif-list": "network-list",
824 "vbd-create": "block-create",
825 "vbd-destroy": "block-destroy",
826 "vbd-list": "block-list",
827 }
830 def xm_lookup_cmd(cmd):
831 if commands.has_key(cmd):
832 return commands[cmd]
833 elif aliases.has_key(cmd):
834 deprecated(cmd,aliases[cmd])
835 return commands[aliases[cmd]]
836 else:
837 if len( cmd ) > 1:
838 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
839 if len( matched_commands ) == 1:
840 return matched_commands[0][1]
841 err('Sub Command %s not found!' % cmd)
842 usage()
844 def deprecated(old,new):
845 err('Option %s is deprecated, and will be removed in future!!!' % old)
846 err('Option %s is the new replacement, see "xm help %s" for more info' % (new, new))
848 def usage(cmd=None):
849 if cmd == 'create':
850 xm_subcommand("create", "--help")
851 sys.exit(1)
852 if help.has_key(cmd):
853 print " " + help[cmd]
854 else:
855 print shorthelp
856 sys.exit(1)
858 def main(argv=sys.argv):
859 if len(argv) < 2:
860 usage()
862 if re.compile('-*help').match(argv[1]):
863 if len(argv) > 2:
864 usage(argv[2])
865 else:
866 usage()
867 sys.exit(0)
869 cmd = xm_lookup_cmd(argv[1])
871 # strip off prog name and subcmd
872 args = argv[2:]
873 if cmd:
874 try:
875 rc = cmd(args)
876 if rc:
877 usage()
878 except socket.error, ex:
879 if os.geteuid() != 0:
880 err("Most commands need root access. Please try again as root.")
881 else:
882 err("Error connecting to xend: %s. Is xend running?" % ex[1])
883 sys.exit(1)
884 except KeyboardInterrupt:
885 print "Interrupted."
886 sys.exit(1)
887 except IOError, ex:
888 if os.geteuid() != 0:
889 err("Most commands need root access. Please try again as root.")
890 else:
891 err("Error connecting to xend: %s." % ex[1])
892 sys.exit(1)
893 except xen.xend.XendError.XendError, ex:
894 if len(args) > 0:
895 handle_xend_error(argv[1], args[0], ex)
896 else:
897 print "Unexpected error:", sys.exc_info()[0]
898 print
899 print "Please report to xen-devel@lists.xensource.com"
900 raise
901 except xen.xend.XendProtocol.XendError, ex:
902 if len(args) > 0:
903 handle_xend_error(argv[1], args[0], ex)
904 else:
905 print "Unexpected error:", sys.exc_info()[0]
906 print
907 print "Please report to xen-devel@lists.xensource.com"
908 raise
909 except SystemExit:
910 sys.exit(1)
911 except:
912 print "Unexpected error:", sys.exc_info()[0]
913 print
914 print "Please report to xen-devel@lists.xensource.com"
915 raise
917 else:
918 usage()
920 if __name__ == "__main__":
921 main()