ia64/xen-unstable

view tools/python/xen/xm/main.py @ 10736:2937703f0ed0

Added blktap support. Includes kernel driver (enabled as CONFIG_XEN_BLKDEV_TAP=y) and userspace tools. The userspace deamon (blktapctrl) is enabled by default when xend is activated. For further information on using and configuring blktap see tools/blktap/README.
author jchesterfield@dhcp92.uk.xensource.com
date Thu Jul 13 10:13:26 2006 +0100 (2006-07-13)
parents 8922c1fbe684
children 7e25295d8d9d
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
33 import traceback
35 import xen.xend.XendProtocol
37 from xen.xend import PrettyPrint
38 from xen.xend import sxp
39 from xen.xm.opts import *
41 import console
42 import xen.xend.XendClient
43 from xen.xend.XendClient import server
44 from xen.util import security
45 from select import select
47 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
48 # getopt.getopt if gnu_getopt is not available. This will mean that options
49 # may only be specified before positional arguments.
50 if not hasattr(getopt, 'gnu_getopt'):
51 getopt.gnu_getopt = getopt.getopt
54 # Strings for shorthelp
55 console_help = "console <DomId> Attach to domain DomId's console."
56 create_help = """create [-c] <ConfigFile>
57 [Name=Value].. Create a domain based on Config File"""
58 destroy_help = "destroy <DomId> Terminate a domain immediately"
59 help_help = "help Display this message"
60 list_help = "list [--long] [DomId, ...] List information about domains"
61 list_label_help = "list [--label] [DomId, ...] List information about domains including their labels"
63 mem_max_help = "mem-max <DomId> <Mem> Set maximum memory reservation for a domain"
64 mem_set_help = "mem-set <DomId> <Mem> Adjust the current memory usage for a domain"
65 migrate_help = "migrate <DomId> <Host> Migrate a domain to another machine"
66 pause_help = "pause <DomId> Pause execution of a domain"
67 reboot_help = "reboot <DomId> [-w][-a] Reboot a domain"
68 restore_help = "restore <File> Create a domain from a saved state file"
69 save_help = "save <DomId> <File> Save domain state (and config) to file"
70 shutdown_help ="shutdown <DomId> [-w][-a][-R|-H] Shutdown a domain"
71 top_help = "top Monitor system and domains in real-time"
72 unpause_help = "unpause <DomId> Unpause a paused domain"
74 help_spacer = """
75 """
77 # Strings for longhelp
78 sysrq_help = "sysrq <DomId> <letter> Send a sysrq to a domain"
79 domid_help = "domid <DomName> Converts a domain name to a domain id"
80 domname_help = "domname <DomId> Convert a domain id to a domain name"
81 vcpu_set_help = """vcpu-set <DomId> <VCPUs> Set the number of VCPUs for a domain"""
82 vcpu_list_help = "vcpu-list <DomId> List the VCPUs for a domain (or all domains)"
83 vcpu_pin_help = "vcpu-pin <DomId> <VCPU> <CPUs> Set which cpus a VCPU can use"
84 dmesg_help = "dmesg [-c|--clear] Read or clear Xen's message buffer"
85 info_help = "info Get information about the xen host"
86 rename_help = "rename <DomId> <New Name> Rename a domain"
87 log_help = "log Print the xend log"
88 sched_bvt_help = """sched-bvt <Parameters> Set Borrowed Virtual Time scheduler
89 parameters"""
90 sched_bvt_ctxallow_help = """sched-bvt-ctxallow <Allow> Set the BVT scheduler context switch
91 allowance"""
92 sched_sedf_help = "sched-sedf [DOM] [OPTIONS] Show|Set simple EDF parameters\n" + \
93 " -p, --period Relative deadline(ms).\n\
94 -s, --slice Worst-case execution time(ms)\n\
95 (slice < period).\n\
96 -l, --latency scaled period(ms) in case the domain\n\
97 is doing heavy I/O.\n\
98 -e, --extra flag (0/1) which controls whether the\n\
99 domain can run in extra-time\n\
100 -w, --weight mutually exclusive with period/slice and\n\
101 specifies another way of setting a domain's\n\
102 cpu period/slice."
104 sched_credit_help = "sched-credit Set or get credit scheduler parameters"
105 block_attach_help = """block-attach <DomId> <BackDev> <FrontDev> <Mode>
106 [BackDomId] Create a new virtual block device"""
107 block_detach_help = """block-detach <DomId> <DevId> Destroy a domain's virtual block device,
108 where <DevId> may either be the device ID
109 or the device name as mounted in the guest"""
111 block_list_help = "block-list <DomId> [--long] List virtual block devices for a domain"
112 network_attach_help = """network-attach <DomID> [script=<script>] [ip=<ip>] [mac=<mac>]
113 [bridge=<bridge>] [backend=<backDomID>]
114 Create a new virtual network device """
115 network_detach_help = """network-detach <DomId> <DevId> Destroy a domain's virtual network
116 device, where <DevId> is the device ID."""
118 network_list_help = "network-list <DomId> [--long] List virtual network interfaces for a domain"
119 vnet_list_help = "vnet-list [-l|--long] list vnets"
120 vnet_create_help = "vnet-create <config> create a vnet from a config file"
121 vnet_delete_help = "vnet-delete <vnetid> delete a vnet"
122 vtpm_list_help = "vtpm-list <DomId> [--long] list virtual TPM devices"
123 addlabel_help = "addlabel <label> dom <configfile> Add security label to domain\n <label> res <resource> or resource"
124 rmlabel_help = "rmlabel dom <configfile> Remove security label from domain\n res <resource> or resource"
125 getlabel_help = "getlabel dom <configfile> Show security label for domain\n res <resource> or resource"
126 dry_run_help = "dry-run <configfile> Tests if domain can access its resources"
127 resources_help = "resources Show info for each labeled resource"
128 cfgbootpolicy_help = "cfgbootpolicy <policy> Add policy to boot configuration "
129 dumppolicy_help = "dumppolicy Print hypervisor ACM state information"
130 loadpolicy_help = "loadpolicy <policy> Load binary policy into hypervisor"
131 makepolicy_help = "makepolicy <policy> Build policy and create .bin/.map files"
132 labels_help = "labels [policy] [type=DOM|..] List <type> labels for (active) policy."
133 serve_help = "serve Proxy Xend XML-RPC over stdio"
135 short_command_list = [
136 "console",
137 "create",
138 "destroy",
139 "help",
140 "list",
141 "mem-set",
142 "migrate",
143 "pause",
144 "reboot",
145 "restore",
146 "save",
147 "shutdown",
148 "top",
149 "unpause",
150 "vcpu-set",
151 ]
153 domain_commands = [
154 "console",
155 "create",
156 "destroy",
157 "domid",
158 "domname",
159 "list",
160 "list_label",
161 "mem-max",
162 "mem-set",
163 "migrate",
164 "pause",
165 "reboot",
166 "rename",
167 "restore",
168 "save",
169 "shutdown",
170 "sysrq",
171 "top",
172 "unpause",
173 "vcpu-list",
174 "vcpu-pin",
175 "vcpu-set",
176 ]
178 host_commands = [
179 "dmesg",
180 "info",
181 "log",
182 "serve",
183 ]
185 scheduler_commands = [
186 "sched-credit",
187 "sched-bvt",
188 "sched-bvt-ctxallow",
189 "sched-sedf",
190 ]
192 device_commands = [
193 "block-attach",
194 "block-detach",
195 "block-list",
196 "network-attach",
197 "network-detach",
198 "network-list",
199 "vtpm-list",
200 ]
202 vnet_commands = [
203 "vnet-list",
204 "vnet-create",
205 "vnet-delete",
206 ]
208 acm_commands = [
209 "labels",
210 "addlabel",
211 "rmlabel",
212 "getlabel",
213 "dry-run",
214 "resources",
215 "makepolicy",
216 "loadpolicy",
217 "cfgbootpolicy",
218 "dumppolicy"
219 ]
221 all_commands = (domain_commands + host_commands + scheduler_commands +
222 device_commands + vnet_commands + acm_commands)
225 def commandToHelp(cmd):
226 return eval(cmd.replace("-", "_") + "_help")
229 shorthelp = """Usage: xm <subcommand> [args]
230 Control, list, and manipulate Xen guest instances
232 xm common subcommands:
233 """ + help_spacer.join(map(commandToHelp, short_command_list)) + """
235 <DomName> can be substituted for <DomId> in xm subcommands.
237 For a complete list of subcommands run 'xm help --long'
238 For more help on xm see the xm(1) man page
239 For more help on xm create, see the xmdomain.cfg(5) man page"""
241 longhelp = """Usage: xm <subcommand> [args]
242 Control, list, and manipulate Xen guest instances
244 xm full list of subcommands:
246 Domain Commands:
247 """ + help_spacer.join(map(commandToHelp, domain_commands)) + """
249 Xen Host Commands:
250 """ + help_spacer.join(map(commandToHelp, host_commands)) + """
252 Scheduler Commands:
253 """ + help_spacer.join(map(commandToHelp, scheduler_commands)) + """
255 Virtual Device Commands:
256 """ + help_spacer.join(map(commandToHelp, device_commands)) + """
258 Vnet commands:
259 """ + help_spacer.join(map(commandToHelp, vnet_commands)) + """
261 Access Control commands:
262 """ + help_spacer.join(map(commandToHelp, acm_commands)) + """
264 <DomName> can be substituted for <DomId> in xm subcommands.
266 For a short list of subcommands run 'xm help'
267 For more help on xm see the xm(1) man page
268 For more help on xm create, see the xmdomain.cfg(5) man page"""
270 # array for xm help <command>
271 help = {
272 "--long": longhelp
273 }
275 for command in all_commands:
276 # create is handled specially
277 if (command != 'create'):
278 help[command] = commandToHelp(command)
281 ####################################################################
282 #
283 # Utility functions
284 #
285 ####################################################################
287 def arg_check(args, name, lo, hi = -1):
288 n = len([i for i in args if i != '--'])
290 if hi == -1:
291 if n != lo:
292 err("'xm %s' requires %d argument%s.\n" % (name, lo,
293 lo > 1 and 's' or ''))
294 usage(name)
295 else:
296 if n < lo or n > hi:
297 err("'xm %s' requires between %d and %d arguments.\n" %
298 (name, lo, hi))
299 usage(name)
302 def unit(c):
303 if not c.isalpha():
304 return 0
305 base = 1
306 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
307 elif c == 'M' or c == 'm': base = 1024 * 1024
308 elif c == 'K' or c == 'k': base = 1024
309 else:
310 print 'ignoring unknown unit'
311 return base
313 def int_unit(str, dest):
314 base = unit(str[-1])
315 if not base:
316 return int(str)
318 value = int(str[:-1])
319 dst_base = unit(dest)
320 if dst_base == 0:
321 dst_base = 1
322 if dst_base > base:
323 return value / (dst_base / base)
324 else:
325 return value * (base / dst_base)
327 def err(msg):
328 print >>sys.stderr, "Error:", msg
331 #########################################################################
332 #
333 # Main xm functions
334 #
335 #########################################################################
337 def xm_save(args):
338 arg_check(args, "save", 2)
340 dom = args[0] # TODO: should check if this exists
341 savefile = os.path.abspath(args[1])
343 if not os.access(os.path.dirname(savefile), os.W_OK):
344 err("xm save: Unable to create file %s" % savefile)
345 sys.exit(1)
347 server.xend.domain.save(dom, savefile)
349 def xm_restore(args):
350 arg_check(args, "restore", 1)
352 savefile = os.path.abspath(args[0])
354 if not os.access(savefile, os.R_OK):
355 err("xm restore: Unable to read file %s" % savefile)
356 sys.exit(1)
358 server.xend.domain.restore(savefile)
361 def getDomains(domain_names):
362 if domain_names:
363 return map(server.xend.domain, domain_names)
364 else:
365 return server.xend.domains(1)
368 def xm_list(args):
369 use_long = 0
370 show_vcpus = 0
371 show_labels = 0
372 try:
373 (options, params) = getopt.gnu_getopt(args, 'lv', ['long','vcpus','label'])
374 except getopt.GetoptError, opterr:
375 err(opterr)
376 sys.exit(1)
378 for (k, v) in options:
379 if k in ['-l', '--long']:
380 use_long = 1
381 if k in ['-v', '--vcpus']:
382 show_vcpus = 1
383 if k in ['--label']:
384 show_labels = 1
386 if show_vcpus:
387 print >>sys.stderr, (
388 "xm list -v is deprecated. Please use xm vcpu-list.")
389 xm_vcpu_list(params)
390 return
392 doms = getDomains(params)
394 if use_long:
395 map(PrettyPrint.prettyprint, doms)
396 elif show_labels:
397 xm_label_list(doms)
398 else:
399 xm_brief_list(doms)
402 def parse_doms_info(info):
403 def get_info(n, t, d):
404 return t(sxp.child_value(info, n, d))
406 return {
407 'dom' : get_info('domid', int, -1),
408 'name' : get_info('name', str, '??'),
409 'mem' : get_info('memory', int, 0),
410 'vcpus' : get_info('online_vcpus', int, 0),
411 'state' : get_info('state', str, '??'),
412 'cpu_time' : get_info('cpu_time', float, 0),
413 'seclabel' : security.get_security_printlabel(info),
414 }
417 def parse_sedf_info(info):
418 def get_info(n, t, d):
419 return t(sxp.child_value(info, n, d))
421 return {
422 'dom' : get_info('domain', int, -1),
423 'period' : get_info('period', int, -1),
424 'slice' : get_info('slice', int, -1),
425 'latency' : get_info('latency', int, -1),
426 'extratime': get_info('extratime', int, -1),
427 'weight' : get_info('weight', int, -1),
428 }
431 def xm_brief_list(doms):
432 print 'Name ID Mem(MiB) VCPUs State Time(s)'
433 for dom in doms:
434 d = parse_doms_info(dom)
435 print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f" % d)
438 def xm_label_list(doms):
439 output = []
440 print 'Name ID Mem(MiB) VCPUs State Time(s) Label'
441 for dom in doms:
442 d = parse_doms_info(dom)
443 l = "%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f " % d
444 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
445 if d['seclabel']:
446 line = (l, d['seclabel'])
447 else:
448 line = (l, "ERROR")
449 elif security.active_policy in ['DEFAULT']:
450 line = (l, "DEFAULT")
451 else:
452 line = (l, "INACTIVE")
453 output.append(line)
454 #sort by labels
455 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
456 for l in output:
457 print l[0] + l[1]
460 def xm_vcpu_list(args):
462 if args:
463 dominfo = map(server.xend.domain.getVCPUInfo, args)
464 else:
465 doms = server.xend.domains(False)
466 dominfo = map(server.xend.domain.getVCPUInfo, doms)
468 print 'Name ID VCPU CPU State Time(s) CPU Affinity'
470 for dom in dominfo:
471 def get_info(n):
472 return sxp.child_value(dom, n)
474 #
475 # convert a list of integers into a list of pairs indicating
476 # continuous sequences in the list:
477 #
478 # [0,1,2,3] -> [(0,3)]
479 # [1,2,4,5] -> [(1,2),(4,5)]
480 # [0] -> [(0,0)]
481 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
482 #
483 def list_to_rangepairs(cmap):
484 cmap.sort()
485 pairs = []
486 x = y = 0
487 for i in range(0,len(cmap)):
488 try:
489 if ((cmap[y+1] - cmap[i]) > 1):
490 pairs.append((cmap[x],cmap[y]))
491 x = y = i+1
492 else:
493 y = y + 1
494 # if we go off the end, then just add x to y
495 except IndexError:
496 pairs.append((cmap[x],cmap[y]))
498 return pairs
500 #
501 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
502 #
503 def format_pairs(pairs):
504 if not pairs:
505 return "no cpus"
506 out = ""
507 for f,s in pairs:
508 if (f==s):
509 out += '%d'%f
510 else:
511 out += '%d-%d'%(f,s)
512 out += ','
513 # trim trailing ','
514 return out[:-1]
516 def format_cpumap(cpumap):
517 cpumap = map(lambda x: int(x), cpumap)
518 cpumap.sort()
520 for x in server.xend.node.info()[1:]:
521 if len(x) > 1 and x[0] == 'nr_cpus':
522 nr_cpus = int(x[1])
523 # normalize cpumap by modulus nr_cpus, and drop duplicates
524 cpumap = dict.fromkeys(
525 map(lambda x: x % nr_cpus, cpumap)).keys()
526 if len(cpumap) == nr_cpus:
527 return "any cpu"
528 break
530 return format_pairs(list_to_rangepairs(cpumap))
532 name = get_info('name')
533 domid = int(get_info('domid'))
535 for vcpu in sxp.children(dom, 'vcpu'):
536 def vinfo(n, t):
537 return t(sxp.child_value(vcpu, n))
539 number = vinfo('number', int)
540 cpu = vinfo('cpu', int)
541 cpumap = format_cpumap(vinfo('cpumap', list))
542 online = vinfo('online', int)
543 cpu_time = vinfo('cpu_time', float)
544 running = vinfo('running', int)
545 blocked = vinfo('blocked', int)
547 if online:
548 c = str(cpu)
549 if running:
550 s = 'r'
551 else:
552 s = '-'
553 if blocked:
554 s += 'b'
555 else:
556 s += '-'
557 s += '-'
558 else:
559 c = "-"
560 s = "--p"
562 print (
563 "%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
564 locals())
567 def xm_reboot(args):
568 arg_check(args, "reboot", 1, 3)
569 from xen.xm import shutdown
570 shutdown.main(["shutdown", "-R"] + args)
572 def xm_pause(args):
573 arg_check(args, "pause", 1)
574 dom = args[0]
576 server.xend.domain.pause(dom)
578 def xm_unpause(args):
579 arg_check(args, "unpause", 1)
580 dom = args[0]
582 server.xend.domain.unpause(dom)
584 def xm_rename(args):
585 arg_check(args, "rename", 2)
587 server.xend.domain.setName(args[0], args[1])
589 def xm_subcommand(command, args):
590 cmd = __import__(command, globals(), locals(), 'xen.xm')
591 cmd.main([command] + args)
594 #############################################################
596 def cpu_make_map(cpulist):
597 cpus = []
598 for c in cpulist.split(','):
599 if c.find('-') != -1:
600 (x,y) = c.split('-')
601 for i in range(int(x),int(y)+1):
602 cpus.append(int(i))
603 else:
604 cpus.append(int(c))
605 cpus.sort()
606 return cpus
608 def xm_vcpu_pin(args):
609 arg_check(args, "vcpu-pin", 3)
611 dom = args[0]
612 vcpu = int(args[1])
613 cpumap = cpu_make_map(args[2])
615 server.xend.domain.pincpu(dom, vcpu, cpumap)
617 def xm_mem_max(args):
618 arg_check(args, "mem-max", 2)
620 dom = args[0]
621 mem = int_unit(args[1], 'm')
623 server.xend.domain.maxmem_set(dom, mem)
625 def xm_mem_set(args):
626 arg_check(args, "mem-set", 2)
628 dom = args[0]
629 mem_target = int_unit(args[1], 'm')
631 server.xend.domain.setMemoryTarget(dom, mem_target)
633 def xm_vcpu_set(args):
634 arg_check(args, "vcpu-set", 2)
636 server.xend.domain.setVCpuCount(args[0], int(args[1]))
639 def xm_destroy(args):
640 arg_check(args, "destroy", 1)
641 server.xend.domain.destroy(args[0])
644 def xm_domid(args):
645 arg_check(args, "domid", 1)
647 name = args[0]
649 dom = server.xend.domain(name)
650 print sxp.child_value(dom, 'domid')
652 def xm_domname(args):
653 arg_check(args, "domname", 1)
655 name = args[0]
657 dom = server.xend.domain(name)
658 print sxp.child_value(dom, 'name')
660 def xm_sched_bvt(args):
661 arg_check(args, "sched-bvt", 6)
662 dom = args[0]
663 v = map(long, args[1:6])
664 server.xend.domain.cpu_bvt_set(dom, *v)
666 def xm_sched_bvt_ctxallow(args):
667 arg_check(args, "sched-bvt-ctxallow", 1)
669 slice = int(args[0])
670 server.xend.node.cpu_bvt_slice_set(slice)
672 def xm_sched_sedf(args):
673 def ns_to_ms(val):
674 return float(val) * 0.000001
676 def ms_to_ns(val):
677 return (float(val) / 0.000001)
679 def print_sedf(info):
680 info['period'] = ns_to_ms(info['period'])
681 info['slice'] = ns_to_ms(info['slice'])
682 info['latency'] = ns_to_ms(info['latency'])
683 print( ("%(name)-32s %(dom)3d %(period)9.1f %(slice)9.1f" +
684 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
686 def domid_match(domid, info):
687 return domid is None or domid == info['name'] or domid == str(info['dom'])
689 # we want to just display current info if no parameters are passed
690 if len(args) == 0:
691 domid = None
692 else:
693 # we expect at least a domain id (name or number)
694 # and at most a domid up to 5 options with values
695 arg_check(args, "sched-sedf", 1, 11)
696 domid = args[0]
697 # drop domid from args since get_opt doesn't recognize it
698 args = args[1:]
700 opts = {}
701 try:
702 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
703 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
704 except getopt.GetoptError, opterr:
705 err(opterr)
706 sys.exit(1)
708 # convert to nanoseconds if needed
709 for (k, v) in options:
710 if k in ['-p', '--period']:
711 opts['period'] = ms_to_ns(v)
712 elif k in ['-s', '--slice']:
713 opts['slice'] = ms_to_ns(v)
714 elif k in ['-l', '--latency']:
715 opts['latency'] = ms_to_ns(v)
716 elif k in ['-e', '--extratime']:
717 opts['extratime'] = v
718 elif k in ['-w', '--weight']:
719 opts['weight'] = v
721 # print header if we aren't setting any parameters
722 if len(opts.keys()) == 0:
723 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s'%('Name','ID','Period(ms)',
724 'Slice(ms)', 'Lat(ms)',
725 'Extra','Weight')
727 doms = filter(lambda x : domid_match(domid, x),
728 [parse_doms_info(dom) for dom in getDomains("")])
729 for d in doms:
730 # fetch current values so as not to clobber them
731 sedf_info = \
732 parse_sedf_info(server.xend.domain.cpu_sedf_get(d['dom']))
733 sedf_info['name'] = d['name']
735 # update values in case of call to set
736 if len(opts.keys()) > 0:
737 for k in opts.keys():
738 sedf_info[k]=opts[k]
740 # send the update, converting user input
741 v = map(int, [sedf_info['period'], sedf_info['slice'],
742 sedf_info['latency'],sedf_info['extratime'],
743 sedf_info['weight']])
744 rv = server.xend.domain.cpu_sedf_set(d['dom'], *v)
745 if int(rv) != 0:
746 err("Failed to set sedf parameters (rv=%d)."%(rv))
748 # not setting values, display info
749 else:
750 print_sedf(sedf_info)
752 def xm_sched_credit(args):
753 usage_msg = """sched-credit: Set or get credit scheduler parameters
754 Usage:
756 sched-credit -d domain [-w weight] [-c cap]
757 """
758 try:
759 opts, args = getopt.getopt(args[0:], "d:w:c:",
760 ["domain=", "weight=", "cap="])
761 except getopt.GetoptError:
762 # print help information and exit:
763 print usage_msg
764 sys.exit(1)
766 domain = None
767 weight = None
768 cap = None
770 for o, a in opts:
771 if o == "-d":
772 domain = a
773 elif o == "-w":
774 weight = int(a)
775 elif o == "-c":
776 cap = int(a);
778 if domain is None:
779 # place holder for system-wide scheduler parameters
780 print usage_msg
781 sys.exit(1)
783 if weight is None and cap is None:
784 print server.xend.domain.sched_credit_get(domain)
785 else:
786 if weight is None:
787 weight = int(0)
788 if cap is None:
789 cap = int(~0)
791 err = server.xend.domain.sched_credit_set(domain, weight, cap)
792 if err != 0:
793 print err
795 def xm_info(args):
796 arg_check(args, "info", 0)
798 info = server.xend.node.info()
800 for x in info[1:]:
801 if len(x) < 2:
802 print "%-23s: (none)" % x[0]
803 else:
804 print "%-23s:" % x[0], x[1]
806 def xm_console(args):
807 arg_check(args, "console", 1)
809 dom = args[0]
810 info = server.xend.domain(dom)
811 domid = int(sxp.child_value(info, 'domid', '-1'))
812 console.execConsole(domid)
815 def xm_top(args):
816 arg_check(args, "top", 0)
818 os.execvp('xentop', ['xentop'])
820 def xm_dmesg(args):
821 arg_check(args, "dmesg", 0, 1)
823 gopts = Opts(use="""[-c|--clear]
825 Read Xen's message buffer (boot output, warning and error messages) or clear
826 its contents if the [-c|--clear] flag is specified.
827 """)
829 gopts.opt('clear', short='c',
830 fn=set_true, default=0,
831 use="Clear the contents of the Xen message buffer.")
832 # Work around for gopts
833 myargs = args
834 myargs.insert(0, 'dmesg')
835 gopts.parse(myargs)
836 if not (1 <= len(myargs) <= 2):
837 err('Invalid arguments: ' + str(myargs))
839 if not gopts.vals.clear:
840 print server.xend.node.dmesg.info()
841 else:
842 server.xend.node.dmesg.clear()
844 def xm_log(args):
845 arg_check(args, "log", 0)
847 print server.xend.node.log()
849 def xm_serve(args):
850 arg_check(args, "serve", 0)
852 from fcntl import fcntl, F_SETFL
854 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
855 s.connect(xen.xend.XendClient.XML_RPC_SOCKET)
856 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
858 while True:
859 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
860 if s in iwtd:
861 data = s.recv(4096)
862 if len(data) > 0:
863 sys.stdout.write(data)
864 sys.stdout.flush()
865 else:
866 break
867 if sys.stdin in iwtd:
868 data = sys.stdin.read(4096)
869 if len(data) > 0:
870 s.sendall(data)
871 else:
872 break
873 s.close()
875 def parse_dev_info(info):
876 def get_info(n, t, d):
877 i = 0
878 while i < len(info):
879 if (info[i][0] == n):
880 return t(info[i][1])
881 i = i + 1
882 return t(d)
883 return {
884 #common
885 'backend-id' : get_info('backend-id', int, -1),
886 'handle' : get_info('handle', int, 0),
887 'state' : get_info('state', int, -1),
888 'be-path' : get_info('backend', str, '??'),
889 'event-ch' : get_info('event-channel',int, -1),
890 #network specific
891 'virtual-device' : get_info('virtual-device', str, '??'),
892 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
893 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
894 'mac' : get_info('mac', str, '??'),
895 #block-device specific
896 'ring-ref' : get_info('ring-ref', int, -1),
897 }
899 def arg_check_for_resource_list(args, name):
900 use_long = 0
901 try:
902 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
903 except getopt.GetoptError, opterr:
904 err(opterr)
905 sys.exit(1)
907 for (k, v) in options:
908 if k in ['-l', '--long']:
909 use_long = 1
911 if len(params) == 0:
912 print 'No domain parameter given'
913 usage(name)
914 if len(params) > 1:
915 print 'No multiple domain parameters allowed'
916 usage(name)
918 return (use_long, params)
920 def xm_network_list(args):
921 (use_long, params) = arg_check_for_resource_list(args, "network-list")
923 dom = params[0]
924 if use_long:
925 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
926 map(PrettyPrint.prettyprint, devs)
927 else:
928 hdr = 0
929 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
930 if hdr == 0:
931 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
932 hdr = 1
933 ni = parse_dev_info(x[1])
934 ni['idx'] = int(x[0])
935 print ("%(idx)-3d "
936 "%(backend-id)-3d"
937 "%(mac)-17s "
938 "%(handle)-3d "
939 "%(state)-3d "
940 "%(event-ch)-3d "
941 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
942 "%(be-path)-30s "
943 % ni)
945 def xm_block_list(args):
946 (use_long, params) = arg_check_for_resource_list(args, "block-list")
948 dom = params[0]
949 if use_long:
950 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
951 map(PrettyPrint.prettyprint, devs)
952 else:
953 hdr = 0
954 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
955 if hdr == 0:
956 print 'Vdev BE handle state evt-ch ring-ref BE-path'
957 hdr = 1
958 ni = parse_dev_info(x[1])
959 ni['idx'] = int(x[0])
960 print ("%(idx)-3d "
961 "%(backend-id)-3d "
962 "%(handle)-3d "
963 "%(state)-3d "
964 "%(event-ch)-3d "
965 "%(ring-ref)-5d "
966 "%(be-path)-30s "
967 % ni)
969 def xm_vtpm_list(args):
970 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
972 dom = params[0]
973 if use_long:
974 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
975 map(PrettyPrint.prettyprint, devs)
976 else:
977 hdr = 0
978 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
979 if hdr == 0:
980 print 'Idx BE handle state evt-ch ring-ref BE-path'
981 hdr = 1
982 ni = parse_dev_info(x[1])
983 ni['idx'] = int(x[0])
984 print ("%(idx)-3d "
985 "%(backend-id)-3d "
986 "%(handle)-3d "
987 "%(state)-3d "
988 "%(event-ch)-3d "
989 "%(ring-ref)-5d "
990 "%(be-path)-30s "
991 % ni)
993 def xm_block_attach(args):
994 arg_check(args, 'block-attach', 4, 5)
996 dom = args[0]
998 if args[1].startswith('tap:'):
999 cls = 'tap'
1000 else:
1001 cls = 'vbd'
1003 vbd = [cls,
1004 ['uname', args[1]],
1005 ['dev', args[2]],
1006 ['mode', args[3]]]
1007 if len(args) == 5:
1008 vbd.append(['backend', args[4]])
1010 # verify that policy permits attaching this resource
1011 try:
1012 if security.on():
1013 dominfo = server.xend.domain(dom)
1014 label = security.get_security_printlabel(dominfo)
1015 else:
1016 label = None
1017 security.res_security_check(args[1], label)
1018 except security.ACMError, e:
1019 print e.value
1020 sys.exit(1)
1021 except:
1022 traceback.print_exc(limit=1)
1023 sys.exit(1)
1025 server.xend.domain.device_create(dom, vbd)
1028 def xm_network_attach(args):
1029 arg_check(args, 'network-attach', 1, 10000)
1031 dom = args[0]
1032 vif = ['vif']
1034 for a in args[1:]:
1035 vif.append(a.split("="))
1037 server.xend.domain.device_create(dom, vif)
1040 def detach(args, command, deviceClass):
1041 arg_check(args, command, 2)
1043 dom = args[0]
1044 dev = args[1]
1046 server.xend.domain.destroyDevice(dom, deviceClass, dev)
1049 def xm_block_detach(args):
1050 detach(args, 'block-detach', 'vbd')
1053 def xm_network_detach(args):
1054 detach(args, 'network-detach', 'vif')
1057 def xm_vnet_list(args):
1058 try:
1059 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1060 except getopt.GetoptError, opterr:
1061 err(opterr)
1062 sys.exit(1)
1064 use_long = 0
1065 for (k, v) in options:
1066 if k in ['-l', '--long']:
1067 use_long = 1
1069 if params:
1070 use_long = 1
1071 vnets = params
1072 else:
1073 vnets = server.xend_vnets()
1075 for vnet in vnets:
1076 try:
1077 if use_long:
1078 info = server.xend_vnet(vnet)
1079 PrettyPrint.prettyprint(info)
1080 else:
1081 print vnet
1082 except Exception, ex:
1083 print vnet, ex
1085 def xm_vnet_create(args):
1086 arg_check(args, "vnet-create", 1)
1087 conf = args[0]
1088 if not os.access(conf, os.R_OK):
1089 print "File not found: %s" % conf
1090 sys.exit(1)
1092 server.xend_vnet_create(conf)
1094 def xm_vnet_delete(args):
1095 arg_check(args, "vnet-delete", 1)
1096 vnet = args[0]
1097 server.xend_vnet_delete(vnet)
1099 commands = {
1100 # console commands
1101 "console": xm_console,
1102 # xenstat commands
1103 "top": xm_top,
1104 # domain commands
1105 "destroy": xm_destroy,
1106 "domid": xm_domid,
1107 "domname": xm_domname,
1108 "rename": xm_rename,
1109 "restore": xm_restore,
1110 "save": xm_save,
1111 "reboot": xm_reboot,
1112 "list": xm_list,
1113 # memory commands
1114 "mem-max": xm_mem_max,
1115 "mem-set": xm_mem_set,
1116 # cpu commands
1117 "vcpu-pin": xm_vcpu_pin,
1118 "vcpu-list": xm_vcpu_list,
1119 "vcpu-set": xm_vcpu_set,
1120 # special
1121 "pause": xm_pause,
1122 "unpause": xm_unpause,
1123 # host commands
1124 "dmesg": xm_dmesg,
1125 "info": xm_info,
1126 "log": xm_log,
1127 "serve": xm_serve,
1128 # scheduler
1129 "sched-bvt": xm_sched_bvt,
1130 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
1131 "sched-sedf": xm_sched_sedf,
1132 "sched-credit": xm_sched_credit,
1133 # block
1134 "block-attach": xm_block_attach,
1135 "block-detach": xm_block_detach,
1136 "block-list": xm_block_list,
1137 # network
1138 "network-attach": xm_network_attach,
1139 "network-detach": xm_network_detach,
1140 "network-list": xm_network_list,
1141 # vnet
1142 "vnet-list": xm_vnet_list,
1143 "vnet-create": xm_vnet_create,
1144 "vnet-delete": xm_vnet_delete,
1145 # vtpm
1146 "vtpm-list": xm_vtpm_list,
1149 ## The commands supported by a separate argument parser in xend.xm.
1150 subcommands = [
1151 'create',
1152 'migrate',
1153 'sysrq',
1154 'shutdown',
1155 'labels',
1156 'addlabel',
1157 'rmlabel',
1158 'getlabel',
1159 'dry-run',
1160 'resources',
1161 'cfgbootpolicy',
1162 'makepolicy',
1163 'loadpolicy',
1164 'dumppolicy'
1167 for c in subcommands:
1168 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
1170 aliases = {
1171 "balloon": "mem-set",
1172 "set-vcpus": "vcpu-set",
1173 "vif-list": "network-list",
1174 "vbd-create": "block-attach",
1175 "vbd-destroy": "block-detach",
1176 "vbd-list": "block-list",
1180 def xm_lookup_cmd(cmd):
1181 if commands.has_key(cmd):
1182 return commands[cmd]
1183 elif aliases.has_key(cmd):
1184 deprecated(cmd,aliases[cmd])
1185 return commands[aliases[cmd]]
1186 else:
1187 if len( cmd ) > 1:
1188 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
1189 if len( matched_commands ) == 1:
1190 return matched_commands[0][1]
1191 err('Sub Command %s not found!' % cmd)
1192 usage()
1194 def deprecated(old,new):
1195 print >>sys.stderr, (
1196 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1198 def usage(cmd=None):
1199 if cmd == 'create':
1200 mycmd = xm_lookup_cmd(cmd)
1201 mycmd( ['--help'] )
1202 sys.exit(1)
1203 if help.has_key(cmd):
1204 print " " + help[cmd]
1205 else:
1206 print shorthelp
1207 sys.exit(1)
1209 def main(argv=sys.argv):
1210 if len(argv) < 2:
1211 usage()
1213 if re.compile('-*help').match(argv[1]):
1214 if len(argv) > 2:
1215 usage(argv[2])
1216 else:
1217 usage()
1218 sys.exit(0)
1220 cmd = xm_lookup_cmd(argv[1])
1222 # strip off prog name and subcmd
1223 args = argv[2:]
1224 if cmd:
1225 try:
1226 rc = cmd(args)
1227 if rc:
1228 usage()
1229 except socket.error, ex:
1230 if os.geteuid() != 0:
1231 err("Most commands need root access. Please try again as root.")
1232 else:
1233 err("Error connecting to xend: %s. Is xend running?" % ex[1])
1234 sys.exit(1)
1235 except KeyboardInterrupt:
1236 print "Interrupted."
1237 sys.exit(1)
1238 except IOError, ex:
1239 if os.geteuid() != 0:
1240 err("Most commands need root access. Please try again as root.")
1241 else:
1242 err("Error connecting to xend: %s." % ex[1])
1243 sys.exit(1)
1244 except SystemExit:
1245 sys.exit(1)
1246 except xmlrpclib.Fault, ex:
1247 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1248 print >>sys.stderr, (
1249 "Error: the domain '%s' does not exist." % ex.faultString)
1250 else:
1251 print >>sys.stderr, "Error: %s" % ex.faultString
1252 sys.exit(1)
1253 except (ValueError, OverflowError):
1254 err("Invalid argument.")
1255 usage(argv[1])
1256 except:
1257 print "Unexpected error:", sys.exc_info()[0]
1258 print
1259 print "Please report to xen-devel@lists.xensource.com"
1260 raise
1262 else:
1263 usage()
1265 if __name__ == "__main__":
1266 main()