ia64/xen-unstable

view tools/python/xen/xm/main.py @ 9544:1d0bd5ea2c87

Print error messages to stderr. Remove unused handle_xend_error.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Fri Mar 31 00:14:09 2006 +0100 (2006-03-31)
parents 33df7d4eff23
children 681a18bf049e
line source
1 # (C) Copyright IBM Corp. 2005
2 # Copyright (C) 2004 Mike Wray
3 # Copyright (c) 2005-2006 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 re
28 import getopt
29 import socket
30 import warnings
31 warnings.filterwarnings('ignore', category=FutureWarning)
32 import xmlrpclib
34 import xen.xend.XendProtocol
36 from xen.xend import PrettyPrint
37 from xen.xend import sxp
38 from xen.xm.opts import *
40 import console
41 import xen.xend.XendClient
42 from xen.xend.XendClient import server
44 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
45 # getopt.getopt if gnu_getopt is not available. This will mean that options
46 # may only be specified before positional arguments.
47 if not hasattr(getopt, 'gnu_getopt'):
48 getopt.gnu_getopt = getopt.getopt
51 # Strings for shorthelp
52 console_help = "console <DomId> Attach to domain DomId's console."
53 create_help = """create [-c] <ConfigFile>
54 [Name=Value].. Create a domain based on Config File"""
55 destroy_help = "destroy <DomId> Terminate a domain immediately"
56 help_help = "help Display this message"
57 list_help = "list [--long] [DomId, ...] List information about domains"
58 mem_max_help = "mem-max <DomId> <Mem> Set maximum memory reservation for a domain"
59 mem_set_help = "mem-set <DomId> <Mem> Adjust the current memory usage for a domain"
60 migrate_help = "migrate <DomId> <Host> Migrate a domain to another machine"
61 pause_help = "pause <DomId> Pause execution of a domain"
62 reboot_help = "reboot <DomId> [-w][-a] Reboot a domain"
63 restore_help = "restore <File> Create a domain from a saved state file"
64 save_help = "save <DomId> <File> Save domain state (and config) to file"
65 shutdown_help ="shutdown <DomId> [-w][-a][-R|-H] Shutdown a domain"
66 top_help = "top Monitor system and domains in real-time"
67 unpause_help = "unpause <DomId> Unpause a paused domain"
69 help_spacer = """
70 """
72 # Strings for longhelp
73 sysrq_help = "sysrq <DomId> <letter> Send a sysrq to a domain"
74 domid_help = "domid <DomName> Converts a domain name to a domain id"
75 domname_help = "domname <DomId> Convert a domain id to a domain name"
76 vcpu_set_help = """vcpu-set <DomId> <VCPUs> Set the number of VCPUs for a domain"""
77 vcpu_list_help = "vcpu-list <DomId> List the VCPUs for a domain (or all domains)"
78 vcpu_pin_help = "vcpu-pin <DomId> <VCPU> <CPUs> Set which cpus a VCPU can use"
79 dmesg_help = "dmesg [-c|--clear] Read or clear Xen's message buffer"
80 info_help = "info Get information about the xen host"
81 rename_help = "rename <DomId> <New Name> Rename a domain"
82 log_help = "log Print the xend log"
83 sched_bvt_help = """sched-bvt <Parameters> Set Borrowed Virtual Time scheduler
84 parameters"""
85 sched_bvt_ctxallow_help = """sched-bvt-ctxallow <Allow> Set the BVT scheduler context switch
86 allowance"""
87 sched_sedf_help = "sched-sedf [DOM] [OPTIONS] Show|Set simple EDF parameters\n" + \
88 " -p, --period Relative deadline(ms).\n\
89 -s, --slice Worst-case execution time(ms)\n\
90 (slice < period).\n\
91 -l, --latency scaled period(ms) in case the domain\n\
92 is doing heavy I/O.\n\
93 -e, --extra flag (0/1) which controls whether the\n\
94 domain can run in extra-time\n\
95 -w, --weight mutually exclusive with period/slice and\n\
96 specifies another way of setting a domain's\n\
97 cpu period/slice."
99 block_attach_help = """block-attach <DomId> <BackDev> <FrontDev> <Mode>
100 [BackDomId] Create a new virtual block device"""
101 block_detach_help = """block-detach <DomId> <DevId> Destroy a domain's virtual block device,
102 where <DevId> may either be the device ID
103 or the device name as mounted in the guest"""
105 block_list_help = "block-list <DomId> [--long] List virtual block devices for a domain"
106 network_attach_help = """network-attach <DomID> [script=<script>] [ip=<ip>] [mac=<mac>]
107 [bridge=<bridge>] [backend=<backDomID>]
108 Create a new virtual network device """
109 network_detach_help = """network-detach <DomId> <DevId> Destroy a domain's virtual network
110 device, where <DevId> is the device ID."""
112 network_list_help = "network-list <DomId> [--long] List virtual network interfaces for a domain"
113 vnet_list_help = "vnet-list [-l|--long] list vnets"
114 vnet_create_help = "vnet-create <config> create a vnet from a config file"
115 vnet_delete_help = "vnet-delete <vnetid> delete a vnet"
116 vtpm_list_help = "vtpm-list <DomId> [--long] list virtual TPM devices"
118 short_command_list = [
119 "console",
120 "create",
121 "destroy",
122 "help",
123 "list",
124 "mem-set",
125 "migrate",
126 "pause",
127 "reboot",
128 "restore",
129 "save",
130 "shutdown",
131 "top",
132 "unpause",
133 "vcpu-set",
134 ]
136 domain_commands = [
137 "console",
138 "create",
139 "destroy",
140 "domid",
141 "domname",
142 "list",
143 "mem-max",
144 "mem-set",
145 "migrate",
146 "pause",
147 "reboot",
148 "rename",
149 "restore",
150 "save",
151 "shutdown",
152 "sysrq",
153 "top",
154 "unpause",
155 "vcpu-list",
156 "vcpu-pin",
157 "vcpu-set",
158 ]
160 host_commands = [
161 "dmesg",
162 "info",
163 "log"
164 ]
166 scheduler_commands = [
167 "sched-bvt",
168 "sched-bvt-ctxallow",
169 "sched-sedf",
170 ]
172 device_commands = [
173 "block-attach",
174 "block-detach",
175 "block-list",
176 "network-attach",
177 "network-detach",
178 "network-list",
179 "vtpm-list",
180 ]
182 vnet_commands = [
183 "vnet-list",
184 "vnet-create",
185 "vnet-delete",
186 ]
188 all_commands = (domain_commands + host_commands + scheduler_commands +
189 device_commands + vnet_commands)
192 def commandToHelp(cmd):
193 return eval(cmd.replace("-", "_") + "_help")
196 shorthelp = """Usage: xm <subcommand> [args]
197 Control, list, and manipulate Xen guest instances
199 xm common subcommands:
200 """ + help_spacer.join(map(commandToHelp, short_command_list)) + """
202 <DomName> can be substituted for <DomId> in xm subcommands.
204 For a complete list of subcommands run 'xm help --long'
205 For more help on xm see the xm(1) man page
206 For more help on xm create, see the xmdomain.cfg(5) man page"""
208 longhelp = """Usage: xm <subcommand> [args]
209 Control, list, and manipulate Xen guest instances
211 xm full list of subcommands:
213 Domain Commands:
214 """ + help_spacer.join(map(commandToHelp, domain_commands)) + """
216 Xen Host Commands:
217 """ + help_spacer.join(map(commandToHelp, host_commands)) + """
219 Scheduler Commands:
220 """ + help_spacer.join(map(commandToHelp, scheduler_commands)) + """
222 Virtual Device Commands:
223 """ + help_spacer.join(map(commandToHelp, device_commands)) + """
225 Vnet commands:
226 """ + help_spacer.join(map(commandToHelp, vnet_commands)) + """
228 <DomName> can be substituted for <DomId> in xm subcommands.
230 For a short list of subcommands run 'xm help'
231 For more help on xm see the xm(1) man page
232 For more help on xm create, see the xmdomain.cfg(5) man page"""
234 # array for xm help <command>
235 help = {
236 "--long": longhelp
237 }
239 for command in all_commands:
240 # create is handled specially
241 if (command != 'create'):
242 help[command] = commandToHelp(command)
245 ####################################################################
246 #
247 # Utility functions
248 #
249 ####################################################################
251 def arg_check(args, name, lo, hi = -1):
252 n = len(args)
254 if hi == -1:
255 if n != lo:
256 err("'xm %s' requires %d argument%s.\n" % (name, lo,
257 lo > 1 and 's' or ''))
258 usage(name)
259 else:
260 if n < lo or n > hi:
261 err("'xm %s' requires between %d and %d arguments.\n" %
262 (name, lo, hi))
263 usage(name)
266 def unit(c):
267 if not c.isalpha():
268 return 0
269 base = 1
270 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
271 elif c == 'M' or c == 'm': base = 1024 * 1024
272 elif c == 'K' or c == 'k': base = 1024
273 else:
274 print 'ignoring unknown unit'
275 return base
277 def int_unit(str, dest):
278 base = unit(str[-1])
279 if not base:
280 return int(str)
282 value = int(str[:-1])
283 dst_base = unit(dest)
284 if dst_base == 0:
285 dst_base = 1
286 if dst_base > base:
287 return value / (dst_base / base)
288 else:
289 return value * (base / dst_base)
291 def err(msg):
292 print >>sys.stderr, "Error:", msg
295 #########################################################################
296 #
297 # Main xm functions
298 #
299 #########################################################################
301 def xm_save(args):
302 arg_check(args, "save", 2)
304 dom = args[0] # TODO: should check if this exists
305 savefile = os.path.abspath(args[1])
307 if not os.access(os.path.dirname(savefile), os.W_OK):
308 err("xm save: Unable to create file %s" % savefile)
309 sys.exit(1)
311 server.xend.domain.save(dom, savefile)
313 def xm_restore(args):
314 arg_check(args, "restore", 1)
316 savefile = os.path.abspath(args[0])
318 if not os.access(savefile, os.R_OK):
319 err("xm restore: Unable to read file %s" % savefile)
320 sys.exit(1)
322 server.xend.domain.restore(savefile)
325 def getDomains(domain_names):
326 if domain_names:
327 return map(server.xend.domain, domain_names)
328 else:
329 return server.xend.domains(1)
332 def xm_list(args):
333 use_long = 0
334 show_vcpus = 0
335 try:
336 (options, params) = getopt.gnu_getopt(args, 'lv', ['long','vcpus'])
337 except getopt.GetoptError, opterr:
338 err(opterr)
339 sys.exit(1)
341 for (k, v) in options:
342 if k in ['-l', '--long']:
343 use_long = 1
344 if k in ['-v', '--vcpus']:
345 show_vcpus = 1
347 if show_vcpus:
348 print >>sys.stderr, (
349 "xm list -v is deprecated. Please use xm vcpu-list.")
350 xm_vcpu_list(params)
351 return
353 doms = getDomains(params)
355 if use_long:
356 map(PrettyPrint.prettyprint, doms)
357 else:
358 xm_brief_list(doms)
361 def parse_doms_info(info):
362 def get_info(n, t, d):
363 return t(sxp.child_value(info, n, d))
365 return {
366 'dom' : get_info('domid', int, -1),
367 'name' : get_info('name', str, '??'),
368 'mem' : get_info('memory', int, 0),
369 'vcpus' : get_info('online_vcpus', int, 0),
370 'state' : get_info('state', str, '??'),
371 'cpu_time' : get_info('cpu_time', float, 0),
372 'ssidref' : get_info('ssidref', int, 0),
373 }
376 def parse_sedf_info(info):
377 def get_info(n, t, d):
378 return t(sxp.child_value(info, n, d))
380 return {
381 'dom' : get_info('domain', int, -1),
382 'period' : get_info('period', int, -1),
383 'slice' : get_info('slice', int, -1),
384 'latency' : get_info('latency', int, -1),
385 'extratime': get_info('extratime', int, -1),
386 'weight' : get_info('weight', int, -1),
387 }
390 def xm_brief_list(doms):
391 print 'Name ID Mem(MiB) VCPUs State Time(s)'
392 for dom in doms:
393 d = parse_doms_info(dom)
394 if (d['ssidref'] != 0):
395 d['ssidstr'] = (" s:%04x/p:%04x" %
396 ((d['ssidref'] >> 16) & 0xffff,
397 d['ssidref'] & 0xffff))
398 else:
399 d['ssidstr'] = ""
400 print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f%(ssidstr)s" % d)
403 def xm_vcpu_list(args):
405 if args:
406 dominfo = map(server.xend.domain.getVCPUInfo, args)
407 else:
408 doms = server.xend.domains(False)
409 dominfo = map(server.xend.domain.getVCPUInfo, doms)
411 print 'Name ID VCPU CPU State Time(s) CPU Affinity'
413 for dom in dominfo:
414 def get_info(n):
415 return sxp.child_value(dom, n)
417 #
418 # convert a list of integers into a list of pairs indicating
419 # continuous sequences in the list:
420 #
421 # [0,1,2,3] -> [(0,3)]
422 # [1,2,4,5] -> [(1,2),(4,5)]
423 # [0] -> [(0,0)]
424 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
425 #
426 def list_to_rangepairs(cmap):
427 cmap.sort()
428 pairs = []
429 x = y = 0
430 for i in range(0,len(cmap)):
431 try:
432 if ((cmap[y+1] - cmap[i]) > 1):
433 pairs.append((cmap[x],cmap[y]))
434 x = y = i+1
435 else:
436 y = y + 1
437 # if we go off the end, then just add x to y
438 except IndexError:
439 pairs.append((cmap[x],cmap[y]))
441 return pairs
443 #
444 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
445 #
446 def format_pairs(pairs):
447 if not pairs:
448 return "no cpus"
449 out = ""
450 for f,s in pairs:
451 if (f==s):
452 out += '%d'%f
453 else:
454 out += '%d-%d'%(f,s)
455 out += ','
456 # trim trailing ','
457 return out[:-1]
459 def format_cpumap(cpumap):
460 cpumap = map(lambda x: int(x), cpumap)
461 cpumap.sort()
463 for x in server.xend.node.info()[1:]:
464 if len(x) > 1 and x[0] == 'nr_cpus':
465 nr_cpus = int(x[1])
466 # normalize cpumap by modulus nr_cpus, and drop duplicates
467 cpumap = dict.fromkeys(
468 map(lambda x: x % nr_cpus, cpumap)).keys()
469 if len(cpumap) == nr_cpus:
470 return "any cpu"
471 break
473 return format_pairs(list_to_rangepairs(cpumap))
475 name = get_info('name')
476 domid = int(get_info('domid'))
478 for vcpu in sxp.children(dom, 'vcpu'):
479 def vinfo(n, t):
480 return t(sxp.child_value(vcpu, n))
482 number = vinfo('number', int)
483 cpu = vinfo('cpu', int)
484 cpumap = format_cpumap(vinfo('cpumap', list))
485 online = vinfo('online', int)
486 cpu_time = vinfo('cpu_time', float)
487 running = vinfo('running', int)
488 blocked = vinfo('blocked', int)
490 if online:
491 c = str(cpu)
492 if running:
493 s = 'r'
494 else:
495 s = '-'
496 if blocked:
497 s += 'b'
498 else:
499 s += '-'
500 s += '-'
501 else:
502 c = "-"
503 s = "--p"
505 print (
506 "%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
507 locals())
510 def xm_reboot(args):
511 arg_check(args, "reboot", 1, 4)
512 from xen.xm import shutdown
513 shutdown.main(["shutdown", "-R"] + args)
515 def xm_pause(args):
516 arg_check(args, "pause", 1)
517 dom = args[0]
519 server.xend.domain.pause(dom)
521 def xm_unpause(args):
522 arg_check(args, "unpause", 1)
523 dom = args[0]
525 server.xend.domain.unpause(dom)
527 def xm_rename(args):
528 arg_check(args, "rename", 2)
530 server.xend.domain.setName(args[0], args[1])
532 def xm_subcommand(command, args):
533 cmd = __import__(command, globals(), locals(), 'xen.xm')
534 cmd.main([command] + args)
537 #############################################################
539 def cpu_make_map(cpulist):
540 cpus = []
541 for c in cpulist.split(','):
542 if c.find('-') != -1:
543 (x,y) = c.split('-')
544 for i in range(int(x),int(y)+1):
545 cpus.append(int(i))
546 else:
547 cpus.append(int(c))
548 cpus.sort()
549 return cpus
551 def xm_vcpu_pin(args):
552 arg_check(args, "vcpu-pin", 3)
554 dom = args[0]
555 vcpu = int(args[1])
556 cpumap = cpu_make_map(args[2])
558 server.xend.domain.pincpu(dom, vcpu, cpumap)
560 def xm_mem_max(args):
561 arg_check(args, "mem-max", 2)
563 dom = args[0]
564 mem = int_unit(args[1], 'm')
566 server.xend.domain.maxmem_set(dom, mem)
568 def xm_mem_set(args):
569 arg_check(args, "mem-set", 2)
571 dom = args[0]
572 mem_target = int_unit(args[1], 'm')
574 server.xend.domain.setMemoryTarget(dom, mem_target)
576 def xm_vcpu_set(args):
577 arg_check(args, "vcpu-set", 2)
579 server.xend.domain.setVCpuCount(args[0], int(args[1]))
582 def xm_destroy(args):
583 arg_check(args, "destroy", 1)
584 server.xend.domain.destroy(args[0])
587 def xm_domid(args):
588 arg_check(args, "domid", 1)
590 name = args[0]
592 dom = server.xend.domain(name)
593 print sxp.child_value(dom, 'domid')
595 def xm_domname(args):
596 arg_check(args, "domname", 1)
598 name = args[0]
600 dom = server.xend.domain(name)
601 print sxp.child_value(dom, 'name')
603 def xm_sched_bvt(args):
604 arg_check(args, "sched-bvt", 6)
605 dom = args[0]
606 v = map(long, args[1:6])
607 server.xend.domain.cpu_bvt_set(dom, *v)
609 def xm_sched_bvt_ctxallow(args):
610 arg_check(args, "sched-bvt-ctxallow", 1)
612 slice = int(args[0])
613 server.xend.node.cpu_bvt_slice_set(slice)
615 def xm_sched_sedf(args):
616 def ns_to_ms(val):
617 return float(val) * 0.000001
619 def ms_to_ns(val):
620 return (float(val) / 0.000001)
622 def print_sedf(info):
623 info['period'] = ns_to_ms(info['period'])
624 info['slice'] = ns_to_ms(info['slice'])
625 info['latency'] = ns_to_ms(info['latency'])
626 print( ("%(name)-32s %(dom)3d %(period)9.1f %(slice)9.1f" +
627 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
629 def domid_match(domid, info):
630 return domid is None or domid == info['name'] or domid == str(info['dom'])
632 # we want to just display current info if no parameters are passed
633 if len(args) == 0:
634 domid = None
635 else:
636 # we expect at least a domain id (name or number)
637 # and at most a domid up to 5 options with values
638 arg_check(args, "sched-sedf", 1, 11)
639 domid = args[0]
640 # drop domid from args since get_opt doesn't recognize it
641 args = args[1:]
643 opts = {}
644 try:
645 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
646 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
647 except getopt.GetoptError, opterr:
648 err(opterr)
649 sys.exit(1)
651 # convert to nanoseconds if needed
652 for (k, v) in options:
653 if k in ['-p', '--period']:
654 opts['period'] = ms_to_ns(v)
655 elif k in ['-s', '--slice']:
656 opts['slice'] = ms_to_ns(v)
657 elif k in ['-l', '--latency']:
658 opts['latency'] = ms_to_ns(v)
659 elif k in ['-e', '--extratime']:
660 opts['extratime'] = v
661 elif k in ['-w', '--weight']:
662 opts['weight'] = v
664 # print header if we aren't setting any parameters
665 if len(opts.keys()) == 0:
666 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s'%('Name','ID','Period(ms)',
667 'Slice(ms)', 'Lat(ms)',
668 'Extra','Weight')
670 doms = filter(lambda x : domid_match(domid, x),
671 [parse_doms_info(dom) for dom in getDomains("")])
672 for d in doms:
673 # fetch current values so as not to clobber them
674 sedf_info = \
675 parse_sedf_info(server.xend.domain.cpu_sedf_get(d['dom']))
676 sedf_info['name'] = d['name']
678 # update values in case of call to set
679 if len(opts.keys()) > 0:
680 for k in opts.keys():
681 sedf_info[k]=opts[k]
683 # send the update, converting user input
684 v = map(int, [sedf_info['period'], sedf_info['slice'],
685 sedf_info['latency'],sedf_info['extratime'],
686 sedf_info['weight']])
687 rv = server.xend.domain.cpu_sedf_set(d['dom'], *v)
688 if int(rv) != 0:
689 err("Failed to set sedf parameters (rv=%d)."%(rv))
691 # not setting values, display info
692 else:
693 print_sedf(sedf_info)
696 def xm_info(args):
697 arg_check(args, "info", 0)
699 info = server.xend.node.info()
701 for x in info[1:]:
702 if len(x) < 2:
703 print "%-23s: (none)" % x[0]
704 else:
705 print "%-23s:" % x[0], x[1]
707 def xm_console(args):
708 arg_check(args, "console", 1)
710 dom = args[0]
711 info = server.xend.domain(dom)
712 domid = int(sxp.child_value(info, 'domid', '-1'))
713 console.execConsole(domid)
716 def xm_top(args):
717 arg_check(args, "top", 0)
719 os.execvp('xentop', ['xentop'])
721 def xm_dmesg(args):
722 arg_check(args, "dmesg", 0)
724 gopts = Opts(use="""[-c|--clear]
726 Read Xen's message buffer (boot output, warning and error messages) or clear
727 its contents if the [-c|--clear] flag is specified.
728 """)
730 gopts.opt('clear', short='c',
731 fn=set_true, default=0,
732 use="Clear the contents of the Xen message buffer.")
733 # Work around for gopts
734 myargs = args
735 myargs.insert(0, 'dmesg')
736 gopts.parse(myargs)
737 if not (1 <= len(myargs) <= 2):
738 err('Invalid arguments: ' + str(myargs))
740 if not gopts.vals.clear:
741 print server.xend.node.dmesg.info()
742 else:
743 server.xend.node.dmesg.clear()
745 def xm_log(args):
746 arg_check(args, "log", 0)
748 print server.xend.node.log()
750 def parse_dev_info(info):
751 def get_info(n, t, d):
752 i = 0
753 while i < len(info):
754 if (info[i][0] == n):
755 return t(info[i][1])
756 i = i + 1
757 return t(d)
758 return {
759 #common
760 'backend-id' : get_info('backend-id', int, -1),
761 'handle' : get_info('handle', int, 0),
762 'state' : get_info('state', int, -1),
763 'be-path' : get_info('backend', str, '??'),
764 'event-ch' : get_info('event-channel',int, -1),
765 #network specific
766 'virtual-device' : get_info('virtual-device', str, '??'),
767 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
768 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
769 'mac' : get_info('mac', str, '??'),
770 #block-device specific
771 'ring-ref' : get_info('ring-ref', int, -1),
772 }
774 def has_long_option(args):
775 use_long = 0
776 try:
777 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
778 except getopt.GetoptError, opterr:
779 err(opterr)
780 sys.exit(1)
782 for (k, v) in options:
783 if k in ['-l', '--long']:
784 use_long = 1
785 return (use_long, params)
787 def xm_network_list(args):
788 arg_check(args, "network-list", 1, 2)
790 (use_long, params) = has_long_option(args)
792 if len(params) == 0:
793 print 'No domain parameter given'
794 sys.exit(1)
795 dom = params[0]
796 if use_long:
797 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
798 map(PrettyPrint.prettyprint, devs)
799 else:
800 hdr = 0
801 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
802 if hdr == 0:
803 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
804 hdr = 1
805 ni = parse_dev_info(x[1])
806 ni['idx'] = int(x[0])
807 print ("%(idx)-3d "
808 "%(backend-id)-3d"
809 "%(mac)-17s "
810 "%(handle)-3d "
811 "%(state)-3d "
812 "%(event-ch)-3d "
813 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
814 "%(be-path)-30s "
815 % ni)
817 def xm_block_list(args):
818 arg_check(args, "block-list", 1, 2)
820 (use_long, params) = has_long_option(args)
822 if len(params) == 0:
823 print 'No domain parameter given'
824 sys.exit(1)
825 dom = params[0]
826 if use_long:
827 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
828 map(PrettyPrint.prettyprint, devs)
829 else:
830 hdr = 0
831 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
832 if hdr == 0:
833 print 'Vdev BE handle state evt-ch ring-ref BE-path'
834 hdr = 1
835 ni = parse_dev_info(x[1])
836 ni['idx'] = int(x[0])
837 print ("%(idx)-3d "
838 "%(backend-id)-3d "
839 "%(handle)-3d "
840 "%(state)-3d "
841 "%(event-ch)-3d "
842 "%(ring-ref)-5d "
843 "%(be-path)-30s "
844 % ni)
846 def xm_vtpm_list(args):
847 arg_check(args, "vtpm-list", 1, 2)
849 (use_long, params) = has_long_option(args)
851 if len(params) == 0:
852 print 'No domain parameter given'
853 sys.exit(1)
854 dom = params[0]
855 if use_long:
856 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
857 map(PrettyPrint.prettyprint, devs)
858 else:
859 hdr = 0
860 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
861 if hdr == 0:
862 print 'Idx BE handle state evt-ch ring-ref BE-path'
863 hdr = 1
864 ni = parse_dev_info(x[1])
865 ni['idx'] = int(x[0])
866 print ("%(idx)-3d "
867 "%(backend-id)-3d "
868 "%(handle)-3d "
869 "%(state)-3d "
870 "%(event-ch)-3d "
871 "%(ring-ref)-5d "
872 "%(be-path)-30s "
873 % ni)
875 def xm_block_attach(args):
876 arg_check(args, 'block-attach', 4, 5)
878 dom = args[0]
879 vbd = ['vbd',
880 ['uname', args[1]],
881 ['dev', args[2]],
882 ['mode', args[3]]]
883 if len(args) == 5:
884 vbd.append(['backend', args[4]])
886 server.xend.domain.device_create(dom, vbd)
889 def xm_network_attach(args):
890 arg_check(args, 'network-attach', 1, 10000)
892 dom = args[0]
893 vif = ['vif']
895 for a in args[1:]:
896 vif.append(a.split("="))
898 server.xend.domain.device_create(dom, vif)
901 def detach(args, command, deviceClass):
902 arg_check(args, command, 2)
904 dom = args[0]
905 dev = args[1]
907 server.xend.domain.destroyDevice(dom, deviceClass, dev)
910 def xm_block_detach(args):
911 detach(args, 'block-detach', 'vbd')
914 def xm_network_detach(args):
915 detach(args, 'network-detach', 'vif')
918 def xm_vnet_list(args):
919 try:
920 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
921 except getopt.GetoptError, opterr:
922 err(opterr)
923 sys.exit(1)
925 use_long = 0
926 for (k, v) in options:
927 if k in ['-l', '--long']:
928 use_long = 1
930 if params:
931 use_long = 1
932 vnets = params
933 else:
934 vnets = server.xend_vnets()
936 for vnet in vnets:
937 try:
938 if use_long:
939 info = server.xend_vnet(vnet)
940 PrettyPrint.prettyprint(info)
941 else:
942 print vnet
943 except Exception, ex:
944 print vnet, ex
946 def xm_vnet_create(args):
947 arg_check(args, "vnet-create", 1)
948 conf = args[0]
949 if not os.access(conf, os.R_OK):
950 print "File not found: %s" % conf
951 sys.exit(1)
953 server.xend_vnet_create(conf)
955 def xm_vnet_delete(args):
956 arg_check(args, "vnet-delete", 1)
957 vnet = args[0]
958 server.xend_vnet_delete(vnet)
960 commands = {
961 # console commands
962 "console": xm_console,
963 # xenstat commands
964 "top": xm_top,
965 # domain commands
966 "destroy": xm_destroy,
967 "domid": xm_domid,
968 "domname": xm_domname,
969 "rename": xm_rename,
970 "restore": xm_restore,
971 "save": xm_save,
972 "reboot": xm_reboot,
973 "list": xm_list,
974 # memory commands
975 "mem-max": xm_mem_max,
976 "mem-set": xm_mem_set,
977 # cpu commands
978 "vcpu-pin": xm_vcpu_pin,
979 "vcpu-list": xm_vcpu_list,
980 "vcpu-set": xm_vcpu_set,
981 # special
982 "pause": xm_pause,
983 "unpause": xm_unpause,
984 # host commands
985 "dmesg": xm_dmesg,
986 "info": xm_info,
987 "log": xm_log,
988 # scheduler
989 "sched-bvt": xm_sched_bvt,
990 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
991 "sched-sedf": xm_sched_sedf,
992 # block
993 "block-attach": xm_block_attach,
994 "block-detach": xm_block_detach,
995 "block-list": xm_block_list,
996 # network
997 "network-attach": xm_network_attach,
998 "network-detach": xm_network_detach,
999 "network-list": xm_network_list,
1000 # vnet
1001 "vnet-list": xm_vnet_list,
1002 "vnet-create": xm_vnet_create,
1003 "vnet-delete": xm_vnet_delete,
1004 # vtpm
1005 "vtpm-list": xm_vtpm_list,
1008 ## The commands supported by a separate argument parser in xend.xm.
1009 subcommands = [
1010 'create',
1011 'migrate',
1012 'sysrq',
1013 'shutdown'
1016 for c in subcommands:
1017 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
1019 aliases = {
1020 "balloon": "mem-set",
1021 "set-vcpus": "vcpu-set",
1022 "vif-list": "network-list",
1023 "vbd-create": "block-attach",
1024 "vbd-destroy": "block-detach",
1025 "vbd-list": "block-list",
1029 def xm_lookup_cmd(cmd):
1030 if commands.has_key(cmd):
1031 return commands[cmd]
1032 elif aliases.has_key(cmd):
1033 deprecated(cmd,aliases[cmd])
1034 return commands[aliases[cmd]]
1035 else:
1036 if len( cmd ) > 1:
1037 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
1038 if len( matched_commands ) == 1:
1039 return matched_commands[0][1]
1040 err('Sub Command %s not found!' % cmd)
1041 usage()
1043 def deprecated(old,new):
1044 print >>sys.stderr, (
1045 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1047 def usage(cmd=None):
1048 if cmd == 'create':
1049 mycmd = xm_lookup_cmd(cmd)
1050 mycmd( ['--help'] )
1051 sys.exit(1)
1052 if help.has_key(cmd):
1053 print " " + help[cmd]
1054 else:
1055 print shorthelp
1056 sys.exit(1)
1058 def main(argv=sys.argv):
1059 if len(argv) < 2:
1060 usage()
1062 if re.compile('-*help').match(argv[1]):
1063 if len(argv) > 2:
1064 usage(argv[2])
1065 else:
1066 usage()
1067 sys.exit(0)
1069 cmd = xm_lookup_cmd(argv[1])
1071 # strip off prog name and subcmd
1072 args = argv[2:]
1073 if cmd:
1074 try:
1075 rc = cmd(args)
1076 if rc:
1077 usage()
1078 except socket.error, ex:
1079 if os.geteuid() != 0:
1080 err("Most commands need root access. Please try again as root.")
1081 else:
1082 err("Error connecting to xend: %s. Is xend running?" % ex[1])
1083 sys.exit(1)
1084 except KeyboardInterrupt:
1085 print "Interrupted."
1086 sys.exit(1)
1087 except IOError, ex:
1088 if os.geteuid() != 0:
1089 err("Most commands need root access. Please try again as root.")
1090 else:
1091 err("Error connecting to xend: %s." % ex[1])
1092 sys.exit(1)
1093 except SystemExit:
1094 sys.exit(1)
1095 except xmlrpclib.Fault, ex:
1096 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1097 print >>sys.stderr, (
1098 "Error: the domain '%s' does not exist." % ex.faultString)
1099 else:
1100 print >>sys.stderr, "Error: %s" % ex.faultString
1101 sys.exit(1)
1102 except:
1103 print "Unexpected error:", sys.exc_info()[0]
1104 print
1105 print "Please report to xen-devel@lists.xensource.com"
1106 raise
1108 else:
1109 usage()
1111 if __name__ == "__main__":
1112 main()