ia64/xen-unstable

view tools/python/xen/xm/main.py @ 10919:aa1ab056bfbf

Clarify the use of vcpu-set. Closes bug #686.

Signed-off-by Harry Butterworth <butterwo@uk.ibm.com>
author emellor@leeni.uk.xensource.com
date Wed Aug 02 17:42:38 2006 +0100 (2006-08-02)
parents 7e25295d8d9d
children 58a04bfedf6b
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 active VCPUs for a domain
82 within the range allowed by the domain
83 configuration"""
84 vcpu_list_help = "vcpu-list <DomId> List the VCPUs for a domain (or all domains)"
85 vcpu_pin_help = "vcpu-pin <DomId> <VCPU> <CPUs> Set which cpus a VCPU can use"
86 dmesg_help = "dmesg [-c|--clear] Read or clear Xen's message buffer"
87 info_help = "info Get information about the xen host"
88 rename_help = "rename <DomId> <New Name> Rename a domain"
89 log_help = "log Print the xend log"
90 sched_bvt_help = """sched-bvt <Parameters> Set Borrowed Virtual Time scheduler
91 parameters"""
92 sched_bvt_ctxallow_help = """sched-bvt-ctxallow <Allow> Set the BVT scheduler context switch
93 allowance"""
94 sched_sedf_help = "sched-sedf [DOM] [OPTIONS] Show|Set simple EDF parameters\n" + \
95 " -p, --period Relative deadline(ms).\n\
96 -s, --slice Worst-case execution time(ms)\n\
97 (slice < period).\n\
98 -l, --latency scaled period(ms) in case the domain\n\
99 is doing heavy I/O.\n\
100 -e, --extra flag (0/1) which controls whether the\n\
101 domain can run in extra-time\n\
102 -w, --weight mutually exclusive with period/slice and\n\
103 specifies another way of setting a domain's\n\
104 cpu period/slice."
106 sched_credit_help = "sched-credit Set or get credit scheduler parameters"
107 block_attach_help = """block-attach <DomId> <BackDev> <FrontDev> <Mode>
108 [BackDomId] Create a new virtual block device"""
109 block_detach_help = """block-detach <DomId> <DevId> Destroy a domain's virtual block device,
110 where <DevId> may either be the device ID
111 or the device name as mounted in the guest"""
113 block_list_help = "block-list <DomId> [--long] List virtual block devices for a domain"
114 network_attach_help = """network-attach <DomID> [script=<script>] [ip=<ip>] [mac=<mac>]
115 [bridge=<bridge>] [backend=<backDomID>]
116 Create a new virtual network device """
117 network_detach_help = """network-detach <DomId> <DevId> Destroy a domain's virtual network
118 device, where <DevId> is the device ID."""
120 network_list_help = "network-list <DomId> [--long] List virtual network interfaces for a domain"
121 vnet_list_help = "vnet-list [-l|--long] list vnets"
122 vnet_create_help = "vnet-create <config> create a vnet from a config file"
123 vnet_delete_help = "vnet-delete <vnetid> delete a vnet"
124 vtpm_list_help = "vtpm-list <DomId> [--long] list virtual TPM devices"
125 addlabel_help = "addlabel <label> dom <configfile> Add security label to domain\n <label> res <resource> or resource"
126 rmlabel_help = "rmlabel dom <configfile> Remove security label from domain\n res <resource> or resource"
127 getlabel_help = "getlabel dom <configfile> Show security label for domain\n res <resource> or resource"
128 dry_run_help = "dry-run <configfile> Tests if domain can access its resources"
129 resources_help = "resources Show info for each labeled resource"
130 cfgbootpolicy_help = "cfgbootpolicy <policy> Add policy to boot configuration "
131 dumppolicy_help = "dumppolicy Print hypervisor ACM state information"
132 loadpolicy_help = "loadpolicy <policy> Load binary policy into hypervisor"
133 makepolicy_help = "makepolicy <policy> Build policy and create .bin/.map files"
134 labels_help = "labels [policy] [type=DOM|..] List <type> labels for (active) policy."
135 serve_help = "serve Proxy Xend XML-RPC over stdio"
137 short_command_list = [
138 "console",
139 "create",
140 "destroy",
141 "help",
142 "list",
143 "mem-set",
144 "migrate",
145 "pause",
146 "reboot",
147 "restore",
148 "save",
149 "shutdown",
150 "top",
151 "unpause",
152 "vcpu-set",
153 ]
155 domain_commands = [
156 "console",
157 "create",
158 "destroy",
159 "domid",
160 "domname",
161 "list",
162 "list_label",
163 "mem-max",
164 "mem-set",
165 "migrate",
166 "pause",
167 "reboot",
168 "rename",
169 "restore",
170 "save",
171 "shutdown",
172 "sysrq",
173 "top",
174 "unpause",
175 "vcpu-list",
176 "vcpu-pin",
177 "vcpu-set",
178 ]
180 host_commands = [
181 "dmesg",
182 "info",
183 "log",
184 "serve",
185 ]
187 scheduler_commands = [
188 "sched-credit",
189 "sched-bvt",
190 "sched-bvt-ctxallow",
191 "sched-sedf",
192 ]
194 device_commands = [
195 "block-attach",
196 "block-detach",
197 "block-list",
198 "network-attach",
199 "network-detach",
200 "network-list",
201 "vtpm-list",
202 ]
204 vnet_commands = [
205 "vnet-list",
206 "vnet-create",
207 "vnet-delete",
208 ]
210 acm_commands = [
211 "labels",
212 "addlabel",
213 "rmlabel",
214 "getlabel",
215 "dry-run",
216 "resources",
217 "makepolicy",
218 "loadpolicy",
219 "cfgbootpolicy",
220 "dumppolicy"
221 ]
223 all_commands = (domain_commands + host_commands + scheduler_commands +
224 device_commands + vnet_commands + acm_commands)
227 def commandToHelp(cmd):
228 return eval(cmd.replace("-", "_") + "_help")
231 shorthelp = """Usage: xm <subcommand> [args]
232 Control, list, and manipulate Xen guest instances
234 xm common subcommands:
235 """ + help_spacer.join(map(commandToHelp, short_command_list)) + """
237 <DomName> can be substituted for <DomId> in xm subcommands.
239 For a complete list of subcommands run 'xm help --long'
240 For more help on xm see the xm(1) man page
241 For more help on xm create, see the xmdomain.cfg(5) man page"""
243 longhelp = """Usage: xm <subcommand> [args]
244 Control, list, and manipulate Xen guest instances
246 xm full list of subcommands:
248 Domain Commands:
249 """ + help_spacer.join(map(commandToHelp, domain_commands)) + """
251 Xen Host Commands:
252 """ + help_spacer.join(map(commandToHelp, host_commands)) + """
254 Scheduler Commands:
255 """ + help_spacer.join(map(commandToHelp, scheduler_commands)) + """
257 Virtual Device Commands:
258 """ + help_spacer.join(map(commandToHelp, device_commands)) + """
260 Vnet commands:
261 """ + help_spacer.join(map(commandToHelp, vnet_commands)) + """
263 Access Control commands:
264 """ + help_spacer.join(map(commandToHelp, acm_commands)) + """
266 <DomName> can be substituted for <DomId> in xm subcommands.
268 For a short list of subcommands run 'xm help'
269 For more help on xm see the xm(1) man page
270 For more help on xm create, see the xmdomain.cfg(5) man page"""
272 # array for xm help <command>
273 help = {
274 "--long": longhelp
275 }
277 for command in all_commands:
278 # create is handled specially
279 if (command != 'create'):
280 help[command] = commandToHelp(command)
283 ####################################################################
284 #
285 # Utility functions
286 #
287 ####################################################################
289 def arg_check(args, name, lo, hi = -1):
290 n = len([i for i in args if i != '--'])
292 if hi == -1:
293 if n != lo:
294 err("'xm %s' requires %d argument%s.\n" % (name, lo,
295 lo > 1 and 's' or ''))
296 usage(name)
297 else:
298 if n < lo or n > hi:
299 err("'xm %s' requires between %d and %d arguments.\n" %
300 (name, lo, hi))
301 usage(name)
304 def unit(c):
305 if not c.isalpha():
306 return 0
307 base = 1
308 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
309 elif c == 'M' or c == 'm': base = 1024 * 1024
310 elif c == 'K' or c == 'k': base = 1024
311 else:
312 print 'ignoring unknown unit'
313 return base
315 def int_unit(str, dest):
316 base = unit(str[-1])
317 if not base:
318 return int(str)
320 value = int(str[:-1])
321 dst_base = unit(dest)
322 if dst_base == 0:
323 dst_base = 1
324 if dst_base > base:
325 return value / (dst_base / base)
326 else:
327 return value * (base / dst_base)
329 def err(msg):
330 print >>sys.stderr, "Error:", msg
333 #########################################################################
334 #
335 # Main xm functions
336 #
337 #########################################################################
339 def xm_save(args):
340 arg_check(args, "save", 2)
342 dom = args[0] # TODO: should check if this exists
343 savefile = os.path.abspath(args[1])
345 if not os.access(os.path.dirname(savefile), os.W_OK):
346 err("xm save: Unable to create file %s" % savefile)
347 sys.exit(1)
349 server.xend.domain.save(dom, savefile)
351 def xm_restore(args):
352 arg_check(args, "restore", 1)
354 savefile = os.path.abspath(args[0])
356 if not os.access(savefile, os.R_OK):
357 err("xm restore: Unable to read file %s" % savefile)
358 sys.exit(1)
360 server.xend.domain.restore(savefile)
363 def getDomains(domain_names):
364 if domain_names:
365 return map(server.xend.domain, domain_names)
366 else:
367 return server.xend.domains(1)
370 def xm_list(args):
371 use_long = 0
372 show_vcpus = 0
373 show_labels = 0
374 try:
375 (options, params) = getopt.gnu_getopt(args, 'lv', ['long','vcpus','label'])
376 except getopt.GetoptError, opterr:
377 err(opterr)
378 sys.exit(1)
380 for (k, v) in options:
381 if k in ['-l', '--long']:
382 use_long = 1
383 if k in ['-v', '--vcpus']:
384 show_vcpus = 1
385 if k in ['--label']:
386 show_labels = 1
388 if show_vcpus:
389 print >>sys.stderr, (
390 "xm list -v is deprecated. Please use xm vcpu-list.")
391 xm_vcpu_list(params)
392 return
394 doms = getDomains(params)
396 if use_long:
397 map(PrettyPrint.prettyprint, doms)
398 elif show_labels:
399 xm_label_list(doms)
400 else:
401 xm_brief_list(doms)
404 def parse_doms_info(info):
405 def get_info(n, t, d):
406 return t(sxp.child_value(info, n, d))
408 return {
409 'dom' : get_info('domid', int, -1),
410 'name' : get_info('name', str, '??'),
411 'mem' : get_info('memory', int, 0),
412 'vcpus' : get_info('online_vcpus', int, 0),
413 'state' : get_info('state', str, '??'),
414 'cpu_time' : get_info('cpu_time', float, 0),
415 'seclabel' : security.get_security_printlabel(info),
416 }
419 def parse_sedf_info(info):
420 def get_info(n, t, d):
421 return t(sxp.child_value(info, n, d))
423 return {
424 'dom' : get_info('domain', int, -1),
425 'period' : get_info('period', int, -1),
426 'slice' : get_info('slice', int, -1),
427 'latency' : get_info('latency', int, -1),
428 'extratime': get_info('extratime', int, -1),
429 'weight' : get_info('weight', int, -1),
430 }
433 def xm_brief_list(doms):
434 print 'Name ID Mem(MiB) VCPUs State Time(s)'
435 for dom in doms:
436 d = parse_doms_info(dom)
437 print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f" % d)
440 def xm_label_list(doms):
441 output = []
442 print 'Name ID Mem(MiB) VCPUs State Time(s) Label'
443 for dom in doms:
444 d = parse_doms_info(dom)
445 l = "%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f " % d
446 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
447 if d['seclabel']:
448 line = (l, d['seclabel'])
449 else:
450 line = (l, "ERROR")
451 elif security.active_policy in ['DEFAULT']:
452 line = (l, "DEFAULT")
453 else:
454 line = (l, "INACTIVE")
455 output.append(line)
456 #sort by labels
457 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
458 for l in output:
459 print l[0] + l[1]
462 def xm_vcpu_list(args):
464 if args:
465 dominfo = map(server.xend.domain.getVCPUInfo, args)
466 else:
467 doms = server.xend.domains(False)
468 dominfo = map(server.xend.domain.getVCPUInfo, doms)
470 print 'Name ID VCPU CPU State Time(s) CPU Affinity'
472 for dom in dominfo:
473 def get_info(n):
474 return sxp.child_value(dom, n)
476 #
477 # convert a list of integers into a list of pairs indicating
478 # continuous sequences in the list:
479 #
480 # [0,1,2,3] -> [(0,3)]
481 # [1,2,4,5] -> [(1,2),(4,5)]
482 # [0] -> [(0,0)]
483 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
484 #
485 def list_to_rangepairs(cmap):
486 cmap.sort()
487 pairs = []
488 x = y = 0
489 for i in range(0,len(cmap)):
490 try:
491 if ((cmap[y+1] - cmap[i]) > 1):
492 pairs.append((cmap[x],cmap[y]))
493 x = y = i+1
494 else:
495 y = y + 1
496 # if we go off the end, then just add x to y
497 except IndexError:
498 pairs.append((cmap[x],cmap[y]))
500 return pairs
502 #
503 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
504 #
505 def format_pairs(pairs):
506 if not pairs:
507 return "no cpus"
508 out = ""
509 for f,s in pairs:
510 if (f==s):
511 out += '%d'%f
512 else:
513 out += '%d-%d'%(f,s)
514 out += ','
515 # trim trailing ','
516 return out[:-1]
518 def format_cpumap(cpumap):
519 cpumap = map(lambda x: int(x), cpumap)
520 cpumap.sort()
522 for x in server.xend.node.info()[1:]:
523 if len(x) > 1 and x[0] == 'nr_cpus':
524 nr_cpus = int(x[1])
525 # normalize cpumap by modulus nr_cpus, and drop duplicates
526 cpumap = dict.fromkeys(
527 map(lambda x: x % nr_cpus, cpumap)).keys()
528 if len(cpumap) == nr_cpus:
529 return "any cpu"
530 break
532 return format_pairs(list_to_rangepairs(cpumap))
534 name = get_info('name')
535 domid = int(get_info('domid'))
537 for vcpu in sxp.children(dom, 'vcpu'):
538 def vinfo(n, t):
539 return t(sxp.child_value(vcpu, n))
541 number = vinfo('number', int)
542 cpu = vinfo('cpu', int)
543 cpumap = format_cpumap(vinfo('cpumap', list))
544 online = vinfo('online', int)
545 cpu_time = vinfo('cpu_time', float)
546 running = vinfo('running', int)
547 blocked = vinfo('blocked', int)
549 if online:
550 c = str(cpu)
551 if running:
552 s = 'r'
553 else:
554 s = '-'
555 if blocked:
556 s += 'b'
557 else:
558 s += '-'
559 s += '-'
560 else:
561 c = "-"
562 s = "--p"
564 print (
565 "%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
566 locals())
569 def xm_reboot(args):
570 arg_check(args, "reboot", 1, 3)
571 from xen.xm import shutdown
572 shutdown.main(["shutdown", "-R"] + args)
574 def xm_shutdown(args):
575 arg_check(args, "shutdown", 1, 4)
576 from xen.xm import shutdown
577 shutdown.main(["shutdown"] + args)
579 def xm_pause(args):
580 arg_check(args, "pause", 1)
581 dom = args[0]
583 server.xend.domain.pause(dom)
585 def xm_unpause(args):
586 arg_check(args, "unpause", 1)
587 dom = args[0]
589 server.xend.domain.unpause(dom)
591 def xm_rename(args):
592 arg_check(args, "rename", 2)
594 server.xend.domain.setName(args[0], args[1])
596 def xm_subcommand(command, args):
597 cmd = __import__(command, globals(), locals(), 'xen.xm')
598 cmd.main([command] + args)
601 #############################################################
603 def cpu_make_map(cpulist):
604 cpus = []
605 for c in cpulist.split(','):
606 if c.find('-') != -1:
607 (x,y) = c.split('-')
608 for i in range(int(x),int(y)+1):
609 cpus.append(int(i))
610 else:
611 cpus.append(int(c))
612 cpus.sort()
613 return cpus
615 def xm_vcpu_pin(args):
616 arg_check(args, "vcpu-pin", 3)
618 dom = args[0]
619 vcpu = int(args[1])
620 cpumap = cpu_make_map(args[2])
622 server.xend.domain.pincpu(dom, vcpu, cpumap)
624 def xm_mem_max(args):
625 arg_check(args, "mem-max", 2)
627 dom = args[0]
628 mem = int_unit(args[1], 'm')
630 server.xend.domain.maxmem_set(dom, mem)
632 def xm_mem_set(args):
633 arg_check(args, "mem-set", 2)
635 dom = args[0]
636 mem_target = int_unit(args[1], 'm')
638 server.xend.domain.setMemoryTarget(dom, mem_target)
640 def xm_vcpu_set(args):
641 arg_check(args, "vcpu-set", 2)
643 server.xend.domain.setVCpuCount(args[0], int(args[1]))
646 def xm_destroy(args):
647 arg_check(args, "destroy", 1)
648 server.xend.domain.destroy(args[0])
651 def xm_domid(args):
652 arg_check(args, "domid", 1)
654 name = args[0]
656 dom = server.xend.domain(name)
657 print sxp.child_value(dom, 'domid')
659 def xm_domname(args):
660 arg_check(args, "domname", 1)
662 name = args[0]
664 dom = server.xend.domain(name)
665 print sxp.child_value(dom, 'name')
667 def xm_sched_bvt(args):
668 arg_check(args, "sched-bvt", 6)
669 dom = args[0]
670 v = map(long, args[1:6])
671 server.xend.domain.cpu_bvt_set(dom, *v)
673 def xm_sched_bvt_ctxallow(args):
674 arg_check(args, "sched-bvt-ctxallow", 1)
676 slice = int(args[0])
677 server.xend.node.cpu_bvt_slice_set(slice)
679 def xm_sched_sedf(args):
680 def ns_to_ms(val):
681 return float(val) * 0.000001
683 def ms_to_ns(val):
684 return (float(val) / 0.000001)
686 def print_sedf(info):
687 info['period'] = ns_to_ms(info['period'])
688 info['slice'] = ns_to_ms(info['slice'])
689 info['latency'] = ns_to_ms(info['latency'])
690 print( ("%(name)-32s %(dom)3d %(period)9.1f %(slice)9.1f" +
691 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
693 def domid_match(domid, info):
694 return domid is None or domid == info['name'] or domid == str(info['dom'])
696 # we want to just display current info if no parameters are passed
697 if len(args) == 0:
698 domid = None
699 else:
700 # we expect at least a domain id (name or number)
701 # and at most a domid up to 5 options with values
702 arg_check(args, "sched-sedf", 1, 11)
703 domid = args[0]
704 # drop domid from args since get_opt doesn't recognize it
705 args = args[1:]
707 opts = {}
708 try:
709 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
710 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
711 except getopt.GetoptError, opterr:
712 err(opterr)
713 sys.exit(1)
715 # convert to nanoseconds if needed
716 for (k, v) in options:
717 if k in ['-p', '--period']:
718 opts['period'] = ms_to_ns(v)
719 elif k in ['-s', '--slice']:
720 opts['slice'] = ms_to_ns(v)
721 elif k in ['-l', '--latency']:
722 opts['latency'] = ms_to_ns(v)
723 elif k in ['-e', '--extratime']:
724 opts['extratime'] = v
725 elif k in ['-w', '--weight']:
726 opts['weight'] = v
728 # print header if we aren't setting any parameters
729 if len(opts.keys()) == 0:
730 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s'%('Name','ID','Period(ms)',
731 'Slice(ms)', 'Lat(ms)',
732 'Extra','Weight')
734 doms = filter(lambda x : domid_match(domid, x),
735 [parse_doms_info(dom) for dom in getDomains("")])
736 for d in doms:
737 # fetch current values so as not to clobber them
738 sedf_info = \
739 parse_sedf_info(server.xend.domain.cpu_sedf_get(d['dom']))
740 sedf_info['name'] = d['name']
742 # update values in case of call to set
743 if len(opts.keys()) > 0:
744 for k in opts.keys():
745 sedf_info[k]=opts[k]
747 # send the update, converting user input
748 v = map(int, [sedf_info['period'], sedf_info['slice'],
749 sedf_info['latency'],sedf_info['extratime'],
750 sedf_info['weight']])
751 rv = server.xend.domain.cpu_sedf_set(d['dom'], *v)
752 if int(rv) != 0:
753 err("Failed to set sedf parameters (rv=%d)."%(rv))
755 # not setting values, display info
756 else:
757 print_sedf(sedf_info)
759 def xm_sched_credit(args):
760 usage_msg = """sched-credit: Set or get credit scheduler parameters
761 Usage:
763 sched-credit -d domain [-w weight] [-c cap]
764 """
765 try:
766 opts, args = getopt.getopt(args[0:], "d:w:c:",
767 ["domain=", "weight=", "cap="])
768 except getopt.GetoptError:
769 # print help information and exit:
770 print usage_msg
771 sys.exit(1)
773 domain = None
774 weight = None
775 cap = None
777 for o, a in opts:
778 if o == "-d":
779 domain = a
780 elif o == "-w":
781 weight = int(a)
782 elif o == "-c":
783 cap = int(a);
785 if domain is None:
786 # place holder for system-wide scheduler parameters
787 print usage_msg
788 sys.exit(1)
790 if weight is None and cap is None:
791 print server.xend.domain.sched_credit_get(domain)
792 else:
793 if weight is None:
794 weight = int(0)
795 if cap is None:
796 cap = int(~0)
798 err = server.xend.domain.sched_credit_set(domain, weight, cap)
799 if err != 0:
800 print err
802 def xm_info(args):
803 arg_check(args, "info", 0)
805 info = server.xend.node.info()
807 for x in info[1:]:
808 if len(x) < 2:
809 print "%-23s: (none)" % x[0]
810 else:
811 print "%-23s:" % x[0], x[1]
813 def xm_console(args):
814 arg_check(args, "console", 1)
816 dom = args[0]
817 info = server.xend.domain(dom)
818 domid = int(sxp.child_value(info, 'domid', '-1'))
819 console.execConsole(domid)
822 def xm_top(args):
823 arg_check(args, "top", 0)
825 os.execvp('xentop', ['xentop'])
827 def xm_dmesg(args):
828 arg_check(args, "dmesg", 0, 1)
830 gopts = Opts(use="""[-c|--clear]
832 Read Xen's message buffer (boot output, warning and error messages) or clear
833 its contents if the [-c|--clear] flag is specified.
834 """)
836 gopts.opt('clear', short='c',
837 fn=set_true, default=0,
838 use="Clear the contents of the Xen message buffer.")
839 # Work around for gopts
840 myargs = args
841 myargs.insert(0, 'dmesg')
842 gopts.parse(myargs)
843 if not (1 <= len(myargs) <= 2):
844 err('Invalid arguments: ' + str(myargs))
846 if not gopts.vals.clear:
847 print server.xend.node.dmesg.info()
848 else:
849 server.xend.node.dmesg.clear()
851 def xm_log(args):
852 arg_check(args, "log", 0)
854 print server.xend.node.log()
856 def xm_serve(args):
857 arg_check(args, "serve", 0)
859 from fcntl import fcntl, F_SETFL
861 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
862 s.connect(xen.xend.XendClient.XML_RPC_SOCKET)
863 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
865 while True:
866 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
867 if s in iwtd:
868 data = s.recv(4096)
869 if len(data) > 0:
870 sys.stdout.write(data)
871 sys.stdout.flush()
872 else:
873 break
874 if sys.stdin in iwtd:
875 data = sys.stdin.read(4096)
876 if len(data) > 0:
877 s.sendall(data)
878 else:
879 break
880 s.close()
882 def parse_dev_info(info):
883 def get_info(n, t, d):
884 i = 0
885 while i < len(info):
886 if (info[i][0] == n):
887 return t(info[i][1])
888 i = i + 1
889 return t(d)
890 return {
891 #common
892 'backend-id' : get_info('backend-id', int, -1),
893 'handle' : get_info('handle', int, 0),
894 'state' : get_info('state', int, -1),
895 'be-path' : get_info('backend', str, '??'),
896 'event-ch' : get_info('event-channel',int, -1),
897 #network specific
898 'virtual-device' : get_info('virtual-device', str, '??'),
899 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
900 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
901 'mac' : get_info('mac', str, '??'),
902 #block-device specific
903 'ring-ref' : get_info('ring-ref', int, -1),
904 }
906 def arg_check_for_resource_list(args, name):
907 use_long = 0
908 try:
909 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
910 except getopt.GetoptError, opterr:
911 err(opterr)
912 sys.exit(1)
914 for (k, v) in options:
915 if k in ['-l', '--long']:
916 use_long = 1
918 if len(params) == 0:
919 print 'No domain parameter given'
920 usage(name)
921 if len(params) > 1:
922 print 'No multiple domain parameters allowed'
923 usage(name)
925 return (use_long, params)
927 def xm_network_list(args):
928 (use_long, params) = arg_check_for_resource_list(args, "network-list")
930 dom = params[0]
931 if use_long:
932 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
933 map(PrettyPrint.prettyprint, devs)
934 else:
935 hdr = 0
936 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
937 if hdr == 0:
938 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
939 hdr = 1
940 ni = parse_dev_info(x[1])
941 ni['idx'] = int(x[0])
942 print ("%(idx)-3d "
943 "%(backend-id)-3d"
944 "%(mac)-17s "
945 "%(handle)-3d "
946 "%(state)-3d "
947 "%(event-ch)-3d "
948 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
949 "%(be-path)-30s "
950 % ni)
952 def xm_block_list(args):
953 (use_long, params) = arg_check_for_resource_list(args, "block-list")
955 dom = params[0]
956 if use_long:
957 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
958 map(PrettyPrint.prettyprint, devs)
959 else:
960 hdr = 0
961 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
962 if hdr == 0:
963 print 'Vdev BE handle state evt-ch ring-ref BE-path'
964 hdr = 1
965 ni = parse_dev_info(x[1])
966 ni['idx'] = int(x[0])
967 print ("%(idx)-3d "
968 "%(backend-id)-3d "
969 "%(handle)-3d "
970 "%(state)-3d "
971 "%(event-ch)-3d "
972 "%(ring-ref)-5d "
973 "%(be-path)-30s "
974 % ni)
976 def xm_vtpm_list(args):
977 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
979 dom = params[0]
980 if use_long:
981 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
982 map(PrettyPrint.prettyprint, devs)
983 else:
984 hdr = 0
985 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
986 if hdr == 0:
987 print 'Idx BE handle state evt-ch ring-ref BE-path'
988 hdr = 1
989 ni = parse_dev_info(x[1])
990 ni['idx'] = int(x[0])
991 print ("%(idx)-3d "
992 "%(backend-id)-3d "
993 "%(handle)-3d "
994 "%(state)-3d "
995 "%(event-ch)-3d "
996 "%(ring-ref)-5d "
997 "%(be-path)-30s "
998 % ni)
1000 def xm_block_attach(args):
1001 arg_check(args, 'block-attach', 4, 5)
1003 dom = args[0]
1005 if args[1].startswith('tap:'):
1006 cls = 'tap'
1007 else:
1008 cls = 'vbd'
1010 vbd = [cls,
1011 ['uname', args[1]],
1012 ['dev', args[2]],
1013 ['mode', args[3]]]
1014 if len(args) == 5:
1015 vbd.append(['backend', args[4]])
1017 # verify that policy permits attaching this resource
1018 try:
1019 if security.on():
1020 dominfo = server.xend.domain(dom)
1021 label = security.get_security_printlabel(dominfo)
1022 else:
1023 label = None
1024 security.res_security_check(args[1], label)
1025 except security.ACMError, e:
1026 print e.value
1027 sys.exit(1)
1028 except:
1029 traceback.print_exc(limit=1)
1030 sys.exit(1)
1032 server.xend.domain.device_create(dom, vbd)
1035 def xm_network_attach(args):
1036 arg_check(args, 'network-attach', 1, 10000)
1038 dom = args[0]
1039 vif = ['vif']
1041 for a in args[1:]:
1042 vif.append(a.split("="))
1044 server.xend.domain.device_create(dom, vif)
1047 def detach(args, command, deviceClass):
1048 arg_check(args, command, 2)
1050 dom = args[0]
1051 dev = args[1]
1053 server.xend.domain.destroyDevice(dom, deviceClass, dev)
1056 def xm_block_detach(args):
1057 detach(args, 'block-detach', 'vbd')
1060 def xm_network_detach(args):
1061 detach(args, 'network-detach', 'vif')
1064 def xm_vnet_list(args):
1065 try:
1066 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1067 except getopt.GetoptError, opterr:
1068 err(opterr)
1069 sys.exit(1)
1071 use_long = 0
1072 for (k, v) in options:
1073 if k in ['-l', '--long']:
1074 use_long = 1
1076 if params:
1077 use_long = 1
1078 vnets = params
1079 else:
1080 vnets = server.xend_vnets()
1082 for vnet in vnets:
1083 try:
1084 if use_long:
1085 info = server.xend_vnet(vnet)
1086 PrettyPrint.prettyprint(info)
1087 else:
1088 print vnet
1089 except Exception, ex:
1090 print vnet, ex
1092 def xm_vnet_create(args):
1093 arg_check(args, "vnet-create", 1)
1094 conf = args[0]
1095 if not os.access(conf, os.R_OK):
1096 print "File not found: %s" % conf
1097 sys.exit(1)
1099 server.xend_vnet_create(conf)
1101 def xm_vnet_delete(args):
1102 arg_check(args, "vnet-delete", 1)
1103 vnet = args[0]
1104 server.xend_vnet_delete(vnet)
1106 commands = {
1107 # console commands
1108 "console": xm_console,
1109 # xenstat commands
1110 "top": xm_top,
1111 # domain commands
1112 "destroy": xm_destroy,
1113 "domid": xm_domid,
1114 "domname": xm_domname,
1115 "rename": xm_rename,
1116 "restore": xm_restore,
1117 "save": xm_save,
1118 "reboot": xm_reboot,
1119 "shutdown": xm_shutdown,
1120 "list": xm_list,
1121 # memory commands
1122 "mem-max": xm_mem_max,
1123 "mem-set": xm_mem_set,
1124 # cpu commands
1125 "vcpu-pin": xm_vcpu_pin,
1126 "vcpu-list": xm_vcpu_list,
1127 "vcpu-set": xm_vcpu_set,
1128 # special
1129 "pause": xm_pause,
1130 "unpause": xm_unpause,
1131 # host commands
1132 "dmesg": xm_dmesg,
1133 "info": xm_info,
1134 "log": xm_log,
1135 "serve": xm_serve,
1136 # scheduler
1137 "sched-bvt": xm_sched_bvt,
1138 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
1139 "sched-sedf": xm_sched_sedf,
1140 "sched-credit": xm_sched_credit,
1141 # block
1142 "block-attach": xm_block_attach,
1143 "block-detach": xm_block_detach,
1144 "block-list": xm_block_list,
1145 # network
1146 "network-attach": xm_network_attach,
1147 "network-detach": xm_network_detach,
1148 "network-list": xm_network_list,
1149 # vnet
1150 "vnet-list": xm_vnet_list,
1151 "vnet-create": xm_vnet_create,
1152 "vnet-delete": xm_vnet_delete,
1153 # vtpm
1154 "vtpm-list": xm_vtpm_list,
1157 ## The commands supported by a separate argument parser in xend.xm.
1158 subcommands = [
1159 'create',
1160 'migrate',
1161 'sysrq',
1162 'labels',
1163 'addlabel',
1164 'rmlabel',
1165 'getlabel',
1166 'dry-run',
1167 'resources',
1168 'cfgbootpolicy',
1169 'makepolicy',
1170 'loadpolicy',
1171 'dumppolicy'
1174 for c in subcommands:
1175 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
1177 aliases = {
1178 "balloon": "mem-set",
1179 "set-vcpus": "vcpu-set",
1180 "vif-list": "network-list",
1181 "vbd-create": "block-attach",
1182 "vbd-destroy": "block-detach",
1183 "vbd-list": "block-list",
1187 def xm_lookup_cmd(cmd):
1188 if commands.has_key(cmd):
1189 return commands[cmd]
1190 elif aliases.has_key(cmd):
1191 deprecated(cmd,aliases[cmd])
1192 return commands[aliases[cmd]]
1193 else:
1194 if len( cmd ) > 1:
1195 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
1196 if len( matched_commands ) == 1:
1197 return matched_commands[0][1]
1198 err('Sub Command %s not found!' % cmd)
1199 usage()
1201 def deprecated(old,new):
1202 print >>sys.stderr, (
1203 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1205 def usage(cmd=None):
1206 if cmd == 'create':
1207 mycmd = xm_lookup_cmd(cmd)
1208 mycmd( ['--help'] )
1209 sys.exit(1)
1210 if help.has_key(cmd):
1211 print " " + help[cmd]
1212 else:
1213 print shorthelp
1214 sys.exit(1)
1216 def main(argv=sys.argv):
1217 if len(argv) < 2:
1218 usage()
1220 if re.compile('-*help').match(argv[1]):
1221 if len(argv) > 2:
1222 usage(argv[2])
1223 else:
1224 usage()
1225 sys.exit(0)
1227 cmd = xm_lookup_cmd(argv[1])
1229 # strip off prog name and subcmd
1230 args = argv[2:]
1231 if cmd:
1232 try:
1233 rc = cmd(args)
1234 if rc:
1235 usage()
1236 except socket.error, ex:
1237 if os.geteuid() != 0:
1238 err("Most commands need root access. Please try again as root.")
1239 else:
1240 err("Error connecting to xend: %s. Is xend running?" % ex[1])
1241 sys.exit(1)
1242 except KeyboardInterrupt:
1243 print "Interrupted."
1244 sys.exit(1)
1245 except IOError, ex:
1246 if os.geteuid() != 0:
1247 err("Most commands need root access. Please try again as root.")
1248 else:
1249 err("Error connecting to xend: %s." % ex[1])
1250 sys.exit(1)
1251 except SystemExit:
1252 sys.exit(1)
1253 except xmlrpclib.Fault, ex:
1254 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1255 print >>sys.stderr, (
1256 "Error: the domain '%s' does not exist." % ex.faultString)
1257 else:
1258 print >>sys.stderr, "Error: %s" % ex.faultString
1259 sys.exit(1)
1260 except (ValueError, OverflowError):
1261 err("Invalid argument.")
1262 usage(argv[1])
1263 except:
1264 print "Unexpected error:", sys.exc_info()[0]
1265 print
1266 print "Please report to xen-devel@lists.xensource.com"
1267 raise
1269 else:
1270 usage()
1272 if __name__ == "__main__":
1273 main()