ia64/xen-unstable

view tools/python/xen/xm/main.py @ 13213:b175c2f19e0a

Format Xen-API error messages nicely.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Dec 28 15:52:31 2006 +0000 (2006-12-28)
parents 777bbae06fdb
children 69579f9f1c81
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 shlex
29 import sys
30 import re
31 import getopt
32 import socket
33 import traceback
34 import xmlrpclib
35 import traceback
36 import time
37 import datetime
38 from select import select
39 import xml.dom.minidom
41 import warnings
42 warnings.filterwarnings('ignore', category=FutureWarning)
44 from xen.xend import PrettyPrint
45 from xen.xend import sxp
46 from xen.xend import XendClient
47 from xen.xend.XendConstants import *
49 from xen.xm.opts import OptionError, Opts, wrap, set_true
50 from xen.xm import console
51 from xen.util import security
52 from xen.util.xmlrpclib2 import ServerProxy
54 import XenAPI
56 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
57 # getopt.getopt if gnu_getopt is not available. This will mean that options
58 # may only be specified before positional arguments.
59 if not hasattr(getopt, 'gnu_getopt'):
60 getopt.gnu_getopt = getopt.getopt
62 XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
64 # Supported types of server
65 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
66 SERVER_XEN_API = 'Xen-API'
68 # General help message
70 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
71 "Control, list, and manipulate Xen guest instances.\n"
73 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
74 'For more help on \'xm\' see the xm(1) man page.\n' \
75 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
76 ' man page.\n'
78 # Help strings are indexed by subcommand name in this way:
79 # 'subcommand': (argstring, description)
81 SUBCOMMAND_HELP = {
82 # common commands
84 'shell' : ('', 'Launch an interactive shell.'),
86 'console' : ('[-q|--quiet] <Domain>',
87 'Attach to <Domain>\'s console.'),
88 'create' : ('<ConfigFile> [options] [vars]',
89 'Create a domain based on <ConfigFile>.'),
90 'destroy' : ('<Domain>',
91 'Terminate a domain immediately.'),
92 'help' : ('', 'Display this message.'),
93 'list' : ('[options] [Domain, ...]',
94 'List information about all/some domains.'),
95 'mem-max' : ('<Domain> <Mem>',
96 'Set the maximum amount reservation for a domain.'),
97 'mem-set' : ('<Domain> <Mem>',
98 'Set the current memory usage for a domain.'),
99 'migrate' : ('<Domain> <Host>',
100 'Migrate a domain to another machine.'),
101 'pause' : ('<Domain>', 'Pause execution of a domain.'),
102 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
103 'restore' : ('<CheckpointFile> [-p]',
104 'Restore a domain from a saved state.'),
105 'save' : ('<Domain> <CheckpointFile>',
106 'Save a domain state to restore later.'),
107 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
108 'top' : ('', 'Monitor a host and the domains in real time.'),
109 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
110 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
112 # Life cycle xm commands
113 'new' : ('<ConfigFile> [options] [vars]',
114 'Adds a domain to Xend domain management'),
115 'delete' : ('<DomainName>',
116 'Remove a domain from Xend domain management.'),
117 'start' : ('<DomainName>', 'Start a Xend managed domain'),
118 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
119 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
121 # less used commands
123 'dmesg' : ('[-c|--clear]',
124 'Read and/or clear Xend\'s message buffer.'),
125 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
126 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
127 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
128 'Dump core for a specific domain.'),
129 'info' : ('', 'Get information about Xen host.'),
130 'log' : ('', 'Print Xend log'),
131 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
132 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
133 'sched-credit': ('-d <Domain> [-w[=WEIGHT]|-c[=CAP]]',
134 'Get/set credit scheduler parameters.'),
135 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
136 'vcpu-list' : ('[<Domain>]',
137 'List the VCPUs for a domain or all domains.'),
138 'vcpu-pin' : ('<Domain> <VCPU> <CPUs>',
139 'Set which CPUs a VCPU can use.'),
140 'vcpu-set' : ('<Domain> <vCPUs>',
141 'Set the number of active VCPUs for allowed for the'
142 ' domain.'),
144 # device commands
146 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
147 'Create a new virtual block device.'),
148 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
149 'Change block device configuration'),
150 'block-detach' : ('<Domain> <DevId> [-f|--force]',
151 'Destroy a domain\'s virtual block device.'),
152 'block-list' : ('<Domain> [--long]',
153 'List virtual block devices for a domain.'),
154 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
155 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
156 '[vifname=<name>]',
157 'Create a new virtual network device.'),
158 'network-detach': ('<Domain> <DevId> [-f|--force]',
159 'Destroy a domain\'s virtual network device.'),
160 'network-list' : ('<Domain> [--long]',
161 'List virtual network interfaces for a domain.'),
162 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
163 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
164 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
165 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
167 # security
169 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
170 'Add security label to domain.'),
171 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
172 'Remove a security label from domain.'),
173 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
174 'Show security label for domain or resource.'),
175 'dry-run' : ('<ConfigFile>',
176 'Test if a domain can access its resources.'),
177 'resources' : ('', 'Show info for each labeled resource.'),
178 'cfgbootpolicy' : ('<policy> [boot-title]',
179 'Add policy to boot configuration.'),
180 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
181 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
182 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
183 'files.'),
184 'labels' : ('[policy] [type=dom|res|any]',
185 'List <type> labels for (active) policy.'),
186 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
187 }
189 SUBCOMMAND_OPTIONS = {
190 'sched-sedf': (
191 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
192 ('-s [MS]', '--slice[=MS]' ,
193 'Worst-case execution time(ms). (slice < period)'),
194 ('-l [MS]', '--latency[=MS]',
195 'Scaled period (ms) when domain performs heavy I/O'),
196 ('-e [FLAG]', '--extra[=FLAG]',
197 'Flag (0 or 1) controls if domain can run in extra time.'),
198 ('-w [FLOAT]', '--weight[=FLOAT]',
199 'CPU Period/slice (do not set with --period/--slice)'),
200 ),
201 'sched-credit': (
202 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
203 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
204 ('-c CAP', '--cap=CAP', 'Cap (int)'),
205 ),
206 'list': (
207 ('-l', '--long', 'Output all VM details in SXP'),
208 ('', '--label', 'Include security labels'),
209 ('', '--state=<state>', 'Select only VMs with the specified state'),
210 ),
211 'console': (
212 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
213 ),
214 'dmesg': (
215 ('-c', '--clear', 'Clear dmesg buffer'),
216 ),
217 'vnet-list': (
218 ('-l', '--long', 'List Vnets as SXP'),
219 ),
220 'network-list': (
221 ('-l', '--long', 'List resources as SXP'),
222 ),
223 'dump-core': (
224 ('-L', '--live', 'Dump core without pausing the domain'),
225 ('-C', '--crash', 'Crash domain after dumping core'),
226 ),
227 'start': (
228 ('-p', '--paused', 'Do not unpause domain after starting it'),
229 ),
230 'resume': (
231 ('-p', '--paused', 'Do not unpause domain after resuming it'),
232 ),
233 'restore': (
234 ('-p', '--paused', 'Do not unpause domain after restoring it'),
235 ),
236 }
238 common_commands = [
239 "console",
240 "create",
241 "new",
242 "delete",
243 "destroy",
244 "dump-core",
245 "help",
246 "list",
247 "mem-set",
248 "migrate",
249 "pause",
250 "reboot",
251 "restore",
252 "resume",
253 "save",
254 "shell",
255 "shutdown",
256 "start",
257 "suspend",
258 "top",
259 "unpause",
260 "uptime",
261 "vcpu-set",
262 ]
264 domain_commands = [
265 "console",
266 "create",
267 "new",
268 "delete",
269 "destroy",
270 "domid",
271 "domname",
272 "dump-core",
273 "list",
274 "mem-max",
275 "mem-set",
276 "migrate",
277 "pause",
278 "reboot",
279 "rename",
280 "restore",
281 "resume",
282 "save",
283 "shutdown",
284 "start",
285 "suspend",
286 "sysrq",
287 "top",
288 "unpause",
289 "uptime",
290 "vcpu-list",
291 "vcpu-pin",
292 "vcpu-set",
293 ]
295 host_commands = [
296 "dmesg",
297 "info",
298 "log",
299 "serve",
300 ]
302 scheduler_commands = [
303 "sched-credit",
304 "sched-sedf",
305 ]
307 device_commands = [
308 "block-attach",
309 "block-detach",
310 "block-list",
311 "block-configure",
312 "network-attach",
313 "network-detach",
314 "network-list",
315 "vtpm-list",
316 ]
318 vnet_commands = [
319 "vnet-list",
320 "vnet-create",
321 "vnet-delete",
322 ]
324 acm_commands = [
325 "labels",
326 "addlabel",
327 "rmlabel",
328 "getlabel",
329 "dry-run",
330 "resources",
331 "makepolicy",
332 "loadpolicy",
333 "cfgbootpolicy",
334 "dumppolicy",
335 ]
337 all_commands = (domain_commands + host_commands + scheduler_commands +
338 device_commands + vnet_commands + acm_commands + ['shell'])
341 ##
342 # Configuration File Parsing
343 ##
345 config = None
346 if os.path.isfile(XM_CONFIG_FILE):
347 try:
348 config = xml.dom.minidom.parse(XM_CONFIG_FILE)
349 except:
350 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
351 XM_CONFIG_FILE)
353 def parseServer():
354 if config:
355 server = config.getElementsByTagName('server')
356 if server:
357 st = server[0].getAttribute('type')
358 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
359 print >>sys.stderr, ('Invalid server type %s; using %s.' %
360 (st, SERVER_LEGACY_XMLRPC))
361 st = SERVER_LEGACY_XMLRPC
362 return (st, server[0].getAttribute('uri'))
364 return SERVER_LEGACY_XMLRPC, XendClient.uri
366 def parseAuthentication():
367 server = config.getElementsByTagName('server')[0]
368 return (server.getAttribute('username'),
369 server.getAttribute('password'))
371 serverType, serverURI = parseServer()
372 server = None
375 ####################################################################
376 #
377 # Help/usage printing functions
378 #
379 ####################################################################
381 def cmdHelp(cmd):
382 """Print help for a specific subcommand."""
384 for fc in SUBCOMMAND_HELP.keys():
385 if fc[:len(cmd)] == cmd:
386 cmd = fc
387 break
389 try:
390 args, desc = SUBCOMMAND_HELP[cmd]
391 except KeyError:
392 shortHelp()
393 return
395 print 'Usage: xm %s %s' % (cmd, args)
396 print
397 print desc
399 try:
400 # If options help message is defined, print this.
401 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
402 if shortopt and longopt:
403 optdesc = '%s, %s' % (shortopt, longopt)
404 elif shortopt:
405 optdesc = shortopt
406 elif longopt:
407 optdesc = longopt
409 wrapped_desc = wrap(desc, 43)
410 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
411 for line in wrapped_desc[1:]:
412 print ' ' * 33 + line
413 print
414 except KeyError:
415 # if the command is an external module, we grab usage help
416 # from the module itself.
417 if cmd in IMPORTED_COMMANDS:
418 try:
419 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
420 cmd_usage = getattr(cmd_module, "help", None)
421 if cmd_usage:
422 print cmd_usage()
423 except ImportError:
424 pass
426 def shortHelp():
427 """Print out generic help when xm is called without subcommand."""
429 print USAGE_HELP
430 print 'Common \'xm\' commands:\n'
432 for command in common_commands:
433 try:
434 args, desc = SUBCOMMAND_HELP[command]
435 except KeyError:
436 continue
437 wrapped_desc = wrap(desc, 50)
438 print ' %-20s %-50s' % (command, wrapped_desc[0])
439 for line in wrapped_desc[1:]:
440 print ' ' * 22 + line
442 print
443 print USAGE_FOOTER
444 print 'For a complete list of subcommands run \'xm help\'.'
446 def longHelp():
447 """Print out full help when xm is called with xm --help or xm help"""
449 print USAGE_HELP
450 print 'xm full list of subcommands:\n'
452 for command in all_commands:
453 try:
454 args, desc = SUBCOMMAND_HELP[command]
455 except KeyError:
456 continue
458 wrapped_desc = wrap(desc, 50)
459 print ' %-20s %-50s' % (command, wrapped_desc[0])
460 for line in wrapped_desc[1:]:
461 print ' ' * 22 + line
463 print
464 print USAGE_FOOTER
466 def _usage(cmd):
467 """ Print help usage information """
468 if cmd:
469 cmdHelp(cmd)
470 else:
471 shortHelp()
473 def usage(cmd = None):
474 """ Print help usage information and exits """
475 _usage(cmd)
476 sys.exit(1)
479 ####################################################################
480 #
481 # Utility functions
482 #
483 ####################################################################
485 def arg_check(args, name, lo, hi = -1):
486 n = len([i for i in args if i != '--'])
488 if hi == -1:
489 if n != lo:
490 err("'xm %s' requires %d argument%s.\n" % (name, lo,
491 lo == 1 and '' or 's'))
492 usage(name)
493 else:
494 if n < lo or n > hi:
495 err("'xm %s' requires between %d and %d arguments.\n" %
496 (name, lo, hi))
497 usage(name)
500 def unit(c):
501 if not c.isalpha():
502 return 0
503 base = 1
504 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
505 elif c == 'M' or c == 'm': base = 1024 * 1024
506 elif c == 'K' or c == 'k': base = 1024
507 else:
508 print 'ignoring unknown unit'
509 return base
511 def int_unit(str, dest):
512 base = unit(str[-1])
513 if not base:
514 return int(str)
516 value = int(str[:-1])
517 dst_base = unit(dest)
518 if dst_base == 0:
519 dst_base = 1
520 if dst_base > base:
521 return value / (dst_base / base)
522 else:
523 return value * (base / dst_base)
525 def err(msg):
526 print >>sys.stderr, "Error:", msg
529 def get_single_vm(dom):
530 uuids = server.xenapi.VM.get_by_name_label(dom)
531 n = len(uuids)
532 if n == 1:
533 return uuids[0]
534 else:
535 dominfo = server.xend.domain(dom, False)
536 return dominfo['uuid']
538 ##
539 #
540 # Xen-API Shell
541 #
542 ##
544 class Shell(cmd.Cmd):
545 def __init__(self):
546 cmd.Cmd.__init__(self)
547 self.prompt = "xm> "
549 def default(self, line):
550 words = shlex.split(line)
551 if len(words) > 0 and words[0] == 'xm':
552 words = words[1:]
553 if len(words) > 0:
554 cmd = xm_lookup_cmd(words[0])
555 if cmd:
556 _run_cmd(cmd, words[0], words[1:])
557 elif serverType == SERVER_XEN_API:
558 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
559 tuple(x)),
560 words[0], words[1:])
561 if ok and res is not None and res != '':
562 pprint.pprint(res)
563 else:
564 print '*** Unknown command: %s' % words[0]
565 return False
567 def emptyline(self):
568 pass
570 def do_EOF(self, line):
571 print
572 sys.exit(0)
574 def do_help(self, line):
575 _usage(line)
578 def xm_shell(args):
579 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
582 #########################################################################
583 #
584 # Main xm functions
585 #
586 #########################################################################
588 def xm_save(args):
589 arg_check(args, "save", 2)
591 try:
592 dominfo = parse_doms_info(server.xend.domain(args[0]))
593 except xmlrpclib.Fault, ex:
594 raise ex
596 domid = dominfo['domid']
597 savefile = os.path.abspath(args[1])
599 if not os.access(os.path.dirname(savefile), os.W_OK):
600 err("xm save: Unable to create file %s" % savefile)
601 sys.exit(1)
603 server.xend.domain.save(domid, savefile)
605 def xm_restore(args):
606 arg_check(args, "restore", 1, 2)
608 try:
609 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
610 except getopt.GetoptError, opterr:
611 err(opterr)
612 usage('restore')
614 paused = False
615 for (k, v) in options:
616 if k in ['-p', '--paused']:
617 paused = True
619 if len(params) != 1:
620 err("Wrong number of parameters")
621 usage('restore')
623 savefile = os.path.abspath(params[0])
625 if not os.access(savefile, os.R_OK):
626 err("xm restore: Unable to read file %s" % savefile)
627 sys.exit(1)
629 server.xend.domain.restore(savefile, paused)
632 def getDomains(domain_names, state, full = 0):
633 if domain_names:
634 return [server.xend.domain(dom, full) for dom in domain_names]
635 else:
636 return server.xend.domains_with_state(True, state, full)
639 def xm_list(args):
640 use_long = 0
641 show_vcpus = 0
642 show_labels = 0
643 state = 'all'
644 try:
645 (options, params) = getopt.gnu_getopt(args, 'lv',
646 ['long','vcpus','label',
647 'state='])
648 except getopt.GetoptError, opterr:
649 err(opterr)
650 usage('list')
652 for (k, v) in options:
653 if k in ['-l', '--long']:
654 use_long = 1
655 if k in ['-v', '--vcpus']:
656 show_vcpus = 1
657 if k in ['--label']:
658 show_labels = 1
659 if k in ['--state']:
660 state = v
662 if state != 'all' and len(params) > 0:
663 raise OptionError(
664 "You may specify either a state or a particular VM, but not both")
666 if show_vcpus:
667 print >>sys.stderr, (
668 "xm list -v is deprecated. Please use xm vcpu-list.")
669 xm_vcpu_list(params)
670 return
672 doms = getDomains(params, state, use_long)
674 if use_long:
675 map(PrettyPrint.prettyprint, doms)
676 elif show_labels:
677 xm_label_list(doms)
678 else:
679 xm_brief_list(doms)
682 def parse_doms_info(info):
683 def get_info(n, t, d):
684 return t(sxp.child_value(info, n, d))
686 def get_status(n, t, d):
687 return DOM_STATES[t(sxp.child_value(info, n, d))]
689 start_time = get_info('start_time', float, -1)
690 if start_time == -1:
691 up_time = float(-1)
692 else:
693 up_time = time.time() - start_time
695 return {
696 'domid' : get_info('domid', str, ''),
697 'name' : get_info('name', str, '??'),
698 'mem' : get_info('memory_dynamic_min', int, 0),
699 'vcpus' : get_info('online_vcpus', int, 0),
700 'state' : get_info('state', str, ''),
701 'cpu_time' : get_info('cpu_time', float, 0),
702 'up_time' : up_time,
703 'seclabel' : security.get_security_printlabel(info),
704 }
707 def parse_sedf_info(info):
708 def get_info(n, t, d):
709 return t(sxp.child_value(info, n, d))
711 return {
712 'domid' : get_info('domid', int, -1),
713 'period' : get_info('period', int, -1),
714 'slice' : get_info('slice', int, -1),
715 'latency' : get_info('latency', int, -1),
716 'extratime': get_info('extratime', int, -1),
717 'weight' : get_info('weight', int, -1),
718 }
720 def xm_brief_list(doms):
721 print '%-40s %3s %5s %5s %10s %9s' % \
722 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
724 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
725 "%(cpu_time)8.1f"
727 for dom in doms:
728 d = parse_doms_info(dom)
729 print format % d
731 def xm_label_list(doms):
732 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
733 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
735 output = []
736 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
737 '%(cpu_time)8.1f %(seclabel)9s'
739 for dom in doms:
740 d = parse_doms_info(dom)
741 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
742 if not d['seclabel']:
743 d['seclabel'] = 'ERROR'
744 elif security.active_policy in ['DEFAULT']:
745 d['seclabel'] = 'DEFAULT'
746 else:
747 d['seclabel'] = 'INACTIVE'
748 output.append((format % d, d['seclabel']))
750 #sort by labels
751 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
752 for line, label in output:
753 print line
756 def xm_vcpu_list(args):
758 if args:
759 dominfo = map(server.xend.domain.getVCPUInfo, args)
760 else:
761 doms = server.xend.domains(False)
762 dominfo = map(server.xend.domain.getVCPUInfo, doms)
764 print '%-32s %3s %5s %5s %5s %9s %s' % \
765 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
767 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
768 ' %(cpu_time)8.1f %(cpumap)s'
770 for dom in dominfo:
771 def get_info(n):
772 return sxp.child_value(dom, n)
774 #
775 # convert a list of integers into a list of pairs indicating
776 # continuous sequences in the list:
777 #
778 # [0,1,2,3] -> [(0,3)]
779 # [1,2,4,5] -> [(1,2),(4,5)]
780 # [0] -> [(0,0)]
781 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
782 #
783 def list_to_rangepairs(cmap):
784 cmap.sort()
785 pairs = []
786 x = y = 0
787 for i in range(0,len(cmap)):
788 try:
789 if ((cmap[y+1] - cmap[i]) > 1):
790 pairs.append((cmap[x],cmap[y]))
791 x = y = i+1
792 else:
793 y = y + 1
794 # if we go off the end, then just add x to y
795 except IndexError:
796 pairs.append((cmap[x],cmap[y]))
798 return pairs
800 #
801 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
802 #
803 def format_pairs(pairs):
804 if not pairs:
805 return "no cpus"
806 out = ""
807 for f,s in pairs:
808 if (f==s):
809 out += '%d'%f
810 else:
811 out += '%d-%d'%(f,s)
812 out += ','
813 # trim trailing ','
814 return out[:-1]
816 def format_cpumap(cpumap):
817 cpumap = map(lambda x: int(x), cpumap)
818 cpumap.sort()
820 for x in server.xend.node.info()[1:]:
821 if len(x) > 1 and x[0] == 'nr_cpus':
822 nr_cpus = int(x[1])
823 # normalize cpumap by modulus nr_cpus, and drop duplicates
824 cpumap = dict.fromkeys(
825 map(lambda x: x % nr_cpus, cpumap)).keys()
826 if len(cpumap) == nr_cpus:
827 return "any cpu"
828 break
830 return format_pairs(list_to_rangepairs(cpumap))
832 name = get_info('name')
833 domid = int(get_info('domid'))
835 for vcpu in sxp.children(dom, 'vcpu'):
836 def vinfo(n, t):
837 return t(sxp.child_value(vcpu, n))
839 number = vinfo('number', int)
840 cpu = vinfo('cpu', int)
841 cpumap = format_cpumap(vinfo('cpumap', list))
842 online = vinfo('online', int)
843 cpu_time = vinfo('cpu_time', float)
844 running = vinfo('running', int)
845 blocked = vinfo('blocked', int)
847 if online:
848 c = str(cpu)
849 if running:
850 s = 'r'
851 else:
852 s = '-'
853 if blocked:
854 s += 'b'
855 else:
856 s += '-'
857 s += '-'
858 else:
859 c = "-"
860 s = "--p"
862 print format % locals()
864 def xm_start(args):
865 arg_check(args, "start", 1, 2)
867 try:
868 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
869 except getopt.GetoptError, opterr:
870 err(opterr)
871 usage('start')
873 paused = False
874 for (k, v) in options:
875 if k in ['-p', '--paused']:
876 paused = True
878 if len(params) != 1:
879 err("Wrong number of parameters")
880 usage('start')
882 dom = params[0]
883 if serverType == SERVER_XEN_API:
884 server.xenapi.VM.start(get_single_vm(dom), paused)
885 else:
886 server.xend.domain.start(dom, paused)
888 def xm_delete(args):
889 arg_check(args, "delete", 1)
890 dom = args[0]
891 if serverType == SERVER_XEN_API:
892 server.xenapi.VM.destroy(get_single_vm(dom))
893 else:
894 server.xend.domain.delete(dom)
896 def xm_suspend(args):
897 arg_check(args, "suspend", 1)
898 dom = args[0]
899 if serverType == SERVER_XEN_API:
900 server.xenapi.VM.suspend(get_single_vm(dom))
901 else:
902 server.xend.domain.suspend(dom)
904 def xm_resume(args):
905 arg_check(args, "resume", 1, 2)
907 try:
908 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
909 except getopt.GetoptError, opterr:
910 err(opterr)
911 usage('resume')
913 paused = False
914 for (k, v) in options:
915 if k in ['-p', '--paused']:
916 paused = True
918 if len(params) != 1:
919 err("Wrong number of parameters")
920 usage('resume')
922 dom = params[0]
923 if serverType == SERVER_XEN_API:
924 server.xenapi.VM.resume(get_single_vm(dom), paused)
925 else:
926 server.xend.domain.resume(dom, paused)
928 def xm_reboot(args):
929 arg_check(args, "reboot", 1, 3)
930 from xen.xm import shutdown
931 shutdown.main(["shutdown", "-R"] + args)
933 def xm_shutdown(args):
934 arg_check(args, "shutdown", 1, 4)
935 from xen.xm import shutdown
936 shutdown.main(["shutdown"] + args)
938 def xm_pause(args):
939 arg_check(args, "pause", 1)
940 dom = args[0]
942 if serverType == SERVER_XEN_API:
943 server.xenapi.VM.pause(get_single_vm(dom))
944 else:
945 server.xend.domain.pause(dom)
947 def xm_unpause(args):
948 arg_check(args, "unpause", 1)
949 dom = args[0]
951 if serverType == SERVER_XEN_API:
952 server.xenapi.VM.unpause(get_single_vm(dom))
953 else:
954 server.xend.domain.unpause(dom)
956 def xm_dump_core(args):
957 live = False
958 crash = False
959 try:
960 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
961 for (k, v) in options:
962 if k in ('-L', '--live'):
963 live = True
964 if k in ('-C', '--crash'):
965 crash = True
967 if len(params) not in (1, 2):
968 raise OptionError("Expects 1 or 2 argument(s)")
969 except getopt.GetoptError, e:
970 raise OptionError(str(e))
972 dom = params[0]
973 if len(params) == 2:
974 filename = os.path.abspath(params[1])
975 else:
976 filename = None
978 if not live:
979 server.xend.domain.pause(dom)
981 try:
982 print "Dumping core of domain: %s ..." % str(dom)
983 server.xend.domain.dump(dom, filename, live, crash)
984 finally:
985 if not live:
986 server.xend.domain.unpause(dom)
988 if crash:
989 print "Destroying domain: %s ..." % str(dom)
990 server.xend.domain.destroy(dom)
992 def xm_rename(args):
993 arg_check(args, "rename", 2)
995 if serverType == SERVER_XEN_API:
996 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
997 else:
998 server.xend.domain.setName(args[0], args[1])
1000 def xm_importcommand(command, args):
1001 cmd = __import__(command, globals(), locals(), 'xen.xm')
1002 cmd.main([command] + args)
1005 #############################################################
1007 def xm_vcpu_pin(args):
1008 arg_check(args, "vcpu-pin", 3)
1010 def cpu_make_map(cpulist):
1011 cpus = []
1012 for c in cpulist.split(','):
1013 if c.find('-') != -1:
1014 (x,y) = c.split('-')
1015 for i in range(int(x),int(y)+1):
1016 cpus.append(int(i))
1017 else:
1018 # remove this element from the list
1019 if c[0] == '^':
1020 cpus = [x for x in cpus if x != int(c[1:])]
1021 else:
1022 cpus.append(int(c))
1023 cpus.sort()
1024 return cpus
1026 dom = args[0]
1027 vcpu = args[1]
1028 cpumap = cpu_make_map(args[2])
1030 server.xend.domain.pincpu(dom, vcpu, cpumap)
1032 def xm_mem_max(args):
1033 arg_check(args, "mem-max", 2)
1035 dom = args[0]
1036 mem = int_unit(args[1], 'm')
1038 server.xend.domain.maxmem_set(dom, mem)
1040 def xm_mem_set(args):
1041 arg_check(args, "mem-set", 2)
1043 dom = args[0]
1044 mem_target = int_unit(args[1], 'm')
1046 server.xend.domain.setMemoryTarget(dom, mem_target)
1048 def xm_vcpu_set(args):
1049 arg_check(args, "vcpu-set", 2)
1051 server.xend.domain.setVCpuCount(args[0], int(args[1]))
1054 def xm_destroy(args):
1055 arg_check(args, "destroy", 1)
1057 dom = args[0]
1058 if serverType == SERVER_XEN_API:
1059 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1060 else:
1061 server.xend.domain.destroy(dom)
1064 def xm_domid(args):
1065 arg_check(args, "domid", 1)
1067 name = args[0]
1069 dom = server.xend.domain(name)
1070 print sxp.child_value(dom, 'domid')
1072 def xm_domname(args):
1073 arg_check(args, "domname", 1)
1075 name = args[0]
1077 dom = server.xend.domain(name)
1078 print sxp.child_value(dom, 'name')
1080 def xm_sched_sedf(args):
1081 def ns_to_ms(val):
1082 return float(val) * 0.000001
1084 def ms_to_ns(val):
1085 return (float(val) / 0.000001)
1087 def print_sedf(info):
1088 info['period'] = ns_to_ms(info['period'])
1089 info['slice'] = ns_to_ms(info['slice'])
1090 info['latency'] = ns_to_ms(info['latency'])
1091 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1092 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1094 def domid_match(domid, info):
1095 return domid is None or domid == info['name'] or \
1096 domid == str(info['domid'])
1098 # we want to just display current info if no parameters are passed
1099 if len(args) == 0:
1100 domid = None
1101 else:
1102 # we expect at least a domain id (name or number)
1103 # and at most a domid up to 5 options with values
1104 arg_check(args, "sched-sedf", 1, 11)
1105 domid = args[0]
1106 # drop domid from args since get_opt doesn't recognize it
1107 args = args[1:]
1109 opts = {}
1110 try:
1111 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1112 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1113 except getopt.GetoptError, opterr:
1114 err(opterr)
1115 usage('sched-sedf')
1117 # convert to nanoseconds if needed
1118 for (k, v) in options:
1119 if k in ['-p', '--period']:
1120 opts['period'] = ms_to_ns(v)
1121 elif k in ['-s', '--slice']:
1122 opts['slice'] = ms_to_ns(v)
1123 elif k in ['-l', '--latency']:
1124 opts['latency'] = ms_to_ns(v)
1125 elif k in ['-e', '--extratime']:
1126 opts['extratime'] = v
1127 elif k in ['-w', '--weight']:
1128 opts['weight'] = v
1130 doms = filter(lambda x : domid_match(domid, x),
1131 [parse_doms_info(dom)
1132 for dom in getDomains(None, 'running')])
1134 # print header if we aren't setting any parameters
1135 if len(opts.keys()) == 0:
1136 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1137 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1138 'Extra','Weight')
1140 for d in doms:
1141 # fetch current values so as not to clobber them
1142 try:
1143 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1144 except xmlrpclib.Fault:
1145 # domain does not support sched-sedf?
1146 sedf_raw = {}
1148 sedf_info = parse_sedf_info(sedf_raw)
1149 sedf_info['name'] = d['name']
1150 # update values in case of call to set
1151 if len(opts.keys()) > 0:
1152 for k in opts.keys():
1153 sedf_info[k]=opts[k]
1155 # send the update, converting user input
1156 v = map(int, [sedf_info['period'], sedf_info['slice'],
1157 sedf_info['latency'],sedf_info['extratime'],
1158 sedf_info['weight']])
1159 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1160 if int(rv) != 0:
1161 err("Failed to set sedf parameters (rv=%d)."%(rv))
1163 # not setting values, display info
1164 else:
1165 print_sedf(sedf_info)
1167 def xm_sched_credit(args):
1168 """Get/Set options for Credit Scheduler."""
1170 try:
1171 opts, params = getopt.getopt(args, "d:w:c:",
1172 ["domain=", "weight=", "cap="])
1173 except getopt.GetoptError, opterr:
1174 err(opterr)
1175 usage('sched-credit')
1177 domain = None
1178 weight = None
1179 cap = None
1181 for o, a in opts:
1182 if o == "-d":
1183 domain = a
1184 elif o == "-w":
1185 weight = int(a)
1186 elif o == "-c":
1187 cap = int(a);
1189 if domain is None:
1190 # place holder for system-wide scheduler parameters
1191 err("No domain given.")
1192 usage('sched-credit')
1194 if weight is None and cap is None:
1195 print server.xend.domain.sched_credit_get(domain)
1196 else:
1197 result = server.xend.domain.sched_credit_set(domain, weight, cap)
1198 if result != 0:
1199 err(str(result))
1201 def xm_info(args):
1202 arg_check(args, "info", 0)
1204 info = server.xend.node.info()
1206 for x in info[1:]:
1207 if len(x) < 2:
1208 print "%-23s: (none)" % x[0]
1209 else:
1210 print "%-23s:" % x[0], x[1]
1212 def xm_console(args):
1213 arg_check(args, "console", 1, 2)
1215 quiet = False;
1217 try:
1218 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1219 except getopt.GetoptError, opterr:
1220 err(opterr)
1221 usage('console')
1223 for (k, v) in options:
1224 if k in ['-q', '--quiet']:
1225 quiet = True
1226 else:
1227 assert False
1229 if len(params) != 1:
1230 err('No domain given')
1231 usage('console')
1233 dom = params[0]
1235 try:
1236 info = server.xend.domain(dom)
1237 except:
1238 if quiet:
1239 sys.exit(1)
1240 else:
1241 raise
1242 domid = int(sxp.child_value(info, 'domid', '-1'))
1243 if domid == -1:
1244 if quiet:
1245 sys.exit(1)
1246 else:
1247 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1249 console.execConsole(domid)
1252 def xm_uptime(args):
1253 short_mode = 0
1255 try:
1256 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1257 except getopt.GetoptError, opterr:
1258 err(opterr)
1259 usage('uptime')
1261 for (k, v) in options:
1262 if k in ['-s', '--short']:
1263 short_mode = 1
1265 doms = getDomains(params, 'running')
1267 if short_mode == 0:
1268 print 'Name ID Uptime'
1270 for dom in doms:
1271 d = parse_doms_info(dom)
1272 if int(d['domid']) > 0:
1273 uptime = int(round(d['up_time']))
1274 else:
1275 f=open('/proc/uptime', 'r')
1276 upfile = f.read()
1277 uptime = int(round(float(upfile.split(' ')[0])))
1278 f.close()
1280 days = int(uptime / 86400)
1281 uptime -= (days * 86400)
1282 hours = int(uptime / 3600)
1283 uptime -= (hours * 3600)
1284 minutes = int(uptime / 60)
1285 uptime -= (minutes * 60)
1286 seconds = uptime
1288 upstring = ""
1289 if days > 0:
1290 upstring += str(days) + " day"
1291 if days > 1:
1292 upstring += "s"
1293 upstring += ", "
1294 upstring += '%(hours)2d:%(minutes)02d' % vars()
1296 if short_mode:
1297 now = datetime.datetime.now()
1298 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1299 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1300 else:
1301 upstring += ':%(seconds)02d' % vars()
1302 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1304 print upstring
1306 def xm_sysrq(args):
1307 arg_check(args, "sysrq", 2)
1308 dom = args[0]
1309 req = args[1]
1310 server.xend.domain.send_sysrq(dom, req)
1312 def xm_top(args):
1313 arg_check(args, "top", 0)
1315 os.execvp('xentop', ['xentop'])
1317 def xm_dmesg(args):
1318 arg_check(args, "dmesg", 0, 1)
1320 try:
1321 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1322 except getopt.GetoptError, opterr:
1323 err(opterr)
1324 usage('dmesg')
1326 use_clear = 0
1327 for (k, v) in options:
1328 if k in ['-c', '--clear']:
1329 use_clear = 1
1331 if len(params) :
1332 err("No parameter required")
1333 usage('dmesg')
1335 if not use_clear:
1336 print server.xend.node.dmesg.info()
1337 else:
1338 server.xend.node.dmesg.clear()
1340 def xm_log(args):
1341 arg_check(args, "log", 0)
1343 print server.xend.node.log()
1345 def xm_serve(args):
1346 arg_check(args, "serve", 0)
1348 from fcntl import fcntl, F_SETFL
1350 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1351 s.connect(XendClient.XML_RPC_SOCKET)
1352 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1354 while True:
1355 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1356 if s in iwtd:
1357 data = s.recv(4096)
1358 if len(data) > 0:
1359 sys.stdout.write(data)
1360 sys.stdout.flush()
1361 else:
1362 break
1363 if sys.stdin in iwtd:
1364 data = sys.stdin.read(4096)
1365 if len(data) > 0:
1366 s.sendall(data)
1367 else:
1368 break
1369 s.close()
1371 def parse_dev_info(info):
1372 def get_info(n, t, d):
1373 i = 0
1374 while i < len(info):
1375 if (info[i][0] == n):
1376 return t(info[i][1])
1377 i = i + 1
1378 return t(d)
1379 return {
1380 #common
1381 'backend-id' : get_info('backend-id', int, -1),
1382 'handle' : get_info('handle', int, 0),
1383 'state' : get_info('state', int, -1),
1384 'be-path' : get_info('backend', str, '??'),
1385 'event-ch' : get_info('event-channel',int, -1),
1386 #network specific
1387 'virtual-device' : get_info('virtual-device', str, '??'),
1388 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1389 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1390 'mac' : get_info('mac', str, '??'),
1391 #block-device specific
1392 'ring-ref' : get_info('ring-ref', int, -1),
1395 def arg_check_for_resource_list(args, name):
1396 use_long = 0
1397 try:
1398 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1399 except getopt.GetoptError, opterr:
1400 err(opterr)
1401 sys.exit(1)
1403 for (k, v) in options:
1404 if k in ['-l', '--long']:
1405 use_long = 1
1407 if len(params) == 0:
1408 print 'No domain parameter given'
1409 usage(name)
1410 if len(params) > 1:
1411 print 'No multiple domain parameters allowed'
1412 usage(name)
1414 return (use_long, params)
1416 def xm_network_list(args):
1417 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1419 dom = params[0]
1420 if use_long:
1421 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1422 map(PrettyPrint.prettyprint, devs)
1423 else:
1424 hdr = 0
1425 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
1426 if hdr == 0:
1427 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1428 hdr = 1
1429 ni = parse_dev_info(x[1])
1430 ni['idx'] = int(x[0])
1431 print ("%(idx)-3d "
1432 "%(backend-id)-3d"
1433 "%(mac)-17s "
1434 "%(handle)-3d "
1435 "%(state)-3d "
1436 "%(event-ch)-3d "
1437 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1438 "%(be-path)-30s "
1439 % ni)
1441 def xm_block_list(args):
1442 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1444 dom = params[0]
1445 if use_long:
1446 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1447 map(PrettyPrint.prettyprint, devs)
1448 else:
1449 hdr = 0
1450 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
1451 if hdr == 0:
1452 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1453 hdr = 1
1454 ni = parse_dev_info(x[1])
1455 ni['idx'] = int(x[0])
1456 print ("%(idx)-3d "
1457 "%(backend-id)-3d "
1458 "%(handle)-3d "
1459 "%(state)-3d "
1460 "%(event-ch)-3d "
1461 "%(ring-ref)-5d "
1462 "%(be-path)-30s "
1463 % ni)
1465 def xm_vtpm_list(args):
1466 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1468 dom = params[0]
1469 if use_long:
1470 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1471 map(PrettyPrint.prettyprint, devs)
1472 else:
1473 hdr = 0
1474 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1475 if hdr == 0:
1476 print 'Idx BE handle state evt-ch ring-ref BE-path'
1477 hdr = 1
1478 ni = parse_dev_info(x[1])
1479 ni['idx'] = int(x[0])
1480 print ("%(idx)-3d "
1481 "%(backend-id)-3d "
1482 "%(handle)-3d "
1483 "%(state)-3d "
1484 "%(event-ch)-3d "
1485 "%(ring-ref)-5d "
1486 "%(be-path)-30s "
1487 % ni)
1490 def parse_block_configuration(args):
1491 dom = args[0]
1493 if args[1].startswith('tap:'):
1494 cls = 'tap'
1495 else:
1496 cls = 'vbd'
1498 vbd = [cls,
1499 ['uname', args[1]],
1500 ['dev', args[2]],
1501 ['mode', args[3]]]
1502 if len(args) == 5:
1503 vbd.append(['backend', args[4]])
1505 # verify that policy permits attaching this resource
1506 if security.on():
1507 dominfo = server.xend.domain(dom)
1508 label = security.get_security_printlabel(dominfo)
1509 else:
1510 label = None
1511 security.res_security_check(args[1], label)
1513 return (dom, vbd)
1516 def xm_block_attach(args):
1517 arg_check(args, 'block-attach', 4, 5)
1519 (dom, vbd) = parse_block_configuration(args)
1520 server.xend.domain.device_create(dom, vbd)
1523 def xm_block_configure(args):
1524 arg_check(args, 'block-configure', 4, 5)
1526 (dom, vbd) = parse_block_configuration(args)
1527 server.xend.domain.device_configure(dom, vbd)
1530 def xm_network_attach(args):
1531 arg_check(args, 'network-attach', 1, 10000)
1533 dom = args[0]
1534 vif = ['vif']
1536 for a in args[1:]:
1537 vif.append(a.split("="))
1539 server.xend.domain.device_create(dom, vif)
1542 def detach(args, command, deviceClass):
1543 arg_check(args, command, 2, 3)
1545 dom = args[0]
1546 dev = args[1]
1547 try:
1548 force = args[2]
1549 if (force != "--force") and (force != "-f"):
1550 print "Ignoring option %s"%(force)
1551 force = None
1552 except IndexError:
1553 force = None
1555 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
1558 def xm_block_detach(args):
1559 try:
1560 detach(args, 'block-detach', 'vbd')
1561 return
1562 except:
1563 pass
1564 detach(args, 'block-detach', 'tap')
1567 def xm_network_detach(args):
1568 detach(args, 'network-detach', 'vif')
1571 def xm_vnet_list(args):
1572 try:
1573 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1574 except getopt.GetoptError, opterr:
1575 err(opterr)
1576 usage('vnet-list')
1578 use_long = 0
1579 for (k, v) in options:
1580 if k in ['-l', '--long']:
1581 use_long = 1
1583 if params:
1584 use_long = 1
1585 vnets = params
1586 else:
1587 vnets = server.xend_vnets()
1589 for vnet in vnets:
1590 try:
1591 if use_long:
1592 info = server.xend_vnet(vnet)
1593 PrettyPrint.prettyprint(info)
1594 else:
1595 print vnet
1596 except Exception, ex:
1597 print vnet, ex
1599 def xm_vnet_create(args):
1600 arg_check(args, "vnet-create", 1)
1601 conf = args[0]
1602 if not os.access(conf, os.R_OK):
1603 print "File not found: %s" % conf
1604 sys.exit(1)
1606 server.xend_vnet_create(conf)
1608 def xm_vnet_delete(args):
1609 arg_check(args, "vnet-delete", 1)
1610 vnet = args[0]
1611 server.xend_vnet_delete(vnet)
1613 commands = {
1614 "shell": xm_shell,
1615 # console commands
1616 "console": xm_console,
1617 # xenstat commands
1618 "top": xm_top,
1619 # domain commands
1620 "delete": xm_delete,
1621 "destroy": xm_destroy,
1622 "domid": xm_domid,
1623 "domname": xm_domname,
1624 "dump-core": xm_dump_core,
1625 "reboot": xm_reboot,
1626 "rename": xm_rename,
1627 "restore": xm_restore,
1628 "resume": xm_resume,
1629 "save": xm_save,
1630 "shutdown": xm_shutdown,
1631 "start": xm_start,
1632 "sysrq": xm_sysrq,
1633 "uptime": xm_uptime,
1634 "suspend": xm_suspend,
1635 "list": xm_list,
1636 # memory commands
1637 "mem-max": xm_mem_max,
1638 "mem-set": xm_mem_set,
1639 # cpu commands
1640 "vcpu-pin": xm_vcpu_pin,
1641 "vcpu-list": xm_vcpu_list,
1642 "vcpu-set": xm_vcpu_set,
1643 # special
1644 "pause": xm_pause,
1645 "unpause": xm_unpause,
1646 # host commands
1647 "dmesg": xm_dmesg,
1648 "info": xm_info,
1649 "log": xm_log,
1650 "serve": xm_serve,
1651 # scheduler
1652 "sched-sedf": xm_sched_sedf,
1653 "sched-credit": xm_sched_credit,
1654 # block
1655 "block-attach": xm_block_attach,
1656 "block-detach": xm_block_detach,
1657 "block-list": xm_block_list,
1658 "block-configure": xm_block_configure,
1659 # network
1660 "network-attach": xm_network_attach,
1661 "network-detach": xm_network_detach,
1662 "network-list": xm_network_list,
1663 # vnet
1664 "vnet-list": xm_vnet_list,
1665 "vnet-create": xm_vnet_create,
1666 "vnet-delete": xm_vnet_delete,
1667 # vtpm
1668 "vtpm-list": xm_vtpm_list,
1671 ## The commands supported by a separate argument parser in xend.xm.
1672 IMPORTED_COMMANDS = [
1673 'create',
1674 'new',
1675 'migrate',
1676 'labels',
1677 'cfgbootpolicy',
1678 'makepolicy',
1679 'loadpolicy',
1680 'dumppolicy',
1681 'addlabel',
1682 'rmlabel',
1683 'getlabel',
1684 'dry-run',
1685 'resources',
1688 for c in IMPORTED_COMMANDS:
1689 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
1691 aliases = {
1692 "balloon": "mem-set",
1693 "set-vcpus": "vcpu-set",
1694 "vif-list": "network-list",
1695 "vbd-create": "block-attach",
1696 "vbd-destroy": "block-detach",
1697 "vbd-list": "block-list",
1701 def xm_lookup_cmd(cmd):
1702 if commands.has_key(cmd):
1703 return commands[cmd]
1704 elif aliases.has_key(cmd):
1705 deprecated(cmd,aliases[cmd])
1706 return commands[aliases[cmd]]
1707 elif cmd == 'help':
1708 longHelp()
1709 sys.exit(0)
1710 else:
1711 # simulate getopt's prefix matching behaviour
1712 if len(cmd) > 1:
1713 same_prefix_cmds = [commands[c] for c in commands.keys() \
1714 if c[:len(cmd)] == cmd]
1715 # only execute if there is only 1 match
1716 if len(same_prefix_cmds) == 1:
1717 return same_prefix_cmds[0]
1718 return None
1720 def deprecated(old,new):
1721 print >>sys.stderr, (
1722 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1724 def main(argv=sys.argv):
1725 if len(argv) < 2:
1726 usage()
1728 # intercept --help(-h) and output our own help
1729 for help in ['--help', '-h']:
1730 if help in argv[1:]:
1731 if help == argv[1]:
1732 longHelp()
1733 sys.exit(0)
1734 else:
1735 usage(argv[1])
1737 cmd_name = argv[1]
1738 cmd = xm_lookup_cmd(cmd_name)
1739 if cmd:
1740 # strip off prog name and subcmd
1741 args = argv[2:]
1742 _, rc = _run_cmd(cmd, cmd_name, args)
1743 sys.exit(rc)
1744 else:
1745 err('Subcommand %s not found!' % cmd_name)
1746 usage()
1748 def _run_cmd(cmd, cmd_name, args):
1749 global server
1751 try:
1752 if server is None:
1753 if serverType == SERVER_XEN_API:
1754 server = XenAPI.Session(serverURI)
1755 username, password = parseAuthentication()
1756 server.login_with_password(username, password)
1757 def logout():
1758 try:
1759 server.xenapi.session.logout()
1760 except:
1761 pass
1762 atexit.register(logout)
1763 else:
1764 server = ServerProxy(serverURI)
1766 return True, cmd(args)
1767 except socket.error, ex:
1768 if os.geteuid() != 0:
1769 err("Most commands need root access. Please try again as root.")
1770 else:
1771 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
1772 except KeyboardInterrupt:
1773 print "Interrupted."
1774 return True, ''
1775 except IOError, ex:
1776 if os.geteuid() != 0:
1777 err("Most commands need root access. Please try again as root.")
1778 else:
1779 err("Unable to connect to xend: %s." % ex[1])
1780 except SystemExit, code:
1781 return code == 0, code
1782 except XenAPI.Failure, exn:
1783 for line in [''] + wrap(str(exn), 80) + ['']:
1784 print >>sys.stderr, line
1785 except xmlrpclib.Fault, ex:
1786 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
1787 err("Domain '%s' does not exist." % ex.faultString)
1788 else:
1789 err(ex.faultString)
1790 _usage(cmd_name)
1791 except xmlrpclib.ProtocolError, ex:
1792 if ex.errcode == -1:
1793 print >>sys.stderr, (
1794 "Xend has probably crashed! Invalid or missing HTTP "
1795 "status code.")
1796 else:
1797 print >>sys.stderr, (
1798 "Xend has probably crashed! ProtocolError(%d, %s)." %
1799 (ex.errcode, ex.errmsg))
1800 except (ValueError, OverflowError):
1801 err("Invalid argument.")
1802 _usage(cmd_name)
1803 except OptionError, e:
1804 err(str(e))
1805 _usage(cmd_name)
1806 print e.usage
1807 except security.ACMError, e:
1808 err(str(e))
1809 except:
1810 print "Unexpected error:", sys.exc_info()[0]
1811 print
1812 print "Please report to xen-devel@lists.xensource.com"
1813 raise
1815 return False, 1
1817 if __name__ == "__main__":
1818 main()