ia64/xen-unstable

view tools/python/xen/xm/main.py @ 12642:33951d547223

Plumb the "start_paused" flag through for VM.start and VM.resume. Do not
unpause the VM on start by default. This should fix problems seen recently
whereby devices are not attached to the VM by the time they boot, as
xm create was expecting to be able to wait for the devices before unpausing.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Nov 28 17:28:43 2006 +0000 (2006-11-28)
parents bbcaa0cad3d2
children 5bed7bc05c8a
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
42 from xen.xend.XendConstants import *
44 from xen.xm.opts import OptionError, Opts, wrap, set_true
45 from xen.xm import console
46 from xen.util import security
48 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
49 # getopt.getopt if gnu_getopt is not available. This will mean that options
50 # may only be specified before positional arguments.
51 if not hasattr(getopt, 'gnu_getopt'):
52 getopt.gnu_getopt = getopt.getopt
54 # General help message
56 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
57 "Control, list, and manipulate Xen guest instances.\n"
59 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
60 'For more help on \'xm\' see the xm(1) man page.\n' \
61 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
62 ' man page.\n'
64 # Help strings are indexed by subcommand name in this way:
65 # 'subcommand': (argstring, description)
67 SUBCOMMAND_HELP = {
68 # common commands
70 'console' : ('[-q|--quiet] <Domain>',
71 'Attach to <Domain>\'s console.'),
72 'create' : ('<ConfigFile> [options] [vars]',
73 'Create a domain based on <ConfigFile>.'),
74 'destroy' : ('<Domain>',
75 'Terminate a domain immediately.'),
76 'help' : ('', 'Display this message.'),
77 'list' : ('[options] [Domain, ...]',
78 'List information about all/some domains.'),
79 'mem-max' : ('<Domain> <Mem>',
80 'Set the maximum amount reservation for a domain.'),
81 'mem-set' : ('<Domain> <Mem>',
82 'Set the current memory usage for a domain.'),
83 'migrate' : ('<Domain> <Host>',
84 'Migrate a domain to another machine.'),
85 'pause' : ('<Domain>', 'Pause execution of a domain.'),
86 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
87 'restore' : ('<CheckpointFile> [-p]',
88 'Restore a domain from a saved state.'),
89 'save' : ('<Domain> <CheckpointFile>',
90 'Save a domain state to restore later.'),
91 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
92 'top' : ('', 'Monitor a host and the domains in real time.'),
93 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
94 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
96 # Life cycle xm commands
97 'new' : ('<ConfigFile> [options] [vars]',
98 'Adds a domain to Xend domain management'),
99 'delete' : ('<DomainName>',
100 'Remove a domain from Xend domain management.'),
101 'start' : ('<DomainName>', 'Start a Xend managed domain'),
102 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
103 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
105 # less used commands
107 'dmesg' : ('[-c|--clear]',
108 'Read and/or clear Xend\'s message buffer.'),
109 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
110 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
111 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
112 'Dump core for a specific domain.'),
113 'info' : ('', 'Get information about Xen host.'),
114 'log' : ('', 'Print Xend log'),
115 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
116 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
117 'sched-credit': ('-d <Domain> [-w[=WEIGHT]|-c[=CAP]]',
118 'Get/set credit scheduler parameters.'),
119 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
120 'vcpu-list' : ('[<Domain>]',
121 'List the VCPUs for a domain or all domains.'),
122 'vcpu-pin' : ('<Domain> <VCPU> <CPUs>',
123 'Set which CPUs a VCPU can use.'),
124 'vcpu-set' : ('<Domain> <vCPUs>',
125 'Set the number of active VCPUs for allowed for the'
126 ' domain.'),
128 # device commands
130 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode>',
131 'Create a new virtual block device.'),
132 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomId]',
133 'Change block device configuration'),
134 'block-detach' : ('<Domain> <DevId>',
135 'Destroy a domain\'s virtual block device.'),
136 'block-list' : ('<Domain> [--long]',
137 'List virtual block devices for a domain.'),
138 'network-attach': ('<Domain> [--script=<script>] [--ip=<ip>] '
139 '[--mac=<mac>]',
140 'Create a new virtual network device.'),
141 'network-detach': ('<Domain> <DevId>',
142 'Destroy a domain\'s virtual network device.'),
143 'network-list' : ('<Domain> [--long]',
144 'List virtual network interfaces for a domain.'),
145 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
146 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
147 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
148 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
150 # security
152 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
153 'Add security label to domain.'),
154 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
155 'Remove a security label from domain.'),
156 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
157 'Show security label for domain or resource.'),
158 'dry-run' : ('<ConfigFile>',
159 'Test if a domain can access its resources.'),
160 'resources' : ('', 'Show info for each labeled resource.'),
161 'cfgbootpolicy' : ('<policy> [boot-title]',
162 'Add policy to boot configuration.'),
163 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
164 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
165 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
166 'files.'),
167 'labels' : ('[policy] [type=dom|res|any]',
168 'List <type> labels for (active) policy.'),
169 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
170 }
172 SUBCOMMAND_OPTIONS = {
173 'sched-sedf': (
174 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
175 ('-s [MS]', '--slice[=MS]' ,
176 'Worst-case execution time(ms). (slice < period)'),
177 ('-l [MS]', '--latency[=MS]',
178 'Scaled period (ms) when domain performs heavy I/O'),
179 ('-e [FLAG]', '--extra[=FLAG]',
180 'Flag (0 or 1) controls if domain can run in extra time.'),
181 ('-w [FLOAT]', '--weight[=FLOAT]',
182 'CPU Period/slice (do not set with --period/--slice)'),
183 ),
184 'sched-credit': (
185 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
186 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
187 ('-c CAP', '--cap=CAP', 'Cap (int)'),
188 ),
189 'list': (
190 ('-l', '--long', 'Output all VM details in SXP'),
191 ('', '--label', 'Include security labels'),
192 ('', '--state=<state>', 'Select only VMs with the specified state'),
193 ),
194 'console': (
195 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
196 ),
197 'dmesg': (
198 ('-c', '--clear', 'Clear dmesg buffer'),
199 ),
200 'vnet-list': (
201 ('-l', '--long', 'List Vnets as SXP'),
202 ),
203 'network-list': (
204 ('-l', '--long', 'List resources as SXP'),
205 ),
206 'dump-core': (
207 ('-L', '--live', 'Dump core without pausing the domain'),
208 ('-C', '--crash', 'Crash domain after dumping core'),
209 ),
210 'start': (
211 ('-p', '--paused', 'Do not unpause domain after starting it'),
212 ),
213 'resume': (
214 ('-p', '--paused', 'Do not unpause domain after resuming it'),
215 ),
216 'restore': (
217 ('-p', '--paused', 'Do not unpause domain after restoring it'),
218 ),
219 }
221 common_commands = [
222 "console",
223 "create",
224 "new",
225 "delete",
226 "destroy",
227 "dump-core",
228 "help",
229 "list",
230 "mem-set",
231 "migrate",
232 "pause",
233 "reboot",
234 "restore",
235 "resume",
236 "save",
237 "shutdown",
238 "start",
239 "suspend",
240 "top",
241 "unpause",
242 "uptime",
243 "vcpu-set",
244 ]
246 domain_commands = [
247 "console",
248 "create",
249 "new",
250 "delete",
251 "destroy",
252 "domid",
253 "domname",
254 "dump-core",
255 "list",
256 "mem-max",
257 "mem-set",
258 "migrate",
259 "pause",
260 "reboot",
261 "rename",
262 "restore",
263 "resume",
264 "save",
265 "shutdown",
266 "start",
267 "suspend",
268 "sysrq",
269 "top",
270 "unpause",
271 "uptime",
272 "vcpu-list",
273 "vcpu-pin",
274 "vcpu-set",
275 ]
277 host_commands = [
278 "dmesg",
279 "info",
280 "log",
281 "serve",
282 ]
284 scheduler_commands = [
285 "sched-credit",
286 "sched-sedf",
287 ]
289 device_commands = [
290 "block-attach",
291 "block-detach",
292 "block-list",
293 "block-configure",
294 "network-attach",
295 "network-detach",
296 "network-list",
297 "vtpm-list",
298 ]
300 vnet_commands = [
301 "vnet-list",
302 "vnet-create",
303 "vnet-delete",
304 ]
306 acm_commands = [
307 "labels",
308 "addlabel",
309 "rmlabel",
310 "getlabel",
311 "dry-run",
312 "resources",
313 "makepolicy",
314 "loadpolicy",
315 "cfgbootpolicy",
316 "dumppolicy",
317 ]
319 all_commands = (domain_commands + host_commands + scheduler_commands +
320 device_commands + vnet_commands + acm_commands)
322 ####################################################################
323 #
324 # Help/usage printing functions
325 #
326 ####################################################################
328 def cmdHelp(cmd):
329 """Print help for a specific subcommand."""
331 for fc in SUBCOMMAND_HELP.keys():
332 if fc[:len(cmd)] == cmd:
333 cmd = fc
334 break
336 try:
337 args, desc = SUBCOMMAND_HELP[cmd]
338 except KeyError:
339 shortHelp()
340 return
342 print 'Usage: xm %s %s' % (cmd, args)
343 print
344 print desc
346 try:
347 # If options help message is defined, print this.
348 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
349 if shortopt and longopt:
350 optdesc = '%s, %s' % (shortopt, longopt)
351 elif shortopt:
352 optdesc = shortopt
353 elif longopt:
354 optdesc = longopt
356 wrapped_desc = wrap(desc, 43)
357 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
358 for line in wrapped_desc[1:]:
359 print ' ' * 33 + line
360 print
361 except KeyError:
362 # if the command is an external module, we grab usage help
363 # from the module itself.
364 if cmd in IMPORTED_COMMANDS:
365 try:
366 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
367 cmd_usage = getattr(cmd_module, "help", None)
368 if cmd_usage:
369 print cmd_usage()
370 except ImportError:
371 pass
373 def shortHelp():
374 """Print out generic help when xm is called without subcommand."""
376 print USAGE_HELP
377 print 'Common \'xm\' commands:\n'
379 for command in common_commands:
380 try:
381 args, desc = SUBCOMMAND_HELP[command]
382 except KeyError:
383 continue
384 wrapped_desc = wrap(desc, 50)
385 print ' %-20s %-50s' % (command, wrapped_desc[0])
386 for line in wrapped_desc[1:]:
387 print ' ' * 22 + line
389 print
390 print USAGE_FOOTER
391 print 'For a complete list of subcommands run \'xm help\'.'
393 def longHelp():
394 """Print out full help when xm is called with xm --help or xm help"""
396 print USAGE_HELP
397 print 'xm full list of subcommands:\n'
399 for command in all_commands:
400 try:
401 args, desc = SUBCOMMAND_HELP[command]
402 except KeyError:
403 continue
405 wrapped_desc = wrap(desc, 50)
406 print ' %-20s %-50s' % (command, wrapped_desc[0])
407 for line in wrapped_desc[1:]:
408 print ' ' * 22 + line
410 print
411 print USAGE_FOOTER
413 def usage(cmd = None):
414 """ Print help usage information and exits """
415 if cmd:
416 cmdHelp(cmd)
417 else:
418 shortHelp()
419 sys.exit(1)
422 ####################################################################
423 #
424 # Utility functions
425 #
426 ####################################################################
428 def arg_check(args, name, lo, hi = -1):
429 n = len([i for i in args if i != '--'])
431 if hi == -1:
432 if n != lo:
433 err("'xm %s' requires %d argument%s.\n" % (name, lo,
434 lo == 1 and '' or 's'))
435 usage(name)
436 else:
437 if n < lo or n > hi:
438 err("'xm %s' requires between %d and %d arguments.\n" %
439 (name, lo, hi))
440 usage(name)
443 def unit(c):
444 if not c.isalpha():
445 return 0
446 base = 1
447 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
448 elif c == 'M' or c == 'm': base = 1024 * 1024
449 elif c == 'K' or c == 'k': base = 1024
450 else:
451 print 'ignoring unknown unit'
452 return base
454 def int_unit(str, dest):
455 base = unit(str[-1])
456 if not base:
457 return int(str)
459 value = int(str[:-1])
460 dst_base = unit(dest)
461 if dst_base == 0:
462 dst_base = 1
463 if dst_base > base:
464 return value / (dst_base / base)
465 else:
466 return value * (base / dst_base)
468 def err(msg):
469 print >>sys.stderr, "Error:", msg
472 #########################################################################
473 #
474 # Main xm functions
475 #
476 #########################################################################
478 def xm_save(args):
479 arg_check(args, "save", 2)
481 try:
482 dominfo = parse_doms_info(server.xend.domain(args[0]))
483 except xmlrpclib.Fault, ex:
484 raise ex
486 domid = dominfo['domid']
487 savefile = os.path.abspath(args[1])
489 if not os.access(os.path.dirname(savefile), os.W_OK):
490 err("xm save: Unable to create file %s" % savefile)
491 sys.exit(1)
493 server.xend.domain.save(domid, savefile)
495 def xm_restore(args):
496 arg_check(args, "restore", 1, 2)
498 try:
499 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
500 except getopt.GetoptError, opterr:
501 err(opterr)
502 sys.exit(1)
504 paused = False
505 for (k, v) in options:
506 if k in ['-p', '--paused']:
507 paused = True
509 if len(params) != 1:
510 err("Wrong number of parameters")
511 usage('restore')
512 sys.exit(1)
514 savefile = os.path.abspath(params[0])
516 if not os.access(savefile, os.R_OK):
517 err("xm restore: Unable to read file %s" % savefile)
518 sys.exit(1)
520 server.xend.domain.restore(savefile, paused)
523 def getDomains(domain_names, state, full = 0):
524 if domain_names:
525 return [server.xend.domain(dom, full) for dom in domain_names]
526 else:
527 return server.xend.domains_with_state(True, state, full)
530 def xm_list(args):
531 use_long = 0
532 show_vcpus = 0
533 show_labels = 0
534 state = 'all'
535 try:
536 (options, params) = getopt.gnu_getopt(args, 'lv',
537 ['long','vcpus','label',
538 'state='])
539 except getopt.GetoptError, opterr:
540 err(opterr)
541 usage('list')
542 sys.exit(1)
544 for (k, v) in options:
545 if k in ['-l', '--long']:
546 use_long = 1
547 if k in ['-v', '--vcpus']:
548 show_vcpus = 1
549 if k in ['--label']:
550 show_labels = 1
551 if k in ['--state']:
552 state = v
554 if state != 'all' and len(params) > 0:
555 raise OptionError(
556 "You may specify either a state or a particular VM, but not both")
558 if show_vcpus:
559 print >>sys.stderr, (
560 "xm list -v is deprecated. Please use xm vcpu-list.")
561 xm_vcpu_list(params)
562 return
564 doms = getDomains(params, state, use_long)
566 if use_long:
567 map(PrettyPrint.prettyprint, doms)
568 elif show_labels:
569 xm_label_list(doms)
570 else:
571 xm_brief_list(doms)
574 def parse_doms_info(info):
575 def get_info(n, t, d):
576 return t(sxp.child_value(info, n, d))
578 def get_status(n, t, d):
579 return DOM_STATES[t(sxp.child_value(info, n, d))]
581 return {
582 'domid' : get_info('domid', str, ''),
583 'name' : get_info('name', str, '??'),
584 'mem' : get_info('memory_dynamic_max', int, 0),
585 'vcpus' : get_info('online_vcpus', int, 0),
586 'state' : get_info('state', str, ''),
587 'cpu_time' : get_info('cpu_time', float, 0),
588 'up_time' : get_info('up_time', float, -1),
589 'seclabel' : security.get_security_printlabel(info),
590 }
593 def parse_sedf_info(info):
594 def get_info(n, t, d):
595 return t(sxp.child_value(info, n, d))
597 return {
598 'domid' : get_info('domid', int, -1),
599 'period' : get_info('period', int, -1),
600 'slice' : get_info('slice', int, -1),
601 'latency' : get_info('latency', int, -1),
602 'extratime': get_info('extratime', int, -1),
603 'weight' : get_info('weight', int, -1),
604 }
606 def xm_brief_list(doms):
607 print '%-40s %3s %5s %5s %10s %9s' % \
608 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
610 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
611 "%(cpu_time)8.1f"
613 for dom in doms:
614 d = parse_doms_info(dom)
615 print format % d
617 def xm_label_list(doms):
618 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
619 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
621 output = []
622 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
623 '%(cpu_time)8.1f %(seclabel)9s'
625 for dom in doms:
626 d = parse_doms_info(dom)
627 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
628 if not d['seclabel']:
629 d['seclabel'] = 'ERROR'
630 elif security.active_policy in ['DEFAULT']:
631 d['seclabel'] = 'DEFAULT'
632 else:
633 d['seclabel'] = 'INACTIVE'
634 output.append((format % d, d['seclabel']))
636 #sort by labels
637 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
638 for line, label in output:
639 print line
642 def xm_vcpu_list(args):
644 if args:
645 dominfo = map(server.xend.domain.getVCPUInfo, args)
646 else:
647 doms = server.xend.domains(False)
648 dominfo = map(server.xend.domain.getVCPUInfo, doms)
650 print '%-32s %3s %5s %5s %5s %9s %s' % \
651 ('Name', 'ID', 'VCPUs', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
653 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
654 ' %(cpu_time)8.1f %(cpumap)s'
656 for dom in dominfo:
657 def get_info(n):
658 return sxp.child_value(dom, n)
660 #
661 # convert a list of integers into a list of pairs indicating
662 # continuous sequences in the list:
663 #
664 # [0,1,2,3] -> [(0,3)]
665 # [1,2,4,5] -> [(1,2),(4,5)]
666 # [0] -> [(0,0)]
667 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
668 #
669 def list_to_rangepairs(cmap):
670 cmap.sort()
671 pairs = []
672 x = y = 0
673 for i in range(0,len(cmap)):
674 try:
675 if ((cmap[y+1] - cmap[i]) > 1):
676 pairs.append((cmap[x],cmap[y]))
677 x = y = i+1
678 else:
679 y = y + 1
680 # if we go off the end, then just add x to y
681 except IndexError:
682 pairs.append((cmap[x],cmap[y]))
684 return pairs
686 #
687 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
688 #
689 def format_pairs(pairs):
690 if not pairs:
691 return "no cpus"
692 out = ""
693 for f,s in pairs:
694 if (f==s):
695 out += '%d'%f
696 else:
697 out += '%d-%d'%(f,s)
698 out += ','
699 # trim trailing ','
700 return out[:-1]
702 def format_cpumap(cpumap):
703 cpumap = map(lambda x: int(x), cpumap)
704 cpumap.sort()
706 for x in server.xend.node.info()[1:]:
707 if len(x) > 1 and x[0] == 'nr_cpus':
708 nr_cpus = int(x[1])
709 # normalize cpumap by modulus nr_cpus, and drop duplicates
710 cpumap = dict.fromkeys(
711 map(lambda x: x % nr_cpus, cpumap)).keys()
712 if len(cpumap) == nr_cpus:
713 return "any cpu"
714 break
716 return format_pairs(list_to_rangepairs(cpumap))
718 name = get_info('name')
719 domid = int(get_info('domid'))
721 for vcpu in sxp.children(dom, 'vcpu'):
722 def vinfo(n, t):
723 return t(sxp.child_value(vcpu, n))
725 number = vinfo('number', int)
726 cpu = vinfo('cpu', int)
727 cpumap = format_cpumap(vinfo('cpumap', list))
728 online = vinfo('online', int)
729 cpu_time = vinfo('cpu_time', float)
730 running = vinfo('running', int)
731 blocked = vinfo('blocked', int)
733 if online:
734 c = str(cpu)
735 if running:
736 s = 'r'
737 else:
738 s = '-'
739 if blocked:
740 s += 'b'
741 else:
742 s += '-'
743 s += '-'
744 else:
745 c = "-"
746 s = "--p"
748 print format % locals()
750 def xm_start(args):
751 arg_check(args, "start", 1, 2)
753 try:
754 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
755 except getopt.GetoptError, opterr:
756 err(opterr)
757 sys.exit(1)
759 paused = False
760 for (k, v) in options:
761 if k in ['-p', '--paused']:
762 paused = True
764 if len(params) != 1:
765 err("Wrong number of parameters")
766 usage('start')
767 sys.exit(1)
769 dom = params[0]
770 server.xend.domain.start(dom, paused)
772 def xm_delete(args):
773 arg_check(args, "delete", 1)
774 dom = args[0]
775 server.xend.domain.delete(dom)
777 def xm_suspend(args):
778 arg_check(args, "suspend", 1)
779 dom = args[0]
780 server.xend.domain.suspend(dom)
782 def xm_resume(args):
783 arg_check(args, "resume", 1, 2)
785 try:
786 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
787 except getopt.GetoptError, opterr:
788 err(opterr)
789 sys.exit(1)
791 paused = False
792 for (k, v) in options:
793 if k in ['-p', '--paused']:
794 paused = True
796 if len(params) != 1:
797 err("Wrong number of parameters")
798 usage('resume')
799 sys.exit(1)
801 dom = params[0]
802 server.xend.domain.resume(dom, paused)
804 def xm_reboot(args):
805 arg_check(args, "reboot", 1, 3)
806 from xen.xm import shutdown
807 shutdown.main(["shutdown", "-R"] + args)
809 def xm_shutdown(args):
810 arg_check(args, "shutdown", 1, 4)
811 from xen.xm import shutdown
812 shutdown.main(["shutdown"] + args)
814 def xm_pause(args):
815 arg_check(args, "pause", 1)
816 dom = args[0]
818 server.xend.domain.pause(dom)
820 def xm_unpause(args):
821 arg_check(args, "unpause", 1)
822 dom = args[0]
824 server.xend.domain.unpause(dom)
826 def xm_dump_core(args):
827 live = False
828 crash = False
829 try:
830 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
831 for (k, v) in options:
832 if k in ('-L', '--live'):
833 live = True
834 if k in ('-C', '--crash'):
835 crash = True
837 if len(params) not in (1, 2):
838 raise OptionError("Expects 1 or 2 argument(s)")
839 except getopt.GetoptError, e:
840 raise OptionError(str(e))
842 dom = params[0]
843 if len(params) == 2:
844 filename = os.path.abspath(params[1])
845 else:
846 filename = None
848 if not live:
849 server.xend.domain.pause(dom)
851 try:
852 print "Dumping core of domain: %s ..." % str(dom)
853 server.xend.domain.dump(dom, filename, live, crash)
854 finally:
855 if not live:
856 server.xend.domain.unpause(dom)
858 if crash:
859 print "Destroying domain: %s ..." % str(dom)
860 server.xend.domain.destroy(dom)
862 def xm_rename(args):
863 arg_check(args, "rename", 2)
865 server.xend.domain.setName(args[0], args[1])
867 def xm_importcommand(command, args):
868 cmd = __import__(command, globals(), locals(), 'xen.xm')
869 cmd.main([command] + args)
872 #############################################################
874 def xm_vcpu_pin(args):
875 arg_check(args, "vcpu-pin", 3)
877 def cpu_make_map(cpulist):
878 cpus = []
879 for c in cpulist.split(','):
880 if c.find('-') != -1:
881 (x,y) = c.split('-')
882 for i in range(int(x),int(y)+1):
883 cpus.append(int(i))
884 else:
885 # remove this element from the list
886 if c[0] == '^':
887 cpus = [x for x in cpus if x != int(c[1:])]
888 else:
889 cpus.append(int(c))
890 cpus.sort()
891 return cpus
893 dom = args[0]
894 vcpu = args[1]
895 cpumap = cpu_make_map(args[2])
897 server.xend.domain.pincpu(dom, vcpu, cpumap)
899 def xm_mem_max(args):
900 arg_check(args, "mem-max", 2)
902 dom = args[0]
903 mem = int_unit(args[1], 'm')
905 server.xend.domain.maxmem_set(dom, mem)
907 def xm_mem_set(args):
908 arg_check(args, "mem-set", 2)
910 dom = args[0]
911 mem_target = int_unit(args[1], 'm')
913 server.xend.domain.setMemoryTarget(dom, mem_target)
915 def xm_vcpu_set(args):
916 arg_check(args, "vcpu-set", 2)
918 server.xend.domain.setVCpuCount(args[0], int(args[1]))
921 def xm_destroy(args):
922 arg_check(args, "destroy", 1)
923 server.xend.domain.destroy(args[0])
926 def xm_domid(args):
927 arg_check(args, "domid", 1)
929 name = args[0]
931 dom = server.xend.domain(name)
932 print sxp.child_value(dom, 'domid')
934 def xm_domname(args):
935 arg_check(args, "domname", 1)
937 name = args[0]
939 dom = server.xend.domain(name)
940 print sxp.child_value(dom, 'name')
942 def xm_sched_sedf(args):
943 def ns_to_ms(val):
944 return float(val) * 0.000001
946 def ms_to_ns(val):
947 return (float(val) / 0.000001)
949 def print_sedf(info):
950 info['period'] = ns_to_ms(info['period'])
951 info['slice'] = ns_to_ms(info['slice'])
952 info['latency'] = ns_to_ms(info['latency'])
953 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
954 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
956 def domid_match(domid, info):
957 return domid is None or domid == info['name'] or \
958 domid == str(info['domid'])
960 # we want to just display current info if no parameters are passed
961 if len(args) == 0:
962 domid = None
963 else:
964 # we expect at least a domain id (name or number)
965 # and at most a domid up to 5 options with values
966 arg_check(args, "sched-sedf", 1, 11)
967 domid = args[0]
968 # drop domid from args since get_opt doesn't recognize it
969 args = args[1:]
971 opts = {}
972 try:
973 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
974 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
975 except getopt.GetoptError, opterr:
976 err(opterr)
977 sys.exit(1)
979 # convert to nanoseconds if needed
980 for (k, v) in options:
981 if k in ['-p', '--period']:
982 opts['period'] = ms_to_ns(v)
983 elif k in ['-s', '--slice']:
984 opts['slice'] = ms_to_ns(v)
985 elif k in ['-l', '--latency']:
986 opts['latency'] = ms_to_ns(v)
987 elif k in ['-e', '--extratime']:
988 opts['extratime'] = v
989 elif k in ['-w', '--weight']:
990 opts['weight'] = v
992 doms = filter(lambda x : domid_match(domid, x),
993 [parse_doms_info(dom)
994 for dom in getDomains(None, 'running')])
996 # print header if we aren't setting any parameters
997 if len(opts.keys()) == 0:
998 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
999 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1000 'Extra','Weight')
1002 for d in doms:
1003 # fetch current values so as not to clobber them
1004 try:
1005 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1006 except xmlrpclib.Fault:
1007 # domain does not support sched-sedf?
1008 sedf_raw = {}
1010 sedf_info = parse_sedf_info(sedf_raw)
1011 sedf_info['name'] = d['name']
1012 # update values in case of call to set
1013 if len(opts.keys()) > 0:
1014 for k in opts.keys():
1015 sedf_info[k]=opts[k]
1017 # send the update, converting user input
1018 v = map(int, [sedf_info['period'], sedf_info['slice'],
1019 sedf_info['latency'],sedf_info['extratime'],
1020 sedf_info['weight']])
1021 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1022 if int(rv) != 0:
1023 err("Failed to set sedf parameters (rv=%d)."%(rv))
1025 # not setting values, display info
1026 else:
1027 print_sedf(sedf_info)
1029 def xm_sched_credit(args):
1030 """Get/Set options for Credit Scheduler."""
1032 try:
1033 opts, params = getopt.getopt(args, "d:w:c:",
1034 ["domain=", "weight=", "cap="])
1035 except getopt.GetoptError, opterr:
1036 err(opterr)
1037 usage('sched-credit')
1038 sys.exit(1)
1040 domain = None
1041 weight = None
1042 cap = None
1044 for o, a in opts:
1045 if o == "-d":
1046 domain = a
1047 elif o == "-w":
1048 weight = int(a)
1049 elif o == "-c":
1050 cap = int(a);
1052 if domain is None:
1053 # place holder for system-wide scheduler parameters
1054 err("No domain given.")
1055 usage('sched-credit')
1056 sys.exit(1)
1058 if weight is None and cap is None:
1059 print server.xend.domain.sched_credit_get(domain)
1060 else:
1061 result = server.xend.domain.sched_credit_set(domain, weight, cap)
1062 if result != 0:
1063 err(str(result))
1065 def xm_info(args):
1066 arg_check(args, "info", 0)
1068 info = server.xend.node.info()
1070 for x in info[1:]:
1071 if len(x) < 2:
1072 print "%-23s: (none)" % x[0]
1073 else:
1074 print "%-23s:" % x[0], x[1]
1076 def xm_console(args):
1077 arg_check(args, "console", 1, 2)
1079 quiet = False;
1081 try:
1082 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1083 except getopt.GetoptError, opterr:
1084 err(opterr)
1085 sys.exit(1)
1087 for (k, v) in options:
1088 if k in ['-q', '--quiet']:
1089 quiet = True
1090 else:
1091 assert False
1093 if len(params) != 1:
1094 err('No domain given')
1095 usage('console')
1096 sys.exit(1)
1098 dom = params[0]
1100 try:
1101 info = server.xend.domain(dom)
1102 except:
1103 if quiet:
1104 sys.exit(1)
1105 else:
1106 raise
1107 domid = int(sxp.child_value(info, 'domid', '-1'))
1108 if domid == -1:
1109 if quiet:
1110 sys.exit(1)
1111 else:
1112 raise Exception("Domain is not started")
1114 console.execConsole(domid)
1117 def xm_uptime(args):
1118 short_mode = 0
1120 try:
1121 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1122 except getopt.GetoptError, opterr:
1123 err(opterr)
1124 sys.exit(1)
1126 for (k, v) in options:
1127 if k in ['-s', '--short']:
1128 short_mode = 1
1130 doms = getDomains(params, 'running')
1132 if short_mode == 0:
1133 print 'Name ID Uptime'
1135 for dom in doms:
1136 d = parse_doms_info(dom)
1137 if d['domid'] > 0:
1138 uptime = int(round(d['up_time']))
1139 else:
1140 f=open('/proc/uptime', 'r')
1141 upfile = f.read()
1142 uptime = int(round(float(upfile.split(' ')[0])))
1143 f.close()
1145 days = int(uptime / 86400)
1146 uptime -= (days * 86400)
1147 hours = int(uptime / 3600)
1148 uptime -= (hours * 3600)
1149 minutes = int(uptime / 60)
1150 uptime -= (minutes * 60)
1151 seconds = uptime
1153 upstring = ""
1154 if days > 0:
1155 upstring += str(days) + " day"
1156 if days > 1:
1157 upstring += "s"
1158 upstring += ", "
1159 upstring += '%(hours)2d:%(minutes)02d' % vars()
1161 if short_mode:
1162 now = datetime.datetime.now()
1163 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1164 upstring += ", " + d['name'] + " (" + str(d['domid']) + ")"
1165 else:
1166 upstring += ':%(seconds)02d' % vars()
1167 upstring = ("%(name)-32s %(domid)3d " % d) + upstring
1169 print upstring
1171 def xm_sysrq(args):
1172 arg_check(args, "sysrq", 2)
1173 dom = args[0]
1174 req = args[1]
1175 server.xend.domain.send_sysrq(dom, req)
1177 def xm_top(args):
1178 arg_check(args, "top", 0)
1180 os.execvp('xentop', ['xentop'])
1182 def xm_dmesg(args):
1183 arg_check(args, "dmesg", 0, 1)
1185 try:
1186 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1187 except getopt.GetoptError, opterr:
1188 err(opterr)
1189 sys.exit(1)
1191 use_clear = 0
1192 for (k, v) in options:
1193 if k in ['-c', '--clear']:
1194 use_clear = 1
1196 if len(params) :
1197 err("No parameter required")
1198 usage('dmesg')
1199 sys.exit(1)
1201 if not use_clear:
1202 print server.xend.node.dmesg.info()
1203 else:
1204 server.xend.node.dmesg.clear()
1206 def xm_log(args):
1207 arg_check(args, "log", 0)
1209 print server.xend.node.log()
1211 def xm_serve(args):
1212 arg_check(args, "serve", 0)
1214 from fcntl import fcntl, F_SETFL
1216 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1217 s.connect(XendClient.XML_RPC_SOCKET)
1218 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1220 while True:
1221 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1222 if s in iwtd:
1223 data = s.recv(4096)
1224 if len(data) > 0:
1225 sys.stdout.write(data)
1226 sys.stdout.flush()
1227 else:
1228 break
1229 if sys.stdin in iwtd:
1230 data = sys.stdin.read(4096)
1231 if len(data) > 0:
1232 s.sendall(data)
1233 else:
1234 break
1235 s.close()
1237 def parse_dev_info(info):
1238 def get_info(n, t, d):
1239 i = 0
1240 while i < len(info):
1241 if (info[i][0] == n):
1242 return t(info[i][1])
1243 i = i + 1
1244 return t(d)
1245 return {
1246 #common
1247 'backend-id' : get_info('backend-id', int, -1),
1248 'handle' : get_info('handle', int, 0),
1249 'state' : get_info('state', int, -1),
1250 'be-path' : get_info('backend', str, '??'),
1251 'event-ch' : get_info('event-channel',int, -1),
1252 #network specific
1253 'virtual-device' : get_info('virtual-device', str, '??'),
1254 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1255 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1256 'mac' : get_info('mac', str, '??'),
1257 #block-device specific
1258 'ring-ref' : get_info('ring-ref', int, -1),
1261 def arg_check_for_resource_list(args, name):
1262 use_long = 0
1263 try:
1264 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1265 except getopt.GetoptError, opterr:
1266 err(opterr)
1267 sys.exit(1)
1269 for (k, v) in options:
1270 if k in ['-l', '--long']:
1271 use_long = 1
1273 if len(params) == 0:
1274 print 'No domain parameter given'
1275 usage(name)
1276 if len(params) > 1:
1277 print 'No multiple domain parameters allowed'
1278 usage(name)
1280 return (use_long, params)
1282 def xm_network_list(args):
1283 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1285 dom = params[0]
1286 if use_long:
1287 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1288 map(PrettyPrint.prettyprint, devs)
1289 else:
1290 hdr = 0
1291 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
1292 if hdr == 0:
1293 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1294 hdr = 1
1295 ni = parse_dev_info(x[1])
1296 ni['idx'] = int(x[0])
1297 print ("%(idx)-3d "
1298 "%(backend-id)-3d"
1299 "%(mac)-17s "
1300 "%(handle)-3d "
1301 "%(state)-3d "
1302 "%(event-ch)-3d "
1303 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1304 "%(be-path)-30s "
1305 % ni)
1307 def xm_block_list(args):
1308 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1310 dom = params[0]
1311 if use_long:
1312 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1313 map(PrettyPrint.prettyprint, devs)
1314 else:
1315 hdr = 0
1316 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
1317 if hdr == 0:
1318 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1319 hdr = 1
1320 ni = parse_dev_info(x[1])
1321 ni['idx'] = int(x[0])
1322 print ("%(idx)-3d "
1323 "%(backend-id)-3d "
1324 "%(handle)-3d "
1325 "%(state)-3d "
1326 "%(event-ch)-3d "
1327 "%(ring-ref)-5d "
1328 "%(be-path)-30s "
1329 % ni)
1331 def xm_vtpm_list(args):
1332 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1334 dom = params[0]
1335 if use_long:
1336 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1337 map(PrettyPrint.prettyprint, devs)
1338 else:
1339 hdr = 0
1340 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1341 if hdr == 0:
1342 print 'Idx BE handle state evt-ch ring-ref BE-path'
1343 hdr = 1
1344 ni = parse_dev_info(x[1])
1345 ni['idx'] = int(x[0])
1346 print ("%(idx)-3d "
1347 "%(backend-id)-3d "
1348 "%(handle)-3d "
1349 "%(state)-3d "
1350 "%(event-ch)-3d "
1351 "%(ring-ref)-5d "
1352 "%(be-path)-30s "
1353 % ni)
1356 def parse_block_configuration(args):
1357 dom = args[0]
1359 if args[1].startswith('tap:'):
1360 cls = 'tap'
1361 else:
1362 cls = 'vbd'
1364 vbd = [cls,
1365 ['uname', args[1]],
1366 ['dev', args[2]],
1367 ['mode', args[3]]]
1368 if len(args) == 5:
1369 vbd.append(['backend', args[4]])
1371 # verify that policy permits attaching this resource
1372 if security.on():
1373 dominfo = server.xend.domain(dom)
1374 label = security.get_security_printlabel(dominfo)
1375 else:
1376 label = None
1377 security.res_security_check(args[1], label)
1379 return (dom, vbd)
1382 def xm_block_attach(args):
1383 arg_check(args, 'block-attach', 4, 5)
1385 (dom, vbd) = parse_block_configuration(args)
1386 server.xend.domain.device_create(dom, vbd)
1389 def xm_block_configure(args):
1390 arg_check(args, 'block-configure', 4, 5)
1392 (dom, vbd) = parse_block_configuration(args)
1393 server.xend.domain.device_configure(dom, vbd)
1396 def xm_network_attach(args):
1397 arg_check(args, 'network-attach', 1, 10000)
1399 dom = args[0]
1400 vif = ['vif']
1402 for a in args[1:]:
1403 vif.append(a.split("="))
1405 server.xend.domain.device_create(dom, vif)
1408 def detach(args, command, deviceClass):
1409 arg_check(args, command, 2)
1411 dom = args[0]
1412 dev = args[1]
1414 server.xend.domain.destroyDevice(dom, deviceClass, dev)
1417 def xm_block_detach(args):
1418 detach(args, 'block-detach', 'vbd')
1421 def xm_network_detach(args):
1422 detach(args, 'network-detach', 'vif')
1425 def xm_vnet_list(args):
1426 try:
1427 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1428 except getopt.GetoptError, opterr:
1429 err(opterr)
1430 sys.exit(1)
1432 use_long = 0
1433 for (k, v) in options:
1434 if k in ['-l', '--long']:
1435 use_long = 1
1437 if params:
1438 use_long = 1
1439 vnets = params
1440 else:
1441 vnets = server.xend_vnets()
1443 for vnet in vnets:
1444 try:
1445 if use_long:
1446 info = server.xend_vnet(vnet)
1447 PrettyPrint.prettyprint(info)
1448 else:
1449 print vnet
1450 except Exception, ex:
1451 print vnet, ex
1453 def xm_vnet_create(args):
1454 arg_check(args, "vnet-create", 1)
1455 conf = args[0]
1456 if not os.access(conf, os.R_OK):
1457 print "File not found: %s" % conf
1458 sys.exit(1)
1460 server.xend_vnet_create(conf)
1462 def xm_vnet_delete(args):
1463 arg_check(args, "vnet-delete", 1)
1464 vnet = args[0]
1465 server.xend_vnet_delete(vnet)
1467 commands = {
1468 # console commands
1469 "console": xm_console,
1470 # xenstat commands
1471 "top": xm_top,
1472 # domain commands
1473 "delete": xm_delete,
1474 "destroy": xm_destroy,
1475 "domid": xm_domid,
1476 "domname": xm_domname,
1477 "dump-core": xm_dump_core,
1478 "reboot": xm_reboot,
1479 "rename": xm_rename,
1480 "restore": xm_restore,
1481 "resume": xm_resume,
1482 "save": xm_save,
1483 "shutdown": xm_shutdown,
1484 "start": xm_start,
1485 "sysrq": xm_sysrq,
1486 "uptime": xm_uptime,
1487 "suspend": xm_suspend,
1488 "list": xm_list,
1489 # memory commands
1490 "mem-max": xm_mem_max,
1491 "mem-set": xm_mem_set,
1492 # cpu commands
1493 "vcpu-pin": xm_vcpu_pin,
1494 "vcpu-list": xm_vcpu_list,
1495 "vcpu-set": xm_vcpu_set,
1496 # special
1497 "pause": xm_pause,
1498 "unpause": xm_unpause,
1499 # host commands
1500 "dmesg": xm_dmesg,
1501 "info": xm_info,
1502 "log": xm_log,
1503 "serve": xm_serve,
1504 # scheduler
1505 "sched-sedf": xm_sched_sedf,
1506 "sched-credit": xm_sched_credit,
1507 # block
1508 "block-attach": xm_block_attach,
1509 "block-detach": xm_block_detach,
1510 "block-list": xm_block_list,
1511 "block-configure": xm_block_configure,
1512 # network
1513 "network-attach": xm_network_attach,
1514 "network-detach": xm_network_detach,
1515 "network-list": xm_network_list,
1516 # vnet
1517 "vnet-list": xm_vnet_list,
1518 "vnet-create": xm_vnet_create,
1519 "vnet-delete": xm_vnet_delete,
1520 # vtpm
1521 "vtpm-list": xm_vtpm_list,
1524 ## The commands supported by a separate argument parser in xend.xm.
1525 IMPORTED_COMMANDS = [
1526 'create',
1527 'new',
1528 'migrate',
1529 'labels',
1530 'cfgbootpolicy',
1531 'makepolicy',
1532 'loadpolicy',
1533 'dumppolicy',
1534 'addlabel',
1535 'rmlabel',
1536 'getlabel',
1537 'dry-run',
1538 'resources',
1541 for c in IMPORTED_COMMANDS:
1542 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
1544 aliases = {
1545 "balloon": "mem-set",
1546 "set-vcpus": "vcpu-set",
1547 "vif-list": "network-list",
1548 "vbd-create": "block-attach",
1549 "vbd-destroy": "block-detach",
1550 "vbd-list": "block-list",
1554 def xm_lookup_cmd(cmd):
1555 if commands.has_key(cmd):
1556 return commands[cmd]
1557 elif aliases.has_key(cmd):
1558 deprecated(cmd,aliases[cmd])
1559 return commands[aliases[cmd]]
1560 elif cmd == 'help':
1561 longHelp()
1562 sys.exit(0)
1563 else:
1564 # simulate getopt's prefix matching behaviour
1565 if len(cmd) > 1:
1566 same_prefix_cmds = [commands[c] for c in commands.keys() \
1567 if c[:len(cmd)] == cmd]
1568 # only execute if there is only 1 match
1569 if len(same_prefix_cmds) == 1:
1570 return same_prefix_cmds[0]
1572 err('Sub Command %s not found!' % cmd)
1573 usage()
1575 def deprecated(old,new):
1576 print >>sys.stderr, (
1577 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1579 def main(argv=sys.argv):
1580 if len(argv) < 2:
1581 usage()
1583 # intercept --help(-h) and output our own help
1584 for help in ['--help', '-h']:
1585 if help in argv[1:]:
1586 if help == argv[1]:
1587 longHelp()
1588 else:
1589 usage(argv[1])
1590 sys.exit(0)
1592 cmd = xm_lookup_cmd(argv[1])
1594 # strip off prog name and subcmd
1595 args = argv[2:]
1596 if cmd:
1597 try:
1598 rc = cmd(args)
1599 if rc:
1600 usage()
1601 except socket.error, ex:
1602 if os.geteuid() != 0:
1603 err("Most commands need root access. Please try again as root.")
1604 else:
1605 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
1606 sys.exit(1)
1607 except KeyboardInterrupt:
1608 print "Interrupted."
1609 sys.exit(1)
1610 except IOError, ex:
1611 if os.geteuid() != 0:
1612 err("Most commands need root access. Please try again as root.")
1613 else:
1614 err("Unable to connect to xend: %s." % ex[1])
1615 sys.exit(1)
1616 except SystemExit:
1617 sys.exit(1)
1618 except xmlrpclib.Fault, ex:
1619 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
1620 err("Domain '%s' does not exist." % ex.faultString)
1621 else:
1622 err(ex.faultString)
1623 usage(argv[1])
1624 sys.exit(1)
1625 except xmlrpclib.ProtocolError, ex:
1626 if ex.errcode == -1:
1627 print >>sys.stderr, (
1628 "Xend has probably crashed! Invalid or missing HTTP "
1629 "status code.")
1630 else:
1631 print >>sys.stderr, (
1632 "Xend has probably crashed! ProtocolError(%d, %s)." %
1633 (ex.errcode, ex.errmsg))
1634 sys.exit(1)
1635 except (ValueError, OverflowError):
1636 err("Invalid argument.")
1637 usage(argv[1])
1638 sys.exit(1)
1639 except OptionError, e:
1640 err(str(e))
1641 usage(argv[1])
1642 print e.usage()
1643 sys.exit(1)
1644 except security.ACMError, e:
1645 err(str(e))
1646 sys.exit(1)
1647 except:
1648 print "Unexpected error:", sys.exc_info()[0]
1649 print
1650 print "Please report to xen-devel@lists.xensource.com"
1651 raise
1653 else:
1654 usage()
1656 if __name__ == "__main__":
1657 main()