debuggers.hg

view tools/python/xen/xm/main.py @ 19680:dc7de36c94e3

xm, xend: passthrough: Add assigned_or_requested_vslot()

Add an accessor to simplify accessing vslot if available,
otherwise requested_vslot.

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 26 10:04:10 2009 +0100 (2009-05-26)
parents 61404d971c92
children f210a633571c
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
58 from xen.util import auxbin
60 import XenAPI
62 import inspect
63 from xen.xend import XendOptions
64 xoptions = XendOptions.instance()
66 import signal
67 signal.signal(signal.SIGINT, signal.SIG_DFL)
69 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
70 # getopt.getopt if gnu_getopt is not available. This will mean that options
71 # may only be specified before positional arguments.
72 if not hasattr(getopt, 'gnu_getopt'):
73 getopt.gnu_getopt = getopt.getopt
75 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
76 XM_CONFIG_FILE_DEFAULT = auxbin.xen_configdir() + '/xm-config.xml'
78 # Supported types of server
79 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
80 SERVER_XEN_API = 'Xen-API'
82 # General help message
84 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
85 "Control, list, and manipulate Xen guest instances.\n"
87 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
88 'For more help on \'xm\' see the xm(1) man page.\n' \
89 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
90 ' man page.\n'
92 # Help strings are indexed by subcommand name in this way:
93 # 'subcommand': (argstring, description)
95 SUBCOMMAND_HELP = {
96 # common commands
98 'shell' : ('', 'Launch an interactive shell.'),
100 'console' : ('[-q|--quiet] <Domain>',
101 'Attach to <Domain>\'s console.'),
102 'vncviewer' : ('[--[vncviewer-]autopass] <Domain>',
103 'Attach to <Domain>\'s VNC server.'),
104 'create' : ('<ConfigFile> [options] [vars]',
105 'Create a domain based on <ConfigFile>.'),
106 'destroy' : ('<Domain>',
107 'Terminate a domain immediately.'),
108 'help' : ('', 'Display this message.'),
109 'list' : ('[options] [Domain, ...]',
110 'List information about all/some domains.'),
111 'mem-max' : ('<Domain> <Mem>',
112 'Set the maximum amount reservation for a domain.'),
113 'mem-set' : ('<Domain> <Mem>',
114 'Set the current memory usage for a domain.'),
115 'migrate' : ('<Domain> <Host>',
116 'Migrate a domain to another machine.'),
117 'pause' : ('<Domain>', 'Pause execution of a domain.'),
118 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
119 'reset' : ('<Domain>', 'Reset a domain.'),
120 'restore' : ('<CheckpointFile> [-p]',
121 'Restore a domain from a saved state.'),
122 'save' : ('[-c] <Domain> <CheckpointFile>',
123 'Save a domain state to restore later.'),
124 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
125 'top' : ('', 'Monitor a host and the domains in real time.'),
126 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
127 'uptime' : ('[-s] [Domain, ...]',
128 'Print uptime for all/some domains.'),
130 # Life cycle xm commands
131 'new' : ('<ConfigFile> [options] [vars]',
132 'Adds a domain to Xend domain management'),
133 'delete' : ('<DomainName>',
134 'Remove a domain from Xend domain management.'),
135 'start' : ('<DomainName>', 'Start a Xend managed domain'),
136 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
137 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
139 # less used commands
141 'dmesg' : ('[-c|--clear]',
142 'Read and/or clear Xend\'s message buffer.'),
143 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
144 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
145 'dump-core' : ('[-L|--live] [-C|--crash] [-R|--reset] <Domain> [Filename]',
146 'Dump core for a specific domain.'),
147 'info' : ('[-c|--config]', 'Get information about Xen host.'),
148 'log' : ('', 'Print Xend log'),
149 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
150 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
151 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
152 'Get/set credit scheduler parameters.'),
153 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
154 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
155 'trigger' : ('<Domain> <nmi|reset|init|s3resume|power> [<VCPU>]',
156 'Send a trigger to a domain.'),
157 'vcpu-list' : ('[Domain, ...]',
158 'List the VCPUs for all/some domains.'),
159 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
160 'Set which CPUs a VCPU can use.'),
161 'vcpu-set' : ('<Domain> <vCPUs>',
162 'Set the number of active VCPUs for allowed for the'
163 ' domain.'),
165 # device commands
167 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
168 'Create a new virtual block device.'),
169 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
170 'Change block device configuration'),
171 'block-detach' : ('<Domain> <DevId> [-f|--force]',
172 'Destroy a domain\'s virtual block device.'),
173 'block-list' : ('<Domain> [--long]',
174 'List virtual block devices for a domain.'),
175 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
176 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
177 '[vifname=<name>] [rate=<rate>] [model=<model>]'
178 '[accel=<accel>]',
179 'Create a new virtual network device.'),
180 'network-detach': ('<Domain> <DevId> [-f|--force]',
181 'Destroy a domain\'s virtual network device.'),
182 'network-list' : ('<Domain> [--long]',
183 'List virtual network interfaces for a domain.'),
184 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
185 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
186 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
187 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
188 'pci-attach' : ('[-o|--options=<opt>] <Domain> <domain:bus:slot.func> [virtual slot]',
189 'Insert a new pass-through pci device.'),
190 'pci-detach' : ('<Domain> <domain:bus:slot.func>',
191 'Remove a domain\'s pass-through pci device.'),
192 'pci-list' : ('<Domain>',
193 'List pass-through pci devices for a domain.'),
194 'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
195 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
196 'Attach a new SCSI device.'),
197 'scsi-detach' : ('<Domain> <VirtDevice>',
198 'Detach a specified SCSI device.'),
199 'scsi-list' : ('<Domain> [--long]',
200 'List all SCSI devices currently attached.'),
202 # security
204 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
205 ' [<policy>]',
206 'Add security label to domain.'),
207 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
208 'Remove a security label from domain.'),
209 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
210 'Show security label for domain or resource.'),
211 'dry-run' : ('<ConfigFile>',
212 'Test if a domain can access its resources.'),
213 'resources' : ('', 'Show info for each labeled resource.'),
214 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
215 'setpolicy' : ('<policytype> <policyfile> [options]',
216 'Set the policy of the system.'),
217 'resetpolicy' : ('',
218 'Set the policy of the system to the default policy.'),
219 'getpolicy' : ('[options]', 'Get the policy of the system.'),
220 'labels' : ('[policy] [type=dom|res|any]',
221 'List <type> labels for (active) policy.'),
222 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
223 }
225 SUBCOMMAND_OPTIONS = {
226 'sched-sedf': (
227 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
228 ('-s [MS]', '--slice[=MS]' ,
229 'Worst-case execution time(ms). (slice < period)'),
230 ('-l [MS]', '--latency[=MS]',
231 'Scaled period (ms) when domain performs heavy I/O'),
232 ('-e [FLAG]', '--extra[=FLAG]',
233 'Flag (0 or 1) controls if domain can run in extra time.'),
234 ('-w [FLOAT]', '--weight[=FLOAT]',
235 'CPU Period/slice (do not set with --period/--slice)'),
236 ),
237 'sched-credit': (
238 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
239 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
240 ('-c CAP', '--cap=CAP', 'Cap (int)'),
241 ),
242 'list': (
243 ('-l', '--long', 'Output all VM details in SXP'),
244 ('', '--label', 'Include security labels'),
245 ('', '--state=<state>', 'Select only VMs with the specified state'),
246 ),
247 'console': (
248 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
249 ),
250 'vncviewer': (
251 ('', '--autopass', 'Pass VNC password to viewer via stdin and -autopass'),
252 ('', '--vncviewer-autopass', '(consistency alias for --autopass)'),
253 ),
254 'dmesg': (
255 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
256 ),
257 'vnet-list': (
258 ('-l', '--long', 'List Vnets as SXP'),
259 ),
260 'network-list': (
261 ('-l', '--long', 'List resources as SXP'),
262 ),
263 'dump-core': (
264 ('-L', '--live', 'Dump core without pausing the domain'),
265 ('-C', '--crash', 'Crash domain after dumping core'),
266 ('-R', '--reset', 'Reset domain after dumping core'),
267 ),
268 'start': (
269 ('-p', '--paused', 'Do not unpause domain after starting it'),
270 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
271 ('', '--vncviewer', 'Connect to display via VNC after the domain is created'),
272 ('', '--vncviewer-autopass', 'Pass VNC password to viewer via stdin and -autopass'),
273 ),
274 'resume': (
275 ('-p', '--paused', 'Do not unpause domain after resuming it'),
276 ),
277 'save': (
278 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
279 ),
280 'restore': (
281 ('-p', '--paused', 'Do not unpause domain after restoring it'),
282 ),
283 'info': (
284 ('-c', '--config', 'List Xend configuration parameters'),
285 ),
286 }
288 common_commands = [
289 "console",
290 "vncviewer",
291 "create",
292 "new",
293 "delete",
294 "destroy",
295 "dump-core",
296 "help",
297 "list",
298 "mem-set",
299 "migrate",
300 "pause",
301 "reboot",
302 "reset",
303 "restore",
304 "resume",
305 "save",
306 "shell",
307 "shutdown",
308 "start",
309 "suspend",
310 "top",
311 "unpause",
312 "uptime",
313 "vcpu-set",
314 ]
316 domain_commands = [
317 "console",
318 "vncviewer",
319 "create",
320 "new",
321 "delete",
322 "destroy",
323 "domid",
324 "domname",
325 "dump-core",
326 "list",
327 "mem-max",
328 "mem-set",
329 "migrate",
330 "pause",
331 "reboot",
332 "rename",
333 "reset",
334 "restore",
335 "resume",
336 "save",
337 "shutdown",
338 "start",
339 "suspend",
340 "sysrq",
341 "trigger",
342 "top",
343 "unpause",
344 "uptime",
345 "vcpu-list",
346 "vcpu-pin",
347 "vcpu-set",
348 ]
350 host_commands = [
351 "debug-keys",
352 "dmesg",
353 "info",
354 "log",
355 "serve",
356 ]
358 scheduler_commands = [
359 "sched-credit",
360 "sched-sedf",
361 ]
363 device_commands = [
364 "block-attach",
365 "block-detach",
366 "block-list",
367 "block-configure",
368 "network-attach",
369 "network-detach",
370 "network-list",
371 "vtpm-list",
372 "pci-attach",
373 "pci-detach",
374 "pci-list",
375 "pci-list-assignable-devices",
376 "scsi-attach",
377 "scsi-detach",
378 "scsi-list",
379 ]
381 vnet_commands = [
382 "vnet-list",
383 "vnet-create",
384 "vnet-delete",
385 ]
387 acm_commands = [
388 "labels",
389 "addlabel",
390 "rmlabel",
391 "getlabel",
392 "dry-run",
393 "resources",
394 "dumppolicy",
395 "setpolicy",
396 "resetpolicy",
397 "getpolicy",
398 ]
400 all_commands = (domain_commands + host_commands + scheduler_commands +
401 device_commands + vnet_commands + acm_commands +
402 ['shell', 'event-monitor'])
405 ##
406 # Configuration File Parsing
407 ##
409 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
410 config = None
411 if os.path.isfile(xmConfigFile):
412 try:
413 config = xml.dom.minidom.parse(xmConfigFile)
414 except:
415 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
416 xmConfigFile)
418 def parseServer():
419 if config:
420 server = config.getElementsByTagName('server')
421 if server:
422 st = server[0].getAttribute('type')
423 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
424 print >>sys.stderr, ('Invalid server type %s; using %s.' %
425 (st, SERVER_LEGACY_XMLRPC))
426 st = SERVER_LEGACY_XMLRPC
427 return (st, server[0].getAttribute('uri'))
429 return SERVER_LEGACY_XMLRPC, XendClient.uri
431 def parseAuthentication():
432 server = config.getElementsByTagName('server')[0]
433 return (server.getAttribute('username'),
434 server.getAttribute('password'))
436 serverType, serverURI = parseServer()
437 server = None
440 ####################################################################
441 #
442 # Help/usage printing functions
443 #
444 ####################################################################
446 def cmdHelp(cmd):
447 """Print help for a specific subcommand."""
449 if not SUBCOMMAND_HELP.has_key(cmd):
450 for fc in SUBCOMMAND_HELP.keys():
451 if fc[:len(cmd)] == cmd:
452 cmd = fc
453 break
455 try:
456 args, desc = SUBCOMMAND_HELP[cmd]
457 except KeyError:
458 shortHelp()
459 return
461 print 'Usage: xm %s %s' % (cmd, args)
462 print
463 print desc
465 try:
466 # If options help message is defined, print this.
467 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
468 if shortopt and longopt:
469 optdesc = '%s, %s' % (shortopt, longopt)
470 elif shortopt:
471 optdesc = shortopt
472 elif longopt:
473 optdesc = longopt
475 wrapped_desc = wrap(desc, 43)
476 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
477 for line in wrapped_desc[1:]:
478 print ' ' * 33 + line
479 print
480 except KeyError:
481 # if the command is an external module, we grab usage help
482 # from the module itself.
483 if cmd in IMPORTED_COMMANDS:
484 try:
485 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
486 cmd_usage = getattr(cmd_module, "help", None)
487 if cmd_usage:
488 print cmd_usage()
489 except ImportError:
490 pass
492 def shortHelp():
493 """Print out generic help when xm is called without subcommand."""
495 print USAGE_HELP
496 print 'Common \'xm\' commands:\n'
498 for command in common_commands:
499 try:
500 args, desc = SUBCOMMAND_HELP[command]
501 except KeyError:
502 continue
503 wrapped_desc = wrap(desc, 50)
504 print ' %-20s %-50s' % (command, wrapped_desc[0])
505 for line in wrapped_desc[1:]:
506 print ' ' * 22 + line
508 print
509 print USAGE_FOOTER
510 print 'For a complete list of subcommands run \'xm help\'.'
512 def longHelp():
513 """Print out full help when xm is called with xm --help or xm help"""
515 print USAGE_HELP
516 print 'xm full list of subcommands:\n'
518 for command in all_commands:
519 try:
520 args, desc = SUBCOMMAND_HELP[command]
521 except KeyError:
522 continue
524 wrapped_desc = wrap(desc, 50)
525 print ' %-20s %-50s' % (command, wrapped_desc[0])
526 for line in wrapped_desc[1:]:
527 print ' ' * 22 + line
529 print
530 print USAGE_FOOTER
532 def _usage(cmd):
533 """ Print help usage information """
534 if cmd:
535 cmdHelp(cmd)
536 else:
537 shortHelp()
539 def usage(cmd = None):
540 """ Print help usage information and exits """
541 _usage(cmd)
542 sys.exit(1)
545 ####################################################################
546 #
547 # Utility functions
548 #
549 ####################################################################
551 def get_default_SR():
552 return [sr_ref
553 for sr_ref in server.xenapi.SR.get_all()
554 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
556 def get_default_Network():
557 return [network_ref
558 for network_ref in server.xenapi.network.get_all()][0]
560 class XenAPIUnsupportedException(Exception):
561 pass
563 def xenapi_unsupported():
564 if serverType == SERVER_XEN_API:
565 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
567 def xenapi_only():
568 if serverType != SERVER_XEN_API:
569 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
571 def map2sxp(m):
572 return [[k, m[k]] for k in m.keys()]
574 def arg_check(args, name, lo, hi = -1):
575 n = len([i for i in args if i != '--'])
577 if hi == -1:
578 if n != lo:
579 err("'xm %s' requires %d argument%s.\n" % (name, lo,
580 lo == 1 and '' or 's'))
581 usage(name)
582 else:
583 if n < lo or n > hi:
584 err("'xm %s' requires between %d and %d arguments.\n" %
585 (name, lo, hi))
586 usage(name)
589 def unit(c):
590 if not c.isalpha():
591 return 0
592 base = 1
593 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
594 elif c == 'M' or c == 'm': base = 1024 * 1024
595 elif c == 'K' or c == 'k': base = 1024
596 else:
597 print 'ignoring unknown unit'
598 return base
600 def int_unit(str, dest):
601 base = unit(str[-1])
602 if not base:
603 return int(str)
605 value = int(str[:-1])
606 dst_base = unit(dest)
607 if dst_base == 0:
608 dst_base = 1
609 if dst_base > base:
610 return value / (dst_base / base)
611 else:
612 return value * (base / dst_base)
614 def err(msg):
615 print >>sys.stderr, "Error:", msg
618 def get_single_vm(dom):
619 if serverType == SERVER_XEN_API:
620 uuids = server.xenapi.VM.get_by_name_label(dom)
621 if len(uuids) > 0:
622 return uuids[0]
624 refs = []
626 try:
627 domid = int(dom)
628 refs = [vm_ref
629 for vm_ref in server.xenapi.VM.get_all()
630 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
631 except:
632 pass
634 if len(refs) > 0:
635 return refs[0]
637 raise OptionError("Domain '%s' not found." % dom)
638 else:
639 dominfo = server.xend.domain(dom, False)
640 return dominfo['uuid']
642 ##
643 #
644 # Xen-API Shell
645 #
646 ##
648 class Shell(cmd.Cmd):
649 def __init__(self):
650 cmd.Cmd.__init__(self)
651 self.prompt = "xm> "
652 if serverType == SERVER_XEN_API:
653 try:
654 res = server.xenapi.host.list_methods()
655 for f in res:
656 setattr(Shell, 'do_' + f + ' ', self.default)
657 except:
658 pass
660 def preloop(self):
661 cmd.Cmd.preloop(self)
662 try:
663 import readline
664 readline.set_completer_delims(' ')
665 except ImportError:
666 pass
668 def default(self, line):
669 words = shlex.split(line)
670 if len(words) > 0 and words[0] == 'xm':
671 words = words[1:]
672 if len(words) > 0:
673 cmd = xm_lookup_cmd(words[0])
674 if cmd:
675 _run_cmd(cmd, words[0], words[1:])
676 elif serverType == SERVER_XEN_API:
677 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
678 tuple(x)),
679 words[0], words[1:])
680 if ok and res is not None and res != '':
681 pprint.pprint(res)
682 else:
683 print '*** Unknown command: %s' % words[0]
684 return False
686 def completedefault(self, text, line, begidx, endidx):
687 words = shlex.split(line[:begidx])
688 clas, func = words[0].split('.')
689 if len(words) > 1 or \
690 func.startswith('get_by_') or \
691 func == 'get_all':
692 return []
693 uuids = server.xenapi_request('%s.get_all' % clas, ())
694 return [u + " " for u in uuids if u.startswith(text)]
696 def emptyline(self):
697 pass
699 def do_EOF(self, line):
700 print
701 sys.exit(0)
703 def do_help(self, line):
704 _usage(line)
707 def xm_shell(args):
708 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
711 def xm_event_monitor(args):
712 if serverType == SERVER_XEN_API:
713 while True:
714 server.xenapi.event.register(args)
715 events = server.xenapi.event.next()
716 for e in events:
717 print e
718 else:
719 err("Event monitoring not supported unless using Xen-API.")
722 #########################################################################
723 #
724 # Main xm functions
725 #
726 #########################################################################
728 def xm_save(args):
730 arg_check(args, "save", 2, 3)
732 try:
733 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
734 except getopt.GetoptError, opterr:
735 err(opterr)
736 usage('save')
738 checkpoint = False
739 for (k, v) in options:
740 if k in ['-c', '--checkpoint']:
741 checkpoint = True
743 if len(params) != 2:
744 err("Wrong number of parameters")
745 usage('save')
747 dom = params[0]
748 savefile = os.path.abspath(params[1])
750 if not os.access(os.path.dirname(savefile), os.W_OK):
751 err("xm save: Unable to create file %s" % savefile)
752 sys.exit(1)
754 if serverType == SERVER_XEN_API:
755 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
756 else:
757 server.xend.domain.save(dom, savefile, checkpoint)
759 def xm_restore(args):
760 arg_check(args, "restore", 1, 2)
762 try:
763 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
764 except getopt.GetoptError, opterr:
765 err(opterr)
766 usage('restore')
768 paused = False
769 for (k, v) in options:
770 if k in ['-p', '--paused']:
771 paused = True
773 if len(params) != 1:
774 err("Wrong number of parameters")
775 usage('restore')
777 savefile = os.path.abspath(params[0])
779 if not os.access(savefile, os.R_OK):
780 err("xm restore: Unable to read file %s" % savefile)
781 sys.exit(1)
783 if serverType == SERVER_XEN_API:
784 server.xenapi.VM.restore(savefile, paused)
785 else:
786 server.xend.domain.restore(savefile, paused)
789 def datetime_to_secs(v):
790 unwanted = ":-."
791 for c in unwanted:
792 v = str(v).replace(c, "")
793 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
795 def getDomains(domain_names, state, full = 0):
796 if serverType == SERVER_XEN_API:
797 doms_sxp = []
798 doms_dict = []
800 dom_recs = server.xenapi.VM.get_all_records()
801 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
803 for dom_ref, dom_rec in dom_recs.items():
804 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
806 states = ('running', 'blocked', 'paused', 'shutdown',
807 'crashed', 'dying')
808 def state_on_off(state):
809 if state in dom_metrics_rec['state']:
810 return state[0]
811 else:
812 return "-"
813 state_str = "".join([state_on_off(state)
814 for state in states])
816 dom_rec.update({'name': dom_rec['name_label'],
817 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
818 'vcpus': dom_metrics_rec['VCPUs_number'],
819 'state': state_str,
820 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
821 'start_time': datetime_to_secs(
822 dom_metrics_rec['start_time'])})
824 doms_sxp.append(['domain'] + map2sxp(dom_rec))
825 doms_dict.append(dom_rec)
827 if domain_names:
828 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
829 if dom["name"] in domain_names]
831 if len(doms) > 0:
832 return doms
833 else:
834 print "Error: no domain%s named %s" % \
835 (len(domain_names) > 1 and 's' or '',
836 ', '.join(domain_names))
837 sys.exit(-1)
838 else:
839 return doms_sxp
840 else:
841 if domain_names:
842 return [server.xend.domain(dom, full) for dom in domain_names]
843 else:
844 return server.xend.domains_with_state(True, state, full)
847 def xm_list(args):
848 use_long = 0
849 show_vcpus = 0
850 show_labels = 0
851 state = 'all'
852 try:
853 (options, params) = getopt.gnu_getopt(args, 'lv',
854 ['long','vcpus','label',
855 'state='])
856 except getopt.GetoptError, opterr:
857 err(opterr)
858 usage('list')
860 for (k, v) in options:
861 if k in ['-l', '--long']:
862 use_long = 1
863 if k in ['-v', '--vcpus']:
864 show_vcpus = 1
865 if k in ['--label']:
866 show_labels = 1
867 if k in ['--state']:
868 state = v
870 if state != 'all' and len(params) > 0:
871 raise OptionError(
872 "You may specify either a state or a particular VM, but not both")
874 if show_vcpus:
875 print >>sys.stderr, (
876 "xm list -v is deprecated. Please use xm vcpu-list.")
877 xm_vcpu_list(params)
878 return
880 doms = getDomains(params, state, use_long)
882 if use_long:
883 map(PrettyPrint.prettyprint, doms)
884 elif show_labels:
885 xm_label_list(doms)
886 else:
887 xm_brief_list(doms)
890 def parse_doms_info(info):
891 def get_info(n, t, d):
892 return t(sxp.child_value(info, n, d))
894 def get_status(n, t, d):
895 return DOM_STATES[t(sxp.child_value(info, n, d))]
897 start_time = get_info('start_time', float, -1)
898 if start_time == -1:
899 up_time = float(-1)
900 else:
901 up_time = time.time() - start_time
903 parsed_info = {
904 'domid' : get_info('domid', str, ''),
905 'name' : get_info('name', str, '??'),
906 'state' : get_info('state', str, ''),
908 # VCPUs is the number online when the VM is up, or the number
909 # configured otherwise.
910 'vcpus' : get_info('online_vcpus', int,
911 get_info('vcpus', int, 0)),
912 'up_time' : up_time
913 }
915 security_label = get_info('security_label', str, '')
916 parsed_info['seclabel'] = security.parse_security_label(security_label)
918 if serverType == SERVER_XEN_API:
919 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
920 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
921 if sum(cpu_times.values()) > 0:
922 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
923 else:
924 parsed_info['cpu_time'] = 0
925 else:
926 parsed_info['mem'] = get_info('memory', int,0)
927 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
929 return parsed_info
931 def check_sched_type(sched):
932 if serverType == SERVER_XEN_API:
933 current = server.xenapi.host.get_sched_policy(
934 server.xenapi.session.get_this_host(server.getSession()))
935 else:
936 current = 'unknown'
937 for x in server.xend.node.info()[1:]:
938 if len(x) > 1 and x[0] == 'xen_scheduler':
939 current = x[1]
940 break
941 if sched != current:
942 err("Xen is running with the %s scheduler" % current)
943 sys.exit(1)
945 def parse_sedf_info(info):
946 def get_info(n, t, d):
947 return t(sxp.child_value(info, n, d))
949 return {
950 'domid' : get_info('domid', int, -1),
951 'period' : get_info('period', int, -1),
952 'slice' : get_info('slice', int, -1),
953 'latency' : get_info('latency', int, -1),
954 'extratime': get_info('extratime', int, -1),
955 'weight' : get_info('weight', int, -1),
956 }
958 def domid_match(domid, info):
959 return domid is None or domid == info['name'] or \
960 domid == str(info['domid'])
962 def xm_brief_list(doms):
963 print '%-40s %5s %5s %5s %10s %9s' % \
964 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
966 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
967 "%(cpu_time)8.1f"
969 for dom in doms:
970 d = parse_doms_info(dom)
971 print format % d
973 def xm_label_list(doms):
974 print '%-40s %5s %5s %5s %10s %9s %-10s' % \
975 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
977 output = []
978 format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
979 '%(cpu_time)8.1f %(seclabel)10s'
981 for dom in doms:
982 d = parse_doms_info(dom)
983 if d['seclabel'] == "" and serverType != SERVER_XEN_API:
984 seclab = server.xend.security.get_domain_label(d['name'])
985 if len(seclab) > 0 and seclab[0] == '\'':
986 seclab = seclab[1:]
987 d['seclabel'] = seclab
988 output.append((format % d, d['seclabel']))
990 #sort by labels
991 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
992 for line, label in output:
993 print line
996 def xm_vcpu_list(args):
997 if serverType == SERVER_XEN_API:
998 if args:
999 vm_refs = map(get_single_vm, args)
1000 else:
1001 vm_refs = server.xenapi.VM.get_all()
1003 vm_records = dict(map(lambda vm_ref:
1004 (vm_ref, server.xenapi.VM.get_record(
1005 vm_ref)),
1006 vm_refs))
1008 vm_metrics = dict(map(lambda (ref, record):
1009 (ref,
1010 server.xenapi.VM_metrics.get_record(
1011 record['metrics'])),
1012 vm_records.items()))
1014 dominfo = []
1016 # vcpu_list doesn't list 'managed' domains
1017 # when they are not running, so filter them out
1019 vm_refs = [vm_ref
1020 for vm_ref in vm_refs
1021 if vm_records[vm_ref]["power_state"] != "Halted"]
1023 for vm_ref in vm_refs:
1024 info = ['domain',
1025 ['domid', vm_records[vm_ref]['domid']],
1026 ['name', vm_records[vm_ref]['name_label']],
1027 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
1029 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
1030 def chk_flag(flag):
1031 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1032 and 1 or 0
1034 vcpu_info = ['vcpu',
1035 ['number',
1036 i],
1037 ['online',
1038 chk_flag("online")],
1039 ['blocked',
1040 chk_flag("blocked")],
1041 ['running',
1042 chk_flag("running")],
1043 ['cpu_time',
1044 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1045 ['cpu',
1046 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1047 ['cpumap',
1048 vm_metrics[vm_ref]['VCPUs_params']\
1049 ['cpumap%i' % i].split(",")]]
1051 info.append(vcpu_info)
1053 dominfo.append(info)
1054 else:
1055 if args:
1056 dominfo = map(server.xend.domain.getVCPUInfo, args)
1057 else:
1058 doms = server.xend.domains_with_state(False, 'all', False)
1059 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1061 print '%-32s %5s %5s %5s %5s %9s %s' % \
1062 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1064 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1065 ' %(cpu_time)8.1f %(cpumap)s'
1067 for dom in dominfo:
1068 def get_info(n):
1069 return sxp.child_value(dom, n)
1072 # convert a list of integers into a list of pairs indicating
1073 # continuous sequences in the list:
1075 # [0,1,2,3] -> [(0,3)]
1076 # [1,2,4,5] -> [(1,2),(4,5)]
1077 # [0] -> [(0,0)]
1078 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1080 def list_to_rangepairs(cmap):
1081 cmap.sort()
1082 pairs = []
1083 x = y = 0
1084 for i in range(0,len(cmap)):
1085 try:
1086 if ((cmap[y+1] - cmap[i]) > 1):
1087 pairs.append((cmap[x],cmap[y]))
1088 x = y = i+1
1089 else:
1090 y = y + 1
1091 # if we go off the end, then just add x to y
1092 except IndexError:
1093 pairs.append((cmap[x],cmap[y]))
1095 return pairs
1098 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1100 def format_pairs(pairs):
1101 if not pairs:
1102 return "no cpus"
1103 out = ""
1104 for f,s in pairs:
1105 if (f==s):
1106 out += '%d'%f
1107 else:
1108 out += '%d-%d'%(f,s)
1109 out += ','
1110 # trim trailing ','
1111 return out[:-1]
1113 def format_cpumap(cpumap):
1114 cpumap = map(lambda x: int(x), cpumap)
1115 cpumap.sort()
1117 if serverType == SERVER_XEN_API:
1118 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1119 server.xenapi.session.get_this_host(server.getSession())))
1120 else:
1121 for x in server.xend.node.info()[1:]:
1122 if len(x) > 1 and x[0] == 'nr_cpus':
1123 nr_cpus = int(x[1])
1125 # normalize cpumap by modulus nr_cpus, and drop duplicates
1126 cpumap = dict.fromkeys(
1127 filter(lambda x: x < nr_cpus, cpumap)).keys()
1128 if len(cpumap) == nr_cpus:
1129 return "any cpu"
1131 return format_pairs(list_to_rangepairs(cpumap))
1133 name = get_info('name')
1134 domid = get_info('domid')
1135 if domid is not None:
1136 domid = str(domid)
1137 else:
1138 domid = ''
1140 for vcpu in sxp.children(dom, 'vcpu'):
1141 def vinfo(n, t):
1142 return t(sxp.child_value(vcpu, n))
1144 number = vinfo('number', int)
1145 cpu = vinfo('cpu', int)
1146 cpumap = format_cpumap(vinfo('cpumap', list))
1147 online = vinfo('online', int)
1148 cpu_time = vinfo('cpu_time', float)
1149 running = vinfo('running', int)
1150 blocked = vinfo('blocked', int)
1152 if cpu < 0:
1153 c = ''
1154 s = ''
1155 elif online:
1156 c = str(cpu)
1157 if running:
1158 s = 'r'
1159 else:
1160 s = '-'
1161 if blocked:
1162 s += 'b'
1163 else:
1164 s += '-'
1165 s += '-'
1166 else:
1167 c = '-'
1168 s = '--p'
1170 print format % locals()
1172 def start_do_console(domain_name):
1173 cpid = os.fork()
1174 if cpid != 0:
1175 for i in range(10):
1176 # Catch failure of the create process
1177 time.sleep(1)
1178 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1179 if os.WIFEXITED(rv):
1180 if os.WEXITSTATUS(rv) != 0:
1181 sys.exit(os.WEXITSTATUS(rv))
1182 try:
1183 # Acquire the console of the created dom
1184 if serverType == SERVER_XEN_API:
1185 domid = server.xenapi.VM.get_domid(
1186 get_single_vm(domain_name))
1187 else:
1188 dom = server.xend.domain(domain_name)
1189 domid = int(sxp.child_value(dom, 'domid', '-1'))
1190 console.execConsole(domid)
1191 except:
1192 pass
1193 print("Could not start console\n");
1194 sys.exit(0)
1196 def xm_start(args):
1198 paused = False
1199 console_autoconnect = False
1200 vncviewer = False
1201 vncviewer_autopass = False
1203 try:
1204 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused','vncviewer','vncviewer-autopass'])
1205 for (k, v) in options:
1206 if k in ('-p', '--paused'):
1207 paused = True
1208 if k in ('-c', '--console_autoconnect'):
1209 console_autoconnect = True
1210 if k in ('--vncviewer'):
1211 vncviewer = True
1212 if k in ('--vncviewer-autopass'):
1213 vncviewer_autopass = True
1215 if len(params) != 1:
1216 raise OptionError("Expects 1 argument")
1217 except getopt.GetoptError, opterr:
1218 err(opterr)
1219 usage('start')
1221 dom = params[0]
1223 if console_autoconnect:
1224 start_do_console(dom)
1226 try:
1227 if serverType == SERVER_XEN_API:
1228 server.xenapi.VM.start(get_single_vm(dom), paused)
1229 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1230 else:
1231 server.xend.domain.start(dom, paused)
1232 info = server.xend.domain(dom)
1233 domid = int(sxp.child_value(info, 'domid', '-1'))
1234 except:
1235 raise
1237 if domid == -1:
1238 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1240 if vncviewer:
1241 console.runVncViewer(domid, vncviewer_autopass, True)
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 print "Dumping core of domain: %s ..." % str(dom)
1349 server.xend.domain.dump(dom, filename, live, crash, reset)
1351 def xm_rename(args):
1352 arg_check(args, "rename", 2)
1354 if serverType == SERVER_XEN_API:
1355 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1356 else:
1357 server.xend.domain.setName(args[0], args[1])
1359 def xm_importcommand(command, args):
1360 cmd = __import__(command, globals(), locals(), 'xen.xm')
1361 cmd.main([command] + args)
1364 #############################################################
1366 def xm_vcpu_pin(args):
1367 arg_check(args, "vcpu-pin", 3)
1369 def cpu_make_map(cpulist):
1370 cpus = []
1371 for c in cpulist.split(','):
1372 if c.find('-') != -1:
1373 (x,y) = c.split('-')
1374 for i in range(int(x),int(y)+1):
1375 cpus.append(int(i))
1376 else:
1377 # remove this element from the list
1378 if c[0] == '^':
1379 cpus = [x for x in cpus if x != int(c[1:])]
1380 else:
1381 cpus.append(int(c))
1382 cpus.sort()
1383 return ",".join(map(str, cpus))
1385 dom = args[0]
1386 vcpu = args[1]
1387 if args[2] == 'all':
1388 cpumap = cpu_make_map('0-63')
1389 else:
1390 cpumap = cpu_make_map(args[2])
1392 if serverType == SERVER_XEN_API:
1393 server.xenapi.VM.add_to_VCPUs_params_live(
1394 get_single_vm(dom), "cpumap%i" % int(vcpu), cpumap)
1395 else:
1396 server.xend.domain.pincpu(dom, vcpu, cpumap)
1398 def xm_mem_max(args):
1399 arg_check(args, "mem-max", 2)
1401 dom = args[0]
1403 if serverType == SERVER_XEN_API:
1404 mem = int_unit(args[1], 'k') * 1024
1405 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1406 else:
1407 mem = int_unit(args[1], 'm')
1408 server.xend.domain.maxmem_set(dom, mem)
1410 def xm_mem_set(args):
1411 arg_check(args, "mem-set", 2)
1413 dom = args[0]
1415 if serverType == SERVER_XEN_API:
1416 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1417 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1418 mem_target)
1419 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1420 mem_target)
1421 else:
1422 mem_target = int_unit(args[1], 'm')
1423 server.xend.domain.setMemoryTarget(dom, mem_target)
1425 def xm_vcpu_set(args):
1426 arg_check(args, "vcpu-set", 2)
1428 dom = args[0]
1429 vcpus = int(args[1])
1431 if serverType == SERVER_XEN_API:
1432 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1433 else:
1434 server.xend.domain.setVCpuCount(dom, vcpus)
1436 def xm_destroy(args):
1437 arg_check(args, "destroy", 1)
1439 dom = args[0]
1441 if serverType == SERVER_XEN_API:
1442 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1443 else:
1444 server.xend.domain.destroy(dom)
1446 def xm_domid(args):
1447 arg_check(args, "domid", 1)
1449 name = args[0]
1451 if serverType == SERVER_XEN_API:
1452 print server.xenapi.VM.get_domid(get_single_vm(name))
1453 else:
1454 dom = server.xend.domain(name)
1455 print sxp.child_value(dom, 'domid')
1457 def xm_domname(args):
1458 arg_check(args, "domname", 1)
1460 name = args[0]
1462 if serverType == SERVER_XEN_API:
1463 print server.xenapi.VM.get_name_label(get_single_vm(name))
1464 else:
1465 dom = server.xend.domain(name)
1466 print sxp.child_value(dom, 'name')
1468 def xm_sched_sedf(args):
1469 xenapi_unsupported()
1471 def ns_to_ms(val):
1472 return float(val) * 0.000001
1474 def ms_to_ns(val):
1475 return (float(val) / 0.000001)
1477 def print_sedf(info):
1478 info['period'] = ns_to_ms(info['period'])
1479 info['slice'] = ns_to_ms(info['slice'])
1480 info['latency'] = ns_to_ms(info['latency'])
1481 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1482 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1484 check_sched_type('sedf')
1486 # we want to just display current info if no parameters are passed
1487 if len(args) == 0:
1488 domid = None
1489 else:
1490 # we expect at least a domain id (name or number)
1491 # and at most a domid up to 5 options with values
1492 arg_check(args, "sched-sedf", 1, 11)
1493 domid = args[0]
1494 # drop domid from args since get_opt doesn't recognize it
1495 args = args[1:]
1497 opts = {}
1498 try:
1499 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1500 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1501 except getopt.GetoptError, opterr:
1502 err(opterr)
1503 usage('sched-sedf')
1505 # convert to nanoseconds if needed
1506 for (k, v) in options:
1507 if k in ['-p', '--period']:
1508 opts['period'] = ms_to_ns(v)
1509 elif k in ['-s', '--slice']:
1510 opts['slice'] = ms_to_ns(v)
1511 elif k in ['-l', '--latency']:
1512 opts['latency'] = ms_to_ns(v)
1513 elif k in ['-e', '--extratime']:
1514 opts['extratime'] = v
1515 elif k in ['-w', '--weight']:
1516 opts['weight'] = v
1518 doms = filter(lambda x : domid_match(domid, x),
1519 [parse_doms_info(dom)
1520 for dom in getDomains(None, 'running')])
1521 if domid is not None and doms == []:
1522 err("Domain '%s' does not exist." % domid)
1523 usage('sched-sedf')
1525 # print header if we aren't setting any parameters
1526 if len(opts.keys()) == 0:
1527 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1528 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1529 'Extra','Weight')
1531 for d in doms:
1532 # fetch current values so as not to clobber them
1533 try:
1534 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1535 except xmlrpclib.Fault:
1536 # domain does not support sched-sedf?
1537 sedf_raw = {}
1539 sedf_info = parse_sedf_info(sedf_raw)
1540 sedf_info['name'] = d['name']
1541 # update values in case of call to set
1542 if len(opts.keys()) > 0:
1543 for k in opts.keys():
1544 sedf_info[k]=opts[k]
1546 # send the update, converting user input
1547 v = map(int, [sedf_info['period'], sedf_info['slice'],
1548 sedf_info['latency'],sedf_info['extratime'],
1549 sedf_info['weight']])
1550 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1551 if int(rv) != 0:
1552 err("Failed to set sedf parameters (rv=%d)."%(rv))
1554 # not setting values, display info
1555 else:
1556 print_sedf(sedf_info)
1558 def xm_sched_credit(args):
1559 """Get/Set options for Credit Scheduler."""
1561 check_sched_type('credit')
1563 try:
1564 opts, params = getopt.getopt(args, "d:w:c:",
1565 ["domain=", "weight=", "cap="])
1566 except getopt.GetoptError, opterr:
1567 err(opterr)
1568 usage('sched-credit')
1570 domid = None
1571 weight = None
1572 cap = None
1574 for o, a in opts:
1575 if o in ["-d", "--domain"]:
1576 domid = a
1577 elif o in ["-w", "--weight"]:
1578 weight = int(a)
1579 elif o in ["-c", "--cap"]:
1580 cap = int(a);
1582 doms = filter(lambda x : domid_match(domid, x),
1583 [parse_doms_info(dom)
1584 for dom in getDomains(None, 'all')])
1586 if weight is None and cap is None:
1587 if domid is not None and doms == []:
1588 err("Domain '%s' does not exist." % domid)
1589 usage('sched-credit')
1590 # print header if we aren't setting any parameters
1591 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1593 for d in doms:
1594 try:
1595 if serverType == SERVER_XEN_API:
1596 info = server.xenapi.VM_metrics.get_VCPUs_params(
1597 server.xenapi.VM.get_metrics(
1598 get_single_vm(d['name'])))
1599 else:
1600 info = server.xend.domain.sched_credit_get(d['name'])
1601 except xmlrpclib.Fault:
1602 pass
1604 if 'weight' not in info or 'cap' not in info:
1605 # domain does not support sched-credit?
1606 info = {'weight': -1, 'cap': -1}
1608 info['weight'] = int(info['weight'])
1609 info['cap'] = int(info['cap'])
1611 info['name'] = d['name']
1612 info['domid'] = str(d['domid'])
1613 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1614 else:
1615 if domid is None:
1616 # place holder for system-wide scheduler parameters
1617 err("No domain given.")
1618 usage('sched-credit')
1620 if serverType == SERVER_XEN_API:
1621 if doms[0]['domid']:
1622 server.xenapi.VM.add_to_VCPUs_params_live(
1623 get_single_vm(domid),
1624 "weight",
1625 weight)
1626 server.xenapi.VM.add_to_VCPUs_params_live(
1627 get_single_vm(domid),
1628 "cap",
1629 cap)
1630 else:
1631 server.xenapi.VM.add_to_VCPUs_params(
1632 get_single_vm(domid),
1633 "weight",
1634 weight)
1635 server.xenapi.VM.add_to_VCPUs_params(
1636 get_single_vm(domid),
1637 "cap",
1638 cap)
1639 else:
1640 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1641 if result != 0:
1642 err(str(result))
1644 def xm_info(args):
1645 arg_check(args, "info", 0, 1)
1647 try:
1648 (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
1649 except getopt.GetoptError, opterr:
1650 err(opterr)
1651 usage('info')
1653 show_xend_config = 0
1654 for (k, v) in options:
1655 if k in ['-c', '--config']:
1656 show_xend_config = 1
1658 if show_xend_config:
1659 for name, obj in inspect.getmembers(xoptions):
1660 if not inspect.ismethod(obj):
1661 if name == "config":
1662 for x in obj[1:]:
1663 if len(x) < 2:
1664 print "%-38s: (none)" % x[0]
1665 else:
1666 print "%-38s:" % x[0], x[1]
1667 else:
1668 print "%-38s:" % name, obj
1669 return
1671 if serverType == SERVER_XEN_API:
1673 # Need to fake out old style xm info as people rely on parsing it
1675 host_record = server.xenapi.host.get_record(
1676 server.xenapi.session.get_this_host(server.getSession()))
1678 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1680 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1682 def getVal(keys, default=""):
1683 data = host_record
1684 for key in keys:
1685 if key in data:
1686 data = data[key]
1687 else:
1688 return default
1689 return data
1691 def getCpuMhz():
1692 cpu_speeds = [int(host_cpu_record["speed"])
1693 for host_cpu_record in host_cpu_records
1694 if "speed" in host_cpu_record]
1695 if len(cpu_speeds) > 0:
1696 return sum(cpu_speeds) / len(cpu_speeds)
1697 else:
1698 return 0
1700 getCpuMhz()
1702 def getCpuFeatures():
1703 if len(host_cpu_records) > 0:
1704 return host_cpu_records[0].get("features", "")
1705 else:
1706 return ""
1708 info = {
1709 "host": getVal(["name_label"]),
1710 "release": getVal(["software_version", "release"]),
1711 "version": getVal(["software_version", "version"]),
1712 "machine": getVal(["software_version", "machine"]),
1713 "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
1714 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1715 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1716 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1717 "cpu_mhz": getCpuMhz(),
1718 "hw_caps": getCpuFeatures(),
1719 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1720 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1721 "xen_major": getVal(["software_version", "xen_major"]),
1722 "xen_minor": getVal(["software_version", "xen_minor"]),
1723 "xen_extra": getVal(["software_version", "xen_extra"]),
1724 "xen_caps": " ".join(getVal(["capabilities"], [])),
1725 "xen_scheduler": getVal(["sched_policy"]),
1726 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1727 "platform_params": getVal(["other_config", "platform_params"]),
1728 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1729 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1730 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1731 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1732 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1733 "xend_config_format":getVal(["software_version", "xend_config_format"])
1736 sorted = info.items()
1737 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1739 for (k, v) in sorted:
1740 print "%-23s:" % k, v
1741 else:
1742 info = server.xend.node.info()
1743 for x in info[1:]:
1744 if len(x) < 2:
1745 print "%-23s: (none)" % x[0]
1746 else:
1747 print "%-23s:" % x[0], x[1]
1749 def xm_console(args):
1750 arg_check(args, "console", 1, 2)
1752 quiet = False;
1754 try:
1755 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1756 except getopt.GetoptError, opterr:
1757 err(opterr)
1758 usage('console')
1760 for (k, v) in options:
1761 if k in ['-q', '--quiet']:
1762 quiet = True
1763 else:
1764 assert False
1766 if len(params) != 1:
1767 err('No domain given')
1768 usage('console')
1770 dom = params[0]
1772 try:
1773 if serverType == SERVER_XEN_API:
1774 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1775 else:
1776 info = server.xend.domain(dom)
1777 domid = int(sxp.child_value(info, 'domid', '-1'))
1778 except:
1779 if quiet:
1780 sys.exit(1)
1781 else:
1782 raise
1784 if domid == -1:
1785 if quiet:
1786 sys.exit(1)
1787 else:
1788 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1790 console.execConsole(domid)
1793 def domain_name_to_domid(domain_name):
1794 if serverType == SERVER_XEN_API:
1795 domid = server.xenapi.VM.get_domid(
1796 get_single_vm(domain_name))
1797 else:
1798 dom = server.xend.domain(domain_name)
1799 domid = int(sxp.child_value(dom, 'domid', '-1'))
1800 return int(domid)
1802 def xm_vncviewer(args):
1803 autopass = False;
1805 try:
1806 (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass'])
1807 except getopt.GetoptError, opterr:
1808 err(opterr)
1809 usage('vncviewer')
1811 for (k, v) in options:
1812 if k in ['--autopass','--vncviewer-autopass']:
1813 autopass = True
1814 else:
1815 assert False
1817 if len(params) != 1:
1818 err('No domain given (or several parameters specified)')
1819 usage('vncviewer')
1821 dom = params[0]
1822 domid = domain_name_to_domid(dom)
1824 console.runVncViewer(domid, autopass)
1827 def xm_uptime(args):
1828 short_mode = 0
1830 try:
1831 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1832 except getopt.GetoptError, opterr:
1833 err(opterr)
1834 usage('uptime')
1836 for (k, v) in options:
1837 if k in ['-s', '--short']:
1838 short_mode = 1
1840 doms = getDomains(params, 'all')
1842 if short_mode == 0:
1843 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1845 for dom in doms:
1846 d = parse_doms_info(dom)
1847 if d['domid'] == '':
1848 uptime = 0
1849 elif int(d['domid']) > 0:
1850 uptime = int(round(d['up_time']))
1851 else:
1852 f=open('/proc/uptime', 'r')
1853 upfile = f.read()
1854 uptime = int(round(float(upfile.split(' ')[0])))
1855 f.close()
1857 days = int(uptime / 86400)
1858 uptime -= (days * 86400)
1859 hours = int(uptime / 3600)
1860 uptime -= (hours * 3600)
1861 minutes = int(uptime / 60)
1862 uptime -= (minutes * 60)
1863 seconds = uptime
1865 upstring = ""
1866 if days > 0:
1867 upstring += str(days) + " day"
1868 if days > 1:
1869 upstring += "s"
1870 upstring += ", "
1871 upstring += '%(hours)2d:%(minutes)02d' % vars()
1873 if short_mode:
1874 now = datetime.datetime.now()
1875 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1876 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1877 else:
1878 upstring += ':%(seconds)02d' % vars()
1879 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1881 print upstring
1883 def xm_sysrq(args):
1884 arg_check(args, "sysrq", 2)
1885 dom = args[0]
1886 req = args[1]
1887 if serverType == SERVER_XEN_API:
1888 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1889 else:
1890 server.xend.domain.send_sysrq(dom, req)
1892 def xm_trigger(args):
1893 vcpu = 0
1895 arg_check(args, "trigger", 2, 3)
1896 dom = args[0]
1897 trigger = args[1]
1898 if len(args) == 3:
1899 vcpu = int(args[2])
1901 if serverType == SERVER_XEN_API:
1902 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1903 else:
1904 server.xend.domain.send_trigger(dom, trigger, vcpu)
1906 def xm_debug_keys(args):
1907 arg_check(args, "debug-keys", 1)
1909 keys = str(args[0])
1911 if serverType == SERVER_XEN_API:
1912 server.xenapi.host.send_debug_keys(
1913 server.xenapi.session.get_this_host(server.getSession()),
1914 keys)
1915 else:
1916 server.xend.node.send_debug_keys(keys)
1918 def xm_top(args):
1919 arg_check(args, "top", 0)
1921 os.system('xentop')
1923 def xm_dmesg(args):
1924 arg_check(args, "dmesg", 0, 1)
1926 try:
1927 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1928 except getopt.GetoptError, opterr:
1929 err(opterr)
1930 usage('dmesg')
1932 use_clear = 0
1933 for (k, v) in options:
1934 if k in ['-c', '--clear']:
1935 use_clear = 1
1937 if len(params) :
1938 err("No parameter required")
1939 usage('dmesg')
1941 if serverType == SERVER_XEN_API:
1942 host = server.xenapi.session.get_this_host(server.getSession())
1943 if use_clear:
1944 print server.xenapi.host.dmesg_clear(host),
1945 else:
1946 print server.xenapi.host.dmesg(host),
1947 else:
1948 if not use_clear:
1949 print server.xend.node.dmesg.info(),
1950 else:
1951 print server.xend.node.dmesg.clear(),
1953 def xm_log(args):
1954 arg_check(args, "log", 0)
1956 if serverType == SERVER_XEN_API:
1957 print server.xenapi.host.get_log(
1958 server.xenapi.session.get_this_host(server.getSession()))
1959 else:
1960 print server.xend.node.log()
1962 def xm_serve(args):
1963 if serverType == SERVER_XEN_API:
1964 print "Not supported with XenAPI"
1965 sys.exit(-1)
1967 arg_check(args, "serve", 0)
1969 from fcntl import fcntl, F_SETFL
1971 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1972 s.connect(XendClient.XML_RPC_SOCKET)
1973 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1975 while True:
1976 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1977 if s in iwtd:
1978 data = s.recv(4096)
1979 if len(data) > 0:
1980 sys.stdout.write(data)
1981 sys.stdout.flush()
1982 else:
1983 break
1984 if sys.stdin in iwtd:
1985 data = sys.stdin.read(4096)
1986 if len(data) > 0:
1987 s.sendall(data)
1988 else:
1989 break
1990 s.close()
1992 def parse_dev_info(info):
1993 def get_info(n, t, d):
1994 i = 0
1995 while i < len(info):
1996 if (info[i][0] == n):
1997 return t(info[i][1])
1998 i = i + 1
1999 return t(d)
2000 return {
2001 #common
2002 'backend-id' : get_info('backend-id', int, -1),
2003 'handle' : get_info('handle', int, 0),
2004 'state' : get_info('state', int, -1),
2005 'be-path' : get_info('backend', str, '??'),
2006 'event-ch' : get_info('event-channel',int, -1),
2007 #network specific
2008 'virtual-device' : get_info('virtual-device', str, '??'),
2009 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
2010 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
2011 'mac' : get_info('mac', str, '??'),
2012 #block-device specific
2013 'ring-ref' : get_info('ring-ref', int, -1),
2014 #vscsi specific
2015 'feature-host' : get_info('feature-host', int, -1),
2018 def arg_check_for_resource_list(args, name):
2019 use_long = 0
2020 try:
2021 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2022 except getopt.GetoptError, opterr:
2023 err(opterr)
2024 sys.exit(1)
2026 for (k, v) in options:
2027 if k in ['-l', '--long']:
2028 use_long = 1
2030 if len(params) == 0:
2031 print 'No domain parameter given'
2032 usage(name)
2033 if len(params) > 1:
2034 print 'No multiple domain parameters allowed'
2035 usage(name)
2037 return (use_long, params)
2039 def xm_network_list(args):
2040 (use_long, params) = arg_check_for_resource_list(args, "network-list")
2042 dom = params[0]
2044 if serverType == SERVER_XEN_API:
2045 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2046 vif_properties = \
2047 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
2048 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2049 zip(range(len(vif_properties)), vif_properties))
2050 else:
2051 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
2053 if use_long:
2054 map(PrettyPrint.prettyprint, devs)
2055 else:
2056 hdr = 0
2057 for x in devs:
2058 if hdr == 0:
2059 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
2060 hdr = 1
2061 ni = parse_dev_info(x[1])
2062 ni['idx'] = int(x[0])
2063 print ("%(idx)-3d "
2064 "%(backend-id)-3d"
2065 "%(mac)-17s "
2066 "%(handle)-3d "
2067 "%(state)-3d "
2068 "%(event-ch)-3d "
2069 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
2070 "%(be-path)-30s "
2071 % ni)
2073 def xm_block_list(args):
2074 (use_long, params) = arg_check_for_resource_list(args, "block-list")
2076 dom = params[0]
2078 if serverType == SERVER_XEN_API:
2079 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2080 vbd_properties = \
2081 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2082 vbd_devs = \
2083 map(server.xenapi.VBD.get_device, vbd_refs)
2084 vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
2085 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2086 zip(vbd_devids, vbd_properties))
2087 else:
2088 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2090 if use_long:
2091 map(PrettyPrint.prettyprint, devs)
2092 else:
2093 hdr = 0
2094 for x in devs:
2095 if hdr == 0:
2096 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2097 hdr = 1
2098 ni = parse_dev_info(x[1])
2099 ni['idx'] = int(x[0])
2100 print ("%(idx)-5d "
2101 "%(backend-id)-3d "
2102 "%(handle)-3d "
2103 "%(state)-3d "
2104 "%(event-ch)-3d "
2105 "%(ring-ref)-5d "
2106 "%(be-path)-30s "
2107 % ni)
2109 def xm_vtpm_list(args):
2110 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2112 dom = params[0]
2114 if serverType == SERVER_XEN_API:
2115 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2116 vtpm_properties = \
2117 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2118 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2119 zip(range(len(vtpm_properties)), vtpm_properties))
2120 else:
2121 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2123 if use_long:
2124 map(PrettyPrint.prettyprint, devs)
2125 else:
2126 hdr = 0
2127 for x in devs:
2128 if hdr == 0:
2129 print 'Idx BE handle state evt-ch ring-ref BE-path'
2130 hdr = 1
2131 ni = parse_dev_info(x[1])
2132 ni['idx'] = int(x[0])
2133 print ("%(idx)-3d "
2134 "%(backend-id)-3d "
2135 "%(handle)-3d "
2136 "%(state)-3d "
2137 "%(event-ch)-3d "
2138 "%(ring-ref)-5d "
2139 "%(be-path)-30s "
2140 % ni)
2143 def xm_pci_list(args):
2144 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2146 dom = params[0]
2148 devs = []
2149 if serverType == SERVER_XEN_API:
2150 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2151 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2152 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2153 dev = {
2154 "domain": "0x%04x" % int(ppci_record["domain"]),
2155 "bus": "0x%02x" % int(ppci_record["bus"]),
2156 "slot": "0x%02x" % int(ppci_record["slot"]),
2157 "func": "0x%01x" % int(ppci_record["func"]),
2158 "vslot": "0x%02x" % \
2159 int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref))
2161 devs.append(dev)
2163 else:
2164 devs = server.xend.domain.getDeviceSxprs(dom, 'pci')
2166 if len(devs) == 0:
2167 return
2169 has_vslot = False
2170 for x in devs:
2171 vslot = assigned_or_requested_vslot(x)
2172 if int(vslot, 16) == AUTO_PHP_SLOT:
2173 x['vslot'] = '-'
2174 else:
2175 x['vslot'] = vslot
2176 has_vslot = True
2178 if has_vslot:
2179 hdr_str = 'VSlt domain bus slot func'
2180 fmt_str = "%(vslot)-4s %(domain)-6s %(bus)-4s %(slot)-4s %(func)-3s "
2181 else:
2182 hdr_str = 'domain bus slot func'
2183 fmt_str = "%(domain)-6s %(bus)-4s %(slot)-4s %(func)-3s "
2184 hdr = 0
2186 for x in devs:
2187 if hdr == 0:
2188 print (hdr_str)
2189 hdr = 1
2190 print ( fmt_str % x )
2193 def parse_pci_info(info):
2194 def get_info(n, t, d):
2195 return t(sxp.child_value(info, n, d))
2196 return {
2197 'domain' : get_info('domain', parse_hex, 0),
2198 'bus' : get_info('bus', parse_hex, -1),
2199 'slot' : get_info('slot', parse_hex, -1),
2200 'func' : get_info('func', parse_hex, -1)
2203 def xm_pci_list_assignable_devices(args):
2204 xenapi_unsupported()
2205 arg_check(args, "pci-list-assignable-devices", 0)
2207 devs = server.xend.node.pciinfo()
2209 fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
2210 for x in devs:
2211 pci = parse_pci_info(x)
2212 print fmt_str % pci
2215 def vscsi_sort(devs):
2216 def sort_hctl(ds, l):
2217 s = []
2218 for d1 in ds:
2219 for d2 in d1:
2220 v_dev = sxp.child_value(d2, 'v-dev')
2221 n = int(v_dev.split(':')[l])
2222 try:
2223 j = s[n]
2224 except IndexError:
2225 j = []
2226 s.extend([ [] for _ in range(len(s), n+1) ])
2227 j.append(d2)
2228 s[n] = j
2229 return s
2231 for i in range(len(devs)):
2232 ds1 = [ devs[i][1][0][1] ]
2233 ds1 = sort_hctl(ds1, 3)
2234 ds1 = sort_hctl(ds1, 2)
2235 ds1 = sort_hctl(ds1, 1)
2236 ds2 = []
2237 for d in ds1:
2238 ds2.extend(d)
2239 devs[i][1][0][1] = ds2
2240 return devs
2242 def vscsi_convert_sxp_to_dict(dev_sxp):
2243 dev_dict = {}
2244 for opt_val in dev_sxp[1:]:
2245 try:
2246 opt, val = opt_val
2247 dev_dict[opt] = val
2248 except TypeError:
2249 pass
2250 return dev_dict
2252 def xm_scsi_list(args):
2253 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2255 dom = params[0]
2257 devs = []
2258 if serverType == SERVER_XEN_API:
2260 dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
2261 dscsi_properties = \
2262 map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
2263 dscsi_dict = {}
2264 for dscsi_property in dscsi_properties:
2265 devid = int(dscsi_property['dev']['devid'])
2266 try:
2267 dscsi_sxp = dscsi_dict[devid]
2268 except:
2269 dscsi_sxp = [['devs', []]]
2270 for key, value in dscsi_property.items():
2271 if key != 'dev':
2272 dscsi_sxp.append([key, value])
2273 dev_sxp = ['dev']
2274 dev_sxp.extend(map2sxp(dscsi_property['dev']))
2275 dscsi_sxp[0][1].append(dev_sxp)
2276 dscsi_dict[devid] = dscsi_sxp
2277 devs = map2sxp(dscsi_dict)
2279 else:
2280 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2282 # Sort devs by virtual HCTL.
2283 devs = vscsi_sort(devs)
2285 if use_long:
2286 map(PrettyPrint.prettyprint, devs)
2287 else:
2288 hdr = 0
2289 for x in devs:
2290 if hdr == 0:
2291 print "%-3s %-3s %-5s %-4s %-10s %-5s %-10s %-4s" \
2292 % ('Idx', 'BE', 'state', 'host', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2293 hdr = 1
2294 ni = parse_dev_info(x[1])
2295 ni['idx'] = int(x[0])
2296 for dev in x[1][0][1]:
2297 mi = vscsi_convert_sxp_to_dict(dev)
2298 print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
2299 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2301 def parse_block_configuration(args):
2302 dom = args[0]
2304 if args[1].startswith('tap:'):
2305 cls = 'tap'
2306 else:
2307 cls = 'vbd'
2309 vbd = [cls,
2310 ['uname', args[1]],
2311 ['dev', args[2]],
2312 ['mode', args[3]]]
2313 if len(args) == 5:
2314 vbd.append(['backend', args[4]])
2316 return (dom, vbd)
2319 def xm_block_attach(args):
2320 arg_check(args, 'block-attach', 4, 5)
2322 if serverType == SERVER_XEN_API:
2323 dom = args[0]
2324 uname = args[1]
2325 dev = args[2]
2326 mode = args[3]
2328 # First create new VDI
2329 vdi_record = {
2330 "name_label": "vdi" + str(uname.__hash__()),
2331 "name_description": "",
2332 "SR": get_default_SR(),
2333 "virtual_size": 0,
2334 "sector_size": 512,
2335 "type": "system",
2336 "sharable": False,
2337 "read_only": mode!="w",
2338 "other_config": {"location": uname}
2341 vdi_ref = server.xenapi.VDI.create(vdi_record)
2343 # Now create new VBD
2345 vbd_record = {
2346 "VM": get_single_vm(dom),
2347 "VDI": vdi_ref,
2348 "device": dev,
2349 "bootable": True,
2350 "mode": mode=="w" and "RW" or "RO",
2351 "type": "Disk",
2352 "qos_algorithm_type": "",
2353 "qos_algorithm_params": {}
2356 server.xenapi.VBD.create(vbd_record)
2358 else:
2359 (dom, vbd) = parse_block_configuration(args)
2360 server.xend.domain.device_create(dom, vbd)
2363 def xm_block_configure(args):
2364 arg_check(args, 'block-configure', 4, 5)
2366 (dom, vbd) = parse_block_configuration(args)
2367 server.xend.domain.device_configure(dom, vbd)
2370 def xm_network_attach(args):
2371 arg_check(args, 'network-attach', 1, 11)
2373 dom = args[0]
2374 vif = ['vif']
2375 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2376 'backend', 'vifname', 'rate', 'model', 'accel']
2378 if serverType == SERVER_XEN_API:
2379 vif_record = {
2380 "device": "eth0",
2381 "network": get_default_Network(),
2382 "VM": get_single_vm(dom),
2383 "MAC": "",
2384 "MTU": "",
2385 "qos_algorithm_type": "",
2386 "qos_algorithm_params": {},
2387 "other_config": {}
2390 def set(keys, val):
2391 record = vif_record
2392 for key in keys[:-1]:
2393 record = record[key]
2394 record[keys[-1]] = val
2396 def get_net_from_bridge(bridge):
2397 # In OSS, we just assert network.name_label == bridge name
2398 networks = dict([(record['name_label'], ref)
2399 for ref, record in server.xenapi.network
2400 .get_all_records().items()])
2401 if bridge not in networks.keys():
2402 raise "Unknown bridge name!"
2403 return networks[bridge]
2405 vif_conv = {
2406 'type':
2407 lambda x: None,
2408 'mac':
2409 lambda x: set(['MAC'], x),
2410 'bridge':
2411 lambda x: set(['network'], get_net_from_bridge(x)),
2412 'ip':
2413 lambda x: set(['other_config', 'ip'], x),
2414 'script':
2415 lambda x: set(['other_config', 'script'], x),
2416 'backend':
2417 lambda x: set(['other_config', 'backend'], x),
2418 'vifname':
2419 lambda x: set(['device'], x),
2420 'rate':
2421 lambda x: set(['qos_algorithm_params', 'rate'], x),
2422 'model':
2423 lambda x: None,
2424 'accel':
2425 lambda x: set(['other_config', 'accel'], x)
2428 for a in args[1:]:
2429 vif_param = a.split("=")
2430 if len(vif_param) != 2 or vif_param[1] == '' or \
2431 vif_param[0] not in vif_params:
2432 err("Invalid argument: %s" % a)
2433 usage('network-attach')
2434 else:
2435 vif_conv[vif_param[0]](vif_param[1])
2437 server.xenapi.VIF.create(vif_record)
2438 else:
2439 for a in args[1:]:
2440 vif_param = a.split("=")
2441 if len(vif_param) != 2 or vif_param[1] == '' or \
2442 vif_param[0] not in vif_params:
2443 err("Invalid argument: %s" % a)
2444 usage('network-attach')
2445 vif.append(vif_param)
2446 server.xend.domain.device_create(dom, vif)
2448 def parse_pci_configuration(args, state, opts = ''):
2449 dom = args[0]
2450 pci_dev_str = args[1]
2451 if len(args) == 3:
2452 vslot = args[2]
2453 else:
2454 vslot = AUTO_PHP_SLOT_STR
2455 pci=['pci']
2456 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
2457 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
2458 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
2459 r"(?P<func>[0-7])$", pci_dev_str)
2460 if pci_match == None:
2461 raise OptionError("Invalid argument: %s %s" % (pci_dev_str, vslot))
2462 pci_dev_info = pci_match.groupdict('0')
2464 try:
2465 pci_bdf =['dev', ['domain', '0x'+ pci_dev_info['domain']], \
2466 ['bus', '0x'+ pci_dev_info['bus']],
2467 ['slot', '0x'+ pci_dev_info['slot']],
2468 ['func', '0x'+ pci_dev_info['func']],
2469 ['requested_vslot', '0x%x' % int(vslot, 16)]]
2470 if len(opts) > 0:
2471 pci_bdf.append(['opts', opts])
2472 pci.append(pci_bdf)
2474 except:
2475 raise OptionError("Invalid argument: %s %s" % (pci_dev_str, vslot))
2476 pci.append(['state', state])
2478 return (dom, pci)
2480 def xm_pci_attach(args):
2481 config_pci_opts = []
2482 (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
2483 for (k, v) in options:
2484 if k in ('-o', '--options'):
2485 if len(v.split('=')) != 2:
2486 err("Invalid pci attach option: %s" % v)
2487 usage('pci-attach')
2488 config_pci_opts.append(v.split('='))
2490 n = len([i for i in params if i != '--'])
2491 if n < 2 or n > 3:
2492 err("Invalid argument for 'xm pci-attach'")
2493 usage('pci-attach')
2495 (dom, pci) = parse_pci_configuration(params, 'Initialising',
2496 config_pci_opts)
2498 if serverType == SERVER_XEN_API:
2500 pci_dev = sxp.children(pci, 'dev')[0]
2501 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2502 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2503 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2504 func = int(sxp.child_value(pci_dev, 'func'), 16)
2505 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2506 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2508 target_ref = None
2509 for ppci_ref in server.xenapi.PPCI.get_all():
2510 if name == server.xenapi.PPCI.get_name(ppci_ref):
2511 target_ref = ppci_ref
2512 break
2513 if target_ref is None:
2514 raise OptionError("Device %s not found" % name)
2516 dpci_record = {
2517 "VM": get_single_vm(dom),
2518 "PPCI": target_ref,
2519 "hotplug_slot": vslot,
2520 "options": dict(config_pci_opts)
2522 server.xenapi.DPCI.create(dpci_record)
2524 else:
2525 server.xend.domain.device_configure(dom, pci)
2527 def parse_scsi_configuration(p_scsi, v_hctl, state):
2528 def get_devid(hctl):
2529 return int(hctl.split(':')[0])
2531 host_mode = 0
2532 scsi_devices = None
2534 if p_scsi is not None:
2535 # xm scsi-attach
2536 if v_hctl == "host":
2537 if serverType == SERVER_XEN_API:
2538 # TODO
2539 raise OptionError("SCSI devices assignment by HBA is not implemeted")
2540 host_mode = 1
2541 scsi_devices = vscsi_util.vscsi_get_scsidevices()
2542 elif len(v_hctl.split(':')) != 4:
2543 raise OptionError("Invalid argument: %s" % v_hctl)
2544 (p_hctl, devname) = \
2545 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
2546 if p_hctl is None:
2547 raise OptionError("Cannot find device '%s'" % p_scsi)
2548 if host_mode:
2549 scsi_info = []
2550 devid = get_devid(p_hctl)
2551 for pHCTL, devname, _, _ in scsi_devices:
2552 if get_devid(pHCTL) == devid:
2553 scsi_info.append([devid, pHCTL, devname, pHCTL])
2554 else:
2555 scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
2556 else:
2557 # xm scsi-detach
2558 if len(v_hctl.split(':')) != 4:
2559 raise OptionError("Invalid argument: %s" % v_hctl)
2560 scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
2562 scsi = ['vscsi', ['feature-host', host_mode]]
2563 for devid, pHCTL, devname, vHCTL in scsi_info:
2564 scsi.append(['dev', \
2565 ['state', state], \
2566 ['devid', devid], \
2567 ['p-dev', pHCTL], \
2568 ['p-devname', devname], \
2569 ['v-dev', vHCTL] \
2570 ])
2571 return scsi
2573 def xm_scsi_attach(args):
2574 arg_check(args, 'scsi-attach', 3, 4)
2575 dom = args[0]
2576 p_scsi = args[1]
2577 v_hctl = args[2]
2578 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2580 if serverType == SERVER_XEN_API:
2582 scsi_dev = sxp.children(scsi, 'dev')[0]
2583 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2584 target_ref = None
2585 for pscsi_ref in server.xenapi.PSCSI.get_all():
2586 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2587 target_ref = pscsi_ref
2588 break
2589 if target_ref is None:
2590 raise OptionError("Cannot find device '%s'" % p_scsi)
2592 dscsi_record = {
2593 "VM": get_single_vm(dom),
2594 "PSCSI": target_ref,
2595 "virtual_HCTL": v_hctl
2597 server.xenapi.DSCSI.create(dscsi_record)
2599 else:
2600 if len(args) == 4:
2601 scsi.append(['backend', args[3]])
2602 server.xend.domain.device_configure(dom, scsi)
2604 def detach(args, deviceClass):
2605 rm_cfg = True
2606 dom = args[0]
2607 dev = args[1]
2608 try:
2609 force = args[2]
2610 if (force != "--force") and (force != "-f"):
2611 print "Ignoring option %s"%(force)
2612 force = None
2613 except IndexError:
2614 force = None
2616 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2619 def xm_block_detach(args):
2620 if serverType == SERVER_XEN_API:
2621 arg_check(args, "block-detach", 2, 3)
2622 dom = args[0]
2623 dev = args[1]
2624 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2625 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2626 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2627 if len(vbd_refs) > 0:
2628 vbd_ref = vbd_refs[0]
2629 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2631 server.xenapi.VBD.destroy(vbd_ref)
2633 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2634 server.xenapi.VDI.destroy(vdi_ref)
2635 else:
2636 raise OptionError("Cannot find device '%s' in domain '%s'"
2637 % (dev,dom))
2638 else:
2639 arg_check(args, 'block-detach', 2, 3)
2640 dom = args[0]
2641 dev = args[1]
2642 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2643 if dc == "tap":
2644 detach(args, 'tap')
2645 else:
2646 detach(args, 'vbd')
2648 def xm_network_detach(args):
2649 if serverType == SERVER_XEN_API:
2650 arg_check(args, "network-detach", 2, 3)
2651 dom = args[0]
2652 devid = args[1]
2653 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2654 vif_refs = [vif_ref for vif_ref in vif_refs
2655 if server.xenapi.VIF.\
2656 get_runtime_properties(vif_ref)["handle"] == devid]
2657 if len(vif_refs) > 0:
2658 vif_ref = vif_refs[0]
2660 server.xenapi.VIF.destroy(vif_ref)
2661 else:
2662 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2663 else:
2664 arg_check(args, 'network-detach', 2, 3)
2665 detach(args, 'vif')
2667 def xm_pci_detach(args):
2668 arg_check(args, 'pci-detach', 2)
2669 (dom, pci) = parse_pci_configuration(args, 'Closing')
2671 if serverType == SERVER_XEN_API:
2673 pci_dev = sxp.children(pci, 'dev')[0]
2674 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2675 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2676 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2677 func = int(sxp.child_value(pci_dev, 'func'), 16)
2678 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2679 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2681 target_ref = None
2682 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2683 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2684 if name == server.xenapi.PPCI.get_name(ppci_ref):
2685 target_ref = ppci_ref
2686 server.xenapi.DPCI.destroy(dpci_ref)
2687 break
2688 if target_ref is None:
2689 raise OptionError("Device %s not assigned" % name)
2691 else:
2692 server.xend.domain.device_configure(dom, pci)
2694 def xm_scsi_detach(args):
2695 arg_check(args, 'scsi-detach', 2)
2696 dom = args[0]
2697 v_hctl = args[1]
2698 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
2700 if serverType == SERVER_XEN_API:
2702 target_ref = None
2703 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
2704 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
2705 target_ref = dscsi_ref
2706 break
2707 if target_ref is None:
2708 raise OptionError("Device %s not assigned" % v_hctl)
2710 server.xenapi.DSCSI.destroy(target_ref)
2712 else:
2713 server.xend.domain.device_configure(dom, scsi)
2715 def xm_vnet_list(args):
2716 xenapi_unsupported()
2717 try:
2718 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2719 except getopt.GetoptError, opterr:
2720 err(opterr)
2721 usage('vnet-list')
2723 use_long = 0
2724 for (k, v) in options:
2725 if k in ['-l', '--long']:
2726 use_long = 1
2728 if params:
2729 use_long = 1
2730 vnets = params
2731 else:
2732 vnets = server.xend_vnets()
2734 for vnet in vnets:
2735 try:
2736 if use_long:
2737 info = server.xend_vnet(vnet)
2738 PrettyPrint.prettyprint(info)
2739 else:
2740 print vnet
2741 except Exception, ex:
2742 print vnet, ex
2744 def xm_vnet_create(args):
2745 xenapi_unsupported()
2746 arg_check(args, "vnet-create", 1)
2747 conf = args[0]
2748 if not os.access(conf, os.R_OK):
2749 print "File not found: %s" % conf
2750 sys.exit(1)
2752 server.xend_vnet_create(conf)
2754 def xm_vnet_delete(args):
2755 xenapi_unsupported()
2756 arg_check(args, "vnet-delete", 1)
2757 vnet = args[0]
2758 server.xend_vnet_delete(vnet)
2760 def xm_network_new(args):
2761 xenapi_only()
2762 arg_check(args, "network-new", 1)
2763 network = args[0]
2765 record = {
2766 "name_label": network,
2767 "name_description": "",
2768 "other_config": {},
2769 "default_gateway": "",
2770 "default_netmask": ""
2773 server.xenapi.network.create(record)
2775 def xm_network_del(args):
2776 xenapi_only()
2777 arg_check(args, "network-del", 1)
2778 network = args[0]
2780 networks = dict([(record['name_label'], ref)
2781 for ref, record in
2782 server.xenapi.network.get_all_records().items()])
2784 if network not in networks.keys():
2785 raise ValueError("'%s' is not a valid network name" % network)
2787 server.xenapi.network.destroy(networks[network])
2789 def xm_network_show(args):
2790 xenapi_only()
2791 arg_check(args, "network-show", 0)
2793 networks = server.xenapi.network.get_all_records()
2794 pifs = server.xenapi.PIF.get_all_records()
2795 vifs = server.xenapi.VIF.get_all_records()
2797 print '%-20s %-40s %-10s' % \
2798 ('Name', 'VIFs', 'PIFs')
2800 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2802 for network_ref, network in networks.items():
2803 for i in range(max(len(network['PIFs']),
2804 len(network['VIFs']), 1)):
2805 if i < len(network['PIFs']):
2806 pif_uuid = network['PIFs'][i]
2807 else:
2808 pif_uuid = None
2810 if i < len(network['VIFs']):
2811 vif_uuid = network['VIFs'][i]
2812 else:
2813 vif_uuid = None
2815 pif = pifs.get(pif_uuid, None)
2816 vif = vifs.get(vif_uuid, None)
2818 if vif:
2819 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2820 vif = "%s.%s" % (dom_name, vif['device'])
2821 else:
2822 vif = ''
2824 if pif:
2825 if int(pif['VLAN']) > -1:
2826 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2827 else:
2828 pif = pif['device']
2829 else:
2830 pif = ''
2832 if i == 0:
2833 r = {'name_label':network['name_label'],
2834 'vif':vif, 'pif':pif}
2835 else:
2836 r = {'name_label':'', 'vif':vif, 'pif':pif}
2838 print format2 % r
2841 commands = {
2842 "shell": xm_shell,
2843 "event-monitor": xm_event_monitor,
2844 # console commands
2845 "console": xm_console,
2846 "vncviewer": xm_vncviewer,
2847 # xenstat commands
2848 "top": xm_top,
2849 # domain commands
2850 "delete": xm_delete,
2851 "destroy": xm_destroy,
2852 "domid": xm_domid,
2853 "domname": xm_domname,
2854 "dump-core": xm_dump_core,
2855 "reboot": xm_reboot,
2856 "rename": xm_rename,
2857 "reset": xm_reset,
2858 "restore": xm_restore,
2859 "resume": xm_resume,
2860 "save": xm_save,
2861 "shutdown": xm_shutdown,
2862 "start": xm_start,
2863 "sysrq": xm_sysrq,
2864 "trigger": xm_trigger,
2865 "uptime": xm_uptime,
2866 "suspend": xm_suspend,
2867 "list": xm_list,
2868 # memory commands
2869 "mem-max": xm_mem_max,
2870 "mem-set": xm_mem_set,
2871 # cpu commands
2872 "vcpu-pin": xm_vcpu_pin,
2873 "vcpu-list": xm_vcpu_list,
2874 "vcpu-set": xm_vcpu_set,
2875 # special
2876 "pause": xm_pause,
2877 "unpause": xm_unpause,
2878 # host commands
2879 "debug-keys": xm_debug_keys,
2880 "dmesg": xm_dmesg,
2881 "info": xm_info,
2882 "log": xm_log,
2883 "serve": xm_serve,
2884 # scheduler
2885 "sched-sedf": xm_sched_sedf,
2886 "sched-credit": xm_sched_credit,
2887 # block
2888 "block-attach": xm_block_attach,
2889 "block-detach": xm_block_detach,
2890 "block-list": xm_block_list,
2891 "block-configure": xm_block_configure,
2892 # network (AKA vifs)
2893 "network-attach": xm_network_attach,
2894 "network-detach": xm_network_detach,
2895 "network-list": xm_network_list,
2896 # network (as in XenAPI)
2897 "network-new": xm_network_new,
2898 "network-del": xm_network_del,
2899 "network-show": xm_network_show,
2900 # vnet
2901 "vnet-list": xm_vnet_list,
2902 "vnet-create": xm_vnet_create,
2903 "vnet-delete": xm_vnet_delete,
2904 # vtpm
2905 "vtpm-list": xm_vtpm_list,
2906 #pci
2907 "pci-attach": xm_pci_attach,
2908 "pci-detach": xm_pci_detach,
2909 "pci-list": xm_pci_list,
2910 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
2911 # vscsi
2912 "scsi-attach": xm_scsi_attach,
2913 "scsi-detach": xm_scsi_detach,
2914 "scsi-list": xm_scsi_list,
2917 ## The commands supported by a separate argument parser in xend.xm.
2918 IMPORTED_COMMANDS = [
2919 'create',
2920 'new',
2921 'migrate',
2922 'labels',
2923 'dumppolicy',
2924 'addlabel',
2925 'rmlabel',
2926 'getlabel',
2927 'dry-run',
2928 'resources',
2929 'getpolicy',
2930 'setpolicy',
2931 'resetpolicy',
2934 for c in IMPORTED_COMMANDS:
2935 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2937 aliases = {
2938 "balloon": "mem-set",
2939 "set-vcpus": "vcpu-set",
2940 "vif-list": "network-list",
2941 "vbd-create": "block-attach",
2942 "vbd-destroy": "block-detach",
2943 "vbd-list": "block-list",
2947 def xm_lookup_cmd(cmd):
2948 if commands.has_key(cmd):
2949 return commands[cmd]
2950 elif aliases.has_key(cmd):
2951 deprecated(cmd,aliases[cmd])
2952 return commands[aliases[cmd]]
2953 elif cmd == 'help':
2954 longHelp()
2955 sys.exit(0)
2956 else:
2957 # simulate getopt's prefix matching behaviour
2958 if len(cmd) > 1:
2959 same_prefix_cmds = [commands[c] for c in commands.keys() \
2960 if c[:len(cmd)] == cmd]
2961 # only execute if there is only 1 match
2962 if len(same_prefix_cmds) == 1:
2963 return same_prefix_cmds[0]
2964 return None
2966 def deprecated(old,new):
2967 print >>sys.stderr, (
2968 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2970 def main(argv=sys.argv):
2971 if len(argv) < 2:
2972 usage()
2974 # intercept --help(-h) and output our own help
2975 for help in ['--help', '-h']:
2976 if help in argv[1:]:
2977 if help == argv[1]:
2978 longHelp()
2979 sys.exit(0)
2980 else:
2981 usage(argv[1])
2983 cmd_name = argv[1]
2984 cmd = xm_lookup_cmd(cmd_name)
2985 if cmd:
2986 # strip off prog name and subcmd
2987 args = argv[2:]
2988 _, rc = _run_cmd(cmd, cmd_name, args)
2989 sys.exit(rc)
2990 else:
2991 err('Subcommand %s not found!' % cmd_name)
2992 usage()
2994 def _run_cmd(cmd, cmd_name, args):
2995 global server
2997 try:
2998 if server is None:
2999 if serverType == SERVER_XEN_API:
3000 server = XenAPI.Session(serverURI)
3001 username, password = parseAuthentication()
3002 server.login_with_password(username, password)
3003 def logout():
3004 try:
3005 server.xenapi.session.logout()
3006 except:
3007 pass
3008 atexit.register(logout)
3009 else:
3010 server = ServerProxy(serverURI)
3012 return True, cmd(args)
3013 except socket.error, ex:
3014 if os.geteuid() != 0:
3015 err("Most commands need root access. Please try again as root.")
3016 else:
3017 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
3018 except KeyboardInterrupt:
3019 print "Interrupted."
3020 return True, ''
3021 except IOError, ex:
3022 if os.geteuid() != 0:
3023 err("Most commands need root access. Please try again as root.")
3024 else:
3025 err("Unable to connect to xend: %s." % ex[1])
3026 except SystemExit, code:
3027 return code == 0, code
3028 except XenAPI.Failure, exn:
3029 for line in [''] + wrap(str(exn), 80) + ['']:
3030 print >>sys.stderr, line
3031 except xmlrpclib.Fault, ex:
3032 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
3033 err("Domain '%s' does not exist." % ex.faultString)
3034 return False, ex.faultCode
3035 else:
3036 err(ex.faultString)
3037 _usage(cmd_name)
3038 except xmlrpclib.ProtocolError, ex:
3039 if ex.errcode == -1:
3040 print >>sys.stderr, (
3041 "Xend has probably crashed! Invalid or missing HTTP "
3042 "status code.")
3043 else:
3044 print >>sys.stderr, (
3045 "Xend has probably crashed! ProtocolError(%d, %s)." %
3046 (ex.errcode, ex.errmsg))
3047 except (ValueError, OverflowError):
3048 err("Invalid argument.")
3049 _usage(cmd_name)
3050 except OptionError, e:
3051 err(str(e))
3052 _usage(cmd_name)
3053 print e.usage
3054 except XenAPIUnsupportedException, e:
3055 err(str(e))
3056 except XSMError, e:
3057 err(str(e))
3058 except Exception, e:
3059 if serverType != SERVER_XEN_API:
3060 import xen.util.xsm.xsm as security
3061 if isinstance(e, security.XSMError):
3062 err(str(e))
3063 return False, 1
3064 print "Unexpected error:", sys.exc_info()[0]
3065 print
3066 print "Please report to xen-devel@lists.xensource.com"
3067 raise
3069 return False, 1
3071 if __name__ == "__main__":
3072 main()