ia64/xen-unstable

view tools/python/xen/xm/main.py @ 19199:94e12fa57816

xm save: Display help text if bad options specified.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 12 10:53:10 2009 +0000 (2009-02-12)
parents 7e15ccb7bbd8
children a35dffe6f1b6
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 *
50 from xen.xend.server.DevConstants import xenbusState
52 from xen.xm.opts import OptionError, Opts, wrap, set_true
53 from xen.xm import console
54 from xen.util.xmlrpcclient import ServerProxy
55 import xen.util.xsm.xsm as security
56 from xen.util.xsm.xsm import XSMError
57 from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
59 import XenAPI
61 import xen.lowlevel.xc
62 try:
63 xc = xen.lowlevel.xc.xc()
64 except Exception, ex:
65 print >>sys.stderr, ("Is xen kernel running?")
66 sys.exit(1)
68 import inspect
69 from xen.xend import XendOptions
70 xoptions = XendOptions.instance()
72 import signal
73 signal.signal(signal.SIGINT, signal.SIG_DFL)
75 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
76 # getopt.getopt if gnu_getopt is not available. This will mean that options
77 # may only be specified before positional arguments.
78 if not hasattr(getopt, 'gnu_getopt'):
79 getopt.gnu_getopt = getopt.getopt
81 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
82 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
84 # Supported types of server
85 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
86 SERVER_XEN_API = 'Xen-API'
88 # General help message
90 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
91 "Control, list, and manipulate Xen guest instances.\n"
93 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
94 'For more help on \'xm\' see the xm(1) man page.\n' \
95 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
96 ' man page.\n'
98 # Help strings are indexed by subcommand name in this way:
99 # 'subcommand': (argstring, description)
101 SUBCOMMAND_HELP = {
102 # common commands
104 'shell' : ('', 'Launch an interactive shell.'),
106 'console' : ('[-q|--quiet] <Domain>',
107 'Attach to <Domain>\'s console.'),
108 'vncviewer' : ('[--[vncviewer-]autopass] <Domain>',
109 'Attach to <Domain>\'s VNC server.'),
110 'create' : ('<ConfigFile> [options] [vars]',
111 'Create a domain based on <ConfigFile>.'),
112 'destroy' : ('<Domain>',
113 'Terminate a domain immediately.'),
114 'help' : ('', 'Display this message.'),
115 'list' : ('[options] [Domain, ...]',
116 'List information about all/some domains.'),
117 'mem-max' : ('<Domain> <Mem>',
118 'Set the maximum amount reservation for a domain.'),
119 'mem-set' : ('<Domain> <Mem>',
120 'Set the current memory usage for a domain.'),
121 'migrate' : ('<Domain> <Host>',
122 'Migrate a domain to another machine.'),
123 'pause' : ('<Domain>', 'Pause execution of a domain.'),
124 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
125 'reset' : ('<Domain>', 'Reset a domain.'),
126 'restore' : ('<CheckpointFile> [-p]',
127 'Restore a domain from a saved state.'),
128 'save' : ('[-c] <Domain> <CheckpointFile>',
129 'Save a domain state to restore later.'),
130 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
131 'top' : ('', 'Monitor a host and the domains in real time.'),
132 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
133 'uptime' : ('[-s] [Domain, ...]',
134 'Print uptime for all/some domains.'),
136 # Life cycle xm commands
137 'new' : ('<ConfigFile> [options] [vars]',
138 'Adds a domain to Xend domain management'),
139 'delete' : ('<DomainName>',
140 'Remove a domain from Xend domain management.'),
141 'start' : ('<DomainName>', 'Start a Xend managed domain'),
142 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
143 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
145 # less used commands
147 'dmesg' : ('[-c|--clear]',
148 'Read and/or clear Xend\'s message buffer.'),
149 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
150 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
151 'dump-core' : ('[-L|--live] [-C|--crash] [-R|--reset] <Domain> [Filename]',
152 'Dump core for a specific domain.'),
153 'info' : ('[-c|--config]', 'Get information about Xen host.'),
154 'log' : ('', 'Print Xend log'),
155 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
156 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
157 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
158 'Get/set credit scheduler parameters.'),
159 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
160 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
161 'trigger' : ('<Domain> <nmi|reset|init|s3resume> [<VCPU>]',
162 'Send a trigger to a domain.'),
163 'vcpu-list' : ('[Domain, ...]',
164 'List the VCPUs for all/some domains.'),
165 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
166 'Set which CPUs a VCPU can use.'),
167 'vcpu-set' : ('<Domain> <vCPUs>',
168 'Set the number of active VCPUs for allowed for the'
169 ' domain.'),
171 # device commands
173 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
174 'Create a new virtual block device.'),
175 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
176 'Change block device configuration'),
177 'block-detach' : ('<Domain> <DevId> [-f|--force]',
178 'Destroy a domain\'s virtual block device.'),
179 'block-list' : ('<Domain> [--long]',
180 'List virtual block devices for a domain.'),
181 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
182 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
183 '[vifname=<name>] [rate=<rate>] [model=<model>]'
184 '[accel=<accel>]',
185 'Create a new virtual network device.'),
186 'network-detach': ('<Domain> <DevId> [-f|--force]',
187 'Destroy a domain\'s virtual network device.'),
188 'network-list' : ('<Domain> [--long]',
189 'List virtual network interfaces for a domain.'),
190 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
191 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
192 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
193 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
194 'pci-attach' : ('[-o|--options=<opt>] <Domain> <domain:bus:slot.func> [virtual slot]',
195 'Insert a new pass-through pci device.'),
196 'pci-detach' : ('<Domain> <domain:bus:slot.func>',
197 'Remove a domain\'s pass-through pci device.'),
198 'pci-list' : ('<Domain>',
199 'List pass-through pci devices for a domain.'),
200 'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
201 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
202 'Attach a new SCSI device.'),
203 'scsi-detach' : ('<Domain> <VirtDevice>',
204 'Detach a specified SCSI device.'),
205 'scsi-list' : ('<Domain> [--long]',
206 'List all SCSI devices currently attached.'),
208 # security
210 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
211 ' [<policy>]',
212 'Add security label to domain.'),
213 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
214 'Remove a security label from domain.'),
215 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
216 'Show security label for domain or resource.'),
217 'dry-run' : ('<ConfigFile>',
218 'Test if a domain can access its resources.'),
219 'resources' : ('', 'Show info for each labeled resource.'),
220 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
221 'setpolicy' : ('<policytype> <policyfile> [options]',
222 'Set the policy of the system.'),
223 'resetpolicy' : ('',
224 'Set the policy of the system to the default policy.'),
225 'getpolicy' : ('[options]', 'Get the policy of the system.'),
226 'labels' : ('[policy] [type=dom|res|any]',
227 'List <type> labels for (active) policy.'),
228 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
229 }
231 SUBCOMMAND_OPTIONS = {
232 'sched-sedf': (
233 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
234 ('-s [MS]', '--slice[=MS]' ,
235 'Worst-case execution time(ms). (slice < period)'),
236 ('-l [MS]', '--latency[=MS]',
237 'Scaled period (ms) when domain performs heavy I/O'),
238 ('-e [FLAG]', '--extra[=FLAG]',
239 'Flag (0 or 1) controls if domain can run in extra time.'),
240 ('-w [FLOAT]', '--weight[=FLOAT]',
241 'CPU Period/slice (do not set with --period/--slice)'),
242 ),
243 'sched-credit': (
244 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
245 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
246 ('-c CAP', '--cap=CAP', 'Cap (int)'),
247 ),
248 'list': (
249 ('-l', '--long', 'Output all VM details in SXP'),
250 ('', '--label', 'Include security labels'),
251 ('', '--state=<state>', 'Select only VMs with the specified state'),
252 ),
253 'console': (
254 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
255 ),
256 'vncviewer': (
257 ('', '--autopass', 'Pass VNC password to viewer via stdin and -autopass'),
258 ('', '--vncviewer-autopass', '(consistency alias for --autopass)'),
259 ),
260 'dmesg': (
261 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
262 ),
263 'vnet-list': (
264 ('-l', '--long', 'List Vnets as SXP'),
265 ),
266 'network-list': (
267 ('-l', '--long', 'List resources as SXP'),
268 ),
269 'dump-core': (
270 ('-L', '--live', 'Dump core without pausing the domain'),
271 ('-C', '--crash', 'Crash domain after dumping core'),
272 ('-R', '--reset', 'Reset domain after dumping core'),
273 ),
274 'start': (
275 ('-p', '--paused', 'Do not unpause domain after starting it'),
276 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
277 ('', '--vncviewer', 'Connect to display via VNC after the domain is created'),
278 ('', '--vncviewer-autopass', 'Pass VNC password to viewer via stdin and -autopass'),
279 ),
280 'resume': (
281 ('-p', '--paused', 'Do not unpause domain after resuming it'),
282 ),
283 'save': (
284 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
285 ),
286 'restore': (
287 ('-p', '--paused', 'Do not unpause domain after restoring it'),
288 ),
289 'info': (
290 ('-c', '--config', 'List Xend configuration parameters'),
291 ),
292 }
294 common_commands = [
295 "console",
296 "vncviewer",
297 "create",
298 "new",
299 "delete",
300 "destroy",
301 "dump-core",
302 "help",
303 "list",
304 "mem-set",
305 "migrate",
306 "pause",
307 "reboot",
308 "reset",
309 "restore",
310 "resume",
311 "save",
312 "shell",
313 "shutdown",
314 "start",
315 "suspend",
316 "top",
317 "unpause",
318 "uptime",
319 "vcpu-set",
320 ]
322 domain_commands = [
323 "console",
324 "vncviewer",
325 "create",
326 "new",
327 "delete",
328 "destroy",
329 "domid",
330 "domname",
331 "dump-core",
332 "list",
333 "mem-max",
334 "mem-set",
335 "migrate",
336 "pause",
337 "reboot",
338 "rename",
339 "reset",
340 "restore",
341 "resume",
342 "save",
343 "shutdown",
344 "start",
345 "suspend",
346 "sysrq",
347 "trigger",
348 "top",
349 "unpause",
350 "uptime",
351 "vcpu-list",
352 "vcpu-pin",
353 "vcpu-set",
354 ]
356 host_commands = [
357 "debug-keys",
358 "dmesg",
359 "info",
360 "log",
361 "serve",
362 ]
364 scheduler_commands = [
365 "sched-credit",
366 "sched-sedf",
367 ]
369 device_commands = [
370 "block-attach",
371 "block-detach",
372 "block-list",
373 "block-configure",
374 "network-attach",
375 "network-detach",
376 "network-list",
377 "vtpm-list",
378 "pci-attach",
379 "pci-detach",
380 "pci-list",
381 "pci-list-assignable-devices",
382 "scsi-attach",
383 "scsi-detach",
384 "scsi-list",
385 ]
387 vnet_commands = [
388 "vnet-list",
389 "vnet-create",
390 "vnet-delete",
391 ]
393 acm_commands = [
394 "labels",
395 "addlabel",
396 "rmlabel",
397 "getlabel",
398 "dry-run",
399 "resources",
400 "dumppolicy",
401 "setpolicy",
402 "resetpolicy",
403 "getpolicy",
404 ]
406 all_commands = (domain_commands + host_commands + scheduler_commands +
407 device_commands + vnet_commands + acm_commands +
408 ['shell', 'event-monitor'])
411 ##
412 # Configuration File Parsing
413 ##
415 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
416 config = None
417 if os.path.isfile(xmConfigFile):
418 try:
419 config = xml.dom.minidom.parse(xmConfigFile)
420 except:
421 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
422 xmConfigFile)
424 def parseServer():
425 if config:
426 server = config.getElementsByTagName('server')
427 if server:
428 st = server[0].getAttribute('type')
429 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
430 print >>sys.stderr, ('Invalid server type %s; using %s.' %
431 (st, SERVER_LEGACY_XMLRPC))
432 st = SERVER_LEGACY_XMLRPC
433 return (st, server[0].getAttribute('uri'))
435 return SERVER_LEGACY_XMLRPC, XendClient.uri
437 def parseAuthentication():
438 server = config.getElementsByTagName('server')[0]
439 return (server.getAttribute('username'),
440 server.getAttribute('password'))
442 serverType, serverURI = parseServer()
443 server = None
446 ####################################################################
447 #
448 # Help/usage printing functions
449 #
450 ####################################################################
452 def cmdHelp(cmd):
453 """Print help for a specific subcommand."""
455 if not SUBCOMMAND_HELP.has_key(cmd):
456 for fc in SUBCOMMAND_HELP.keys():
457 if fc[:len(cmd)] == cmd:
458 cmd = fc
459 break
461 try:
462 args, desc = SUBCOMMAND_HELP[cmd]
463 except KeyError:
464 shortHelp()
465 return
467 print 'Usage: xm %s %s' % (cmd, args)
468 print
469 print desc
471 try:
472 # If options help message is defined, print this.
473 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
474 if shortopt and longopt:
475 optdesc = '%s, %s' % (shortopt, longopt)
476 elif shortopt:
477 optdesc = shortopt
478 elif longopt:
479 optdesc = longopt
481 wrapped_desc = wrap(desc, 43)
482 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
483 for line in wrapped_desc[1:]:
484 print ' ' * 33 + line
485 print
486 except KeyError:
487 # if the command is an external module, we grab usage help
488 # from the module itself.
489 if cmd in IMPORTED_COMMANDS:
490 try:
491 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
492 cmd_usage = getattr(cmd_module, "help", None)
493 if cmd_usage:
494 print cmd_usage()
495 except ImportError:
496 pass
498 def shortHelp():
499 """Print out generic help when xm is called without subcommand."""
501 print USAGE_HELP
502 print 'Common \'xm\' commands:\n'
504 for command in common_commands:
505 try:
506 args, desc = SUBCOMMAND_HELP[command]
507 except KeyError:
508 continue
509 wrapped_desc = wrap(desc, 50)
510 print ' %-20s %-50s' % (command, wrapped_desc[0])
511 for line in wrapped_desc[1:]:
512 print ' ' * 22 + line
514 print
515 print USAGE_FOOTER
516 print 'For a complete list of subcommands run \'xm help\'.'
518 def longHelp():
519 """Print out full help when xm is called with xm --help or xm help"""
521 print USAGE_HELP
522 print 'xm full list of subcommands:\n'
524 for command in all_commands:
525 try:
526 args, desc = SUBCOMMAND_HELP[command]
527 except KeyError:
528 continue
530 wrapped_desc = wrap(desc, 50)
531 print ' %-20s %-50s' % (command, wrapped_desc[0])
532 for line in wrapped_desc[1:]:
533 print ' ' * 22 + line
535 print
536 print USAGE_FOOTER
538 def _usage(cmd):
539 """ Print help usage information """
540 if cmd:
541 cmdHelp(cmd)
542 else:
543 shortHelp()
545 def usage(cmd = None):
546 """ Print help usage information and exits """
547 _usage(cmd)
548 sys.exit(1)
551 ####################################################################
552 #
553 # Utility functions
554 #
555 ####################################################################
557 def get_default_SR():
558 return [sr_ref
559 for sr_ref in server.xenapi.SR.get_all()
560 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
562 def get_default_Network():
563 return [network_ref
564 for network_ref in server.xenapi.network.get_all()][0]
566 class XenAPIUnsupportedException(Exception):
567 pass
569 def xenapi_unsupported():
570 if serverType == SERVER_XEN_API:
571 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
573 def xenapi_only():
574 if serverType != SERVER_XEN_API:
575 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
577 def map2sxp(m):
578 return [[k, m[k]] for k in m.keys()]
580 def arg_check(args, name, lo, hi = -1):
581 n = len([i for i in args if i != '--'])
583 if hi == -1:
584 if n != lo:
585 err("'xm %s' requires %d argument%s.\n" % (name, lo,
586 lo == 1 and '' or 's'))
587 usage(name)
588 else:
589 if n < lo or n > hi:
590 err("'xm %s' requires between %d and %d arguments.\n" %
591 (name, lo, hi))
592 usage(name)
595 def unit(c):
596 if not c.isalpha():
597 return 0
598 base = 1
599 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
600 elif c == 'M' or c == 'm': base = 1024 * 1024
601 elif c == 'K' or c == 'k': base = 1024
602 else:
603 print 'ignoring unknown unit'
604 return base
606 def int_unit(str, dest):
607 base = unit(str[-1])
608 if not base:
609 return int(str)
611 value = int(str[:-1])
612 dst_base = unit(dest)
613 if dst_base == 0:
614 dst_base = 1
615 if dst_base > base:
616 return value / (dst_base / base)
617 else:
618 return value * (base / dst_base)
620 def err(msg):
621 print >>sys.stderr, "Error:", msg
624 def get_single_vm(dom):
625 if serverType == SERVER_XEN_API:
626 uuids = server.xenapi.VM.get_by_name_label(dom)
627 if len(uuids) > 0:
628 return uuids[0]
630 refs = []
632 try:
633 domid = int(dom)
634 refs = [vm_ref
635 for vm_ref in server.xenapi.VM.get_all()
636 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
637 except:
638 pass
640 if len(refs) > 0:
641 return refs[0]
643 raise OptionError("Domain '%s' not found." % dom)
644 else:
645 dominfo = server.xend.domain(dom, False)
646 return dominfo['uuid']
648 ##
649 #
650 # Xen-API Shell
651 #
652 ##
654 class Shell(cmd.Cmd):
655 def __init__(self):
656 cmd.Cmd.__init__(self)
657 self.prompt = "xm> "
658 if serverType == SERVER_XEN_API:
659 try:
660 res = server.xenapi.host.list_methods()
661 for f in res:
662 setattr(Shell, 'do_' + f + ' ', self.default)
663 except:
664 pass
666 def preloop(self):
667 cmd.Cmd.preloop(self)
668 try:
669 import readline
670 readline.set_completer_delims(' ')
671 except ImportError:
672 pass
674 def default(self, line):
675 words = shlex.split(line)
676 if len(words) > 0 and words[0] == 'xm':
677 words = words[1:]
678 if len(words) > 0:
679 cmd = xm_lookup_cmd(words[0])
680 if cmd:
681 _run_cmd(cmd, words[0], words[1:])
682 elif serverType == SERVER_XEN_API:
683 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
684 tuple(x)),
685 words[0], words[1:])
686 if ok and res is not None and res != '':
687 pprint.pprint(res)
688 else:
689 print '*** Unknown command: %s' % words[0]
690 return False
692 def completedefault(self, text, line, begidx, endidx):
693 words = shlex.split(line[:begidx])
694 clas, func = words[0].split('.')
695 if len(words) > 1 or \
696 func.startswith('get_by_') or \
697 func == 'get_all':
698 return []
699 uuids = server.xenapi_request('%s.get_all' % clas, ())
700 return [u + " " for u in uuids if u.startswith(text)]
702 def emptyline(self):
703 pass
705 def do_EOF(self, line):
706 print
707 sys.exit(0)
709 def do_help(self, line):
710 _usage(line)
713 def xm_shell(args):
714 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
717 def xm_event_monitor(args):
718 if serverType == SERVER_XEN_API:
719 while True:
720 server.xenapi.event.register(args)
721 events = server.xenapi.event.next()
722 for e in events:
723 print e
724 else:
725 err("Event monitoring not supported unless using Xen-API.")
728 #########################################################################
729 #
730 # Main xm functions
731 #
732 #########################################################################
734 def xm_save(args):
736 arg_check(args, "save", 2, 3)
738 try:
739 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
740 except getopt.GetoptError, opterr:
741 err(opterr)
742 usage('save')
744 checkpoint = False
745 for (k, v) in options:
746 if k in ['-c', '--checkpoint']:
747 checkpoint = True
749 if len(params) != 2:
750 err("Wrong number of parameters")
751 usage('save')
753 dom = params[0]
754 savefile = os.path.abspath(params[1])
756 if not os.access(os.path.dirname(savefile), os.W_OK):
757 err("xm save: Unable to create file %s" % savefile)
758 sys.exit(1)
760 if serverType == SERVER_XEN_API:
761 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
762 else:
763 server.xend.domain.save(dom, savefile, checkpoint)
765 def xm_restore(args):
766 arg_check(args, "restore", 1, 2)
768 try:
769 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
770 except getopt.GetoptError, opterr:
771 err(opterr)
772 usage('restore')
774 paused = False
775 for (k, v) in options:
776 if k in ['-p', '--paused']:
777 paused = True
779 if len(params) != 1:
780 err("Wrong number of parameters")
781 usage('restore')
783 savefile = os.path.abspath(params[0])
785 if not os.access(savefile, os.R_OK):
786 err("xm restore: Unable to read file %s" % savefile)
787 sys.exit(1)
789 if serverType == SERVER_XEN_API:
790 server.xenapi.VM.restore(savefile, paused)
791 else:
792 server.xend.domain.restore(savefile, paused)
795 def datetime_to_secs(v):
796 unwanted = ":-."
797 for c in unwanted:
798 v = str(v).replace(c, "")
799 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
801 def getDomains(domain_names, state, full = 0):
802 if serverType == SERVER_XEN_API:
803 doms_sxp = []
804 doms_dict = []
806 dom_recs = server.xenapi.VM.get_all_records()
807 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
809 for dom_ref, dom_rec in dom_recs.items():
810 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
812 states = ('running', 'blocked', 'paused', 'shutdown',
813 'crashed', 'dying')
814 def state_on_off(state):
815 if state in dom_metrics_rec['state']:
816 return state[0]
817 else:
818 return "-"
819 state_str = "".join([state_on_off(state)
820 for state in states])
822 dom_rec.update({'name': dom_rec['name_label'],
823 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
824 'vcpus': dom_metrics_rec['VCPUs_number'],
825 'state': state_str,
826 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
827 'start_time': datetime_to_secs(
828 dom_metrics_rec['start_time'])})
830 doms_sxp.append(['domain'] + map2sxp(dom_rec))
831 doms_dict.append(dom_rec)
833 if domain_names:
834 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
835 if dom["name"] in domain_names]
837 if len(doms) > 0:
838 return doms
839 else:
840 print "Error: no domain%s named %s" % \
841 (len(domain_names) > 1 and 's' or '',
842 ', '.join(domain_names))
843 sys.exit(-1)
844 else:
845 return doms_sxp
846 else:
847 if domain_names:
848 return [server.xend.domain(dom, full) for dom in domain_names]
849 else:
850 return server.xend.domains_with_state(True, state, full)
853 def xm_list(args):
854 use_long = 0
855 show_vcpus = 0
856 show_labels = 0
857 state = 'all'
858 try:
859 (options, params) = getopt.gnu_getopt(args, 'lv',
860 ['long','vcpus','label',
861 'state='])
862 except getopt.GetoptError, opterr:
863 err(opterr)
864 usage('list')
866 for (k, v) in options:
867 if k in ['-l', '--long']:
868 use_long = 1
869 if k in ['-v', '--vcpus']:
870 show_vcpus = 1
871 if k in ['--label']:
872 show_labels = 1
873 if k in ['--state']:
874 state = v
876 if state != 'all' and len(params) > 0:
877 raise OptionError(
878 "You may specify either a state or a particular VM, but not both")
880 if show_vcpus:
881 print >>sys.stderr, (
882 "xm list -v is deprecated. Please use xm vcpu-list.")
883 xm_vcpu_list(params)
884 return
886 doms = getDomains(params, state, use_long)
888 if use_long:
889 map(PrettyPrint.prettyprint, doms)
890 elif show_labels:
891 xm_label_list(doms)
892 else:
893 xm_brief_list(doms)
896 def parse_doms_info(info):
897 def get_info(n, t, d):
898 return t(sxp.child_value(info, n, d))
900 def get_status(n, t, d):
901 return DOM_STATES[t(sxp.child_value(info, n, d))]
903 start_time = get_info('start_time', float, -1)
904 if start_time == -1:
905 up_time = float(-1)
906 else:
907 up_time = time.time() - start_time
909 parsed_info = {
910 'domid' : get_info('domid', str, ''),
911 'name' : get_info('name', str, '??'),
912 'state' : get_info('state', str, ''),
914 # VCPUs is the number online when the VM is up, or the number
915 # configured otherwise.
916 'vcpus' : get_info('online_vcpus', int,
917 get_info('vcpus', int, 0)),
918 'up_time' : up_time
919 }
921 security_label = get_info('security_label', str, '')
922 parsed_info['seclabel'] = security.parse_security_label(security_label)
924 if serverType == SERVER_XEN_API:
925 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
926 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
927 if sum(cpu_times.values()) > 0:
928 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
929 else:
930 parsed_info['cpu_time'] = 0
931 else:
932 parsed_info['mem'] = get_info('memory', int,0)
933 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
935 return parsed_info
937 def check_sched_type(sched):
938 if serverType == SERVER_XEN_API:
939 current = server.xenapi.host.get_sched_policy(
940 server.xenapi.session.get_this_host(server.getSession()))
941 else:
942 current = 'unknown'
943 for x in server.xend.node.info()[1:]:
944 if len(x) > 1 and x[0] == 'xen_scheduler':
945 current = x[1]
946 break
947 if sched != current:
948 err("Xen is running with the %s scheduler" % current)
949 sys.exit(1)
951 def parse_sedf_info(info):
952 def get_info(n, t, d):
953 return t(sxp.child_value(info, n, d))
955 return {
956 'domid' : get_info('domid', int, -1),
957 'period' : get_info('period', int, -1),
958 'slice' : get_info('slice', int, -1),
959 'latency' : get_info('latency', int, -1),
960 'extratime': get_info('extratime', int, -1),
961 'weight' : get_info('weight', int, -1),
962 }
964 def domid_match(domid, info):
965 return domid is None or domid == info['name'] or \
966 domid == str(info['domid'])
968 def xm_brief_list(doms):
969 print '%-40s %5s %5s %5s %10s %9s' % \
970 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
972 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
973 "%(cpu_time)8.1f"
975 for dom in doms:
976 d = parse_doms_info(dom)
977 print format % d
979 def xm_label_list(doms):
980 print '%-40s %5s %5s %5s %10s %9s %-10s' % \
981 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
983 output = []
984 format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
985 '%(cpu_time)8.1f %(seclabel)10s'
987 for dom in doms:
988 d = parse_doms_info(dom)
989 if d['seclabel'] == "" and serverType != SERVER_XEN_API:
990 seclab = server.xend.security.get_domain_label(d['name'])
991 if len(seclab) > 0 and seclab[0] == '\'':
992 seclab = seclab[1:]
993 d['seclabel'] = seclab
994 output.append((format % d, d['seclabel']))
996 #sort by labels
997 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
998 for line, label in output:
999 print line
1002 def xm_vcpu_list(args):
1003 if serverType == SERVER_XEN_API:
1004 if args:
1005 vm_refs = map(get_single_vm, args)
1006 else:
1007 vm_refs = server.xenapi.VM.get_all()
1009 vm_records = dict(map(lambda vm_ref:
1010 (vm_ref, server.xenapi.VM.get_record(
1011 vm_ref)),
1012 vm_refs))
1014 vm_metrics = dict(map(lambda (ref, record):
1015 (ref,
1016 server.xenapi.VM_metrics.get_record(
1017 record['metrics'])),
1018 vm_records.items()))
1020 dominfo = []
1022 # vcpu_list doesn't list 'managed' domains
1023 # when they are not running, so filter them out
1025 vm_refs = [vm_ref
1026 for vm_ref in vm_refs
1027 if vm_records[vm_ref]["power_state"] != "Halted"]
1029 for vm_ref in vm_refs:
1030 info = ['domain',
1031 ['domid', vm_records[vm_ref]['domid']],
1032 ['name', vm_records[vm_ref]['name_label']],
1033 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
1035 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
1036 def chk_flag(flag):
1037 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1038 and 1 or 0
1040 vcpu_info = ['vcpu',
1041 ['number',
1042 i],
1043 ['online',
1044 chk_flag("online")],
1045 ['blocked',
1046 chk_flag("blocked")],
1047 ['running',
1048 chk_flag("running")],
1049 ['cpu_time',
1050 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1051 ['cpu',
1052 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1053 ['cpumap',
1054 vm_metrics[vm_ref]['VCPUs_params']\
1055 ['cpumap%i' % i].split(",")]]
1057 info.append(vcpu_info)
1059 dominfo.append(info)
1060 else:
1061 if args:
1062 dominfo = map(server.xend.domain.getVCPUInfo, args)
1063 else:
1064 doms = server.xend.domains_with_state(False, 'all', False)
1065 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1067 print '%-32s %5s %5s %5s %5s %9s %s' % \
1068 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1070 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1071 ' %(cpu_time)8.1f %(cpumap)s'
1073 for dom in dominfo:
1074 def get_info(n):
1075 return sxp.child_value(dom, n)
1078 # convert a list of integers into a list of pairs indicating
1079 # continuous sequences in the list:
1081 # [0,1,2,3] -> [(0,3)]
1082 # [1,2,4,5] -> [(1,2),(4,5)]
1083 # [0] -> [(0,0)]
1084 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1086 def list_to_rangepairs(cmap):
1087 cmap.sort()
1088 pairs = []
1089 x = y = 0
1090 for i in range(0,len(cmap)):
1091 try:
1092 if ((cmap[y+1] - cmap[i]) > 1):
1093 pairs.append((cmap[x],cmap[y]))
1094 x = y = i+1
1095 else:
1096 y = y + 1
1097 # if we go off the end, then just add x to y
1098 except IndexError:
1099 pairs.append((cmap[x],cmap[y]))
1101 return pairs
1104 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1106 def format_pairs(pairs):
1107 if not pairs:
1108 return "no cpus"
1109 out = ""
1110 for f,s in pairs:
1111 if (f==s):
1112 out += '%d'%f
1113 else:
1114 out += '%d-%d'%(f,s)
1115 out += ','
1116 # trim trailing ','
1117 return out[:-1]
1119 def format_cpumap(cpumap):
1120 cpumap = map(lambda x: int(x), cpumap)
1121 cpumap.sort()
1123 if serverType == SERVER_XEN_API:
1124 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1125 server.xenapi.session.get_this_host(server.getSession())))
1126 else:
1127 for x in server.xend.node.info()[1:]:
1128 if len(x) > 1 and x[0] == 'nr_cpus':
1129 nr_cpus = int(x[1])
1131 # normalize cpumap by modulus nr_cpus, and drop duplicates
1132 cpumap = dict.fromkeys(
1133 filter(lambda x: x < nr_cpus, cpumap)).keys()
1134 if len(cpumap) == nr_cpus:
1135 return "any cpu"
1137 return format_pairs(list_to_rangepairs(cpumap))
1139 name = get_info('name')
1140 domid = get_info('domid')
1141 if domid is not None:
1142 domid = str(domid)
1143 else:
1144 domid = ''
1146 for vcpu in sxp.children(dom, 'vcpu'):
1147 def vinfo(n, t):
1148 return t(sxp.child_value(vcpu, n))
1150 number = vinfo('number', int)
1151 cpu = vinfo('cpu', int)
1152 cpumap = format_cpumap(vinfo('cpumap', list))
1153 online = vinfo('online', int)
1154 cpu_time = vinfo('cpu_time', float)
1155 running = vinfo('running', int)
1156 blocked = vinfo('blocked', int)
1158 if cpu < 0:
1159 c = ''
1160 s = ''
1161 elif online:
1162 c = str(cpu)
1163 if running:
1164 s = 'r'
1165 else:
1166 s = '-'
1167 if blocked:
1168 s += 'b'
1169 else:
1170 s += '-'
1171 s += '-'
1172 else:
1173 c = '-'
1174 s = '--p'
1176 print format % locals()
1178 def start_do_console(domain_name):
1179 cpid = os.fork()
1180 if cpid != 0:
1181 for i in range(10):
1182 # Catch failure of the create process
1183 time.sleep(1)
1184 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1185 if os.WIFEXITED(rv):
1186 if os.WEXITSTATUS(rv) != 0:
1187 sys.exit(os.WEXITSTATUS(rv))
1188 try:
1189 # Acquire the console of the created dom
1190 if serverType == SERVER_XEN_API:
1191 domid = server.xenapi.VM.get_domid(
1192 get_single_vm(domain_name))
1193 else:
1194 dom = server.xend.domain(domain_name)
1195 domid = int(sxp.child_value(dom, 'domid', '-1'))
1196 console.execConsole(domid)
1197 except:
1198 pass
1199 print("Could not start console\n");
1200 sys.exit(0)
1202 def xm_start(args):
1204 paused = False
1205 console_autoconnect = False
1206 vncviewer = False
1207 vncviewer_autopass = False
1209 try:
1210 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused','vncviewer','vncviewer-autopass'])
1211 for (k, v) in options:
1212 if k in ('-p', '--paused'):
1213 paused = True
1214 if k in ('-c', '--console_autoconnect'):
1215 console_autoconnect = True
1216 if k in ('--vncviewer'):
1217 vncviewer = True
1218 if k in ('--vncviewer-autopass'):
1219 vncviewer_autopass = True
1221 if len(params) != 1:
1222 raise OptionError("Expects 1 argument")
1223 except getopt.GetoptError, opterr:
1224 err(opterr)
1225 usage('start')
1227 dom = params[0]
1229 if console_autoconnect:
1230 start_do_console(dom)
1232 try:
1233 if serverType == SERVER_XEN_API:
1234 server.xenapi.VM.start(get_single_vm(dom), paused)
1235 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1236 else:
1237 server.xend.domain.start(dom, paused)
1238 info = server.xend.domain(dom)
1239 domid = int(sxp.child_value(info, 'domid', '-1'))
1240 except:
1241 raise
1243 if domid == -1:
1244 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1246 if vncviewer:
1247 console.runVncViewer(domid, vncviewer_autopass, True)
1250 def xm_delete(args):
1251 arg_check(args, "delete", 1)
1252 dom = args[0]
1253 if serverType == SERVER_XEN_API:
1254 server.xenapi.VM.destroy(get_single_vm(dom))
1255 else:
1256 server.xend.domain.delete(dom)
1258 def xm_suspend(args):
1259 arg_check(args, "suspend", 1)
1260 dom = args[0]
1261 if serverType == SERVER_XEN_API:
1262 server.xenapi.VM.suspend(get_single_vm(dom))
1263 else:
1264 server.xend.domain.suspend(dom)
1266 def xm_resume(args):
1267 arg_check(args, "resume", 1, 2)
1269 try:
1270 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1271 except getopt.GetoptError, opterr:
1272 err(opterr)
1273 usage('resume')
1275 paused = False
1276 for (k, v) in options:
1277 if k in ['-p', '--paused']:
1278 paused = True
1280 if len(params) != 1:
1281 err("Wrong number of parameters")
1282 usage('resume')
1284 dom = params[0]
1285 if serverType == SERVER_XEN_API:
1286 server.xenapi.VM.resume(get_single_vm(dom), paused)
1287 else:
1288 server.xend.domain.resume(dom, paused)
1290 def xm_reboot(args):
1291 arg_check(args, "reboot", 1, 3)
1292 from xen.xm import shutdown
1293 shutdown.main(["shutdown", "-R"] + args)
1295 def xm_shutdown(args):
1296 arg_check(args, "shutdown", 1, 4)
1297 from xen.xm import shutdown
1298 shutdown.main(["shutdown"] + args)
1300 def xm_reset(args):
1301 arg_check(args, "reset", 1)
1302 dom = args[0]
1304 if serverType == SERVER_XEN_API:
1305 server.xenapi.VM.hard_reboot(get_single_vm(dom))
1306 else:
1307 server.xend.domain.reset(dom)
1309 def xm_pause(args):
1310 arg_check(args, "pause", 1)
1311 dom = args[0]
1313 if serverType == SERVER_XEN_API:
1314 server.xenapi.VM.pause(get_single_vm(dom))
1315 else:
1316 server.xend.domain.pause(dom)
1318 def xm_unpause(args):
1319 arg_check(args, "unpause", 1)
1320 dom = args[0]
1322 if serverType == SERVER_XEN_API:
1323 server.xenapi.VM.unpause(get_single_vm(dom))
1324 else:
1325 server.xend.domain.unpause(dom)
1327 def xm_dump_core(args):
1328 live = False
1329 crash = False
1330 reset = False
1331 try:
1332 (options, params) = getopt.gnu_getopt(args, 'LCR', ['live', 'crash', 'reset'])
1333 for (k, v) in options:
1334 if k in ('-L', '--live'):
1335 live = True
1336 elif k in ('-C', '--crash'):
1337 crash = True
1338 elif k in ('-R', '--reset'):
1339 reset = True
1341 if crash and reset:
1342 raise OptionError("You may not specify more than one '-CR' option")
1343 if len(params) not in (1, 2):
1344 raise OptionError("Expects 1 or 2 argument(s)")
1345 except getopt.GetoptError, e:
1346 raise OptionError(str(e))
1348 dom = params[0]
1349 if len(params) == 2:
1350 filename = os.path.abspath(params[1])
1351 else:
1352 filename = None
1354 if not live:
1355 ds = server.xend.domain.pause(dom, True)
1357 try:
1358 print "Dumping core of domain: %s ..." % str(dom)
1359 server.xend.domain.dump(dom, filename, live, crash)
1361 if crash:
1362 print "Destroying domain: %s ..." % str(dom)
1363 server.xend.domain.destroy(dom)
1364 elif reset:
1365 print "Resetting domain: %s ..." % str(dom)
1366 server.xend.domain.reset(dom)
1367 finally:
1368 if not live and not crash and not reset and ds == DOM_STATE_RUNNING:
1369 server.xend.domain.unpause(dom)
1371 def xm_rename(args):
1372 arg_check(args, "rename", 2)
1374 if serverType == SERVER_XEN_API:
1375 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1376 else:
1377 server.xend.domain.setName(args[0], args[1])
1379 def xm_importcommand(command, args):
1380 cmd = __import__(command, globals(), locals(), 'xen.xm')
1381 cmd.main([command] + args)
1384 #############################################################
1386 def xm_vcpu_pin(args):
1387 arg_check(args, "vcpu-pin", 3)
1389 def cpu_make_map(cpulist):
1390 cpus = []
1391 for c in cpulist.split(','):
1392 if c.find('-') != -1:
1393 (x,y) = c.split('-')
1394 for i in range(int(x),int(y)+1):
1395 cpus.append(int(i))
1396 else:
1397 # remove this element from the list
1398 if c[0] == '^':
1399 cpus = [x for x in cpus if x != int(c[1:])]
1400 else:
1401 cpus.append(int(c))
1402 cpus.sort()
1403 return cpus
1405 dom = args[0]
1406 vcpu = args[1]
1407 if args[2] == 'all':
1408 cpumap = cpu_make_map('0-63')
1409 else:
1410 cpumap = cpu_make_map(args[2])
1412 if serverType == SERVER_XEN_API:
1413 cpumap = map(str, cpumap)
1414 server.xenapi.VM.add_to_VCPUs_params_live(
1415 get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap))
1416 else:
1417 server.xend.domain.pincpu(dom, vcpu, cpumap)
1419 def xm_mem_max(args):
1420 arg_check(args, "mem-max", 2)
1422 dom = args[0]
1424 if serverType == SERVER_XEN_API:
1425 mem = int_unit(args[1], 'k') * 1024
1426 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1427 else:
1428 mem = int_unit(args[1], 'm')
1429 server.xend.domain.maxmem_set(dom, mem)
1431 def xm_mem_set(args):
1432 arg_check(args, "mem-set", 2)
1434 dom = args[0]
1436 if serverType == SERVER_XEN_API:
1437 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1438 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1439 mem_target)
1440 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1441 mem_target)
1442 else:
1443 mem_target = int_unit(args[1], 'm')
1444 server.xend.domain.setMemoryTarget(dom, mem_target)
1446 def xm_vcpu_set(args):
1447 arg_check(args, "vcpu-set", 2)
1449 dom = args[0]
1450 vcpus = int(args[1])
1452 if serverType == SERVER_XEN_API:
1453 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1454 else:
1455 server.xend.domain.setVCpuCount(dom, vcpus)
1457 def xm_destroy(args):
1458 arg_check(args, "destroy", 1)
1460 dom = args[0]
1462 if serverType == SERVER_XEN_API:
1463 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1464 else:
1465 server.xend.domain.destroy(dom)
1467 def xm_domid(args):
1468 arg_check(args, "domid", 1)
1470 name = args[0]
1472 if serverType == SERVER_XEN_API:
1473 print server.xenapi.VM.get_domid(get_single_vm(name))
1474 else:
1475 dom = server.xend.domain(name)
1476 print sxp.child_value(dom, 'domid')
1478 def xm_domname(args):
1479 arg_check(args, "domname", 1)
1481 name = args[0]
1483 if serverType == SERVER_XEN_API:
1484 print server.xenapi.VM.get_name_label(get_single_vm(name))
1485 else:
1486 dom = server.xend.domain(name)
1487 print sxp.child_value(dom, 'name')
1489 def xm_sched_sedf(args):
1490 xenapi_unsupported()
1492 def ns_to_ms(val):
1493 return float(val) * 0.000001
1495 def ms_to_ns(val):
1496 return (float(val) / 0.000001)
1498 def print_sedf(info):
1499 info['period'] = ns_to_ms(info['period'])
1500 info['slice'] = ns_to_ms(info['slice'])
1501 info['latency'] = ns_to_ms(info['latency'])
1502 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1503 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1505 check_sched_type('sedf')
1507 # we want to just display current info if no parameters are passed
1508 if len(args) == 0:
1509 domid = None
1510 else:
1511 # we expect at least a domain id (name or number)
1512 # and at most a domid up to 5 options with values
1513 arg_check(args, "sched-sedf", 1, 11)
1514 domid = args[0]
1515 # drop domid from args since get_opt doesn't recognize it
1516 args = args[1:]
1518 opts = {}
1519 try:
1520 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1521 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1522 except getopt.GetoptError, opterr:
1523 err(opterr)
1524 usage('sched-sedf')
1526 # convert to nanoseconds if needed
1527 for (k, v) in options:
1528 if k in ['-p', '--period']:
1529 opts['period'] = ms_to_ns(v)
1530 elif k in ['-s', '--slice']:
1531 opts['slice'] = ms_to_ns(v)
1532 elif k in ['-l', '--latency']:
1533 opts['latency'] = ms_to_ns(v)
1534 elif k in ['-e', '--extratime']:
1535 opts['extratime'] = v
1536 elif k in ['-w', '--weight']:
1537 opts['weight'] = v
1539 doms = filter(lambda x : domid_match(domid, x),
1540 [parse_doms_info(dom)
1541 for dom in getDomains(None, 'running')])
1542 if domid is not None and doms == []:
1543 err("Domain '%s' does not exist." % domid)
1544 usage('sched-sedf')
1546 # print header if we aren't setting any parameters
1547 if len(opts.keys()) == 0:
1548 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1549 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1550 'Extra','Weight')
1552 for d in doms:
1553 # fetch current values so as not to clobber them
1554 try:
1555 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1556 except xmlrpclib.Fault:
1557 # domain does not support sched-sedf?
1558 sedf_raw = {}
1560 sedf_info = parse_sedf_info(sedf_raw)
1561 sedf_info['name'] = d['name']
1562 # update values in case of call to set
1563 if len(opts.keys()) > 0:
1564 for k in opts.keys():
1565 sedf_info[k]=opts[k]
1567 # send the update, converting user input
1568 v = map(int, [sedf_info['period'], sedf_info['slice'],
1569 sedf_info['latency'],sedf_info['extratime'],
1570 sedf_info['weight']])
1571 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1572 if int(rv) != 0:
1573 err("Failed to set sedf parameters (rv=%d)."%(rv))
1575 # not setting values, display info
1576 else:
1577 print_sedf(sedf_info)
1579 def xm_sched_credit(args):
1580 """Get/Set options for Credit Scheduler."""
1582 check_sched_type('credit')
1584 try:
1585 opts, params = getopt.getopt(args, "d:w:c:",
1586 ["domain=", "weight=", "cap="])
1587 except getopt.GetoptError, opterr:
1588 err(opterr)
1589 usage('sched-credit')
1591 domid = None
1592 weight = None
1593 cap = None
1595 for o, a in opts:
1596 if o in ["-d", "--domain"]:
1597 domid = a
1598 elif o in ["-w", "--weight"]:
1599 weight = int(a)
1600 elif o in ["-c", "--cap"]:
1601 cap = int(a);
1603 doms = filter(lambda x : domid_match(domid, x),
1604 [parse_doms_info(dom)
1605 for dom in getDomains(None, 'all')])
1607 if weight is None and cap is None:
1608 if domid is not None and doms == []:
1609 err("Domain '%s' does not exist." % domid)
1610 usage('sched-credit')
1611 # print header if we aren't setting any parameters
1612 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1614 for d in doms:
1615 try:
1616 if serverType == SERVER_XEN_API:
1617 info = server.xenapi.VM_metrics.get_VCPUs_params(
1618 server.xenapi.VM.get_metrics(
1619 get_single_vm(d['name'])))
1620 else:
1621 info = server.xend.domain.sched_credit_get(d['name'])
1622 except xmlrpclib.Fault:
1623 pass
1625 if 'weight' not in info or 'cap' not in info:
1626 # domain does not support sched-credit?
1627 info = {'weight': -1, 'cap': -1}
1629 info['weight'] = int(info['weight'])
1630 info['cap'] = int(info['cap'])
1632 info['name'] = d['name']
1633 info['domid'] = str(d['domid'])
1634 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1635 else:
1636 if domid is None:
1637 # place holder for system-wide scheduler parameters
1638 err("No domain given.")
1639 usage('sched-credit')
1641 if serverType == SERVER_XEN_API:
1642 if doms[0]['domid']:
1643 server.xenapi.VM.add_to_VCPUs_params_live(
1644 get_single_vm(domid),
1645 "weight",
1646 weight)
1647 server.xenapi.VM.add_to_VCPUs_params_live(
1648 get_single_vm(domid),
1649 "cap",
1650 cap)
1651 else:
1652 server.xenapi.VM.add_to_VCPUs_params(
1653 get_single_vm(domid),
1654 "weight",
1655 weight)
1656 server.xenapi.VM.add_to_VCPUs_params(
1657 get_single_vm(domid),
1658 "cap",
1659 cap)
1660 else:
1661 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1662 if result != 0:
1663 err(str(result))
1665 def xm_info(args):
1666 arg_check(args, "info", 0, 1)
1668 try:
1669 (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
1670 except getopt.GetoptError, opterr:
1671 err(opterr)
1672 usage('info')
1674 show_xend_config = 0
1675 for (k, v) in options:
1676 if k in ['-c', '--config']:
1677 show_xend_config = 1
1679 if show_xend_config:
1680 for name, obj in inspect.getmembers(xoptions):
1681 if not inspect.ismethod(obj):
1682 if name == "config":
1683 for x in obj[1:]:
1684 if len(x) < 2:
1685 print "%-38s: (none)" % x[0]
1686 else:
1687 print "%-38s:" % x[0], x[1]
1688 else:
1689 print "%-38s:" % name, obj
1690 return
1692 if serverType == SERVER_XEN_API:
1694 # Need to fake out old style xm info as people rely on parsing it
1696 host_record = server.xenapi.host.get_record(
1697 server.xenapi.session.get_this_host(server.getSession()))
1699 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1701 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1703 def getVal(keys, default=""):
1704 data = host_record
1705 for key in keys:
1706 if key in data:
1707 data = data[key]
1708 else:
1709 return default
1710 return data
1712 def getCpuMhz():
1713 cpu_speeds = [int(host_cpu_record["speed"])
1714 for host_cpu_record in host_cpu_records
1715 if "speed" in host_cpu_record]
1716 if len(cpu_speeds) > 0:
1717 return sum(cpu_speeds) / len(cpu_speeds)
1718 else:
1719 return 0
1721 getCpuMhz()
1723 def getCpuFeatures():
1724 if len(host_cpu_records) > 0:
1725 return host_cpu_records[0].get("features", "")
1726 else:
1727 return ""
1729 info = {
1730 "host": getVal(["name_label"]),
1731 "release": getVal(["software_version", "release"]),
1732 "version": getVal(["software_version", "version"]),
1733 "machine": getVal(["software_version", "machine"]),
1734 "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
1735 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1736 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1737 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1738 "cpu_mhz": getCpuMhz(),
1739 "hw_caps": getCpuFeatures(),
1740 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1741 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1742 "xen_major": getVal(["software_version", "xen_major"]),
1743 "xen_minor": getVal(["software_version", "xen_minor"]),
1744 "xen_extra": getVal(["software_version", "xen_extra"]),
1745 "xen_caps": " ".join(getVal(["capabilities"], [])),
1746 "xen_scheduler": getVal(["sched_policy"]),
1747 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1748 "platform_params": getVal(["other_config", "platform_params"]),
1749 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1750 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1751 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1752 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1753 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1754 "xend_config_format":getVal(["software_version", "xend_config_format"])
1757 sorted = info.items()
1758 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1760 for (k, v) in sorted:
1761 print "%-23s:" % k, v
1762 else:
1763 info = server.xend.node.info()
1764 for x in info[1:]:
1765 if len(x) < 2:
1766 print "%-23s: (none)" % x[0]
1767 else:
1768 print "%-23s:" % x[0], x[1]
1770 def xm_console(args):
1771 arg_check(args, "console", 1, 2)
1773 quiet = False;
1775 try:
1776 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1777 except getopt.GetoptError, opterr:
1778 err(opterr)
1779 usage('console')
1781 for (k, v) in options:
1782 if k in ['-q', '--quiet']:
1783 quiet = True
1784 else:
1785 assert False
1787 if len(params) != 1:
1788 err('No domain given')
1789 usage('console')
1791 dom = params[0]
1793 try:
1794 if serverType == SERVER_XEN_API:
1795 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1796 else:
1797 info = server.xend.domain(dom)
1798 domid = int(sxp.child_value(info, 'domid', '-1'))
1799 except:
1800 if quiet:
1801 sys.exit(1)
1802 else:
1803 raise
1805 if domid == -1:
1806 if quiet:
1807 sys.exit(1)
1808 else:
1809 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1811 console.execConsole(domid)
1814 def domain_name_to_domid(domain_name):
1815 if serverType == SERVER_XEN_API:
1816 domid = server.xenapi.VM.get_domid(
1817 get_single_vm(domain_name))
1818 else:
1819 dom = server.xend.domain(domain_name)
1820 domid = int(sxp.child_value(dom, 'domid', '-1'))
1821 return int(domid)
1823 def xm_vncviewer(args):
1824 autopass = False;
1826 try:
1827 (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass'])
1828 except getopt.GetoptError, opterr:
1829 err(opterr)
1830 usage('vncviewer')
1832 for (k, v) in options:
1833 if k in ['--autopass','--vncviewer-autopass']:
1834 autopass = True
1835 else:
1836 assert False
1838 if len(params) != 1:
1839 err('No domain given (or several parameters specified)')
1840 usage('vncviewer')
1842 dom = params[0]
1843 domid = domain_name_to_domid(dom)
1845 console.runVncViewer(domid, autopass)
1848 def xm_uptime(args):
1849 short_mode = 0
1851 try:
1852 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1853 except getopt.GetoptError, opterr:
1854 err(opterr)
1855 usage('uptime')
1857 for (k, v) in options:
1858 if k in ['-s', '--short']:
1859 short_mode = 1
1861 doms = getDomains(params, 'all')
1863 if short_mode == 0:
1864 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1866 for dom in doms:
1867 d = parse_doms_info(dom)
1868 if d['domid'] == '':
1869 uptime = 0
1870 elif int(d['domid']) > 0:
1871 uptime = int(round(d['up_time']))
1872 else:
1873 f=open('/proc/uptime', 'r')
1874 upfile = f.read()
1875 uptime = int(round(float(upfile.split(' ')[0])))
1876 f.close()
1878 days = int(uptime / 86400)
1879 uptime -= (days * 86400)
1880 hours = int(uptime / 3600)
1881 uptime -= (hours * 3600)
1882 minutes = int(uptime / 60)
1883 uptime -= (minutes * 60)
1884 seconds = uptime
1886 upstring = ""
1887 if days > 0:
1888 upstring += str(days) + " day"
1889 if days > 1:
1890 upstring += "s"
1891 upstring += ", "
1892 upstring += '%(hours)2d:%(minutes)02d' % vars()
1894 if short_mode:
1895 now = datetime.datetime.now()
1896 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1897 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1898 else:
1899 upstring += ':%(seconds)02d' % vars()
1900 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1902 print upstring
1904 def xm_sysrq(args):
1905 arg_check(args, "sysrq", 2)
1906 dom = args[0]
1907 req = args[1]
1908 if serverType == SERVER_XEN_API:
1909 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1910 else:
1911 server.xend.domain.send_sysrq(dom, req)
1913 def xm_trigger(args):
1914 vcpu = 0
1916 arg_check(args, "trigger", 2, 3)
1917 dom = args[0]
1918 trigger = args[1]
1919 if len(args) == 3:
1920 vcpu = int(args[2])
1922 if serverType == SERVER_XEN_API:
1923 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1924 else:
1925 server.xend.domain.send_trigger(dom, trigger, vcpu)
1927 def xm_debug_keys(args):
1928 arg_check(args, "debug-keys", 1)
1930 keys = str(args[0])
1932 if serverType == SERVER_XEN_API:
1933 server.xenapi.host.send_debug_keys(
1934 server.xenapi.session.get_this_host(server.getSession()),
1935 keys)
1936 else:
1937 server.xend.node.send_debug_keys(keys)
1939 def xm_top(args):
1940 arg_check(args, "top", 0)
1942 os.system('xentop')
1944 def xm_dmesg(args):
1945 arg_check(args, "dmesg", 0, 1)
1947 try:
1948 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1949 except getopt.GetoptError, opterr:
1950 err(opterr)
1951 usage('dmesg')
1953 use_clear = 0
1954 for (k, v) in options:
1955 if k in ['-c', '--clear']:
1956 use_clear = 1
1958 if len(params) :
1959 err("No parameter required")
1960 usage('dmesg')
1962 if serverType == SERVER_XEN_API:
1963 host = server.xenapi.session.get_this_host(server.getSession())
1964 if use_clear:
1965 print server.xenapi.host.dmesg_clear(host),
1966 else:
1967 print server.xenapi.host.dmesg(host),
1968 else:
1969 if not use_clear:
1970 print server.xend.node.dmesg.info(),
1971 else:
1972 print server.xend.node.dmesg.clear(),
1974 def xm_log(args):
1975 arg_check(args, "log", 0)
1977 if serverType == SERVER_XEN_API:
1978 print server.xenapi.host.get_log(
1979 server.xenapi.session.get_this_host(server.getSession()))
1980 else:
1981 print server.xend.node.log()
1983 def xm_serve(args):
1984 if serverType == SERVER_XEN_API:
1985 print "Not supported with XenAPI"
1986 sys.exit(-1)
1988 arg_check(args, "serve", 0)
1990 from fcntl import fcntl, F_SETFL
1992 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1993 s.connect(XendClient.XML_RPC_SOCKET)
1994 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1996 while True:
1997 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1998 if s in iwtd:
1999 data = s.recv(4096)
2000 if len(data) > 0:
2001 sys.stdout.write(data)
2002 sys.stdout.flush()
2003 else:
2004 break
2005 if sys.stdin in iwtd:
2006 data = sys.stdin.read(4096)
2007 if len(data) > 0:
2008 s.sendall(data)
2009 else:
2010 break
2011 s.close()
2013 def parse_dev_info(info):
2014 def get_info(n, t, d):
2015 i = 0
2016 while i < len(info):
2017 if (info[i][0] == n):
2018 return t(info[i][1])
2019 i = i + 1
2020 return t(d)
2021 return {
2022 #common
2023 'backend-id' : get_info('backend-id', int, -1),
2024 'handle' : get_info('handle', int, 0),
2025 'state' : get_info('state', int, -1),
2026 'be-path' : get_info('backend', str, '??'),
2027 'event-ch' : get_info('event-channel',int, -1),
2028 #network specific
2029 'virtual-device' : get_info('virtual-device', str, '??'),
2030 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
2031 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
2032 'mac' : get_info('mac', str, '??'),
2033 #block-device specific
2034 'ring-ref' : get_info('ring-ref', int, -1),
2037 def arg_check_for_resource_list(args, name):
2038 use_long = 0
2039 try:
2040 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2041 except getopt.GetoptError, opterr:
2042 err(opterr)
2043 sys.exit(1)
2045 for (k, v) in options:
2046 if k in ['-l', '--long']:
2047 use_long = 1
2049 if len(params) == 0:
2050 print 'No domain parameter given'
2051 usage(name)
2052 if len(params) > 1:
2053 print 'No multiple domain parameters allowed'
2054 usage(name)
2056 return (use_long, params)
2058 def xm_network_list(args):
2059 (use_long, params) = arg_check_for_resource_list(args, "network-list")
2061 dom = params[0]
2063 if serverType == SERVER_XEN_API:
2064 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2065 vif_properties = \
2066 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
2067 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2068 zip(range(len(vif_properties)), vif_properties))
2069 else:
2070 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
2072 if use_long:
2073 map(PrettyPrint.prettyprint, devs)
2074 else:
2075 hdr = 0
2076 for x in devs:
2077 if hdr == 0:
2078 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
2079 hdr = 1
2080 ni = parse_dev_info(x[1])
2081 ni['idx'] = int(x[0])
2082 print ("%(idx)-3d "
2083 "%(backend-id)-3d"
2084 "%(mac)-17s "
2085 "%(handle)-3d "
2086 "%(state)-3d "
2087 "%(event-ch)-3d "
2088 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
2089 "%(be-path)-30s "
2090 % ni)
2092 def xm_block_list(args):
2093 (use_long, params) = arg_check_for_resource_list(args, "block-list")
2095 dom = params[0]
2097 if serverType == SERVER_XEN_API:
2098 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2099 vbd_properties = \
2100 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2101 vbd_devs = \
2102 map(server.xenapi.VBD.get_device, vbd_refs)
2103 vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
2104 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2105 zip(vbd_devids, vbd_properties))
2106 else:
2107 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2109 if use_long:
2110 map(PrettyPrint.prettyprint, devs)
2111 else:
2112 hdr = 0
2113 for x in devs:
2114 if hdr == 0:
2115 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2116 hdr = 1
2117 ni = parse_dev_info(x[1])
2118 ni['idx'] = int(x[0])
2119 print ("%(idx)-5d "
2120 "%(backend-id)-3d "
2121 "%(handle)-3d "
2122 "%(state)-3d "
2123 "%(event-ch)-3d "
2124 "%(ring-ref)-5d "
2125 "%(be-path)-30s "
2126 % ni)
2128 def xm_vtpm_list(args):
2129 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2131 dom = params[0]
2133 if serverType == SERVER_XEN_API:
2134 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2135 vtpm_properties = \
2136 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2137 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2138 zip(range(len(vtpm_properties)), vtpm_properties))
2139 else:
2140 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2142 if use_long:
2143 map(PrettyPrint.prettyprint, devs)
2144 else:
2145 hdr = 0
2146 for x in devs:
2147 if hdr == 0:
2148 print 'Idx BE handle state evt-ch ring-ref BE-path'
2149 hdr = 1
2150 ni = parse_dev_info(x[1])
2151 ni['idx'] = int(x[0])
2152 print ("%(idx)-3d "
2153 "%(backend-id)-3d "
2154 "%(handle)-3d "
2155 "%(state)-3d "
2156 "%(event-ch)-3d "
2157 "%(ring-ref)-5d "
2158 "%(be-path)-30s "
2159 % ni)
2162 def xm_pci_list(args):
2163 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2165 dom = params[0]
2167 devs = []
2168 if serverType == SERVER_XEN_API:
2169 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2170 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2171 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2172 dev = {
2173 "domain": "0x%04x" % int(ppci_record["domain"]),
2174 "bus": "0x%02x" % int(ppci_record["bus"]),
2175 "slot": "0x%02x" % int(ppci_record["slot"]),
2176 "func": "0x%01x" % int(ppci_record["func"]),
2177 "vslt": "0x%02x" % \
2178 int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref))
2180 devs.append(dev)
2182 else:
2183 devs = server.xend.domain.getDeviceSxprs(dom, 'pci')
2185 if len(devs) == 0:
2186 return
2188 has_vslt = devs[0].has_key('vslt')
2189 if has_vslt:
2190 hdr_str = 'VSlt domain bus slot func'
2191 fmt_str = "%(vslt)-3s %(domain)-3s %(bus)-3s %(slot)-3s %(func)-3s "
2192 else:
2193 hdr_str = 'domain bus slot func'
2194 fmt_str = "%(domain)-3s %(bus)-3s %(slot)-3s %(func)-3s "
2195 hdr = 0
2197 for x in devs:
2198 if hdr == 0:
2199 print (hdr_str)
2200 hdr = 1
2201 print ( fmt_str % x )
2203 def xm_pci_list_assignable_devices(args):
2204 # Each element of dev_list is a PciDevice
2205 dev_list = find_all_devices_owned_by_pciback()
2207 # Each element of devs_list is a list of PciDevice
2208 devs_list = check_FLR_capability(dev_list)
2210 devs_list = check_mmio_bar(devs_list)
2212 # Check if the devices have been assigned to guests.
2213 final_devs_list = []
2214 for dev_list in devs_list:
2215 available = True
2216 for d in dev_list:
2217 pci_str = '0x%x,0x%x,0x%x,0x%x' %(d.domain, d.bus, d.slot, d.func)
2218 # Xen doesn't care what the domid is, so we pass 0 here...
2219 domid = 0
2220 bdf = xc.test_assign_device(domid, pci_str)
2221 if bdf != 0:
2222 available = False
2223 break
2224 if available:
2225 final_devs_list = final_devs_list + [dev_list]
2227 for dev_list in final_devs_list:
2228 for d in dev_list:
2229 print d.name,
2230 print
2232 def vscsi_convert_sxp_to_dict(dev_sxp):
2233 dev_dict = {}
2234 for opt_val in dev_sxp[1:]:
2235 try:
2236 opt, val = opt_val
2237 dev_dict[opt] = val
2238 except TypeError:
2239 pass
2240 return dev_dict
2242 def xm_scsi_list(args):
2243 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2245 dom = params[0]
2247 devs = []
2248 if serverType == SERVER_XEN_API:
2250 dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
2251 dscsi_properties = \
2252 map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
2253 dscsi_dict = {}
2254 for dscsi_property in dscsi_properties:
2255 devid = int(dscsi_property['dev']['devid'])
2256 try:
2257 dscsi_sxp = dscsi_dict[devid]
2258 except:
2259 dscsi_sxp = [['devs', []]]
2260 for key, value in dscsi_property.items():
2261 if key != 'dev':
2262 dscsi_sxp.append([key, value])
2263 dev_sxp = ['dev']
2264 dev_sxp.extend(map2sxp(dscsi_property['dev']))
2265 dscsi_sxp[0][1].append(dev_sxp)
2266 dscsi_dict[devid] = dscsi_sxp
2267 devs = map2sxp(dscsi_dict)
2269 else:
2270 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2272 if use_long:
2273 map(PrettyPrint.prettyprint, devs)
2274 else:
2275 hdr = 0
2276 for x in devs:
2277 if hdr == 0:
2278 print "%-3s %-3s %-5s %-10s %-5s %-10s %-4s" \
2279 % ('Idx', 'BE', 'state', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2280 hdr = 1
2281 ni = parse_dev_info(x[1])
2282 ni['idx'] = int(x[0])
2283 for dev in x[1][0][1]:
2284 mi = vscsi_convert_sxp_to_dict(dev)
2285 print "%(idx)-3d %(backend-id)-3d %(state)-5d " % ni,
2286 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2288 def parse_block_configuration(args):
2289 dom = args[0]
2291 if args[1].startswith('tap:'):
2292 cls = 'tap'
2293 else:
2294 cls = 'vbd'
2296 vbd = [cls,
2297 ['uname', args[1]],
2298 ['dev', args[2]],
2299 ['mode', args[3]]]
2300 if len(args) == 5:
2301 vbd.append(['backend', args[4]])
2303 return (dom, vbd)
2306 def xm_block_attach(args):
2307 arg_check(args, 'block-attach', 4, 5)
2309 if serverType == SERVER_XEN_API:
2310 dom = args[0]
2311 uname = args[1]
2312 dev = args[2]
2313 mode = args[3]
2315 # First create new VDI
2316 vdi_record = {
2317 "name_label": "vdi" + str(uname.__hash__()),
2318 "name_description": "",
2319 "SR": get_default_SR(),
2320 "virtual_size": 0,
2321 "sector_size": 512,
2322 "type": "system",
2323 "sharable": False,
2324 "read_only": mode!="w",
2325 "other_config": {"location": uname}
2328 vdi_ref = server.xenapi.VDI.create(vdi_record)
2330 # Now create new VBD
2332 vbd_record = {
2333 "VM": get_single_vm(dom),
2334 "VDI": vdi_ref,
2335 "device": dev,
2336 "bootable": True,
2337 "mode": mode=="w" and "RW" or "RO",
2338 "type": "Disk",
2339 "qos_algorithm_type": "",
2340 "qos_algorithm_params": {}
2343 server.xenapi.VBD.create(vbd_record)
2345 else:
2346 (dom, vbd) = parse_block_configuration(args)
2347 server.xend.domain.device_create(dom, vbd)
2350 def xm_block_configure(args):
2351 arg_check(args, 'block-configure', 4, 5)
2353 (dom, vbd) = parse_block_configuration(args)
2354 server.xend.domain.device_configure(dom, vbd)
2357 def xm_network_attach(args):
2358 arg_check(args, 'network-attach', 1, 11)
2360 dom = args[0]
2361 vif = ['vif']
2362 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2363 'backend', 'vifname', 'rate', 'model', 'accel']
2365 if serverType == SERVER_XEN_API:
2366 vif_record = {
2367 "device": "eth0",
2368 "network": get_default_Network(),
2369 "VM": get_single_vm(dom),
2370 "MAC": "",
2371 "MTU": "",
2372 "qos_algorithm_type": "",
2373 "qos_algorithm_params": {},
2374 "other_config": {}
2377 def set(keys, val):
2378 record = vif_record
2379 for key in keys[:-1]:
2380 record = record[key]
2381 record[keys[-1]] = val
2383 def get_net_from_bridge(bridge):
2384 # In OSS, we just assert network.name_label == bridge name
2385 networks = dict([(record['name_label'], ref)
2386 for ref, record in server.xenapi.network
2387 .get_all_records().items()])
2388 if bridge not in networks.keys():
2389 raise "Unknown bridge name!"
2390 return networks[bridge]
2392 vif_conv = {
2393 'type':
2394 lambda x: None,
2395 'mac':
2396 lambda x: set(['MAC'], x),
2397 'bridge':
2398 lambda x: set(['network'], get_net_from_bridge(x)),
2399 'ip':
2400 lambda x: set(['other_config', 'ip'], x),
2401 'script':
2402 lambda x: set(['other_config', 'script'], x),
2403 'backend':
2404 lambda x: set(['other_config', 'backend'], x),
2405 'vifname':
2406 lambda x: set(['device'], x),
2407 'rate':
2408 lambda x: set(['qos_algorithm_params', 'rate'], x),
2409 'model':
2410 lambda x: None,
2411 'accel':
2412 lambda x: set(['other_config', 'accel'], x)
2415 for a in args[1:]:
2416 vif_param = a.split("=")
2417 if len(vif_param) != 2 or vif_param[1] == '' or \
2418 vif_param[0] not in vif_params:
2419 err("Invalid argument: %s" % a)
2420 usage('network-attach')
2421 else:
2422 vif_conv[vif_param[0]](vif_param[1])
2424 server.xenapi.VIF.create(vif_record)
2425 else:
2426 for a in args[1:]:
2427 vif_param = a.split("=")
2428 if len(vif_param) != 2 or vif_param[1] == '' or \
2429 vif_param[0] not in vif_params:
2430 err("Invalid argument: %s" % a)
2431 usage('network-attach')
2432 vif.append(vif_param)
2433 server.xend.domain.device_create(dom, vif)
2435 def parse_pci_configuration(args, state, opts = ''):
2436 dom = args[0]
2437 pci_dev_str = args[1]
2438 if len(args) == 3:
2439 vslt = args[2]
2440 else:
2441 vslt = '0x0' #chose a free virtual PCI slot
2442 pci=['pci']
2443 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
2444 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
2445 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
2446 r"(?P<func>[0-7])$", pci_dev_str)
2447 if pci_match == None:
2448 raise OptionError("Invalid argument: %s %s" % (pci_dev_str,vslt))
2449 pci_dev_info = pci_match.groupdict('0')
2451 try:
2452 pci_bdf =['dev', ['domain', '0x'+ pci_dev_info['domain']], \
2453 ['bus', '0x'+ pci_dev_info['bus']],
2454 ['slot', '0x'+ pci_dev_info['slot']],
2455 ['func', '0x'+ pci_dev_info['func']],
2456 ['vslt', '0x%x' % int(vslt, 16)]]
2457 if len(opts) > 0:
2458 pci_bdf.append(['opts', opts])
2459 pci.append(pci_bdf)
2461 except:
2462 raise OptionError("Invalid argument: %s %s" % (pci_dev_str,vslt))
2463 pci.append(['state', state])
2465 return (dom, pci)
2467 def xm_pci_attach(args):
2468 config_pci_opts = []
2469 (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
2470 for (k, v) in options:
2471 if k in ('-o', '--options'):
2472 if len(v.split('=')) != 2:
2473 err("Invalid pci attach option: %s" % v)
2474 usage('pci-attach')
2475 config_pci_opts.append(v.split('='))
2477 n = len([i for i in params if i != '--'])
2478 if n < 2 or n > 3:
2479 err("Invalid argument for 'xm pci-attach'")
2480 usage('pci-attach')
2482 (dom, pci) = parse_pci_configuration(params, 'Initialising',
2483 config_pci_opts)
2485 if serverType == SERVER_XEN_API:
2487 pci_dev = sxp.children(pci, 'dev')[0]
2488 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2489 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2490 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2491 func = int(sxp.child_value(pci_dev, 'func'), 16)
2492 vslt = int(sxp.child_value(pci_dev, 'vslt'), 16)
2493 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2495 target_ref = None
2496 for ppci_ref in server.xenapi.PPCI.get_all():
2497 if name == server.xenapi.PPCI.get_name(ppci_ref):
2498 target_ref = ppci_ref
2499 break
2500 if target_ref is None:
2501 raise OptionError("Device %s not found" % name)
2503 dpci_record = {
2504 "VM": get_single_vm(dom),
2505 "PPCI": target_ref,
2506 "hotplug_slot": vslt,
2507 "options": dict(config_pci_opts)
2509 server.xenapi.DPCI.create(dpci_record)
2511 else:
2512 server.xend.domain.device_configure(dom, pci)
2514 def parse_scsi_configuration(p_scsi, v_hctl, state):
2515 v = v_hctl.split(':')
2516 if len(v) != 4:
2517 raise OptionError("Invalid argument: %s" % v_hctl)
2519 p_hctl = None
2520 devname = None
2521 if p_scsi is not None:
2522 (p_hctl, devname) = \
2523 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi)
2524 if p_hctl is None:
2525 raise OptionError("Cannot find device '%s'" % p_scsi)
2527 scsi = ['vscsi']
2528 scsi.append(['dev', \
2529 ['state', state], \
2530 ['devid', int(v[0])], \
2531 ['p-dev', p_hctl], \
2532 ['p-devname', devname], \
2533 ['v-dev', v_hctl] \
2534 ])
2536 return scsi
2538 def xm_scsi_attach(args):
2539 arg_check(args, 'scsi-attach', 3, 4)
2540 dom = args[0]
2541 p_scsi = args[1]
2542 v_hctl = args[2]
2543 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2545 if serverType == SERVER_XEN_API:
2547 scsi_dev = sxp.children(scsi, 'dev')[0]
2548 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2549 target_ref = None
2550 for pscsi_ref in server.xenapi.PSCSI.get_all():
2551 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2552 target_ref = pscsi_ref
2553 break
2554 if target_ref is None:
2555 raise OptionError("Cannot find device '%s'" % p_scsi)
2557 dscsi_record = {
2558 "VM": get_single_vm(dom),
2559 "PSCSI": target_ref,
2560 "virtual_HCTL": v_hctl
2562 server.xenapi.DSCSI.create(dscsi_record)
2564 else:
2565 if len(args) == 4:
2566 scsi.append(['backend', args[3]])
2567 server.xend.domain.device_configure(dom, scsi)
2569 def detach(args, deviceClass):
2570 rm_cfg = True
2571 dom = args[0]
2572 dev = args[1]
2573 try:
2574 force = args[2]
2575 if (force != "--force") and (force != "-f"):
2576 print "Ignoring option %s"%(force)
2577 force = None
2578 except IndexError:
2579 force = None
2581 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2584 def xm_block_detach(args):
2585 if serverType == SERVER_XEN_API:
2586 arg_check(args, "block-detach", 2, 3)
2587 dom = args[0]
2588 dev = args[1]
2589 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2590 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2591 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2592 if len(vbd_refs) > 0:
2593 vbd_ref = vbd_refs[0]
2594 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2596 server.xenapi.VBD.destroy(vbd_ref)
2598 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2599 server.xenapi.VDI.destroy(vdi_ref)
2600 else:
2601 raise OptionError("Cannot find device '%s' in domain '%s'"
2602 % (dev,dom))
2603 else:
2604 arg_check(args, 'block-detach', 2, 3)
2605 dom = args[0]
2606 dev = args[1]
2607 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2608 if dc == "tap":
2609 detach(args, 'tap')
2610 else:
2611 detach(args, 'vbd')
2613 def xm_network_detach(args):
2614 if serverType == SERVER_XEN_API:
2615 arg_check(args, "network-detach", 2, 3)
2616 dom = args[0]
2617 devid = args[1]
2618 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2619 vif_refs = [vif_ref for vif_ref in vif_refs
2620 if server.xenapi.VIF.\
2621 get_runtime_properties(vif_ref)["handle"] == devid]
2622 if len(vif_refs) > 0:
2623 vif_ref = vif_refs[0]
2625 server.xenapi.VIF.destroy(vif_ref)
2626 else:
2627 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2628 else:
2629 arg_check(args, 'network-detach', 2, 3)
2630 detach(args, 'vif')
2632 def xm_pci_detach(args):
2633 arg_check(args, 'pci-detach', 2)
2634 (dom, pci) = parse_pci_configuration(args, 'Closing')
2636 if serverType == SERVER_XEN_API:
2638 pci_dev = sxp.children(pci, 'dev')[0]
2639 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2640 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2641 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2642 func = int(sxp.child_value(pci_dev, 'func'), 16)
2643 vslt = int(sxp.child_value(pci_dev, 'vslt'), 16)
2644 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2646 target_ref = None
2647 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2648 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2649 if name == server.xenapi.PPCI.get_name(ppci_ref):
2650 target_ref = ppci_ref
2651 server.xenapi.DPCI.destroy(dpci_ref)
2652 break
2653 if target_ref is None:
2654 raise OptionError("Device %s not assigned" % name)
2656 else:
2657 server.xend.domain.device_configure(dom, pci)
2659 def xm_scsi_detach(args):
2660 arg_check(args, 'scsi-detach', 2)
2661 dom = args[0]
2662 v_hctl = args[1]
2663 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
2665 if serverType == SERVER_XEN_API:
2667 target_ref = None
2668 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
2669 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
2670 target_ref = dscsi_ref
2671 break
2672 if target_ref is None:
2673 raise OptionError("Device %s not assigned" % v_hctl)
2675 server.xenapi.DSCSI.destroy(target_ref)
2677 else:
2678 server.xend.domain.device_configure(dom, scsi)
2680 def xm_vnet_list(args):
2681 xenapi_unsupported()
2682 try:
2683 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2684 except getopt.GetoptError, opterr:
2685 err(opterr)
2686 usage('vnet-list')
2688 use_long = 0
2689 for (k, v) in options:
2690 if k in ['-l', '--long']:
2691 use_long = 1
2693 if params:
2694 use_long = 1
2695 vnets = params
2696 else:
2697 vnets = server.xend_vnets()
2699 for vnet in vnets:
2700 try:
2701 if use_long:
2702 info = server.xend_vnet(vnet)
2703 PrettyPrint.prettyprint(info)
2704 else:
2705 print vnet
2706 except Exception, ex:
2707 print vnet, ex
2709 def xm_vnet_create(args):
2710 xenapi_unsupported()
2711 arg_check(args, "vnet-create", 1)
2712 conf = args[0]
2713 if not os.access(conf, os.R_OK):
2714 print "File not found: %s" % conf
2715 sys.exit(1)
2717 server.xend_vnet_create(conf)
2719 def xm_vnet_delete(args):
2720 xenapi_unsupported()
2721 arg_check(args, "vnet-delete", 1)
2722 vnet = args[0]
2723 server.xend_vnet_delete(vnet)
2725 def xm_network_new(args):
2726 xenapi_only()
2727 arg_check(args, "network-new", 1)
2728 network = args[0]
2730 record = {
2731 "name_label": network,
2732 "name_description": "",
2733 "other_config": {},
2734 "default_gateway": "",
2735 "default_netmask": ""
2738 server.xenapi.network.create(record)
2740 def xm_network_del(args):
2741 xenapi_only()
2742 arg_check(args, "network-del", 1)
2743 network = args[0]
2745 networks = dict([(record['name_label'], ref)
2746 for ref, record in
2747 server.xenapi.network.get_all_records().items()])
2749 if network not in networks.keys():
2750 raise ValueError("'%s' is not a valid network name" % network)
2752 server.xenapi.network.destroy(networks[network])
2754 def xm_network_show(args):
2755 xenapi_only()
2756 arg_check(args, "network-show", 0)
2758 networks = server.xenapi.network.get_all_records()
2759 pifs = server.xenapi.PIF.get_all_records()
2760 vifs = server.xenapi.VIF.get_all_records()
2762 print '%-20s %-40s %-10s' % \
2763 ('Name', 'VIFs', 'PIFs')
2765 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2767 for network_ref, network in networks.items():
2768 for i in range(max(len(network['PIFs']),
2769 len(network['VIFs']), 1)):
2770 if i < len(network['PIFs']):
2771 pif_uuid = network['PIFs'][i]
2772 else:
2773 pif_uuid = None
2775 if i < len(network['VIFs']):
2776 vif_uuid = network['VIFs'][i]
2777 else:
2778 vif_uuid = None
2780 pif = pifs.get(pif_uuid, None)
2781 vif = vifs.get(vif_uuid, None)
2783 if vif:
2784 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2785 vif = "%s.%s" % (dom_name, vif['device'])
2786 else:
2787 vif = ''
2789 if pif:
2790 if int(pif['VLAN']) > -1:
2791 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2792 else:
2793 pif = pif['device']
2794 else:
2795 pif = ''
2797 if i == 0:
2798 r = {'name_label':network['name_label'],
2799 'vif':vif, 'pif':pif}
2800 else:
2801 r = {'name_label':'', 'vif':vif, 'pif':pif}
2803 print format2 % r
2806 commands = {
2807 "shell": xm_shell,
2808 "event-monitor": xm_event_monitor,
2809 # console commands
2810 "console": xm_console,
2811 "vncviewer": xm_vncviewer,
2812 # xenstat commands
2813 "top": xm_top,
2814 # domain commands
2815 "delete": xm_delete,
2816 "destroy": xm_destroy,
2817 "domid": xm_domid,
2818 "domname": xm_domname,
2819 "dump-core": xm_dump_core,
2820 "reboot": xm_reboot,
2821 "rename": xm_rename,
2822 "reset": xm_reset,
2823 "restore": xm_restore,
2824 "resume": xm_resume,
2825 "save": xm_save,
2826 "shutdown": xm_shutdown,
2827 "start": xm_start,
2828 "sysrq": xm_sysrq,
2829 "trigger": xm_trigger,
2830 "uptime": xm_uptime,
2831 "suspend": xm_suspend,
2832 "list": xm_list,
2833 # memory commands
2834 "mem-max": xm_mem_max,
2835 "mem-set": xm_mem_set,
2836 # cpu commands
2837 "vcpu-pin": xm_vcpu_pin,
2838 "vcpu-list": xm_vcpu_list,
2839 "vcpu-set": xm_vcpu_set,
2840 # special
2841 "pause": xm_pause,
2842 "unpause": xm_unpause,
2843 # host commands
2844 "debug-keys": xm_debug_keys,
2845 "dmesg": xm_dmesg,
2846 "info": xm_info,
2847 "log": xm_log,
2848 "serve": xm_serve,
2849 # scheduler
2850 "sched-sedf": xm_sched_sedf,
2851 "sched-credit": xm_sched_credit,
2852 # block
2853 "block-attach": xm_block_attach,
2854 "block-detach": xm_block_detach,
2855 "block-list": xm_block_list,
2856 "block-configure": xm_block_configure,
2857 # network (AKA vifs)
2858 "network-attach": xm_network_attach,
2859 "network-detach": xm_network_detach,
2860 "network-list": xm_network_list,
2861 # network (as in XenAPI)
2862 "network-new": xm_network_new,
2863 "network-del": xm_network_del,
2864 "network-show": xm_network_show,
2865 # vnet
2866 "vnet-list": xm_vnet_list,
2867 "vnet-create": xm_vnet_create,
2868 "vnet-delete": xm_vnet_delete,
2869 # vtpm
2870 "vtpm-list": xm_vtpm_list,
2871 #pci
2872 "pci-attach": xm_pci_attach,
2873 "pci-detach": xm_pci_detach,
2874 "pci-list": xm_pci_list,
2875 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
2876 # vscsi
2877 "scsi-attach": xm_scsi_attach,
2878 "scsi-detach": xm_scsi_detach,
2879 "scsi-list": xm_scsi_list,
2882 ## The commands supported by a separate argument parser in xend.xm.
2883 IMPORTED_COMMANDS = [
2884 'create',
2885 'new',
2886 'migrate',
2887 'labels',
2888 'dumppolicy',
2889 'addlabel',
2890 'rmlabel',
2891 'getlabel',
2892 'dry-run',
2893 'resources',
2894 'getpolicy',
2895 'setpolicy',
2896 'resetpolicy',
2899 for c in IMPORTED_COMMANDS:
2900 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2902 aliases = {
2903 "balloon": "mem-set",
2904 "set-vcpus": "vcpu-set",
2905 "vif-list": "network-list",
2906 "vbd-create": "block-attach",
2907 "vbd-destroy": "block-detach",
2908 "vbd-list": "block-list",
2912 def xm_lookup_cmd(cmd):
2913 if commands.has_key(cmd):
2914 return commands[cmd]
2915 elif aliases.has_key(cmd):
2916 deprecated(cmd,aliases[cmd])
2917 return commands[aliases[cmd]]
2918 elif cmd == 'help':
2919 longHelp()
2920 sys.exit(0)
2921 else:
2922 # simulate getopt's prefix matching behaviour
2923 if len(cmd) > 1:
2924 same_prefix_cmds = [commands[c] for c in commands.keys() \
2925 if c[:len(cmd)] == cmd]
2926 # only execute if there is only 1 match
2927 if len(same_prefix_cmds) == 1:
2928 return same_prefix_cmds[0]
2929 return None
2931 def deprecated(old,new):
2932 print >>sys.stderr, (
2933 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2935 def main(argv=sys.argv):
2936 if len(argv) < 2:
2937 usage()
2939 # intercept --help(-h) and output our own help
2940 for help in ['--help', '-h']:
2941 if help in argv[1:]:
2942 if help == argv[1]:
2943 longHelp()
2944 sys.exit(0)
2945 else:
2946 usage(argv[1])
2948 cmd_name = argv[1]
2949 cmd = xm_lookup_cmd(cmd_name)
2950 if cmd:
2951 # strip off prog name and subcmd
2952 args = argv[2:]
2953 _, rc = _run_cmd(cmd, cmd_name, args)
2954 sys.exit(rc)
2955 else:
2956 err('Subcommand %s not found!' % cmd_name)
2957 usage()
2959 def _run_cmd(cmd, cmd_name, args):
2960 global server
2962 try:
2963 if server is None:
2964 if serverType == SERVER_XEN_API:
2965 server = XenAPI.Session(serverURI)
2966 username, password = parseAuthentication()
2967 server.login_with_password(username, password)
2968 def logout():
2969 try:
2970 server.xenapi.session.logout()
2971 except:
2972 pass
2973 atexit.register(logout)
2974 else:
2975 server = ServerProxy(serverURI)
2977 return True, cmd(args)
2978 except socket.error, ex:
2979 if os.geteuid() != 0:
2980 err("Most commands need root access. Please try again as root.")
2981 else:
2982 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2983 except KeyboardInterrupt:
2984 print "Interrupted."
2985 return True, ''
2986 except IOError, ex:
2987 if os.geteuid() != 0:
2988 err("Most commands need root access. Please try again as root.")
2989 else:
2990 err("Unable to connect to xend: %s." % ex[1])
2991 except SystemExit, code:
2992 return code == 0, code
2993 except XenAPI.Failure, exn:
2994 for line in [''] + wrap(str(exn), 80) + ['']:
2995 print >>sys.stderr, line
2996 except xmlrpclib.Fault, ex:
2997 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2998 err("Domain '%s' does not exist." % ex.faultString)
2999 return False, ex.faultCode
3000 else:
3001 err(ex.faultString)
3002 _usage(cmd_name)
3003 except xmlrpclib.ProtocolError, ex:
3004 if ex.errcode == -1:
3005 print >>sys.stderr, (
3006 "Xend has probably crashed! Invalid or missing HTTP "
3007 "status code.")
3008 else:
3009 print >>sys.stderr, (
3010 "Xend has probably crashed! ProtocolError(%d, %s)." %
3011 (ex.errcode, ex.errmsg))
3012 except (ValueError, OverflowError):
3013 err("Invalid argument.")
3014 _usage(cmd_name)
3015 except OptionError, e:
3016 err(str(e))
3017 _usage(cmd_name)
3018 print e.usage
3019 except XenAPIUnsupportedException, e:
3020 err(str(e))
3021 except XSMError, e:
3022 err(str(e))
3023 except Exception, e:
3024 if serverType != SERVER_XEN_API:
3025 import xen.util.xsm.xsm as security
3026 if isinstance(e, security.XSMError):
3027 err(str(e))
3028 return False, 1
3029 print "Unexpected error:", sys.exc_info()[0]
3030 print
3031 print "Please report to xen-devel@lists.xensource.com"
3032 raise
3034 return False, 1
3036 if __name__ == "__main__":
3037 main()