ia64/xen-unstable

view tools/python/xen/xm/main.py @ 13024:21609e7f5a49

[XM] Fix typo in 'xm vcpu-list' header.
Signed-off-by: Amos Waterland <apw@us.ibm.com>
author kfraser@localhost.localdomain
date Thu Dec 14 11:39:40 2006 +0000 (2006-12-14)
parents c09dab67c178
children c91f6506b270
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 os
26 import sys
27 import re
28 import getopt
29 import socket
30 import traceback
31 import xmlrpclib
32 import traceback
33 import time
34 import datetime
35 from select import select
36 import xml.dom.minidom
38 import warnings
39 warnings.filterwarnings('ignore', category=FutureWarning)
41 from xen.xend import PrettyPrint
42 from xen.xend import sxp
43 from xen.xend import XendClient
44 from xen.xend.XendConstants import *
46 from xen.xm.opts import OptionError, Opts, wrap, set_true
47 from xen.xm import console
48 from xen.util import security
49 from xen.util.xmlrpclib2 import ServerProxy
51 import XenAPI
53 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
54 # getopt.getopt if gnu_getopt is not available. This will mean that options
55 # may only be specified before positional arguments.
56 if not hasattr(getopt, 'gnu_getopt'):
57 getopt.gnu_getopt = getopt.getopt
59 XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
61 # Supported types of server
62 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
63 SERVER_XEN_API = 'Xen-API'
65 # General help message
67 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
68 "Control, list, and manipulate Xen guest instances.\n"
70 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
71 'For more help on \'xm\' see the xm(1) man page.\n' \
72 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
73 ' man page.\n'
75 # Help strings are indexed by subcommand name in this way:
76 # 'subcommand': (argstring, description)
78 SUBCOMMAND_HELP = {
79 # common commands
81 'console' : ('[-q|--quiet] <Domain>',
82 'Attach to <Domain>\'s console.'),
83 'create' : ('<ConfigFile> [options] [vars]',
84 'Create a domain based on <ConfigFile>.'),
85 'destroy' : ('<Domain>',
86 'Terminate a domain immediately.'),
87 'help' : ('', 'Display this message.'),
88 'list' : ('[options] [Domain, ...]',
89 'List information about all/some domains.'),
90 'mem-max' : ('<Domain> <Mem>',
91 'Set the maximum amount reservation for a domain.'),
92 'mem-set' : ('<Domain> <Mem>',
93 'Set the current memory usage for a domain.'),
94 'migrate' : ('<Domain> <Host>',
95 'Migrate a domain to another machine.'),
96 'pause' : ('<Domain>', 'Pause execution of a domain.'),
97 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
98 'restore' : ('<CheckpointFile> [-p]',
99 'Restore a domain from a saved state.'),
100 'save' : ('<Domain> <CheckpointFile>',
101 'Save a domain state to restore later.'),
102 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
103 'top' : ('', 'Monitor a host and the domains in real time.'),
104 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
105 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
107 # Life cycle xm commands
108 'new' : ('<ConfigFile> [options] [vars]',
109 'Adds a domain to Xend domain management'),
110 'delete' : ('<DomainName>',
111 'Remove a domain from Xend domain management.'),
112 'start' : ('<DomainName>', 'Start a Xend managed domain'),
113 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
114 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
116 # less used commands
118 'dmesg' : ('[-c|--clear]',
119 'Read and/or clear Xend\'s message buffer.'),
120 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
121 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
122 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
123 'Dump core for a specific domain.'),
124 'info' : ('', 'Get information about Xen host.'),
125 'log' : ('', 'Print Xend log'),
126 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
127 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
128 'sched-credit': ('-d <Domain> [-w[=WEIGHT]|-c[=CAP]]',
129 'Get/set credit scheduler parameters.'),
130 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
131 'vcpu-list' : ('[<Domain>]',
132 'List the VCPUs for a domain or all domains.'),
133 'vcpu-pin' : ('<Domain> <VCPU> <CPUs>',
134 'Set which CPUs a VCPU can use.'),
135 'vcpu-set' : ('<Domain> <vCPUs>',
136 'Set the number of active VCPUs for allowed for the'
137 ' domain.'),
139 # device commands
141 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
142 'Create a new virtual block device.'),
143 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
144 'Change block device configuration'),
145 'block-detach' : ('<Domain> <DevId> [-f|--force]',
146 'Destroy a domain\'s virtual block device.'),
147 'block-list' : ('<Domain> [--long]',
148 'List virtual block devices for a domain.'),
149 'network-attach': ('<Domain> [--script=<script>] [--ip=<ip>] '
150 '[--mac=<mac>]',
151 'Create a new virtual network device.'),
152 'network-detach': ('<Domain> <DevId> [-f|--force]',
153 'Destroy a domain\'s virtual network device.'),
154 'network-list' : ('<Domain> [--long]',
155 'List virtual network interfaces for a domain.'),
156 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
157 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
158 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
159 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
161 # security
163 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
164 'Add security label to domain.'),
165 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
166 'Remove a security label from domain.'),
167 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
168 'Show security label for domain or resource.'),
169 'dry-run' : ('<ConfigFile>',
170 'Test if a domain can access its resources.'),
171 'resources' : ('', 'Show info for each labeled resource.'),
172 'cfgbootpolicy' : ('<policy> [boot-title]',
173 'Add policy to boot configuration.'),
174 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
175 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
176 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
177 'files.'),
178 'labels' : ('[policy] [type=dom|res|any]',
179 'List <type> labels for (active) policy.'),
180 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
181 }
183 SUBCOMMAND_OPTIONS = {
184 'sched-sedf': (
185 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
186 ('-s [MS]', '--slice[=MS]' ,
187 'Worst-case execution time(ms). (slice < period)'),
188 ('-l [MS]', '--latency[=MS]',
189 'Scaled period (ms) when domain performs heavy I/O'),
190 ('-e [FLAG]', '--extra[=FLAG]',
191 'Flag (0 or 1) controls if domain can run in extra time.'),
192 ('-w [FLOAT]', '--weight[=FLOAT]',
193 'CPU Period/slice (do not set with --period/--slice)'),
194 ),
195 'sched-credit': (
196 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
197 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
198 ('-c CAP', '--cap=CAP', 'Cap (int)'),
199 ),
200 'list': (
201 ('-l', '--long', 'Output all VM details in SXP'),
202 ('', '--label', 'Include security labels'),
203 ('', '--state=<state>', 'Select only VMs with the specified state'),
204 ),
205 'console': (
206 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
207 ),
208 'dmesg': (
209 ('-c', '--clear', 'Clear dmesg buffer'),
210 ),
211 'vnet-list': (
212 ('-l', '--long', 'List Vnets as SXP'),
213 ),
214 'network-list': (
215 ('-l', '--long', 'List resources as SXP'),
216 ),
217 'dump-core': (
218 ('-L', '--live', 'Dump core without pausing the domain'),
219 ('-C', '--crash', 'Crash domain after dumping core'),
220 ),
221 'start': (
222 ('-p', '--paused', 'Do not unpause domain after starting it'),
223 ),
224 'resume': (
225 ('-p', '--paused', 'Do not unpause domain after resuming it'),
226 ),
227 'restore': (
228 ('-p', '--paused', 'Do not unpause domain after restoring it'),
229 ),
230 }
232 common_commands = [
233 "console",
234 "create",
235 "new",
236 "delete",
237 "destroy",
238 "dump-core",
239 "help",
240 "list",
241 "mem-set",
242 "migrate",
243 "pause",
244 "reboot",
245 "restore",
246 "resume",
247 "save",
248 "shutdown",
249 "start",
250 "suspend",
251 "top",
252 "unpause",
253 "uptime",
254 "vcpu-set",
255 ]
257 domain_commands = [
258 "console",
259 "create",
260 "new",
261 "delete",
262 "destroy",
263 "domid",
264 "domname",
265 "dump-core",
266 "list",
267 "mem-max",
268 "mem-set",
269 "migrate",
270 "pause",
271 "reboot",
272 "rename",
273 "restore",
274 "resume",
275 "save",
276 "shutdown",
277 "start",
278 "suspend",
279 "sysrq",
280 "top",
281 "unpause",
282 "uptime",
283 "vcpu-list",
284 "vcpu-pin",
285 "vcpu-set",
286 ]
288 host_commands = [
289 "dmesg",
290 "info",
291 "log",
292 "serve",
293 ]
295 scheduler_commands = [
296 "sched-credit",
297 "sched-sedf",
298 ]
300 device_commands = [
301 "block-attach",
302 "block-detach",
303 "block-list",
304 "block-configure",
305 "network-attach",
306 "network-detach",
307 "network-list",
308 "vtpm-list",
309 ]
311 vnet_commands = [
312 "vnet-list",
313 "vnet-create",
314 "vnet-delete",
315 ]
317 acm_commands = [
318 "labels",
319 "addlabel",
320 "rmlabel",
321 "getlabel",
322 "dry-run",
323 "resources",
324 "makepolicy",
325 "loadpolicy",
326 "cfgbootpolicy",
327 "dumppolicy",
328 ]
330 all_commands = (domain_commands + host_commands + scheduler_commands +
331 device_commands + vnet_commands + acm_commands)
334 ##
335 # Configuration File Parsing
336 ##
338 config = None
339 if os.path.isfile(XM_CONFIG_FILE):
340 try:
341 config = xml.dom.minidom.parse(XM_CONFIG_FILE)
342 except:
343 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
344 XM_CONFIG_FILE)
346 def parseServer():
347 if config:
348 server = config.getElementsByTagName('server')
349 if server:
350 st = server[0].getAttribute('type')
351 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
352 print >>sys.stderr, ('Invalid server type %s; using %s.' %
353 (st, SERVER_LEGACY_XMLRPC))
354 st = SERVER_LEGACY_XMLRPC
355 return (st, server[0].getAttribute('uri'))
357 return SERVER_LEGACY_XMLRPC, XendClient.uri
359 def parseAuthentication():
360 server = config.getElementsByTagName('server')[0]
361 return (server.getAttribute('username'),
362 server.getAttribute('password'))
364 serverType, serverURI = parseServer()
367 ####################################################################
368 #
369 # Help/usage printing functions
370 #
371 ####################################################################
373 def cmdHelp(cmd):
374 """Print help for a specific subcommand."""
376 for fc in SUBCOMMAND_HELP.keys():
377 if fc[:len(cmd)] == cmd:
378 cmd = fc
379 break
381 try:
382 args, desc = SUBCOMMAND_HELP[cmd]
383 except KeyError:
384 shortHelp()
385 return
387 print 'Usage: xm %s %s' % (cmd, args)
388 print
389 print desc
391 try:
392 # If options help message is defined, print this.
393 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
394 if shortopt and longopt:
395 optdesc = '%s, %s' % (shortopt, longopt)
396 elif shortopt:
397 optdesc = shortopt
398 elif longopt:
399 optdesc = longopt
401 wrapped_desc = wrap(desc, 43)
402 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
403 for line in wrapped_desc[1:]:
404 print ' ' * 33 + line
405 print
406 except KeyError:
407 # if the command is an external module, we grab usage help
408 # from the module itself.
409 if cmd in IMPORTED_COMMANDS:
410 try:
411 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
412 cmd_usage = getattr(cmd_module, "help", None)
413 if cmd_usage:
414 print cmd_usage()
415 except ImportError:
416 pass
418 def shortHelp():
419 """Print out generic help when xm is called without subcommand."""
421 print USAGE_HELP
422 print 'Common \'xm\' commands:\n'
424 for command in common_commands:
425 try:
426 args, desc = SUBCOMMAND_HELP[command]
427 except KeyError:
428 continue
429 wrapped_desc = wrap(desc, 50)
430 print ' %-20s %-50s' % (command, wrapped_desc[0])
431 for line in wrapped_desc[1:]:
432 print ' ' * 22 + line
434 print
435 print USAGE_FOOTER
436 print 'For a complete list of subcommands run \'xm help\'.'
438 def longHelp():
439 """Print out full help when xm is called with xm --help or xm help"""
441 print USAGE_HELP
442 print 'xm full list of subcommands:\n'
444 for command in all_commands:
445 try:
446 args, desc = SUBCOMMAND_HELP[command]
447 except KeyError:
448 continue
450 wrapped_desc = wrap(desc, 50)
451 print ' %-20s %-50s' % (command, wrapped_desc[0])
452 for line in wrapped_desc[1:]:
453 print ' ' * 22 + line
455 print
456 print USAGE_FOOTER
458 def usage(cmd = None):
459 """ Print help usage information and exits """
460 if cmd:
461 cmdHelp(cmd)
462 else:
463 shortHelp()
464 sys.exit(1)
467 ####################################################################
468 #
469 # Utility functions
470 #
471 ####################################################################
473 def arg_check(args, name, lo, hi = -1):
474 n = len([i for i in args if i != '--'])
476 if hi == -1:
477 if n != lo:
478 err("'xm %s' requires %d argument%s.\n" % (name, lo,
479 lo == 1 and '' or 's'))
480 usage(name)
481 else:
482 if n < lo or n > hi:
483 err("'xm %s' requires between %d and %d arguments.\n" %
484 (name, lo, hi))
485 usage(name)
488 def unit(c):
489 if not c.isalpha():
490 return 0
491 base = 1
492 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
493 elif c == 'M' or c == 'm': base = 1024 * 1024
494 elif c == 'K' or c == 'k': base = 1024
495 else:
496 print 'ignoring unknown unit'
497 return base
499 def int_unit(str, dest):
500 base = unit(str[-1])
501 if not base:
502 return int(str)
504 value = int(str[:-1])
505 dst_base = unit(dest)
506 if dst_base == 0:
507 dst_base = 1
508 if dst_base > base:
509 return value / (dst_base / base)
510 else:
511 return value * (base / dst_base)
513 def err(msg):
514 print >>sys.stderr, "Error:", msg
517 def get_single_vm(dom):
518 uuids = server.xenapi.VM.get_by_name_label(dom)
519 n = len(uuids)
520 if n == 1:
521 return uuids[0]
522 else:
523 dominfo = server.xend.domain(dom, False)
524 return dominfo['uuid']
527 #########################################################################
528 #
529 # Main xm functions
530 #
531 #########################################################################
533 def xm_save(args):
534 arg_check(args, "save", 2)
536 try:
537 dominfo = parse_doms_info(server.xend.domain(args[0]))
538 except xmlrpclib.Fault, ex:
539 raise ex
541 domid = dominfo['domid']
542 savefile = os.path.abspath(args[1])
544 if not os.access(os.path.dirname(savefile), os.W_OK):
545 err("xm save: Unable to create file %s" % savefile)
546 sys.exit(1)
548 server.xend.domain.save(domid, savefile)
550 def xm_restore(args):
551 arg_check(args, "restore", 1, 2)
553 try:
554 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
555 except getopt.GetoptError, opterr:
556 err(opterr)
557 sys.exit(1)
559 paused = False
560 for (k, v) in options:
561 if k in ['-p', '--paused']:
562 paused = True
564 if len(params) != 1:
565 err("Wrong number of parameters")
566 usage('restore')
567 sys.exit(1)
569 savefile = os.path.abspath(params[0])
571 if not os.access(savefile, os.R_OK):
572 err("xm restore: Unable to read file %s" % savefile)
573 sys.exit(1)
575 server.xend.domain.restore(savefile, paused)
578 def getDomains(domain_names, state, full = 0):
579 if domain_names:
580 return [server.xend.domain(dom, full) for dom in domain_names]
581 else:
582 return server.xend.domains_with_state(True, state, full)
585 def xm_list(args):
586 use_long = 0
587 show_vcpus = 0
588 show_labels = 0
589 state = 'all'
590 try:
591 (options, params) = getopt.gnu_getopt(args, 'lv',
592 ['long','vcpus','label',
593 'state='])
594 except getopt.GetoptError, opterr:
595 err(opterr)
596 usage('list')
597 sys.exit(1)
599 for (k, v) in options:
600 if k in ['-l', '--long']:
601 use_long = 1
602 if k in ['-v', '--vcpus']:
603 show_vcpus = 1
604 if k in ['--label']:
605 show_labels = 1
606 if k in ['--state']:
607 state = v
609 if state != 'all' and len(params) > 0:
610 raise OptionError(
611 "You may specify either a state or a particular VM, but not both")
613 if show_vcpus:
614 print >>sys.stderr, (
615 "xm list -v is deprecated. Please use xm vcpu-list.")
616 xm_vcpu_list(params)
617 return
619 doms = getDomains(params, state, use_long)
621 if use_long:
622 map(PrettyPrint.prettyprint, doms)
623 elif show_labels:
624 xm_label_list(doms)
625 else:
626 xm_brief_list(doms)
629 def parse_doms_info(info):
630 def get_info(n, t, d):
631 return t(sxp.child_value(info, n, d))
633 def get_status(n, t, d):
634 return DOM_STATES[t(sxp.child_value(info, n, d))]
636 start_time = get_info('start_time', float, -1)
637 if start_time == -1:
638 up_time = float(-1)
639 else:
640 up_time = time.time() - start_time
642 return {
643 'domid' : get_info('domid', str, ''),
644 'name' : get_info('name', str, '??'),
645 'mem' : get_info('memory_dynamic_min', int, 0),
646 'vcpus' : get_info('online_vcpus', int, 0),
647 'state' : get_info('state', str, ''),
648 'cpu_time' : get_info('cpu_time', float, 0),
649 'up_time' : up_time,
650 'seclabel' : security.get_security_printlabel(info),
651 }
654 def parse_sedf_info(info):
655 def get_info(n, t, d):
656 return t(sxp.child_value(info, n, d))
658 return {
659 'domid' : get_info('domid', int, -1),
660 'period' : get_info('period', int, -1),
661 'slice' : get_info('slice', int, -1),
662 'latency' : get_info('latency', int, -1),
663 'extratime': get_info('extratime', int, -1),
664 'weight' : get_info('weight', int, -1),
665 }
667 def xm_brief_list(doms):
668 print '%-40s %3s %5s %5s %10s %9s' % \
669 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
671 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
672 "%(cpu_time)8.1f"
674 for dom in doms:
675 d = parse_doms_info(dom)
676 print format % d
678 def xm_label_list(doms):
679 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
680 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
682 output = []
683 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
684 '%(cpu_time)8.1f %(seclabel)9s'
686 for dom in doms:
687 d = parse_doms_info(dom)
688 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
689 if not d['seclabel']:
690 d['seclabel'] = 'ERROR'
691 elif security.active_policy in ['DEFAULT']:
692 d['seclabel'] = 'DEFAULT'
693 else:
694 d['seclabel'] = 'INACTIVE'
695 output.append((format % d, d['seclabel']))
697 #sort by labels
698 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
699 for line, label in output:
700 print line
703 def xm_vcpu_list(args):
705 if args:
706 dominfo = map(server.xend.domain.getVCPUInfo, args)
707 else:
708 doms = server.xend.domains(False)
709 dominfo = map(server.xend.domain.getVCPUInfo, doms)
711 print '%-32s %3s %5s %5s %5s %9s %s' % \
712 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
714 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
715 ' %(cpu_time)8.1f %(cpumap)s'
717 for dom in dominfo:
718 def get_info(n):
719 return sxp.child_value(dom, n)
721 #
722 # convert a list of integers into a list of pairs indicating
723 # continuous sequences in the list:
724 #
725 # [0,1,2,3] -> [(0,3)]
726 # [1,2,4,5] -> [(1,2),(4,5)]
727 # [0] -> [(0,0)]
728 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
729 #
730 def list_to_rangepairs(cmap):
731 cmap.sort()
732 pairs = []
733 x = y = 0
734 for i in range(0,len(cmap)):
735 try:
736 if ((cmap[y+1] - cmap[i]) > 1):
737 pairs.append((cmap[x],cmap[y]))
738 x = y = i+1
739 else:
740 y = y + 1
741 # if we go off the end, then just add x to y
742 except IndexError:
743 pairs.append((cmap[x],cmap[y]))
745 return pairs
747 #
748 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
749 #
750 def format_pairs(pairs):
751 if not pairs:
752 return "no cpus"
753 out = ""
754 for f,s in pairs:
755 if (f==s):
756 out += '%d'%f
757 else:
758 out += '%d-%d'%(f,s)
759 out += ','
760 # trim trailing ','
761 return out[:-1]
763 def format_cpumap(cpumap):
764 cpumap = map(lambda x: int(x), cpumap)
765 cpumap.sort()
767 for x in server.xend.node.info()[1:]:
768 if len(x) > 1 and x[0] == 'nr_cpus':
769 nr_cpus = int(x[1])
770 # normalize cpumap by modulus nr_cpus, and drop duplicates
771 cpumap = dict.fromkeys(
772 map(lambda x: x % nr_cpus, cpumap)).keys()
773 if len(cpumap) == nr_cpus:
774 return "any cpu"
775 break
777 return format_pairs(list_to_rangepairs(cpumap))
779 name = get_info('name')
780 domid = int(get_info('domid'))
782 for vcpu in sxp.children(dom, 'vcpu'):
783 def vinfo(n, t):
784 return t(sxp.child_value(vcpu, n))
786 number = vinfo('number', int)
787 cpu = vinfo('cpu', int)
788 cpumap = format_cpumap(vinfo('cpumap', list))
789 online = vinfo('online', int)
790 cpu_time = vinfo('cpu_time', float)
791 running = vinfo('running', int)
792 blocked = vinfo('blocked', int)
794 if online:
795 c = str(cpu)
796 if running:
797 s = 'r'
798 else:
799 s = '-'
800 if blocked:
801 s += 'b'
802 else:
803 s += '-'
804 s += '-'
805 else:
806 c = "-"
807 s = "--p"
809 print format % locals()
811 def xm_start(args):
812 arg_check(args, "start", 1, 2)
814 try:
815 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
816 except getopt.GetoptError, opterr:
817 err(opterr)
818 sys.exit(1)
820 paused = False
821 for (k, v) in options:
822 if k in ['-p', '--paused']:
823 paused = True
825 if len(params) != 1:
826 err("Wrong number of parameters")
827 usage('start')
828 sys.exit(1)
830 dom = params[0]
831 if serverType == SERVER_XEN_API:
832 server.xenapi.VM.start(get_single_vm(dom), paused)
833 else:
834 server.xend.domain.start(dom, paused)
836 def xm_delete(args):
837 arg_check(args, "delete", 1)
838 dom = args[0]
839 if serverType == SERVER_XEN_API:
840 server.xenapi.VM.destroy(get_single_vm(dom))
841 else:
842 server.xend.domain.delete(dom)
844 def xm_suspend(args):
845 arg_check(args, "suspend", 1)
846 dom = args[0]
847 if serverType == SERVER_XEN_API:
848 server.xenapi.VM.suspend(get_single_vm(dom))
849 else:
850 server.xend.domain.suspend(dom)
852 def xm_resume(args):
853 arg_check(args, "resume", 1, 2)
855 try:
856 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
857 except getopt.GetoptError, opterr:
858 err(opterr)
859 sys.exit(1)
861 paused = False
862 for (k, v) in options:
863 if k in ['-p', '--paused']:
864 paused = True
866 if len(params) != 1:
867 err("Wrong number of parameters")
868 usage('resume')
869 sys.exit(1)
871 dom = params[0]
872 if serverType == SERVER_XEN_API:
873 server.xenapi.VM.resume(get_single_vm(dom), paused)
874 else:
875 server.xend.domain.resume(dom, paused)
877 def xm_reboot(args):
878 arg_check(args, "reboot", 1, 3)
879 from xen.xm import shutdown
880 shutdown.main(["shutdown", "-R"] + args)
882 def xm_shutdown(args):
883 arg_check(args, "shutdown", 1, 4)
884 from xen.xm import shutdown
885 shutdown.main(["shutdown"] + args)
887 def xm_pause(args):
888 arg_check(args, "pause", 1)
889 dom = args[0]
891 if serverType == SERVER_XEN_API:
892 server.xenapi.VM.pause(get_single_vm(dom))
893 else:
894 server.xend.domain.pause(dom)
896 def xm_unpause(args):
897 arg_check(args, "unpause", 1)
898 dom = args[0]
900 if serverType == SERVER_XEN_API:
901 server.xenapi.VM.unpause(get_single_vm(dom))
902 else:
903 server.xend.domain.unpause(dom)
905 def xm_dump_core(args):
906 live = False
907 crash = False
908 try:
909 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
910 for (k, v) in options:
911 if k in ('-L', '--live'):
912 live = True
913 if k in ('-C', '--crash'):
914 crash = True
916 if len(params) not in (1, 2):
917 raise OptionError("Expects 1 or 2 argument(s)")
918 except getopt.GetoptError, e:
919 raise OptionError(str(e))
921 dom = params[0]
922 if len(params) == 2:
923 filename = os.path.abspath(params[1])
924 else:
925 filename = None
927 if not live:
928 server.xend.domain.pause(dom)
930 try:
931 print "Dumping core of domain: %s ..." % str(dom)
932 server.xend.domain.dump(dom, filename, live, crash)
933 finally:
934 if not live:
935 server.xend.domain.unpause(dom)
937 if crash:
938 print "Destroying domain: %s ..." % str(dom)
939 server.xend.domain.destroy(dom)
941 def xm_rename(args):
942 arg_check(args, "rename", 2)
944 if serverType == SERVER_XEN_API:
945 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
946 else:
947 server.xend.domain.setName(args[0], args[1])
949 def xm_importcommand(command, args):
950 cmd = __import__(command, globals(), locals(), 'xen.xm')
951 cmd.main([command] + args)
954 #############################################################
956 def xm_vcpu_pin(args):
957 arg_check(args, "vcpu-pin", 3)
959 def cpu_make_map(cpulist):
960 cpus = []
961 for c in cpulist.split(','):
962 if c.find('-') != -1:
963 (x,y) = c.split('-')
964 for i in range(int(x),int(y)+1):
965 cpus.append(int(i))
966 else:
967 # remove this element from the list
968 if c[0] == '^':
969 cpus = [x for x in cpus if x != int(c[1:])]
970 else:
971 cpus.append(int(c))
972 cpus.sort()
973 return cpus
975 dom = args[0]
976 vcpu = args[1]
977 cpumap = cpu_make_map(args[2])
979 server.xend.domain.pincpu(dom, vcpu, cpumap)
981 def xm_mem_max(args):
982 arg_check(args, "mem-max", 2)
984 dom = args[0]
985 mem = int_unit(args[1], 'm')
987 server.xend.domain.maxmem_set(dom, mem)
989 def xm_mem_set(args):
990 arg_check(args, "mem-set", 2)
992 dom = args[0]
993 mem_target = int_unit(args[1], 'm')
995 server.xend.domain.setMemoryTarget(dom, mem_target)
997 def xm_vcpu_set(args):
998 arg_check(args, "vcpu-set", 2)
1000 server.xend.domain.setVCpuCount(args[0], int(args[1]))
1003 def xm_destroy(args):
1004 arg_check(args, "destroy", 1)
1006 dom = args[0]
1007 if serverType == SERVER_XEN_API:
1008 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1009 else:
1010 server.xend.domain.destroy(dom)
1013 def xm_domid(args):
1014 arg_check(args, "domid", 1)
1016 name = args[0]
1018 dom = server.xend.domain(name)
1019 print sxp.child_value(dom, 'domid')
1021 def xm_domname(args):
1022 arg_check(args, "domname", 1)
1024 name = args[0]
1026 dom = server.xend.domain(name)
1027 print sxp.child_value(dom, 'name')
1029 def xm_sched_sedf(args):
1030 def ns_to_ms(val):
1031 return float(val) * 0.000001
1033 def ms_to_ns(val):
1034 return (float(val) / 0.000001)
1036 def print_sedf(info):
1037 info['period'] = ns_to_ms(info['period'])
1038 info['slice'] = ns_to_ms(info['slice'])
1039 info['latency'] = ns_to_ms(info['latency'])
1040 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1041 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1043 def domid_match(domid, info):
1044 return domid is None or domid == info['name'] or \
1045 domid == str(info['domid'])
1047 # we want to just display current info if no parameters are passed
1048 if len(args) == 0:
1049 domid = None
1050 else:
1051 # we expect at least a domain id (name or number)
1052 # and at most a domid up to 5 options with values
1053 arg_check(args, "sched-sedf", 1, 11)
1054 domid = args[0]
1055 # drop domid from args since get_opt doesn't recognize it
1056 args = args[1:]
1058 opts = {}
1059 try:
1060 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1061 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1062 except getopt.GetoptError, opterr:
1063 err(opterr)
1064 sys.exit(1)
1066 # convert to nanoseconds if needed
1067 for (k, v) in options:
1068 if k in ['-p', '--period']:
1069 opts['period'] = ms_to_ns(v)
1070 elif k in ['-s', '--slice']:
1071 opts['slice'] = ms_to_ns(v)
1072 elif k in ['-l', '--latency']:
1073 opts['latency'] = ms_to_ns(v)
1074 elif k in ['-e', '--extratime']:
1075 opts['extratime'] = v
1076 elif k in ['-w', '--weight']:
1077 opts['weight'] = v
1079 doms = filter(lambda x : domid_match(domid, x),
1080 [parse_doms_info(dom)
1081 for dom in getDomains(None, 'running')])
1083 # print header if we aren't setting any parameters
1084 if len(opts.keys()) == 0:
1085 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1086 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1087 'Extra','Weight')
1089 for d in doms:
1090 # fetch current values so as not to clobber them
1091 try:
1092 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1093 except xmlrpclib.Fault:
1094 # domain does not support sched-sedf?
1095 sedf_raw = {}
1097 sedf_info = parse_sedf_info(sedf_raw)
1098 sedf_info['name'] = d['name']
1099 # update values in case of call to set
1100 if len(opts.keys()) > 0:
1101 for k in opts.keys():
1102 sedf_info[k]=opts[k]
1104 # send the update, converting user input
1105 v = map(int, [sedf_info['period'], sedf_info['slice'],
1106 sedf_info['latency'],sedf_info['extratime'],
1107 sedf_info['weight']])
1108 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1109 if int(rv) != 0:
1110 err("Failed to set sedf parameters (rv=%d)."%(rv))
1112 # not setting values, display info
1113 else:
1114 print_sedf(sedf_info)
1116 def xm_sched_credit(args):
1117 """Get/Set options for Credit Scheduler."""
1119 try:
1120 opts, params = getopt.getopt(args, "d:w:c:",
1121 ["domain=", "weight=", "cap="])
1122 except getopt.GetoptError, opterr:
1123 err(opterr)
1124 usage('sched-credit')
1125 sys.exit(1)
1127 domain = None
1128 weight = None
1129 cap = None
1131 for o, a in opts:
1132 if o == "-d":
1133 domain = a
1134 elif o == "-w":
1135 weight = int(a)
1136 elif o == "-c":
1137 cap = int(a);
1139 if domain is None:
1140 # place holder for system-wide scheduler parameters
1141 err("No domain given.")
1142 usage('sched-credit')
1143 sys.exit(1)
1145 if weight is None and cap is None:
1146 print server.xend.domain.sched_credit_get(domain)
1147 else:
1148 result = server.xend.domain.sched_credit_set(domain, weight, cap)
1149 if result != 0:
1150 err(str(result))
1152 def xm_info(args):
1153 arg_check(args, "info", 0)
1155 info = server.xend.node.info()
1157 for x in info[1:]:
1158 if len(x) < 2:
1159 print "%-23s: (none)" % x[0]
1160 else:
1161 print "%-23s:" % x[0], x[1]
1163 def xm_console(args):
1164 arg_check(args, "console", 1, 2)
1166 quiet = False;
1168 try:
1169 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1170 except getopt.GetoptError, opterr:
1171 err(opterr)
1172 sys.exit(1)
1174 for (k, v) in options:
1175 if k in ['-q', '--quiet']:
1176 quiet = True
1177 else:
1178 assert False
1180 if len(params) != 1:
1181 err('No domain given')
1182 usage('console')
1183 sys.exit(1)
1185 dom = params[0]
1187 try:
1188 info = server.xend.domain(dom)
1189 except:
1190 if quiet:
1191 sys.exit(1)
1192 else:
1193 raise
1194 domid = int(sxp.child_value(info, 'domid', '-1'))
1195 if domid == -1:
1196 if quiet:
1197 sys.exit(1)
1198 else:
1199 raise Exception("Domain is not started")
1201 console.execConsole(domid)
1204 def xm_uptime(args):
1205 short_mode = 0
1207 try:
1208 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1209 except getopt.GetoptError, opterr:
1210 err(opterr)
1211 sys.exit(1)
1213 for (k, v) in options:
1214 if k in ['-s', '--short']:
1215 short_mode = 1
1217 doms = getDomains(params, 'running')
1219 if short_mode == 0:
1220 print 'Name ID Uptime'
1222 for dom in doms:
1223 d = parse_doms_info(dom)
1224 if int(d['domid']) > 0:
1225 uptime = int(round(d['up_time']))
1226 else:
1227 f=open('/proc/uptime', 'r')
1228 upfile = f.read()
1229 uptime = int(round(float(upfile.split(' ')[0])))
1230 f.close()
1232 days = int(uptime / 86400)
1233 uptime -= (days * 86400)
1234 hours = int(uptime / 3600)
1235 uptime -= (hours * 3600)
1236 minutes = int(uptime / 60)
1237 uptime -= (minutes * 60)
1238 seconds = uptime
1240 upstring = ""
1241 if days > 0:
1242 upstring += str(days) + " day"
1243 if days > 1:
1244 upstring += "s"
1245 upstring += ", "
1246 upstring += '%(hours)2d:%(minutes)02d' % vars()
1248 if short_mode:
1249 now = datetime.datetime.now()
1250 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1251 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1252 else:
1253 upstring += ':%(seconds)02d' % vars()
1254 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1256 print upstring
1258 def xm_sysrq(args):
1259 arg_check(args, "sysrq", 2)
1260 dom = args[0]
1261 req = args[1]
1262 server.xend.domain.send_sysrq(dom, req)
1264 def xm_top(args):
1265 arg_check(args, "top", 0)
1267 os.execvp('xentop', ['xentop'])
1269 def xm_dmesg(args):
1270 arg_check(args, "dmesg", 0, 1)
1272 try:
1273 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1274 except getopt.GetoptError, opterr:
1275 err(opterr)
1276 sys.exit(1)
1278 use_clear = 0
1279 for (k, v) in options:
1280 if k in ['-c', '--clear']:
1281 use_clear = 1
1283 if len(params) :
1284 err("No parameter required")
1285 usage('dmesg')
1286 sys.exit(1)
1288 if not use_clear:
1289 print server.xend.node.dmesg.info()
1290 else:
1291 server.xend.node.dmesg.clear()
1293 def xm_log(args):
1294 arg_check(args, "log", 0)
1296 print server.xend.node.log()
1298 def xm_serve(args):
1299 arg_check(args, "serve", 0)
1301 from fcntl import fcntl, F_SETFL
1303 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1304 s.connect(XendClient.XML_RPC_SOCKET)
1305 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1307 while True:
1308 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1309 if s in iwtd:
1310 data = s.recv(4096)
1311 if len(data) > 0:
1312 sys.stdout.write(data)
1313 sys.stdout.flush()
1314 else:
1315 break
1316 if sys.stdin in iwtd:
1317 data = sys.stdin.read(4096)
1318 if len(data) > 0:
1319 s.sendall(data)
1320 else:
1321 break
1322 s.close()
1324 def parse_dev_info(info):
1325 def get_info(n, t, d):
1326 i = 0
1327 while i < len(info):
1328 if (info[i][0] == n):
1329 return t(info[i][1])
1330 i = i + 1
1331 return t(d)
1332 return {
1333 #common
1334 'backend-id' : get_info('backend-id', int, -1),
1335 'handle' : get_info('handle', int, 0),
1336 'state' : get_info('state', int, -1),
1337 'be-path' : get_info('backend', str, '??'),
1338 'event-ch' : get_info('event-channel',int, -1),
1339 #network specific
1340 'virtual-device' : get_info('virtual-device', str, '??'),
1341 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1342 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1343 'mac' : get_info('mac', str, '??'),
1344 #block-device specific
1345 'ring-ref' : get_info('ring-ref', int, -1),
1348 def arg_check_for_resource_list(args, name):
1349 use_long = 0
1350 try:
1351 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1352 except getopt.GetoptError, opterr:
1353 err(opterr)
1354 sys.exit(1)
1356 for (k, v) in options:
1357 if k in ['-l', '--long']:
1358 use_long = 1
1360 if len(params) == 0:
1361 print 'No domain parameter given'
1362 usage(name)
1363 if len(params) > 1:
1364 print 'No multiple domain parameters allowed'
1365 usage(name)
1367 return (use_long, params)
1369 def xm_network_list(args):
1370 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1372 dom = params[0]
1373 if use_long:
1374 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1375 map(PrettyPrint.prettyprint, devs)
1376 else:
1377 hdr = 0
1378 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
1379 if hdr == 0:
1380 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1381 hdr = 1
1382 ni = parse_dev_info(x[1])
1383 ni['idx'] = int(x[0])
1384 print ("%(idx)-3d "
1385 "%(backend-id)-3d"
1386 "%(mac)-17s "
1387 "%(handle)-3d "
1388 "%(state)-3d "
1389 "%(event-ch)-3d "
1390 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1391 "%(be-path)-30s "
1392 % ni)
1394 def xm_block_list(args):
1395 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1397 dom = params[0]
1398 if use_long:
1399 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1400 map(PrettyPrint.prettyprint, devs)
1401 else:
1402 hdr = 0
1403 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
1404 if hdr == 0:
1405 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1406 hdr = 1
1407 ni = parse_dev_info(x[1])
1408 ni['idx'] = int(x[0])
1409 print ("%(idx)-3d "
1410 "%(backend-id)-3d "
1411 "%(handle)-3d "
1412 "%(state)-3d "
1413 "%(event-ch)-3d "
1414 "%(ring-ref)-5d "
1415 "%(be-path)-30s "
1416 % ni)
1418 def xm_vtpm_list(args):
1419 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1421 dom = params[0]
1422 if use_long:
1423 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1424 map(PrettyPrint.prettyprint, devs)
1425 else:
1426 hdr = 0
1427 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1428 if hdr == 0:
1429 print 'Idx BE handle state evt-ch ring-ref BE-path'
1430 hdr = 1
1431 ni = parse_dev_info(x[1])
1432 ni['idx'] = int(x[0])
1433 print ("%(idx)-3d "
1434 "%(backend-id)-3d "
1435 "%(handle)-3d "
1436 "%(state)-3d "
1437 "%(event-ch)-3d "
1438 "%(ring-ref)-5d "
1439 "%(be-path)-30s "
1440 % ni)
1443 def parse_block_configuration(args):
1444 dom = args[0]
1446 if args[1].startswith('tap:'):
1447 cls = 'tap'
1448 else:
1449 cls = 'vbd'
1451 vbd = [cls,
1452 ['uname', args[1]],
1453 ['dev', args[2]],
1454 ['mode', args[3]]]
1455 if len(args) == 5:
1456 vbd.append(['backend', args[4]])
1458 # verify that policy permits attaching this resource
1459 if security.on():
1460 dominfo = server.xend.domain(dom)
1461 label = security.get_security_printlabel(dominfo)
1462 else:
1463 label = None
1464 security.res_security_check(args[1], label)
1466 return (dom, vbd)
1469 def xm_block_attach(args):
1470 arg_check(args, 'block-attach', 4, 5)
1472 (dom, vbd) = parse_block_configuration(args)
1473 server.xend.domain.device_create(dom, vbd)
1476 def xm_block_configure(args):
1477 arg_check(args, 'block-configure', 4, 5)
1479 (dom, vbd) = parse_block_configuration(args)
1480 server.xend.domain.device_configure(dom, vbd)
1483 def xm_network_attach(args):
1484 arg_check(args, 'network-attach', 1, 10000)
1486 dom = args[0]
1487 vif = ['vif']
1489 for a in args[1:]:
1490 vif.append(a.split("="))
1492 server.xend.domain.device_create(dom, vif)
1495 def detach(args, command, deviceClass):
1496 arg_check(args, command, 2, 3)
1498 dom = args[0]
1499 dev = args[1]
1500 try:
1501 force = args[2]
1502 if (force != "--force") and (force != "-f"):
1503 print "Ignoring option %s"%(force)
1504 force = None
1505 except IndexError:
1506 force = None
1508 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
1511 def xm_block_detach(args):
1512 detach(args, 'block-detach', 'vbd')
1513 detach(args, 'block-detach', 'tap')
1516 def xm_network_detach(args):
1517 detach(args, 'network-detach', 'vif')
1520 def xm_vnet_list(args):
1521 try:
1522 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1523 except getopt.GetoptError, opterr:
1524 err(opterr)
1525 sys.exit(1)
1527 use_long = 0
1528 for (k, v) in options:
1529 if k in ['-l', '--long']:
1530 use_long = 1
1532 if params:
1533 use_long = 1
1534 vnets = params
1535 else:
1536 vnets = server.xend_vnets()
1538 for vnet in vnets:
1539 try:
1540 if use_long:
1541 info = server.xend_vnet(vnet)
1542 PrettyPrint.prettyprint(info)
1543 else:
1544 print vnet
1545 except Exception, ex:
1546 print vnet, ex
1548 def xm_vnet_create(args):
1549 arg_check(args, "vnet-create", 1)
1550 conf = args[0]
1551 if not os.access(conf, os.R_OK):
1552 print "File not found: %s" % conf
1553 sys.exit(1)
1555 server.xend_vnet_create(conf)
1557 def xm_vnet_delete(args):
1558 arg_check(args, "vnet-delete", 1)
1559 vnet = args[0]
1560 server.xend_vnet_delete(vnet)
1562 commands = {
1563 # console commands
1564 "console": xm_console,
1565 # xenstat commands
1566 "top": xm_top,
1567 # domain commands
1568 "delete": xm_delete,
1569 "destroy": xm_destroy,
1570 "domid": xm_domid,
1571 "domname": xm_domname,
1572 "dump-core": xm_dump_core,
1573 "reboot": xm_reboot,
1574 "rename": xm_rename,
1575 "restore": xm_restore,
1576 "resume": xm_resume,
1577 "save": xm_save,
1578 "shutdown": xm_shutdown,
1579 "start": xm_start,
1580 "sysrq": xm_sysrq,
1581 "uptime": xm_uptime,
1582 "suspend": xm_suspend,
1583 "list": xm_list,
1584 # memory commands
1585 "mem-max": xm_mem_max,
1586 "mem-set": xm_mem_set,
1587 # cpu commands
1588 "vcpu-pin": xm_vcpu_pin,
1589 "vcpu-list": xm_vcpu_list,
1590 "vcpu-set": xm_vcpu_set,
1591 # special
1592 "pause": xm_pause,
1593 "unpause": xm_unpause,
1594 # host commands
1595 "dmesg": xm_dmesg,
1596 "info": xm_info,
1597 "log": xm_log,
1598 "serve": xm_serve,
1599 # scheduler
1600 "sched-sedf": xm_sched_sedf,
1601 "sched-credit": xm_sched_credit,
1602 # block
1603 "block-attach": xm_block_attach,
1604 "block-detach": xm_block_detach,
1605 "block-list": xm_block_list,
1606 "block-configure": xm_block_configure,
1607 # network
1608 "network-attach": xm_network_attach,
1609 "network-detach": xm_network_detach,
1610 "network-list": xm_network_list,
1611 # vnet
1612 "vnet-list": xm_vnet_list,
1613 "vnet-create": xm_vnet_create,
1614 "vnet-delete": xm_vnet_delete,
1615 # vtpm
1616 "vtpm-list": xm_vtpm_list,
1619 ## The commands supported by a separate argument parser in xend.xm.
1620 IMPORTED_COMMANDS = [
1621 'create',
1622 'new',
1623 'migrate',
1624 'labels',
1625 'cfgbootpolicy',
1626 'makepolicy',
1627 'loadpolicy',
1628 'dumppolicy',
1629 'addlabel',
1630 'rmlabel',
1631 'getlabel',
1632 'dry-run',
1633 'resources',
1636 for c in IMPORTED_COMMANDS:
1637 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
1639 aliases = {
1640 "balloon": "mem-set",
1641 "set-vcpus": "vcpu-set",
1642 "vif-list": "network-list",
1643 "vbd-create": "block-attach",
1644 "vbd-destroy": "block-detach",
1645 "vbd-list": "block-list",
1649 def xm_lookup_cmd(cmd):
1650 if commands.has_key(cmd):
1651 return commands[cmd]
1652 elif aliases.has_key(cmd):
1653 deprecated(cmd,aliases[cmd])
1654 return commands[aliases[cmd]]
1655 elif cmd == 'help':
1656 longHelp()
1657 sys.exit(0)
1658 else:
1659 # simulate getopt's prefix matching behaviour
1660 if len(cmd) > 1:
1661 same_prefix_cmds = [commands[c] for c in commands.keys() \
1662 if c[:len(cmd)] == cmd]
1663 # only execute if there is only 1 match
1664 if len(same_prefix_cmds) == 1:
1665 return same_prefix_cmds[0]
1667 err('Sub Command %s not found!' % cmd)
1668 usage()
1670 def deprecated(old,new):
1671 print >>sys.stderr, (
1672 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1674 def main(argv=sys.argv):
1675 global server
1677 if len(argv) < 2:
1678 usage()
1680 # intercept --help(-h) and output our own help
1681 for help in ['--help', '-h']:
1682 if help in argv[1:]:
1683 if help == argv[1]:
1684 longHelp()
1685 else:
1686 usage(argv[1])
1687 sys.exit(0)
1689 cmd = xm_lookup_cmd(argv[1])
1691 # strip off prog name and subcmd
1692 args = argv[2:]
1693 if cmd:
1694 try:
1695 if serverType == SERVER_XEN_API:
1696 server = XenAPI.Session(serverURI)
1697 username, password = parseAuthentication()
1698 server.login_with_password(username, password)
1699 def logout():
1700 try:
1701 server.xenapi.session.logout()
1702 except:
1703 pass
1704 atexit.register(logout)
1705 else:
1706 server = ServerProxy(serverURI)
1708 rc = cmd(args)
1709 if rc:
1710 usage()
1711 except socket.error, ex:
1712 if os.geteuid() != 0:
1713 err("Most commands need root access. Please try again as root.")
1714 else:
1715 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
1716 sys.exit(1)
1717 except KeyboardInterrupt:
1718 print "Interrupted."
1719 sys.exit(1)
1720 except IOError, ex:
1721 if os.geteuid() != 0:
1722 err("Most commands need root access. Please try again as root.")
1723 else:
1724 err("Unable to connect to xend: %s." % ex[1])
1725 sys.exit(1)
1726 except SystemExit:
1727 sys.exit(1)
1728 except XenAPI.Failure, exn:
1729 err(str(exn))
1730 sys.exit(1)
1731 except xmlrpclib.Fault, ex:
1732 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
1733 err("Domain '%s' does not exist." % ex.faultString)
1734 else:
1735 err(ex.faultString)
1736 usage(argv[1])
1737 sys.exit(1)
1738 except xmlrpclib.ProtocolError, ex:
1739 if ex.errcode == -1:
1740 print >>sys.stderr, (
1741 "Xend has probably crashed! Invalid or missing HTTP "
1742 "status code.")
1743 else:
1744 print >>sys.stderr, (
1745 "Xend has probably crashed! ProtocolError(%d, %s)." %
1746 (ex.errcode, ex.errmsg))
1747 sys.exit(1)
1748 except (ValueError, OverflowError):
1749 err("Invalid argument.")
1750 usage(argv[1])
1751 sys.exit(1)
1752 except OptionError, e:
1753 err(str(e))
1754 usage(argv[1])
1755 print e.usage()
1756 sys.exit(1)
1757 except security.ACMError, e:
1758 err(str(e))
1759 sys.exit(1)
1760 except:
1761 print "Unexpected error:", sys.exc_info()[0]
1762 print
1763 print "Please report to xen-devel@lists.xensource.com"
1764 raise
1766 else:
1767 usage()
1769 if __name__ == "__main__":
1770 main()