ia64/xen-unstable

view tools/python/xen/xm/main.py @ 9426:c1bb4eb56529

Added exception handler for ProtocolError.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Mar 23 11:58:19 2006 +0100 (2006-03-23)
parents ffee7e07ad4b
children da24df1ea484
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 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
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
294 def handle_xend_error(cmd, args, ex):
295 non_option = filter(lambda x: x[0] != '-', args)
296 dom = len(non_option) > 0 and non_option[0] or None
298 error = str(ex)
299 if error == "Not found" and dom != None:
300 err("Domain '%s' not found when running 'xm %s'" % (dom, cmd))
301 else:
302 err(error)
304 sys.exit(1)
307 #########################################################################
308 #
309 # Main xm functions
310 #
311 #########################################################################
313 def xm_save(args):
314 arg_check(args, "save", 2)
316 dom = args[0] # TODO: should check if this exists
317 savefile = os.path.abspath(args[1])
319 if not os.access(os.path.dirname(savefile), os.W_OK):
320 err("xm save: Unable to create file %s" % savefile)
321 sys.exit(1)
323 server.xend.domain.save(dom, savefile)
325 def xm_restore(args):
326 arg_check(args, "restore", 1)
328 savefile = os.path.abspath(args[0])
330 if not os.access(savefile, os.R_OK):
331 err("xm restore: Unable to read file %s" % savefile)
332 sys.exit(1)
334 server.xend.domain.restore(savefile)
337 def getDomains(domain_names):
338 if domain_names:
339 return map(server.xend.domain, domain_names)
340 else:
341 return server.xend.domains(1)
344 def xm_list(args):
345 use_long = 0
346 show_vcpus = 0
347 try:
348 (options, params) = getopt.gnu_getopt(args, 'lv', ['long','vcpus'])
349 except getopt.GetoptError, opterr:
350 err(opterr)
351 sys.exit(1)
353 for (k, v) in options:
354 if k in ['-l', '--long']:
355 use_long = 1
356 if k in ['-v', '--vcpus']:
357 show_vcpus = 1
359 if show_vcpus:
360 print >>sys.stderr, (
361 "xm list -v is deprecated. Please use xm vcpu-list.")
362 xm_vcpu_list(params)
363 return
365 doms = getDomains(params)
367 if use_long:
368 map(PrettyPrint.prettyprint, doms)
369 else:
370 xm_brief_list(doms)
373 def parse_doms_info(info):
374 def get_info(n, t, d):
375 return t(sxp.child_value(info, n, d))
377 return {
378 'dom' : get_info('domid', int, -1),
379 'name' : get_info('name', str, '??'),
380 'mem' : get_info('memory', int, 0),
381 'vcpus' : get_info('online_vcpus', int, 0),
382 'state' : get_info('state', str, '??'),
383 'cpu_time' : get_info('cpu_time', float, 0),
384 'ssidref' : get_info('ssidref', int, 0),
385 }
388 def parse_sedf_info(info):
389 def get_info(n, t, d):
390 return t(sxp.child_value(info, n, d))
392 return {
393 'dom' : get_info('domain', int, -1),
394 'period' : get_info('period', int, -1),
395 'slice' : get_info('slice', int, -1),
396 'latency' : get_info('latency', int, -1),
397 'extratime': get_info('extratime', int, -1),
398 'weight' : get_info('weight', int, -1),
399 }
402 def xm_brief_list(doms):
403 print 'Name ID Mem(MiB) VCPUs State Time(s)'
404 for dom in doms:
405 d = parse_doms_info(dom)
406 if (d['ssidref'] != 0):
407 d['ssidstr'] = (" s:%04x/p:%04x" %
408 ((d['ssidref'] >> 16) & 0xffff,
409 d['ssidref'] & 0xffff))
410 else:
411 d['ssidstr'] = ""
412 print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f%(ssidstr)s" % d)
415 def xm_vcpu_list(args):
417 if args:
418 dominfo = map(server.xend.domain.getVCPUInfo, args)
419 else:
420 doms = server.xend.domains(False)
421 dominfo = map(server.xend.domain.getVCPUInfo, doms)
423 print 'Name ID VCPU CPU State Time(s) CPU Affinity'
425 for dom in dominfo:
426 def get_info(n):
427 return sxp.child_value(dom, n)
429 #
430 # convert a list of integers into a list of pairs indicating
431 # continuous sequences in the list:
432 #
433 # [0,1,2,3] -> [(0,3)]
434 # [1,2,4,5] -> [(1,2),(4,5)]
435 # [0] -> [(0,0)]
436 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
437 #
438 def list_to_rangepairs(cmap):
439 cmap.sort()
440 pairs = []
441 x = y = 0
442 for i in range(0,len(cmap)):
443 try:
444 if ((cmap[y+1] - cmap[i]) > 1):
445 pairs.append((cmap[x],cmap[y]))
446 x = y = i+1
447 else:
448 y = y + 1
449 # if we go off the end, then just add x to y
450 except IndexError:
451 pairs.append((cmap[x],cmap[y]))
453 return pairs
455 #
456 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
457 #
458 def format_pairs(pairs):
459 if not pairs:
460 return "no cpus"
461 out = ""
462 for f,s in pairs:
463 if (f==s):
464 out += '%d'%f
465 else:
466 out += '%d-%d'%(f,s)
467 out += ','
468 # trim trailing ','
469 return out[:-1]
471 def format_cpumap(cpumap):
472 cpumap = map(lambda x: int(x), cpumap)
473 cpumap.sort()
475 for x in server.xend.node.info()[1:]:
476 if len(x) > 1 and x[0] == 'nr_cpus':
477 nr_cpus = int(x[1])
478 # normalize cpumap by modulus nr_cpus, and drop duplicates
479 cpumap = dict.fromkeys(
480 map(lambda x: x % nr_cpus, cpumap)).keys()
481 if len(cpumap) == nr_cpus:
482 return "any cpu"
483 break
485 return format_pairs(list_to_rangepairs(cpumap))
487 name = get_info('name')
488 domid = int(get_info('domid'))
490 for vcpu in sxp.children(dom, 'vcpu'):
491 def vinfo(n, t):
492 return t(sxp.child_value(vcpu, n))
494 number = vinfo('number', int)
495 cpu = vinfo('cpu', int)
496 cpumap = format_cpumap(vinfo('cpumap', list))
497 online = vinfo('online', int)
498 cpu_time = vinfo('cpu_time', float)
499 running = vinfo('running', int)
500 blocked = vinfo('blocked', int)
502 if online:
503 c = str(cpu)
504 if running:
505 s = 'r'
506 else:
507 s = '-'
508 if blocked:
509 s += 'b'
510 else:
511 s += '-'
512 s += '-'
513 else:
514 c = "-"
515 s = "--p"
517 print (
518 "%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
519 locals())
522 def xm_reboot(args):
523 arg_check(args, "reboot", 1, 4)
524 from xen.xm import shutdown
525 shutdown.main(["shutdown", "-R"] + args)
527 def xm_pause(args):
528 arg_check(args, "pause", 1)
529 dom = args[0]
531 server.xend.domain.pause(dom)
533 def xm_unpause(args):
534 arg_check(args, "unpause", 1)
535 dom = args[0]
537 server.xend.domain.unpause(dom)
539 def xm_rename(args):
540 arg_check(args, "rename", 2)
542 server.xend.domain.setName(args[0], args[1])
544 def xm_subcommand(command, args):
545 cmd = __import__(command, globals(), locals(), 'xen.xm')
546 cmd.main([command] + args)
549 #############################################################
551 def cpu_make_map(cpulist):
552 cpus = []
553 for c in cpulist.split(','):
554 if c.find('-') != -1:
555 (x,y) = c.split('-')
556 for i in range(int(x),int(y)+1):
557 cpus.append(int(i))
558 else:
559 cpus.append(int(c))
560 cpus.sort()
561 return cpus
563 def xm_vcpu_pin(args):
564 arg_check(args, "vcpu-pin", 3)
566 dom = args[0]
567 vcpu = int(args[1])
568 cpumap = cpu_make_map(args[2])
570 server.xend.domain.pincpu(dom, vcpu, cpumap)
572 def xm_mem_max(args):
573 arg_check(args, "mem-max", 2)
575 dom = args[0]
576 mem = int_unit(args[1], 'm')
578 server.xend.domain.maxmem_set(dom, mem)
580 def xm_mem_set(args):
581 arg_check(args, "mem-set", 2)
583 dom = args[0]
584 mem_target = int_unit(args[1], 'm')
586 server.xend.domain.setMemoryTarget(dom, mem_target)
588 def xm_vcpu_set(args):
589 arg_check(args, "vcpu-set", 2)
591 server.xend.domain.setVCpuCount(args[0], int(args[1]))
594 def xm_destroy(args):
595 arg_check(args, "destroy", 1)
596 server.xend.domain.destroy(args[0])
599 def xm_domid(args):
600 arg_check(args, "domid", 1)
602 name = args[0]
604 dom = server.xend.domain(name)
605 print sxp.child_value(dom, 'domid')
607 def xm_domname(args):
608 arg_check(args, "domname", 1)
610 name = args[0]
612 dom = server.xend.domain(name)
613 print sxp.child_value(dom, 'name')
615 def xm_sched_bvt(args):
616 arg_check(args, "sched-bvt", 6)
617 dom = args[0]
618 v = map(long, args[1:6])
619 server.xend.domain.cpu_bvt_set(dom, *v)
621 def xm_sched_bvt_ctxallow(args):
622 arg_check(args, "sched-bvt-ctxallow", 1)
624 slice = int(args[0])
625 server.xend.node.cpu_bvt_slice_set(slice)
627 def xm_sched_sedf(args):
628 def ns_to_ms(val):
629 return float(val) * 0.000001
631 def ms_to_ns(val):
632 return (float(val) / 0.000001)
634 def print_sedf(info):
635 info['period'] = ns_to_ms(info['period'])
636 info['slice'] = ns_to_ms(info['slice'])
637 info['latency'] = ns_to_ms(info['latency'])
638 print( ("%(name)-32s %(dom)3d %(period)9.1f %(slice)9.1f" +
639 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
641 def domid_match(domid, info):
642 return domid is None or domid == info['name'] or domid == str(info['dom'])
644 # we want to just display current info if no parameters are passed
645 if len(args) == 0:
646 domid = None
647 else:
648 # we expect at least a domain id (name or number)
649 # and at most a domid up to 5 options with values
650 arg_check(args, "sched-sedf", 1, 11)
651 domid = args[0]
652 # drop domid from args since get_opt doesn't recognize it
653 args = args[1:]
655 opts = {}
656 try:
657 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
658 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
659 except getopt.GetoptError, opterr:
660 err(opterr)
661 sys.exit(1)
663 # convert to nanoseconds if needed
664 for (k, v) in options:
665 if k in ['-p', '--period']:
666 opts['period'] = ms_to_ns(v)
667 elif k in ['-s', '--slice']:
668 opts['slice'] = ms_to_ns(v)
669 elif k in ['-l', '--latency']:
670 opts['latency'] = ms_to_ns(v)
671 elif k in ['-e', '--extratime']:
672 opts['extratime'] = v
673 elif k in ['-w', '--weight']:
674 opts['weight'] = v
676 # print header if we aren't setting any parameters
677 if len(opts.keys()) == 0:
678 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s'%('Name','ID','Period(ms)',
679 'Slice(ms)', 'Lat(ms)',
680 'Extra','Weight')
682 doms = filter(lambda x : domid_match(domid, x),
683 [parse_doms_info(dom) for dom in getDomains("")])
684 for d in doms:
685 # fetch current values so as not to clobber them
686 sedf_info = \
687 parse_sedf_info(server.xend.domain.cpu_sedf_get(d['dom']))
688 sedf_info['name'] = d['name']
690 # update values in case of call to set
691 if len(opts.keys()) > 0:
692 for k in opts.keys():
693 sedf_info[k]=opts[k]
695 # send the update, converting user input
696 v = map(int, [sedf_info['period'], sedf_info['slice'],
697 sedf_info['latency'],sedf_info['extratime'],
698 sedf_info['weight']])
699 rv = server.xend.domain.cpu_sedf_set(d['dom'], *v)
700 if int(rv) != 0:
701 err("Failed to set sedf parameters (rv=%d)."%(rv))
703 # not setting values, display info
704 else:
705 print_sedf(sedf_info)
708 def xm_info(args):
709 arg_check(args, "info", 0)
711 info = server.xend.node.info()
713 for x in info[1:]:
714 if len(x) < 2:
715 print "%-23s: (none)" % x[0]
716 else:
717 print "%-23s:" % x[0], x[1]
719 def xm_console(args):
720 arg_check(args, "console", 1)
722 dom = args[0]
723 info = server.xend.domain(dom)
724 domid = int(sxp.child_value(info, 'domid', '-1'))
725 console.execConsole(domid)
728 def xm_top(args):
729 arg_check(args, "top", 0)
731 os.execvp('xentop', ['xentop'])
733 def xm_dmesg(args):
734 arg_check(args, "dmesg", 0)
736 gopts = Opts(use="""[-c|--clear]
738 Read Xen's message buffer (boot output, warning and error messages) or clear
739 its contents if the [-c|--clear] flag is specified.
740 """)
742 gopts.opt('clear', short='c',
743 fn=set_true, default=0,
744 use="Clear the contents of the Xen message buffer.")
745 # Work around for gopts
746 myargs = args
747 myargs.insert(0, 'dmesg')
748 gopts.parse(myargs)
749 if not (1 <= len(myargs) <= 2):
750 err('Invalid arguments: ' + str(myargs))
752 if not gopts.vals.clear:
753 print server.xend.node.dmesg.info()
754 else:
755 server.xend.node.dmesg.clear()
757 def xm_log(args):
758 arg_check(args, "log", 0)
760 print server.xend.node.log()
762 def parse_dev_info(info):
763 def get_info(n, t, d):
764 i = 0
765 while i < len(info):
766 if (info[i][0] == n):
767 return t(info[i][1])
768 i = i + 1
769 return t(d)
770 return {
771 #common
772 'backend-id' : get_info('backend-id', int, -1),
773 'handle' : get_info('handle', int, 0),
774 'state' : get_info('state', int, -1),
775 'be-path' : get_info('backend', str, '??'),
776 'event-ch' : get_info('event-channel',int, -1),
777 #network specific
778 'virtual-device' : get_info('virtual-device', str, '??'),
779 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
780 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
781 'mac' : get_info('mac', str, '??'),
782 #block-device specific
783 'ring-ref' : get_info('ring-ref', int, -1),
784 }
786 def has_long_option(args):
787 use_long = 0
788 try:
789 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
790 except getopt.GetoptError, opterr:
791 err(opterr)
792 sys.exit(1)
794 for (k, v) in options:
795 if k in ['-l', '--long']:
796 use_long = 1
797 return (use_long, params)
799 def xm_network_list(args):
800 arg_check(args, "network-list", 1, 2)
802 (use_long, params) = has_long_option(args)
804 if len(params) == 0:
805 print 'No domain parameter given'
806 sys.exit(1)
807 dom = params[0]
808 if use_long:
809 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
810 map(PrettyPrint.prettyprint, devs)
811 else:
812 hdr = 0
813 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
814 if hdr == 0:
815 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
816 hdr = 1
817 ni = parse_dev_info(x[1])
818 ni['idx'] = int(x[0])
819 print ("%(idx)-3d "
820 "%(backend-id)-3d"
821 "%(mac)-17s "
822 "%(handle)-3d "
823 "%(state)-3d "
824 "%(event-ch)-3d "
825 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
826 "%(be-path)-30s "
827 % ni)
829 def xm_block_list(args):
830 arg_check(args, "block-list", 1, 2)
832 (use_long, params) = has_long_option(args)
834 if len(params) == 0:
835 print 'No domain parameter given'
836 sys.exit(1)
837 dom = params[0]
838 if use_long:
839 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
840 map(PrettyPrint.prettyprint, devs)
841 else:
842 hdr = 0
843 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
844 if hdr == 0:
845 print 'Vdev BE handle state evt-ch ring-ref BE-path'
846 hdr = 1
847 ni = parse_dev_info(x[1])
848 ni['idx'] = int(x[0])
849 print ("%(idx)-3d "
850 "%(backend-id)-3d "
851 "%(handle)-3d "
852 "%(state)-3d "
853 "%(event-ch)-3d "
854 "%(ring-ref)-5d "
855 "%(be-path)-30s "
856 % ni)
858 def xm_vtpm_list(args):
859 arg_check(args, "vtpm-list", 1, 2)
861 (use_long, params) = has_long_option(args)
863 if len(params) == 0:
864 print 'No domain parameter given'
865 sys.exit(1)
866 dom = params[0]
867 if use_long:
868 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
869 map(PrettyPrint.prettyprint, devs)
870 else:
871 hdr = 0
872 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
873 if hdr == 0:
874 print 'Idx BE handle state evt-ch ring-ref BE-path'
875 hdr = 1
876 ni = parse_dev_info(x[1])
877 ni['idx'] = int(x[0])
878 print ("%(idx)-3d "
879 "%(backend-id)-3d "
880 "%(handle)-3d "
881 "%(state)-3d "
882 "%(event-ch)-3d "
883 "%(ring-ref)-5d "
884 "%(be-path)-30s "
885 % ni)
887 def xm_block_attach(args):
888 arg_check(args, 'block-attach', 4, 5)
890 dom = args[0]
891 vbd = ['vbd',
892 ['uname', args[1]],
893 ['dev', args[2]],
894 ['mode', args[3]]]
895 if len(args) == 5:
896 vbd.append(['backend', args[4]])
898 server.xend.domain.device_create(dom, vbd)
901 def xm_network_attach(args):
902 arg_check(args, 'network-attach', 1, 10000)
904 dom = args[0]
905 vif = ['vif']
907 for a in args[1:]:
908 vif.append(a.split("="))
910 server.xend.domain.device_create(dom, vif)
913 def detach(args, command, deviceClass):
914 arg_check(args, command, 2)
916 dom = args[0]
917 dev = args[1]
919 server.xend.domain.destroyDevice(dom, deviceClass, dev)
922 def xm_block_detach(args):
923 detach(args, 'block-detach', 'vbd')
926 def xm_network_detach(args):
927 detach(args, 'network-detach', 'vif')
930 def xm_vnet_list(args):
931 try:
932 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
933 except getopt.GetoptError, opterr:
934 err(opterr)
935 sys.exit(1)
937 use_long = 0
938 for (k, v) in options:
939 if k in ['-l', '--long']:
940 use_long = 1
942 if params:
943 use_long = 1
944 vnets = params
945 else:
946 vnets = server.xend_vnets()
948 for vnet in vnets:
949 try:
950 if use_long:
951 info = server.xend_vnet(vnet)
952 PrettyPrint.prettyprint(info)
953 else:
954 print vnet
955 except Exception, ex:
956 print vnet, ex
958 def xm_vnet_create(args):
959 arg_check(args, "vnet-create", 1)
960 conf = args[0]
961 if not os.access(conf, os.R_OK):
962 print "File not found: %s" % conf
963 sys.exit(1)
965 server.xend_vnet_create(conf)
967 def xm_vnet_delete(args):
968 arg_check(args, "vnet-delete", 1)
969 vnet = args[0]
970 server.xend_vnet_delete(vnet)
972 commands = {
973 # console commands
974 "console": xm_console,
975 # xenstat commands
976 "top": xm_top,
977 # domain commands
978 "destroy": xm_destroy,
979 "domid": xm_domid,
980 "domname": xm_domname,
981 "rename": xm_rename,
982 "restore": xm_restore,
983 "save": xm_save,
984 "reboot": xm_reboot,
985 "list": xm_list,
986 # memory commands
987 "mem-max": xm_mem_max,
988 "mem-set": xm_mem_set,
989 # cpu commands
990 "vcpu-pin": xm_vcpu_pin,
991 "vcpu-list": xm_vcpu_list,
992 "vcpu-set": xm_vcpu_set,
993 # special
994 "pause": xm_pause,
995 "unpause": xm_unpause,
996 # host commands
997 "dmesg": xm_dmesg,
998 "info": xm_info,
999 "log": xm_log,
1000 # scheduler
1001 "sched-bvt": xm_sched_bvt,
1002 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
1003 "sched-sedf": xm_sched_sedf,
1004 # block
1005 "block-attach": xm_block_attach,
1006 "block-detach": xm_block_detach,
1007 "block-list": xm_block_list,
1008 # network
1009 "network-attach": xm_network_attach,
1010 "network-detach": xm_network_detach,
1011 "network-list": xm_network_list,
1012 # vnet
1013 "vnet-list": xm_vnet_list,
1014 "vnet-create": xm_vnet_create,
1015 "vnet-delete": xm_vnet_delete,
1016 # vtpm
1017 "vtpm-list": xm_vtpm_list,
1020 ## The commands supported by a separate argument parser in xend.xm.
1021 subcommands = [
1022 'create',
1023 'migrate',
1024 'sysrq',
1025 'shutdown'
1028 for c in subcommands:
1029 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
1031 aliases = {
1032 "balloon": "mem-set",
1033 "set-vcpus": "vcpu-set",
1034 "vif-list": "network-list",
1035 "vbd-create": "block-attach",
1036 "vbd-destroy": "block-detach",
1037 "vbd-list": "block-list",
1041 def xm_lookup_cmd(cmd):
1042 if commands.has_key(cmd):
1043 return commands[cmd]
1044 elif aliases.has_key(cmd):
1045 deprecated(cmd,aliases[cmd])
1046 return commands[aliases[cmd]]
1047 else:
1048 if len( cmd ) > 1:
1049 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
1050 if len( matched_commands ) == 1:
1051 return matched_commands[0][1]
1052 err('Sub Command %s not found!' % cmd)
1053 usage()
1055 def deprecated(old,new):
1056 print >>sys.stderr, (
1057 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1059 def usage(cmd=None):
1060 if cmd == 'create':
1061 mycmd = xm_lookup_cmd(cmd)
1062 mycmd( ['--help'] )
1063 sys.exit(1)
1064 if help.has_key(cmd):
1065 print " " + help[cmd]
1066 else:
1067 print shorthelp
1068 sys.exit(1)
1070 def main(argv=sys.argv):
1071 if len(argv) < 2:
1072 usage()
1074 if re.compile('-*help').match(argv[1]):
1075 if len(argv) > 2:
1076 usage(argv[2])
1077 else:
1078 usage()
1079 sys.exit(0)
1081 cmd = xm_lookup_cmd(argv[1])
1083 # strip off prog name and subcmd
1084 args = argv[2:]
1085 if cmd:
1086 try:
1087 rc = cmd(args)
1088 if rc:
1089 usage()
1090 except socket.error, ex:
1091 if os.geteuid() != 0:
1092 err("Most commands need root access. Please try again as root.")
1093 else:
1094 err("Error connecting to xend: %s. Is xend running?" % ex[1])
1095 sys.exit(1)
1096 except KeyboardInterrupt:
1097 print "Interrupted."
1098 sys.exit(1)
1099 except IOError, ex:
1100 if os.geteuid() != 0:
1101 err("Most commands need root access. Please try again as root.")
1102 else:
1103 err("Error connecting to xend: %s." % ex[1])
1104 sys.exit(1)
1105 except xmlrpclib.ProtocolError, ex:
1106 if os.geteuid() != 0:
1107 err("Most commands need root access. Please try again as root.")
1108 else:
1109 err("Error connecting to xend: %s." % ex.errmsg)
1110 sys.exit(1)
1111 except SystemExit:
1112 sys.exit(1)
1113 except xmlrpclib.Fault, ex:
1114 print "Error: %s" % ex.faultString
1115 sys.exit(1)
1116 except:
1117 print "Unexpected error:", sys.exc_info()[0]
1118 print
1119 print "Please report to xen-devel@lists.xensource.com"
1120 raise
1122 else:
1123 usage()
1125 if __name__ == "__main__":
1126 main()