ia64/xen-unstable

view tools/python/xen/xm/main.py @ 11716:51fa58f0583b

[XM] Fix missing security check in block-attach

This patch fixes an indentation error in main.py. The effect of this
bug is that block-attach does not check labels if the ACM is
active. This bug slipped in with change set 11572_:_ ad22c711ccb7
<http://xenbits.xensource.com/xen-unstable.hg?cs=ad22c711ccb7>.

Signed-off by: Reiner Sailer <sailer@us.ibm.com>
author Alastair Tse <atse@xensource.com>
date Tue Oct 03 10:48:07 2006 +0100 (2006-10-03)
parents e57815fcc352
children efb8b20004b7
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 sys
26 import re
27 import getopt
28 import socket
29 import traceback
30 import xmlrpclib
31 import traceback
32 import datetime
33 from select import select
35 import warnings
36 warnings.filterwarnings('ignore', category=FutureWarning)
38 from xen.xend import PrettyPrint
39 from xen.xend import sxp
40 from xen.xend import XendClient
41 from xen.xend.XendClient import server
43 from xen.xm.opts import OptionError, Opts, wrap, set_true
44 from xen.xm import console
45 from xen.util import security
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
53 # General help message
55 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
56 "Control, list, and manipulate Xen guest instances.\n"
58 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
59 'For more help on \'xm\' see the xm(1) man page.\n' \
60 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
61 ' man page.\n'
63 # Help strings are indexed by subcommand name in this way:
64 # 'subcommand': (argstring, description)
66 SUBCOMMAND_HELP = {
67 # common commands
69 'console' : ('<Domain>',
70 'Attach to <Domain>\'s console.'),
71 'create' : ('<ConfigFile> [options] [vars]',
72 'Create a domain based on <ConfigFile>.'),
73 'destroy' : ('<Domain>',
74 'Terminate a domain immediately.'),
75 'help' : ('', 'Display this message.'),
76 'list' : ('[options] [Domain, ...]',
77 'List information about all/some domains.'),
78 'mem-max' : ('<Domain> <Mem>',
79 'Set the maximum amount reservation for a domain.'),
80 'mem-set' : ('<Domain> <Mem>',
81 'Set the current memory usage for a domain.'),
82 'migrate' : ('<Domain> <Host>',
83 'Migrate a domain to another machine.'),
84 'pause' : ('<Domain>', 'Pause execution of a domain.'),
85 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
86 'restore' : ('<CheckpointFile>',
87 'Restore a domain from a saved state.'),
88 'save' : ('<Domain> <CheckpointFile>',
89 'Save a domain state to restore later.'),
90 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
91 'top' : ('', 'Monitor a host and the domains in real time.'),
92 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
93 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
95 # less used commands
97 'dmesg' : ('[-c|--clear]',
98 'Read and/or clear Xend\'s message buffer.'),
99 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
100 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
101 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
102 'Dump core for a specific domain.'),
103 'info' : ('', 'Get information about Xen host.'),
104 'log' : ('', 'Print Xend log'),
105 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
106 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
107 'sched-credit': ('-d <Domain> [-w[=WEIGHT]|-c[=CAP]]',
108 'Get/set credit scheduler parameters.'),
109 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
110 'vcpu-list' : ('[<Domain>]',
111 'List the VCPUs for a domain or all domains.'),
112 'vcpu-pin' : ('<Domain> <VCPU> <CPUs>',
113 'Set which CPUs a VCPU can use.'),
114 'vcpu-set' : ('<Domain> <vCPUs>',
115 'Set the number of active VCPUs for allowed for the'
116 ' domain.'),
118 # device commands
120 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode>',
121 'Create a new virtual block device.'),
122 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomId]',
123 'Change block device configuration'),
124 'block-detach' : ('<Domain> <DevId>',
125 'Destroy a domain\'s virtual block device.'),
126 'block-list' : ('<Domain> [--long]',
127 'List virtual block devices for a domain.'),
128 'network-attach': ('<Domain> [--script=<script>] [--ip=<ip>] '
129 '[--mac=<mac>]',
130 'Create a new virtual network device.'),
131 'network-detach': ('<Domain> <DevId>',
132 'Destroy a domain\'s virtual network device.'),
133 'network-list' : ('<Domain> [--long]',
134 'List virtual network interfaces for a domain.'),
135 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
136 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
137 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
138 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
140 # security
142 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
143 'Add security label to domain.'),
144 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
145 'Remove a security label from domain.'),
146 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
147 'Show security label for domain or resource.'),
148 'dry-run' : ('<ConfigFile>',
149 'Test if a domain can access its resources.'),
150 'resources' : ('', 'Show info for each labeled resource.'),
151 'cfgbootpolicy' : ('<policy> [kernelversion]',
152 'Add policy to boot configuration.'),
153 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
154 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
155 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
156 'files.'),
157 'labels' : ('[policy] [type=dom|res|any]',
158 'List <type> labels for (active) policy.'),
159 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
160 }
162 SUBCOMMAND_OPTIONS = {
163 'sched-sedf': (
164 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
165 ('-s [MS]', '--slice[=MS]' ,
166 'Worst-case execution time(ms). (slice < period)'),
167 ('-l [MS]', '--latency[=MS]',
168 'Scaled period (ms) when domain performs heavy I/O'),
169 ('-e [FLAG]', '--extra[=FLAG]',
170 'Flag (0 or 1) controls if domain can run in extra time.'),
171 ('-w [FLOAT]', '--weight[=FLOAT]',
172 'CPU Period/slice (do not set with --period/--slice)'),
173 ),
174 'sched-credit': (
175 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
176 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
177 ('-c CAP', '--cap=CAP', 'Cap (int)'),
178 ),
179 'list': (
180 ('-l', '--long', 'Output all VM details in SXP'),
181 ('', '--label', 'Include security labels'),
182 ),
183 'dmesg': (
184 ('-c', '--clear', 'Clear dmesg buffer'),
185 ),
186 'vnet-list': (
187 ('-l', '--long', 'List Vnets as SXP'),
188 ),
189 'network-list': (
190 ('-l', '--long', 'List resources as SXP'),
191 ),
192 }
194 common_commands = [
195 "console",
196 "create",
197 "destroy",
198 "dump-core",
199 "help",
200 "list",
201 "mem-set",
202 "migrate",
203 "pause",
204 "reboot",
205 "restore",
206 "save",
207 "shutdown",
208 "top",
209 "unpause",
210 "uptime",
211 "vcpu-set",
212 ]
214 domain_commands = [
215 "console",
216 "create",
217 "destroy",
218 "domid",
219 "domname",
220 "dump-core",
221 "list",
222 "mem-max",
223 "mem-set",
224 "migrate",
225 "pause",
226 "reboot",
227 "rename",
228 "restore",
229 "save",
230 "shutdown",
231 "sysrq",
232 "top",
233 "unpause",
234 "uptime",
235 "vcpu-list",
236 "vcpu-pin",
237 "vcpu-set",
238 ]
240 host_commands = [
241 "dmesg",
242 "info",
243 "log",
244 "serve",
245 ]
247 scheduler_commands = [
248 "sched-credit",
249 "sched-sedf",
250 ]
252 device_commands = [
253 "block-attach",
254 "block-detach",
255 "block-list",
256 "block-configure",
257 "network-attach",
258 "network-detach",
259 "network-list",
260 "vtpm-list",
261 ]
263 vnet_commands = [
264 "vnet-list",
265 "vnet-create",
266 "vnet-delete",
267 ]
269 acm_commands = [
270 "labels",
271 "addlabel",
272 "rmlabel",
273 "getlabel",
274 "dry-run",
275 "resources",
276 "makepolicy",
277 "loadpolicy",
278 "cfgbootpolicy",
279 "dumppolicy",
280 ]
282 all_commands = (domain_commands + host_commands + scheduler_commands +
283 device_commands + vnet_commands + acm_commands)
285 ####################################################################
286 #
287 # Help/usage printing functions
288 #
289 ####################################################################
291 def cmdHelp(cmd):
292 """Print help for a specific subcommand."""
294 try:
295 args, desc = SUBCOMMAND_HELP[cmd]
296 except KeyError:
297 shortHelp()
298 return
300 print 'Usage: xm %s %s' % (cmd, args)
301 print
302 print desc
304 try:
305 # If options help message is defined, print this.
306 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
307 if shortopt and longopt:
308 optdesc = '%s, %s' % (shortopt, longopt)
309 elif shortopt:
310 optdesc = shortopt
311 elif longopt:
312 optdesc = longopt
314 wrapped_desc = wrap(desc, 43)
315 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
316 for line in wrapped_desc[1:]:
317 print ' ' * 33 + line
318 print
319 except KeyError:
320 # if the command is an external module, we grab usage help
321 # from the module itself.
322 if cmd in IMPORTED_COMMANDS:
323 try:
324 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
325 cmd_usage = getattr(cmd_module, "help", None)
326 if cmd_usage:
327 print cmd_usage()
328 except ImportError:
329 pass
331 def shortHelp():
332 """Print out generic help when xm is called without subcommand."""
334 print USAGE_HELP
335 print 'Common \'xm\' commands:\n'
337 for command in common_commands:
338 try:
339 args, desc = SUBCOMMAND_HELP[command]
340 except KeyError:
341 continue
342 wrapped_desc = wrap(desc, 50)
343 print ' %-20s %-50s' % (command, wrapped_desc[0])
344 for line in wrapped_desc[1:]:
345 print ' ' * 22 + line
347 print
348 print USAGE_FOOTER
349 print 'For a complete list of subcommands run \'xm help\'.'
351 def longHelp():
352 """Print out full help when xm is called with xm --help or xm help"""
354 print USAGE_HELP
355 print 'xm full list of subcommands:\n'
357 for command in all_commands:
358 try:
359 args, desc = SUBCOMMAND_HELP[command]
360 except KeyError:
361 continue
363 wrapped_desc = wrap(desc, 50)
364 print ' %-20s %-50s' % (command, wrapped_desc[0])
365 for line in wrapped_desc[1:]:
366 print ' ' * 22 + line
368 print
369 print USAGE_FOOTER
371 def usage(cmd = None):
372 """ Print help usage information and exits """
373 if cmd:
374 cmdHelp(cmd)
375 else:
376 shortHelp()
377 sys.exit(1)
380 ####################################################################
381 #
382 # Utility functions
383 #
384 ####################################################################
386 def arg_check(args, name, lo, hi = -1):
387 n = len([i for i in args if i != '--'])
389 if hi == -1:
390 if n != lo:
391 err("'xm %s' requires %d argument%s.\n" % (name, lo,
392 lo == 1 and '' or 's'))
393 usage(name)
394 else:
395 if n < lo or n > hi:
396 err("'xm %s' requires between %d and %d arguments.\n" %
397 (name, lo, hi))
398 usage(name)
401 def unit(c):
402 if not c.isalpha():
403 return 0
404 base = 1
405 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
406 elif c == 'M' or c == 'm': base = 1024 * 1024
407 elif c == 'K' or c == 'k': base = 1024
408 else:
409 print 'ignoring unknown unit'
410 return base
412 def int_unit(str, dest):
413 base = unit(str[-1])
414 if not base:
415 return int(str)
417 value = int(str[:-1])
418 dst_base = unit(dest)
419 if dst_base == 0:
420 dst_base = 1
421 if dst_base > base:
422 return value / (dst_base / base)
423 else:
424 return value * (base / dst_base)
426 def err(msg):
427 print >>sys.stderr, "Error:", msg
430 #########################################################################
431 #
432 # Main xm functions
433 #
434 #########################################################################
436 def xm_save(args):
437 arg_check(args, "save", 2)
439 try:
440 dominfo = parse_doms_info(server.xend.domain(args[0]))
441 except xmlrpclib.Fault, ex:
442 raise ex
444 domid = dominfo['domid']
445 savefile = os.path.abspath(args[1])
447 if not os.access(os.path.dirname(savefile), os.W_OK):
448 err("xm save: Unable to create file %s" % savefile)
449 sys.exit(1)
451 server.xend.domain.save(domid, savefile)
453 def xm_restore(args):
454 arg_check(args, "restore", 1)
456 savefile = os.path.abspath(args[0])
458 if not os.access(savefile, os.R_OK):
459 err("xm restore: Unable to read file %s" % savefile)
460 sys.exit(1)
462 server.xend.domain.restore(savefile)
465 def getDomains(domain_names, full = 0):
466 if domain_names:
467 return [server.xend.domain(dom) for dom in domain_names]
468 else:
469 return server.xend.domains(1)
472 def xm_list(args):
473 use_long = 0
474 show_vcpus = 0
475 show_labels = 0
476 try:
477 (options, params) = getopt.gnu_getopt(args, 'lv',
478 ['long','vcpus','label'])
479 except getopt.GetoptError, opterr:
480 err(opterr)
481 usage('list')
482 sys.exit(1)
484 for (k, v) in options:
485 if k in ['-l', '--long']:
486 use_long = 1
487 if k in ['-v', '--vcpus']:
488 show_vcpus = 1
489 if k in ['--label']:
490 show_labels = 1
492 if show_vcpus:
493 print >>sys.stderr, (
494 "xm list -v is deprecated. Please use xm vcpu-list.")
495 xm_vcpu_list(params)
496 return
498 doms = getDomains(params, use_long)
500 if use_long:
501 map(PrettyPrint.prettyprint, doms)
502 elif show_labels:
503 xm_label_list(doms)
504 else:
505 xm_brief_list(doms)
508 def parse_doms_info(info):
509 def get_info(n, t, d):
510 return t(sxp.child_value(info, n, d))
512 return {
513 'domid' : get_info('domid', int, -1),
514 'name' : get_info('name', str, '??'),
515 'mem' : get_info('memory', int, 0),
516 'vcpus' : get_info('online_vcpus', int, 0),
517 'state' : get_info('state', str, '??'),
518 'cpu_time' : get_info('cpu_time', float, 0),
519 'up_time' : get_info('up_time', float, -1),
520 'seclabel' : security.get_security_printlabel(info),
521 }
524 def parse_sedf_info(info):
525 def get_info(n, t, d):
526 return t(sxp.child_value(info, n, d))
528 return {
529 'domid' : get_info('domain', int, -1),
530 'period' : get_info('period', int, -1),
531 'slice' : get_info('slice', int, -1),
532 'latency' : get_info('latency', int, -1),
533 'extratime': get_info('extratime', int, -1),
534 'weight' : get_info('weight', int, -1),
535 }
537 def xm_brief_list(doms):
538 print '%-40s %3s %8s %5s %5s %9s' % \
539 ('Name', 'ID', 'Mem(MiB)', 'VCPUs', 'State', 'Time(s)')
541 format = "%(name)-40s %(domid)3d %(mem)8d %(vcpus)5d %(state)5s " \
542 "%(cpu_time)8.1f"
544 for dom in doms:
545 d = parse_doms_info(dom)
546 print format % d
548 def xm_label_list(doms):
549 print '%-32s %3s %8s %5s %5s %9s %-8s' % \
550 ('Name', 'ID', 'Mem(MiB)', 'VCPUs', 'State', 'Time(s)', 'Label')
552 output = []
553 format = '%(name)-32s %(domid)3d %(mem)8d %(vcpus)5d %(state)5s ' \
554 '%(cpu_time)8.1f %(seclabel)9s'
556 for dom in doms:
557 d = parse_doms_info(dom)
558 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
559 if not d['seclabel']:
560 d['seclabel'] = 'ERROR'
561 elif security.active_policy in ['DEFAULT']:
562 d['seclabel'] = 'DEFAULT'
563 else:
564 d['seclabel'] = 'INACTIVE'
565 output.append((format % d, d['seclabel']))
567 #sort by labels
568 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
569 for line, label in output:
570 print line
573 def xm_vcpu_list(args):
575 if args:
576 dominfo = map(server.xend.domain.getVCPUInfo, args)
577 else:
578 doms = server.xend.domains(False)
579 dominfo = map(server.xend.domain.getVCPUInfo, doms)
581 print '%-32s %3s %5s %5s %5s %9s %s' % \
582 ('Name', 'ID', 'VCPUs', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
584 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
585 ' %(cpu_time)8.1f %(cpumap)s'
587 for dom in dominfo:
588 def get_info(n):
589 return sxp.child_value(dom, n)
591 #
592 # convert a list of integers into a list of pairs indicating
593 # continuous sequences in the list:
594 #
595 # [0,1,2,3] -> [(0,3)]
596 # [1,2,4,5] -> [(1,2),(4,5)]
597 # [0] -> [(0,0)]
598 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
599 #
600 def list_to_rangepairs(cmap):
601 cmap.sort()
602 pairs = []
603 x = y = 0
604 for i in range(0,len(cmap)):
605 try:
606 if ((cmap[y+1] - cmap[i]) > 1):
607 pairs.append((cmap[x],cmap[y]))
608 x = y = i+1
609 else:
610 y = y + 1
611 # if we go off the end, then just add x to y
612 except IndexError:
613 pairs.append((cmap[x],cmap[y]))
615 return pairs
617 #
618 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
619 #
620 def format_pairs(pairs):
621 if not pairs:
622 return "no cpus"
623 out = ""
624 for f,s in pairs:
625 if (f==s):
626 out += '%d'%f
627 else:
628 out += '%d-%d'%(f,s)
629 out += ','
630 # trim trailing ','
631 return out[:-1]
633 def format_cpumap(cpumap):
634 cpumap = map(lambda x: int(x), cpumap)
635 cpumap.sort()
637 for x in server.xend.node.info()[1:]:
638 if len(x) > 1 and x[0] == 'nr_cpus':
639 nr_cpus = int(x[1])
640 # normalize cpumap by modulus nr_cpus, and drop duplicates
641 cpumap = dict.fromkeys(
642 map(lambda x: x % nr_cpus, cpumap)).keys()
643 if len(cpumap) == nr_cpus:
644 return "any cpu"
645 break
647 return format_pairs(list_to_rangepairs(cpumap))
649 name = get_info('name')
650 domid = int(get_info('domid'))
652 for vcpu in sxp.children(dom, 'vcpu'):
653 def vinfo(n, t):
654 return t(sxp.child_value(vcpu, n))
656 number = vinfo('number', int)
657 cpu = vinfo('cpu', int)
658 cpumap = format_cpumap(vinfo('cpumap', list))
659 online = vinfo('online', int)
660 cpu_time = vinfo('cpu_time', float)
661 running = vinfo('running', int)
662 blocked = vinfo('blocked', int)
664 if online:
665 c = str(cpu)
666 if running:
667 s = 'r'
668 else:
669 s = '-'
670 if blocked:
671 s += 'b'
672 else:
673 s += '-'
674 s += '-'
675 else:
676 c = "-"
677 s = "--p"
679 print format % locals()
681 def xm_reboot(args):
682 arg_check(args, "reboot", 1, 3)
683 from xen.xm import shutdown
684 shutdown.main(["shutdown", "-R"] + args)
686 def xm_shutdown(args):
687 arg_check(args, "shutdown", 1, 4)
688 from xen.xm import shutdown
689 shutdown.main(["shutdown"] + args)
691 def xm_pause(args):
692 arg_check(args, "pause", 1)
693 dom = args[0]
695 server.xend.domain.pause(dom)
697 def xm_unpause(args):
698 arg_check(args, "unpause", 1)
699 dom = args[0]
701 server.xend.domain.unpause(dom)
703 def xm_dump_core(args):
704 live = False
705 crash = False
706 try:
707 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
708 for (k, v) in options:
709 if k in ('-L', '--live'):
710 live = True
711 if k in ('-C', '--crash'):
712 crash = True
714 if len(params) not in (1, 2):
715 raise OptionError("Expects 1 or 2 argument(s)")
716 except getopt.GetoptError, e:
717 raise OptionError(str(e))
719 dom = params[0]
720 if len(params) == 2:
721 filename = os.path.abspath(params[1])
722 else:
723 filename = None
725 if not live:
726 server.xend.domain.pause(dom)
728 try:
729 print "Dumping core of domain: %s ..." % str(dom)
730 server.xend.domain.dump(dom, filename, live, crash)
731 finally:
732 if not live:
733 server.xend.domain.unpause(dom)
735 if crash:
736 print "Destroying domain: %s ..." % str(dom)
737 server.xend.domain.destroy(dom)
739 def xm_rename(args):
740 arg_check(args, "rename", 2)
742 server.xend.domain.setName(args[0], args[1])
744 def xm_importcommand(command, args):
745 cmd = __import__(command, globals(), locals(), 'xen.xm')
746 cmd.main([command] + args)
749 #############################################################
751 def xm_vcpu_pin(args):
752 arg_check(args, "vcpu-pin", 3)
754 def cpu_make_map(cpulist):
755 cpus = []
756 for c in cpulist.split(','):
757 if c.find('-') != -1:
758 (x,y) = c.split('-')
759 for i in range(int(x),int(y)+1):
760 cpus.append(int(i))
761 else:
762 # remove this element from the list
763 if c[0] == '^':
764 cpus = [x for x in cpus if x != int(c[1:])]
765 else:
766 cpus.append(int(c))
767 cpus.sort()
768 return cpus
770 dom = args[0]
771 vcpu = args[1]
772 cpumap = cpu_make_map(args[2])
774 server.xend.domain.pincpu(dom, vcpu, cpumap)
776 def xm_mem_max(args):
777 arg_check(args, "mem-max", 2)
779 dom = args[0]
780 mem = int_unit(args[1], 'm')
782 server.xend.domain.maxmem_set(dom, mem)
784 def xm_mem_set(args):
785 arg_check(args, "mem-set", 2)
787 dom = args[0]
788 mem_target = int_unit(args[1], 'm')
790 server.xend.domain.setMemoryTarget(dom, mem_target)
792 def xm_vcpu_set(args):
793 arg_check(args, "vcpu-set", 2)
795 server.xend.domain.setVCpuCount(args[0], int(args[1]))
798 def xm_destroy(args):
799 arg_check(args, "destroy", 1)
800 server.xend.domain.destroy(args[0])
803 def xm_domid(args):
804 arg_check(args, "domid", 1)
806 name = args[0]
808 dom = server.xend.domain(name)
809 print sxp.child_value(dom, 'domid')
811 def xm_domname(args):
812 arg_check(args, "domname", 1)
814 name = args[0]
816 dom = server.xend.domain(name)
817 print sxp.child_value(dom, 'name')
819 def xm_sched_sedf(args):
820 def ns_to_ms(val):
821 return float(val) * 0.000001
823 def ms_to_ns(val):
824 return (float(val) / 0.000001)
826 def print_sedf(info):
827 info['period'] = ns_to_ms(info['period'])
828 info['slice'] = ns_to_ms(info['slice'])
829 info['latency'] = ns_to_ms(info['latency'])
830 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
831 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
833 def domid_match(domid, info):
834 return domid is None or domid == info['name'] or \
835 domid == str(info['domid'])
837 # we want to just display current info if no parameters are passed
838 if len(args) == 0:
839 domid = None
840 else:
841 # we expect at least a domain id (name or number)
842 # and at most a domid up to 5 options with values
843 arg_check(args, "sched-sedf", 1, 11)
844 domid = args[0]
845 # drop domid from args since get_opt doesn't recognize it
846 args = args[1:]
848 opts = {}
849 try:
850 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
851 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
852 except getopt.GetoptError, opterr:
853 err(opterr)
854 sys.exit(1)
856 # convert to nanoseconds if needed
857 for (k, v) in options:
858 if k in ['-p', '--period']:
859 opts['period'] = ms_to_ns(v)
860 elif k in ['-s', '--slice']:
861 opts['slice'] = ms_to_ns(v)
862 elif k in ['-l', '--latency']:
863 opts['latency'] = ms_to_ns(v)
864 elif k in ['-e', '--extratime']:
865 opts['extratime'] = v
866 elif k in ['-w', '--weight']:
867 opts['weight'] = v
869 doms = filter(lambda x : domid_match(domid, x),
870 [parse_doms_info(dom) for dom in getDomains("")])
872 # print header if we aren't setting any parameters
873 if len(opts.keys()) == 0:
874 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
875 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
876 'Extra','Weight')
878 for d in doms:
879 # fetch current values so as not to clobber them
880 try:
881 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
882 except xmlrpclib.Fault:
883 # domain does not support sched-sedf?
884 sedf_raw = {}
886 sedf_info = parse_sedf_info(sedf_raw)
887 sedf_info['name'] = d['name']
888 # update values in case of call to set
889 if len(opts.keys()) > 0:
890 for k in opts.keys():
891 sedf_info[k]=opts[k]
893 # send the update, converting user input
894 v = map(int, [sedf_info['period'], sedf_info['slice'],
895 sedf_info['latency'],sedf_info['extratime'],
896 sedf_info['weight']])
897 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
898 if int(rv) != 0:
899 err("Failed to set sedf parameters (rv=%d)."%(rv))
901 # not setting values, display info
902 else:
903 print_sedf(sedf_info)
905 def xm_sched_credit(args):
906 """Get/Set options for Credit Scheduler."""
908 try:
909 opts, params = getopt.getopt(args, "d:w:c:",
910 ["domain=", "weight=", "cap="])
911 except getopt.GetoptError, opterr:
912 err(opterr)
913 usage('sched-credit')
914 sys.exit(1)
916 domain = None
917 weight = None
918 cap = None
920 for o, a in opts:
921 if o == "-d":
922 domain = a
923 elif o == "-w":
924 weight = int(a)
925 elif o == "-c":
926 cap = int(a);
928 if domain is None:
929 # place holder for system-wide scheduler parameters
930 err("No domain given.")
931 usage('sched-credit')
932 sys.exit(1)
934 if weight is None and cap is None:
935 print server.xend.domain.sched_credit_get(domain)
936 else:
937 result = server.xend.domain.sched_credit_set(domain, weight, cap)
938 if result != 0:
939 err(str(result))
941 def xm_info(args):
942 arg_check(args, "info", 0)
944 info = server.xend.node.info()
946 for x in info[1:]:
947 if len(x) < 2:
948 print "%-23s: (none)" % x[0]
949 else:
950 print "%-23s:" % x[0], x[1]
952 def xm_console(args):
953 arg_check(args, "console", 1)
955 dom = args[0]
956 info = server.xend.domain(dom)
957 domid = int(sxp.child_value(info, 'domid', '-1'))
958 if domid == -1:
959 raise Exception("Domain is not started")
960 console.execConsole(domid)
962 def xm_uptime(args):
963 short_mode = 0
965 try:
966 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
967 except getopt.GetoptError, opterr:
968 err(opterr)
969 sys.exit(1)
971 for (k, v) in options:
972 if k in ['-s', '--short']:
973 short_mode = 1
975 doms = getDomains(params)
977 if short_mode == 0:
978 print 'Name ID Uptime'
980 for dom in doms:
981 d = parse_doms_info(dom)
982 if d['domid'] > 0:
983 uptime = int(round(d['up_time']))
984 else:
985 f=open('/proc/uptime', 'r')
986 upfile = f.read()
987 uptime = int(round(float(upfile.split(' ')[0])))
988 f.close()
990 days = int(uptime / 86400)
991 uptime -= (days * 86400)
992 hours = int(uptime / 3600)
993 uptime -= (hours * 3600)
994 minutes = int(uptime / 60)
995 uptime -= (minutes * 60)
996 seconds = uptime
998 upstring = ""
999 if days > 0:
1000 upstring += str(days) + " day"
1001 if days > 1:
1002 upstring += "s"
1003 upstring += ", "
1004 upstring += '%(hours)2d:%(minutes)02d' % vars()
1006 if short_mode:
1007 now = datetime.datetime.now()
1008 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1009 upstring += ", " + d['name'] + " (" + str(d['domid']) + ")"
1010 else:
1011 upstring += ':%(seconds)02d' % vars()
1012 upstring = ("%(name)-32s %(domid)3d " % d) + upstring
1014 print upstring
1016 def xm_sysrq(args):
1017 arg_check(args, "sysrq", 2)
1018 dom = args[0]
1019 req = args[1]
1020 server.xend.domain.send_sysrq(dom, req)
1022 def xm_top(args):
1023 arg_check(args, "top", 0)
1025 os.execvp('xentop', ['xentop'])
1027 def xm_dmesg(args):
1028 arg_check(args, "dmesg", 0, 1)
1030 gopts = Opts(use="""[-c|--clear]
1032 Read Xen's message buffer (boot output, warning and error messages) or clear
1033 its contents if the [-c|--clear] flag is specified.
1034 """)
1036 gopts.opt('clear', short='c',
1037 fn=set_true, default=0,
1038 use="Clear the contents of the Xen message buffer.")
1039 # Work around for gopts
1040 myargs = args
1041 myargs.insert(0, 'dmesg')
1042 gopts.parse(myargs)
1044 if len(myargs) not in (1, 2):
1045 err('Invalid arguments: ' + str(myargs))
1046 usage('dmesg')
1047 sys.exit(1)
1049 if not gopts.vals.clear:
1050 print server.xend.node.dmesg.info()
1051 else:
1052 server.xend.node.dmesg.clear()
1054 def xm_log(args):
1055 arg_check(args, "log", 0)
1057 print server.xend.node.log()
1059 def xm_serve(args):
1060 arg_check(args, "serve", 0)
1062 from fcntl import fcntl, F_SETFL
1064 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1065 s.connect(XendClient.XML_RPC_SOCKET)
1066 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1068 while True:
1069 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1070 if s in iwtd:
1071 data = s.recv(4096)
1072 if len(data) > 0:
1073 sys.stdout.write(data)
1074 sys.stdout.flush()
1075 else:
1076 break
1077 if sys.stdin in iwtd:
1078 data = sys.stdin.read(4096)
1079 if len(data) > 0:
1080 s.sendall(data)
1081 else:
1082 break
1083 s.close()
1085 def parse_dev_info(info):
1086 def get_info(n, t, d):
1087 i = 0
1088 while i < len(info):
1089 if (info[i][0] == n):
1090 return t(info[i][1])
1091 i = i + 1
1092 return t(d)
1093 return {
1094 #common
1095 'backend-id' : get_info('backend-id', int, -1),
1096 'handle' : get_info('handle', int, 0),
1097 'state' : get_info('state', int, -1),
1098 'be-path' : get_info('backend', str, '??'),
1099 'event-ch' : get_info('event-channel',int, -1),
1100 #network specific
1101 'virtual-device' : get_info('virtual-device', str, '??'),
1102 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1103 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1104 'mac' : get_info('mac', str, '??'),
1105 #block-device specific
1106 'ring-ref' : get_info('ring-ref', int, -1),
1109 def arg_check_for_resource_list(args, name):
1110 use_long = 0
1111 try:
1112 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1113 except getopt.GetoptError, opterr:
1114 err(opterr)
1115 sys.exit(1)
1117 for (k, v) in options:
1118 if k in ['-l', '--long']:
1119 use_long = 1
1121 if len(params) == 0:
1122 print 'No domain parameter given'
1123 usage(name)
1124 if len(params) > 1:
1125 print 'No multiple domain parameters allowed'
1126 usage(name)
1128 return (use_long, params)
1130 def xm_network_list(args):
1131 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1133 dom = params[0]
1134 if use_long:
1135 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1136 map(PrettyPrint.prettyprint, devs)
1137 else:
1138 hdr = 0
1139 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
1140 if hdr == 0:
1141 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1142 hdr = 1
1143 ni = parse_dev_info(x[1])
1144 ni['idx'] = int(x[0])
1145 print ("%(idx)-3d "
1146 "%(backend-id)-3d"
1147 "%(mac)-17s "
1148 "%(handle)-3d "
1149 "%(state)-3d "
1150 "%(event-ch)-3d "
1151 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1152 "%(be-path)-30s "
1153 % ni)
1155 def xm_block_list(args):
1156 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1158 dom = params[0]
1159 if use_long:
1160 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1161 map(PrettyPrint.prettyprint, devs)
1162 else:
1163 hdr = 0
1164 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
1165 if hdr == 0:
1166 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1167 hdr = 1
1168 ni = parse_dev_info(x[1])
1169 ni['idx'] = int(x[0])
1170 print ("%(idx)-3d "
1171 "%(backend-id)-3d "
1172 "%(handle)-3d "
1173 "%(state)-3d "
1174 "%(event-ch)-3d "
1175 "%(ring-ref)-5d "
1176 "%(be-path)-30s "
1177 % ni)
1179 def xm_vtpm_list(args):
1180 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1182 dom = params[0]
1183 if use_long:
1184 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1185 map(PrettyPrint.prettyprint, devs)
1186 else:
1187 hdr = 0
1188 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1189 if hdr == 0:
1190 print 'Idx BE handle state evt-ch ring-ref BE-path'
1191 hdr = 1
1192 ni = parse_dev_info(x[1])
1193 ni['idx'] = int(x[0])
1194 print ("%(idx)-3d "
1195 "%(backend-id)-3d "
1196 "%(handle)-3d "
1197 "%(state)-3d "
1198 "%(event-ch)-3d "
1199 "%(ring-ref)-5d "
1200 "%(be-path)-30s "
1201 % ni)
1204 def parse_block_configuration(args):
1205 dom = args[0]
1207 if args[1].startswith('tap:'):
1208 cls = 'tap'
1209 else:
1210 cls = 'vbd'
1212 vbd = [cls,
1213 ['uname', args[1]],
1214 ['dev', args[2]],
1215 ['mode', args[3]]]
1216 if len(args) == 5:
1217 vbd.append(['backend', args[4]])
1219 # verify that policy permits attaching this resource
1220 if security.on():
1221 dominfo = server.xend.domain(dom)
1222 label = security.get_security_printlabel(dominfo)
1223 else:
1224 label = None
1225 security.res_security_check(args[1], label)
1227 return (dom, vbd)
1230 def xm_block_attach(args):
1231 arg_check(args, 'block-attach', 4, 5)
1233 (dom, vbd) = parse_block_configuration(args)
1234 server.xend.domain.device_create(dom, vbd)
1237 def xm_block_configure(args):
1238 arg_check(args, 'block-configure', 4, 5)
1240 (dom, vbd) = parse_block_configuration(args)
1241 server.xend.domain.device_configure(dom, vbd)
1244 def xm_network_attach(args):
1245 arg_check(args, 'network-attach', 1, 10000)
1247 dom = args[0]
1248 vif = ['vif']
1250 for a in args[1:]:
1251 vif.append(a.split("="))
1253 server.xend.domain.device_create(dom, vif)
1256 def detach(args, command, deviceClass):
1257 arg_check(args, command, 2)
1259 dom = args[0]
1260 dev = args[1]
1262 server.xend.domain.destroyDevice(dom, deviceClass, dev)
1265 def xm_block_detach(args):
1266 detach(args, 'block-detach', 'vbd')
1269 def xm_network_detach(args):
1270 detach(args, 'network-detach', 'vif')
1273 def xm_vnet_list(args):
1274 try:
1275 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1276 except getopt.GetoptError, opterr:
1277 err(opterr)
1278 sys.exit(1)
1280 use_long = 0
1281 for (k, v) in options:
1282 if k in ['-l', '--long']:
1283 use_long = 1
1285 if params:
1286 use_long = 1
1287 vnets = params
1288 else:
1289 vnets = server.xend_vnets()
1291 for vnet in vnets:
1292 try:
1293 if use_long:
1294 info = server.xend_vnet(vnet)
1295 PrettyPrint.prettyprint(info)
1296 else:
1297 print vnet
1298 except Exception, ex:
1299 print vnet, ex
1301 def xm_vnet_create(args):
1302 arg_check(args, "vnet-create", 1)
1303 conf = args[0]
1304 if not os.access(conf, os.R_OK):
1305 print "File not found: %s" % conf
1306 sys.exit(1)
1308 server.xend_vnet_create(conf)
1310 def xm_vnet_delete(args):
1311 arg_check(args, "vnet-delete", 1)
1312 vnet = args[0]
1313 server.xend_vnet_delete(vnet)
1315 commands = {
1316 # console commands
1317 "console": xm_console,
1318 # xenstat commands
1319 "top": xm_top,
1320 # domain commands
1321 "destroy": xm_destroy,
1322 "domid": xm_domid,
1323 "domname": xm_domname,
1324 "dump-core": xm_dump_core,
1325 "reboot": xm_reboot,
1326 "rename": xm_rename,
1327 "restore": xm_restore,
1328 "save": xm_save,
1329 "shutdown": xm_shutdown,
1330 "sysrq": xm_sysrq,
1331 "uptime": xm_uptime,
1332 "list": xm_list,
1333 # memory commands
1334 "mem-max": xm_mem_max,
1335 "mem-set": xm_mem_set,
1336 # cpu commands
1337 "vcpu-pin": xm_vcpu_pin,
1338 "vcpu-list": xm_vcpu_list,
1339 "vcpu-set": xm_vcpu_set,
1340 # special
1341 "pause": xm_pause,
1342 "unpause": xm_unpause,
1343 # host commands
1344 "dmesg": xm_dmesg,
1345 "info": xm_info,
1346 "log": xm_log,
1347 "serve": xm_serve,
1348 # scheduler
1349 "sched-sedf": xm_sched_sedf,
1350 "sched-credit": xm_sched_credit,
1351 # block
1352 "block-attach": xm_block_attach,
1353 "block-detach": xm_block_detach,
1354 "block-list": xm_block_list,
1355 "block-configure": xm_block_configure,
1356 # network
1357 "network-attach": xm_network_attach,
1358 "network-detach": xm_network_detach,
1359 "network-list": xm_network_list,
1360 # vnet
1361 "vnet-list": xm_vnet_list,
1362 "vnet-create": xm_vnet_create,
1363 "vnet-delete": xm_vnet_delete,
1364 # vtpm
1365 "vtpm-list": xm_vtpm_list,
1368 ## The commands supported by a separate argument parser in xend.xm.
1369 IMPORTED_COMMANDS = [
1370 'create',
1371 'migrate',
1372 'labels',
1373 'addlabel',
1374 'cfgbootpolicy',
1375 'makepolicy',
1376 'loadpolicy',
1377 'dumppolicy',
1378 'rmlabel',
1379 'getlabel',
1380 'dry-run',
1381 'resources',
1384 for c in IMPORTED_COMMANDS:
1385 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
1387 aliases = {
1388 "balloon": "mem-set",
1389 "set-vcpus": "vcpu-set",
1390 "vif-list": "network-list",
1391 "vbd-create": "block-attach",
1392 "vbd-destroy": "block-detach",
1393 "vbd-list": "block-list",
1397 def xm_lookup_cmd(cmd):
1398 if commands.has_key(cmd):
1399 return commands[cmd]
1400 elif aliases.has_key(cmd):
1401 deprecated(cmd,aliases[cmd])
1402 return commands[aliases[cmd]]
1403 elif cmd == 'help':
1404 longHelp()
1405 sys.exit(0)
1406 else:
1407 # simulate getopt's prefix matching behaviour
1408 if len(cmd) > 1:
1409 same_prefix_cmds = [commands[c] for c in commands.keys() \
1410 if c[:len(cmd)] == cmd]
1411 # only execute if there is only 1 match
1412 if len(same_prefix_cmds) == 1:
1413 return same_prefix_cmds[0]
1415 err('Sub Command %s not found!' % cmd)
1416 usage()
1418 def deprecated(old,new):
1419 print >>sys.stderr, (
1420 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1422 def main(argv=sys.argv):
1423 if len(argv) < 2:
1424 usage()
1426 # intercept --help(-h) and output our own help
1427 for help in ['--help', '-h']:
1428 if help in argv[1:]:
1429 if help == argv[1]:
1430 longHelp()
1431 else:
1432 usage(argv[1])
1433 sys.exit(0)
1435 cmd = xm_lookup_cmd(argv[1])
1437 # strip off prog name and subcmd
1438 args = argv[2:]
1439 if cmd:
1440 try:
1441 rc = cmd(args)
1442 if rc:
1443 usage()
1444 except socket.error, ex:
1445 if os.geteuid() != 0:
1446 err("Most commands need root access. Please try again as root.")
1447 else:
1448 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
1449 sys.exit(1)
1450 except KeyboardInterrupt:
1451 print "Interrupted."
1452 sys.exit(1)
1453 except IOError, ex:
1454 if os.geteuid() != 0:
1455 err("Most commands need root access. Please try again as root.")
1456 else:
1457 err("Unable to connect to xend: %s." % ex[1])
1458 sys.exit(1)
1459 except SystemExit:
1460 sys.exit(1)
1461 except xmlrpclib.Fault, ex:
1462 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
1463 err("Domain '%s' does not exist." % ex.faultString)
1464 else:
1465 err(ex.faultString)
1466 usage(argv[1])
1467 sys.exit(1)
1468 except xmlrpclib.ProtocolError, ex:
1469 if ex.errcode == -1:
1470 print >>sys.stderr, (
1471 "Xend has probably crashed! Invalid or missing HTTP "
1472 "status code.")
1473 else:
1474 print >>sys.stderr, (
1475 "Xend has probably crashed! ProtocolError(%d, %s)." %
1476 (ex.errcode, ex.errmsg))
1477 sys.exit(1)
1478 except (ValueError, OverflowError):
1479 err("Invalid argument.")
1480 usage(argv[1])
1481 sys.exit(1)
1482 except OptionError, e:
1483 err(str(e))
1484 usage(argv[1])
1485 print e.usage()
1486 sys.exit(1)
1487 except security.ACMError, e:
1488 err(str(e))
1489 sys.exit(1)
1490 except:
1491 print "Unexpected error:", sys.exc_info()[0]
1492 print
1493 print "Please report to xen-devel@lists.xensource.com"
1494 raise
1496 else:
1497 usage()
1499 if __name__ == "__main__":
1500 main()