ia64/xen-unstable

view tools/python/xen/xm/main.py @ 14540:238ed1c75194

Ignore exceptions in the get_all_methods call.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Fri Mar 23 17:42:08 2007 +0000 (2007-03-23)
parents f434c63b484a
children effef488d448
line source
1 # (C) Copyright IBM Corp. 2005
2 # Copyright (C) 2004 Mike Wray
3 # Copyright (c) 2005-2006 XenSource Ltd.
4 #
5 # Authors:
6 # Sean Dague <sean at dague dot net>
7 # Mike Wray <mike dot wray at hp dot com>
8 #
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of version 2.1 of the GNU Lesser General Public
11 # License as published by the Free Software Foundation.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 """Grand unified management application for Xen.
23 """
24 import atexit
25 import cmd
26 import os
27 import pprint
28 import readline
29 import shlex
30 import sys
31 import re
32 import getopt
33 import socket
34 import traceback
35 import xmlrpclib
36 import time
37 import datetime
38 from select import select
39 import xml.dom.minidom
40 from xen.util.blkif import blkdev_name_to_number
42 import warnings
43 warnings.filterwarnings('ignore', category=FutureWarning)
45 from xen.xend import PrettyPrint
46 from xen.xend import sxp
47 from xen.xend import XendClient
48 from xen.xend.XendConstants import *
50 from xen.xm.opts import OptionError, Opts, wrap, set_true
51 from xen.xm import console
52 from xen.util.xmlrpclib2 import ServerProxy
54 import XenAPI
57 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
58 # getopt.getopt if gnu_getopt is not available. This will mean that options
59 # may only be specified before positional arguments.
60 if not hasattr(getopt, 'gnu_getopt'):
61 getopt.gnu_getopt = getopt.getopt
63 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
64 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
66 # Supported types of server
67 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
68 SERVER_XEN_API = 'Xen-API'
70 # General help message
72 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
73 "Control, list, and manipulate Xen guest instances.\n"
75 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
76 'For more help on \'xm\' see the xm(1) man page.\n' \
77 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
78 ' man page.\n'
80 # Help strings are indexed by subcommand name in this way:
81 # 'subcommand': (argstring, description)
83 SUBCOMMAND_HELP = {
84 # common commands
86 'shell' : ('', 'Launch an interactive shell.'),
88 'console' : ('[-q|--quiet] <Domain>',
89 'Attach to <Domain>\'s console.'),
90 'create' : ('<ConfigFile> [options] [vars]',
91 'Create a domain based on <ConfigFile>.'),
92 'destroy' : ('<Domain>',
93 'Terminate a domain immediately.'),
94 'help' : ('', 'Display this message.'),
95 'list' : ('[options] [Domain, ...]',
96 'List information about all/some domains.'),
97 'mem-max' : ('<Domain> <Mem>',
98 'Set the maximum amount reservation for a domain.'),
99 'mem-set' : ('<Domain> <Mem>',
100 'Set the current memory usage for a domain.'),
101 'migrate' : ('<Domain> <Host>',
102 'Migrate a domain to another machine.'),
103 'pause' : ('<Domain>', 'Pause execution of a domain.'),
104 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
105 'restore' : ('<CheckpointFile> [-p]',
106 'Restore a domain from a saved state.'),
107 'save' : ('[-c] <Domain> <CheckpointFile>',
108 'Save a domain state to restore later.'),
109 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
110 'top' : ('', 'Monitor a host and the domains in real time.'),
111 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
112 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
114 # Life cycle xm commands
115 'new' : ('<ConfigFile> [options] [vars]',
116 'Adds a domain to Xend domain management'),
117 'delete' : ('<DomainName>',
118 'Remove a domain from Xend domain management.'),
119 'start' : ('<DomainName>', 'Start a Xend managed domain'),
120 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
121 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
123 # less used commands
125 'dmesg' : ('[-c|--clear]',
126 'Read and/or clear Xend\'s message buffer.'),
127 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
128 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
129 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
130 'Dump core for a specific domain.'),
131 'info' : ('', 'Get information about Xen host.'),
132 'log' : ('', 'Print Xend log'),
133 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
134 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
135 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
136 'Get/set credit scheduler parameters.'),
137 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
138 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
139 'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
140 'Send a trigger to a domain.'),
141 'vcpu-list' : ('[<Domain>]',
142 'List the VCPUs for a domain or all domains.'),
143 'vcpu-pin' : ('<Domain> <VCPU> <CPUs|all>',
144 'Set which CPUs a VCPU can use.'),
145 'vcpu-set' : ('<Domain> <vCPUs>',
146 'Set the number of active VCPUs for allowed for the'
147 ' domain.'),
149 # device commands
151 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
152 'Create a new virtual block device.'),
153 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
154 'Change block device configuration'),
155 'block-detach' : ('<Domain> <DevId> [-f|--force]',
156 'Destroy a domain\'s virtual block device.'),
157 'block-list' : ('<Domain> [--long]',
158 'List virtual block devices for a domain.'),
159 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
160 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
161 '[vifname=<name>] [rate=<rate>] [model=<model>]',
162 'Create a new virtual network device.'),
163 'network-detach': ('<Domain> <DevId> [-f|--force]',
164 'Destroy a domain\'s virtual network device.'),
165 'network-list' : ('<Domain> [--long]',
166 'List virtual network interfaces for a domain.'),
167 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
168 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
169 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
170 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
172 # security
174 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
175 'Add security label to domain.'),
176 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
177 'Remove a security label from domain.'),
178 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
179 'Show security label for domain or resource.'),
180 'dry-run' : ('<ConfigFile>',
181 'Test if a domain can access its resources.'),
182 'resources' : ('', 'Show info for each labeled resource.'),
183 'cfgbootpolicy' : ('<policy> [boot-title]',
184 'Add policy to boot configuration.'),
185 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
186 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
187 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
188 'files.'),
189 'labels' : ('[policy] [type=dom|res|any]',
190 'List <type> labels for (active) policy.'),
191 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
192 }
194 SUBCOMMAND_OPTIONS = {
195 'sched-sedf': (
196 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
197 ('-s [MS]', '--slice[=MS]' ,
198 'Worst-case execution time(ms). (slice < period)'),
199 ('-l [MS]', '--latency[=MS]',
200 'Scaled period (ms) when domain performs heavy I/O'),
201 ('-e [FLAG]', '--extra[=FLAG]',
202 'Flag (0 or 1) controls if domain can run in extra time.'),
203 ('-w [FLOAT]', '--weight[=FLOAT]',
204 'CPU Period/slice (do not set with --period/--slice)'),
205 ),
206 'sched-credit': (
207 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
208 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
209 ('-c CAP', '--cap=CAP', 'Cap (int)'),
210 ),
211 'list': (
212 ('-l', '--long', 'Output all VM details in SXP'),
213 ('', '--label', 'Include security labels'),
214 ('', '--state=<state>', 'Select only VMs with the specified state'),
215 ),
216 'console': (
217 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
218 ),
219 'dmesg': (
220 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
221 ),
222 'vnet-list': (
223 ('-l', '--long', 'List Vnets as SXP'),
224 ),
225 'network-list': (
226 ('-l', '--long', 'List resources as SXP'),
227 ),
228 'dump-core': (
229 ('-L', '--live', 'Dump core without pausing the domain'),
230 ('-C', '--crash', 'Crash domain after dumping core'),
231 ),
232 'start': (
233 ('-p', '--paused', 'Do not unpause domain after starting it'),
234 ),
235 'resume': (
236 ('-p', '--paused', 'Do not unpause domain after resuming it'),
237 ),
238 'save': (
239 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
240 ),
241 'restore': (
242 ('-p', '--paused', 'Do not unpause domain after restoring it'),
243 ),
244 }
246 common_commands = [
247 "console",
248 "create",
249 "new",
250 "delete",
251 "destroy",
252 "dump-core",
253 "help",
254 "list",
255 "mem-set",
256 "migrate",
257 "pause",
258 "reboot",
259 "restore",
260 "resume",
261 "save",
262 "shell",
263 "shutdown",
264 "start",
265 "suspend",
266 "top",
267 "unpause",
268 "uptime",
269 "vcpu-set",
270 ]
272 domain_commands = [
273 "console",
274 "create",
275 "new",
276 "delete",
277 "destroy",
278 "domid",
279 "domname",
280 "dump-core",
281 "list",
282 "mem-max",
283 "mem-set",
284 "migrate",
285 "pause",
286 "reboot",
287 "rename",
288 "restore",
289 "resume",
290 "save",
291 "shutdown",
292 "start",
293 "suspend",
294 "sysrq",
295 "trigger",
296 "top",
297 "unpause",
298 "uptime",
299 "vcpu-list",
300 "vcpu-pin",
301 "vcpu-set",
302 ]
304 host_commands = [
305 "debug-keys",
306 "dmesg",
307 "info",
308 "log",
309 "serve",
310 ]
312 scheduler_commands = [
313 "sched-credit",
314 "sched-sedf",
315 ]
317 device_commands = [
318 "block-attach",
319 "block-detach",
320 "block-list",
321 "block-configure",
322 "network-attach",
323 "network-detach",
324 "network-list",
325 "vtpm-list",
326 ]
328 vnet_commands = [
329 "vnet-list",
330 "vnet-create",
331 "vnet-delete",
332 ]
334 acm_commands = [
335 "labels",
336 "addlabel",
337 "rmlabel",
338 "getlabel",
339 "dry-run",
340 "resources",
341 "makepolicy",
342 "loadpolicy",
343 "cfgbootpolicy",
344 "dumppolicy",
345 ]
347 all_commands = (domain_commands + host_commands + scheduler_commands +
348 device_commands + vnet_commands + acm_commands + ['shell'])
351 ##
352 # Configuration File Parsing
353 ##
355 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
356 config = None
357 if os.path.isfile(xmConfigFile):
358 try:
359 config = xml.dom.minidom.parse(xmConfigFile)
360 except:
361 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
362 xmConfigFile)
364 def parseServer():
365 if config:
366 server = config.getElementsByTagName('server')
367 if server:
368 st = server[0].getAttribute('type')
369 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
370 print >>sys.stderr, ('Invalid server type %s; using %s.' %
371 (st, SERVER_LEGACY_XMLRPC))
372 st = SERVER_LEGACY_XMLRPC
373 return (st, server[0].getAttribute('uri'))
375 return SERVER_LEGACY_XMLRPC, XendClient.uri
377 def parseAuthentication():
378 server = config.getElementsByTagName('server')[0]
379 return (server.getAttribute('username'),
380 server.getAttribute('password'))
382 serverType, serverURI = parseServer()
383 server = None
386 ####################################################################
387 #
388 # Help/usage printing functions
389 #
390 ####################################################################
392 def cmdHelp(cmd):
393 """Print help for a specific subcommand."""
395 for fc in SUBCOMMAND_HELP.keys():
396 if fc[:len(cmd)] == cmd:
397 cmd = fc
398 break
400 try:
401 args, desc = SUBCOMMAND_HELP[cmd]
402 except KeyError:
403 shortHelp()
404 return
406 print 'Usage: xm %s %s' % (cmd, args)
407 print
408 print desc
410 try:
411 # If options help message is defined, print this.
412 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
413 if shortopt and longopt:
414 optdesc = '%s, %s' % (shortopt, longopt)
415 elif shortopt:
416 optdesc = shortopt
417 elif longopt:
418 optdesc = longopt
420 wrapped_desc = wrap(desc, 43)
421 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
422 for line in wrapped_desc[1:]:
423 print ' ' * 33 + line
424 print
425 except KeyError:
426 # if the command is an external module, we grab usage help
427 # from the module itself.
428 if cmd in IMPORTED_COMMANDS:
429 try:
430 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
431 cmd_usage = getattr(cmd_module, "help", None)
432 if cmd_usage:
433 print cmd_usage()
434 except ImportError:
435 pass
437 def shortHelp():
438 """Print out generic help when xm is called without subcommand."""
440 print USAGE_HELP
441 print 'Common \'xm\' commands:\n'
443 for command in common_commands:
444 try:
445 args, desc = SUBCOMMAND_HELP[command]
446 except KeyError:
447 continue
448 wrapped_desc = wrap(desc, 50)
449 print ' %-20s %-50s' % (command, wrapped_desc[0])
450 for line in wrapped_desc[1:]:
451 print ' ' * 22 + line
453 print
454 print USAGE_FOOTER
455 print 'For a complete list of subcommands run \'xm help\'.'
457 def longHelp():
458 """Print out full help when xm is called with xm --help or xm help"""
460 print USAGE_HELP
461 print 'xm full list of subcommands:\n'
463 for command in all_commands:
464 try:
465 args, desc = SUBCOMMAND_HELP[command]
466 except KeyError:
467 continue
469 wrapped_desc = wrap(desc, 50)
470 print ' %-20s %-50s' % (command, wrapped_desc[0])
471 for line in wrapped_desc[1:]:
472 print ' ' * 22 + line
474 print
475 print USAGE_FOOTER
477 def _usage(cmd):
478 """ Print help usage information """
479 if cmd:
480 cmdHelp(cmd)
481 else:
482 shortHelp()
484 def usage(cmd = None):
485 """ Print help usage information and exits """
486 _usage(cmd)
487 sys.exit(1)
490 ####################################################################
491 #
492 # Utility functions
493 #
494 ####################################################################
496 def get_default_SR():
497 return [sr_ref
498 for sr_ref in server.xenapi.SR.get_all()
499 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
501 def get_default_Network():
502 return [network_ref
503 for network_ref in server.xenapi.network.get_all()][0]
505 class XenAPIUnsupportedException(Exception):
506 pass
508 def xenapi_unsupported():
509 if serverType == SERVER_XEN_API:
510 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
512 def map2sxp(m):
513 return [[k, m[k]] for k in m.keys()]
515 def arg_check(args, name, lo, hi = -1):
516 n = len([i for i in args if i != '--'])
518 if hi == -1:
519 if n != lo:
520 err("'xm %s' requires %d argument%s.\n" % (name, lo,
521 lo == 1 and '' or 's'))
522 usage(name)
523 else:
524 if n < lo or n > hi:
525 err("'xm %s' requires between %d and %d arguments.\n" %
526 (name, lo, hi))
527 usage(name)
530 def unit(c):
531 if not c.isalpha():
532 return 0
533 base = 1
534 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
535 elif c == 'M' or c == 'm': base = 1024 * 1024
536 elif c == 'K' or c == 'k': base = 1024
537 else:
538 print 'ignoring unknown unit'
539 return base
541 def int_unit(str, dest):
542 base = unit(str[-1])
543 if not base:
544 return int(str)
546 value = int(str[:-1])
547 dst_base = unit(dest)
548 if dst_base == 0:
549 dst_base = 1
550 if dst_base > base:
551 return value / (dst_base / base)
552 else:
553 return value * (base / dst_base)
555 def err(msg):
556 print >>sys.stderr, "Error:", msg
559 def get_single_vm(dom):
560 if serverType == SERVER_XEN_API:
561 uuids = server.xenapi.VM.get_by_name_label(dom)
562 n = len(uuids)
563 if n > 0:
564 return uuids[0]
565 else:
566 raise OptionError("Domain '%s' not found." % dom)
567 else:
568 dominfo = server.xend.domain(dom, False)
569 return dominfo['uuid']
571 ##
572 #
573 # Xen-API Shell
574 #
575 ##
577 class Shell(cmd.Cmd):
578 def __init__(self):
579 cmd.Cmd.__init__(self)
580 self.prompt = "xm> "
581 if serverType == SERVER_XEN_API:
582 try:
583 res = server.xenapi._UNSUPPORTED_list_all_methods()
584 for f in res:
585 setattr(Shell, 'do_' + f + ' ', self.default)
586 except:
587 pass
589 def preloop(self):
590 cmd.Cmd.preloop(self)
591 readline.set_completer_delims(' ')
593 def default(self, line):
594 words = shlex.split(line)
595 if len(words) > 0 and words[0] == 'xm':
596 words = words[1:]
597 if len(words) > 0:
598 cmd = xm_lookup_cmd(words[0])
599 if cmd:
600 _run_cmd(cmd, words[0], words[1:])
601 elif serverType == SERVER_XEN_API:
602 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
603 tuple(x)),
604 words[0], words[1:])
605 if ok and res is not None and res != '':
606 pprint.pprint(res)
607 else:
608 print '*** Unknown command: %s' % words[0]
609 return False
611 def completedefault(self, text, line, begidx, endidx):
612 words = shlex.split(line[:begidx])
613 clas, func = words[0].split('.')
614 if len(words) > 1 or \
615 func.startswith('get_by_') or \
616 func == 'get_all':
617 return []
618 uuids = server.xenapi_request('%s.get_all' % clas, ())
619 return [u + " " for u in uuids if u.startswith(text)]
621 def emptyline(self):
622 pass
624 def do_EOF(self, line):
625 print
626 sys.exit(0)
628 def do_help(self, line):
629 _usage(line)
632 def xm_shell(args):
633 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
636 #########################################################################
637 #
638 # Main xm functions
639 #
640 #########################################################################
642 def xm_save(args):
644 arg_check(args, "save", 2, 3)
646 try:
647 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
648 except getopt.GetoptError, opterr:
649 err(opterr)
650 sys.exit(1)
652 dom = params[0]
653 savefile = params[1]
655 checkpoint = False
656 for (k, v) in options:
657 if k in ['-c', '--checkpoint']:
658 checkpoint = True
660 if len(params) != 2:
661 err("Wrong number of parameters")
662 usage('save')
663 sys.exit(1)
665 savefile = os.path.abspath(savefile)
667 if not os.access(os.path.dirname(savefile), os.W_OK):
668 err("xm save: Unable to create file %s" % savefile)
669 sys.exit(1)
671 if serverType == SERVER_XEN_API:
672 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
673 else:
674 try:
675 dominfo = parse_doms_info(server.xend.domain(dom))
676 except xmlrpclib.Fault, ex:
677 raise ex
679 domid = dominfo['domid']
680 server.xend.domain.save(domid, savefile, checkpoint)
682 def xm_restore(args):
683 arg_check(args, "restore", 1, 2)
685 try:
686 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
687 except getopt.GetoptError, opterr:
688 err(opterr)
689 usage('restore')
691 paused = False
692 for (k, v) in options:
693 if k in ['-p', '--paused']:
694 paused = True
696 if len(params) != 1:
697 err("Wrong number of parameters")
698 usage('restore')
700 savefile = os.path.abspath(params[0])
702 if not os.access(savefile, os.R_OK):
703 err("xm restore: Unable to read file %s" % savefile)
704 sys.exit(1)
706 if serverType == SERVER_XEN_API:
707 server.xenapi.VM.restore(savefile, paused)
708 else:
709 server.xend.domain.restore(savefile, paused)
712 def getDomains(domain_names, state, full = 0):
713 if serverType == SERVER_XEN_API:
714 doms_sxp = []
715 doms_dict = []
716 dom_refs = server.xenapi.VM.get_all()
717 for dom_ref in dom_refs:
718 dom_rec = server.xenapi.VM.get_record(dom_ref)
719 dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref)
720 dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref)
722 states = ('running', 'blocked', 'paused', 'shutdown',
723 'crashed', 'dying')
724 def state_on_off(state):
725 if dom_metrics['state'].find(state) > -1:
726 return state[0]
727 else:
728 return "-"
729 state_str = "".join([state_on_off(state)
730 for state in states])
732 dom_rec.update({'name': dom_rec['name_label'],
733 'memory_actual': int(dom_metrics['memory_actual'])/1024,
734 'vcpus': dom_metrics['VCPUs_number'],
735 'state': state_str,
736 'cpu_time': dom_metrics['VCPUs_utilisation'],
737 'start_time': dom_metrics['start_time']})
739 doms_sxp.append(['domain'] + map2sxp(dom_rec))
740 doms_dict.append(dom_rec)
742 if domain_names:
743 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
744 if dom["name"] in domain_names]
746 if len(doms) > 0:
747 return doms
748 else:
749 print "Error: no domain%s named %s" % \
750 (len(domain_names) > 1 and 's' or '',
751 ', '.join(domain_names))
752 sys.exit(-1)
753 else:
754 return doms_sxp
755 else:
756 if domain_names:
757 return [server.xend.domain(dom, full) for dom in domain_names]
758 else:
759 return server.xend.domains_with_state(True, state, full)
762 def xm_list(args):
763 use_long = 0
764 show_vcpus = 0
765 show_labels = 0
766 state = 'all'
767 try:
768 (options, params) = getopt.gnu_getopt(args, 'lv',
769 ['long','vcpus','label',
770 'state='])
771 except getopt.GetoptError, opterr:
772 err(opterr)
773 usage('list')
775 for (k, v) in options:
776 if k in ['-l', '--long']:
777 use_long = 1
778 if k in ['-v', '--vcpus']:
779 show_vcpus = 1
780 if k in ['--label']:
781 show_labels = 1
782 if k in ['--state']:
783 state = v
785 if state != 'all' and len(params) > 0:
786 raise OptionError(
787 "You may specify either a state or a particular VM, but not both")
789 if show_vcpus:
790 print >>sys.stderr, (
791 "xm list -v is deprecated. Please use xm vcpu-list.")
792 xm_vcpu_list(params)
793 return
795 doms = getDomains(params, state, use_long)
797 if use_long:
798 map(PrettyPrint.prettyprint, doms)
799 elif show_labels:
800 xm_label_list(doms)
801 else:
802 xm_brief_list(doms)
805 def parse_doms_info(info):
806 def get_info(n, t, d):
807 return t(sxp.child_value(info, n, d))
809 def get_status(n, t, d):
810 return DOM_STATES[t(sxp.child_value(info, n, d))]
812 start_time = get_info('start_time', float, -1)
813 if start_time == -1:
814 up_time = float(-1)
815 else:
816 up_time = time.time() - start_time
818 parsed_info = {
819 'domid' : get_info('domid', str, ''),
820 'name' : get_info('name', str, '??'),
821 'state' : get_info('state', str, ''),
823 # VCPUs is the number online when the VM is up, or the number
824 # configured otherwise.
825 'vcpus' : get_info('online_vcpus', int,
826 get_info('vcpus', int, 0)),
827 'up_time' : up_time
828 }
830 # We're not supporting security stuff just yet via XenAPI
832 if serverType != SERVER_XEN_API:
833 from xen.util import security
834 parsed_info['seclabel'] = security.get_security_printlabel(info)
835 else:
836 parsed_info['seclabel'] = ""
838 if serverType == SERVER_XEN_API:
839 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
840 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
841 if sum(cpu_times.values()) > 0:
842 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
843 else:
844 parsed_info['cpu_time'] = 0
845 else:
846 parsed_info['mem'] = get_info('memory', int,0)
847 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
849 return parsed_info
851 def check_sched_type(sched):
852 if serverType == SERVER_XEN_API:
853 current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host())
854 else:
855 current = 'unknown'
856 for x in server.xend.node.info()[1:]:
857 if len(x) > 1 and x[0] == 'xen_scheduler':
858 current = x[1]
859 break
860 if sched != current:
861 err("Xen is running with the %s scheduler" % current)
862 sys.exit(1)
864 def parse_sedf_info(info):
865 def get_info(n, t, d):
866 return t(sxp.child_value(info, n, d))
868 return {
869 'domid' : get_info('domid', int, -1),
870 'period' : get_info('period', int, -1),
871 'slice' : get_info('slice', int, -1),
872 'latency' : get_info('latency', int, -1),
873 'extratime': get_info('extratime', int, -1),
874 'weight' : get_info('weight', int, -1),
875 }
877 def domid_match(domid, info):
878 return domid is None or domid == info['name'] or \
879 domid == str(info['domid'])
881 def xm_brief_list(doms):
882 print '%-40s %3s %5s %5s %10s %9s' % \
883 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
885 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
886 "%(cpu_time)8.1f"
888 for dom in doms:
889 d = parse_doms_info(dom)
890 print format % d
892 def xm_label_list(doms):
893 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
894 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
896 output = []
897 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
898 '%(cpu_time)8.1f %(seclabel)9s'
900 if serverType != SERVER_XEN_API:
901 from xen.util import security
903 for dom in doms:
904 d = parse_doms_info(dom)
906 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
907 if not d['seclabel']:
908 d['seclabel'] = 'ERROR'
909 elif security.active_policy in ['DEFAULT']:
910 d['seclabel'] = 'DEFAULT'
911 else:
912 d['seclabel'] = 'INACTIVE'
914 output.append((format % d, d['seclabel']))
916 #sort by labels
917 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
918 for line, label in output:
919 print line
922 def xm_vcpu_list(args):
923 if serverType == SERVER_XEN_API:
924 if args:
925 vm_refs = map(get_single_vm, args)
926 else:
927 vm_refs = server.xenapi.VM.get_all()
929 vm_records = dict(map(lambda vm_ref:
930 (vm_ref, server.xenapi.VM.get_record(
931 vm_ref)),
932 vm_refs))
934 vm_metrics = dict(map(lambda (ref, record):
935 (ref,
936 server.xenapi.VM_metrics.get_record(
937 record['metrics'])),
938 vm_records.items()))
940 dominfo = []
942 # vcpu_list doesn't list 'managed' domains
943 # when they are not running, so filter them out
945 vm_refs = [vm_ref
946 for vm_ref in vm_refs
947 if vm_records[vm_ref]["power_state"] != "Halted"]
949 for vm_ref in vm_refs:
950 info = ['domain',
951 ['domid', vm_records[vm_ref]['domid']],
952 ['name', vm_records[vm_ref]['name_label']],
953 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
957 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
958 def chk_flag(flag):
959 return vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
960 .find(flag) > -1 and 1 or 0
962 vcpu_info = ['vcpu',
963 ['number',
964 i],
965 ['online',
966 chk_flag("online")],
967 ['blocked',
968 chk_flag("blocked")],
969 ['running',
970 chk_flag("running")],
971 ['cpu_time',
972 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
973 ['cpu',
974 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
975 ['cpumap',
976 vm_metrics[vm_ref]['VCPUs_params']\
977 ['cpumap%i' % i].split(",")]]
979 info.append(vcpu_info)
981 dominfo.append(info)
982 else:
983 if args:
984 dominfo = map(server.xend.domain.getVCPUInfo, args)
985 else:
986 doms = server.xend.domains(False)
987 dominfo = map(server.xend.domain.getVCPUInfo, doms)
989 print '%-32s %3s %5s %5s %5s %9s %s' % \
990 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
992 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
993 ' %(cpu_time)8.1f %(cpumap)s'
995 for dom in dominfo:
996 def get_info(n):
997 return sxp.child_value(dom, n)
999 #
1000 # convert a list of integers into a list of pairs indicating
1001 # continuous sequences in the list:
1003 # [0,1,2,3] -> [(0,3)]
1004 # [1,2,4,5] -> [(1,2),(4,5)]
1005 # [0] -> [(0,0)]
1006 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1008 def list_to_rangepairs(cmap):
1009 cmap.sort()
1010 pairs = []
1011 x = y = 0
1012 for i in range(0,len(cmap)):
1013 try:
1014 if ((cmap[y+1] - cmap[i]) > 1):
1015 pairs.append((cmap[x],cmap[y]))
1016 x = y = i+1
1017 else:
1018 y = y + 1
1019 # if we go off the end, then just add x to y
1020 except IndexError:
1021 pairs.append((cmap[x],cmap[y]))
1023 return pairs
1026 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1028 def format_pairs(pairs):
1029 if not pairs:
1030 return "no cpus"
1031 out = ""
1032 for f,s in pairs:
1033 if (f==s):
1034 out += '%d'%f
1035 else:
1036 out += '%d-%d'%(f,s)
1037 out += ','
1038 # trim trailing ','
1039 return out[:-1]
1041 def format_cpumap(cpumap):
1042 cpumap = map(lambda x: int(x), cpumap)
1043 cpumap.sort()
1045 if serverType == SERVER_XEN_API:
1046 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1047 server.xenapi.session.get_this_host()))
1048 else:
1049 for x in server.xend.node.info()[1:]:
1050 if len(x) > 1 and x[0] == 'nr_cpus':
1051 nr_cpus = int(x[1])
1053 # normalize cpumap by modulus nr_cpus, and drop duplicates
1054 cpumap = dict.fromkeys(
1055 map(lambda x: x % nr_cpus, cpumap)).keys()
1056 if len(cpumap) == nr_cpus:
1057 return "any cpu"
1059 return format_pairs(list_to_rangepairs(cpumap))
1061 name = get_info('name')
1062 domid = int(get_info('domid'))
1064 for vcpu in sxp.children(dom, 'vcpu'):
1065 def vinfo(n, t):
1066 return t(sxp.child_value(vcpu, n))
1068 number = vinfo('number', int)
1069 cpu = vinfo('cpu', int)
1070 cpumap = format_cpumap(vinfo('cpumap', list))
1071 online = vinfo('online', int)
1072 cpu_time = vinfo('cpu_time', float)
1073 running = vinfo('running', int)
1074 blocked = vinfo('blocked', int)
1076 if online:
1077 c = str(cpu)
1078 if running:
1079 s = 'r'
1080 else:
1081 s = '-'
1082 if blocked:
1083 s += 'b'
1084 else:
1085 s += '-'
1086 s += '-'
1087 else:
1088 c = "-"
1089 s = "--p"
1091 print format % locals()
1093 def xm_start(args):
1094 arg_check(args, "start", 1, 2)
1096 try:
1097 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1098 except getopt.GetoptError, opterr:
1099 err(opterr)
1100 usage('start')
1102 paused = False
1103 for (k, v) in options:
1104 if k in ['-p', '--paused']:
1105 paused = True
1107 if len(params) != 1:
1108 err("Wrong number of parameters")
1109 usage('start')
1111 dom = params[0]
1112 if serverType == SERVER_XEN_API:
1113 server.xenapi.VM.start(get_single_vm(dom), paused)
1114 else:
1115 server.xend.domain.start(dom, paused)
1117 def xm_delete(args):
1118 arg_check(args, "delete", 1)
1119 dom = args[0]
1120 if serverType == SERVER_XEN_API:
1121 server.xenapi.VM.destroy(get_single_vm(dom))
1122 else:
1123 server.xend.domain.delete(dom)
1125 def xm_suspend(args):
1126 arg_check(args, "suspend", 1)
1127 dom = args[0]
1128 if serverType == SERVER_XEN_API:
1129 server.xenapi.VM.suspend(get_single_vm(dom))
1130 else:
1131 server.xend.domain.suspend(dom)
1133 def xm_resume(args):
1134 arg_check(args, "resume", 1, 2)
1136 try:
1137 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1138 except getopt.GetoptError, opterr:
1139 err(opterr)
1140 usage('resume')
1142 paused = False
1143 for (k, v) in options:
1144 if k in ['-p', '--paused']:
1145 paused = True
1147 if len(params) != 1:
1148 err("Wrong number of parameters")
1149 usage('resume')
1151 dom = params[0]
1152 if serverType == SERVER_XEN_API:
1153 server.xenapi.VM.resume(get_single_vm(dom), paused)
1154 else:
1155 server.xend.domain.resume(dom, paused)
1157 def xm_reboot(args):
1158 arg_check(args, "reboot", 1, 3)
1159 from xen.xm import shutdown
1160 shutdown.main(["shutdown", "-R"] + args)
1162 def xm_shutdown(args):
1163 arg_check(args, "shutdown", 1, 4)
1164 from xen.xm import shutdown
1165 shutdown.main(["shutdown"] + args)
1167 def xm_pause(args):
1168 arg_check(args, "pause", 1)
1169 dom = args[0]
1171 if serverType == SERVER_XEN_API:
1172 server.xenapi.VM.pause(get_single_vm(dom))
1173 else:
1174 server.xend.domain.pause(dom)
1176 def xm_unpause(args):
1177 arg_check(args, "unpause", 1)
1178 dom = args[0]
1180 if serverType == SERVER_XEN_API:
1181 server.xenapi.VM.unpause(get_single_vm(dom))
1182 else:
1183 server.xend.domain.unpause(dom)
1185 def xm_dump_core(args):
1186 live = False
1187 crash = False
1188 try:
1189 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1190 for (k, v) in options:
1191 if k in ('-L', '--live'):
1192 live = True
1193 if k in ('-C', '--crash'):
1194 crash = True
1196 if len(params) not in (1, 2):
1197 raise OptionError("Expects 1 or 2 argument(s)")
1198 except getopt.GetoptError, e:
1199 raise OptionError(str(e))
1201 dom = params[0]
1202 if len(params) == 2:
1203 filename = os.path.abspath(params[1])
1204 else:
1205 filename = None
1207 if not live:
1208 server.xend.domain.pause(dom)
1210 try:
1211 print "Dumping core of domain: %s ..." % str(dom)
1212 server.xend.domain.dump(dom, filename, live, crash)
1213 finally:
1214 if not live:
1215 server.xend.domain.unpause(dom)
1217 if crash:
1218 print "Destroying domain: %s ..." % str(dom)
1219 server.xend.domain.destroy(dom)
1221 def xm_rename(args):
1222 arg_check(args, "rename", 2)
1224 if serverType == SERVER_XEN_API:
1225 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1226 else:
1227 server.xend.domain.setName(args[0], args[1])
1229 def xm_importcommand(command, args):
1230 cmd = __import__(command, globals(), locals(), 'xen.xm')
1231 cmd.main([command] + args)
1234 #############################################################
1236 def xm_vcpu_pin(args):
1237 arg_check(args, "vcpu-pin", 3)
1239 def cpu_make_map(cpulist):
1240 cpus = []
1241 for c in cpulist.split(','):
1242 if c.find('-') != -1:
1243 (x,y) = c.split('-')
1244 for i in range(int(x),int(y)+1):
1245 cpus.append(int(i))
1246 else:
1247 # remove this element from the list
1248 if c[0] == '^':
1249 cpus = [x for x in cpus if x != int(c[1:])]
1250 else:
1251 cpus.append(int(c))
1252 cpus.sort()
1253 return cpus
1255 dom = args[0]
1256 vcpu = int(args[1])
1257 if args[2] == 'all':
1258 cpumap = cpu_make_map('0-63')
1259 else:
1260 cpumap = cpu_make_map(args[2])
1262 if serverType == SERVER_XEN_API:
1263 server.xenapi.VM.add_to_VCPUs_params_live(
1264 get_single_vm(dom), "cpumap%i" % vcpu, ",".join(cpumap))
1265 else:
1266 server.xend.domain.pincpu(dom, vcpu, cpumap)
1268 def xm_mem_max(args):
1269 arg_check(args, "mem-max", 2)
1271 dom = args[0]
1273 if serverType == SERVER_XEN_API:
1274 mem = int_unit(args[1], 'k') * 1024
1275 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1276 else:
1277 mem = int_unit(args[1], 'm')
1278 server.xend.domain.maxmem_set(dom, mem)
1280 def xm_mem_set(args):
1281 arg_check(args, "mem-set", 2)
1283 dom = args[0]
1285 if serverType == SERVER_XEN_API:
1286 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1287 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1288 mem_target)
1289 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1290 mem_target)
1291 else:
1292 mem_target = int_unit(args[1], 'm')
1293 server.xend.domain.setMemoryTarget(dom, mem_target)
1295 def xm_vcpu_set(args):
1296 arg_check(args, "vcpu-set", 2)
1298 dom = args[0]
1299 vcpus = int(args[1])
1301 if serverType == SERVER_XEN_API:
1302 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1303 else:
1304 server.xend.domain.setVCpuCount(dom, vcpus)
1306 def xm_destroy(args):
1307 arg_check(args, "destroy", 1)
1309 dom = args[0]
1311 if serverType == SERVER_XEN_API:
1312 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1313 else:
1314 server.xend.domain.destroy(dom)
1316 def xm_domid(args):
1317 arg_check(args, "domid", 1)
1319 name = args[0]
1321 if serverType == SERVER_XEN_API:
1322 print server.xenapi.VM.get_domid(get_single_vm(name))
1323 else:
1324 dom = server.xend.domain(name)
1325 print sxp.child_value(dom, 'domid')
1327 def xm_domname(args):
1328 arg_check(args, "domname", 1)
1330 name = args[0]
1332 if serverType == SERVER_XEN_API:
1333 print server.xenapi.VM.get_name_label(get_single_vm(name))
1334 else:
1335 dom = server.xend.domain(name)
1336 print sxp.child_value(dom, 'name')
1338 def xm_sched_sedf(args):
1339 xenapi_unsupported()
1341 def ns_to_ms(val):
1342 return float(val) * 0.000001
1344 def ms_to_ns(val):
1345 return (float(val) / 0.000001)
1347 def print_sedf(info):
1348 info['period'] = ns_to_ms(info['period'])
1349 info['slice'] = ns_to_ms(info['slice'])
1350 info['latency'] = ns_to_ms(info['latency'])
1351 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1352 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1354 check_sched_type('sedf')
1356 # we want to just display current info if no parameters are passed
1357 if len(args) == 0:
1358 domid = None
1359 else:
1360 # we expect at least a domain id (name or number)
1361 # and at most a domid up to 5 options with values
1362 arg_check(args, "sched-sedf", 1, 11)
1363 domid = args[0]
1364 # drop domid from args since get_opt doesn't recognize it
1365 args = args[1:]
1367 opts = {}
1368 try:
1369 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1370 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1371 except getopt.GetoptError, opterr:
1372 err(opterr)
1373 usage('sched-sedf')
1375 # convert to nanoseconds if needed
1376 for (k, v) in options:
1377 if k in ['-p', '--period']:
1378 opts['period'] = ms_to_ns(v)
1379 elif k in ['-s', '--slice']:
1380 opts['slice'] = ms_to_ns(v)
1381 elif k in ['-l', '--latency']:
1382 opts['latency'] = ms_to_ns(v)
1383 elif k in ['-e', '--extratime']:
1384 opts['extratime'] = v
1385 elif k in ['-w', '--weight']:
1386 opts['weight'] = v
1388 doms = filter(lambda x : domid_match(domid, x),
1389 [parse_doms_info(dom)
1390 for dom in getDomains(None, 'running')])
1391 if domid is not None and doms == []:
1392 err("Domain '%s' does not exist." % domid)
1393 usage('sched-sedf')
1395 # print header if we aren't setting any parameters
1396 if len(opts.keys()) == 0:
1397 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1398 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1399 'Extra','Weight')
1401 for d in doms:
1402 # fetch current values so as not to clobber them
1403 try:
1404 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1405 except xmlrpclib.Fault:
1406 # domain does not support sched-sedf?
1407 sedf_raw = {}
1409 sedf_info = parse_sedf_info(sedf_raw)
1410 sedf_info['name'] = d['name']
1411 # update values in case of call to set
1412 if len(opts.keys()) > 0:
1413 for k in opts.keys():
1414 sedf_info[k]=opts[k]
1416 # send the update, converting user input
1417 v = map(int, [sedf_info['period'], sedf_info['slice'],
1418 sedf_info['latency'],sedf_info['extratime'],
1419 sedf_info['weight']])
1420 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1421 if int(rv) != 0:
1422 err("Failed to set sedf parameters (rv=%d)."%(rv))
1424 # not setting values, display info
1425 else:
1426 print_sedf(sedf_info)
1428 def xm_sched_credit(args):
1429 """Get/Set options for Credit Scheduler."""
1431 check_sched_type('credit')
1433 try:
1434 opts, params = getopt.getopt(args, "d:w:c:",
1435 ["domain=", "weight=", "cap="])
1436 except getopt.GetoptError, opterr:
1437 err(opterr)
1438 usage('sched-credit')
1440 domid = None
1441 weight = None
1442 cap = None
1444 for o, a in opts:
1445 if o == "-d":
1446 domid = a
1447 elif o == "-w":
1448 weight = int(a)
1449 elif o == "-c":
1450 cap = int(a);
1452 doms = filter(lambda x : domid_match(domid, x),
1453 [parse_doms_info(dom)
1454 for dom in getDomains(None, 'running')])
1456 if weight is None and cap is None:
1457 if domid is not None and doms == []:
1458 err("Domain '%s' does not exist." % domid)
1459 usage('sched-credit')
1460 # print header if we aren't setting any parameters
1461 print '%-33s %-2s %-6s %-4s' % ('Name','ID','Weight','Cap')
1463 for d in doms:
1464 try:
1465 if serverType == SERVER_XEN_API:
1466 info = server.xenapi.VM_metrics.get_VCPUs_params(
1467 server.xenapi.VM.get_metrics(
1468 get_single_vm(d['name'])))
1469 else:
1470 info = server.xend.domain.sched_credit_get(d['domid'])
1471 except xmlrpclib.Fault:
1472 pass
1474 if 'weight' not in info or 'cap' not in info:
1475 # domain does not support sched-credit?
1476 info = {'weight': -1, 'cap': -1}
1478 info['weight'] = int(info['weight'])
1479 info['cap'] = int(info['cap'])
1481 info['name'] = d['name']
1482 info['domid'] = int(d['domid'])
1483 print( ("%(name)-32s %(domid)3d %(weight)6d %(cap)4d") % info)
1484 else:
1485 if domid is None:
1486 # place holder for system-wide scheduler parameters
1487 err("No domain given.")
1488 usage('sched-credit')
1490 if serverType == SERVER_XEN_API:
1491 server.xenapi.VM.add_to_VCPUs_params_live(
1492 get_single_vm(domid),
1493 "weight",
1494 weight)
1495 server.xenapi.VM.add_to_VCPUs_params_live(
1496 get_single_vm(domid),
1497 "cap",
1498 cap)
1499 else:
1500 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1501 if result != 0:
1502 err(str(result))
1504 def xm_info(args):
1505 arg_check(args, "info", 0)
1507 if serverType == SERVER_XEN_API:
1509 # Need to fake out old style xm info as people rely on parsing it
1511 host_record = server.xenapi.host.get_record(
1512 server.xenapi.session.get_this_host())
1514 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1516 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1518 info = {
1519 "host": host_record["name_label"],
1520 "release": host_record["software_version"]["release"],
1521 "version": host_record["software_version"]["version"],
1522 "machine": host_record["software_version"]["machine"],
1523 "nr_cpus": len(host_record["host_CPUs"]),
1524 "nr_nodes": host_record["cpu_configuration"]["nr_nodes"],
1525 "sockets_per_node": host_record["cpu_configuration"]["sockets_per_node"],
1526 "cores_per_socket": host_record["cpu_configuration"]["cores_per_socket"],
1527 "threads_per_core": host_record["cpu_configuration"]["threads_per_core"],
1528 "cpu_mhz": sum([int(host_cpu_record["speed"]) for host_cpu_record in host_cpu_records])
1529 / len(host_cpu_records),
1530 "hw_caps": host_cpu_records[0]["features"],
1531 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1532 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1533 "xen_major": host_record["software_version"]["xen_major"],
1534 "xen_minor": host_record["software_version"]["xen_minor"],
1535 "xen_extra": host_record["software_version"]["xen_extra"],
1536 "xen_caps": " ".join(host_record["capabilities"]),
1537 "xen_scheduler": host_record["sched_policy"],
1538 "xen_pagesize": host_record["other_config"]["xen_pagesize"],
1539 "platform_params": host_record["other_config"]["platform_params"],
1540 "xen_changeset": host_record["software_version"]["xen_changeset"],
1541 "cc_compiler": host_record["software_version"]["cc_compiler"],
1542 "cc_compile_by": host_record["software_version"]["cc_compile_by"],
1543 "cc_compile_domain": host_record["software_version"]["cc_compile_domain"],
1544 "cc_compile_date": host_record["software_version"]["cc_compile_date"],
1545 "xend_config_format":host_record["software_version"]["xend_config_format"]
1548 sorted = info.items()
1549 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1551 for (k, v) in sorted:
1552 print "%-23s:" % k, v
1553 else:
1554 info = server.xend.node.info()
1555 for x in info[1:]:
1556 if len(x) < 2:
1557 print "%-23s: (none)" % x[0]
1558 else:
1559 print "%-23s:" % x[0], x[1]
1561 def xm_console(args):
1562 arg_check(args, "console", 1, 2)
1564 quiet = False;
1566 try:
1567 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1568 except getopt.GetoptError, opterr:
1569 err(opterr)
1570 usage('console')
1572 for (k, v) in options:
1573 if k in ['-q', '--quiet']:
1574 quiet = True
1575 else:
1576 assert False
1578 if len(params) != 1:
1579 err('No domain given')
1580 usage('console')
1582 dom = params[0]
1584 try:
1585 if serverType == SERVER_XEN_API:
1586 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1587 else:
1588 info = server.xend.domain(dom)
1589 domid = int(sxp.child_value(info, 'domid', '-1'))
1590 except:
1591 if quiet:
1592 sys.exit(1)
1593 else:
1594 raise
1596 if domid == -1:
1597 if quiet:
1598 sys.exit(1)
1599 else:
1600 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1602 console.execConsole(domid)
1605 def xm_uptime(args):
1606 short_mode = 0
1608 try:
1609 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1610 except getopt.GetoptError, opterr:
1611 err(opterr)
1612 usage('uptime')
1614 for (k, v) in options:
1615 if k in ['-s', '--short']:
1616 short_mode = 1
1618 doms = getDomains(params, 'running')
1620 if short_mode == 0:
1621 print 'Name ID Uptime'
1623 for dom in doms:
1624 d = parse_doms_info(dom)
1625 if int(d['domid']) > 0:
1626 uptime = int(round(d['up_time']))
1627 else:
1628 f=open('/proc/uptime', 'r')
1629 upfile = f.read()
1630 uptime = int(round(float(upfile.split(' ')[0])))
1631 f.close()
1633 days = int(uptime / 86400)
1634 uptime -= (days * 86400)
1635 hours = int(uptime / 3600)
1636 uptime -= (hours * 3600)
1637 minutes = int(uptime / 60)
1638 uptime -= (minutes * 60)
1639 seconds = uptime
1641 upstring = ""
1642 if days > 0:
1643 upstring += str(days) + " day"
1644 if days > 1:
1645 upstring += "s"
1646 upstring += ", "
1647 upstring += '%(hours)2d:%(minutes)02d' % vars()
1649 if short_mode:
1650 now = datetime.datetime.now()
1651 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1652 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1653 else:
1654 upstring += ':%(seconds)02d' % vars()
1655 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1657 print upstring
1659 def xm_sysrq(args):
1660 arg_check(args, "sysrq", 2)
1661 dom = args[0]
1662 req = args[1]
1663 if serverType == SERVER_XEN_API:
1664 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1665 else:
1666 server.xend.domain.send_sysrq(dom, req)
1668 def xm_trigger(args):
1669 vcpu = 0
1671 arg_check(args, "trigger", 2, 3)
1672 dom = args[0]
1673 trigger = args[1]
1674 if len(args) == 3:
1675 vcpu = int(args[2])
1677 if serverType == SERVER_XEN_API:
1678 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1679 else:
1680 server.xend.domain.send_trigger(dom, trigger, vcpu)
1682 def xm_debug_keys(args):
1683 arg_check(args, "debug-keys", 1)
1685 keys = str(args[0])
1687 if serverType == SERVER_XEN_API:
1688 server.xenapi.host.send_debug_keys(
1689 server.xenapi.session.get_this_host(),
1690 keys)
1691 else:
1692 server.xend.node.send_debug_keys(keys)
1694 def xm_top(args):
1695 arg_check(args, "top", 0)
1697 os.execvp('xentop', ['xentop'])
1699 def xm_dmesg(args):
1700 arg_check(args, "dmesg", 0, 1)
1702 try:
1703 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1704 except getopt.GetoptError, opterr:
1705 err(opterr)
1706 usage('dmesg')
1708 use_clear = 0
1709 for (k, v) in options:
1710 if k in ['-c', '--clear']:
1711 use_clear = 1
1713 if len(params) :
1714 err("No parameter required")
1715 usage('dmesg')
1717 if serverType == SERVER_XEN_API:
1718 host = server.xenapi.session.get_this_host()
1719 if use_clear:
1720 print server.xenapi.host.dmesg_clear(host),
1721 else:
1722 print server.xenapi.host.dmesg(host),
1723 else:
1724 if not use_clear:
1725 print server.xend.node.dmesg.info(),
1726 else:
1727 print server.xend.node.dmesg.clear(),
1729 def xm_log(args):
1730 arg_check(args, "log", 0)
1732 if serverType == SERVER_XEN_API:
1733 print server.xenapi.host.get_log(
1734 server.xenapi.session.get_this_host())
1735 else:
1736 print server.xend.node.log()
1738 def xm_serve(args):
1739 if serverType == SERVER_XEN_API:
1740 print "Not supported with XenAPI"
1741 sys.exit(-1)
1743 arg_check(args, "serve", 0)
1745 from fcntl import fcntl, F_SETFL
1747 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1748 s.connect(XendClient.XML_RPC_SOCKET)
1749 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1751 while True:
1752 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1753 if s in iwtd:
1754 data = s.recv(4096)
1755 if len(data) > 0:
1756 sys.stdout.write(data)
1757 sys.stdout.flush()
1758 else:
1759 break
1760 if sys.stdin in iwtd:
1761 data = sys.stdin.read(4096)
1762 if len(data) > 0:
1763 s.sendall(data)
1764 else:
1765 break
1766 s.close()
1768 def parse_dev_info(info):
1769 def get_info(n, t, d):
1770 i = 0
1771 while i < len(info):
1772 if (info[i][0] == n):
1773 return t(info[i][1])
1774 i = i + 1
1775 return t(d)
1776 return {
1777 #common
1778 'backend-id' : get_info('backend-id', int, -1),
1779 'handle' : get_info('handle', int, 0),
1780 'state' : get_info('state', int, -1),
1781 'be-path' : get_info('backend', str, '??'),
1782 'event-ch' : get_info('event-channel',int, -1),
1783 #network specific
1784 'virtual-device' : get_info('virtual-device', str, '??'),
1785 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1786 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1787 'mac' : get_info('mac', str, '??'),
1788 #block-device specific
1789 'ring-ref' : get_info('ring-ref', int, -1),
1792 def arg_check_for_resource_list(args, name):
1793 use_long = 0
1794 try:
1795 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1796 except getopt.GetoptError, opterr:
1797 err(opterr)
1798 sys.exit(1)
1800 for (k, v) in options:
1801 if k in ['-l', '--long']:
1802 use_long = 1
1804 if len(params) == 0:
1805 print 'No domain parameter given'
1806 usage(name)
1807 if len(params) > 1:
1808 print 'No multiple domain parameters allowed'
1809 usage(name)
1811 return (use_long, params)
1813 def xm_network_list(args):
1814 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1816 dom = params[0]
1818 if serverType == SERVER_XEN_API:
1819 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1820 vif_properties = \
1821 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1822 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
1823 zip(range(len(vif_properties)), vif_properties))
1824 else:
1825 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1827 if use_long:
1828 map(PrettyPrint.prettyprint, devs)
1829 else:
1830 hdr = 0
1831 for x in devs:
1832 if hdr == 0:
1833 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1834 hdr = 1
1835 ni = parse_dev_info(x[1])
1836 ni['idx'] = int(x[0])
1837 print ("%(idx)-3d "
1838 "%(backend-id)-3d"
1839 "%(mac)-17s "
1840 "%(handle)-3d "
1841 "%(state)-3d "
1842 "%(event-ch)-3d "
1843 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1844 "%(be-path)-30s "
1845 % ni)
1847 def xm_block_list(args):
1848 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1850 dom = params[0]
1852 if serverType == SERVER_XEN_API:
1853 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1854 vbd_properties = \
1855 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
1856 vbd_devs = \
1857 map(server.xenapi.VBD.get_device, vbd_refs)
1858 vbd_devids = \
1859 map(blkdev_name_to_number, vbd_devs)
1860 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
1861 zip(vbd_devids, vbd_properties))
1862 else:
1863 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1865 if use_long:
1866 map(PrettyPrint.prettyprint, devs)
1867 else:
1868 hdr = 0
1869 for x in devs:
1870 if hdr == 0:
1871 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1872 hdr = 1
1873 ni = parse_dev_info(x[1])
1874 ni['idx'] = int(x[0])
1875 print ("%(idx)-3d "
1876 "%(backend-id)-3d "
1877 "%(handle)-3d "
1878 "%(state)-3d "
1879 "%(event-ch)-3d "
1880 "%(ring-ref)-5d "
1881 "%(be-path)-30s "
1882 % ni)
1884 def xm_vtpm_list(args):
1885 xenapi_unsupported()
1886 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1888 dom = params[0]
1889 if use_long:
1890 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1891 map(PrettyPrint.prettyprint, devs)
1892 else:
1893 hdr = 0
1894 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1895 if hdr == 0:
1896 print 'Idx BE handle state evt-ch ring-ref BE-path'
1897 hdr = 1
1898 ni = parse_dev_info(x[1])
1899 ni['idx'] = int(x[0])
1900 print ("%(idx)-3d "
1901 "%(backend-id)-3d "
1902 "%(handle)-3d "
1903 "%(state)-3d "
1904 "%(event-ch)-3d "
1905 "%(ring-ref)-5d "
1906 "%(be-path)-30s "
1907 % ni)
1910 def parse_block_configuration(args):
1911 dom = args[0]
1913 if args[1].startswith('tap:'):
1914 cls = 'tap'
1915 else:
1916 cls = 'vbd'
1918 vbd = [cls,
1919 ['uname', args[1]],
1920 ['dev', args[2]],
1921 ['mode', args[3]]]
1922 if len(args) == 5:
1923 vbd.append(['backend', args[4]])
1925 if serverType != SERVER_XEN_API:
1926 # verify that policy permits attaching this resource
1927 from xen.util import security
1929 if security.on():
1930 dominfo = server.xend.domain(dom)
1931 label = security.get_security_printlabel(dominfo)
1932 else:
1933 label = None
1935 security.res_security_check(args[1], label)
1937 return (dom, vbd)
1940 def xm_block_attach(args):
1941 arg_check(args, 'block-attach', 4, 5)
1943 if serverType == SERVER_XEN_API:
1944 dom = args[0]
1945 uname = args[1]
1946 dev = args[2]
1947 mode = args[3]
1949 # First create new VDI
1950 vdi_record = {
1951 "name_label": "vdi" + str(uname.__hash__()),
1952 "name_description": "",
1953 "SR": get_default_SR(),
1954 "virtual_size": 0,
1955 "sector_size": 512,
1956 "type": "system",
1957 "sharable": False,
1958 "read_only": mode!="w",
1959 "other_config": {"location": uname}
1962 vdi_ref = server.xenapi.VDI.create(vdi_record)
1964 # Now create new VBD
1966 vbd_record = {
1967 "VM": get_single_vm(dom),
1968 "VDI": vdi_ref,
1969 "device": dev,
1970 "bootable": True,
1971 "mode": mode=="w" and "RW" or "RO",
1972 "type": "Disk",
1973 "qos_algorithm_type": "",
1974 "qos_algorithm_params": {}
1977 server.xenapi.VBD.create(vbd_record)
1979 else:
1980 (dom, vbd) = parse_block_configuration(args)
1981 server.xend.domain.device_create(dom, vbd)
1984 def xm_block_configure(args):
1985 arg_check(args, 'block-configure', 4, 5)
1987 (dom, vbd) = parse_block_configuration(args)
1988 server.xend.domain.device_configure(dom, vbd)
1991 def xm_network_attach(args):
1992 arg_check(args, 'network-attach', 1, 10)
1994 dom = args[0]
1995 vif = ['vif']
1996 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
1997 'backend', 'vifname', 'rate', 'model']
1999 if serverType == SERVER_XEN_API:
2000 vif_record = {
2001 "device": "eth0",
2002 "network": get_default_Network(),
2003 "VM": get_single_vm(dom),
2004 "MAC": "",
2005 "MTU": "",
2006 "qos_algorithm_type": "",
2007 "qos_algorithm_params": {},
2008 "other_config": {}
2011 def set(keys, val):
2012 record = vif_record
2013 for key in keys[:-1]:
2014 record = record[key]
2015 record[keys[-1]] = val
2017 def get_net_from_bridge(bridge):
2018 raise "Not supported just yet"
2020 vif_conv = {
2021 'type':
2022 lambda x: None,
2023 'mac':
2024 lambda x: set(['MAC'], x),
2025 'bridge':
2026 lambda x: set(['network'], get_net_from_bridge(x)),
2027 'ip':
2028 lambda x: set(['other_config', 'ip'], x),
2029 'script':
2030 lambda x: set(['other_config', 'script'], x),
2031 'backend':
2032 lambda x: set(['other_config', 'backend'], x),
2033 'vifname':
2034 lambda x: set(['device'], x),
2035 'rate':
2036 lambda x: set(['qos_algorithm_params', 'rate'], x),
2037 'model':
2038 lambda x: None
2041 for a in args[1:]:
2042 vif_param = a.split("=")
2043 if len(vif_param) != 2 or vif_param[1] == '' or \
2044 vif_param[0] not in vif_params:
2045 err("Invalid argument: %s" % a)
2046 usage('network-attach')
2047 else:
2048 vif_conv[vif_param[0]](vif_param[1])
2050 print str(vif_record)
2051 server.xenapi.VIF.create(vif_record)
2052 else:
2053 for a in args[1:]:
2054 vif_param = a.split("=")
2055 if len(vif_param) != 2 or vif_param[1] == '' or \
2056 vif_param[0] not in vif_params:
2057 err("Invalid argument: %s" % a)
2058 usage('network-attach')
2059 vif.append(vif_param)
2060 server.xend.domain.device_create(dom, vif)
2063 def detach(args, command, deviceClass):
2064 arg_check(args, command, 2, 3)
2066 dom = args[0]
2067 dev = args[1]
2068 try:
2069 force = args[2]
2070 if (force != "--force") and (force != "-f"):
2071 print "Ignoring option %s"%(force)
2072 force = None
2073 except IndexError:
2074 force = None
2076 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
2079 def xm_block_detach(args):
2080 if serverType == SERVER_XEN_API:
2081 arg_check(args, "xm_block_detach", 2, 3)
2082 dom = args[0]
2083 dev = args[1]
2084 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2085 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2086 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2087 if len(vbd_refs) > 0:
2088 vbd_ref = vbd_refs[0]
2089 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2091 server.xenapi.VBD.destroy(vbd_ref)
2093 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2094 server.xenapi.VDI.destroy(vdi_ref)
2095 else:
2096 raise OptionError("Cannot find device '%s' in domain '%s'"
2097 % (dev,dom))
2098 else:
2099 try:
2100 detach(args, 'block-detach', 'vbd')
2101 return
2102 except:
2103 pass
2104 detach(args, 'block-detach', 'tap')
2106 def xm_network_detach(args):
2107 if serverType == SERVER_XEN_API:
2108 arg_check(args, "xm_block_detach", 2, 3)
2109 dom = args[0]
2110 devid = args[1]
2111 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2112 vif_refs = [vif_ref for vif_ref in vif_refs
2113 if server.xenapi.VIF.\
2114 get_runtime_properties(vif_ref)["handle"] == devid]
2115 if len(vif_refs) > 0:
2116 vif_ref = vif_refs[0]
2118 server.xenapi.VIF.destroy(vif_ref)
2119 else:
2120 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2121 else:
2122 detach(args, 'network-detach', 'vif')
2125 def xm_vnet_list(args):
2126 xenapi_unsupported()
2127 try:
2128 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2129 except getopt.GetoptError, opterr:
2130 err(opterr)
2131 usage('vnet-list')
2133 use_long = 0
2134 for (k, v) in options:
2135 if k in ['-l', '--long']:
2136 use_long = 1
2138 if params:
2139 use_long = 1
2140 vnets = params
2141 else:
2142 vnets = server.xend_vnets()
2144 for vnet in vnets:
2145 try:
2146 if use_long:
2147 info = server.xend_vnet(vnet)
2148 PrettyPrint.prettyprint(info)
2149 else:
2150 print vnet
2151 except Exception, ex:
2152 print vnet, ex
2154 def xm_vnet_create(args):
2155 xenapi_unsupported()
2156 arg_check(args, "vnet-create", 1)
2157 conf = args[0]
2158 if not os.access(conf, os.R_OK):
2159 print "File not found: %s" % conf
2160 sys.exit(1)
2162 server.xend_vnet_create(conf)
2164 def xm_vnet_delete(args):
2165 xenapi_unsupported()
2166 arg_check(args, "vnet-delete", 1)
2167 vnet = args[0]
2168 server.xend_vnet_delete(vnet)
2170 commands = {
2171 "shell": xm_shell,
2172 # console commands
2173 "console": xm_console,
2174 # xenstat commands
2175 "top": xm_top,
2176 # domain commands
2177 "delete": xm_delete,
2178 "destroy": xm_destroy,
2179 "domid": xm_domid,
2180 "domname": xm_domname,
2181 "dump-core": xm_dump_core,
2182 "reboot": xm_reboot,
2183 "rename": xm_rename,
2184 "restore": xm_restore,
2185 "resume": xm_resume,
2186 "save": xm_save,
2187 "shutdown": xm_shutdown,
2188 "start": xm_start,
2189 "sysrq": xm_sysrq,
2190 "trigger": xm_trigger,
2191 "uptime": xm_uptime,
2192 "suspend": xm_suspend,
2193 "list": xm_list,
2194 # memory commands
2195 "mem-max": xm_mem_max,
2196 "mem-set": xm_mem_set,
2197 # cpu commands
2198 "vcpu-pin": xm_vcpu_pin,
2199 "vcpu-list": xm_vcpu_list,
2200 "vcpu-set": xm_vcpu_set,
2201 # special
2202 "pause": xm_pause,
2203 "unpause": xm_unpause,
2204 # host commands
2205 "debug-keys": xm_debug_keys,
2206 "dmesg": xm_dmesg,
2207 "info": xm_info,
2208 "log": xm_log,
2209 "serve": xm_serve,
2210 # scheduler
2211 "sched-sedf": xm_sched_sedf,
2212 "sched-credit": xm_sched_credit,
2213 # block
2214 "block-attach": xm_block_attach,
2215 "block-detach": xm_block_detach,
2216 "block-list": xm_block_list,
2217 "block-configure": xm_block_configure,
2218 # network
2219 "network-attach": xm_network_attach,
2220 "network-detach": xm_network_detach,
2221 "network-list": xm_network_list,
2222 # vnet
2223 "vnet-list": xm_vnet_list,
2224 "vnet-create": xm_vnet_create,
2225 "vnet-delete": xm_vnet_delete,
2226 # vtpm
2227 "vtpm-list": xm_vtpm_list,
2230 ## The commands supported by a separate argument parser in xend.xm.
2231 IMPORTED_COMMANDS = [
2232 'create',
2233 'new',
2234 'migrate',
2235 'labels',
2236 'cfgbootpolicy',
2237 'makepolicy',
2238 'loadpolicy',
2239 'dumppolicy',
2240 'addlabel',
2241 'rmlabel',
2242 'getlabel',
2243 'dry-run',
2244 'resources',
2247 for c in IMPORTED_COMMANDS:
2248 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2250 aliases = {
2251 "balloon": "mem-set",
2252 "set-vcpus": "vcpu-set",
2253 "vif-list": "network-list",
2254 "vbd-create": "block-attach",
2255 "vbd-destroy": "block-detach",
2256 "vbd-list": "block-list",
2260 def xm_lookup_cmd(cmd):
2261 if commands.has_key(cmd):
2262 return commands[cmd]
2263 elif aliases.has_key(cmd):
2264 deprecated(cmd,aliases[cmd])
2265 return commands[aliases[cmd]]
2266 elif cmd == 'help':
2267 longHelp()
2268 sys.exit(0)
2269 else:
2270 # simulate getopt's prefix matching behaviour
2271 if len(cmd) > 1:
2272 same_prefix_cmds = [commands[c] for c in commands.keys() \
2273 if c[:len(cmd)] == cmd]
2274 # only execute if there is only 1 match
2275 if len(same_prefix_cmds) == 1:
2276 return same_prefix_cmds[0]
2277 return None
2279 def deprecated(old,new):
2280 print >>sys.stderr, (
2281 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2283 def main(argv=sys.argv):
2284 if len(argv) < 2:
2285 usage()
2287 # intercept --help(-h) and output our own help
2288 for help in ['--help', '-h']:
2289 if help in argv[1:]:
2290 if help == argv[1]:
2291 longHelp()
2292 sys.exit(0)
2293 else:
2294 usage(argv[1])
2296 cmd_name = argv[1]
2297 cmd = xm_lookup_cmd(cmd_name)
2298 if cmd:
2299 # strip off prog name and subcmd
2300 args = argv[2:]
2301 _, rc = _run_cmd(cmd, cmd_name, args)
2302 sys.exit(rc)
2303 else:
2304 err('Subcommand %s not found!' % cmd_name)
2305 usage()
2307 def _run_cmd(cmd, cmd_name, args):
2308 global server
2310 try:
2311 if server is None:
2312 if serverType == SERVER_XEN_API:
2313 server = XenAPI.Session(serverURI)
2314 username, password = parseAuthentication()
2315 server.login_with_password(username, password)
2316 def logout():
2317 try:
2318 server.xenapi.session.logout()
2319 except:
2320 pass
2321 atexit.register(logout)
2322 else:
2323 server = ServerProxy(serverURI)
2325 return True, cmd(args)
2326 except socket.error, ex:
2327 if os.geteuid() != 0:
2328 err("Most commands need root access. Please try again as root.")
2329 else:
2330 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2331 except KeyboardInterrupt:
2332 print "Interrupted."
2333 return True, ''
2334 except IOError, ex:
2335 if os.geteuid() != 0:
2336 err("Most commands need root access. Please try again as root.")
2337 else:
2338 err("Unable to connect to xend: %s." % ex[1])
2339 except SystemExit, code:
2340 return code == 0, code
2341 except XenAPI.Failure, exn:
2342 for line in [''] + wrap(str(exn), 80) + ['']:
2343 print >>sys.stderr, line
2344 except xmlrpclib.Fault, ex:
2345 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2346 err("Domain '%s' does not exist." % ex.faultString)
2347 else:
2348 err(ex.faultString)
2349 _usage(cmd_name)
2350 except xmlrpclib.ProtocolError, ex:
2351 if ex.errcode == -1:
2352 print >>sys.stderr, (
2353 "Xend has probably crashed! Invalid or missing HTTP "
2354 "status code.")
2355 else:
2356 print >>sys.stderr, (
2357 "Xend has probably crashed! ProtocolError(%d, %s)." %
2358 (ex.errcode, ex.errmsg))
2359 except (ValueError, OverflowError):
2360 err("Invalid argument.")
2361 _usage(cmd_name)
2362 except OptionError, e:
2363 err(str(e))
2364 _usage(cmd_name)
2365 print e.usage
2366 except XenAPIUnsupportedException, e:
2367 err(str(e))
2368 except Exception, e:
2369 if serverType != SERVER_XEN_API:
2370 from xen.util import security
2371 if isinstance(e, security.ACMError):
2372 err(str(e))
2373 return False, 1
2374 else:
2375 print "Unexpected error:", sys.exc_info()[0]
2376 print
2377 print "Please report to xen-devel@lists.xensource.com"
2378 raise
2380 return False, 1
2382 if __name__ == "__main__":
2383 main()