ia64/xen-unstable

view tools/python/xen/xm/main.py @ 6102:3229cda2d6f1

The attached patch fixes the xm list command, which very
recently stopped working if security was enabled.

xm list fails if security is enabled because of a single
additional "%" character in a print.

Signed-off-by: Reiner Sailer <sailer@watson.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Aug 11 08:55:47 2005 +0000 (2005-08-11)
parents 50e57636bdd8
children 0761551e993a
line source
1 # (C) Copyright IBM Corp. 2005
2 # Copyright (C) 2004 Mike Wray
3 #
4 # Authors:
5 # Sean Dague <sean at dague dot net>
6 # Mike Wray <mike dot wray at hp dot com>
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of version 2.1 of the GNU Lesser General Public
10 # License as published by the Free Software Foundation.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 """Grand unified management application for Xen.
22 """
23 import os
24 import os.path
25 import sys
26 import commands
27 import re
28 from getopt import getopt
29 import socket
30 import warnings
31 warnings.filterwarnings('ignore', category=FutureWarning)
32 from xen.xend import PrettyPrint
33 from xen.xend import sxp
34 from xen.xm.opts import *
35 shorthelp = """Usage: xm <subcommand> [args]
36 Control, list, and manipulate Xen guest instances
38 xm common subcommands:
39 console <DomId> attach to console of DomId
40 create <CfgFile> create a domain based on Config File
41 destroy <DomId> terminate a domain immediately
42 help display this message
43 list [DomId, ...] list information about domains
44 mem-max <DomId> <Mem> set the maximum memory reservation for a domain
45 mem-set <DomId> <Mem> adjust the current memory usage for a domain
46 migrate <DomId> <Host> migrate a domain to another machine
47 pause <DomId> pause execution of a domain
48 reboot <DomId> reboot a domain
49 restore <File> create a domain from a saved state file
50 save <DomId> <File> save domain state (and config) to file
51 shutdown <DomId> shutdown a domain
52 unpause <DomId> unpause a paused domain
54 For a complete list of subcommands run 'xm help --long'
55 For more help on xm see the xm(1) man page
56 For more help on xm create, see the xmdomain.cfg(5) man page"""
58 longhelp = """Usage: xm <subcommand> [args]
59 Control, list, and manipulate Xen guest instances
61 xm full list of subcommands:
63 Domain Commands:
64 console <DomId> attach to console of DomId
65 cpus-list <DomId> <VCpu> get the list of cpus for a VCPU
66 cpus-set <DomId> <VCpu> <CPUS> set which cpus a VCPU can use.
67 create <ConfigFile> create a domain
68 destroy <DomId> terminate a domain immediately
69 domid <DomName> convert a domain name to a domain id
70 domname <DomId> convert a domain id to a domain name
71 list list information about domains
72 mem-max <DomId> <Mem> set domain maximum memory limit
73 mem-set <DomId> <Mem> set the domain's memory dynamically
74 migrate <DomId> <Host> migrate a domain to another machine
75 pause <DomId> pause execution of a domain
76 reboot [-w|-a] <DomId> reboot a domain
77 restore <File> create a domain from a saved state file
78 save <DomId> <File> save domain state (and config) to file
79 shutdown [-w|-a] <DomId> shutdown a domain
80 sysrq <DomId> <letter> send a sysrq to a domain
81 unpause <DomId> unpause a paused domain
82 vcpu-enable <DomId> <VCPU> disable VCPU in a domain
83 vcpu-disable <DomId> <VCPU> enable VCPU in a domain
84 vcpu-list <DomId> get the list of VCPUs for a domain
86 Xen Host Commands:
87 dmesg [--clear] read or clear Xen's message buffer
88 info get information about the xen host
89 log print the xend log
91 Scheduler Commands:
92 bvt <options> set BVT scheduler parameters
93 bvt_ctxallow <Allow> set the BVT scheduler context switch allowance
94 sedf <options> set simple EDF parameters
96 Virtual Device Commands:
97 block-create <DomId> <BackDev> <FrontDev> <Mode> [BackDomId]
98 Create a new virtual block device
99 block-destroy <DomId> <DevId> Destroy a domain's virtual block device
100 block-list <DomId> List virtual block devices for a domain
101 block-refresh <DomId> <DevId> Refresh a virtual block device for a domain
102 network-limit <DomId> <Vif> <Credit> <Period>
103 Limit the transmission rate of a virtual network interface
104 network-list <DomId> List virtual network interfaces for a domain
106 For a short list of subcommands run 'xm help'
107 For more help on xm see the xm(1) man page
108 For more help on xm create, see the xmdomain.cfg(5) man page"""
110 ####################################################################
111 #
112 # Utility functions
113 #
114 ####################################################################
116 def arg_check(args,num,name):
117 if len(args) < num:
118 err("'xm %s' requires %s argument(s)!\n" % (name, num))
119 usage(name)
121 def unit(c):
122 if not c.isalpha():
123 return 0
124 base = 1
125 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
126 elif c == 'M' or c == 'm': base = 1024 * 1024
127 elif c == 'K' or c == 'k': base = 1024
128 else:
129 print 'ignoring unknown unit'
130 return base
132 def int_unit(str, dest):
133 base = unit(str[-1])
134 if not base:
135 return int(str)
137 value = int(str[:-1])
138 dst_base = unit(dest)
139 if dst_base == 0:
140 dst_base = 1
141 if dst_base > base:
142 return value / (dst_base / base)
143 else:
144 return value * (base / dst_base)
146 def err(msg):
147 print >>sys.stderr, "Error:", msg
149 def handle_xend_error(cmd, dom, ex):
150 error = str(ex)
151 if error == "Not found" and dom != None:
152 err("Domain '%s' not found when running 'xm %s'" % (dom, cmd))
153 sys.exit(1)
154 else:
155 raise ex
158 #########################################################################
159 #
160 # Main xm functions
161 #
162 #########################################################################
164 def xm_create(args):
165 from xen.xm import create
166 # ugly hack because the opt parser apparently wants
167 # the subcommand name just to throw it away!
168 args.insert(0,"bogus")
169 create.main(args)
171 def xm_save(args):
172 arg_check(args,2,"save")
174 dom = args[0] # TODO: should check if this exists
175 savefile = os.path.abspath(args[1])
177 from xen.xend.XendClient import server
178 server.xend_domain_save(dom, savefile)
180 def xm_restore(args):
181 arg_check(args,1,"restore")
183 savefile = os.path.abspath(args[0])
185 from xen.xend.XendClient import server
186 info = server.xend_domain_restore(savefile)
187 PrettyPrint.prettyprint(info)
188 id = sxp.child_value(info, 'id')
189 if id is not None:
190 server.xend_domain_unpause(id)
192 def xm_migrate(args):
193 # TODO: arg_check
194 from xen.xm import migrate
195 # ugly hack because the opt parser apparently wants
196 # the subcommand name just to throw it away!
197 args.insert(0,"bogus")
198 migrate.main(args)
200 def xm_list(args):
201 use_long = 0
202 show_vcpus = 0
203 (options, params) = getopt(args, 'lv', ['long','vcpus'])
205 n = len(params)
206 for (k, v) in options:
207 if k in ['-l', '--long']:
208 use_long = 1
209 if k in ['-v', '--vcpus']:
210 show_vcpus = 1
212 domsinfo = []
213 from xen.xend.XendClient import server
214 if n == 0:
215 doms = server.xend_domains()
216 doms.sort()
217 else:
218 doms = params
219 for dom in doms:
220 info = server.xend_domain(dom)
221 domsinfo.append(parse_doms_info(info))
223 if use_long:
224 # this actually seems like a bad idea, as it just dumps sexp out
225 PrettyPrint.prettyprint(info)
226 elif show_vcpus:
227 xm_show_vcpus(domsinfo)
228 else:
229 xm_brief_list(domsinfo)
231 def parse_doms_info(info):
232 dominfo = {}
233 dominfo['dom'] = int(sxp.child_value(info, 'id', '-1'))
234 dominfo['name'] = sxp.child_value(info, 'name', '??')
235 dominfo['mem'] = int(sxp.child_value(info, 'memory', '0'))
236 dominfo['cpu'] = str(sxp.child_value(info, 'cpu', '0'))
237 dominfo['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
238 # if there is more than 1 cpu, the value doesn't mean much
239 if dominfo['vcpus'] > 1:
240 dominfo['cpu'] = '-'
241 dominfo['state'] = sxp.child_value(info, 'state', '??')
242 dominfo['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
243 # security identifiers
244 if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
245 dominfo['ssidref1'] = int(sxp.child_value(info, 'ssidref', '0')) & 0xffff
246 dominfo['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 16) & 0xffff
247 # get out the vcpu information
248 dominfo['vcpulist'] = []
249 vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
250 cpumap = sxp.child_value(info, 'cpumap', [])
251 mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
252 count = 0
253 for cpu in vcpu_to_cpu:
254 vcpuinfo = {}
255 vcpuinfo['name'] = sxp.child_value(info, 'name', '??')
256 vcpuinfo['dom'] = int(sxp.child_value(info, 'id', '-1'))
257 vcpuinfo['vcpu'] = int(count)
258 vcpuinfo['cpu'] = int(cpu)
259 vcpuinfo['cpumap'] = int(cpumap[count])&mask
260 count = count + 1
261 dominfo['vcpulist'].append(vcpuinfo)
262 return dominfo
264 def xm_brief_list(domsinfo):
265 print 'Name Id Mem(MB) CPU VCPU(s) State Time(s)'
266 for dominfo in domsinfo:
267 if dominfo.has_key("ssidref1"):
268 print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo)
269 else:
270 print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f" % dominfo)
272 def xm_show_vcpus(domsinfo):
273 print 'Name Id VCPU CPU CPUMAP'
274 for dominfo in domsinfo:
275 for vcpuinfo in dominfo['vcpulist']:
276 print ("%(name)-16s %(dom)3d %(vcpu)4d %(cpu)3d 0x%(cpumap)x" %
277 vcpuinfo)
279 def xm_vcpu_list(args):
280 args.insert(0,"-v")
281 xm_list(args)
283 def xm_destroy(args):
284 arg_check(args,1,"destroy")
286 from xen.xm import destroy
287 # ugly hack because the opt parser apparently wants
288 # the subcommand name just to throw it away!
289 args.insert(0,"bogus")
290 destroy.main(args)
292 # TODO: make reboot do the right thing, right now
293 # reboot and shutdown are exactly the same
294 def xm_reboot(args):
295 arg_check(args,1,"reboot")
296 # ugly hack because the opt parser apparently wants
297 # the subcommand name just to throw it away!
298 args.insert(0,"bogus")
299 from xen.xm import shutdown
300 shutdown.main(args)
302 def xm_shutdown(args):
303 arg_check(args,1,"shutdown")
305 # ugly hack because the opt parser apparently wants
306 # the subcommand name just to throw it away!
307 args.insert(0,"bogus")
308 from xen.xm import shutdown
309 shutdown.main(args)
311 def xm_sysrq(args):
312 from xen.xm import sysrq
313 # ugly hack because the opt parser apparently wants
314 # the subcommand name just to throw it away!
315 args.insert(0,"bogus")
316 sysrq.main(args)
318 def xm_pause(args):
319 arg_check(args, 1, "pause")
320 dom = args[0]
322 from xen.xend.XendClient import server
323 server.xend_domain_pause(dom)
325 def xm_unpause(args):
326 arg_check(args, 1, "unpause")
327 dom = args[0]
329 from xen.xend.XendClient import server
330 server.xend_domain_unpause(dom)
332 #############################################################
334 def cpu_make_map(cpulist):
335 cpus = []
336 cpumap = 0
337 for c in cpulist.split(','):
338 if c.find('-') != -1:
339 (x,y) = c.split('-')
340 for i in range(int(x),int(y)+1):
341 cpus.append(int(i))
342 else:
343 cpus.append(int(c))
344 cpus.sort()
345 for c in cpus:
346 cpumap = cpumap | 1<<c
348 return cpumap
350 def xm_cpus_set(args):
351 arg_check(args, 3, "cpus-set")
353 dom = args[0]
354 vcpu = int(args[1])
355 cpumap = cpu_make_map(args[2])
357 from xen.xend.XendClient import server
358 server.xend_domain_pincpu(dom, vcpu, cpumap)
360 def xm_mem_max(args):
361 arg_check(args, 2, "mem-max")
363 dom = args[0]
364 mem = int_unit(args[1], 'm')
366 from xen.xend.XendClient import server
367 server.xend_domain_maxmem_set(dom, mem)
369 def xm_mem_set(args):
370 arg_check(args, 2, "mem-set")
372 dom = args[0]
373 mem_target = int_unit(args[1], 'm')
375 from xen.xend.XendClient import server
376 server.xend_domain_mem_target_set(dom, mem_target)
378 # TODO: why does this lookup by name? and what if that fails!?
379 def xm_vcpu_enable(args):
380 arg_check(args, 2, "vcpu-enable")
382 name = args[0]
383 vcpu = int(args[1])
385 from xen.xend.XendClient import server
386 dom = server.xend_domain(name)
387 id = sxp.child_value(dom, 'id')
388 server.xend_domain_vcpu_hotplug(id, vcpu, 1)
390 def xm_vcpu_disable(args):
391 arg_check(args, 2, "vcpu-disable")
393 name = args[0]
394 vcpu = int(args[1])
396 from xen.xend.XendClient import server
397 dom = server.xend_domain(name)
398 id = sxp.child_value(dom, 'id')
399 server.xend_domain_vcpu_hotplug(id, vcpu, 0)
401 def xm_domid(args):
402 name = args[0]
404 from xen.xend.XendClient import server
405 dom = server.xend_domain(name)
406 print sxp.child_value(dom, 'id')
408 def xm_domname(args):
409 name = args[0]
411 from xen.xend.XendClient import server
412 dom = server.xend_domain(name)
413 print sxp.child_value(dom, 'name')
415 def xm_bvt(args):
416 arg_check(args, 6, "bvt")
417 dom = args[0]
418 v = map(long, args[1:6])
419 from xen.xend.XendClient import server
420 server.xend_domain_cpu_bvt_set(dom, *v)
422 def xm_bvt_ctxallow(args):
423 arg_check(args, 1, "bvt_ctxallow")
425 slice = int(args[0])
426 from xen.xend.XendClient import server
427 server.xend_node_cpu_bvt_slice_set(slice)
429 def xm_sedf(args):
430 arg_check(args, 6, "sedf")
432 dom = args[0]
433 v = map(int, args[1:5])
434 from xen.xend.XendClient import server
435 server.xend_domain_cpu_sedf_set(dom, *v)
437 def xm_info(args):
438 from xen.xend.XendClient import server
439 info = server.xend_node()
441 for x in info[1:]:
442 print "%-23s:" % x[0], x[1]
444 # TODO: remove as soon as console server shows up
445 def xm_console(args):
446 arg_check(args,1,"console")
448 dom = args[0]
449 from xen.xend.XendClient import server
450 info = server.xend_domain(dom)
451 domid = int(sxp.child_value(info, 'id', '-1'))
452 cmd = "/usr/libexec/xen/xenconsole %d" % domid
453 os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
454 console = sxp.child(info, "console")
456 def xm_dmesg(args):
458 gopts = Opts(use="""[-c|--clear]
460 Read Xen's message buffer (boot output, warning and error messages) or clear
461 its contents if the [-c|--clear] flag is specified.
462 """)
464 gopts.opt('clear', short='c',
465 fn=set_true, default=0,
466 use="Clear the contents of the Xen message buffer.")
467 # Work around for gopts
468 args.insert(0,"bogus")
469 gopts.parse(args)
470 if not (1 <= len(args) <= 2):
471 err('Invalid arguments: ' + str(args))
473 from xen.xend.XendClient import server
474 if not gopts.vals.clear:
475 print server.xend_node_get_dmesg()
476 else:
477 server.xend_node_clear_dmesg()
479 def xm_log(args):
480 from xen.xend.XendClient import server
481 print server.xend_node_log()
483 def xm_network_limit(args):
484 arg_check(args,4,"network-limit")
485 dom = args[0]
486 v = map(int, args[1:4])
487 from xen.xend.XendClient import server
488 server.xend_domain_vif_limit(dom, *v)
490 def xm_network_list(args):
491 arg_check(args,1,"network-list")
492 dom = args[0]
493 from xen.xend.XendClient import server
494 for x in server.xend_domain_devices(dom, 'vif'):
495 sxp.show(x)
496 print
498 def xm_block_list(args):
499 arg_check(args,1,"block-list")
500 dom = args[0]
501 from xen.xend.XendClient import server
502 for x in server.xend_domain_devices(dom, 'vbd'):
503 sxp.show(x)
504 print
506 def xm_block_create(args):
507 n = len(args)
508 if n < 4 or n > 5:
509 err("%s: Invalid argument(s)" % args[0])
510 usage("block-create")
512 dom = args[0]
513 vbd = ['vbd',
514 ['uname', args[1]],
515 ['dev', args[2]],
516 ['mode', args[3]]]
517 if n == 5:
518 vbd.append(['backend', args[4]])
520 from xen.xend.XendClient import server
521 server.xend_domain_device_create(dom, vbd)
523 def xm_block_refresh(args):
524 arg_check(args,2,"block-refresh")
526 dom = args[0]
527 dev = args[1]
529 from xen.xend.XendClient import server
530 server.xend_domain_device_refresh(dom, 'vbd', dev)
532 def xm_block_destroy(args):
533 arg_check(args,2,"block-destroy")
535 dom = args[0]
536 dev = args[1]
538 from xen.xend.XendClient import server
539 server.xend_domain_device_destroy(dom, 'vbd', dev)
541 commands = {
542 # console commands
543 "console": xm_console,
544 # domain commands
545 "domid": xm_domid,
546 "domname": xm_domname,
547 "create": xm_create,
548 "destroy": xm_destroy,
549 "restore": xm_restore,
550 "save": xm_save,
551 "shutdown": xm_shutdown,
552 "reboot": xm_reboot,
553 "list": xm_list,
554 # memory commands
555 "mem-max": xm_mem_max,
556 "mem-set": xm_mem_set,
557 # cpu commands
558 "cpus-set": xm_cpus_set,
559 # "cpus-list": xm_cpus_list,
560 "vcpu-enable": xm_vcpu_enable,
561 "vcpu-disable": xm_vcpu_disable,
562 "vcpu-list": xm_vcpu_list,
563 # migration
564 "migrate": xm_migrate,
565 # special
566 "sysrq": xm_sysrq,
567 "pause": xm_pause,
568 "unpause": xm_unpause,
569 # host commands
570 "dmesg": xm_dmesg,
571 "info": xm_info,
572 "log": xm_log,
573 # scheduler
574 "bvt": xm_bvt,
575 "bvt_ctxallow": xm_bvt_ctxallow,
576 "sedf": xm_sedf,
577 # block
578 "block-create": xm_block_create,
579 "block-destroy": xm_block_destroy,
580 "block-list": xm_block_list,
581 "block-refresh": xm_block_refresh,
582 # network
583 "network-limit": xm_network_limit,
584 "network-list": xm_network_list
585 }
587 aliases = {
588 "balloon": "mem-set",
589 "vif-list": "network-list",
590 "vif-limit": "network-limit",
591 "vbd-create": "block-create",
592 "vbd-destroy": "block-destroy",
593 "vbd-list": "block-list",
594 "vbd-refresh": "block-refresh",
595 }
597 help = {
598 "--long": longhelp
599 }
601 def xm_lookup_cmd(cmd):
602 if commands.has_key(cmd):
603 return commands[cmd]
604 elif aliases.has_key(cmd):
605 deprecated(cmd,aliases[cmd])
606 return commands[aliases[cmd]]
607 else:
608 err('Sub Command %s not found!' % cmd)
609 usage()
611 def deprecated(old,new):
612 err('Option %s is deprecated, and will be removed in future!!!' % old)
613 err('Option %s is the new replacement, see "xm help %s" for more info' % (new, new))
615 def usage(cmd=None):
616 if cmd == "full":
617 print fullhelp
618 elif help.has_key(cmd):
619 print help[cmd]
620 else:
621 print shorthelp
622 sys.exit(1)
624 def main(argv=sys.argv):
625 if len(argv) < 2:
626 usage()
628 if re.compile('-*help').match(argv[1]):
629 if len(argv) > 2 and help.has_key(argv[2]):
630 usage(argv[2])
631 else:
632 usage()
633 sys.exit(0)
635 cmd = xm_lookup_cmd(argv[1])
637 # strip off prog name and subcmd
638 args = argv[2:]
639 if cmd:
640 try:
641 from xen.xend.XendClient import XendError
642 rc = cmd(args)
643 if rc:
644 usage()
645 except socket.error, ex:
646 print >>sys.stderr, ex
647 err("Error connecting to xend, is xend running?")
648 sys.exit(1)
649 except IOError:
650 err("Most commands need root access. Please try again as root")
651 sys.exit(1)
652 except XendError, ex:
653 if len(args) > 0:
654 handle_xend_error(argv[1], args[1], ex)
655 else:
656 print "Unexpected error:", sys.exc_info()[0]
657 print
658 print "Please report to xen-devel@lists.xensource.com"
659 raise
660 except SystemExit:
661 sys.exit(1)
662 except:
663 print "Unexpected error:", sys.exc_info()[0]
664 print
665 print "Please report to xen-devel@lists.xensource.com"
666 raise
668 else:
669 usage()
671 if __name__ == "__main__":
672 main()