ia64/xen-unstable

view tools/python/xen/xm/main.py @ 14492:92f14ace389c

Fix xm network-list through the Xen-API for managed domains.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Mar 20 17:34:34 2007 +0000 (2007-03-20)
parents 07d1bd92ade8
children 3fd9b0c71b8c
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 atexit
25 import cmd
26 import os
27 import pprint
28 import readline
29 import shlex
30 import sys
31 import re
32 import getopt
33 import socket
34 import traceback
35 import xmlrpclib
36 import time
37 import datetime
38 from select import select
39 import xml.dom.minidom
40 from xen.util.blkif import blkdev_name_to_number
42 import warnings
43 warnings.filterwarnings('ignore', category=FutureWarning)
45 from xen.xend import PrettyPrint
46 from xen.xend import sxp
47 from xen.xend import XendClient
48 from xen.xend.XendConstants import *
50 from xen.xm.opts import OptionError, Opts, wrap, set_true
51 from xen.xm import console
52 from xen.util.xmlrpclib2 import ServerProxy
54 import XenAPI
57 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
58 # getopt.getopt if gnu_getopt is not available. This will mean that options
59 # may only be specified before positional arguments.
60 if not hasattr(getopt, 'gnu_getopt'):
61 getopt.gnu_getopt = getopt.getopt
63 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
64 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
66 # Supported types of server
67 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
68 SERVER_XEN_API = 'Xen-API'
70 # General help message
72 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
73 "Control, list, and manipulate Xen guest instances.\n"
75 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
76 'For more help on \'xm\' see the xm(1) man page.\n' \
77 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
78 ' man page.\n'
80 # Help strings are indexed by subcommand name in this way:
81 # 'subcommand': (argstring, description)
83 SUBCOMMAND_HELP = {
84 # common commands
86 'shell' : ('', 'Launch an interactive shell.'),
88 'console' : ('[-q|--quiet] <Domain>',
89 'Attach to <Domain>\'s console.'),
90 'create' : ('<ConfigFile> [options] [vars]',
91 'Create a domain based on <ConfigFile>.'),
92 'destroy' : ('<Domain>',
93 'Terminate a domain immediately.'),
94 'help' : ('', 'Display this message.'),
95 'list' : ('[options] [Domain, ...]',
96 'List information about all/some domains.'),
97 'mem-max' : ('<Domain> <Mem>',
98 'Set the maximum amount reservation for a domain.'),
99 'mem-set' : ('<Domain> <Mem>',
100 'Set the current memory usage for a domain.'),
101 'migrate' : ('<Domain> <Host>',
102 'Migrate a domain to another machine.'),
103 'pause' : ('<Domain>', 'Pause execution of a domain.'),
104 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
105 'restore' : ('<CheckpointFile> [-p]',
106 'Restore a domain from a saved state.'),
107 'save' : ('[-c] <Domain> <CheckpointFile>',
108 'Save a domain state to restore later.'),
109 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
110 'top' : ('', 'Monitor a host and the domains in real time.'),
111 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
112 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
114 # Life cycle xm commands
115 'new' : ('<ConfigFile> [options] [vars]',
116 'Adds a domain to Xend domain management'),
117 'delete' : ('<DomainName>',
118 'Remove a domain from Xend domain management.'),
119 'start' : ('<DomainName>', 'Start a Xend managed domain'),
120 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
121 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
123 # less used commands
125 'dmesg' : ('[-c|--clear]',
126 'Read and/or clear Xend\'s message buffer.'),
127 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
128 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
129 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
130 'Dump core for a specific domain.'),
131 'info' : ('', 'Get information about Xen host.'),
132 'log' : ('', 'Print Xend log'),
133 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
134 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
135 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
136 'Get/set credit scheduler parameters.'),
137 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
138 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
139 'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
140 'Send a trigger to a domain.'),
141 'vcpu-list' : ('[<Domain>]',
142 'List the VCPUs for a domain or all domains.'),
143 'vcpu-pin' : ('<Domain> <VCPU> <CPUs|all>',
144 'Set which CPUs a VCPU can use.'),
145 'vcpu-set' : ('<Domain> <vCPUs>',
146 'Set the number of active VCPUs for allowed for the'
147 ' domain.'),
149 # device commands
151 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
152 'Create a new virtual block device.'),
153 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
154 'Change block device configuration'),
155 'block-detach' : ('<Domain> <DevId> [-f|--force]',
156 'Destroy a domain\'s virtual block device.'),
157 'block-list' : ('<Domain> [--long]',
158 'List virtual block devices for a domain.'),
159 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
160 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
161 '[vifname=<name>] [rate=<rate>] [model=<model>]',
162 'Create a new virtual network device.'),
163 'network-detach': ('<Domain> <DevId> [-f|--force]',
164 'Destroy a domain\'s virtual network device.'),
165 'network-list' : ('<Domain> [--long]',
166 'List virtual network interfaces for a domain.'),
167 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
168 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
169 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
170 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
172 # security
174 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
175 'Add security label to domain.'),
176 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
177 'Remove a security label from domain.'),
178 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
179 'Show security label for domain or resource.'),
180 'dry-run' : ('<ConfigFile>',
181 'Test if a domain can access its resources.'),
182 'resources' : ('', 'Show info for each labeled resource.'),
183 'cfgbootpolicy' : ('<policy> [boot-title]',
184 'Add policy to boot configuration.'),
185 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
186 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
187 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
188 'files.'),
189 'labels' : ('[policy] [type=dom|res|any]',
190 'List <type> labels for (active) policy.'),
191 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
192 }
194 SUBCOMMAND_OPTIONS = {
195 'sched-sedf': (
196 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
197 ('-s [MS]', '--slice[=MS]' ,
198 'Worst-case execution time(ms). (slice < period)'),
199 ('-l [MS]', '--latency[=MS]',
200 'Scaled period (ms) when domain performs heavy I/O'),
201 ('-e [FLAG]', '--extra[=FLAG]',
202 'Flag (0 or 1) controls if domain can run in extra time.'),
203 ('-w [FLOAT]', '--weight[=FLOAT]',
204 'CPU Period/slice (do not set with --period/--slice)'),
205 ),
206 'sched-credit': (
207 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
208 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
209 ('-c CAP', '--cap=CAP', 'Cap (int)'),
210 ),
211 'list': (
212 ('-l', '--long', 'Output all VM details in SXP'),
213 ('', '--label', 'Include security labels'),
214 ('', '--state=<state>', 'Select only VMs with the specified state'),
215 ),
216 'console': (
217 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
218 ),
219 'dmesg': (
220 ('-c', '--clear', 'Clear dmesg buffer'),
221 ),
222 'vnet-list': (
223 ('-l', '--long', 'List Vnets as SXP'),
224 ),
225 'network-list': (
226 ('-l', '--long', 'List resources as SXP'),
227 ),
228 'dump-core': (
229 ('-L', '--live', 'Dump core without pausing the domain'),
230 ('-C', '--crash', 'Crash domain after dumping core'),
231 ),
232 'start': (
233 ('-p', '--paused', 'Do not unpause domain after starting it'),
234 ),
235 'resume': (
236 ('-p', '--paused', 'Do not unpause domain after resuming it'),
237 ),
238 'save': (
239 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
240 ),
241 'restore': (
242 ('-p', '--paused', 'Do not unpause domain after restoring it'),
243 ),
244 }
246 common_commands = [
247 "console",
248 "create",
249 "new",
250 "delete",
251 "destroy",
252 "dump-core",
253 "help",
254 "list",
255 "mem-set",
256 "migrate",
257 "pause",
258 "reboot",
259 "restore",
260 "resume",
261 "save",
262 "shell",
263 "shutdown",
264 "start",
265 "suspend",
266 "top",
267 "unpause",
268 "uptime",
269 "vcpu-set",
270 ]
272 domain_commands = [
273 "console",
274 "create",
275 "new",
276 "delete",
277 "destroy",
278 "domid",
279 "domname",
280 "dump-core",
281 "list",
282 "mem-max",
283 "mem-set",
284 "migrate",
285 "pause",
286 "reboot",
287 "rename",
288 "restore",
289 "resume",
290 "save",
291 "shutdown",
292 "start",
293 "suspend",
294 "sysrq",
295 "trigger",
296 "top",
297 "unpause",
298 "uptime",
299 "vcpu-list",
300 "vcpu-pin",
301 "vcpu-set",
302 ]
304 host_commands = [
305 "debug-keys",
306 "dmesg",
307 "info",
308 "log",
309 "serve",
310 ]
312 scheduler_commands = [
313 "sched-credit",
314 "sched-sedf",
315 ]
317 device_commands = [
318 "block-attach",
319 "block-detach",
320 "block-list",
321 "block-configure",
322 "network-attach",
323 "network-detach",
324 "network-list",
325 "vtpm-list",
326 ]
328 vnet_commands = [
329 "vnet-list",
330 "vnet-create",
331 "vnet-delete",
332 ]
334 acm_commands = [
335 "labels",
336 "addlabel",
337 "rmlabel",
338 "getlabel",
339 "dry-run",
340 "resources",
341 "makepolicy",
342 "loadpolicy",
343 "cfgbootpolicy",
344 "dumppolicy",
345 ]
347 all_commands = (domain_commands + host_commands + scheduler_commands +
348 device_commands + vnet_commands + acm_commands + ['shell'])
351 ##
352 # Configuration File Parsing
353 ##
355 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
356 config = None
357 if os.path.isfile(xmConfigFile):
358 try:
359 config = xml.dom.minidom.parse(xmConfigFile)
360 except:
361 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
362 xmConfigFile)
364 def parseServer():
365 if config:
366 server = config.getElementsByTagName('server')
367 if server:
368 st = server[0].getAttribute('type')
369 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
370 print >>sys.stderr, ('Invalid server type %s; using %s.' %
371 (st, SERVER_LEGACY_XMLRPC))
372 st = SERVER_LEGACY_XMLRPC
373 return (st, server[0].getAttribute('uri'))
375 return SERVER_LEGACY_XMLRPC, XendClient.uri
377 def parseAuthentication():
378 server = config.getElementsByTagName('server')[0]
379 return (server.getAttribute('username'),
380 server.getAttribute('password'))
382 serverType, serverURI = parseServer()
383 server = None
386 ####################################################################
387 #
388 # Help/usage printing functions
389 #
390 ####################################################################
392 def cmdHelp(cmd):
393 """Print help for a specific subcommand."""
395 for fc in SUBCOMMAND_HELP.keys():
396 if fc[:len(cmd)] == cmd:
397 cmd = fc
398 break
400 try:
401 args, desc = SUBCOMMAND_HELP[cmd]
402 except KeyError:
403 shortHelp()
404 return
406 print 'Usage: xm %s %s' % (cmd, args)
407 print
408 print desc
410 try:
411 # If options help message is defined, print this.
412 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
413 if shortopt and longopt:
414 optdesc = '%s, %s' % (shortopt, longopt)
415 elif shortopt:
416 optdesc = shortopt
417 elif longopt:
418 optdesc = longopt
420 wrapped_desc = wrap(desc, 43)
421 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
422 for line in wrapped_desc[1:]:
423 print ' ' * 33 + line
424 print
425 except KeyError:
426 # if the command is an external module, we grab usage help
427 # from the module itself.
428 if cmd in IMPORTED_COMMANDS:
429 try:
430 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
431 cmd_usage = getattr(cmd_module, "help", None)
432 if cmd_usage:
433 print cmd_usage()
434 except ImportError:
435 pass
437 def shortHelp():
438 """Print out generic help when xm is called without subcommand."""
440 print USAGE_HELP
441 print 'Common \'xm\' commands:\n'
443 for command in common_commands:
444 try:
445 args, desc = SUBCOMMAND_HELP[command]
446 except KeyError:
447 continue
448 wrapped_desc = wrap(desc, 50)
449 print ' %-20s %-50s' % (command, wrapped_desc[0])
450 for line in wrapped_desc[1:]:
451 print ' ' * 22 + line
453 print
454 print USAGE_FOOTER
455 print 'For a complete list of subcommands run \'xm help\'.'
457 def longHelp():
458 """Print out full help when xm is called with xm --help or xm help"""
460 print USAGE_HELP
461 print 'xm full list of subcommands:\n'
463 for command in all_commands:
464 try:
465 args, desc = SUBCOMMAND_HELP[command]
466 except KeyError:
467 continue
469 wrapped_desc = wrap(desc, 50)
470 print ' %-20s %-50s' % (command, wrapped_desc[0])
471 for line in wrapped_desc[1:]:
472 print ' ' * 22 + line
474 print
475 print USAGE_FOOTER
477 def _usage(cmd):
478 """ Print help usage information """
479 if cmd:
480 cmdHelp(cmd)
481 else:
482 shortHelp()
484 def usage(cmd = None):
485 """ Print help usage information and exits """
486 _usage(cmd)
487 sys.exit(1)
490 ####################################################################
491 #
492 # Utility functions
493 #
494 ####################################################################
496 def get_default_SR():
497 return [sr_ref
498 for sr_ref in server.xenapi.SR.get_all()
499 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
501 def get_default_Network():
502 return [network_ref
503 for network_ref in server.xenapi.network.get_all()][0]
505 def map2sxp(m):
506 return [[k, m[k]] for k in m.keys()]
508 def arg_check(args, name, lo, hi = -1):
509 n = len([i for i in args if i != '--'])
511 if hi == -1:
512 if n != lo:
513 err("'xm %s' requires %d argument%s.\n" % (name, lo,
514 lo == 1 and '' or 's'))
515 usage(name)
516 else:
517 if n < lo or n > hi:
518 err("'xm %s' requires between %d and %d arguments.\n" %
519 (name, lo, hi))
520 usage(name)
523 def unit(c):
524 if not c.isalpha():
525 return 0
526 base = 1
527 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
528 elif c == 'M' or c == 'm': base = 1024 * 1024
529 elif c == 'K' or c == 'k': base = 1024
530 else:
531 print 'ignoring unknown unit'
532 return base
534 def int_unit(str, dest):
535 base = unit(str[-1])
536 if not base:
537 return int(str)
539 value = int(str[:-1])
540 dst_base = unit(dest)
541 if dst_base == 0:
542 dst_base = 1
543 if dst_base > base:
544 return value / (dst_base / base)
545 else:
546 return value * (base / dst_base)
548 def err(msg):
549 print >>sys.stderr, "Error:", msg
552 def get_single_vm(dom):
553 uuids = server.xenapi.VM.get_by_name_label(dom)
554 n = len(uuids)
555 if n == 1:
556 return uuids[0]
557 else:
558 dominfo = server.xend.domain(dom, False)
559 return dominfo['uuid']
561 ##
562 #
563 # Xen-API Shell
564 #
565 ##
567 class Shell(cmd.Cmd):
568 def __init__(self):
569 cmd.Cmd.__init__(self)
570 self.prompt = "xm> "
571 if serverType == SERVER_XEN_API:
572 res = server.xenapi._UNSUPPORTED_list_all_methods()
573 for f in res:
574 setattr(Shell, 'do_' + f + ' ', self.default)
576 def preloop(self):
577 cmd.Cmd.preloop(self)
578 readline.set_completer_delims(' ')
580 def default(self, line):
581 words = shlex.split(line)
582 if len(words) > 0 and words[0] == 'xm':
583 words = words[1:]
584 if len(words) > 0:
585 cmd = xm_lookup_cmd(words[0])
586 if cmd:
587 _run_cmd(cmd, words[0], words[1:])
588 elif serverType == SERVER_XEN_API:
589 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
590 tuple(x)),
591 words[0], words[1:])
592 if ok and res is not None and res != '':
593 pprint.pprint(res)
594 else:
595 print '*** Unknown command: %s' % words[0]
596 return False
598 def completedefault(self, text, line, begidx, endidx):
599 words = shlex.split(line[:begidx])
600 clas, func = words[0].split('.')
601 if len(words) > 1 or \
602 func.startswith('get_by_') or \
603 func == 'get_all':
604 return []
605 uuids = server.xenapi_request('%s.get_all' % clas, ())
606 return [u + " " for u in uuids if u.startswith(text)]
608 def emptyline(self):
609 pass
611 def do_EOF(self, line):
612 print
613 sys.exit(0)
615 def do_help(self, line):
616 _usage(line)
619 def xm_shell(args):
620 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
623 #########################################################################
624 #
625 # Main xm functions
626 #
627 #########################################################################
629 def xm_save(args):
630 arg_check(args, "save", 2, 3)
632 try:
633 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
634 except getopt.GetoptError, opterr:
635 err(opterr)
636 sys.exit(1)
638 checkpoint = False
639 for (k, v) in options:
640 if k in ['-c', '--checkpoint']:
641 checkpoint = True
643 if len(params) != 2:
644 err("Wrong number of parameters")
645 usage('save')
646 sys.exit(1)
648 try:
649 dominfo = parse_doms_info(server.xend.domain(params[0]))
650 except xmlrpclib.Fault, ex:
651 raise ex
653 domid = dominfo['domid']
654 savefile = os.path.abspath(params[1])
656 if not os.access(os.path.dirname(savefile), os.W_OK):
657 err("xm save: Unable to create file %s" % savefile)
658 sys.exit(1)
660 server.xend.domain.save(domid, savefile, checkpoint)
662 def xm_restore(args):
663 arg_check(args, "restore", 1, 2)
665 try:
666 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
667 except getopt.GetoptError, opterr:
668 err(opterr)
669 usage('restore')
671 paused = False
672 for (k, v) in options:
673 if k in ['-p', '--paused']:
674 paused = True
676 if len(params) != 1:
677 err("Wrong number of parameters")
678 usage('restore')
680 savefile = os.path.abspath(params[0])
682 if not os.access(savefile, os.R_OK):
683 err("xm restore: Unable to read file %s" % savefile)
684 sys.exit(1)
686 server.xend.domain.restore(savefile, paused)
689 def getDomains(domain_names, state, full = 0):
690 if serverType == SERVER_XEN_API:
691 doms_sxp = []
692 doms_dict = []
693 dom_refs = server.xenapi.VM.get_all()
694 for dom_ref in dom_refs:
695 dom_rec = server.xenapi.VM.get_record(dom_ref)
696 dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref)
697 dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref)
698 dom_rec.update({'name': dom_rec['name_label'],
699 'memory_actual': int(dom_metrics['memory_actual'])/1024,
700 'vcpus': dom_metrics['vcpus_number'],
701 'state': '-----',
702 'cpu_time': dom_metrics['vcpus_utilisation']})
704 doms_sxp.append(['domain'] + map2sxp(dom_rec))
705 doms_dict.append(dom_rec)
707 if domain_names:
708 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
709 if dom["name"] in domain_names]
711 if len(doms) > 0:
712 return doms
713 else:
714 print "Error: no domain%s named %s" % \
715 (len(domain_names) > 1 and 's' or '',
716 ', '.join(domain_names))
717 sys.exit(-1)
718 else:
719 return doms_sxp
720 else:
721 if domain_names:
722 return [server.xend.domain(dom, full) for dom in domain_names]
723 else:
724 return server.xend.domains_with_state(True, state, full)
727 def xm_list(args):
728 use_long = 0
729 show_vcpus = 0
730 show_labels = 0
731 state = 'all'
732 try:
733 (options, params) = getopt.gnu_getopt(args, 'lv',
734 ['long','vcpus','label',
735 'state='])
736 except getopt.GetoptError, opterr:
737 err(opterr)
738 usage('list')
740 for (k, v) in options:
741 if k in ['-l', '--long']:
742 use_long = 1
743 if k in ['-v', '--vcpus']:
744 show_vcpus = 1
745 if k in ['--label']:
746 show_labels = 1
747 if k in ['--state']:
748 state = v
750 if state != 'all' and len(params) > 0:
751 raise OptionError(
752 "You may specify either a state or a particular VM, but not both")
754 if show_vcpus:
755 print >>sys.stderr, (
756 "xm list -v is deprecated. Please use xm vcpu-list.")
757 xm_vcpu_list(params)
758 return
760 doms = getDomains(params, state, use_long)
762 if use_long:
763 map(PrettyPrint.prettyprint, doms)
764 elif show_labels:
765 xm_label_list(doms)
766 else:
767 xm_brief_list(doms)
770 def parse_doms_info(info):
771 def get_info(n, t, d):
772 return t(sxp.child_value(info, n, d))
774 def get_status(n, t, d):
775 return DOM_STATES[t(sxp.child_value(info, n, d))]
777 start_time = get_info('start_time', float, -1)
778 if start_time == -1:
779 up_time = float(-1)
780 else:
781 up_time = time.time() - start_time
783 parsed_info = {
784 'domid' : get_info('domid', str, ''),
785 'name' : get_info('name', str, '??'),
786 'state' : get_info('state', str, ''),
788 # VCPUs is the number online when the VM is up, or the number
789 # configured otherwise.
790 'vcpus' : get_info('online_vcpus', int,
791 get_info('vcpus', int, 0)),
792 'up_time' : up_time
793 }
795 # We're not supporting security stuff just yet via XenAPI
797 if serverType != SERVER_XEN_API:
798 from xen.util import security
799 parsed_info['seclabel'] = security.get_security_printlabel(info)
800 else:
801 parsed_info['seclabel'] = ""
803 if serverType == SERVER_XEN_API:
804 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
805 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
806 if sum(cpu_times.values()) > 0:
807 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
808 else:
809 parsed_info['cpu_time'] = 0
810 else:
811 parsed_info['mem'] = get_info('memory', int,0)
812 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
814 return parsed_info
816 def check_sched_type(sched):
817 if serverType == SERVER_XEN_API:
818 current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host())
819 else:
820 current = 'unknown'
821 for x in server.xend.node.info()[1:]:
822 if len(x) > 1 and x[0] == 'xen_scheduler':
823 current = x[1]
824 break
825 if sched != current:
826 err("Xen is running with the %s scheduler" % current)
827 sys.exit(1)
829 def parse_sedf_info(info):
830 def get_info(n, t, d):
831 return t(sxp.child_value(info, n, d))
833 return {
834 'domid' : get_info('domid', int, -1),
835 'period' : get_info('period', int, -1),
836 'slice' : get_info('slice', int, -1),
837 'latency' : get_info('latency', int, -1),
838 'extratime': get_info('extratime', int, -1),
839 'weight' : get_info('weight', int, -1),
840 }
842 def domid_match(domid, info):
843 return domid is None or domid == info['name'] or \
844 domid == str(info['domid'])
846 def xm_brief_list(doms):
847 print '%-40s %3s %5s %5s %10s %9s' % \
848 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
850 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
851 "%(cpu_time)8.1f"
853 for dom in doms:
854 d = parse_doms_info(dom)
855 print format % d
857 def xm_label_list(doms):
858 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
859 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
861 output = []
862 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
863 '%(cpu_time)8.1f %(seclabel)9s'
865 if serverType != SERVER_XEN_API:
866 from xen.util import security
868 for dom in doms:
869 d = parse_doms_info(dom)
871 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
872 if not d['seclabel']:
873 d['seclabel'] = 'ERROR'
874 elif security.active_policy in ['DEFAULT']:
875 d['seclabel'] = 'DEFAULT'
876 else:
877 d['seclabel'] = 'INACTIVE'
879 output.append((format % d, d['seclabel']))
881 #sort by labels
882 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
883 for line, label in output:
884 print line
887 def xm_vcpu_list(args):
888 if args:
889 dominfo = map(server.xend.domain.getVCPUInfo, args)
890 else:
891 doms = server.xend.domains(False)
892 dominfo = map(server.xend.domain.getVCPUInfo, doms)
894 print '%-32s %3s %5s %5s %5s %9s %s' % \
895 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
897 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
898 ' %(cpu_time)8.1f %(cpumap)s'
900 for dom in dominfo:
901 def get_info(n):
902 return sxp.child_value(dom, n)
904 #
905 # convert a list of integers into a list of pairs indicating
906 # continuous sequences in the list:
907 #
908 # [0,1,2,3] -> [(0,3)]
909 # [1,2,4,5] -> [(1,2),(4,5)]
910 # [0] -> [(0,0)]
911 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
912 #
913 def list_to_rangepairs(cmap):
914 cmap.sort()
915 pairs = []
916 x = y = 0
917 for i in range(0,len(cmap)):
918 try:
919 if ((cmap[y+1] - cmap[i]) > 1):
920 pairs.append((cmap[x],cmap[y]))
921 x = y = i+1
922 else:
923 y = y + 1
924 # if we go off the end, then just add x to y
925 except IndexError:
926 pairs.append((cmap[x],cmap[y]))
928 return pairs
930 #
931 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
932 #
933 def format_pairs(pairs):
934 if not pairs:
935 return "no cpus"
936 out = ""
937 for f,s in pairs:
938 if (f==s):
939 out += '%d'%f
940 else:
941 out += '%d-%d'%(f,s)
942 out += ','
943 # trim trailing ','
944 return out[:-1]
946 def format_cpumap(cpumap):
947 cpumap = map(lambda x: int(x), cpumap)
948 cpumap.sort()
950 for x in server.xend.node.info()[1:]:
951 if len(x) > 1 and x[0] == 'nr_cpus':
952 nr_cpus = int(x[1])
953 # normalize cpumap by modulus nr_cpus, and drop duplicates
954 cpumap = dict.fromkeys(
955 map(lambda x: x % nr_cpus, cpumap)).keys()
956 if len(cpumap) == nr_cpus:
957 return "any cpu"
958 break
960 return format_pairs(list_to_rangepairs(cpumap))
962 name = get_info('name')
963 domid = int(get_info('domid'))
965 for vcpu in sxp.children(dom, 'vcpu'):
966 def vinfo(n, t):
967 return t(sxp.child_value(vcpu, n))
969 number = vinfo('number', int)
970 cpu = vinfo('cpu', int)
971 cpumap = format_cpumap(vinfo('cpumap', list))
972 online = vinfo('online', int)
973 cpu_time = vinfo('cpu_time', float)
974 running = vinfo('running', int)
975 blocked = vinfo('blocked', int)
977 if online:
978 c = str(cpu)
979 if running:
980 s = 'r'
981 else:
982 s = '-'
983 if blocked:
984 s += 'b'
985 else:
986 s += '-'
987 s += '-'
988 else:
989 c = "-"
990 s = "--p"
992 print format % locals()
994 def xm_start(args):
995 arg_check(args, "start", 1, 2)
997 try:
998 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
999 except getopt.GetoptError, opterr:
1000 err(opterr)
1001 usage('start')
1003 paused = False
1004 for (k, v) in options:
1005 if k in ['-p', '--paused']:
1006 paused = True
1008 if len(params) != 1:
1009 err("Wrong number of parameters")
1010 usage('start')
1012 dom = params[0]
1013 if serverType == SERVER_XEN_API:
1014 server.xenapi.VM.start(get_single_vm(dom), paused)
1015 else:
1016 server.xend.domain.start(dom, paused)
1018 def xm_delete(args):
1019 arg_check(args, "delete", 1)
1020 dom = args[0]
1021 if serverType == SERVER_XEN_API:
1022 server.xenapi.VM.destroy(get_single_vm(dom))
1023 else:
1024 server.xend.domain.delete(dom)
1026 def xm_suspend(args):
1027 arg_check(args, "suspend", 1)
1028 dom = args[0]
1029 if serverType == SERVER_XEN_API:
1030 server.xenapi.VM.suspend(get_single_vm(dom))
1031 else:
1032 server.xend.domain.suspend(dom)
1034 def xm_resume(args):
1035 arg_check(args, "resume", 1, 2)
1037 try:
1038 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1039 except getopt.GetoptError, opterr:
1040 err(opterr)
1041 usage('resume')
1043 paused = False
1044 for (k, v) in options:
1045 if k in ['-p', '--paused']:
1046 paused = True
1048 if len(params) != 1:
1049 err("Wrong number of parameters")
1050 usage('resume')
1052 dom = params[0]
1053 if serverType == SERVER_XEN_API:
1054 server.xenapi.VM.resume(get_single_vm(dom), paused)
1055 else:
1056 server.xend.domain.resume(dom, paused)
1058 def xm_reboot(args):
1059 arg_check(args, "reboot", 1, 3)
1060 from xen.xm import shutdown
1061 shutdown.main(["shutdown", "-R"] + args)
1063 def xm_shutdown(args):
1064 arg_check(args, "shutdown", 1, 4)
1065 from xen.xm import shutdown
1066 shutdown.main(["shutdown"] + args)
1068 def xm_pause(args):
1069 arg_check(args, "pause", 1)
1070 dom = args[0]
1072 if serverType == SERVER_XEN_API:
1073 server.xenapi.VM.pause(get_single_vm(dom))
1074 else:
1075 server.xend.domain.pause(dom)
1077 def xm_unpause(args):
1078 arg_check(args, "unpause", 1)
1079 dom = args[0]
1081 if serverType == SERVER_XEN_API:
1082 server.xenapi.VM.unpause(get_single_vm(dom))
1083 else:
1084 server.xend.domain.unpause(dom)
1086 def xm_dump_core(args):
1087 live = False
1088 crash = False
1089 try:
1090 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1091 for (k, v) in options:
1092 if k in ('-L', '--live'):
1093 live = True
1094 if k in ('-C', '--crash'):
1095 crash = True
1097 if len(params) not in (1, 2):
1098 raise OptionError("Expects 1 or 2 argument(s)")
1099 except getopt.GetoptError, e:
1100 raise OptionError(str(e))
1102 dom = params[0]
1103 if len(params) == 2:
1104 filename = os.path.abspath(params[1])
1105 else:
1106 filename = None
1108 if not live:
1109 server.xend.domain.pause(dom)
1111 try:
1112 print "Dumping core of domain: %s ..." % str(dom)
1113 server.xend.domain.dump(dom, filename, live, crash)
1114 finally:
1115 if not live:
1116 server.xend.domain.unpause(dom)
1118 if crash:
1119 print "Destroying domain: %s ..." % str(dom)
1120 server.xend.domain.destroy(dom)
1122 def xm_rename(args):
1123 arg_check(args, "rename", 2)
1125 if serverType == SERVER_XEN_API:
1126 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1127 else:
1128 server.xend.domain.setName(args[0], args[1])
1130 def xm_importcommand(command, args):
1131 cmd = __import__(command, globals(), locals(), 'xen.xm')
1132 cmd.main([command] + args)
1135 #############################################################
1137 def xm_vcpu_pin(args):
1138 arg_check(args, "vcpu-pin", 3)
1140 def cpu_make_map(cpulist):
1141 cpus = []
1142 for c in cpulist.split(','):
1143 if c.find('-') != -1:
1144 (x,y) = c.split('-')
1145 for i in range(int(x),int(y)+1):
1146 cpus.append(int(i))
1147 else:
1148 # remove this element from the list
1149 if c[0] == '^':
1150 cpus = [x for x in cpus if x != int(c[1:])]
1151 else:
1152 cpus.append(int(c))
1153 cpus.sort()
1154 return cpus
1156 dom = args[0]
1157 vcpu = args[1]
1158 if args[2] == 'all':
1159 cpumap = cpu_make_map('0-63')
1160 else:
1161 cpumap = cpu_make_map(args[2])
1163 server.xend.domain.pincpu(dom, vcpu, cpumap)
1165 def xm_mem_max(args):
1166 arg_check(args, "mem-max", 2)
1168 dom = args[0]
1170 if serverType == SERVER_XEN_API:
1171 mem = int_unit(args[1], 'k') * 1024
1172 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1173 else:
1174 mem = int_unit(args[1], 'm')
1175 server.xend.domain.maxmem_set(dom, mem)
1177 def xm_mem_set(args):
1178 arg_check(args, "mem-set", 2)
1180 dom = args[0]
1182 if serverType == SERVER_XEN_API:
1183 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1184 server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target)
1185 server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target)
1186 else:
1187 mem_target = int_unit(args[1], 'm')
1188 server.xend.domain.setMemoryTarget(dom, mem_target)
1190 def xm_vcpu_set(args):
1191 arg_check(args, "vcpu-set", 2)
1193 dom = args[0]
1194 vcpus = int(args[1])
1196 if serverType == SERVER_XEN_API:
1197 server.xenapi.VM.set_vcpus_live(get_single_vm(dom), vcpus)
1198 else:
1199 server.xend.domain.setVCpuCount(dom, vcpus)
1201 def xm_destroy(args):
1202 arg_check(args, "destroy", 1)
1204 dom = args[0]
1206 if serverType == SERVER_XEN_API:
1207 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1208 else:
1209 server.xend.domain.destroy(dom)
1211 def xm_domid(args):
1212 arg_check(args, "domid", 1)
1214 name = args[0]
1216 if serverType == SERVER_XEN_API:
1217 print server.xenapi.VM.get_domid(get_single_vm(name))
1218 else:
1219 dom = server.xend.domain(name)
1220 print sxp.child_value(dom, 'domid')
1222 def xm_domname(args):
1223 arg_check(args, "domname", 1)
1225 name = args[0]
1227 if serverType == SERVER_XEN_API:
1228 print server.xenapi.VM.get_name_label(get_single_vm(name))
1229 else:
1230 dom = server.xend.domain(name)
1231 print sxp.child_value(dom, 'name')
1233 def xm_sched_sedf(args):
1234 def ns_to_ms(val):
1235 return float(val) * 0.000001
1237 def ms_to_ns(val):
1238 return (float(val) / 0.000001)
1240 def print_sedf(info):
1241 info['period'] = ns_to_ms(info['period'])
1242 info['slice'] = ns_to_ms(info['slice'])
1243 info['latency'] = ns_to_ms(info['latency'])
1244 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1245 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1247 check_sched_type('sedf')
1249 # we want to just display current info if no parameters are passed
1250 if len(args) == 0:
1251 domid = None
1252 else:
1253 # we expect at least a domain id (name or number)
1254 # and at most a domid up to 5 options with values
1255 arg_check(args, "sched-sedf", 1, 11)
1256 domid = args[0]
1257 # drop domid from args since get_opt doesn't recognize it
1258 args = args[1:]
1260 opts = {}
1261 try:
1262 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1263 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1264 except getopt.GetoptError, opterr:
1265 err(opterr)
1266 usage('sched-sedf')
1268 # convert to nanoseconds if needed
1269 for (k, v) in options:
1270 if k in ['-p', '--period']:
1271 opts['period'] = ms_to_ns(v)
1272 elif k in ['-s', '--slice']:
1273 opts['slice'] = ms_to_ns(v)
1274 elif k in ['-l', '--latency']:
1275 opts['latency'] = ms_to_ns(v)
1276 elif k in ['-e', '--extratime']:
1277 opts['extratime'] = v
1278 elif k in ['-w', '--weight']:
1279 opts['weight'] = v
1281 doms = filter(lambda x : domid_match(domid, x),
1282 [parse_doms_info(dom)
1283 for dom in getDomains(None, 'running')])
1284 if domid is not None and doms == []:
1285 err("Domain '%s' does not exist." % domid)
1286 usage('sched-sedf')
1288 # print header if we aren't setting any parameters
1289 if len(opts.keys()) == 0:
1290 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1291 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1292 'Extra','Weight')
1294 for d in doms:
1295 # fetch current values so as not to clobber them
1296 try:
1297 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1298 except xmlrpclib.Fault:
1299 # domain does not support sched-sedf?
1300 sedf_raw = {}
1302 sedf_info = parse_sedf_info(sedf_raw)
1303 sedf_info['name'] = d['name']
1304 # update values in case of call to set
1305 if len(opts.keys()) > 0:
1306 for k in opts.keys():
1307 sedf_info[k]=opts[k]
1309 # send the update, converting user input
1310 v = map(int, [sedf_info['period'], sedf_info['slice'],
1311 sedf_info['latency'],sedf_info['extratime'],
1312 sedf_info['weight']])
1313 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1314 if int(rv) != 0:
1315 err("Failed to set sedf parameters (rv=%d)."%(rv))
1317 # not setting values, display info
1318 else:
1319 print_sedf(sedf_info)
1321 def xm_sched_credit(args):
1322 """Get/Set options for Credit Scheduler."""
1324 check_sched_type('credit')
1326 try:
1327 opts, params = getopt.getopt(args, "d:w:c:",
1328 ["domain=", "weight=", "cap="])
1329 except getopt.GetoptError, opterr:
1330 err(opterr)
1331 usage('sched-credit')
1333 domid = None
1334 weight = None
1335 cap = None
1337 for o, a in opts:
1338 if o == "-d":
1339 domid = a
1340 elif o == "-w":
1341 weight = int(a)
1342 elif o == "-c":
1343 cap = int(a);
1345 doms = filter(lambda x : domid_match(domid, x),
1346 [parse_doms_info(dom)
1347 for dom in getDomains(None, 'running')])
1349 if weight is None and cap is None:
1350 if domid is not None and doms == []:
1351 err("Domain '%s' does not exist." % domid)
1352 usage('sched-credit')
1353 # print header if we aren't setting any parameters
1354 print '%-33s %-2s %-6s %-4s' % ('Name','ID','Weight','Cap')
1356 for d in doms:
1357 try:
1358 info = server.xend.domain.sched_credit_get(d['domid'])
1359 except xmlrpclib.Fault:
1360 # domain does not support sched-credit?
1361 info = {'weight': -1, 'cap': -1}
1363 info['name'] = d['name']
1364 info['domid'] = int(d['domid'])
1365 print( ("%(name)-32s %(domid)3d %(weight)6d %(cap)4d") % info)
1366 else:
1367 if domid is None:
1368 # place holder for system-wide scheduler parameters
1369 err("No domain given.")
1370 usage('sched-credit')
1372 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1373 if result != 0:
1374 err(str(result))
1376 def xm_info(args):
1377 arg_check(args, "info", 0)
1379 if serverType == SERVER_XEN_API:
1381 # Need to fake out old style xm info as people rely on parsing it
1383 host_record = server.xenapi.host.get_record(
1384 server.xenapi.session.get_this_host())
1386 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1388 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1390 info = {
1391 "host": host_record["name_label"],
1392 "release": host_record["software_version"]["release"],
1393 "version": host_record["software_version"]["version"],
1394 "machine": host_record["software_version"]["machine"],
1395 "nr_cpus": len(host_record["host_CPUs"]),
1396 "nr_nodes": host_record["cpu_configuration"]["nr_nodes"],
1397 "sockets_per_node": host_record["cpu_configuration"]["sockets_per_node"],
1398 "cores_per_socket": host_record["cpu_configuration"]["cores_per_socket"],
1399 "threads_per_core": host_record["cpu_configuration"]["threads_per_core"],
1400 "cpu_mhz": sum([int(host_cpu_record["speed"]) for host_cpu_record in host_cpu_records])
1401 / len(host_cpu_records),
1402 "hw_caps": host_cpu_records[0]["features"],
1403 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1404 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1405 "xen_major": host_record["software_version"]["xen_major"],
1406 "xen_minor": host_record["software_version"]["xen_minor"],
1407 "xen_extra": host_record["software_version"]["xen_extra"],
1408 "xen_caps": " ".join(host_record["capabilities"]),
1409 "xen_scheduler": host_record["sched_policy"],
1410 "xen_pagesize": host_record["other_config"]["xen_pagesize"],
1411 "platform_params": host_record["other_config"]["platform_params"],
1412 "xen_changeset": host_record["software_version"]["xen_changeset"],
1413 "cc_compiler": host_record["software_version"]["cc_compiler"],
1414 "cc_compile_by": host_record["software_version"]["cc_compile_by"],
1415 "cc_compile_domain": host_record["software_version"]["cc_compile_domain"],
1416 "cc_compile_date": host_record["software_version"]["cc_compile_date"],
1417 "xend_config_format":host_record["software_version"]["xend_config_format"]
1420 sorted = info.items()
1421 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1423 for (k, v) in sorted:
1424 print "%-23s:" % k, v
1425 else:
1426 info = server.xend.node.info()
1427 for x in info[1:]:
1428 if len(x) < 2:
1429 print "%-23s: (none)" % x[0]
1430 else:
1431 print "%-23s:" % x[0], x[1]
1433 def xm_console(args):
1434 arg_check(args, "console", 1, 2)
1436 quiet = False;
1438 try:
1439 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1440 except getopt.GetoptError, opterr:
1441 err(opterr)
1442 usage('console')
1444 for (k, v) in options:
1445 if k in ['-q', '--quiet']:
1446 quiet = True
1447 else:
1448 assert False
1450 if len(params) != 1:
1451 err('No domain given')
1452 usage('console')
1454 dom = params[0]
1456 try:
1457 if serverType == SERVER_XEN_API:
1458 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1459 else:
1460 info = server.xend.domain(dom)
1461 domid = int(sxp.child_value(info, 'domid', '-1'))
1462 except:
1463 if quiet:
1464 sys.exit(1)
1465 else:
1466 raise
1468 if domid == -1:
1469 if quiet:
1470 sys.exit(1)
1471 else:
1472 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1474 console.execConsole(domid)
1477 def xm_uptime(args):
1478 short_mode = 0
1480 try:
1481 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1482 except getopt.GetoptError, opterr:
1483 err(opterr)
1484 usage('uptime')
1486 for (k, v) in options:
1487 if k in ['-s', '--short']:
1488 short_mode = 1
1490 doms = getDomains(params, 'running')
1492 if short_mode == 0:
1493 print 'Name ID Uptime'
1495 for dom in doms:
1496 d = parse_doms_info(dom)
1497 if int(d['domid']) > 0:
1498 uptime = int(round(d['up_time']))
1499 else:
1500 f=open('/proc/uptime', 'r')
1501 upfile = f.read()
1502 uptime = int(round(float(upfile.split(' ')[0])))
1503 f.close()
1505 days = int(uptime / 86400)
1506 uptime -= (days * 86400)
1507 hours = int(uptime / 3600)
1508 uptime -= (hours * 3600)
1509 minutes = int(uptime / 60)
1510 uptime -= (minutes * 60)
1511 seconds = uptime
1513 upstring = ""
1514 if days > 0:
1515 upstring += str(days) + " day"
1516 if days > 1:
1517 upstring += "s"
1518 upstring += ", "
1519 upstring += '%(hours)2d:%(minutes)02d' % vars()
1521 if short_mode:
1522 now = datetime.datetime.now()
1523 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1524 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1525 else:
1526 upstring += ':%(seconds)02d' % vars()
1527 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1529 print upstring
1531 def xm_sysrq(args):
1532 arg_check(args, "sysrq", 2)
1533 dom = args[0]
1534 req = args[1]
1535 if serverType == SERVER_XEN_API:
1536 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1537 else:
1538 server.xend.domain.send_sysrq(dom, req)
1540 def xm_trigger(args):
1541 vcpu = 0
1543 arg_check(args, "trigger", 2, 3)
1544 dom = args[0]
1545 trigger = args[1]
1546 if len(args) == 3:
1547 vcpu = int(args[2])
1549 if serverType == SERVER_XEN_API:
1550 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1551 else:
1552 server.xend.domain.send_trigger(dom, trigger, vcpu)
1554 def xm_debug_keys(args):
1555 arg_check(args, "debug-keys", 1)
1557 keys = str(args[0])
1559 if serverType == SERVER_XEN_API:
1560 server.xenapi.host.send_debug_keys(
1561 server.xenapi.session.get_this_host(),
1562 keys)
1563 else:
1564 server.xend.node.send_debug_keys(keys)
1566 def xm_top(args):
1567 arg_check(args, "top", 0)
1569 os.execvp('xentop', ['xentop'])
1571 def xm_dmesg(args):
1572 arg_check(args, "dmesg", 0, 1)
1574 try:
1575 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1576 except getopt.GetoptError, opterr:
1577 err(opterr)
1578 usage('dmesg')
1580 use_clear = 0
1581 for (k, v) in options:
1582 if k in ['-c', '--clear']:
1583 use_clear = 1
1585 if len(params) :
1586 err("No parameter required")
1587 usage('dmesg')
1589 if serverType == SERVER_XEN_API:
1590 if not use_clear:
1591 print server.xenapi.host.dmesg(
1592 server.xenapi.session.get_this_host(),0)
1593 else:
1594 server.xenapi.host.dmesg(
1595 server.xenapi.session.get_this_host(),1)
1596 else:
1597 if not use_clear:
1598 print server.xend.node.dmesg.info()
1599 else:
1600 server.xend.node.dmesg.clear()
1602 def xm_log(args):
1603 arg_check(args, "log", 0)
1605 if serverType == SERVER_XEN_API:
1606 print server.xenapi.host.get_log(
1607 server.xenapi.session.get_this_host())
1608 else:
1609 print server.xend.node.log()
1611 def xm_serve(args):
1612 if serverType == SERVER_XEN_API:
1613 print "Not supported with XenAPI"
1614 sys.exit(-1)
1616 arg_check(args, "serve", 0)
1618 from fcntl import fcntl, F_SETFL
1620 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1621 s.connect(XendClient.XML_RPC_SOCKET)
1622 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1624 while True:
1625 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1626 if s in iwtd:
1627 data = s.recv(4096)
1628 if len(data) > 0:
1629 sys.stdout.write(data)
1630 sys.stdout.flush()
1631 else:
1632 break
1633 if sys.stdin in iwtd:
1634 data = sys.stdin.read(4096)
1635 if len(data) > 0:
1636 s.sendall(data)
1637 else:
1638 break
1639 s.close()
1641 def parse_dev_info(info):
1642 def get_info(n, t, d):
1643 i = 0
1644 while i < len(info):
1645 if (info[i][0] == n):
1646 return t(info[i][1])
1647 i = i + 1
1648 return t(d)
1649 return {
1650 #common
1651 'backend-id' : get_info('backend-id', int, -1),
1652 'handle' : get_info('handle', int, 0),
1653 'state' : get_info('state', int, -1),
1654 'be-path' : get_info('backend', str, '??'),
1655 'event-ch' : get_info('event-channel',int, -1),
1656 #network specific
1657 'virtual-device' : get_info('virtual-device', str, '??'),
1658 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1659 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1660 'mac' : get_info('mac', str, '??'),
1661 #block-device specific
1662 'ring-ref' : get_info('ring-ref', int, -1),
1665 def arg_check_for_resource_list(args, name):
1666 use_long = 0
1667 try:
1668 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1669 except getopt.GetoptError, opterr:
1670 err(opterr)
1671 sys.exit(1)
1673 for (k, v) in options:
1674 if k in ['-l', '--long']:
1675 use_long = 1
1677 if len(params) == 0:
1678 print 'No domain parameter given'
1679 usage(name)
1680 if len(params) > 1:
1681 print 'No multiple domain parameters allowed'
1682 usage(name)
1684 return (use_long, params)
1686 def xm_network_list(args):
1687 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1689 dom = params[0]
1691 if serverType == SERVER_XEN_API:
1692 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1693 vif_properties = \
1694 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1695 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
1696 zip(range(len(vif_properties)), vif_properties))
1697 else:
1698 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1700 if use_long:
1701 map(PrettyPrint.prettyprint, devs)
1702 else:
1703 hdr = 0
1704 for x in devs:
1705 if hdr == 0:
1706 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1707 hdr = 1
1708 ni = parse_dev_info(x[1])
1709 ni['idx'] = int(x[0])
1710 print ("%(idx)-3d "
1711 "%(backend-id)-3d"
1712 "%(mac)-17s "
1713 "%(handle)-3d "
1714 "%(state)-3d "
1715 "%(event-ch)-3d "
1716 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1717 "%(be-path)-30s "
1718 % ni)
1720 def xm_block_list(args):
1721 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1723 dom = params[0]
1725 if serverType == SERVER_XEN_API:
1726 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1727 vbd_properties = \
1728 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
1729 vbd_devs = \
1730 map(server.xenapi.VBD.get_device, vbd_refs)
1731 vbd_devids = \
1732 map(blkdev_name_to_number, vbd_devs)
1733 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
1734 zip(vbd_devids, vbd_properties))
1735 else:
1736 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1738 if use_long:
1739 map(PrettyPrint.prettyprint, devs)
1740 else:
1741 hdr = 0
1742 for x in devs:
1743 if hdr == 0:
1744 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1745 hdr = 1
1746 ni = parse_dev_info(x[1])
1747 ni['idx'] = int(x[0])
1748 print ("%(idx)-3d "
1749 "%(backend-id)-3d "
1750 "%(handle)-3d "
1751 "%(state)-3d "
1752 "%(event-ch)-3d "
1753 "%(ring-ref)-5d "
1754 "%(be-path)-30s "
1755 % ni)
1757 def xm_vtpm_list(args):
1758 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1760 dom = params[0]
1761 if use_long:
1762 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1763 map(PrettyPrint.prettyprint, devs)
1764 else:
1765 hdr = 0
1766 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1767 if hdr == 0:
1768 print 'Idx BE handle state evt-ch ring-ref BE-path'
1769 hdr = 1
1770 ni = parse_dev_info(x[1])
1771 ni['idx'] = int(x[0])
1772 print ("%(idx)-3d "
1773 "%(backend-id)-3d "
1774 "%(handle)-3d "
1775 "%(state)-3d "
1776 "%(event-ch)-3d "
1777 "%(ring-ref)-5d "
1778 "%(be-path)-30s "
1779 % ni)
1782 def parse_block_configuration(args):
1783 dom = args[0]
1785 if args[1].startswith('tap:'):
1786 cls = 'tap'
1787 else:
1788 cls = 'vbd'
1790 vbd = [cls,
1791 ['uname', args[1]],
1792 ['dev', args[2]],
1793 ['mode', args[3]]]
1794 if len(args) == 5:
1795 vbd.append(['backend', args[4]])
1797 if serverType != SERVER_XEN_API:
1798 # verify that policy permits attaching this resource
1799 from xen.util import security
1801 if security.on():
1802 dominfo = server.xend.domain(dom)
1803 label = security.get_security_printlabel(dominfo)
1804 else:
1805 label = None
1807 security.res_security_check(args[1], label)
1809 return (dom, vbd)
1812 def xm_block_attach(args):
1813 arg_check(args, 'block-attach', 4, 5)
1815 if serverType == SERVER_XEN_API:
1816 dom = args[0]
1817 uname = args[1]
1818 dev = args[2]
1819 mode = args[3]
1821 # First create new VDI
1822 vdi_record = {
1823 "name_label": "vdi" + str(uname.__hash__()),
1824 "name_description": "",
1825 "SR": get_default_SR(),
1826 "virtual_size": 0,
1827 "sector_size": 512,
1828 "type": "system",
1829 "sharable": False,
1830 "read_only": mode!="w",
1831 "other_config": {"location": uname}
1834 vdi_ref = server.xenapi.VDI.create(vdi_record)
1836 # Now create new VBD
1838 vbd_record = {
1839 "VM": get_single_vm(dom),
1840 "VDI": vdi_ref,
1841 "device": dev,
1842 "bootable": True,
1843 "mode": mode=="w" and "RW" or "RO",
1844 "type": "Disk",
1845 "qos_algorithm_type": "",
1846 "qos_algorithm_params": {}
1849 server.xenapi.VBD.create(vbd_record)
1851 else:
1852 (dom, vbd) = parse_block_configuration(args)
1853 server.xend.domain.device_create(dom, vbd)
1856 def xm_block_configure(args):
1857 arg_check(args, 'block-configure', 4, 5)
1859 (dom, vbd) = parse_block_configuration(args)
1860 server.xend.domain.device_configure(dom, vbd)
1863 def xm_network_attach(args):
1864 arg_check(args, 'network-attach', 1, 10)
1866 dom = args[0]
1867 vif = ['vif']
1868 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
1869 'backend', 'vifname', 'rate', 'model']
1871 if serverType == SERVER_XEN_API:
1872 vif_record = {
1873 "device": "eth0",
1874 "network": get_default_Network(),
1875 "VM": get_single_vm(dom),
1876 "MAC": "",
1877 "MTU": "",
1878 "qos_algorithm_type": "",
1879 "qos_algorithm_params": {},
1880 "other_config": {}
1883 def set(keys, val):
1884 record = vif_record
1885 for key in keys[:-1]:
1886 record = record[key]
1887 record[keys[-1]] = val
1889 vif_conv = {
1890 'type':
1891 lambda x: None,
1892 'mac':
1893 lambda x: set(['MAC'], x),
1894 'bridge':
1895 lambda x: set(['network'], get_net_from_bridge(x)),
1896 'ip':
1897 lambda x: set(['other_config', 'ip'], x),
1898 'script':
1899 lambda x: set(['other_config', 'script'], x),
1900 'backend':
1901 lambda x: set(['other_config', 'backend'], x),
1902 'vifname':
1903 lambda x: set(['device'], x),
1904 'rate':
1905 lambda x: set(['qos_algorithm_params', 'rate'], x),
1906 'model':
1907 lambda x: None
1910 for a in args[1:]:
1911 vif_param = a.split("=")
1912 if len(vif_param) != 2 or vif_param[1] == '' or \
1913 vif_param[0] not in vif_params:
1914 err("Invalid argument: %s" % a)
1915 usage('network-attach')
1916 else:
1917 vif_conv[vif_param[0]](vif_param[1])
1919 print str(vif_record)
1920 server.xenapi.VIF.create(vif_record)
1921 else:
1922 for a in args[1:]:
1923 vif_param = a.split("=")
1924 if len(vif_param) != 2 or vif_param[1] == '' or \
1925 vif_param[0] not in vif_params:
1926 err("Invalid argument: %s" % a)
1927 usage('network-attach')
1928 vif.append(vif_param)
1929 server.xend.domain.device_create(dom, vif)
1932 def detach(args, command, deviceClass):
1933 arg_check(args, command, 2, 3)
1935 dom = args[0]
1936 dev = args[1]
1937 try:
1938 force = args[2]
1939 if (force != "--force") and (force != "-f"):
1940 print "Ignoring option %s"%(force)
1941 force = None
1942 except IndexError:
1943 force = None
1945 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
1948 def xm_block_detach(args):
1949 if serverType == SERVER_XEN_API:
1950 arg_check(args, "xm_block_detach", 2, 3)
1951 dom = args[0]
1952 dev = args[1]
1953 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1954 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
1955 if server.xenapi.VBD.get_device(vbd_ref) == dev]
1956 if len(vbd_refs) > 0:
1957 vbd_ref = vbd_refs[0]
1958 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
1960 server.xenapi.VBD.destroy(vbd_ref)
1962 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
1963 server.xenapi.VDI.destroy(vdi_ref)
1964 else:
1965 print "Cannot find device '%s' in domain '%s'" % (dev,dom)
1966 else:
1967 try:
1968 detach(args, 'block-detach', 'vbd')
1969 return
1970 except:
1971 pass
1972 detach(args, 'block-detach', 'tap')
1974 def xm_network_detach(args):
1975 if serverType == SERVER_XEN_API:
1976 arg_check(args, "xm_block_detach", 2, 3)
1977 dom = args[0]
1978 devid = args[1]
1979 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1980 vif_refs = [vif_ref for vif_ref in vif_refs
1981 if server.xenapi.VIF.\
1982 get_runtime_properties(vif_ref)["handle"] == devid]
1983 if len(vif_refs) > 0:
1984 vif_ref = vif_refs[0]
1986 server.xenapi.VIF.destroy(vif_ref)
1987 else:
1988 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
1989 else:
1990 detach(args, 'network-detach', 'vif')
1993 def xm_vnet_list(args):
1994 try:
1995 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1996 except getopt.GetoptError, opterr:
1997 err(opterr)
1998 usage('vnet-list')
2000 use_long = 0
2001 for (k, v) in options:
2002 if k in ['-l', '--long']:
2003 use_long = 1
2005 if params:
2006 use_long = 1
2007 vnets = params
2008 else:
2009 vnets = server.xend_vnets()
2011 for vnet in vnets:
2012 try:
2013 if use_long:
2014 info = server.xend_vnet(vnet)
2015 PrettyPrint.prettyprint(info)
2016 else:
2017 print vnet
2018 except Exception, ex:
2019 print vnet, ex
2021 def xm_vnet_create(args):
2022 arg_check(args, "vnet-create", 1)
2023 conf = args[0]
2024 if not os.access(conf, os.R_OK):
2025 print "File not found: %s" % conf
2026 sys.exit(1)
2028 server.xend_vnet_create(conf)
2030 def xm_vnet_delete(args):
2031 arg_check(args, "vnet-delete", 1)
2032 vnet = args[0]
2033 server.xend_vnet_delete(vnet)
2035 commands = {
2036 "shell": xm_shell,
2037 # console commands
2038 "console": xm_console,
2039 # xenstat commands
2040 "top": xm_top,
2041 # domain commands
2042 "delete": xm_delete,
2043 "destroy": xm_destroy,
2044 "domid": xm_domid,
2045 "domname": xm_domname,
2046 "dump-core": xm_dump_core,
2047 "reboot": xm_reboot,
2048 "rename": xm_rename,
2049 "restore": xm_restore,
2050 "resume": xm_resume,
2051 "save": xm_save,
2052 "shutdown": xm_shutdown,
2053 "start": xm_start,
2054 "sysrq": xm_sysrq,
2055 "trigger": xm_trigger,
2056 "uptime": xm_uptime,
2057 "suspend": xm_suspend,
2058 "list": xm_list,
2059 # memory commands
2060 "mem-max": xm_mem_max,
2061 "mem-set": xm_mem_set,
2062 # cpu commands
2063 "vcpu-pin": xm_vcpu_pin,
2064 "vcpu-list": xm_vcpu_list,
2065 "vcpu-set": xm_vcpu_set,
2066 # special
2067 "pause": xm_pause,
2068 "unpause": xm_unpause,
2069 # host commands
2070 "debug-keys": xm_debug_keys,
2071 "dmesg": xm_dmesg,
2072 "info": xm_info,
2073 "log": xm_log,
2074 "serve": xm_serve,
2075 # scheduler
2076 "sched-sedf": xm_sched_sedf,
2077 "sched-credit": xm_sched_credit,
2078 # block
2079 "block-attach": xm_block_attach,
2080 "block-detach": xm_block_detach,
2081 "block-list": xm_block_list,
2082 "block-configure": xm_block_configure,
2083 # network
2084 "network-attach": xm_network_attach,
2085 "network-detach": xm_network_detach,
2086 "network-list": xm_network_list,
2087 # vnet
2088 "vnet-list": xm_vnet_list,
2089 "vnet-create": xm_vnet_create,
2090 "vnet-delete": xm_vnet_delete,
2091 # vtpm
2092 "vtpm-list": xm_vtpm_list,
2095 ## The commands supported by a separate argument parser in xend.xm.
2096 IMPORTED_COMMANDS = [
2097 'create',
2098 'new',
2099 'migrate',
2100 'labels',
2101 'cfgbootpolicy',
2102 'makepolicy',
2103 'loadpolicy',
2104 'dumppolicy',
2105 'addlabel',
2106 'rmlabel',
2107 'getlabel',
2108 'dry-run',
2109 'resources',
2112 for c in IMPORTED_COMMANDS:
2113 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2115 aliases = {
2116 "balloon": "mem-set",
2117 "set-vcpus": "vcpu-set",
2118 "vif-list": "network-list",
2119 "vbd-create": "block-attach",
2120 "vbd-destroy": "block-detach",
2121 "vbd-list": "block-list",
2125 def xm_lookup_cmd(cmd):
2126 if commands.has_key(cmd):
2127 return commands[cmd]
2128 elif aliases.has_key(cmd):
2129 deprecated(cmd,aliases[cmd])
2130 return commands[aliases[cmd]]
2131 elif cmd == 'help':
2132 longHelp()
2133 sys.exit(0)
2134 else:
2135 # simulate getopt's prefix matching behaviour
2136 if len(cmd) > 1:
2137 same_prefix_cmds = [commands[c] for c in commands.keys() \
2138 if c[:len(cmd)] == cmd]
2139 # only execute if there is only 1 match
2140 if len(same_prefix_cmds) == 1:
2141 return same_prefix_cmds[0]
2142 return None
2144 def deprecated(old,new):
2145 print >>sys.stderr, (
2146 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2148 def main(argv=sys.argv):
2149 if len(argv) < 2:
2150 usage()
2152 # intercept --help(-h) and output our own help
2153 for help in ['--help', '-h']:
2154 if help in argv[1:]:
2155 if help == argv[1]:
2156 longHelp()
2157 sys.exit(0)
2158 else:
2159 usage(argv[1])
2161 cmd_name = argv[1]
2162 cmd = xm_lookup_cmd(cmd_name)
2163 if cmd:
2164 # strip off prog name and subcmd
2165 args = argv[2:]
2166 _, rc = _run_cmd(cmd, cmd_name, args)
2167 sys.exit(rc)
2168 else:
2169 err('Subcommand %s not found!' % cmd_name)
2170 usage()
2172 def _run_cmd(cmd, cmd_name, args):
2173 global server
2175 try:
2176 if server is None:
2177 if serverType == SERVER_XEN_API:
2178 server = XenAPI.Session(serverURI)
2179 username, password = parseAuthentication()
2180 server.login_with_password(username, password)
2181 def logout():
2182 try:
2183 server.xenapi.session.logout()
2184 except:
2185 pass
2186 atexit.register(logout)
2187 else:
2188 server = ServerProxy(serverURI)
2190 return True, cmd(args)
2191 except socket.error, ex:
2192 if os.geteuid() != 0:
2193 err("Most commands need root access. Please try again as root.")
2194 else:
2195 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2196 except KeyboardInterrupt:
2197 print "Interrupted."
2198 return True, ''
2199 except IOError, ex:
2200 if os.geteuid() != 0:
2201 err("Most commands need root access. Please try again as root.")
2202 else:
2203 err("Unable to connect to xend: %s." % ex[1])
2204 except SystemExit, code:
2205 return code == 0, code
2206 except XenAPI.Failure, exn:
2207 for line in [''] + wrap(str(exn), 80) + ['']:
2208 print >>sys.stderr, line
2209 except xmlrpclib.Fault, ex:
2210 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2211 err("Domain '%s' does not exist." % ex.faultString)
2212 else:
2213 err(ex.faultString)
2214 _usage(cmd_name)
2215 except xmlrpclib.ProtocolError, ex:
2216 if ex.errcode == -1:
2217 print >>sys.stderr, (
2218 "Xend has probably crashed! Invalid or missing HTTP "
2219 "status code.")
2220 else:
2221 print >>sys.stderr, (
2222 "Xend has probably crashed! ProtocolError(%d, %s)." %
2223 (ex.errcode, ex.errmsg))
2224 except (ValueError, OverflowError):
2225 err("Invalid argument.")
2226 _usage(cmd_name)
2227 except OptionError, e:
2228 err(str(e))
2229 _usage(cmd_name)
2230 print e.usage
2231 except Exception, e:
2232 if serverType != SERVER_XEN_API:
2233 from xen.util import security
2234 if isinstance(e, security.ACMError):
2235 err(str(e))
2236 return False, 1
2237 else:
2238 print "Unexpected error:", sys.exc_info()[0]
2239 print
2240 print "Please report to xen-devel@lists.xensource.com"
2241 raise
2243 return False, 1
2245 if __name__ == "__main__":
2246 main()