ia64/xen-unstable

view tools/python/xen/xm/main.py @ 6303:42f0160093ff

Fix broken 'xm sedf', fixed by Ross Mcilroy
Signed-off by: Stephan.Diestelhorst@{cl.cam.ac.uk, inf.tu-dresden.de}
author sd386@font.cl.cam.ac.uk
date Fri Aug 19 18:08:29 2005 +0000 (2005-08-19)
parents 47d49e8b8042
children eb9df2c3a478
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 try:
204 (options, params) = getopt(args, 'lv', ['long','vcpus'])
205 except GetoptError, opterr:
206 err(opterr)
207 sys.exit(1)
209 n = len(params)
210 for (k, v) in options:
211 if k in ['-l', '--long']:
212 use_long = 1
213 if k in ['-v', '--vcpus']:
214 show_vcpus = 1
216 domsinfo = []
217 from xen.xend.XendClient import server
218 if n == 0:
219 doms = server.xend_domains()
220 doms.sort()
221 else:
222 doms = params
223 for dom in doms:
224 info = server.xend_domain(dom)
225 domsinfo.append(parse_doms_info(info))
227 if use_long:
228 for dom in doms:
229 info = server.xend_domain(dom)
230 PrettyPrint.prettyprint(info)
231 elif show_vcpus:
232 xm_show_vcpus(domsinfo)
233 else:
234 xm_brief_list(domsinfo)
236 def parse_doms_info(info):
237 dominfo = {}
238 dominfo['dom'] = int(sxp.child_value(info, 'id', '-1'))
239 dominfo['name'] = sxp.child_value(info, 'name', '??')
240 dominfo['mem'] = int(sxp.child_value(info, 'memory', '0'))
241 dominfo['cpu'] = str(sxp.child_value(info, 'cpu', '0'))
242 dominfo['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
243 # if there is more than 1 cpu, the value doesn't mean much
244 if dominfo['vcpus'] > 1:
245 dominfo['cpu'] = '-'
246 dominfo['state'] = sxp.child_value(info, 'state', '??')
247 dominfo['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
248 # security identifiers
249 if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
250 dominfo['ssidref1'] = int(sxp.child_value(info, 'ssidref', '0')) & 0xffff
251 dominfo['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 16) & 0xffff
252 # get out the vcpu information
253 dominfo['vcpulist'] = []
254 vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
255 cpumap = sxp.child_value(info, 'cpumap', [])
256 mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
257 count = 0
258 for cpu in vcpu_to_cpu:
259 vcpuinfo = {}
260 vcpuinfo['name'] = sxp.child_value(info, 'name', '??')
261 vcpuinfo['dom'] = int(sxp.child_value(info, 'id', '-1'))
262 vcpuinfo['vcpu'] = int(count)
263 vcpuinfo['cpu'] = int(cpu)
264 vcpuinfo['cpumap'] = int(cpumap[count])&mask
265 count = count + 1
266 dominfo['vcpulist'].append(vcpuinfo)
267 return dominfo
269 def xm_brief_list(domsinfo):
270 print 'Name Id Mem(MB) CPU VCPU(s) State Time(s)'
271 for dominfo in domsinfo:
272 if dominfo.has_key("ssidref1"):
273 print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo)
274 else:
275 print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f" % dominfo)
277 def xm_show_vcpus(domsinfo):
278 print 'Name Id VCPU CPU CPUMAP'
279 for dominfo in domsinfo:
280 for vcpuinfo in dominfo['vcpulist']:
281 print ("%(name)-16s %(dom)3d %(vcpu)4d %(cpu)3d 0x%(cpumap)x" %
282 vcpuinfo)
284 def xm_vcpu_list(args):
285 args.insert(0,"-v")
286 xm_list(args)
288 def xm_destroy(args):
289 arg_check(args,1,"destroy")
291 from xen.xm import destroy
292 # ugly hack because the opt parser apparently wants
293 # the subcommand name just to throw it away!
294 args.insert(0,"bogus")
295 destroy.main(args)
297 def xm_reboot(args):
298 arg_check(args,1,"reboot")
299 # ugly hack because the opt parser apparently wants
300 # the subcommand name just to throw it away!
301 args.insert(0,"bogus")
302 args.insert(2,"-R")
303 from xen.xm import shutdown
304 shutdown.main(args)
306 def xm_shutdown(args):
307 arg_check(args,1,"shutdown")
309 # ugly hack because the opt parser apparently wants
310 # the subcommand name just to throw it away!
311 args.insert(0,"bogus")
312 from xen.xm import shutdown
313 shutdown.main(args)
315 def xm_sysrq(args):
316 from xen.xm import sysrq
317 # ugly hack because the opt parser apparently wants
318 # the subcommand name just to throw it away!
319 args.insert(0,"bogus")
320 sysrq.main(args)
322 def xm_pause(args):
323 arg_check(args, 1, "pause")
324 dom = args[0]
326 from xen.xend.XendClient import server
327 server.xend_domain_pause(dom)
329 def xm_unpause(args):
330 arg_check(args, 1, "unpause")
331 dom = args[0]
333 from xen.xend.XendClient import server
334 server.xend_domain_unpause(dom)
336 #############################################################
338 def cpu_make_map(cpulist):
339 cpus = []
340 cpumap = 0
341 for c in cpulist.split(','):
342 if c.find('-') != -1:
343 (x,y) = c.split('-')
344 for i in range(int(x),int(y)+1):
345 cpus.append(int(i))
346 else:
347 cpus.append(int(c))
348 cpus.sort()
349 for c in cpus:
350 cpumap = cpumap | 1<<c
352 return cpumap
354 def xm_cpus_set(args):
355 arg_check(args, 3, "cpus-set")
357 dom = args[0]
358 vcpu = int(args[1])
359 cpumap = cpu_make_map(args[2])
361 from xen.xend.XendClient import server
362 server.xend_domain_pincpu(dom, vcpu, cpumap)
364 def xm_mem_max(args):
365 arg_check(args, 2, "mem-max")
367 dom = args[0]
368 mem = int_unit(args[1], 'm')
370 from xen.xend.XendClient import server
371 server.xend_domain_maxmem_set(dom, mem)
373 def xm_mem_set(args):
374 arg_check(args, 2, "mem-set")
376 dom = args[0]
377 mem_target = int_unit(args[1], 'm')
379 from xen.xend.XendClient import server
380 server.xend_domain_mem_target_set(dom, mem_target)
382 # TODO: why does this lookup by name? and what if that fails!?
383 def xm_vcpu_enable(args):
384 arg_check(args, 2, "vcpu-enable")
386 name = args[0]
387 vcpu = int(args[1])
389 from xen.xend.XendClient import server
390 dom = server.xend_domain(name)
391 id = sxp.child_value(dom, 'id')
392 server.xend_domain_vcpu_hotplug(id, vcpu, 1)
394 def xm_vcpu_disable(args):
395 arg_check(args, 2, "vcpu-disable")
397 name = args[0]
398 vcpu = int(args[1])
400 from xen.xend.XendClient import server
401 dom = server.xend_domain(name)
402 id = sxp.child_value(dom, 'id')
403 server.xend_domain_vcpu_hotplug(id, vcpu, 0)
405 def xm_domid(args):
406 name = args[0]
408 from xen.xend.XendClient import server
409 dom = server.xend_domain(name)
410 print sxp.child_value(dom, 'id')
412 def xm_domname(args):
413 name = args[0]
415 from xen.xend.XendClient import server
416 dom = server.xend_domain(name)
417 print sxp.child_value(dom, 'name')
419 def xm_bvt(args):
420 arg_check(args, 6, "bvt")
421 dom = args[0]
422 v = map(long, args[1:6])
423 from xen.xend.XendClient import server
424 server.xend_domain_cpu_bvt_set(dom, *v)
426 def xm_bvt_ctxallow(args):
427 arg_check(args, 1, "bvt_ctxallow")
429 slice = int(args[0])
430 from xen.xend.XendClient import server
431 server.xend_node_cpu_bvt_slice_set(slice)
433 def xm_sedf(args):
434 arg_check(args, 6, "sedf")
436 dom = args[0]
437 v = map(int, args[1:6])
438 from xen.xend.XendClient import server
439 server.xend_domain_cpu_sedf_set(dom, *v)
441 def xm_info(args):
442 from xen.xend.XendClient import server
443 info = server.xend_node()
445 for x in info[1:]:
446 print "%-23s:" % x[0], x[1]
448 # TODO: remove as soon as console server shows up
449 def xm_console(args):
450 arg_check(args,1,"console")
452 dom = args[0]
453 from xen.xend.XendClient import server
454 info = server.xend_domain(dom)
455 domid = int(sxp.child_value(info, 'id', '-1'))
456 cmd = "/usr/libexec/xen/xenconsole %d" % domid
457 os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
458 console = sxp.child(info, "console")
460 def xm_dmesg(args):
462 gopts = Opts(use="""[-c|--clear]
464 Read Xen's message buffer (boot output, warning and error messages) or clear
465 its contents if the [-c|--clear] flag is specified.
466 """)
468 gopts.opt('clear', short='c',
469 fn=set_true, default=0,
470 use="Clear the contents of the Xen message buffer.")
471 # Work around for gopts
472 args.insert(0,"bogus")
473 gopts.parse(args)
474 if not (1 <= len(args) <= 2):
475 err('Invalid arguments: ' + str(args))
477 from xen.xend.XendClient import server
478 if not gopts.vals.clear:
479 print server.xend_node_get_dmesg()
480 else:
481 server.xend_node_clear_dmesg()
483 def xm_log(args):
484 from xen.xend.XendClient import server
485 print server.xend_node_log()
487 def xm_network_limit(args):
488 arg_check(args,4,"network-limit")
489 dom = args[0]
490 v = map(int, args[1:4])
491 from xen.xend.XendClient import server
492 server.xend_domain_vif_limit(dom, *v)
494 def xm_network_list(args):
495 arg_check(args,1,"network-list")
496 dom = args[0]
497 from xen.xend.XendClient import server
498 for x in server.xend_domain_devices(dom, 'vif'):
499 sxp.show(x)
500 print
502 def xm_block_list(args):
503 arg_check(args,1,"block-list")
504 dom = args[0]
505 from xen.xend.XendClient import server
506 for x in server.xend_domain_devices(dom, 'vbd'):
507 sxp.show(x)
508 print
510 def xm_block_create(args):
511 n = len(args)
512 if n < 4 or n > 5:
513 err("%s: Invalid argument(s)" % args[0])
514 usage("block-create")
516 dom = args[0]
517 vbd = ['vbd',
518 ['uname', args[1]],
519 ['dev', args[2]],
520 ['mode', args[3]]]
521 if n == 5:
522 vbd.append(['backend', args[4]])
524 from xen.xend.XendClient import server
525 server.xend_domain_device_create(dom, vbd)
527 def xm_block_refresh(args):
528 arg_check(args,2,"block-refresh")
530 dom = args[0]
531 dev = args[1]
533 from xen.xend.XendClient import server
534 server.xend_domain_device_refresh(dom, 'vbd', dev)
536 def xm_block_destroy(args):
537 arg_check(args,2,"block-destroy")
539 dom = args[0]
540 dev = args[1]
542 from xen.xend.XendClient import server
543 server.xend_domain_device_destroy(dom, 'vbd', dev)
545 commands = {
546 # console commands
547 "console": xm_console,
548 # domain commands
549 "domid": xm_domid,
550 "domname": xm_domname,
551 "create": xm_create,
552 "destroy": xm_destroy,
553 "restore": xm_restore,
554 "save": xm_save,
555 "shutdown": xm_shutdown,
556 "reboot": xm_reboot,
557 "list": xm_list,
558 # memory commands
559 "mem-max": xm_mem_max,
560 "mem-set": xm_mem_set,
561 # cpu commands
562 "cpus-set": xm_cpus_set,
563 # "cpus-list": xm_cpus_list,
564 "vcpu-enable": xm_vcpu_enable,
565 "vcpu-disable": xm_vcpu_disable,
566 "vcpu-list": xm_vcpu_list,
567 # migration
568 "migrate": xm_migrate,
569 # special
570 "sysrq": xm_sysrq,
571 "pause": xm_pause,
572 "unpause": xm_unpause,
573 # host commands
574 "dmesg": xm_dmesg,
575 "info": xm_info,
576 "log": xm_log,
577 # scheduler
578 "bvt": xm_bvt,
579 "bvt_ctxallow": xm_bvt_ctxallow,
580 "sedf": xm_sedf,
581 # block
582 "block-create": xm_block_create,
583 "block-destroy": xm_block_destroy,
584 "block-list": xm_block_list,
585 "block-refresh": xm_block_refresh,
586 # network
587 "network-limit": xm_network_limit,
588 "network-list": xm_network_list
589 }
591 aliases = {
592 "balloon": "mem-set",
593 "vif-list": "network-list",
594 "vif-limit": "network-limit",
595 "vbd-create": "block-create",
596 "vbd-destroy": "block-destroy",
597 "vbd-list": "block-list",
598 "vbd-refresh": "block-refresh",
599 }
601 help = {
602 "--long": longhelp
603 }
605 def xm_lookup_cmd(cmd):
606 if commands.has_key(cmd):
607 return commands[cmd]
608 elif aliases.has_key(cmd):
609 deprecated(cmd,aliases[cmd])
610 return commands[aliases[cmd]]
611 else:
612 if len( cmd ) > 1:
613 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
614 if len( matched_commands ) == 1:
615 return matched_commands[0][1]
616 err('Sub Command %s not found!' % cmd)
617 usage()
619 def deprecated(old,new):
620 err('Option %s is deprecated, and will be removed in future!!!' % old)
621 err('Option %s is the new replacement, see "xm help %s" for more info' % (new, new))
623 def usage(cmd=None):
624 if cmd == "full":
625 print fullhelp
626 elif help.has_key(cmd):
627 print help[cmd]
628 else:
629 print shorthelp
630 sys.exit(1)
632 def main(argv=sys.argv):
633 if len(argv) < 2:
634 usage()
636 if re.compile('-*help').match(argv[1]):
637 if len(argv) > 2 and help.has_key(argv[2]):
638 usage(argv[2])
639 else:
640 usage()
641 sys.exit(0)
643 cmd = xm_lookup_cmd(argv[1])
645 # strip off prog name and subcmd
646 args = argv[2:]
647 if cmd:
648 try:
649 from xen.xend.XendClient import XendError
650 rc = cmd(args)
651 if rc:
652 usage()
653 except socket.error, ex:
654 print >>sys.stderr, ex
655 err("Error connecting to xend, is xend running?")
656 sys.exit(1)
657 except IOError:
658 err("Most commands need root access. Please try again as root")
659 sys.exit(1)
660 except XendError, ex:
661 if len(args) > 0:
662 handle_xend_error(argv[1], args[1], ex)
663 else:
664 print "Unexpected error:", sys.exc_info()[0]
665 print
666 print "Please report to xen-devel@lists.xensource.com"
667 raise
668 except SystemExit:
669 sys.exit(1)
670 except:
671 print "Unexpected error:", sys.exc_info()[0]
672 print
673 print "Please report to xen-devel@lists.xensource.com"
674 raise
676 else:
677 usage()
679 if __name__ == "__main__":
680 main()