ia64/xen-unstable

view tools/python/xen/xm/main.py @ 18516:79459028af39

xm list: Return unique exit code for non-existent domain

This patch will make xm return a exit code of 3 if `xm list
<non_existant_domain>` is done rather than the generic code of 1. I
used 3 because XendClient had a macro setup pointing
ERROR_INVALID_DOMAIN to 3.

From: "Shaun R." <mailinglists@unix-scripts.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Sep 18 10:41:41 2008 +0100 (2008-09-18)
parents fba8dca321c2
children ddf62f696111
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 time
36 import datetime
37 from select import select
38 import xml.dom.minidom
39 from xen.util.blkif import blkdev_name_to_number
40 from xen.util import vscsi_util
41 from xen.util.pci import *
43 import warnings
44 warnings.filterwarnings('ignore', category=FutureWarning)
46 from xen.xend import PrettyPrint
47 from xen.xend import sxp
48 from xen.xend import XendClient
49 from xen.xend.XendConstants import *
51 from xen.xm.opts import OptionError, Opts, wrap, set_true
52 from xen.xm import console
53 from xen.util.xmlrpcclient import ServerProxy
54 import xen.util.xsm.xsm as security
55 from xen.util.xsm.xsm import XSMError
56 from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
58 import XenAPI
60 import xen.lowlevel.xc
61 xc = xen.lowlevel.xc.xc()
63 import inspect
64 from xen.xend import XendOptions
65 xoptions = XendOptions.instance()
67 import signal
68 signal.signal(signal.SIGINT, signal.SIG_DFL)
70 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
71 # getopt.getopt if gnu_getopt is not available. This will mean that options
72 # may only be specified before positional arguments.
73 if not hasattr(getopt, 'gnu_getopt'):
74 getopt.gnu_getopt = getopt.getopt
76 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
77 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
79 # Supported types of server
80 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
81 SERVER_XEN_API = 'Xen-API'
83 # General help message
85 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
86 "Control, list, and manipulate Xen guest instances.\n"
88 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
89 'For more help on \'xm\' see the xm(1) man page.\n' \
90 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
91 ' man page.\n'
93 # Help strings are indexed by subcommand name in this way:
94 # 'subcommand': (argstring, description)
96 SUBCOMMAND_HELP = {
97 # common commands
99 'shell' : ('', 'Launch an interactive shell.'),
101 'console' : ('[-q|--quiet] <Domain>',
102 'Attach to <Domain>\'s console.'),
103 'vncviewer' : ('[--[vncviewer-]autopass] <Domain>',
104 'Attach to <Domain>\'s VNC server.'),
105 'create' : ('<ConfigFile> [options] [vars]',
106 'Create a domain based on <ConfigFile>.'),
107 'destroy' : ('<Domain>',
108 'Terminate a domain immediately.'),
109 'help' : ('', 'Display this message.'),
110 'list' : ('[options] [Domain, ...]',
111 'List information about all/some domains.'),
112 'mem-max' : ('<Domain> <Mem>',
113 'Set the maximum amount reservation for a domain.'),
114 'mem-set' : ('<Domain> <Mem>',
115 'Set the current memory usage for a domain.'),
116 'migrate' : ('<Domain> <Host>',
117 'Migrate a domain to another machine.'),
118 'pause' : ('<Domain>', 'Pause execution of a domain.'),
119 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
120 'reset' : ('<Domain>', 'Reset a domain.'),
121 'restore' : ('<CheckpointFile> [-p]',
122 'Restore a domain from a saved state.'),
123 'save' : ('[-c] <Domain> <CheckpointFile>',
124 'Save a domain state to restore later.'),
125 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
126 'top' : ('', 'Monitor a host and the domains in real time.'),
127 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
128 'uptime' : ('[-s] [Domain, ...]',
129 'Print uptime for all/some domains.'),
131 # Life cycle xm commands
132 'new' : ('<ConfigFile> [options] [vars]',
133 'Adds a domain to Xend domain management'),
134 'delete' : ('<DomainName>',
135 'Remove a domain from Xend domain management.'),
136 'start' : ('<DomainName>', 'Start a Xend managed domain'),
137 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
138 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
140 # less used commands
142 'dmesg' : ('[-c|--clear]',
143 'Read and/or clear Xend\'s message buffer.'),
144 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
145 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
146 'dump-core' : ('[-L|--live] [-C|--crash] [-R|--reset] <Domain> [Filename]',
147 'Dump core for a specific domain.'),
148 'info' : ('[-c|--config]', 'Get information about Xen host.'),
149 'log' : ('', 'Print Xend log'),
150 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
151 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
152 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
153 'Get/set credit scheduler parameters.'),
154 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
155 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
156 'trigger' : ('<Domain> <nmi|reset|init|s3resume> [<VCPU>]',
157 'Send a trigger to a domain.'),
158 'vcpu-list' : ('[Domain, ...]',
159 'List the VCPUs for all/some domains.'),
160 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
161 'Set which CPUs a VCPU can use.'),
162 'vcpu-set' : ('<Domain> <vCPUs>',
163 'Set the number of active VCPUs for allowed for the'
164 ' domain.'),
166 # device commands
168 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
169 'Create a new virtual block device.'),
170 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
171 'Change block device configuration'),
172 'block-detach' : ('<Domain> <DevId> [-f|--force]',
173 'Destroy a domain\'s virtual block device.'),
174 'block-list' : ('<Domain> [--long]',
175 'List virtual block devices for a domain.'),
176 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
177 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
178 '[vifname=<name>] [rate=<rate>] [model=<model>]'
179 '[accel=<accel>]',
180 'Create a new virtual network device.'),
181 'network-detach': ('<Domain> <DevId> [-f|--force]',
182 'Destroy a domain\'s virtual network device.'),
183 'network-list' : ('<Domain> [--long]',
184 'List virtual network interfaces for a domain.'),
185 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
186 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
187 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
188 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
189 'pci-attach' : ('<Domain> <domain:bus:slot.func> [virtual slot]',
190 'Insert a new pass-through pci device.'),
191 'pci-detach' : ('<Domain> <domain:bus:slot.func>',
192 'Remove a domain\'s pass-through pci device.'),
193 'pci-list' : ('<Domain>',
194 'List pass-through pci devices for a domain.'),
195 'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
196 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
197 'Attach a new SCSI device.'),
198 'scsi-detach' : ('<Domain> <VirtDevice>',
199 'Detach a specified SCSI device.'),
200 'scsi-list' : ('<Domain> [--long]',
201 'List all SCSI devices currently attached.'),
203 # security
205 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
206 ' [<policy>]',
207 'Add security label to domain.'),
208 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
209 'Remove a security label from domain.'),
210 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
211 'Show security label for domain or resource.'),
212 'dry-run' : ('<ConfigFile>',
213 'Test if a domain can access its resources.'),
214 'resources' : ('', 'Show info for each labeled resource.'),
215 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
216 'setpolicy' : ('<policytype> <policyfile> [options]',
217 'Set the policy of the system.'),
218 'resetpolicy' : ('',
219 'Set the policy of the system to the default policy.'),
220 'getpolicy' : ('[options]', 'Get the policy of the system.'),
221 'labels' : ('[policy] [type=dom|res|any]',
222 'List <type> labels for (active) policy.'),
223 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
224 }
226 SUBCOMMAND_OPTIONS = {
227 'sched-sedf': (
228 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
229 ('-s [MS]', '--slice[=MS]' ,
230 'Worst-case execution time(ms). (slice < period)'),
231 ('-l [MS]', '--latency[=MS]',
232 'Scaled period (ms) when domain performs heavy I/O'),
233 ('-e [FLAG]', '--extra[=FLAG]',
234 'Flag (0 or 1) controls if domain can run in extra time.'),
235 ('-w [FLOAT]', '--weight[=FLOAT]',
236 'CPU Period/slice (do not set with --period/--slice)'),
237 ),
238 'sched-credit': (
239 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
240 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
241 ('-c CAP', '--cap=CAP', 'Cap (int)'),
242 ),
243 'list': (
244 ('-l', '--long', 'Output all VM details in SXP'),
245 ('', '--label', 'Include security labels'),
246 ('', '--state=<state>', 'Select only VMs with the specified state'),
247 ),
248 'console': (
249 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
250 ),
251 'vncviewer': (
252 ('', '--autopass', 'Pass VNC password to viewer via stdin and -autopass'),
253 ('', '--vncviewer-autopass', '(consistency alias for --autopass)'),
254 ),
255 'dmesg': (
256 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
257 ),
258 'vnet-list': (
259 ('-l', '--long', 'List Vnets as SXP'),
260 ),
261 'network-list': (
262 ('-l', '--long', 'List resources as SXP'),
263 ),
264 'dump-core': (
265 ('-L', '--live', 'Dump core without pausing the domain'),
266 ('-C', '--crash', 'Crash domain after dumping core'),
267 ('-R', '--reset', 'Reset domain after dumping core'),
268 ),
269 'start': (
270 ('-p', '--paused', 'Do not unpause domain after starting it'),
271 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
272 ('', '--vncviewer', 'Connect to display via VNC after the domain is created'),
273 ('', '--vncviewer-autopass', 'Pass VNC password to viewer via stdin and -autopass'),
274 ),
275 'resume': (
276 ('-p', '--paused', 'Do not unpause domain after resuming it'),
277 ),
278 'save': (
279 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
280 ),
281 'restore': (
282 ('-p', '--paused', 'Do not unpause domain after restoring it'),
283 ),
284 'info': (
285 ('-c', '--config', 'List Xend configuration parameters'),
286 ),
287 }
289 common_commands = [
290 "console",
291 "vncviewer",
292 "create",
293 "new",
294 "delete",
295 "destroy",
296 "dump-core",
297 "help",
298 "list",
299 "mem-set",
300 "migrate",
301 "pause",
302 "reboot",
303 "reset",
304 "restore",
305 "resume",
306 "save",
307 "shell",
308 "shutdown",
309 "start",
310 "suspend",
311 "top",
312 "unpause",
313 "uptime",
314 "vcpu-set",
315 ]
317 domain_commands = [
318 "console",
319 "vncviewer",
320 "create",
321 "new",
322 "delete",
323 "destroy",
324 "domid",
325 "domname",
326 "dump-core",
327 "list",
328 "mem-max",
329 "mem-set",
330 "migrate",
331 "pause",
332 "reboot",
333 "rename",
334 "reset",
335 "restore",
336 "resume",
337 "save",
338 "shutdown",
339 "start",
340 "suspend",
341 "sysrq",
342 "trigger",
343 "top",
344 "unpause",
345 "uptime",
346 "vcpu-list",
347 "vcpu-pin",
348 "vcpu-set",
349 ]
351 host_commands = [
352 "debug-keys",
353 "dmesg",
354 "info",
355 "log",
356 "serve",
357 ]
359 scheduler_commands = [
360 "sched-credit",
361 "sched-sedf",
362 ]
364 device_commands = [
365 "block-attach",
366 "block-detach",
367 "block-list",
368 "block-configure",
369 "network-attach",
370 "network-detach",
371 "network-list",
372 "vtpm-list",
373 "pci-attach",
374 "pci-detach",
375 "pci-list",
376 "pci-list-assignable-devices",
377 "scsi-attach",
378 "scsi-detach",
379 "scsi-list",
380 ]
382 vnet_commands = [
383 "vnet-list",
384 "vnet-create",
385 "vnet-delete",
386 ]
388 acm_commands = [
389 "labels",
390 "addlabel",
391 "rmlabel",
392 "getlabel",
393 "dry-run",
394 "resources",
395 "dumppolicy",
396 "setpolicy",
397 "resetpolicy",
398 "getpolicy",
399 ]
401 all_commands = (domain_commands + host_commands + scheduler_commands +
402 device_commands + vnet_commands + acm_commands +
403 ['shell', 'event-monitor'])
406 ##
407 # Configuration File Parsing
408 ##
410 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
411 config = None
412 if os.path.isfile(xmConfigFile):
413 try:
414 config = xml.dom.minidom.parse(xmConfigFile)
415 except:
416 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
417 xmConfigFile)
419 def parseServer():
420 if config:
421 server = config.getElementsByTagName('server')
422 if server:
423 st = server[0].getAttribute('type')
424 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
425 print >>sys.stderr, ('Invalid server type %s; using %s.' %
426 (st, SERVER_LEGACY_XMLRPC))
427 st = SERVER_LEGACY_XMLRPC
428 return (st, server[0].getAttribute('uri'))
430 return SERVER_LEGACY_XMLRPC, XendClient.uri
432 def parseAuthentication():
433 server = config.getElementsByTagName('server')[0]
434 return (server.getAttribute('username'),
435 server.getAttribute('password'))
437 serverType, serverURI = parseServer()
438 server = None
441 ####################################################################
442 #
443 # Help/usage printing functions
444 #
445 ####################################################################
447 def cmdHelp(cmd):
448 """Print help for a specific subcommand."""
450 if not SUBCOMMAND_HELP.has_key(cmd):
451 for fc in SUBCOMMAND_HELP.keys():
452 if fc[:len(cmd)] == cmd:
453 cmd = fc
454 break
456 try:
457 args, desc = SUBCOMMAND_HELP[cmd]
458 except KeyError:
459 shortHelp()
460 return
462 print 'Usage: xm %s %s' % (cmd, args)
463 print
464 print desc
466 try:
467 # If options help message is defined, print this.
468 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
469 if shortopt and longopt:
470 optdesc = '%s, %s' % (shortopt, longopt)
471 elif shortopt:
472 optdesc = shortopt
473 elif longopt:
474 optdesc = longopt
476 wrapped_desc = wrap(desc, 43)
477 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
478 for line in wrapped_desc[1:]:
479 print ' ' * 33 + line
480 print
481 except KeyError:
482 # if the command is an external module, we grab usage help
483 # from the module itself.
484 if cmd in IMPORTED_COMMANDS:
485 try:
486 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
487 cmd_usage = getattr(cmd_module, "help", None)
488 if cmd_usage:
489 print cmd_usage()
490 except ImportError:
491 pass
493 def shortHelp():
494 """Print out generic help when xm is called without subcommand."""
496 print USAGE_HELP
497 print 'Common \'xm\' commands:\n'
499 for command in common_commands:
500 try:
501 args, desc = SUBCOMMAND_HELP[command]
502 except KeyError:
503 continue
504 wrapped_desc = wrap(desc, 50)
505 print ' %-20s %-50s' % (command, wrapped_desc[0])
506 for line in wrapped_desc[1:]:
507 print ' ' * 22 + line
509 print
510 print USAGE_FOOTER
511 print 'For a complete list of subcommands run \'xm help\'.'
513 def longHelp():
514 """Print out full help when xm is called with xm --help or xm help"""
516 print USAGE_HELP
517 print 'xm full list of subcommands:\n'
519 for command in all_commands:
520 try:
521 args, desc = SUBCOMMAND_HELP[command]
522 except KeyError:
523 continue
525 wrapped_desc = wrap(desc, 50)
526 print ' %-20s %-50s' % (command, wrapped_desc[0])
527 for line in wrapped_desc[1:]:
528 print ' ' * 22 + line
530 print
531 print USAGE_FOOTER
533 def _usage(cmd):
534 """ Print help usage information """
535 if cmd:
536 cmdHelp(cmd)
537 else:
538 shortHelp()
540 def usage(cmd = None):
541 """ Print help usage information and exits """
542 _usage(cmd)
543 sys.exit(1)
546 ####################################################################
547 #
548 # Utility functions
549 #
550 ####################################################################
552 def get_default_SR():
553 return [sr_ref
554 for sr_ref in server.xenapi.SR.get_all()
555 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
557 def get_default_Network():
558 return [network_ref
559 for network_ref in server.xenapi.network.get_all()][0]
561 class XenAPIUnsupportedException(Exception):
562 pass
564 def xenapi_unsupported():
565 if serverType == SERVER_XEN_API:
566 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
568 def xenapi_only():
569 if serverType != SERVER_XEN_API:
570 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
572 def map2sxp(m):
573 return [[k, m[k]] for k in m.keys()]
575 def arg_check(args, name, lo, hi = -1):
576 n = len([i for i in args if i != '--'])
578 if hi == -1:
579 if n != lo:
580 err("'xm %s' requires %d argument%s.\n" % (name, lo,
581 lo == 1 and '' or 's'))
582 usage(name)
583 else:
584 if n < lo or n > hi:
585 err("'xm %s' requires between %d and %d arguments.\n" %
586 (name, lo, hi))
587 usage(name)
590 def unit(c):
591 if not c.isalpha():
592 return 0
593 base = 1
594 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
595 elif c == 'M' or c == 'm': base = 1024 * 1024
596 elif c == 'K' or c == 'k': base = 1024
597 else:
598 print 'ignoring unknown unit'
599 return base
601 def int_unit(str, dest):
602 base = unit(str[-1])
603 if not base:
604 return int(str)
606 value = int(str[:-1])
607 dst_base = unit(dest)
608 if dst_base == 0:
609 dst_base = 1
610 if dst_base > base:
611 return value / (dst_base / base)
612 else:
613 return value * (base / dst_base)
615 def err(msg):
616 print >>sys.stderr, "Error:", msg
619 def get_single_vm(dom):
620 if serverType == SERVER_XEN_API:
621 uuids = server.xenapi.VM.get_by_name_label(dom)
622 if len(uuids) > 0:
623 return uuids[0]
625 refs = []
627 try:
628 domid = int(dom)
629 refs = [vm_ref
630 for vm_ref in server.xenapi.VM.get_all()
631 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
632 except:
633 pass
635 if len(refs) > 0:
636 return refs[0]
638 raise OptionError("Domain '%s' not found." % dom)
639 else:
640 dominfo = server.xend.domain(dom, False)
641 return dominfo['uuid']
643 ##
644 #
645 # Xen-API Shell
646 #
647 ##
649 class Shell(cmd.Cmd):
650 def __init__(self):
651 cmd.Cmd.__init__(self)
652 self.prompt = "xm> "
653 if serverType == SERVER_XEN_API:
654 try:
655 res = server.xenapi.host.list_methods()
656 for f in res:
657 setattr(Shell, 'do_' + f + ' ', self.default)
658 except:
659 pass
661 def preloop(self):
662 cmd.Cmd.preloop(self)
663 try:
664 import readline
665 readline.set_completer_delims(' ')
666 except ImportError:
667 pass
669 def default(self, line):
670 words = shlex.split(line)
671 if len(words) > 0 and words[0] == 'xm':
672 words = words[1:]
673 if len(words) > 0:
674 cmd = xm_lookup_cmd(words[0])
675 if cmd:
676 _run_cmd(cmd, words[0], words[1:])
677 elif serverType == SERVER_XEN_API:
678 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
679 tuple(x)),
680 words[0], words[1:])
681 if ok and res is not None and res != '':
682 pprint.pprint(res)
683 else:
684 print '*** Unknown command: %s' % words[0]
685 return False
687 def completedefault(self, text, line, begidx, endidx):
688 words = shlex.split(line[:begidx])
689 clas, func = words[0].split('.')
690 if len(words) > 1 or \
691 func.startswith('get_by_') or \
692 func == 'get_all':
693 return []
694 uuids = server.xenapi_request('%s.get_all' % clas, ())
695 return [u + " " for u in uuids if u.startswith(text)]
697 def emptyline(self):
698 pass
700 def do_EOF(self, line):
701 print
702 sys.exit(0)
704 def do_help(self, line):
705 _usage(line)
708 def xm_shell(args):
709 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
712 def xm_event_monitor(args):
713 if serverType == SERVER_XEN_API:
714 while True:
715 server.xenapi.event.register(args)
716 events = server.xenapi.event.next()
717 for e in events:
718 print e
719 else:
720 err("Event monitoring not supported unless using Xen-API.")
723 #########################################################################
724 #
725 # Main xm functions
726 #
727 #########################################################################
729 def xm_save(args):
731 arg_check(args, "save", 2, 3)
733 try:
734 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
735 except getopt.GetoptError, opterr:
736 err(opterr)
737 sys.exit(1)
739 checkpoint = False
740 for (k, v) in options:
741 if k in ['-c', '--checkpoint']:
742 checkpoint = True
744 if len(params) != 2:
745 err("Wrong number of parameters")
746 usage('save')
748 dom = params[0]
749 savefile = os.path.abspath(params[1])
751 if not os.access(os.path.dirname(savefile), os.W_OK):
752 err("xm save: Unable to create file %s" % savefile)
753 sys.exit(1)
755 if serverType == SERVER_XEN_API:
756 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
757 else:
758 server.xend.domain.save(dom, savefile, checkpoint)
760 def xm_restore(args):
761 arg_check(args, "restore", 1, 2)
763 try:
764 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
765 except getopt.GetoptError, opterr:
766 err(opterr)
767 usage('restore')
769 paused = False
770 for (k, v) in options:
771 if k in ['-p', '--paused']:
772 paused = True
774 if len(params) != 1:
775 err("Wrong number of parameters")
776 usage('restore')
778 savefile = os.path.abspath(params[0])
780 if not os.access(savefile, os.R_OK):
781 err("xm restore: Unable to read file %s" % savefile)
782 sys.exit(1)
784 if serverType == SERVER_XEN_API:
785 server.xenapi.VM.restore(savefile, paused)
786 else:
787 server.xend.domain.restore(savefile, paused)
790 def datetime_to_secs(v):
791 unwanted = ":-."
792 for c in unwanted:
793 v = str(v).replace(c, "")
794 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
796 def getDomains(domain_names, state, full = 0):
797 if serverType == SERVER_XEN_API:
798 doms_sxp = []
799 doms_dict = []
801 dom_recs = server.xenapi.VM.get_all_records()
802 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
804 for dom_ref, dom_rec in dom_recs.items():
805 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
807 states = ('running', 'blocked', 'paused', 'shutdown',
808 'crashed', 'dying')
809 def state_on_off(state):
810 if state in dom_metrics_rec['state']:
811 return state[0]
812 else:
813 return "-"
814 state_str = "".join([state_on_off(state)
815 for state in states])
817 dom_rec.update({'name': dom_rec['name_label'],
818 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
819 'vcpus': dom_metrics_rec['VCPUs_number'],
820 'state': state_str,
821 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
822 'start_time': datetime_to_secs(
823 dom_metrics_rec['start_time'])})
825 doms_sxp.append(['domain'] + map2sxp(dom_rec))
826 doms_dict.append(dom_rec)
828 if domain_names:
829 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
830 if dom["name"] in domain_names]
832 if len(doms) > 0:
833 return doms
834 else:
835 print "Error: no domain%s named %s" % \
836 (len(domain_names) > 1 and 's' or '',
837 ', '.join(domain_names))
838 sys.exit(-1)
839 else:
840 return doms_sxp
841 else:
842 if domain_names:
843 return [server.xend.domain(dom, full) for dom in domain_names]
844 else:
845 return server.xend.domains_with_state(True, state, full)
848 def xm_list(args):
849 use_long = 0
850 show_vcpus = 0
851 show_labels = 0
852 state = 'all'
853 try:
854 (options, params) = getopt.gnu_getopt(args, 'lv',
855 ['long','vcpus','label',
856 'state='])
857 except getopt.GetoptError, opterr:
858 err(opterr)
859 usage('list')
861 for (k, v) in options:
862 if k in ['-l', '--long']:
863 use_long = 1
864 if k in ['-v', '--vcpus']:
865 show_vcpus = 1
866 if k in ['--label']:
867 show_labels = 1
868 if k in ['--state']:
869 state = v
871 if state != 'all' and len(params) > 0:
872 raise OptionError(
873 "You may specify either a state or a particular VM, but not both")
875 if show_vcpus:
876 print >>sys.stderr, (
877 "xm list -v is deprecated. Please use xm vcpu-list.")
878 xm_vcpu_list(params)
879 return
881 doms = getDomains(params, state, use_long)
883 if use_long:
884 map(PrettyPrint.prettyprint, doms)
885 elif show_labels:
886 xm_label_list(doms)
887 else:
888 xm_brief_list(doms)
891 def parse_doms_info(info):
892 def get_info(n, t, d):
893 return t(sxp.child_value(info, n, d))
895 def get_status(n, t, d):
896 return DOM_STATES[t(sxp.child_value(info, n, d))]
898 start_time = get_info('start_time', float, -1)
899 if start_time == -1:
900 up_time = float(-1)
901 else:
902 up_time = time.time() - start_time
904 parsed_info = {
905 'domid' : get_info('domid', str, ''),
906 'name' : get_info('name', str, '??'),
907 'state' : get_info('state', str, ''),
909 # VCPUs is the number online when the VM is up, or the number
910 # configured otherwise.
911 'vcpus' : get_info('online_vcpus', int,
912 get_info('vcpus', int, 0)),
913 'up_time' : up_time
914 }
916 security_label = get_info('security_label', str, '')
917 parsed_info['seclabel'] = security.parse_security_label(security_label)
919 if serverType == SERVER_XEN_API:
920 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
921 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
922 if sum(cpu_times.values()) > 0:
923 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
924 else:
925 parsed_info['cpu_time'] = 0
926 else:
927 parsed_info['mem'] = get_info('memory', int,0)
928 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
930 return parsed_info
932 def check_sched_type(sched):
933 if serverType == SERVER_XEN_API:
934 current = server.xenapi.host.get_sched_policy(
935 server.xenapi.session.get_this_host(server.getSession()))
936 else:
937 current = 'unknown'
938 for x in server.xend.node.info()[1:]:
939 if len(x) > 1 and x[0] == 'xen_scheduler':
940 current = x[1]
941 break
942 if sched != current:
943 err("Xen is running with the %s scheduler" % current)
944 sys.exit(1)
946 def parse_sedf_info(info):
947 def get_info(n, t, d):
948 return t(sxp.child_value(info, n, d))
950 return {
951 'domid' : get_info('domid', int, -1),
952 'period' : get_info('period', int, -1),
953 'slice' : get_info('slice', int, -1),
954 'latency' : get_info('latency', int, -1),
955 'extratime': get_info('extratime', int, -1),
956 'weight' : get_info('weight', int, -1),
957 }
959 def domid_match(domid, info):
960 return domid is None or domid == info['name'] or \
961 domid == str(info['domid'])
963 def xm_brief_list(doms):
964 print '%-40s %5s %5s %5s %10s %9s' % \
965 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
967 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
968 "%(cpu_time)8.1f"
970 for dom in doms:
971 d = parse_doms_info(dom)
972 print format % d
974 def xm_label_list(doms):
975 print '%-40s %5s %5s %5s %10s %9s %-10s' % \
976 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
978 output = []
979 format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
980 '%(cpu_time)8.1f %(seclabel)10s'
982 for dom in doms:
983 d = parse_doms_info(dom)
984 if d['seclabel'] == "" and serverType != SERVER_XEN_API:
985 seclab = server.xend.security.get_domain_label(d['name'])
986 if len(seclab) > 0 and seclab[0] == '\'':
987 seclab = seclab[1:]
988 d['seclabel'] = seclab
989 output.append((format % d, d['seclabel']))
991 #sort by labels
992 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
993 for line, label in output:
994 print line
997 def xm_vcpu_list(args):
998 if serverType == SERVER_XEN_API:
999 if args:
1000 vm_refs = map(get_single_vm, args)
1001 else:
1002 vm_refs = server.xenapi.VM.get_all()
1004 vm_records = dict(map(lambda vm_ref:
1005 (vm_ref, server.xenapi.VM.get_record(
1006 vm_ref)),
1007 vm_refs))
1009 vm_metrics = dict(map(lambda (ref, record):
1010 (ref,
1011 server.xenapi.VM_metrics.get_record(
1012 record['metrics'])),
1013 vm_records.items()))
1015 dominfo = []
1017 # vcpu_list doesn't list 'managed' domains
1018 # when they are not running, so filter them out
1020 vm_refs = [vm_ref
1021 for vm_ref in vm_refs
1022 if vm_records[vm_ref]["power_state"] != "Halted"]
1024 for vm_ref in vm_refs:
1025 info = ['domain',
1026 ['domid', vm_records[vm_ref]['domid']],
1027 ['name', vm_records[vm_ref]['name_label']],
1028 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
1030 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
1031 def chk_flag(flag):
1032 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1033 and 1 or 0
1035 vcpu_info = ['vcpu',
1036 ['number',
1037 i],
1038 ['online',
1039 chk_flag("online")],
1040 ['blocked',
1041 chk_flag("blocked")],
1042 ['running',
1043 chk_flag("running")],
1044 ['cpu_time',
1045 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1046 ['cpu',
1047 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1048 ['cpumap',
1049 vm_metrics[vm_ref]['VCPUs_params']\
1050 ['cpumap%i' % i].split(",")]]
1052 info.append(vcpu_info)
1054 dominfo.append(info)
1055 else:
1056 if args:
1057 dominfo = map(server.xend.domain.getVCPUInfo, args)
1058 else:
1059 doms = server.xend.domains_with_state(False, 'all', False)
1060 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1062 print '%-32s %5s %5s %5s %5s %9s %s' % \
1063 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1065 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1066 ' %(cpu_time)8.1f %(cpumap)s'
1068 for dom in dominfo:
1069 def get_info(n):
1070 return sxp.child_value(dom, n)
1073 # convert a list of integers into a list of pairs indicating
1074 # continuous sequences in the list:
1076 # [0,1,2,3] -> [(0,3)]
1077 # [1,2,4,5] -> [(1,2),(4,5)]
1078 # [0] -> [(0,0)]
1079 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1081 def list_to_rangepairs(cmap):
1082 cmap.sort()
1083 pairs = []
1084 x = y = 0
1085 for i in range(0,len(cmap)):
1086 try:
1087 if ((cmap[y+1] - cmap[i]) > 1):
1088 pairs.append((cmap[x],cmap[y]))
1089 x = y = i+1
1090 else:
1091 y = y + 1
1092 # if we go off the end, then just add x to y
1093 except IndexError:
1094 pairs.append((cmap[x],cmap[y]))
1096 return pairs
1099 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1101 def format_pairs(pairs):
1102 if not pairs:
1103 return "no cpus"
1104 out = ""
1105 for f,s in pairs:
1106 if (f==s):
1107 out += '%d'%f
1108 else:
1109 out += '%d-%d'%(f,s)
1110 out += ','
1111 # trim trailing ','
1112 return out[:-1]
1114 def format_cpumap(cpumap):
1115 cpumap = map(lambda x: int(x), cpumap)
1116 cpumap.sort()
1118 if serverType == SERVER_XEN_API:
1119 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1120 server.xenapi.session.get_this_host(server.getSession())))
1121 else:
1122 for x in server.xend.node.info()[1:]:
1123 if len(x) > 1 and x[0] == 'nr_cpus':
1124 nr_cpus = int(x[1])
1126 # normalize cpumap by modulus nr_cpus, and drop duplicates
1127 cpumap = dict.fromkeys(
1128 filter(lambda x: x < nr_cpus, cpumap)).keys()
1129 if len(cpumap) == nr_cpus:
1130 return "any cpu"
1132 return format_pairs(list_to_rangepairs(cpumap))
1134 name = get_info('name')
1135 domid = get_info('domid')
1136 if domid is not None:
1137 domid = str(domid)
1138 else:
1139 domid = ''
1141 for vcpu in sxp.children(dom, 'vcpu'):
1142 def vinfo(n, t):
1143 return t(sxp.child_value(vcpu, n))
1145 number = vinfo('number', int)
1146 cpu = vinfo('cpu', int)
1147 cpumap = format_cpumap(vinfo('cpumap', list))
1148 online = vinfo('online', int)
1149 cpu_time = vinfo('cpu_time', float)
1150 running = vinfo('running', int)
1151 blocked = vinfo('blocked', int)
1153 if cpu < 0:
1154 c = ''
1155 s = ''
1156 elif online:
1157 c = str(cpu)
1158 if running:
1159 s = 'r'
1160 else:
1161 s = '-'
1162 if blocked:
1163 s += 'b'
1164 else:
1165 s += '-'
1166 s += '-'
1167 else:
1168 c = '-'
1169 s = '--p'
1171 print format % locals()
1173 def start_do_console(domain_name):
1174 cpid = os.fork()
1175 if cpid != 0:
1176 for i in range(10):
1177 # Catch failure of the create process
1178 time.sleep(1)
1179 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1180 if os.WIFEXITED(rv):
1181 if os.WEXITSTATUS(rv) != 0:
1182 sys.exit(os.WEXITSTATUS(rv))
1183 try:
1184 # Acquire the console of the created dom
1185 if serverType == SERVER_XEN_API:
1186 domid = server.xenapi.VM.get_domid(
1187 get_single_vm(domain_name))
1188 else:
1189 dom = server.xend.domain(domain_name)
1190 domid = int(sxp.child_value(dom, 'domid', '-1'))
1191 console.execConsole(domid)
1192 except:
1193 pass
1194 print("Could not start console\n");
1195 sys.exit(0)
1197 def xm_start(args):
1199 paused = False
1200 console_autoconnect = False
1201 vncviewer = False
1202 vncviewer_autopass = False
1204 try:
1205 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused','vncviewer','vncviewer-autopass'])
1206 for (k, v) in options:
1207 if k in ('-p', '--paused'):
1208 paused = True
1209 if k in ('-c', '--console_autoconnect'):
1210 console_autoconnect = True
1211 if k in ('--vncviewer'):
1212 vncviewer = True
1213 if k in ('--vncviewer-autopass'):
1214 vncviewer_autopass = True
1216 if len(params) != 1:
1217 raise OptionError("Expects 1 argument")
1218 except getopt.GetoptError, opterr:
1219 err(opterr)
1220 usage('start')
1222 dom = params[0]
1224 if console_autoconnect:
1225 start_do_console(dom)
1227 if console_autoconnect:
1228 console.runVncViewer(domid, vncviewer_autopass, True)
1230 try:
1231 if serverType == SERVER_XEN_API:
1232 server.xenapi.VM.start(get_single_vm(dom), paused)
1233 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1234 else:
1235 server.xend.domain.start(dom, paused)
1236 info = server.xend.domain(dom)
1237 domid = int(sxp.child_value(info, 'domid', '-1'))
1238 except:
1239 raise
1241 if domid == -1:
1242 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1244 def xm_delete(args):
1245 arg_check(args, "delete", 1)
1246 dom = args[0]
1247 if serverType == SERVER_XEN_API:
1248 server.xenapi.VM.destroy(get_single_vm(dom))
1249 else:
1250 server.xend.domain.delete(dom)
1252 def xm_suspend(args):
1253 arg_check(args, "suspend", 1)
1254 dom = args[0]
1255 if serverType == SERVER_XEN_API:
1256 server.xenapi.VM.suspend(get_single_vm(dom))
1257 else:
1258 server.xend.domain.suspend(dom)
1260 def xm_resume(args):
1261 arg_check(args, "resume", 1, 2)
1263 try:
1264 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1265 except getopt.GetoptError, opterr:
1266 err(opterr)
1267 usage('resume')
1269 paused = False
1270 for (k, v) in options:
1271 if k in ['-p', '--paused']:
1272 paused = True
1274 if len(params) != 1:
1275 err("Wrong number of parameters")
1276 usage('resume')
1278 dom = params[0]
1279 if serverType == SERVER_XEN_API:
1280 server.xenapi.VM.resume(get_single_vm(dom), paused)
1281 else:
1282 server.xend.domain.resume(dom, paused)
1284 def xm_reboot(args):
1285 arg_check(args, "reboot", 1, 3)
1286 from xen.xm import shutdown
1287 shutdown.main(["shutdown", "-R"] + args)
1289 def xm_shutdown(args):
1290 arg_check(args, "shutdown", 1, 4)
1291 from xen.xm import shutdown
1292 shutdown.main(["shutdown"] + args)
1294 def xm_reset(args):
1295 arg_check(args, "reset", 1)
1296 dom = args[0]
1298 if serverType == SERVER_XEN_API:
1299 server.xenapi.VM.hard_reboot(get_single_vm(dom))
1300 else:
1301 server.xend.domain.reset(dom)
1303 def xm_pause(args):
1304 arg_check(args, "pause", 1)
1305 dom = args[0]
1307 if serverType == SERVER_XEN_API:
1308 server.xenapi.VM.pause(get_single_vm(dom))
1309 else:
1310 server.xend.domain.pause(dom)
1312 def xm_unpause(args):
1313 arg_check(args, "unpause", 1)
1314 dom = args[0]
1316 if serverType == SERVER_XEN_API:
1317 server.xenapi.VM.unpause(get_single_vm(dom))
1318 else:
1319 server.xend.domain.unpause(dom)
1321 def xm_dump_core(args):
1322 live = False
1323 crash = False
1324 reset = False
1325 try:
1326 (options, params) = getopt.gnu_getopt(args, 'LCR', ['live', 'crash', 'reset'])
1327 for (k, v) in options:
1328 if k in ('-L', '--live'):
1329 live = True
1330 elif k in ('-C', '--crash'):
1331 crash = True
1332 elif k in ('-R', '--reset'):
1333 reset = True
1335 if crash and reset:
1336 raise OptionError("You may not specify more than one '-CR' option")
1337 if len(params) not in (1, 2):
1338 raise OptionError("Expects 1 or 2 argument(s)")
1339 except getopt.GetoptError, e:
1340 raise OptionError(str(e))
1342 dom = params[0]
1343 if len(params) == 2:
1344 filename = os.path.abspath(params[1])
1345 else:
1346 filename = None
1348 if not live:
1349 ds = server.xend.domain.pause(dom, True)
1351 try:
1352 print "Dumping core of domain: %s ..." % str(dom)
1353 server.xend.domain.dump(dom, filename, live, crash)
1355 if crash:
1356 print "Destroying domain: %s ..." % str(dom)
1357 server.xend.domain.destroy(dom)
1358 elif reset:
1359 print "Resetting domain: %s ..." % str(dom)
1360 server.xend.domain.reset(dom)
1361 finally:
1362 if not live and not crash and not reset and ds == DOM_STATE_RUNNING:
1363 server.xend.domain.unpause(dom)
1365 def xm_rename(args):
1366 arg_check(args, "rename", 2)
1368 if serverType == SERVER_XEN_API:
1369 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1370 else:
1371 server.xend.domain.setName(args[0], args[1])
1373 def xm_importcommand(command, args):
1374 cmd = __import__(command, globals(), locals(), 'xen.xm')
1375 cmd.main([command] + args)
1378 #############################################################
1380 def xm_vcpu_pin(args):
1381 arg_check(args, "vcpu-pin", 3)
1383 def cpu_make_map(cpulist):
1384 cpus = []
1385 for c in cpulist.split(','):
1386 if c.find('-') != -1:
1387 (x,y) = c.split('-')
1388 for i in range(int(x),int(y)+1):
1389 cpus.append(int(i))
1390 else:
1391 # remove this element from the list
1392 if c[0] == '^':
1393 cpus = [x for x in cpus if x != int(c[1:])]
1394 else:
1395 cpus.append(int(c))
1396 cpus.sort()
1397 return cpus
1399 dom = args[0]
1400 vcpu = args[1]
1401 if args[2] == 'all':
1402 cpumap = cpu_make_map('0-63')
1403 else:
1404 cpumap = cpu_make_map(args[2])
1406 if serverType == SERVER_XEN_API:
1407 cpumap = map(str, cpumap)
1408 server.xenapi.VM.add_to_VCPUs_params_live(
1409 get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap))
1410 else:
1411 server.xend.domain.pincpu(dom, vcpu, cpumap)
1413 def xm_mem_max(args):
1414 arg_check(args, "mem-max", 2)
1416 dom = args[0]
1418 if serverType == SERVER_XEN_API:
1419 mem = int_unit(args[1], 'k') * 1024
1420 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1421 else:
1422 mem = int_unit(args[1], 'm')
1423 server.xend.domain.maxmem_set(dom, mem)
1425 def xm_mem_set(args):
1426 arg_check(args, "mem-set", 2)
1428 dom = args[0]
1430 if serverType == SERVER_XEN_API:
1431 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1432 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1433 mem_target)
1434 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1435 mem_target)
1436 else:
1437 mem_target = int_unit(args[1], 'm')
1438 server.xend.domain.setMemoryTarget(dom, mem_target)
1440 def xm_vcpu_set(args):
1441 arg_check(args, "vcpu-set", 2)
1443 dom = args[0]
1444 vcpus = int(args[1])
1446 if serverType == SERVER_XEN_API:
1447 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1448 else:
1449 server.xend.domain.setVCpuCount(dom, vcpus)
1451 def xm_destroy(args):
1452 arg_check(args, "destroy", 1)
1454 dom = args[0]
1456 if serverType == SERVER_XEN_API:
1457 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1458 else:
1459 server.xend.domain.destroy(dom)
1461 def xm_domid(args):
1462 arg_check(args, "domid", 1)
1464 name = args[0]
1466 if serverType == SERVER_XEN_API:
1467 print server.xenapi.VM.get_domid(get_single_vm(name))
1468 else:
1469 dom = server.xend.domain(name)
1470 print sxp.child_value(dom, 'domid')
1472 def xm_domname(args):
1473 arg_check(args, "domname", 1)
1475 name = args[0]
1477 if serverType == SERVER_XEN_API:
1478 print server.xenapi.VM.get_name_label(get_single_vm(name))
1479 else:
1480 dom = server.xend.domain(name)
1481 print sxp.child_value(dom, 'name')
1483 def xm_sched_sedf(args):
1484 xenapi_unsupported()
1486 def ns_to_ms(val):
1487 return float(val) * 0.000001
1489 def ms_to_ns(val):
1490 return (float(val) / 0.000001)
1492 def print_sedf(info):
1493 info['period'] = ns_to_ms(info['period'])
1494 info['slice'] = ns_to_ms(info['slice'])
1495 info['latency'] = ns_to_ms(info['latency'])
1496 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1497 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1499 check_sched_type('sedf')
1501 # we want to just display current info if no parameters are passed
1502 if len(args) == 0:
1503 domid = None
1504 else:
1505 # we expect at least a domain id (name or number)
1506 # and at most a domid up to 5 options with values
1507 arg_check(args, "sched-sedf", 1, 11)
1508 domid = args[0]
1509 # drop domid from args since get_opt doesn't recognize it
1510 args = args[1:]
1512 opts = {}
1513 try:
1514 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1515 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1516 except getopt.GetoptError, opterr:
1517 err(opterr)
1518 usage('sched-sedf')
1520 # convert to nanoseconds if needed
1521 for (k, v) in options:
1522 if k in ['-p', '--period']:
1523 opts['period'] = ms_to_ns(v)
1524 elif k in ['-s', '--slice']:
1525 opts['slice'] = ms_to_ns(v)
1526 elif k in ['-l', '--latency']:
1527 opts['latency'] = ms_to_ns(v)
1528 elif k in ['-e', '--extratime']:
1529 opts['extratime'] = v
1530 elif k in ['-w', '--weight']:
1531 opts['weight'] = v
1533 doms = filter(lambda x : domid_match(domid, x),
1534 [parse_doms_info(dom)
1535 for dom in getDomains(None, 'running')])
1536 if domid is not None and doms == []:
1537 err("Domain '%s' does not exist." % domid)
1538 usage('sched-sedf')
1540 # print header if we aren't setting any parameters
1541 if len(opts.keys()) == 0:
1542 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1543 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1544 'Extra','Weight')
1546 for d in doms:
1547 # fetch current values so as not to clobber them
1548 try:
1549 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1550 except xmlrpclib.Fault:
1551 # domain does not support sched-sedf?
1552 sedf_raw = {}
1554 sedf_info = parse_sedf_info(sedf_raw)
1555 sedf_info['name'] = d['name']
1556 # update values in case of call to set
1557 if len(opts.keys()) > 0:
1558 for k in opts.keys():
1559 sedf_info[k]=opts[k]
1561 # send the update, converting user input
1562 v = map(int, [sedf_info['period'], sedf_info['slice'],
1563 sedf_info['latency'],sedf_info['extratime'],
1564 sedf_info['weight']])
1565 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1566 if int(rv) != 0:
1567 err("Failed to set sedf parameters (rv=%d)."%(rv))
1569 # not setting values, display info
1570 else:
1571 print_sedf(sedf_info)
1573 def xm_sched_credit(args):
1574 """Get/Set options for Credit Scheduler."""
1576 check_sched_type('credit')
1578 try:
1579 opts, params = getopt.getopt(args, "d:w:c:",
1580 ["domain=", "weight=", "cap="])
1581 except getopt.GetoptError, opterr:
1582 err(opterr)
1583 usage('sched-credit')
1585 domid = None
1586 weight = None
1587 cap = None
1589 for o, a in opts:
1590 if o in ["-d", "--domain"]:
1591 domid = a
1592 elif o in ["-w", "--weight"]:
1593 weight = int(a)
1594 elif o in ["-c", "--cap"]:
1595 cap = int(a);
1597 doms = filter(lambda x : domid_match(domid, x),
1598 [parse_doms_info(dom)
1599 for dom in getDomains(None, 'all')])
1601 if weight is None and cap is None:
1602 if domid is not None and doms == []:
1603 err("Domain '%s' does not exist." % domid)
1604 usage('sched-credit')
1605 # print header if we aren't setting any parameters
1606 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1608 for d in doms:
1609 try:
1610 if serverType == SERVER_XEN_API:
1611 info = server.xenapi.VM_metrics.get_VCPUs_params(
1612 server.xenapi.VM.get_metrics(
1613 get_single_vm(d['name'])))
1614 else:
1615 info = server.xend.domain.sched_credit_get(d['name'])
1616 except xmlrpclib.Fault:
1617 pass
1619 if 'weight' not in info or 'cap' not in info:
1620 # domain does not support sched-credit?
1621 info = {'weight': -1, 'cap': -1}
1623 info['weight'] = int(info['weight'])
1624 info['cap'] = int(info['cap'])
1626 info['name'] = d['name']
1627 info['domid'] = str(d['domid'])
1628 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1629 else:
1630 if domid is None:
1631 # place holder for system-wide scheduler parameters
1632 err("No domain given.")
1633 usage('sched-credit')
1635 if serverType == SERVER_XEN_API:
1636 if doms[0]['domid']:
1637 server.xenapi.VM.add_to_VCPUs_params_live(
1638 get_single_vm(domid),
1639 "weight",
1640 weight)
1641 server.xenapi.VM.add_to_VCPUs_params_live(
1642 get_single_vm(domid),
1643 "cap",
1644 cap)
1645 else:
1646 server.xenapi.VM.add_to_VCPUs_params(
1647 get_single_vm(domid),
1648 "weight",
1649 weight)
1650 server.xenapi.VM.add_to_VCPUs_params(
1651 get_single_vm(domid),
1652 "cap",
1653 cap)
1654 else:
1655 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1656 if result != 0:
1657 err(str(result))
1659 def xm_info(args):
1660 arg_check(args, "info", 0, 1)
1662 try:
1663 (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
1664 except getopt.GetoptError, opterr:
1665 err(opterr)
1666 usage('info')
1668 show_xend_config = 0
1669 for (k, v) in options:
1670 if k in ['-c', '--config']:
1671 show_xend_config = 1
1673 if show_xend_config:
1674 for name, obj in inspect.getmembers(xoptions):
1675 if not inspect.ismethod(obj):
1676 if name == "config":
1677 for x in obj[1:]:
1678 if len(x) < 2:
1679 print "%-38s: (none)" % x[0]
1680 else:
1681 print "%-38s:" % x[0], x[1]
1682 else:
1683 print "%-38s:" % name, obj
1684 return
1686 if serverType == SERVER_XEN_API:
1688 # Need to fake out old style xm info as people rely on parsing it
1690 host_record = server.xenapi.host.get_record(
1691 server.xenapi.session.get_this_host(server.getSession()))
1693 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1695 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1697 def getVal(keys, default=""):
1698 data = host_record
1699 for key in keys:
1700 if key in data:
1701 data = data[key]
1702 else:
1703 return default
1704 return data
1706 def getCpuMhz():
1707 cpu_speeds = [int(host_cpu_record["speed"])
1708 for host_cpu_record in host_cpu_records
1709 if "speed" in host_cpu_record]
1710 if len(cpu_speeds) > 0:
1711 return sum(cpu_speeds) / len(cpu_speeds)
1712 else:
1713 return 0
1715 getCpuMhz()
1717 def getCpuFeatures():
1718 if len(host_cpu_records) > 0:
1719 return host_cpu_records[0].get("features", "")
1720 else:
1721 return ""
1723 info = {
1724 "host": getVal(["name_label"]),
1725 "release": getVal(["software_version", "release"]),
1726 "version": getVal(["software_version", "version"]),
1727 "machine": getVal(["software_version", "machine"]),
1728 "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
1729 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1730 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1731 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1732 "cpu_mhz": getCpuMhz(),
1733 "hw_caps": getCpuFeatures(),
1734 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1735 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1736 "xen_major": getVal(["software_version", "xen_major"]),
1737 "xen_minor": getVal(["software_version", "xen_minor"]),
1738 "xen_extra": getVal(["software_version", "xen_extra"]),
1739 "xen_caps": " ".join(getVal(["capabilities"], [])),
1740 "xen_scheduler": getVal(["sched_policy"]),
1741 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1742 "platform_params": getVal(["other_config", "platform_params"]),
1743 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1744 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1745 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1746 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1747 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1748 "xend_config_format":getVal(["software_version", "xend_config_format"])
1751 sorted = info.items()
1752 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1754 for (k, v) in sorted:
1755 print "%-23s:" % k, v
1756 else:
1757 info = server.xend.node.info()
1758 for x in info[1:]:
1759 if len(x) < 2:
1760 print "%-23s: (none)" % x[0]
1761 else:
1762 print "%-23s:" % x[0], x[1]
1764 def xm_console(args):
1765 arg_check(args, "console", 1, 2)
1767 quiet = False;
1769 try:
1770 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1771 except getopt.GetoptError, opterr:
1772 err(opterr)
1773 usage('console')
1775 for (k, v) in options:
1776 if k in ['-q', '--quiet']:
1777 quiet = True
1778 else:
1779 assert False
1781 if len(params) != 1:
1782 err('No domain given')
1783 usage('console')
1785 dom = params[0]
1787 try:
1788 if serverType == SERVER_XEN_API:
1789 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1790 else:
1791 info = server.xend.domain(dom)
1792 domid = int(sxp.child_value(info, 'domid', '-1'))
1793 except:
1794 if quiet:
1795 sys.exit(1)
1796 else:
1797 raise
1799 if domid == -1:
1800 if quiet:
1801 sys.exit(1)
1802 else:
1803 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1805 console.execConsole(domid)
1808 def domain_name_to_domid(domain_name):
1809 if serverType == SERVER_XEN_API:
1810 domid = server.xenapi.VM.get_domid(
1811 get_single_vm(domain_name))
1812 else:
1813 dom = server.xend.domain(domain_name)
1814 domid = int(sxp.child_value(dom, 'domid', '-1'))
1815 return int(domid)
1817 def xm_vncviewer(args):
1818 autopass = False;
1820 try:
1821 (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass'])
1822 except getopt.GetoptError, opterr:
1823 err(opterr)
1824 usage('vncviewer')
1826 for (k, v) in options:
1827 if k in ['--autopass','--vncviewer-autopass']:
1828 autopass = True
1829 else:
1830 assert False
1832 if len(params) != 1:
1833 err('No domain given (or several parameters specified)')
1834 usage('vncviewer')
1836 dom = params[0]
1837 domid = domain_name_to_domid(dom)
1839 console.runVncViewer(domid, autopass)
1842 def xm_uptime(args):
1843 short_mode = 0
1845 try:
1846 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1847 except getopt.GetoptError, opterr:
1848 err(opterr)
1849 usage('uptime')
1851 for (k, v) in options:
1852 if k in ['-s', '--short']:
1853 short_mode = 1
1855 doms = getDomains(params, 'all')
1857 if short_mode == 0:
1858 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1860 for dom in doms:
1861 d = parse_doms_info(dom)
1862 if d['domid'] == '':
1863 uptime = 0
1864 elif int(d['domid']) > 0:
1865 uptime = int(round(d['up_time']))
1866 else:
1867 f=open('/proc/uptime', 'r')
1868 upfile = f.read()
1869 uptime = int(round(float(upfile.split(' ')[0])))
1870 f.close()
1872 days = int(uptime / 86400)
1873 uptime -= (days * 86400)
1874 hours = int(uptime / 3600)
1875 uptime -= (hours * 3600)
1876 minutes = int(uptime / 60)
1877 uptime -= (minutes * 60)
1878 seconds = uptime
1880 upstring = ""
1881 if days > 0:
1882 upstring += str(days) + " day"
1883 if days > 1:
1884 upstring += "s"
1885 upstring += ", "
1886 upstring += '%(hours)2d:%(minutes)02d' % vars()
1888 if short_mode:
1889 now = datetime.datetime.now()
1890 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1891 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1892 else:
1893 upstring += ':%(seconds)02d' % vars()
1894 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1896 print upstring
1898 def xm_sysrq(args):
1899 arg_check(args, "sysrq", 2)
1900 dom = args[0]
1901 req = args[1]
1902 if serverType == SERVER_XEN_API:
1903 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1904 else:
1905 server.xend.domain.send_sysrq(dom, req)
1907 def xm_trigger(args):
1908 vcpu = 0
1910 arg_check(args, "trigger", 2, 3)
1911 dom = args[0]
1912 trigger = args[1]
1913 if len(args) == 3:
1914 vcpu = int(args[2])
1916 if serverType == SERVER_XEN_API:
1917 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1918 else:
1919 server.xend.domain.send_trigger(dom, trigger, vcpu)
1921 def xm_debug_keys(args):
1922 arg_check(args, "debug-keys", 1)
1924 keys = str(args[0])
1926 if serverType == SERVER_XEN_API:
1927 server.xenapi.host.send_debug_keys(
1928 server.xenapi.session.get_this_host(server.getSession()),
1929 keys)
1930 else:
1931 server.xend.node.send_debug_keys(keys)
1933 def xm_top(args):
1934 arg_check(args, "top", 0)
1936 os.system('xentop')
1938 def xm_dmesg(args):
1939 arg_check(args, "dmesg", 0, 1)
1941 try:
1942 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1943 except getopt.GetoptError, opterr:
1944 err(opterr)
1945 usage('dmesg')
1947 use_clear = 0
1948 for (k, v) in options:
1949 if k in ['-c', '--clear']:
1950 use_clear = 1
1952 if len(params) :
1953 err("No parameter required")
1954 usage('dmesg')
1956 if serverType == SERVER_XEN_API:
1957 host = server.xenapi.session.get_this_host(server.getSession())
1958 if use_clear:
1959 print server.xenapi.host.dmesg_clear(host),
1960 else:
1961 print server.xenapi.host.dmesg(host),
1962 else:
1963 if not use_clear:
1964 print server.xend.node.dmesg.info(),
1965 else:
1966 print server.xend.node.dmesg.clear(),
1968 def xm_log(args):
1969 arg_check(args, "log", 0)
1971 if serverType == SERVER_XEN_API:
1972 print server.xenapi.host.get_log(
1973 server.xenapi.session.get_this_host(server.getSession()))
1974 else:
1975 print server.xend.node.log()
1977 def xm_serve(args):
1978 if serverType == SERVER_XEN_API:
1979 print "Not supported with XenAPI"
1980 sys.exit(-1)
1982 arg_check(args, "serve", 0)
1984 from fcntl import fcntl, F_SETFL
1986 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1987 s.connect(XendClient.XML_RPC_SOCKET)
1988 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1990 while True:
1991 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1992 if s in iwtd:
1993 data = s.recv(4096)
1994 if len(data) > 0:
1995 sys.stdout.write(data)
1996 sys.stdout.flush()
1997 else:
1998 break
1999 if sys.stdin in iwtd:
2000 data = sys.stdin.read(4096)
2001 if len(data) > 0:
2002 s.sendall(data)
2003 else:
2004 break
2005 s.close()
2007 def parse_dev_info(info):
2008 def get_info(n, t, d):
2009 i = 0
2010 while i < len(info):
2011 if (info[i][0] == n):
2012 return t(info[i][1])
2013 i = i + 1
2014 return t(d)
2015 return {
2016 #common
2017 'backend-id' : get_info('backend-id', int, -1),
2018 'handle' : get_info('handle', int, 0),
2019 'state' : get_info('state', int, -1),
2020 'be-path' : get_info('backend', str, '??'),
2021 'event-ch' : get_info('event-channel',int, -1),
2022 #network specific
2023 'virtual-device' : get_info('virtual-device', str, '??'),
2024 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
2025 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
2026 'mac' : get_info('mac', str, '??'),
2027 #block-device specific
2028 'ring-ref' : get_info('ring-ref', int, -1),
2031 def arg_check_for_resource_list(args, name):
2032 use_long = 0
2033 try:
2034 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2035 except getopt.GetoptError, opterr:
2036 err(opterr)
2037 sys.exit(1)
2039 for (k, v) in options:
2040 if k in ['-l', '--long']:
2041 use_long = 1
2043 if len(params) == 0:
2044 print 'No domain parameter given'
2045 usage(name)
2046 if len(params) > 1:
2047 print 'No multiple domain parameters allowed'
2048 usage(name)
2050 return (use_long, params)
2052 def xm_network_list(args):
2053 (use_long, params) = arg_check_for_resource_list(args, "network-list")
2055 dom = params[0]
2057 if serverType == SERVER_XEN_API:
2058 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2059 vif_properties = \
2060 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
2061 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2062 zip(range(len(vif_properties)), vif_properties))
2063 else:
2064 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
2066 if use_long:
2067 map(PrettyPrint.prettyprint, devs)
2068 else:
2069 hdr = 0
2070 for x in devs:
2071 if hdr == 0:
2072 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
2073 hdr = 1
2074 ni = parse_dev_info(x[1])
2075 ni['idx'] = int(x[0])
2076 print ("%(idx)-3d "
2077 "%(backend-id)-3d"
2078 "%(mac)-17s "
2079 "%(handle)-3d "
2080 "%(state)-3d "
2081 "%(event-ch)-3d "
2082 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
2083 "%(be-path)-30s "
2084 % ni)
2086 def xm_block_list(args):
2087 (use_long, params) = arg_check_for_resource_list(args, "block-list")
2089 dom = params[0]
2091 if serverType == SERVER_XEN_API:
2092 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2093 vbd_properties = \
2094 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2095 vbd_devs = \
2096 map(server.xenapi.VBD.get_device, vbd_refs)
2097 vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
2098 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2099 zip(vbd_devids, vbd_properties))
2100 else:
2101 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2103 if use_long:
2104 map(PrettyPrint.prettyprint, devs)
2105 else:
2106 hdr = 0
2107 for x in devs:
2108 if hdr == 0:
2109 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2110 hdr = 1
2111 ni = parse_dev_info(x[1])
2112 ni['idx'] = int(x[0])
2113 print ("%(idx)-5d "
2114 "%(backend-id)-3d "
2115 "%(handle)-3d "
2116 "%(state)-3d "
2117 "%(event-ch)-3d "
2118 "%(ring-ref)-5d "
2119 "%(be-path)-30s "
2120 % ni)
2122 def xm_vtpm_list(args):
2123 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2125 dom = params[0]
2127 if serverType == SERVER_XEN_API:
2128 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2129 vtpm_properties = \
2130 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2131 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2132 zip(range(len(vtpm_properties)), vtpm_properties))
2133 else:
2134 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2136 if use_long:
2137 map(PrettyPrint.prettyprint, devs)
2138 else:
2139 hdr = 0
2140 for x in devs:
2141 if hdr == 0:
2142 print 'Idx BE handle state evt-ch ring-ref BE-path'
2143 hdr = 1
2144 ni = parse_dev_info(x[1])
2145 ni['idx'] = int(x[0])
2146 print ("%(idx)-3d "
2147 "%(backend-id)-3d "
2148 "%(handle)-3d "
2149 "%(state)-3d "
2150 "%(event-ch)-3d "
2151 "%(ring-ref)-5d "
2152 "%(be-path)-30s "
2153 % ni)
2156 def xm_pci_list(args):
2157 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2159 dom = params[0]
2161 devs = []
2162 if serverType == SERVER_XEN_API:
2163 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2164 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2165 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2166 dev = {
2167 "domain": "0x%04x" % int(ppci_record["domain"]),
2168 "bus": "0x%02x" % int(ppci_record["bus"]),
2169 "slot": "0x%02x" % int(ppci_record["slot"]),
2170 "func": "0x%01x" % int(ppci_record["func"]),
2171 "vslt": "0x%02x" % \
2172 int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref))
2174 devs.append(dev)
2176 else:
2177 devs = server.xend.domain.getDeviceSxprs(dom, 'pci')
2179 if len(devs) == 0:
2180 return
2182 has_vslt = devs[0].has_key('vslt')
2183 if has_vslt:
2184 hdr_str = 'VSlt domain bus slot func'
2185 fmt_str = "%(vslt)-3s %(domain)-3s %(bus)-3s %(slot)-3s %(func)-3s "
2186 else:
2187 hdr_str = 'domain bus slot func'
2188 fmt_str = "%(domain)-3s %(bus)-3s %(slot)-3s %(func)-3s "
2189 hdr = 0
2191 for x in devs:
2192 if hdr == 0:
2193 print (hdr_str)
2194 hdr = 1
2195 print ( fmt_str % x )
2197 def xm_pci_list_assignable_devices(args):
2198 # Each element of dev_list is a PciDevice
2199 dev_list = find_all_devices_owned_by_pciback()
2201 # Each element of devs_list is a list of PciDevice
2202 devs_list = check_FLR_capability(dev_list)
2204 devs_list = check_mmio_bar(devs_list)
2206 # Check if the devices have been assigned to guests.
2207 final_devs_list = []
2208 for dev_list in devs_list:
2209 available = True
2210 for d in dev_list:
2211 pci_str = '0x%x,0x%x,0x%x,0x%x' %(d.domain, d.bus, d.slot, d.func)
2212 # Xen doesn't care what the domid is, so we pass 0 here...
2213 domid = 0
2214 bdf = xc.test_assign_device(domid, pci_str)
2215 if bdf != 0:
2216 available = False
2217 break
2218 if available:
2219 final_devs_list = final_devs_list + [dev_list]
2221 for dev_list in final_devs_list:
2222 for d in dev_list:
2223 print d.name,
2224 print
2226 def vscsi_convert_sxp_to_dict(dev_sxp):
2227 dev_dict = {}
2228 for opt_val in dev_sxp[1:]:
2229 try:
2230 opt, val = opt_val
2231 dev_dict[opt] = val
2232 except TypeError:
2233 pass
2234 return dev_dict
2236 def xm_scsi_list(args):
2237 xenapi_unsupported()
2238 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2240 dom = params[0]
2242 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2244 if use_long:
2245 map(PrettyPrint.prettyprint, devs)
2246 else:
2247 hdr = 0
2248 for x in devs:
2249 if hdr == 0:
2250 print "%-3s %-3s %-5s %-10s %-5s %-10s %-4s" \
2251 % ('Idx', 'BE', 'state', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2252 hdr = 1
2253 ni = parse_dev_info(x[1])
2254 ni['idx'] = int(x[0])
2255 for dev in x[1][0][1]:
2256 mi = vscsi_convert_sxp_to_dict(dev)
2257 print "%(idx)-3d %(backend-id)-3d %(state)-5d " % ni,
2258 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2260 def parse_block_configuration(args):
2261 dom = args[0]
2263 if args[1].startswith('tap:'):
2264 cls = 'tap'
2265 else:
2266 cls = 'vbd'
2268 vbd = [cls,
2269 ['uname', args[1]],
2270 ['dev', args[2]],
2271 ['mode', args[3]]]
2272 if len(args) == 5:
2273 vbd.append(['backend', args[4]])
2275 return (dom, vbd)
2278 def xm_block_attach(args):
2279 arg_check(args, 'block-attach', 4, 5)
2281 if serverType == SERVER_XEN_API:
2282 dom = args[0]
2283 uname = args[1]
2284 dev = args[2]
2285 mode = args[3]
2287 # First create new VDI
2288 vdi_record = {
2289 "name_label": "vdi" + str(uname.__hash__()),
2290 "name_description": "",
2291 "SR": get_default_SR(),
2292 "virtual_size": 0,
2293 "sector_size": 512,
2294 "type": "system",
2295 "sharable": False,
2296 "read_only": mode!="w",
2297 "other_config": {"location": uname}
2300 vdi_ref = server.xenapi.VDI.create(vdi_record)
2302 # Now create new VBD
2304 vbd_record = {
2305 "VM": get_single_vm(dom),
2306 "VDI": vdi_ref,
2307 "device": dev,
2308 "bootable": True,
2309 "mode": mode=="w" and "RW" or "RO",
2310 "type": "Disk",
2311 "qos_algorithm_type": "",
2312 "qos_algorithm_params": {}
2315 server.xenapi.VBD.create(vbd_record)
2317 else:
2318 (dom, vbd) = parse_block_configuration(args)
2319 server.xend.domain.device_create(dom, vbd)
2322 def xm_block_configure(args):
2323 arg_check(args, 'block-configure', 4, 5)
2325 (dom, vbd) = parse_block_configuration(args)
2326 server.xend.domain.device_configure(dom, vbd)
2329 def xm_network_attach(args):
2330 arg_check(args, 'network-attach', 1, 11)
2332 dom = args[0]
2333 vif = ['vif']
2334 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2335 'backend', 'vifname', 'rate', 'model', 'accel']
2337 if serverType == SERVER_XEN_API:
2338 vif_record = {
2339 "device": "eth0",
2340 "network": get_default_Network(),
2341 "VM": get_single_vm(dom),
2342 "MAC": "",
2343 "MTU": "",
2344 "qos_algorithm_type": "",
2345 "qos_algorithm_params": {},
2346 "other_config": {}
2349 def set(keys, val):
2350 record = vif_record
2351 for key in keys[:-1]:
2352 record = record[key]
2353 record[keys[-1]] = val
2355 def get_net_from_bridge(bridge):
2356 # In OSS, we just assert network.name_label == bridge name
2357 networks = dict([(record['name_label'], ref)
2358 for ref, record in server.xenapi.network
2359 .get_all_records().items()])
2360 if bridge not in networks.keys():
2361 raise "Unknown bridge name!"
2362 return networks[bridge]
2364 vif_conv = {
2365 'type':
2366 lambda x: None,
2367 'mac':
2368 lambda x: set(['MAC'], x),
2369 'bridge':
2370 lambda x: set(['network'], get_net_from_bridge(x)),
2371 'ip':
2372 lambda x: set(['other_config', 'ip'], x),
2373 'script':
2374 lambda x: set(['other_config', 'script'], x),
2375 'backend':
2376 lambda x: set(['other_config', 'backend'], x),
2377 'vifname':
2378 lambda x: set(['device'], x),
2379 'rate':
2380 lambda x: set(['qos_algorithm_params', 'rate'], x),
2381 'model':
2382 lambda x: None,
2383 'accel':
2384 lambda x: set(['other_config', 'accel'], x)
2387 for a in args[1:]:
2388 vif_param = a.split("=")
2389 if len(vif_param) != 2 or vif_param[1] == '' or \
2390 vif_param[0] not in vif_params:
2391 err("Invalid argument: %s" % a)
2392 usage('network-attach')
2393 else:
2394 vif_conv[vif_param[0]](vif_param[1])
2396 server.xenapi.VIF.create(vif_record)
2397 else:
2398 for a in args[1:]:
2399 vif_param = a.split("=")
2400 if len(vif_param) != 2 or vif_param[1] == '' or \
2401 vif_param[0] not in vif_params:
2402 err("Invalid argument: %s" % a)
2403 usage('network-attach')
2404 vif.append(vif_param)
2405 server.xend.domain.device_create(dom, vif)
2407 def parse_pci_configuration(args, state):
2408 dom = args[0]
2409 pci_dev_str = args[1]
2410 if len(args) == 3:
2411 vslt = args[2]
2412 else:
2413 vslt = '0x0' #chose a free virtual PCI slot
2414 pci=['pci']
2415 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
2416 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
2417 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
2418 r"(?P<func>[0-7])$", pci_dev_str)
2419 if pci_match == None:
2420 raise OptionError("Invalid argument: %s %s" % (pci_dev_str,vslt))
2421 pci_dev_info = pci_match.groupdict('0')
2422 try:
2423 pci.append(['dev', ['domain', '0x'+ pci_dev_info['domain']], \
2424 ['bus', '0x'+ pci_dev_info['bus']],
2425 ['slot', '0x'+ pci_dev_info['slot']],
2426 ['func', '0x'+ pci_dev_info['func']],
2427 ['vslt', '0x%x' % int(vslt, 16)]])
2428 except:
2429 raise OptionError("Invalid argument: %s %s" % (pci_dev_str,vslt))
2430 pci.append(['state', state])
2432 return (dom, pci)
2434 def xm_pci_attach(args):
2435 arg_check(args, 'pci-attach', 2, 3)
2436 (dom, pci) = parse_pci_configuration(args, 'Initialising')
2438 if serverType == SERVER_XEN_API:
2440 pci_dev = sxp.children(pci, 'dev')[0]
2441 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2442 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2443 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2444 func = int(sxp.child_value(pci_dev, 'func'), 16)
2445 vslt = int(sxp.child_value(pci_dev, 'vslt'), 16)
2446 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2448 target_ref = None
2449 for ppci_ref in server.xenapi.PPCI.get_all():
2450 if name == server.xenapi.PPCI.get_name(ppci_ref):
2451 target_ref = ppci_ref
2452 break
2453 if target_ref is None:
2454 raise OptionError("Device %s not found" % name)
2456 dpci_record = {
2457 "VM": get_single_vm(dom),
2458 "PPCI": target_ref,
2459 "hotplug_slot": vslt
2461 server.xenapi.DPCI.create(dpci_record)
2463 else:
2464 server.xend.domain.device_configure(dom, pci)
2466 def xm_scsi_attach(args):
2467 xenapi_unsupported()
2469 arg_check(args, 'scsi-attach', 3, 4)
2470 p_devname = args[1]
2471 v_dev = args[2]
2473 v_hctl = v_dev.split(':')
2474 if len(v_hctl) != 4:
2475 raise OptionError("Invalid argument: %s" % v_dev)
2477 (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_devname)
2479 if p_hctl == None:
2480 raise OptionError("Cannot find device \"%s\"" % p_devname)
2482 dom = args[0]
2483 vscsi = ['vscsi']
2484 vscsi.append(['dev', \
2485 ['state', 'Initialising'], \
2486 ['devid', v_hctl[0]], \
2487 ['p-dev', p_hctl], \
2488 ['p-devname', block], \
2489 ['v-dev', v_dev] ])
2491 if len(args) == 4:
2492 vscsi.append(['backend', args[3]])
2494 vscsi.append(['state', 'Initialising'])
2495 vscsi.append(['devid', v_hctl[0]])
2496 server.xend.domain.device_configure(dom, vscsi)
2498 def detach(args, deviceClass):
2499 rm_cfg = True
2500 dom = args[0]
2501 dev = args[1]
2502 try:
2503 force = args[2]
2504 if (force != "--force") and (force != "-f"):
2505 print "Ignoring option %s"%(force)
2506 force = None
2507 except IndexError:
2508 force = None
2510 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2513 def xm_block_detach(args):
2514 if serverType == SERVER_XEN_API:
2515 arg_check(args, "block-detach", 2, 3)
2516 dom = args[0]
2517 dev = args[1]
2518 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2519 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2520 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2521 if len(vbd_refs) > 0:
2522 vbd_ref = vbd_refs[0]
2523 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2525 server.xenapi.VBD.destroy(vbd_ref)
2527 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2528 server.xenapi.VDI.destroy(vdi_ref)
2529 else:
2530 raise OptionError("Cannot find device '%s' in domain '%s'"
2531 % (dev,dom))
2532 else:
2533 arg_check(args, 'block-detach', 2, 3)
2534 dom = args[0]
2535 dev = args[1]
2536 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2537 if dc == "tap":
2538 detach(args, 'tap')
2539 else:
2540 detach(args, 'vbd')
2542 def xm_network_detach(args):
2543 if serverType == SERVER_XEN_API:
2544 arg_check(args, "network-detach", 2, 3)
2545 dom = args[0]
2546 devid = args[1]
2547 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2548 vif_refs = [vif_ref for vif_ref in vif_refs
2549 if server.xenapi.VIF.\
2550 get_runtime_properties(vif_ref)["handle"] == devid]
2551 if len(vif_refs) > 0:
2552 vif_ref = vif_refs[0]
2554 server.xenapi.VIF.destroy(vif_ref)
2555 else:
2556 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2557 else:
2558 arg_check(args, 'network-detach', 2, 3)
2559 detach(args, 'vif')
2561 def xm_pci_detach(args):
2562 arg_check(args, 'pci-detach', 2)
2563 (dom, pci) = parse_pci_configuration(args, 'Closing')
2565 if serverType == SERVER_XEN_API:
2567 pci_dev = sxp.children(pci, 'dev')[0]
2568 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2569 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2570 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2571 func = int(sxp.child_value(pci_dev, 'func'), 16)
2572 vslt = int(sxp.child_value(pci_dev, 'vslt'), 16)
2573 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2575 target_ref = None
2576 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2577 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2578 if name == server.xenapi.PPCI.get_name(ppci_ref):
2579 target_ref = ppci_ref
2580 server.xenapi.DPCI.destroy(dpci_ref)
2581 break
2582 if target_ref is None:
2583 raise OptionError("Device %s not assigned" % name)
2585 else:
2586 server.xend.domain.device_configure(dom, pci)
2588 def xm_scsi_detach(args):
2589 xenapi_unsupported()
2590 arg_check(args, 'scsi-detach', 2)
2592 v_dev = args[1]
2593 v_hctl = v_dev.split(':')
2594 if len(v_hctl) != 4:
2595 raise OptionError("Invalid argument: %s" % v_dev)
2597 dom = args[0]
2598 vscsi = ['vscsi']
2599 vscsi.append(['dev', \
2600 ['state', 'Closing'], \
2601 ['devid', v_hctl[0]], \
2602 ['p-dev', ''], \
2603 ['p-devname', ''], \
2604 ['v-dev', v_dev] ])
2606 vscsi.append(['state', 'Closing'])
2607 vscsi.append(['devid', v_hctl[0]])
2608 server.xend.domain.device_configure(dom, vscsi)
2610 def xm_vnet_list(args):
2611 xenapi_unsupported()
2612 try:
2613 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2614 except getopt.GetoptError, opterr:
2615 err(opterr)
2616 usage('vnet-list')
2618 use_long = 0
2619 for (k, v) in options:
2620 if k in ['-l', '--long']:
2621 use_long = 1
2623 if params:
2624 use_long = 1
2625 vnets = params
2626 else:
2627 vnets = server.xend_vnets()
2629 for vnet in vnets:
2630 try:
2631 if use_long:
2632 info = server.xend_vnet(vnet)
2633 PrettyPrint.prettyprint(info)
2634 else:
2635 print vnet
2636 except Exception, ex:
2637 print vnet, ex
2639 def xm_vnet_create(args):
2640 xenapi_unsupported()
2641 arg_check(args, "vnet-create", 1)
2642 conf = args[0]
2643 if not os.access(conf, os.R_OK):
2644 print "File not found: %s" % conf
2645 sys.exit(1)
2647 server.xend_vnet_create(conf)
2649 def xm_vnet_delete(args):
2650 xenapi_unsupported()
2651 arg_check(args, "vnet-delete", 1)
2652 vnet = args[0]
2653 server.xend_vnet_delete(vnet)
2655 def xm_network_new(args):
2656 xenapi_only()
2657 arg_check(args, "network-new", 1)
2658 network = args[0]
2660 record = {
2661 "name_label": network,
2662 "name_description": "",
2663 "other_config": {},
2664 "default_gateway": "",
2665 "default_netmask": ""
2668 server.xenapi.network.create(record)
2670 def xm_network_del(args):
2671 xenapi_only()
2672 arg_check(args, "network-del", 1)
2673 network = args[0]
2675 networks = dict([(record['name_label'], ref)
2676 for ref, record in
2677 server.xenapi.network.get_all_records().items()])
2679 if network not in networks.keys():
2680 raise ValueError("'%s' is not a valid network name" % network)
2682 server.xenapi.network.destroy(networks[network])
2684 def xm_network_show(args):
2685 xenapi_only()
2686 arg_check(args, "network-show", 0)
2688 networks = server.xenapi.network.get_all_records()
2689 pifs = server.xenapi.PIF.get_all_records()
2690 vifs = server.xenapi.VIF.get_all_records()
2692 print '%-20s %-40s %-10s' % \
2693 ('Name', 'VIFs', 'PIFs')
2695 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2697 for network_ref, network in networks.items():
2698 for i in range(max(len(network['PIFs']),
2699 len(network['VIFs']), 1)):
2700 if i < len(network['PIFs']):
2701 pif_uuid = network['PIFs'][i]
2702 else:
2703 pif_uuid = None
2705 if i < len(network['VIFs']):
2706 vif_uuid = network['VIFs'][i]
2707 else:
2708 vif_uuid = None
2710 pif = pifs.get(pif_uuid, None)
2711 vif = vifs.get(vif_uuid, None)
2713 if vif:
2714 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2715 vif = "%s.%s" % (dom_name, vif['device'])
2716 else:
2717 vif = ''
2719 if pif:
2720 if int(pif['VLAN']) > -1:
2721 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2722 else:
2723 pif = pif['device']
2724 else:
2725 pif = ''
2727 if i == 0:
2728 r = {'name_label':network['name_label'],
2729 'vif':vif, 'pif':pif}
2730 else:
2731 r = {'name_label':'', 'vif':vif, 'pif':pif}
2733 print format2 % r
2736 commands = {
2737 "shell": xm_shell,
2738 "event-monitor": xm_event_monitor,
2739 # console commands
2740 "console": xm_console,
2741 "vncviewer": xm_vncviewer,
2742 # xenstat commands
2743 "top": xm_top,
2744 # domain commands
2745 "delete": xm_delete,
2746 "destroy": xm_destroy,
2747 "domid": xm_domid,
2748 "domname": xm_domname,
2749 "dump-core": xm_dump_core,
2750 "reboot": xm_reboot,
2751 "rename": xm_rename,
2752 "reset": xm_reset,
2753 "restore": xm_restore,
2754 "resume": xm_resume,
2755 "save": xm_save,
2756 "shutdown": xm_shutdown,
2757 "start": xm_start,
2758 "sysrq": xm_sysrq,
2759 "trigger": xm_trigger,
2760 "uptime": xm_uptime,
2761 "suspend": xm_suspend,
2762 "list": xm_list,
2763 # memory commands
2764 "mem-max": xm_mem_max,
2765 "mem-set": xm_mem_set,
2766 # cpu commands
2767 "vcpu-pin": xm_vcpu_pin,
2768 "vcpu-list": xm_vcpu_list,
2769 "vcpu-set": xm_vcpu_set,
2770 # special
2771 "pause": xm_pause,
2772 "unpause": xm_unpause,
2773 # host commands
2774 "debug-keys": xm_debug_keys,
2775 "dmesg": xm_dmesg,
2776 "info": xm_info,
2777 "log": xm_log,
2778 "serve": xm_serve,
2779 # scheduler
2780 "sched-sedf": xm_sched_sedf,
2781 "sched-credit": xm_sched_credit,
2782 # block
2783 "block-attach": xm_block_attach,
2784 "block-detach": xm_block_detach,
2785 "block-list": xm_block_list,
2786 "block-configure": xm_block_configure,
2787 # network (AKA vifs)
2788 "network-attach": xm_network_attach,
2789 "network-detach": xm_network_detach,
2790 "network-list": xm_network_list,
2791 # network (as in XenAPI)
2792 "network-new": xm_network_new,
2793 "network-del": xm_network_del,
2794 "network-show": xm_network_show,
2795 # vnet
2796 "vnet-list": xm_vnet_list,
2797 "vnet-create": xm_vnet_create,
2798 "vnet-delete": xm_vnet_delete,
2799 # vtpm
2800 "vtpm-list": xm_vtpm_list,
2801 #pci
2802 "pci-attach": xm_pci_attach,
2803 "pci-detach": xm_pci_detach,
2804 "pci-list": xm_pci_list,
2805 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
2806 # vscsi
2807 "scsi-attach": xm_scsi_attach,
2808 "scsi-detach": xm_scsi_detach,
2809 "scsi-list": xm_scsi_list,
2812 ## The commands supported by a separate argument parser in xend.xm.
2813 IMPORTED_COMMANDS = [
2814 'create',
2815 'new',
2816 'migrate',
2817 'labels',
2818 'dumppolicy',
2819 'addlabel',
2820 'rmlabel',
2821 'getlabel',
2822 'dry-run',
2823 'resources',
2824 'getpolicy',
2825 'setpolicy',
2826 'resetpolicy',
2829 for c in IMPORTED_COMMANDS:
2830 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2832 aliases = {
2833 "balloon": "mem-set",
2834 "set-vcpus": "vcpu-set",
2835 "vif-list": "network-list",
2836 "vbd-create": "block-attach",
2837 "vbd-destroy": "block-detach",
2838 "vbd-list": "block-list",
2842 def xm_lookup_cmd(cmd):
2843 if commands.has_key(cmd):
2844 return commands[cmd]
2845 elif aliases.has_key(cmd):
2846 deprecated(cmd,aliases[cmd])
2847 return commands[aliases[cmd]]
2848 elif cmd == 'help':
2849 longHelp()
2850 sys.exit(0)
2851 else:
2852 # simulate getopt's prefix matching behaviour
2853 if len(cmd) > 1:
2854 same_prefix_cmds = [commands[c] for c in commands.keys() \
2855 if c[:len(cmd)] == cmd]
2856 # only execute if there is only 1 match
2857 if len(same_prefix_cmds) == 1:
2858 return same_prefix_cmds[0]
2859 return None
2861 def deprecated(old,new):
2862 print >>sys.stderr, (
2863 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2865 def main(argv=sys.argv):
2866 if len(argv) < 2:
2867 usage()
2869 # intercept --help(-h) and output our own help
2870 for help in ['--help', '-h']:
2871 if help in argv[1:]:
2872 if help == argv[1]:
2873 longHelp()
2874 sys.exit(0)
2875 else:
2876 usage(argv[1])
2878 cmd_name = argv[1]
2879 cmd = xm_lookup_cmd(cmd_name)
2880 if cmd:
2881 # strip off prog name and subcmd
2882 args = argv[2:]
2883 _, rc = _run_cmd(cmd, cmd_name, args)
2884 sys.exit(rc)
2885 else:
2886 err('Subcommand %s not found!' % cmd_name)
2887 usage()
2889 def _run_cmd(cmd, cmd_name, args):
2890 global server
2892 try:
2893 if server is None:
2894 if serverType == SERVER_XEN_API:
2895 server = XenAPI.Session(serverURI)
2896 username, password = parseAuthentication()
2897 server.login_with_password(username, password)
2898 def logout():
2899 try:
2900 server.xenapi.session.logout()
2901 except:
2902 pass
2903 atexit.register(logout)
2904 else:
2905 server = ServerProxy(serverURI)
2907 return True, cmd(args)
2908 except socket.error, ex:
2909 if os.geteuid() != 0:
2910 err("Most commands need root access. Please try again as root.")
2911 else:
2912 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2913 except KeyboardInterrupt:
2914 print "Interrupted."
2915 return True, ''
2916 except IOError, ex:
2917 if os.geteuid() != 0:
2918 err("Most commands need root access. Please try again as root.")
2919 else:
2920 err("Unable to connect to xend: %s." % ex[1])
2921 except SystemExit, code:
2922 return code == 0, code
2923 except XenAPI.Failure, exn:
2924 for line in [''] + wrap(str(exn), 80) + ['']:
2925 print >>sys.stderr, line
2926 except xmlrpclib.Fault, ex:
2927 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2928 err("Domain '%s' does not exist." % ex.faultString)
2929 return False, ex.faultCode
2930 else:
2931 err(ex.faultString)
2932 _usage(cmd_name)
2933 except xmlrpclib.ProtocolError, ex:
2934 if ex.errcode == -1:
2935 print >>sys.stderr, (
2936 "Xend has probably crashed! Invalid or missing HTTP "
2937 "status code.")
2938 else:
2939 print >>sys.stderr, (
2940 "Xend has probably crashed! ProtocolError(%d, %s)." %
2941 (ex.errcode, ex.errmsg))
2942 except (ValueError, OverflowError):
2943 err("Invalid argument.")
2944 _usage(cmd_name)
2945 except OptionError, e:
2946 err(str(e))
2947 _usage(cmd_name)
2948 print e.usage
2949 except XenAPIUnsupportedException, e:
2950 err(str(e))
2951 except XSMError, e:
2952 err(str(e))
2953 except Exception, e:
2954 if serverType != SERVER_XEN_API:
2955 import xen.util.xsm.xsm as security
2956 if isinstance(e, security.XSMError):
2957 err(str(e))
2958 return False, 1
2959 print "Unexpected error:", sys.exc_info()[0]
2960 print
2961 print "Please report to xen-devel@lists.xensource.com"
2962 raise
2964 return False, 1
2966 if __name__ == "__main__":
2967 main()