ia64/xen-unstable

view tools/python/xen/xm/main.py @ 12810:cf1ca0615414

Added support for configuration file for xm, and use that to specify
contact and authentication details for the Xen-API server.

The default behaviour is still to use the existing legacy XML-RPC server.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Wed Dec 06 11:02:32 2006 +0000 (2006-12-06)
parents 5bed7bc05c8a
children 26a3c7c10782
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 datetime
34 from select import select
35 import xml.dom.minidom
37 import warnings
38 warnings.filterwarnings('ignore', category=FutureWarning)
40 from xen.xend import PrettyPrint
41 from xen.xend import sxp
42 from xen.xend import XendClient
43 from xen.xend.XendConstants import *
45 from xen.xm.opts import OptionError, Opts, wrap, set_true
46 from xen.xm import console
47 from xen.util import security
48 from xen.util.xmlrpclib2 import ServerProxy
50 import XenAPI
52 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
53 # getopt.getopt if gnu_getopt is not available. This will mean that options
54 # may only be specified before positional arguments.
55 if not hasattr(getopt, 'gnu_getopt'):
56 getopt.gnu_getopt = getopt.getopt
58 XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
60 # Supported types of server
61 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
62 SERVER_XEN_API = 'Xen-API'
64 # General help message
66 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
67 "Control, list, and manipulate Xen guest instances.\n"
69 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
70 'For more help on \'xm\' see the xm(1) man page.\n' \
71 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
72 ' man page.\n'
74 # Help strings are indexed by subcommand name in this way:
75 # 'subcommand': (argstring, description)
77 SUBCOMMAND_HELP = {
78 # common commands
80 'console' : ('[-q|--quiet] <Domain>',
81 'Attach to <Domain>\'s console.'),
82 'create' : ('<ConfigFile> [options] [vars]',
83 'Create a domain based on <ConfigFile>.'),
84 'destroy' : ('<Domain>',
85 'Terminate a domain immediately.'),
86 'help' : ('', 'Display this message.'),
87 'list' : ('[options] [Domain, ...]',
88 'List information about all/some domains.'),
89 'mem-max' : ('<Domain> <Mem>',
90 'Set the maximum amount reservation for a domain.'),
91 'mem-set' : ('<Domain> <Mem>',
92 'Set the current memory usage for a domain.'),
93 'migrate' : ('<Domain> <Host>',
94 'Migrate a domain to another machine.'),
95 'pause' : ('<Domain>', 'Pause execution of a domain.'),
96 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
97 'restore' : ('<CheckpointFile> [-p]',
98 'Restore a domain from a saved state.'),
99 'save' : ('<Domain> <CheckpointFile>',
100 'Save a domain state to restore later.'),
101 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
102 'top' : ('', 'Monitor a host and the domains in real time.'),
103 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
104 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
106 # Life cycle xm commands
107 'new' : ('<ConfigFile> [options] [vars]',
108 'Adds a domain to Xend domain management'),
109 'delete' : ('<DomainName>',
110 'Remove a domain from Xend domain management.'),
111 'start' : ('<DomainName>', 'Start a Xend managed domain'),
112 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
113 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
115 # less used commands
117 'dmesg' : ('[-c|--clear]',
118 'Read and/or clear Xend\'s message buffer.'),
119 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
120 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
121 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
122 'Dump core for a specific domain.'),
123 'info' : ('', 'Get information about Xen host.'),
124 'log' : ('', 'Print Xend log'),
125 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
126 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
127 'sched-credit': ('-d <Domain> [-w[=WEIGHT]|-c[=CAP]]',
128 'Get/set credit scheduler parameters.'),
129 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
130 'vcpu-list' : ('[<Domain>]',
131 'List the VCPUs for a domain or all domains.'),
132 'vcpu-pin' : ('<Domain> <VCPU> <CPUs>',
133 'Set which CPUs a VCPU can use.'),
134 'vcpu-set' : ('<Domain> <vCPUs>',
135 'Set the number of active VCPUs for allowed for the'
136 ' domain.'),
138 # device commands
140 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode>',
141 'Create a new virtual block device.'),
142 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomId]',
143 'Change block device configuration'),
144 'block-detach' : ('<Domain> <DevId>',
145 'Destroy a domain\'s virtual block device.'),
146 'block-list' : ('<Domain> [--long]',
147 'List virtual block devices for a domain.'),
148 'network-attach': ('<Domain> [--script=<script>] [--ip=<ip>] '
149 '[--mac=<mac>]',
150 'Create a new virtual network device.'),
151 'network-detach': ('<Domain> <DevId>',
152 'Destroy a domain\'s virtual network device.'),
153 'network-list' : ('<Domain> [--long]',
154 'List virtual network interfaces for a domain.'),
155 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
156 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
157 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
158 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
160 # security
162 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
163 'Add security label to domain.'),
164 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
165 'Remove a security label from domain.'),
166 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
167 'Show security label for domain or resource.'),
168 'dry-run' : ('<ConfigFile>',
169 'Test if a domain can access its resources.'),
170 'resources' : ('', 'Show info for each labeled resource.'),
171 'cfgbootpolicy' : ('<policy> [boot-title]',
172 'Add policy to boot configuration.'),
173 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
174 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
175 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
176 'files.'),
177 'labels' : ('[policy] [type=dom|res|any]',
178 'List <type> labels for (active) policy.'),
179 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
180 }
182 SUBCOMMAND_OPTIONS = {
183 'sched-sedf': (
184 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
185 ('-s [MS]', '--slice[=MS]' ,
186 'Worst-case execution time(ms). (slice < period)'),
187 ('-l [MS]', '--latency[=MS]',
188 'Scaled period (ms) when domain performs heavy I/O'),
189 ('-e [FLAG]', '--extra[=FLAG]',
190 'Flag (0 or 1) controls if domain can run in extra time.'),
191 ('-w [FLOAT]', '--weight[=FLOAT]',
192 'CPU Period/slice (do not set with --period/--slice)'),
193 ),
194 'sched-credit': (
195 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
196 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
197 ('-c CAP', '--cap=CAP', 'Cap (int)'),
198 ),
199 'list': (
200 ('-l', '--long', 'Output all VM details in SXP'),
201 ('', '--label', 'Include security labels'),
202 ('', '--state=<state>', 'Select only VMs with the specified state'),
203 ),
204 'console': (
205 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
206 ),
207 'dmesg': (
208 ('-c', '--clear', 'Clear dmesg buffer'),
209 ),
210 'vnet-list': (
211 ('-l', '--long', 'List Vnets as SXP'),
212 ),
213 'network-list': (
214 ('-l', '--long', 'List resources as SXP'),
215 ),
216 'dump-core': (
217 ('-L', '--live', 'Dump core without pausing the domain'),
218 ('-C', '--crash', 'Crash domain after dumping core'),
219 ),
220 'start': (
221 ('-p', '--paused', 'Do not unpause domain after starting it'),
222 ),
223 'resume': (
224 ('-p', '--paused', 'Do not unpause domain after resuming it'),
225 ),
226 'restore': (
227 ('-p', '--paused', 'Do not unpause domain after restoring it'),
228 ),
229 }
231 common_commands = [
232 "console",
233 "create",
234 "new",
235 "delete",
236 "destroy",
237 "dump-core",
238 "help",
239 "list",
240 "mem-set",
241 "migrate",
242 "pause",
243 "reboot",
244 "restore",
245 "resume",
246 "save",
247 "shutdown",
248 "start",
249 "suspend",
250 "top",
251 "unpause",
252 "uptime",
253 "vcpu-set",
254 ]
256 domain_commands = [
257 "console",
258 "create",
259 "new",
260 "delete",
261 "destroy",
262 "domid",
263 "domname",
264 "dump-core",
265 "list",
266 "mem-max",
267 "mem-set",
268 "migrate",
269 "pause",
270 "reboot",
271 "rename",
272 "restore",
273 "resume",
274 "save",
275 "shutdown",
276 "start",
277 "suspend",
278 "sysrq",
279 "top",
280 "unpause",
281 "uptime",
282 "vcpu-list",
283 "vcpu-pin",
284 "vcpu-set",
285 ]
287 host_commands = [
288 "dmesg",
289 "info",
290 "log",
291 "serve",
292 ]
294 scheduler_commands = [
295 "sched-credit",
296 "sched-sedf",
297 ]
299 device_commands = [
300 "block-attach",
301 "block-detach",
302 "block-list",
303 "block-configure",
304 "network-attach",
305 "network-detach",
306 "network-list",
307 "vtpm-list",
308 ]
310 vnet_commands = [
311 "vnet-list",
312 "vnet-create",
313 "vnet-delete",
314 ]
316 acm_commands = [
317 "labels",
318 "addlabel",
319 "rmlabel",
320 "getlabel",
321 "dry-run",
322 "resources",
323 "makepolicy",
324 "loadpolicy",
325 "cfgbootpolicy",
326 "dumppolicy",
327 ]
329 all_commands = (domain_commands + host_commands + scheduler_commands +
330 device_commands + vnet_commands + acm_commands)
333 ##
334 # Configuration File Parsing
335 ##
337 if os.path.isfile(XM_CONFIG_FILE):
338 config = xml.dom.minidom.parse(XM_CONFIG_FILE)
339 else:
340 config = None
342 def parseServer():
343 if config:
344 server = config.getElementsByTagName('server')
345 if server:
346 st = server[0].getAttribute('type')
347 if st != SERVER_XEN_API:
348 st = SERVER_LEGACY_XMLRPC
349 return (st, server[0].getAttribute('uri'))
351 return SERVER_LEGACY_XMLRPC, XendClient.uri
353 def parseAuthentication():
354 server = config.getElementsByTagName('server')[0]
355 return (server.getAttribute('username'),
356 server.getAttribute('password'))
358 serverType, serverURI = parseServer()
361 ####################################################################
362 #
363 # Help/usage printing functions
364 #
365 ####################################################################
367 def cmdHelp(cmd):
368 """Print help for a specific subcommand."""
370 for fc in SUBCOMMAND_HELP.keys():
371 if fc[:len(cmd)] == cmd:
372 cmd = fc
373 break
375 try:
376 args, desc = SUBCOMMAND_HELP[cmd]
377 except KeyError:
378 shortHelp()
379 return
381 print 'Usage: xm %s %s' % (cmd, args)
382 print
383 print desc
385 try:
386 # If options help message is defined, print this.
387 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
388 if shortopt and longopt:
389 optdesc = '%s, %s' % (shortopt, longopt)
390 elif shortopt:
391 optdesc = shortopt
392 elif longopt:
393 optdesc = longopt
395 wrapped_desc = wrap(desc, 43)
396 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
397 for line in wrapped_desc[1:]:
398 print ' ' * 33 + line
399 print
400 except KeyError:
401 # if the command is an external module, we grab usage help
402 # from the module itself.
403 if cmd in IMPORTED_COMMANDS:
404 try:
405 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
406 cmd_usage = getattr(cmd_module, "help", None)
407 if cmd_usage:
408 print cmd_usage()
409 except ImportError:
410 pass
412 def shortHelp():
413 """Print out generic help when xm is called without subcommand."""
415 print USAGE_HELP
416 print 'Common \'xm\' commands:\n'
418 for command in common_commands:
419 try:
420 args, desc = SUBCOMMAND_HELP[command]
421 except KeyError:
422 continue
423 wrapped_desc = wrap(desc, 50)
424 print ' %-20s %-50s' % (command, wrapped_desc[0])
425 for line in wrapped_desc[1:]:
426 print ' ' * 22 + line
428 print
429 print USAGE_FOOTER
430 print 'For a complete list of subcommands run \'xm help\'.'
432 def longHelp():
433 """Print out full help when xm is called with xm --help or xm help"""
435 print USAGE_HELP
436 print 'xm full list of subcommands:\n'
438 for command in all_commands:
439 try:
440 args, desc = SUBCOMMAND_HELP[command]
441 except KeyError:
442 continue
444 wrapped_desc = wrap(desc, 50)
445 print ' %-20s %-50s' % (command, wrapped_desc[0])
446 for line in wrapped_desc[1:]:
447 print ' ' * 22 + line
449 print
450 print USAGE_FOOTER
452 def usage(cmd = None):
453 """ Print help usage information and exits """
454 if cmd:
455 cmdHelp(cmd)
456 else:
457 shortHelp()
458 sys.exit(1)
461 ####################################################################
462 #
463 # Utility functions
464 #
465 ####################################################################
467 def arg_check(args, name, lo, hi = -1):
468 n = len([i for i in args if i != '--'])
470 if hi == -1:
471 if n != lo:
472 err("'xm %s' requires %d argument%s.\n" % (name, lo,
473 lo == 1 and '' or 's'))
474 usage(name)
475 else:
476 if n < lo or n > hi:
477 err("'xm %s' requires between %d and %d arguments.\n" %
478 (name, lo, hi))
479 usage(name)
482 def unit(c):
483 if not c.isalpha():
484 return 0
485 base = 1
486 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
487 elif c == 'M' or c == 'm': base = 1024 * 1024
488 elif c == 'K' or c == 'k': base = 1024
489 else:
490 print 'ignoring unknown unit'
491 return base
493 def int_unit(str, dest):
494 base = unit(str[-1])
495 if not base:
496 return int(str)
498 value = int(str[:-1])
499 dst_base = unit(dest)
500 if dst_base == 0:
501 dst_base = 1
502 if dst_base > base:
503 return value / (dst_base / base)
504 else:
505 return value * (base / dst_base)
507 def err(msg):
508 print >>sys.stderr, "Error:", msg
511 def get_single_vm(dom):
512 uuids = server.xenapi.VM.get_by_name_label(dom)
513 n = len(uuids)
514 if n == 1:
515 return uuids[0]
516 else:
517 dominfo = server.xend.domain(dom, False)
518 return dominfo['uuid']
521 #########################################################################
522 #
523 # Main xm functions
524 #
525 #########################################################################
527 def xm_save(args):
528 arg_check(args, "save", 2)
530 try:
531 dominfo = parse_doms_info(server.xend.domain(args[0]))
532 except xmlrpclib.Fault, ex:
533 raise ex
535 domid = dominfo['domid']
536 savefile = os.path.abspath(args[1])
538 if not os.access(os.path.dirname(savefile), os.W_OK):
539 err("xm save: Unable to create file %s" % savefile)
540 sys.exit(1)
542 server.xend.domain.save(domid, savefile)
544 def xm_restore(args):
545 arg_check(args, "restore", 1, 2)
547 try:
548 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
549 except getopt.GetoptError, opterr:
550 err(opterr)
551 sys.exit(1)
553 paused = False
554 for (k, v) in options:
555 if k in ['-p', '--paused']:
556 paused = True
558 if len(params) != 1:
559 err("Wrong number of parameters")
560 usage('restore')
561 sys.exit(1)
563 savefile = os.path.abspath(params[0])
565 if not os.access(savefile, os.R_OK):
566 err("xm restore: Unable to read file %s" % savefile)
567 sys.exit(1)
569 server.xend.domain.restore(savefile, paused)
572 def getDomains(domain_names, state, full = 0):
573 if domain_names:
574 return [server.xend.domain(dom, full) for dom in domain_names]
575 else:
576 return server.xend.domains_with_state(True, state, full)
579 def xm_list(args):
580 use_long = 0
581 show_vcpus = 0
582 show_labels = 0
583 state = 'all'
584 try:
585 (options, params) = getopt.gnu_getopt(args, 'lv',
586 ['long','vcpus','label',
587 'state='])
588 except getopt.GetoptError, opterr:
589 err(opterr)
590 usage('list')
591 sys.exit(1)
593 for (k, v) in options:
594 if k in ['-l', '--long']:
595 use_long = 1
596 if k in ['-v', '--vcpus']:
597 show_vcpus = 1
598 if k in ['--label']:
599 show_labels = 1
600 if k in ['--state']:
601 state = v
603 if state != 'all' and len(params) > 0:
604 raise OptionError(
605 "You may specify either a state or a particular VM, but not both")
607 if show_vcpus:
608 print >>sys.stderr, (
609 "xm list -v is deprecated. Please use xm vcpu-list.")
610 xm_vcpu_list(params)
611 return
613 doms = getDomains(params, state, use_long)
615 if use_long:
616 map(PrettyPrint.prettyprint, doms)
617 elif show_labels:
618 xm_label_list(doms)
619 else:
620 xm_brief_list(doms)
623 def parse_doms_info(info):
624 def get_info(n, t, d):
625 return t(sxp.child_value(info, n, d))
627 def get_status(n, t, d):
628 return DOM_STATES[t(sxp.child_value(info, n, d))]
630 return {
631 'domid' : get_info('domid', str, ''),
632 'name' : get_info('name', str, '??'),
633 'mem' : get_info('memory_dynamic_min', int, 0),
634 'vcpus' : get_info('vcpus', int, 0),
635 'state' : get_info('state', str, ''),
636 'cpu_time' : get_info('cpu_time', float, 0),
637 'up_time' : get_info('up_time', float, -1),
638 'seclabel' : security.get_security_printlabel(info),
639 }
642 def parse_sedf_info(info):
643 def get_info(n, t, d):
644 return t(sxp.child_value(info, n, d))
646 return {
647 'domid' : get_info('domid', int, -1),
648 'period' : get_info('period', int, -1),
649 'slice' : get_info('slice', int, -1),
650 'latency' : get_info('latency', int, -1),
651 'extratime': get_info('extratime', int, -1),
652 'weight' : get_info('weight', int, -1),
653 }
655 def xm_brief_list(doms):
656 print '%-40s %3s %5s %5s %10s %9s' % \
657 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
659 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
660 "%(cpu_time)8.1f"
662 for dom in doms:
663 d = parse_doms_info(dom)
664 print format % d
666 def xm_label_list(doms):
667 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
668 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
670 output = []
671 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
672 '%(cpu_time)8.1f %(seclabel)9s'
674 for dom in doms:
675 d = parse_doms_info(dom)
676 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
677 if not d['seclabel']:
678 d['seclabel'] = 'ERROR'
679 elif security.active_policy in ['DEFAULT']:
680 d['seclabel'] = 'DEFAULT'
681 else:
682 d['seclabel'] = 'INACTIVE'
683 output.append((format % d, d['seclabel']))
685 #sort by labels
686 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
687 for line, label in output:
688 print line
691 def xm_vcpu_list(args):
693 if args:
694 dominfo = map(server.xend.domain.getVCPUInfo, args)
695 else:
696 doms = server.xend.domains(False)
697 dominfo = map(server.xend.domain.getVCPUInfo, doms)
699 print '%-32s %3s %5s %5s %5s %9s %s' % \
700 ('Name', 'ID', 'VCPUs', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
702 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
703 ' %(cpu_time)8.1f %(cpumap)s'
705 for dom in dominfo:
706 def get_info(n):
707 return sxp.child_value(dom, n)
709 #
710 # convert a list of integers into a list of pairs indicating
711 # continuous sequences in the list:
712 #
713 # [0,1,2,3] -> [(0,3)]
714 # [1,2,4,5] -> [(1,2),(4,5)]
715 # [0] -> [(0,0)]
716 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
717 #
718 def list_to_rangepairs(cmap):
719 cmap.sort()
720 pairs = []
721 x = y = 0
722 for i in range(0,len(cmap)):
723 try:
724 if ((cmap[y+1] - cmap[i]) > 1):
725 pairs.append((cmap[x],cmap[y]))
726 x = y = i+1
727 else:
728 y = y + 1
729 # if we go off the end, then just add x to y
730 except IndexError:
731 pairs.append((cmap[x],cmap[y]))
733 return pairs
735 #
736 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
737 #
738 def format_pairs(pairs):
739 if not pairs:
740 return "no cpus"
741 out = ""
742 for f,s in pairs:
743 if (f==s):
744 out += '%d'%f
745 else:
746 out += '%d-%d'%(f,s)
747 out += ','
748 # trim trailing ','
749 return out[:-1]
751 def format_cpumap(cpumap):
752 cpumap = map(lambda x: int(x), cpumap)
753 cpumap.sort()
755 for x in server.xend.node.info()[1:]:
756 if len(x) > 1 and x[0] == 'nr_cpus':
757 nr_cpus = int(x[1])
758 # normalize cpumap by modulus nr_cpus, and drop duplicates
759 cpumap = dict.fromkeys(
760 map(lambda x: x % nr_cpus, cpumap)).keys()
761 if len(cpumap) == nr_cpus:
762 return "any cpu"
763 break
765 return format_pairs(list_to_rangepairs(cpumap))
767 name = get_info('name')
768 domid = int(get_info('domid'))
770 for vcpu in sxp.children(dom, 'vcpu'):
771 def vinfo(n, t):
772 return t(sxp.child_value(vcpu, n))
774 number = vinfo('number', int)
775 cpu = vinfo('cpu', int)
776 cpumap = format_cpumap(vinfo('cpumap', list))
777 online = vinfo('online', int)
778 cpu_time = vinfo('cpu_time', float)
779 running = vinfo('running', int)
780 blocked = vinfo('blocked', int)
782 if online:
783 c = str(cpu)
784 if running:
785 s = 'r'
786 else:
787 s = '-'
788 if blocked:
789 s += 'b'
790 else:
791 s += '-'
792 s += '-'
793 else:
794 c = "-"
795 s = "--p"
797 print format % locals()
799 def xm_start(args):
800 arg_check(args, "start", 1, 2)
802 try:
803 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
804 except getopt.GetoptError, opterr:
805 err(opterr)
806 sys.exit(1)
808 paused = False
809 for (k, v) in options:
810 if k in ['-p', '--paused']:
811 paused = True
813 if len(params) != 1:
814 err("Wrong number of parameters")
815 usage('start')
816 sys.exit(1)
818 dom = params[0]
819 if serverType == SERVER_XEN_API:
820 server.xenapi.VM.start(get_single_vm(dom), paused)
821 else:
822 server.xend.domain.start(dom, paused)
824 def xm_delete(args):
825 arg_check(args, "delete", 1)
826 dom = args[0]
827 if serverType == SERVER_XEN_API:
828 server.xenapi.VM.destroy(dom)
829 else:
830 server.xend.domain.delete(dom)
832 def xm_suspend(args):
833 arg_check(args, "suspend", 1)
834 dom = args[0]
835 if serverType == SERVER_XEN_API:
836 server.xenapi.VM.suspend(get_single_vm(dom))
837 else:
838 server.xend.domain.suspend(dom)
840 def xm_resume(args):
841 arg_check(args, "resume", 1, 2)
843 try:
844 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
845 except getopt.GetoptError, opterr:
846 err(opterr)
847 sys.exit(1)
849 paused = False
850 for (k, v) in options:
851 if k in ['-p', '--paused']:
852 paused = True
854 if len(params) != 1:
855 err("Wrong number of parameters")
856 usage('resume')
857 sys.exit(1)
859 dom = params[0]
860 if serverType == SERVER_XEN_API:
861 server.xenapi.VM.resume(dom, paused)
862 else:
863 server.xend.domain.resume(dom, paused)
865 def xm_reboot(args):
866 arg_check(args, "reboot", 1, 3)
867 from xen.xm import shutdown
868 shutdown.main(["shutdown", "-R"] + args)
870 def xm_shutdown(args):
871 arg_check(args, "shutdown", 1, 4)
872 from xen.xm import shutdown
873 shutdown.main(["shutdown"] + args)
875 def xm_pause(args):
876 arg_check(args, "pause", 1)
877 dom = args[0]
879 server.xend.domain.pause(dom)
881 def xm_unpause(args):
882 arg_check(args, "unpause", 1)
883 dom = args[0]
885 server.xend.domain.unpause(dom)
887 def xm_dump_core(args):
888 live = False
889 crash = False
890 try:
891 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
892 for (k, v) in options:
893 if k in ('-L', '--live'):
894 live = True
895 if k in ('-C', '--crash'):
896 crash = True
898 if len(params) not in (1, 2):
899 raise OptionError("Expects 1 or 2 argument(s)")
900 except getopt.GetoptError, e:
901 raise OptionError(str(e))
903 dom = params[0]
904 if len(params) == 2:
905 filename = os.path.abspath(params[1])
906 else:
907 filename = None
909 if not live:
910 server.xend.domain.pause(dom)
912 try:
913 print "Dumping core of domain: %s ..." % str(dom)
914 server.xend.domain.dump(dom, filename, live, crash)
915 finally:
916 if not live:
917 server.xend.domain.unpause(dom)
919 if crash:
920 print "Destroying domain: %s ..." % str(dom)
921 server.xend.domain.destroy(dom)
923 def xm_rename(args):
924 arg_check(args, "rename", 2)
926 server.xend.domain.setName(args[0], args[1])
928 def xm_importcommand(command, args):
929 cmd = __import__(command, globals(), locals(), 'xen.xm')
930 cmd.main([command] + args)
933 #############################################################
935 def xm_vcpu_pin(args):
936 arg_check(args, "vcpu-pin", 3)
938 def cpu_make_map(cpulist):
939 cpus = []
940 for c in cpulist.split(','):
941 if c.find('-') != -1:
942 (x,y) = c.split('-')
943 for i in range(int(x),int(y)+1):
944 cpus.append(int(i))
945 else:
946 # remove this element from the list
947 if c[0] == '^':
948 cpus = [x for x in cpus if x != int(c[1:])]
949 else:
950 cpus.append(int(c))
951 cpus.sort()
952 return cpus
954 dom = args[0]
955 vcpu = args[1]
956 cpumap = cpu_make_map(args[2])
958 server.xend.domain.pincpu(dom, vcpu, cpumap)
960 def xm_mem_max(args):
961 arg_check(args, "mem-max", 2)
963 dom = args[0]
964 mem = int_unit(args[1], 'm')
966 server.xend.domain.maxmem_set(dom, mem)
968 def xm_mem_set(args):
969 arg_check(args, "mem-set", 2)
971 dom = args[0]
972 mem_target = int_unit(args[1], 'm')
974 server.xend.domain.setMemoryTarget(dom, mem_target)
976 def xm_vcpu_set(args):
977 arg_check(args, "vcpu-set", 2)
979 server.xend.domain.setVCpuCount(args[0], int(args[1]))
982 def xm_destroy(args):
983 arg_check(args, "destroy", 1)
984 server.xend.domain.destroy(args[0])
987 def xm_domid(args):
988 arg_check(args, "domid", 1)
990 name = args[0]
992 dom = server.xend.domain(name)
993 print sxp.child_value(dom, 'domid')
995 def xm_domname(args):
996 arg_check(args, "domname", 1)
998 name = args[0]
1000 dom = server.xend.domain(name)
1001 print sxp.child_value(dom, 'name')
1003 def xm_sched_sedf(args):
1004 def ns_to_ms(val):
1005 return float(val) * 0.000001
1007 def ms_to_ns(val):
1008 return (float(val) / 0.000001)
1010 def print_sedf(info):
1011 info['period'] = ns_to_ms(info['period'])
1012 info['slice'] = ns_to_ms(info['slice'])
1013 info['latency'] = ns_to_ms(info['latency'])
1014 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1015 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1017 def domid_match(domid, info):
1018 return domid is None or domid == info['name'] or \
1019 domid == str(info['domid'])
1021 # we want to just display current info if no parameters are passed
1022 if len(args) == 0:
1023 domid = None
1024 else:
1025 # we expect at least a domain id (name or number)
1026 # and at most a domid up to 5 options with values
1027 arg_check(args, "sched-sedf", 1, 11)
1028 domid = args[0]
1029 # drop domid from args since get_opt doesn't recognize it
1030 args = args[1:]
1032 opts = {}
1033 try:
1034 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1035 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1036 except getopt.GetoptError, opterr:
1037 err(opterr)
1038 sys.exit(1)
1040 # convert to nanoseconds if needed
1041 for (k, v) in options:
1042 if k in ['-p', '--period']:
1043 opts['period'] = ms_to_ns(v)
1044 elif k in ['-s', '--slice']:
1045 opts['slice'] = ms_to_ns(v)
1046 elif k in ['-l', '--latency']:
1047 opts['latency'] = ms_to_ns(v)
1048 elif k in ['-e', '--extratime']:
1049 opts['extratime'] = v
1050 elif k in ['-w', '--weight']:
1051 opts['weight'] = v
1053 doms = filter(lambda x : domid_match(domid, x),
1054 [parse_doms_info(dom)
1055 for dom in getDomains(None, 'running')])
1057 # print header if we aren't setting any parameters
1058 if len(opts.keys()) == 0:
1059 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1060 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1061 'Extra','Weight')
1063 for d in doms:
1064 # fetch current values so as not to clobber them
1065 try:
1066 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1067 except xmlrpclib.Fault:
1068 # domain does not support sched-sedf?
1069 sedf_raw = {}
1071 sedf_info = parse_sedf_info(sedf_raw)
1072 sedf_info['name'] = d['name']
1073 # update values in case of call to set
1074 if len(opts.keys()) > 0:
1075 for k in opts.keys():
1076 sedf_info[k]=opts[k]
1078 # send the update, converting user input
1079 v = map(int, [sedf_info['period'], sedf_info['slice'],
1080 sedf_info['latency'],sedf_info['extratime'],
1081 sedf_info['weight']])
1082 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1083 if int(rv) != 0:
1084 err("Failed to set sedf parameters (rv=%d)."%(rv))
1086 # not setting values, display info
1087 else:
1088 print_sedf(sedf_info)
1090 def xm_sched_credit(args):
1091 """Get/Set options for Credit Scheduler."""
1093 try:
1094 opts, params = getopt.getopt(args, "d:w:c:",
1095 ["domain=", "weight=", "cap="])
1096 except getopt.GetoptError, opterr:
1097 err(opterr)
1098 usage('sched-credit')
1099 sys.exit(1)
1101 domain = None
1102 weight = None
1103 cap = None
1105 for o, a in opts:
1106 if o == "-d":
1107 domain = a
1108 elif o == "-w":
1109 weight = int(a)
1110 elif o == "-c":
1111 cap = int(a);
1113 if domain is None:
1114 # place holder for system-wide scheduler parameters
1115 err("No domain given.")
1116 usage('sched-credit')
1117 sys.exit(1)
1119 if weight is None and cap is None:
1120 print server.xend.domain.sched_credit_get(domain)
1121 else:
1122 result = server.xend.domain.sched_credit_set(domain, weight, cap)
1123 if result != 0:
1124 err(str(result))
1126 def xm_info(args):
1127 arg_check(args, "info", 0)
1129 info = server.xend.node.info()
1131 for x in info[1:]:
1132 if len(x) < 2:
1133 print "%-23s: (none)" % x[0]
1134 else:
1135 print "%-23s:" % x[0], x[1]
1137 def xm_console(args):
1138 arg_check(args, "console", 1, 2)
1140 quiet = False;
1142 try:
1143 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1144 except getopt.GetoptError, opterr:
1145 err(opterr)
1146 sys.exit(1)
1148 for (k, v) in options:
1149 if k in ['-q', '--quiet']:
1150 quiet = True
1151 else:
1152 assert False
1154 if len(params) != 1:
1155 err('No domain given')
1156 usage('console')
1157 sys.exit(1)
1159 dom = params[0]
1161 try:
1162 info = server.xend.domain(dom)
1163 except:
1164 if quiet:
1165 sys.exit(1)
1166 else:
1167 raise
1168 domid = int(sxp.child_value(info, 'domid', '-1'))
1169 if domid == -1:
1170 if quiet:
1171 sys.exit(1)
1172 else:
1173 raise Exception("Domain is not started")
1175 console.execConsole(domid)
1178 def xm_uptime(args):
1179 short_mode = 0
1181 try:
1182 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1183 except getopt.GetoptError, opterr:
1184 err(opterr)
1185 sys.exit(1)
1187 for (k, v) in options:
1188 if k in ['-s', '--short']:
1189 short_mode = 1
1191 doms = getDomains(params, 'running')
1193 if short_mode == 0:
1194 print 'Name ID Uptime'
1196 for dom in doms:
1197 d = parse_doms_info(dom)
1198 if d['domid'] > 0:
1199 uptime = int(round(d['up_time']))
1200 else:
1201 f=open('/proc/uptime', 'r')
1202 upfile = f.read()
1203 uptime = int(round(float(upfile.split(' ')[0])))
1204 f.close()
1206 days = int(uptime / 86400)
1207 uptime -= (days * 86400)
1208 hours = int(uptime / 3600)
1209 uptime -= (hours * 3600)
1210 minutes = int(uptime / 60)
1211 uptime -= (minutes * 60)
1212 seconds = uptime
1214 upstring = ""
1215 if days > 0:
1216 upstring += str(days) + " day"
1217 if days > 1:
1218 upstring += "s"
1219 upstring += ", "
1220 upstring += '%(hours)2d:%(minutes)02d' % vars()
1222 if short_mode:
1223 now = datetime.datetime.now()
1224 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1225 upstring += ", " + d['name'] + " (" + str(d['domid']) + ")"
1226 else:
1227 upstring += ':%(seconds)02d' % vars()
1228 upstring = ("%(name)-32s %(domid)3d " % d) + upstring
1230 print upstring
1232 def xm_sysrq(args):
1233 arg_check(args, "sysrq", 2)
1234 dom = args[0]
1235 req = args[1]
1236 server.xend.domain.send_sysrq(dom, req)
1238 def xm_top(args):
1239 arg_check(args, "top", 0)
1241 os.execvp('xentop', ['xentop'])
1243 def xm_dmesg(args):
1244 arg_check(args, "dmesg", 0, 1)
1246 try:
1247 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1248 except getopt.GetoptError, opterr:
1249 err(opterr)
1250 sys.exit(1)
1252 use_clear = 0
1253 for (k, v) in options:
1254 if k in ['-c', '--clear']:
1255 use_clear = 1
1257 if len(params) :
1258 err("No parameter required")
1259 usage('dmesg')
1260 sys.exit(1)
1262 if not use_clear:
1263 print server.xend.node.dmesg.info()
1264 else:
1265 server.xend.node.dmesg.clear()
1267 def xm_log(args):
1268 arg_check(args, "log", 0)
1270 print server.xend.node.log()
1272 def xm_serve(args):
1273 arg_check(args, "serve", 0)
1275 from fcntl import fcntl, F_SETFL
1277 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1278 s.connect(XendClient.XML_RPC_SOCKET)
1279 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1281 while True:
1282 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1283 if s in iwtd:
1284 data = s.recv(4096)
1285 if len(data) > 0:
1286 sys.stdout.write(data)
1287 sys.stdout.flush()
1288 else:
1289 break
1290 if sys.stdin in iwtd:
1291 data = sys.stdin.read(4096)
1292 if len(data) > 0:
1293 s.sendall(data)
1294 else:
1295 break
1296 s.close()
1298 def parse_dev_info(info):
1299 def get_info(n, t, d):
1300 i = 0
1301 while i < len(info):
1302 if (info[i][0] == n):
1303 return t(info[i][1])
1304 i = i + 1
1305 return t(d)
1306 return {
1307 #common
1308 'backend-id' : get_info('backend-id', int, -1),
1309 'handle' : get_info('handle', int, 0),
1310 'state' : get_info('state', int, -1),
1311 'be-path' : get_info('backend', str, '??'),
1312 'event-ch' : get_info('event-channel',int, -1),
1313 #network specific
1314 'virtual-device' : get_info('virtual-device', str, '??'),
1315 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1316 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1317 'mac' : get_info('mac', str, '??'),
1318 #block-device specific
1319 'ring-ref' : get_info('ring-ref', int, -1),
1322 def arg_check_for_resource_list(args, name):
1323 use_long = 0
1324 try:
1325 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1326 except getopt.GetoptError, opterr:
1327 err(opterr)
1328 sys.exit(1)
1330 for (k, v) in options:
1331 if k in ['-l', '--long']:
1332 use_long = 1
1334 if len(params) == 0:
1335 print 'No domain parameter given'
1336 usage(name)
1337 if len(params) > 1:
1338 print 'No multiple domain parameters allowed'
1339 usage(name)
1341 return (use_long, params)
1343 def xm_network_list(args):
1344 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1346 dom = params[0]
1347 if use_long:
1348 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1349 map(PrettyPrint.prettyprint, devs)
1350 else:
1351 hdr = 0
1352 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
1353 if hdr == 0:
1354 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1355 hdr = 1
1356 ni = parse_dev_info(x[1])
1357 ni['idx'] = int(x[0])
1358 print ("%(idx)-3d "
1359 "%(backend-id)-3d"
1360 "%(mac)-17s "
1361 "%(handle)-3d "
1362 "%(state)-3d "
1363 "%(event-ch)-3d "
1364 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1365 "%(be-path)-30s "
1366 % ni)
1368 def xm_block_list(args):
1369 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1371 dom = params[0]
1372 if use_long:
1373 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1374 map(PrettyPrint.prettyprint, devs)
1375 else:
1376 hdr = 0
1377 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
1378 if hdr == 0:
1379 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1380 hdr = 1
1381 ni = parse_dev_info(x[1])
1382 ni['idx'] = int(x[0])
1383 print ("%(idx)-3d "
1384 "%(backend-id)-3d "
1385 "%(handle)-3d "
1386 "%(state)-3d "
1387 "%(event-ch)-3d "
1388 "%(ring-ref)-5d "
1389 "%(be-path)-30s "
1390 % ni)
1392 def xm_vtpm_list(args):
1393 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1395 dom = params[0]
1396 if use_long:
1397 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1398 map(PrettyPrint.prettyprint, devs)
1399 else:
1400 hdr = 0
1401 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1402 if hdr == 0:
1403 print 'Idx BE handle state evt-ch ring-ref BE-path'
1404 hdr = 1
1405 ni = parse_dev_info(x[1])
1406 ni['idx'] = int(x[0])
1407 print ("%(idx)-3d "
1408 "%(backend-id)-3d "
1409 "%(handle)-3d "
1410 "%(state)-3d "
1411 "%(event-ch)-3d "
1412 "%(ring-ref)-5d "
1413 "%(be-path)-30s "
1414 % ni)
1417 def parse_block_configuration(args):
1418 dom = args[0]
1420 if args[1].startswith('tap:'):
1421 cls = 'tap'
1422 else:
1423 cls = 'vbd'
1425 vbd = [cls,
1426 ['uname', args[1]],
1427 ['dev', args[2]],
1428 ['mode', args[3]]]
1429 if len(args) == 5:
1430 vbd.append(['backend', args[4]])
1432 # verify that policy permits attaching this resource
1433 if security.on():
1434 dominfo = server.xend.domain(dom)
1435 label = security.get_security_printlabel(dominfo)
1436 else:
1437 label = None
1438 security.res_security_check(args[1], label)
1440 return (dom, vbd)
1443 def xm_block_attach(args):
1444 arg_check(args, 'block-attach', 4, 5)
1446 (dom, vbd) = parse_block_configuration(args)
1447 server.xend.domain.device_create(dom, vbd)
1450 def xm_block_configure(args):
1451 arg_check(args, 'block-configure', 4, 5)
1453 (dom, vbd) = parse_block_configuration(args)
1454 server.xend.domain.device_configure(dom, vbd)
1457 def xm_network_attach(args):
1458 arg_check(args, 'network-attach', 1, 10000)
1460 dom = args[0]
1461 vif = ['vif']
1463 for a in args[1:]:
1464 vif.append(a.split("="))
1466 server.xend.domain.device_create(dom, vif)
1469 def detach(args, command, deviceClass):
1470 arg_check(args, command, 2)
1472 dom = args[0]
1473 dev = args[1]
1475 server.xend.domain.destroyDevice(dom, deviceClass, dev)
1478 def xm_block_detach(args):
1479 detach(args, 'block-detach', 'vbd')
1482 def xm_network_detach(args):
1483 detach(args, 'network-detach', 'vif')
1486 def xm_vnet_list(args):
1487 try:
1488 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1489 except getopt.GetoptError, opterr:
1490 err(opterr)
1491 sys.exit(1)
1493 use_long = 0
1494 for (k, v) in options:
1495 if k in ['-l', '--long']:
1496 use_long = 1
1498 if params:
1499 use_long = 1
1500 vnets = params
1501 else:
1502 vnets = server.xend_vnets()
1504 for vnet in vnets:
1505 try:
1506 if use_long:
1507 info = server.xend_vnet(vnet)
1508 PrettyPrint.prettyprint(info)
1509 else:
1510 print vnet
1511 except Exception, ex:
1512 print vnet, ex
1514 def xm_vnet_create(args):
1515 arg_check(args, "vnet-create", 1)
1516 conf = args[0]
1517 if not os.access(conf, os.R_OK):
1518 print "File not found: %s" % conf
1519 sys.exit(1)
1521 server.xend_vnet_create(conf)
1523 def xm_vnet_delete(args):
1524 arg_check(args, "vnet-delete", 1)
1525 vnet = args[0]
1526 server.xend_vnet_delete(vnet)
1528 commands = {
1529 # console commands
1530 "console": xm_console,
1531 # xenstat commands
1532 "top": xm_top,
1533 # domain commands
1534 "delete": xm_delete,
1535 "destroy": xm_destroy,
1536 "domid": xm_domid,
1537 "domname": xm_domname,
1538 "dump-core": xm_dump_core,
1539 "reboot": xm_reboot,
1540 "rename": xm_rename,
1541 "restore": xm_restore,
1542 "resume": xm_resume,
1543 "save": xm_save,
1544 "shutdown": xm_shutdown,
1545 "start": xm_start,
1546 "sysrq": xm_sysrq,
1547 "uptime": xm_uptime,
1548 "suspend": xm_suspend,
1549 "list": xm_list,
1550 # memory commands
1551 "mem-max": xm_mem_max,
1552 "mem-set": xm_mem_set,
1553 # cpu commands
1554 "vcpu-pin": xm_vcpu_pin,
1555 "vcpu-list": xm_vcpu_list,
1556 "vcpu-set": xm_vcpu_set,
1557 # special
1558 "pause": xm_pause,
1559 "unpause": xm_unpause,
1560 # host commands
1561 "dmesg": xm_dmesg,
1562 "info": xm_info,
1563 "log": xm_log,
1564 "serve": xm_serve,
1565 # scheduler
1566 "sched-sedf": xm_sched_sedf,
1567 "sched-credit": xm_sched_credit,
1568 # block
1569 "block-attach": xm_block_attach,
1570 "block-detach": xm_block_detach,
1571 "block-list": xm_block_list,
1572 "block-configure": xm_block_configure,
1573 # network
1574 "network-attach": xm_network_attach,
1575 "network-detach": xm_network_detach,
1576 "network-list": xm_network_list,
1577 # vnet
1578 "vnet-list": xm_vnet_list,
1579 "vnet-create": xm_vnet_create,
1580 "vnet-delete": xm_vnet_delete,
1581 # vtpm
1582 "vtpm-list": xm_vtpm_list,
1585 ## The commands supported by a separate argument parser in xend.xm.
1586 IMPORTED_COMMANDS = [
1587 'create',
1588 'new',
1589 'migrate',
1590 'labels',
1591 'cfgbootpolicy',
1592 'makepolicy',
1593 'loadpolicy',
1594 'dumppolicy',
1595 'addlabel',
1596 'rmlabel',
1597 'getlabel',
1598 'dry-run',
1599 'resources',
1602 for c in IMPORTED_COMMANDS:
1603 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
1605 aliases = {
1606 "balloon": "mem-set",
1607 "set-vcpus": "vcpu-set",
1608 "vif-list": "network-list",
1609 "vbd-create": "block-attach",
1610 "vbd-destroy": "block-detach",
1611 "vbd-list": "block-list",
1615 def xm_lookup_cmd(cmd):
1616 if commands.has_key(cmd):
1617 return commands[cmd]
1618 elif aliases.has_key(cmd):
1619 deprecated(cmd,aliases[cmd])
1620 return commands[aliases[cmd]]
1621 elif cmd == 'help':
1622 longHelp()
1623 sys.exit(0)
1624 else:
1625 # simulate getopt's prefix matching behaviour
1626 if len(cmd) > 1:
1627 same_prefix_cmds = [commands[c] for c in commands.keys() \
1628 if c[:len(cmd)] == cmd]
1629 # only execute if there is only 1 match
1630 if len(same_prefix_cmds) == 1:
1631 return same_prefix_cmds[0]
1633 err('Sub Command %s not found!' % cmd)
1634 usage()
1636 def deprecated(old,new):
1637 print >>sys.stderr, (
1638 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1640 def main(argv=sys.argv):
1641 global server
1643 if len(argv) < 2:
1644 usage()
1646 # intercept --help(-h) and output our own help
1647 for help in ['--help', '-h']:
1648 if help in argv[1:]:
1649 if help == argv[1]:
1650 longHelp()
1651 else:
1652 usage(argv[1])
1653 sys.exit(0)
1655 cmd = xm_lookup_cmd(argv[1])
1657 # strip off prog name and subcmd
1658 args = argv[2:]
1659 if cmd:
1660 try:
1661 if serverType == SERVER_XEN_API:
1662 server = XenAPI.Session(serverURI)
1663 username, password = parseAuthentication()
1664 server.login_with_password(username, password)
1665 def logout():
1666 try:
1667 server.xenapi.session.logout()
1668 except:
1669 pass
1670 atexit.register(logout)
1671 else:
1672 server = ServerProxy(serverURI)
1674 rc = cmd(args)
1675 if rc:
1676 usage()
1677 except socket.error, ex:
1678 if os.geteuid() != 0:
1679 err("Most commands need root access. Please try again as root.")
1680 else:
1681 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
1682 sys.exit(1)
1683 except KeyboardInterrupt:
1684 print "Interrupted."
1685 sys.exit(1)
1686 except IOError, ex:
1687 if os.geteuid() != 0:
1688 err("Most commands need root access. Please try again as root.")
1689 else:
1690 err("Unable to connect to xend: %s." % ex[1])
1691 sys.exit(1)
1692 except SystemExit:
1693 sys.exit(1)
1694 except XenAPI.Failure, exn:
1695 err(str(exn))
1696 sys.exit(1)
1697 except xmlrpclib.Fault, ex:
1698 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
1699 err("Domain '%s' does not exist." % ex.faultString)
1700 else:
1701 err(ex.faultString)
1702 usage(argv[1])
1703 sys.exit(1)
1704 except xmlrpclib.ProtocolError, ex:
1705 if ex.errcode == -1:
1706 print >>sys.stderr, (
1707 "Xend has probably crashed! Invalid or missing HTTP "
1708 "status code.")
1709 else:
1710 print >>sys.stderr, (
1711 "Xend has probably crashed! ProtocolError(%d, %s)." %
1712 (ex.errcode, ex.errmsg))
1713 sys.exit(1)
1714 except (ValueError, OverflowError):
1715 err("Invalid argument.")
1716 usage(argv[1])
1717 sys.exit(1)
1718 except OptionError, e:
1719 err(str(e))
1720 usage(argv[1])
1721 print e.usage()
1722 sys.exit(1)
1723 except security.ACMError, e:
1724 err(str(e))
1725 sys.exit(1)
1726 except:
1727 print "Unexpected error:", sys.exc_info()[0]
1728 print
1729 print "Please report to xen-devel@lists.xensource.com"
1730 raise
1732 else:
1733 usage()
1735 if __name__ == "__main__":
1736 main()