ia64/xen-unstable

view tools/python/xen/xm/main.py @ 10720:8922c1fbe684

[XM][ACM] Add xm subcommands to work with security resource labels.

This patch adds new xm subcommands to support working with resource
labels. The new subcommands are 'xm resources', 'xm rmlabel', 'xm
getlabel' and 'xm dry-run'. In addition, the 'xm addlabel' subcommand
now uses an updated syntax to support labeling both domains and
resources. See the xm man page for details on each subcommand.

Beyond the new subcommands, this patch allows users to immediately see
when security checks will fail by pushing some basic security checking
into the beginning of 'xm create' and 'xm block-attach'. ACM security
attributes for block devices are added to XenStore in order to support
the final security enforcement, which will be performed in the kernel
and included in a separate patch.

Signed-off-by: Bryan D. Payne <bdpayne@us.ibm.com>
Signed-off-by: Reiner Sailer <sailer@us.ibm.com>
author kfraser@localhost.localdomain
date Mon Jul 10 17:18:07 2006 +0100 (2006-07-10)
parents 9dbcf482f600
children 2937703f0ed0
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]
997 vbd = ['vbd',
998 ['uname', args[1]],
999 ['dev', args[2]],
1000 ['mode', args[3]]]
1001 if len(args) == 5:
1002 vbd.append(['backend', args[4]])
1004 # verify that policy permits attaching this resource
1005 try:
1006 if security.on():
1007 dominfo = server.xend.domain(dom)
1008 label = security.get_security_printlabel(dominfo)
1009 else:
1010 label = None
1011 security.res_security_check(args[1], label)
1012 except security.ACMError, e:
1013 print e.value
1014 sys.exit(1)
1015 except:
1016 traceback.print_exc(limit=1)
1017 sys.exit(1)
1019 server.xend.domain.device_create(dom, vbd)
1022 def xm_network_attach(args):
1023 arg_check(args, 'network-attach', 1, 10000)
1025 dom = args[0]
1026 vif = ['vif']
1028 for a in args[1:]:
1029 vif.append(a.split("="))
1031 server.xend.domain.device_create(dom, vif)
1034 def detach(args, command, deviceClass):
1035 arg_check(args, command, 2)
1037 dom = args[0]
1038 dev = args[1]
1040 server.xend.domain.destroyDevice(dom, deviceClass, dev)
1043 def xm_block_detach(args):
1044 detach(args, 'block-detach', 'vbd')
1047 def xm_network_detach(args):
1048 detach(args, 'network-detach', 'vif')
1051 def xm_vnet_list(args):
1052 try:
1053 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1054 except getopt.GetoptError, opterr:
1055 err(opterr)
1056 sys.exit(1)
1058 use_long = 0
1059 for (k, v) in options:
1060 if k in ['-l', '--long']:
1061 use_long = 1
1063 if params:
1064 use_long = 1
1065 vnets = params
1066 else:
1067 vnets = server.xend_vnets()
1069 for vnet in vnets:
1070 try:
1071 if use_long:
1072 info = server.xend_vnet(vnet)
1073 PrettyPrint.prettyprint(info)
1074 else:
1075 print vnet
1076 except Exception, ex:
1077 print vnet, ex
1079 def xm_vnet_create(args):
1080 arg_check(args, "vnet-create", 1)
1081 conf = args[0]
1082 if not os.access(conf, os.R_OK):
1083 print "File not found: %s" % conf
1084 sys.exit(1)
1086 server.xend_vnet_create(conf)
1088 def xm_vnet_delete(args):
1089 arg_check(args, "vnet-delete", 1)
1090 vnet = args[0]
1091 server.xend_vnet_delete(vnet)
1093 commands = {
1094 # console commands
1095 "console": xm_console,
1096 # xenstat commands
1097 "top": xm_top,
1098 # domain commands
1099 "destroy": xm_destroy,
1100 "domid": xm_domid,
1101 "domname": xm_domname,
1102 "rename": xm_rename,
1103 "restore": xm_restore,
1104 "save": xm_save,
1105 "reboot": xm_reboot,
1106 "list": xm_list,
1107 # memory commands
1108 "mem-max": xm_mem_max,
1109 "mem-set": xm_mem_set,
1110 # cpu commands
1111 "vcpu-pin": xm_vcpu_pin,
1112 "vcpu-list": xm_vcpu_list,
1113 "vcpu-set": xm_vcpu_set,
1114 # special
1115 "pause": xm_pause,
1116 "unpause": xm_unpause,
1117 # host commands
1118 "dmesg": xm_dmesg,
1119 "info": xm_info,
1120 "log": xm_log,
1121 "serve": xm_serve,
1122 # scheduler
1123 "sched-bvt": xm_sched_bvt,
1124 "sched-bvt-ctxallow": xm_sched_bvt_ctxallow,
1125 "sched-sedf": xm_sched_sedf,
1126 "sched-credit": xm_sched_credit,
1127 # block
1128 "block-attach": xm_block_attach,
1129 "block-detach": xm_block_detach,
1130 "block-list": xm_block_list,
1131 # network
1132 "network-attach": xm_network_attach,
1133 "network-detach": xm_network_detach,
1134 "network-list": xm_network_list,
1135 # vnet
1136 "vnet-list": xm_vnet_list,
1137 "vnet-create": xm_vnet_create,
1138 "vnet-delete": xm_vnet_delete,
1139 # vtpm
1140 "vtpm-list": xm_vtpm_list,
1143 ## The commands supported by a separate argument parser in xend.xm.
1144 subcommands = [
1145 'create',
1146 'migrate',
1147 'sysrq',
1148 'shutdown',
1149 'labels',
1150 'addlabel',
1151 'rmlabel',
1152 'getlabel',
1153 'dry-run',
1154 'resources',
1155 'cfgbootpolicy',
1156 'makepolicy',
1157 'loadpolicy',
1158 'dumppolicy'
1161 for c in subcommands:
1162 commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
1164 aliases = {
1165 "balloon": "mem-set",
1166 "set-vcpus": "vcpu-set",
1167 "vif-list": "network-list",
1168 "vbd-create": "block-attach",
1169 "vbd-destroy": "block-detach",
1170 "vbd-list": "block-list",
1174 def xm_lookup_cmd(cmd):
1175 if commands.has_key(cmd):
1176 return commands[cmd]
1177 elif aliases.has_key(cmd):
1178 deprecated(cmd,aliases[cmd])
1179 return commands[aliases[cmd]]
1180 else:
1181 if len( cmd ) > 1:
1182 matched_commands = filter( lambda (command, func): command[ 0:len(cmd) ] == cmd, commands.iteritems() )
1183 if len( matched_commands ) == 1:
1184 return matched_commands[0][1]
1185 err('Sub Command %s not found!' % cmd)
1186 usage()
1188 def deprecated(old,new):
1189 print >>sys.stderr, (
1190 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1192 def usage(cmd=None):
1193 if cmd == 'create':
1194 mycmd = xm_lookup_cmd(cmd)
1195 mycmd( ['--help'] )
1196 sys.exit(1)
1197 if help.has_key(cmd):
1198 print " " + help[cmd]
1199 else:
1200 print shorthelp
1201 sys.exit(1)
1203 def main(argv=sys.argv):
1204 if len(argv) < 2:
1205 usage()
1207 if re.compile('-*help').match(argv[1]):
1208 if len(argv) > 2:
1209 usage(argv[2])
1210 else:
1211 usage()
1212 sys.exit(0)
1214 cmd = xm_lookup_cmd(argv[1])
1216 # strip off prog name and subcmd
1217 args = argv[2:]
1218 if cmd:
1219 try:
1220 rc = cmd(args)
1221 if rc:
1222 usage()
1223 except socket.error, ex:
1224 if os.geteuid() != 0:
1225 err("Most commands need root access. Please try again as root.")
1226 else:
1227 err("Error connecting to xend: %s. Is xend running?" % ex[1])
1228 sys.exit(1)
1229 except KeyboardInterrupt:
1230 print "Interrupted."
1231 sys.exit(1)
1232 except IOError, ex:
1233 if os.geteuid() != 0:
1234 err("Most commands need root access. Please try again as root.")
1235 else:
1236 err("Error connecting to xend: %s." % ex[1])
1237 sys.exit(1)
1238 except SystemExit:
1239 sys.exit(1)
1240 except xmlrpclib.Fault, ex:
1241 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1242 print >>sys.stderr, (
1243 "Error: the domain '%s' does not exist." % ex.faultString)
1244 else:
1245 print >>sys.stderr, "Error: %s" % ex.faultString
1246 sys.exit(1)
1247 except (ValueError, OverflowError):
1248 err("Invalid argument.")
1249 usage(argv[1])
1250 except:
1251 print "Unexpected error:", sys.exc_info()[0]
1252 print
1253 print "Please report to xen-devel@lists.xensource.com"
1254 raise
1256 else:
1257 usage()
1259 if __name__ == "__main__":
1260 main()