ia64/xen-unstable

view tools/python/xen/xm/main.py @ 10508:c2e8e9b1e192

[TOOLS] Treat '--' command-line split option correctly.
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Jun 22 15:09:48 2006 +0100 (2006-06-22)
parents 95ac3f0f79bc
children e236794915cc
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
43 from xen.util import security
44 from select import select
46 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
47 # getopt.getopt if gnu_getopt is not available. This will mean that options
48 # may only be specified before positional arguments.
49 if not hasattr(getopt, 'gnu_getopt'):
50 getopt.gnu_getopt = getopt.getopt
53 # Strings for shorthelp
54 console_help = "console <DomId> Attach to domain DomId's console."
55 create_help = """create [-c] <ConfigFile>
56 [Name=Value].. Create a domain based on Config File"""
57 destroy_help = "destroy <DomId> Terminate a domain immediately"
58 help_help = "help Display this message"
59 list_help = "list [--long] [DomId, ...] List information about domains"
60 list_label_help = "list [--label] [DomId, ...] List information about domains including their labels"
62 mem_max_help = "mem-max <DomId> <Mem> Set maximum memory reservation for a domain"
63 mem_set_help = "mem-set <DomId> <Mem> Adjust the current memory usage for a domain"
64 migrate_help = "migrate <DomId> <Host> Migrate a domain to another machine"
65 pause_help = "pause <DomId> Pause execution of a domain"
66 reboot_help = "reboot <DomId> [-w][-a] Reboot a domain"
67 restore_help = "restore <File> Create a domain from a saved state file"
68 save_help = "save <DomId> <File> Save domain state (and config) to file"
69 shutdown_help ="shutdown <DomId> [-w][-a][-R|-H] Shutdown a domain"
70 top_help = "top Monitor system and domains in real-time"
71 unpause_help = "unpause <DomId> Unpause a paused domain"
73 help_spacer = """
74 """
76 # Strings for longhelp
77 sysrq_help = "sysrq <DomId> <letter> Send a sysrq to a domain"
78 domid_help = "domid <DomName> Converts a domain name to a domain id"
79 domname_help = "domname <DomId> Convert a domain id to a domain name"
80 vcpu_set_help = """vcpu-set <DomId> <VCPUs> Set the number of VCPUs for a domain"""
81 vcpu_list_help = "vcpu-list <DomId> List the VCPUs for a domain (or all domains)"
82 vcpu_pin_help = "vcpu-pin <DomId> <VCPU> <CPUs> Set which cpus a VCPU can use"
83 dmesg_help = "dmesg [-c|--clear] Read or clear Xen's message buffer"
84 info_help = "info Get information about the xen host"
85 rename_help = "rename <DomId> <New Name> Rename a domain"
86 log_help = "log Print the xend log"
87 sched_bvt_help = """sched-bvt <Parameters> Set Borrowed Virtual Time scheduler
88 parameters"""
89 sched_bvt_ctxallow_help = """sched-bvt-ctxallow <Allow> Set the BVT scheduler context switch
90 allowance"""
91 sched_sedf_help = "sched-sedf [DOM] [OPTIONS] Show|Set simple EDF parameters\n" + \
92 " -p, --period Relative deadline(ms).\n\
93 -s, --slice Worst-case execution time(ms)\n\
94 (slice < period).\n\
95 -l, --latency scaled period(ms) in case the domain\n\
96 is doing heavy I/O.\n\
97 -e, --extra flag (0/1) which controls whether the\n\
98 domain can run in extra-time\n\
99 -w, --weight mutually exclusive with period/slice and\n\
100 specifies another way of setting a domain's\n\
101 cpu period/slice."
103 sched_credit_help = "sched-credit Set or get credit scheduler parameters"
104 block_attach_help = """block-attach <DomId> <BackDev> <FrontDev> <Mode>
105 [BackDomId] Create a new virtual block device"""
106 block_detach_help = """block-detach <DomId> <DevId> Destroy a domain's virtual block device,
107 where <DevId> may either be the device ID
108 or the device name as mounted in the guest"""
110 block_list_help = "block-list <DomId> [--long] List virtual block devices for a domain"
111 network_attach_help = """network-attach <DomID> [script=<script>] [ip=<ip>] [mac=<mac>]
112 [bridge=<bridge>] [backend=<backDomID>]
113 Create a new virtual network device """
114 network_detach_help = """network-detach <DomId> <DevId> Destroy a domain's virtual network
115 device, where <DevId> is the device ID."""
117 network_list_help = "network-list <DomId> [--long] List virtual network interfaces for a domain"
118 vnet_list_help = "vnet-list [-l|--long] list vnets"
119 vnet_create_help = "vnet-create <config> create a vnet from a config file"
120 vnet_delete_help = "vnet-delete <vnetid> delete a vnet"
121 vtpm_list_help = "vtpm-list <DomId> [--long] list virtual TPM devices"
122 addlabel_help = "addlabel <ConfigFile> <label> Add security label to ConfigFile"
123 cfgbootpolicy_help = "cfgbootpolicy <policy> Add policy to boot configuration "
124 dumppolicy_help = "dumppolicy Print hypervisor ACM state information"
125 loadpolicy_help = "loadpolicy <policy> Load binary policy into hypervisor"
126 makepolicy_help = "makepolicy <policy> Build policy and create .bin/.map files"
127 labels_help = "labels [policy] [type=DOM|..] List <type> labels for (active) policy."
128 serve_help = "serve Proxy Xend XML-RPC over stdio"
130 short_command_list = [
131 "console",
132 "create",
133 "destroy",
134 "help",
135 "list",
136 "mem-set",
137 "migrate",
138 "pause",
139 "reboot",
140 "restore",
141 "save",
142 "shutdown",
143 "top",
144 "unpause",
145 "vcpu-set",
146 ]
148 domain_commands = [
149 "console",
150 "create",
151 "destroy",
152 "domid",
153 "domname",
154 "list",
155 "list_label",
156 "mem-max",
157 "mem-set",
158 "migrate",
159 "pause",
160 "reboot",
161 "rename",
162 "restore",
163 "save",
164 "shutdown",
165 "sysrq",
166 "top",
167 "unpause",
168 "vcpu-list",
169 "vcpu-pin",
170 "vcpu-set",
171 ]
173 host_commands = [
174 "dmesg",
175 "info",
176 "log",
177 "serve",
178 ]
180 scheduler_commands = [
181 "sched-credit",
182 "sched-bvt",
183 "sched-bvt-ctxallow",
184 "sched-sedf",
185 ]
187 device_commands = [
188 "block-attach",
189 "block-detach",
190 "block-list",
191 "network-attach",
192 "network-detach",
193 "network-list",
194 "vtpm-list",
195 ]
197 vnet_commands = [
198 "vnet-list",
199 "vnet-create",
200 "vnet-delete",
201 ]
203 acm_commands = [
204 "labels",
205 "addlabel",
206 "makepolicy",
207 "loadpolicy",
208 "cfgbootpolicy",
209 "dumppolicy"
210 ]
212 all_commands = (domain_commands + host_commands + scheduler_commands +
213 device_commands + vnet_commands + acm_commands)
216 def commandToHelp(cmd):
217 return eval(cmd.replace("-", "_") + "_help")
220 shorthelp = """Usage: xm <subcommand> [args]
221 Control, list, and manipulate Xen guest instances
223 xm common subcommands:
224 """ + help_spacer.join(map(commandToHelp, short_command_list)) + """
226 <DomName> can be substituted for <DomId> in xm subcommands.
228 For a complete list of subcommands run 'xm help --long'
229 For more help on xm see the xm(1) man page
230 For more help on xm create, see the xmdomain.cfg(5) man page"""
232 longhelp = """Usage: xm <subcommand> [args]
233 Control, list, and manipulate Xen guest instances
235 xm full list of subcommands:
237 Domain Commands:
238 """ + help_spacer.join(map(commandToHelp, domain_commands)) + """
240 Xen Host Commands:
241 """ + help_spacer.join(map(commandToHelp, host_commands)) + """
243 Scheduler Commands:
244 """ + help_spacer.join(map(commandToHelp, scheduler_commands)) + """
246 Virtual Device Commands:
247 """ + help_spacer.join(map(commandToHelp, device_commands)) + """
249 Vnet commands:
250 """ + help_spacer.join(map(commandToHelp, vnet_commands)) + """
252 Access Control commands:
253 """ + help_spacer.join(map(commandToHelp, acm_commands)) + """
255 <DomName> can be substituted for <DomId> in xm subcommands.
257 For a short list of subcommands run 'xm help'
258 For more help on xm see the xm(1) man page
259 For more help on xm create, see the xmdomain.cfg(5) man page"""
261 # array for xm help <command>
262 help = {
263 "--long": longhelp
264 }
266 for command in all_commands:
267 # create is handled specially
268 if (command != 'create'):
269 help[command] = commandToHelp(command)
272 ####################################################################
273 #
274 # Utility functions
275 #
276 ####################################################################
278 def arg_check(args, name, lo, hi = -1):
279 n = len([i for i in args if i != '--'])
281 if hi == -1:
282 if n != lo:
283 err("'xm %s' requires %d argument%s.\n" % (name, lo,
284 lo > 1 and 's' or ''))
285 usage(name)
286 else:
287 if n < lo or n > hi:
288 err("'xm %s' requires between %d and %d arguments.\n" %
289 (name, lo, hi))
290 usage(name)
293 def unit(c):
294 if not c.isalpha():
295 return 0
296 base = 1
297 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
298 elif c == 'M' or c == 'm': base = 1024 * 1024
299 elif c == 'K' or c == 'k': base = 1024
300 else:
301 print 'ignoring unknown unit'
302 return base
304 def int_unit(str, dest):
305 base = unit(str[-1])
306 if not base:
307 return int(str)
309 value = int(str[:-1])
310 dst_base = unit(dest)
311 if dst_base == 0:
312 dst_base = 1
313 if dst_base > base:
314 return value / (dst_base / base)
315 else:
316 return value * (base / dst_base)
318 def err(msg):
319 print >>sys.stderr, "Error:", msg
322 #########################################################################
323 #
324 # Main xm functions
325 #
326 #########################################################################
328 def xm_save(args):
329 arg_check(args, "save", 2)
331 dom = args[0] # TODO: should check if this exists
332 savefile = os.path.abspath(args[1])
334 if not os.access(os.path.dirname(savefile), os.W_OK):
335 err("xm save: Unable to create file %s" % savefile)
336 sys.exit(1)
338 server.xend.domain.save(dom, savefile)
340 def xm_restore(args):
341 arg_check(args, "restore", 1)
343 savefile = os.path.abspath(args[0])
345 if not os.access(savefile, os.R_OK):
346 err("xm restore: Unable to read file %s" % savefile)
347 sys.exit(1)
349 server.xend.domain.restore(savefile)
352 def getDomains(domain_names):
353 if domain_names:
354 return map(server.xend.domain, domain_names)
355 else:
356 return server.xend.domains(1)
359 def xm_list(args):
360 use_long = 0
361 show_vcpus = 0
362 show_labels = 0
363 try:
364 (options, params) = getopt.gnu_getopt(args, 'lv', ['long','vcpus','label'])
365 except getopt.GetoptError, opterr:
366 err(opterr)
367 sys.exit(1)
369 for (k, v) in options:
370 if k in ['-l', '--long']:
371 use_long = 1
372 if k in ['-v', '--vcpus']:
373 show_vcpus = 1
374 if k in ['--label']:
375 show_labels = 1
377 if show_vcpus:
378 print >>sys.stderr, (
379 "xm list -v is deprecated. Please use xm vcpu-list.")
380 xm_vcpu_list(params)
381 return
383 doms = getDomains(params)
385 if use_long:
386 map(PrettyPrint.prettyprint, doms)
387 elif show_labels:
388 xm_label_list(doms)
389 else:
390 xm_brief_list(doms)
393 def parse_doms_info(info):
394 def get_info(n, t, d):
395 return t(sxp.child_value(info, n, d))
397 return {
398 'dom' : get_info('domid', int, -1),
399 'name' : get_info('name', str, '??'),
400 'mem' : get_info('memory', int, 0),
401 'vcpus' : get_info('online_vcpus', int, 0),
402 'state' : get_info('state', str, '??'),
403 'cpu_time' : get_info('cpu_time', float, 0),
404 'seclabel' : security.get_security_printlabel(info),
405 }
408 def parse_sedf_info(info):
409 def get_info(n, t, d):
410 return t(sxp.child_value(info, n, d))
412 return {
413 'dom' : get_info('domain', int, -1),
414 'period' : get_info('period', int, -1),
415 'slice' : get_info('slice', int, -1),
416 'latency' : get_info('latency', int, -1),
417 'extratime': get_info('extratime', int, -1),
418 'weight' : get_info('weight', int, -1),
419 }
422 def xm_brief_list(doms):
423 print 'Name ID Mem(MiB) VCPUs State Time(s)'
424 for dom in doms:
425 d = parse_doms_info(dom)
426 print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f" % d)
429 def xm_label_list(doms):
430 output = []
431 print 'Name ID Mem(MiB) VCPUs State Time(s) Label'
432 for dom in doms:
433 d = parse_doms_info(dom)
434 l = "%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f " % d
435 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
436 if d['seclabel']:
437 line = (l, d['seclabel'])
438 else:
439 line = (l, "ERROR")
440 elif security.active_policy in ['DEFAULT']:
441 line = (l, "DEFAULT")
442 else:
443 line = (l, "INACTIVE")
444 output.append(line)
445 #sort by labels
446 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
447 for l in output:
448 print l[0] + l[1]
451 def xm_vcpu_list(args):
453 if args:
454 dominfo = map(server.xend.domain.getVCPUInfo, args)
455 else:
456 doms = server.xend.domains(False)
457 dominfo = map(server.xend.domain.getVCPUInfo, doms)
459 print 'Name ID VCPU CPU State Time(s) CPU Affinity'
461 for dom in dominfo:
462 def get_info(n):
463 return sxp.child_value(dom, n)
465 #
466 # convert a list of integers into a list of pairs indicating
467 # continuous sequences in the list:
468 #
469 # [0,1,2,3] -> [(0,3)]
470 # [1,2,4,5] -> [(1,2),(4,5)]
471 # [0] -> [(0,0)]
472 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
473 #
474 def list_to_rangepairs(cmap):
475 cmap.sort()
476 pairs = []
477 x = y = 0
478 for i in range(0,len(cmap)):
479 try:
480 if ((cmap[y+1] - cmap[i]) > 1):
481 pairs.append((cmap[x],cmap[y]))
482 x = y = i+1
483 else:
484 y = y + 1
485 # if we go off the end, then just add x to y
486 except IndexError:
487 pairs.append((cmap[x],cmap[y]))
489 return pairs
491 #
492 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
493 #
494 def format_pairs(pairs):
495 if not pairs:
496 return "no cpus"
497 out = ""
498 for f,s in pairs:
499 if (f==s):
500 out += '%d'%f
501 else:
502 out += '%d-%d'%(f,s)
503 out += ','
504 # trim trailing ','
505 return out[:-1]
507 def format_cpumap(cpumap):
508 cpumap = map(lambda x: int(x), cpumap)
509 cpumap.sort()
511 for x in server.xend.node.info()[1:]:
512 if len(x) > 1 and x[0] == 'nr_cpus':
513 nr_cpus = int(x[1])
514 # normalize cpumap by modulus nr_cpus, and drop duplicates
515 cpumap = dict.fromkeys(
516 map(lambda x: x % nr_cpus, cpumap)).keys()
517 if len(cpumap) == nr_cpus:
518 return "any cpu"
519 break
521 return format_pairs(list_to_rangepairs(cpumap))
523 name = get_info('name')
524 domid = int(get_info('domid'))
526 for vcpu in sxp.children(dom, 'vcpu'):
527 def vinfo(n, t):
528 return t(sxp.child_value(vcpu, n))
530 number = vinfo('number', int)
531 cpu = vinfo('cpu', int)
532 cpumap = format_cpumap(vinfo('cpumap', list))
533 online = vinfo('online', int)
534 cpu_time = vinfo('cpu_time', float)
535 running = vinfo('running', int)
536 blocked = vinfo('blocked', int)
538 if online:
539 c = str(cpu)
540 if running:
541 s = 'r'
542 else:
543 s = '-'
544 if blocked:
545 s += 'b'
546 else:
547 s += '-'
548 s += '-'
549 else:
550 c = "-"
551 s = "--p"
553 print (
554 "%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
555 locals())
558 def xm_reboot(args):
559 arg_check(args, "reboot", 1, 4)
560 from xen.xm import shutdown
561 shutdown.main(["shutdown", "-R"] + args)
563 def xm_pause(args):
564 arg_check(args, "pause", 1)
565 dom = args[0]
567 server.xend.domain.pause(dom)
569 def xm_unpause(args):
570 arg_check(args, "unpause", 1)
571 dom = args[0]
573 server.xend.domain.unpause(dom)
575 def xm_rename(args):
576 arg_check(args, "rename", 2)
578 server.xend.domain.setName(args[0], args[1])
580 def xm_subcommand(command, args):
581 cmd = __import__(command, globals(), locals(), 'xen.xm')
582 cmd.main([command] + args)
585 #############################################################
587 def cpu_make_map(cpulist):
588 cpus = []
589 for c in cpulist.split(','):
590 if c.find('-') != -1:
591 (x,y) = c.split('-')
592 for i in range(int(x),int(y)+1):
593 cpus.append(int(i))
594 else:
595 cpus.append(int(c))
596 cpus.sort()
597 return cpus
599 def xm_vcpu_pin(args):
600 arg_check(args, "vcpu-pin", 3)
602 dom = args[0]
603 vcpu = int(args[1])
604 cpumap = cpu_make_map(args[2])
606 server.xend.domain.pincpu(dom, vcpu, cpumap)
608 def xm_mem_max(args):
609 arg_check(args, "mem-max", 2)
611 dom = args[0]
612 mem = int_unit(args[1], 'm')
614 server.xend.domain.maxmem_set(dom, mem)
616 def xm_mem_set(args):
617 arg_check(args, "mem-set", 2)
619 dom = args[0]
620 mem_target = int_unit(args[1], 'm')
622 server.xend.domain.setMemoryTarget(dom, mem_target)
624 def xm_vcpu_set(args):
625 arg_check(args, "vcpu-set", 2)
627 server.xend.domain.setVCpuCount(args[0], int(args[1]))
630 def xm_destroy(args):
631 arg_check(args, "destroy", 1)
632 server.xend.domain.destroy(args[0])
635 def xm_domid(args):
636 arg_check(args, "domid", 1)
638 name = args[0]
640 dom = server.xend.domain(name)
641 print sxp.child_value(dom, 'domid')
643 def xm_domname(args):
644 arg_check(args, "domname", 1)
646 name = args[0]
648 dom = server.xend.domain(name)
649 print sxp.child_value(dom, 'name')
651 def xm_sched_bvt(args):
652 arg_check(args, "sched-bvt", 6)
653 dom = args[0]
654 v = map(long, args[1:6])
655 server.xend.domain.cpu_bvt_set(dom, *v)
657 def xm_sched_bvt_ctxallow(args):
658 arg_check(args, "sched-bvt-ctxallow", 1)
660 slice = int(args[0])
661 server.xend.node.cpu_bvt_slice_set(slice)
663 def xm_sched_sedf(args):
664 def ns_to_ms(val):
665 return float(val) * 0.000001
667 def ms_to_ns(val):
668 return (float(val) / 0.000001)
670 def print_sedf(info):
671 info['period'] = ns_to_ms(info['period'])
672 info['slice'] = ns_to_ms(info['slice'])
673 info['latency'] = ns_to_ms(info['latency'])
674 print( ("%(name)-32s %(dom)3d %(period)9.1f %(slice)9.1f" +
675 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
677 def domid_match(domid, info):
678 return domid is None or domid == info['name'] or domid == str(info['dom'])
680 # we want to just display current info if no parameters are passed
681 if len(args) == 0:
682 domid = None
683 else:
684 # we expect at least a domain id (name or number)
685 # and at most a domid up to 5 options with values
686 arg_check(args, "sched-sedf", 1, 11)
687 domid = args[0]
688 # drop domid from args since get_opt doesn't recognize it
689 args = args[1:]
691 opts = {}
692 try:
693 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
694 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
695 except getopt.GetoptError, opterr:
696 err(opterr)
697 sys.exit(1)
699 # convert to nanoseconds if needed
700 for (k, v) in options:
701 if k in ['-p', '--period']:
702 opts['period'] = ms_to_ns(v)
703 elif k in ['-s', '--slice']:
704 opts['slice'] = ms_to_ns(v)
705 elif k in ['-l', '--latency']:
706 opts['latency'] = ms_to_ns(v)
707 elif k in ['-e', '--extratime']:
708 opts['extratime'] = v
709 elif k in ['-w', '--weight']:
710 opts['weight'] = v
712 # print header if we aren't setting any parameters
713 if len(opts.keys()) == 0:
714 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s'%('Name','ID','Period(ms)',
715 'Slice(ms)', 'Lat(ms)',
716 'Extra','Weight')
718 doms = filter(lambda x : domid_match(domid, x),
719 [parse_doms_info(dom) for dom in getDomains("")])
720 for d in doms:
721 # fetch current values so as not to clobber them
722 sedf_info = \
723 parse_sedf_info(server.xend.domain.cpu_sedf_get(d['dom']))
724 sedf_info['name'] = d['name']
726 # update values in case of call to set
727 if len(opts.keys()) > 0:
728 for k in opts.keys():
729 sedf_info[k]=opts[k]
731 # send the update, converting user input
732 v = map(int, [sedf_info['period'], sedf_info['slice'],
733 sedf_info['latency'],sedf_info['extratime'],
734 sedf_info['weight']])
735 rv = server.xend.domain.cpu_sedf_set(d['dom'], *v)
736 if int(rv) != 0:
737 err("Failed to set sedf parameters (rv=%d)."%(rv))
739 # not setting values, display info
740 else:
741 print_sedf(sedf_info)
743 def xm_sched_credit(args):
744 usage_msg = """sched-credit: Set or get credit scheduler parameters
745 Usage:
747 sched-credit -d domain [-w weight] [-c cap]
748 """
749 try:
750 opts, args = getopt.getopt(args[0:], "d:w:c:",
751 ["domain=", "weight=", "cap="])
752 except getopt.GetoptError:
753 # print help information and exit:
754 print usage_msg
755 sys.exit(1)
757 domain = None
758 weight = None
759 cap = None
761 for o, a in opts:
762 if o == "-d":
763 domain = a
764 elif o == "-w":
765 weight = int(a)
766 elif o == "-c":
767 cap = int(a);
769 if domain is None:
770 # place holder for system-wide scheduler parameters
771 print usage_msg
772 sys.exit(1)
774 if weight is None and cap is None:
775 print server.xend.domain.sched_credit_get(domain)
776 else:
777 if weight is None:
778 weight = int(0)
779 if cap is None:
780 cap = int(~0)
782 err = server.xend.domain.sched_credit_set(domain, weight, cap)
783 if err != 0:
784 print err
786 def xm_info(args):
787 arg_check(args, "info", 0)
789 info = server.xend.node.info()
791 for x in info[1:]:
792 if len(x) < 2:
793 print "%-23s: (none)" % x[0]
794 else:
795 print "%-23s:" % x[0], x[1]
797 def xm_console(args):
798 arg_check(args, "console", 1)
800 dom = args[0]
801 info = server.xend.domain(dom)
802 domid = int(sxp.child_value(info, 'domid', '-1'))
803 console.execConsole(domid)
806 def xm_top(args):
807 arg_check(args, "top", 0)
809 os.execvp('xentop', ['xentop'])
811 def xm_dmesg(args):
812 arg_check(args, "dmesg", 0, 1)
814 gopts = Opts(use="""[-c|--clear]
816 Read Xen's message buffer (boot output, warning and error messages) or clear
817 its contents if the [-c|--clear] flag is specified.
818 """)
820 gopts.opt('clear', short='c',
821 fn=set_true, default=0,
822 use="Clear the contents of the Xen message buffer.")
823 # Work around for gopts
824 myargs = args
825 myargs.insert(0, 'dmesg')
826 gopts.parse(myargs)
827 if not (1 <= len(myargs) <= 2):
828 err('Invalid arguments: ' + str(myargs))
830 if not gopts.vals.clear:
831 print server.xend.node.dmesg.info()
832 else:
833 server.xend.node.dmesg.clear()
835 def xm_log(args):
836 arg_check(args, "log", 0)
838 print server.xend.node.log()
840 def xm_serve(args):
841 arg_check(args, "serve", 0)
843 from fcntl import fcntl, F_SETFL
845 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
846 s.connect(xen.xend.XendClient.XML_RPC_SOCKET)
847 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
849 while True:
850 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
851 if s in iwtd:
852 data = s.recv(4096)
853 if len(data) > 0:
854 sys.stdout.write(data)
855 sys.stdout.flush()
856 else:
857 break
858 if sys.stdin in iwtd:
859 data = sys.stdin.read(4096)
860 if len(data) > 0:
861 s.sendall(data)
862 else:
863 break
864 s.close()
866 def parse_dev_info(info):
867 def get_info(n, t, d):
868 i = 0
869 while i < len(info):
870 if (info[i][0] == n):
871 return t(info[i][1])
872 i = i + 1
873 return t(d)
874 return {
875 #common
876 'backend-id' : get_info('backend-id', int, -1),
877 'handle' : get_info('handle', int, 0),
878 'state' : get_info('state', int, -1),
879 'be-path' : get_info('backend', str, '??'),
880 'event-ch' : get_info('event-channel',int, -1),
881 #network specific
882 'virtual-device' : get_info('virtual-device', str, '??'),
883 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
884 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
885 'mac' : get_info('mac', str, '??'),
886 #block-device specific
887 'ring-ref' : get_info('ring-ref', int, -1),
888 }
890 def has_long_option(args):
891 use_long = 0
892 try:
893 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
894 except getopt.GetoptError, opterr:
895 err(opterr)
896 sys.exit(1)
898 for (k, v) in options:
899 if k in ['-l', '--long']:
900 use_long = 1
901 return (use_long, params)
903 def xm_network_list(args):
904 arg_check(args, "network-list", 1, 2)
906 (use_long, params) = has_long_option(args)
908 if len(params) == 0:
909 print 'No domain parameter given'
910 sys.exit(1)
911 dom = params[0]
912 if use_long:
913 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
914 map(PrettyPrint.prettyprint, devs)
915 else:
916 hdr = 0
917 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
918 if hdr == 0:
919 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
920 hdr = 1
921 ni = parse_dev_info(x[1])
922 ni['idx'] = int(x[0])
923 print ("%(idx)-3d "
924 "%(backend-id)-3d"
925 "%(mac)-17s "
926 "%(handle)-3d "
927 "%(state)-3d "
928 "%(event-ch)-3d "
929 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
930 "%(be-path)-30s "
931 % ni)
933 def xm_block_list(args):
934 arg_check(args, "block-list", 1, 2)
936 (use_long, params) = has_long_option(args)
938 if len(params) == 0:
939 print 'No domain parameter given'
940 sys.exit(1)
941 dom = params[0]
942 if use_long:
943 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
944 map(PrettyPrint.prettyprint, devs)
945 else:
946 hdr = 0
947 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
948 if hdr == 0:
949 print 'Vdev BE handle state evt-ch ring-ref BE-path'
950 hdr = 1
951 ni = parse_dev_info(x[1])
952 ni['idx'] = int(x[0])
953 print ("%(idx)-3d "
954 "%(backend-id)-3d "
955 "%(handle)-3d "
956 "%(state)-3d "
957 "%(event-ch)-3d "
958 "%(ring-ref)-5d "
959 "%(be-path)-30s "
960 % ni)
962 def xm_vtpm_list(args):
963 arg_check(args, "vtpm-list", 1, 2)
965 (use_long, params) = has_long_option(args)
967 if len(params) == 0:
968 print 'No domain parameter given'
969 sys.exit(1)
970 dom = params[0]
971 if use_long:
972 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
973 map(PrettyPrint.prettyprint, devs)
974 else:
975 hdr = 0
976 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
977 if hdr == 0:
978 print 'Idx BE handle state evt-ch ring-ref BE-path'
979 hdr = 1
980 ni = parse_dev_info(x[1])
981 ni['idx'] = int(x[0])
982 print ("%(idx)-3d "
983 "%(backend-id)-3d "
984 "%(handle)-3d "
985 "%(state)-3d "
986 "%(event-ch)-3d "
987 "%(ring-ref)-5d "
988 "%(be-path)-30s "
989 % ni)
991 def xm_block_attach(args):
992 arg_check(args, 'block-attach', 4, 5)
994 dom = args[0]
995 vbd = ['vbd',
996 ['uname', args[1]],
997 ['dev', args[2]],
998 ['mode', args[3]]]
999 if len(args) == 5:
1000 vbd.append(['backend', args[4]])
1002 server.xend.domain.device_create(dom, vbd)
1005 def xm_network_attach(args):
1006 arg_check(args, 'network-attach', 1, 10000)
1008 dom = args[0]
1009 vif = ['vif']
1011 for a in args[1:]:
1012 vif.append(a.split("="))
1014 server.xend.domain.device_create(dom, vif)
1017 def detach(args, command, deviceClass):
1018 arg_check(args, command, 2)
1020 dom = args[0]
1021 dev = args[1]
1023 server.xend.domain.destroyDevice(dom, deviceClass, dev)
1026 def xm_block_detach(args):
1027 detach(args, 'block-detach', 'vbd')
1030 def xm_network_detach(args):
1031 detach(args, 'network-detach', 'vif')
1034 def xm_vnet_list(args):
1035 try:
1036 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1037 except getopt.GetoptError, opterr:
1038 err(opterr)
1039 sys.exit(1)
1041 use_long = 0
1042 for (k, v) in options:
1043 if k in ['-l', '--long']:
1044 use_long = 1
1046 if params:
1047 use_long = 1
1048 vnets = params
1049 else:
1050 vnets = server.xend_vnets()
1052 for vnet in vnets:
1053 try:
1054 if use_long:
1055 info = server.xend_vnet(vnet)
1056 PrettyPrint.prettyprint(info)
1057 else:
1058 print vnet
1059 except Exception, ex:
1060 print vnet, ex
1062 def xm_vnet_create(args):
1063 arg_check(args, "vnet-create", 1)
1064 conf = args[0]
1065 if not os.access(conf, os.R_OK):
1066 print "File not found: %s" % conf
1067 sys.exit(1)
1069 server.xend_vnet_create(conf)
1071 def xm_vnet_delete(args):
1072 arg_check(args, "vnet-delete", 1)
1073 vnet = args[0]
1074 server.xend_vnet_delete(vnet)
1076 commands = {
1077 # console commands
1078 "console": xm_console,
1079 # xenstat commands
1080 "top": xm_top,
1081 # domain commands
1082 "destroy": xm_destroy,
1083 "domid": xm_domid,
1084 "domname": xm_domname,
1085 "rename": xm_rename,
1086 "restore": xm_restore,
1087 "save": xm_save,
1088 "reboot": xm_reboot,
1089 "list": xm_list,
1090 # memory commands
1091 "mem-max": xm_mem_max,
1092 "mem-set": xm_mem_set,
1093 # cpu commands
1094 "vcpu-pin": xm_vcpu_pin,
1095 "vcpu-list": xm_vcpu_list,
1096 "vcpu-set": xm_vcpu_set,
1097 # special
1098 "pause": xm_pause,
1099 "unpause": xm_unpause,
1100 # host commands
1101 "dmesg": xm_dmesg,
1102 "info": xm_info,
1103 "log": xm_log,
1104 "serve": xm_serve,
1105 # scheduler
1106 "sched-bvt": xm_sched_bvt,
1107 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
1108 "sched-sedf": xm_sched_sedf,
1109 "sched-credit": xm_sched_credit,
1110 # block
1111 "block-attach": xm_block_attach,
1112 "block-detach": xm_block_detach,
1113 "block-list": xm_block_list,
1114 # network
1115 "network-attach": xm_network_attach,
1116 "network-detach": xm_network_detach,
1117 "network-list": xm_network_list,
1118 # vnet
1119 "vnet-list": xm_vnet_list,
1120 "vnet-create": xm_vnet_create,
1121 "vnet-delete": xm_vnet_delete,
1122 # vtpm
1123 "vtpm-list": xm_vtpm_list,
1126 ## The commands supported by a separate argument parser in xend.xm.
1127 subcommands = [
1128 'create',
1129 'migrate',
1130 'sysrq',
1131 'shutdown',
1132 'labels',
1133 'addlabel',
1134 'cfgbootpolicy',
1135 'makepolicy',
1136 'loadpolicy',
1137 'dumppolicy'
1140 for c in subcommands:
1141 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
1143 aliases = {
1144 "balloon": "mem-set",
1145 "set-vcpus": "vcpu-set",
1146 "vif-list": "network-list",
1147 "vbd-create": "block-attach",
1148 "vbd-destroy": "block-detach",
1149 "vbd-list": "block-list",
1153 def xm_lookup_cmd(cmd):
1154 if commands.has_key(cmd):
1155 return commands[cmd]
1156 elif aliases.has_key(cmd):
1157 deprecated(cmd,aliases[cmd])
1158 return commands[aliases[cmd]]
1159 else:
1160 if len( cmd ) > 1:
1161 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
1162 if len( matched_commands ) == 1:
1163 return matched_commands[0][1]
1164 err('Sub Command %s not found!' % cmd)
1165 usage()
1167 def deprecated(old,new):
1168 print >>sys.stderr, (
1169 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1171 def usage(cmd=None):
1172 if cmd == 'create':
1173 mycmd = xm_lookup_cmd(cmd)
1174 mycmd( ['--help'] )
1175 sys.exit(1)
1176 if help.has_key(cmd):
1177 print " " + help[cmd]
1178 else:
1179 print shorthelp
1180 sys.exit(1)
1182 def main(argv=sys.argv):
1183 if len(argv) < 2:
1184 usage()
1186 if re.compile('-*help').match(argv[1]):
1187 if len(argv) > 2:
1188 usage(argv[2])
1189 else:
1190 usage()
1191 sys.exit(0)
1193 cmd = xm_lookup_cmd(argv[1])
1195 # strip off prog name and subcmd
1196 args = argv[2:]
1197 if cmd:
1198 try:
1199 rc = cmd(args)
1200 if rc:
1201 usage()
1202 except socket.error, ex:
1203 if os.geteuid() != 0:
1204 err("Most commands need root access. Please try again as root.")
1205 else:
1206 err("Error connecting to xend: %s. Is xend running?" % ex[1])
1207 sys.exit(1)
1208 except KeyboardInterrupt:
1209 print "Interrupted."
1210 sys.exit(1)
1211 except IOError, ex:
1212 if os.geteuid() != 0:
1213 err("Most commands need root access. Please try again as root.")
1214 else:
1215 err("Error connecting to xend: %s." % ex[1])
1216 sys.exit(1)
1217 except SystemExit:
1218 sys.exit(1)
1219 except xmlrpclib.Fault, ex:
1220 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1221 print >>sys.stderr, (
1222 "Error: the domain '%s' does not exist." % ex.faultString)
1223 else:
1224 print >>sys.stderr, "Error: %s" % ex.faultString
1225 sys.exit(1)
1226 except (ValueError, OverflowError):
1227 err("Invalid argument.")
1228 usage(argv[1])
1229 except:
1230 print "Unexpected error:", sys.exc_info()[0]
1231 print
1232 print "Please report to xen-devel@lists.xensource.com"
1233 raise
1235 else:
1236 usage()
1238 if __name__ == "__main__":
1239 main()