ia64/xen-unstable

view tools/python/xen/xm/main.py @ 19634:61404d971c92

xend: Fix typo in usage of new auxbin.xen_configdir() function

Signed-off-by: Keir Fraser <keir.fraser@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 21 04:31:47 2009 +0100 (2009-05-21)
parents 23f9857f642f
children dc7de36c94e3
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 if x.has_key('vslot'):
2172 if x['vslot'] == "0x%s" % AUTO_PHP_SLOT_STR:
2173 x['vslot'] = '-'
2174 else:
2175 has_vslot = True
2176 elif not x.has_key('requested_vslot'):
2177 x['vslot'] = '-'
2178 elif x['requested_vslot'] == "0x%s" % AUTO_PHP_SLOT_STR:
2179 x['vslot'] = '-'
2180 else:
2181 has_vslot = True
2182 x['vslot'] = x['requested_vslot']
2184 if has_vslot:
2185 hdr_str = 'VSlt domain bus slot func'
2186 fmt_str = "%(vslot)-4s %(domain)-6s %(bus)-4s %(slot)-4s %(func)-3s "
2187 else:
2188 hdr_str = 'domain bus slot func'
2189 fmt_str = "%(domain)-6s %(bus)-4s %(slot)-4s %(func)-3s "
2190 hdr = 0
2192 for x in devs:
2193 if hdr == 0:
2194 print (hdr_str)
2195 hdr = 1
2196 print ( fmt_str % x )
2199 def parse_pci_info(info):
2200 def get_info(n, t, d):
2201 return t(sxp.child_value(info, n, d))
2202 return {
2203 'domain' : get_info('domain', parse_hex, 0),
2204 'bus' : get_info('bus', parse_hex, -1),
2205 'slot' : get_info('slot', parse_hex, -1),
2206 'func' : get_info('func', parse_hex, -1)
2209 def xm_pci_list_assignable_devices(args):
2210 xenapi_unsupported()
2211 arg_check(args, "pci-list-assignable-devices", 0)
2213 devs = server.xend.node.pciinfo()
2215 fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
2216 for x in devs:
2217 pci = parse_pci_info(x)
2218 print fmt_str % pci
2221 def vscsi_sort(devs):
2222 def sort_hctl(ds, l):
2223 s = []
2224 for d1 in ds:
2225 for d2 in d1:
2226 v_dev = sxp.child_value(d2, 'v-dev')
2227 n = int(v_dev.split(':')[l])
2228 try:
2229 j = s[n]
2230 except IndexError:
2231 j = []
2232 s.extend([ [] for _ in range(len(s), n+1) ])
2233 j.append(d2)
2234 s[n] = j
2235 return s
2237 for i in range(len(devs)):
2238 ds1 = [ devs[i][1][0][1] ]
2239 ds1 = sort_hctl(ds1, 3)
2240 ds1 = sort_hctl(ds1, 2)
2241 ds1 = sort_hctl(ds1, 1)
2242 ds2 = []
2243 for d in ds1:
2244 ds2.extend(d)
2245 devs[i][1][0][1] = ds2
2246 return devs
2248 def vscsi_convert_sxp_to_dict(dev_sxp):
2249 dev_dict = {}
2250 for opt_val in dev_sxp[1:]:
2251 try:
2252 opt, val = opt_val
2253 dev_dict[opt] = val
2254 except TypeError:
2255 pass
2256 return dev_dict
2258 def xm_scsi_list(args):
2259 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2261 dom = params[0]
2263 devs = []
2264 if serverType == SERVER_XEN_API:
2266 dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
2267 dscsi_properties = \
2268 map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
2269 dscsi_dict = {}
2270 for dscsi_property in dscsi_properties:
2271 devid = int(dscsi_property['dev']['devid'])
2272 try:
2273 dscsi_sxp = dscsi_dict[devid]
2274 except:
2275 dscsi_sxp = [['devs', []]]
2276 for key, value in dscsi_property.items():
2277 if key != 'dev':
2278 dscsi_sxp.append([key, value])
2279 dev_sxp = ['dev']
2280 dev_sxp.extend(map2sxp(dscsi_property['dev']))
2281 dscsi_sxp[0][1].append(dev_sxp)
2282 dscsi_dict[devid] = dscsi_sxp
2283 devs = map2sxp(dscsi_dict)
2285 else:
2286 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2288 # Sort devs by virtual HCTL.
2289 devs = vscsi_sort(devs)
2291 if use_long:
2292 map(PrettyPrint.prettyprint, devs)
2293 else:
2294 hdr = 0
2295 for x in devs:
2296 if hdr == 0:
2297 print "%-3s %-3s %-5s %-4s %-10s %-5s %-10s %-4s" \
2298 % ('Idx', 'BE', 'state', 'host', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2299 hdr = 1
2300 ni = parse_dev_info(x[1])
2301 ni['idx'] = int(x[0])
2302 for dev in x[1][0][1]:
2303 mi = vscsi_convert_sxp_to_dict(dev)
2304 print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
2305 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2307 def parse_block_configuration(args):
2308 dom = args[0]
2310 if args[1].startswith('tap:'):
2311 cls = 'tap'
2312 else:
2313 cls = 'vbd'
2315 vbd = [cls,
2316 ['uname', args[1]],
2317 ['dev', args[2]],
2318 ['mode', args[3]]]
2319 if len(args) == 5:
2320 vbd.append(['backend', args[4]])
2322 return (dom, vbd)
2325 def xm_block_attach(args):
2326 arg_check(args, 'block-attach', 4, 5)
2328 if serverType == SERVER_XEN_API:
2329 dom = args[0]
2330 uname = args[1]
2331 dev = args[2]
2332 mode = args[3]
2334 # First create new VDI
2335 vdi_record = {
2336 "name_label": "vdi" + str(uname.__hash__()),
2337 "name_description": "",
2338 "SR": get_default_SR(),
2339 "virtual_size": 0,
2340 "sector_size": 512,
2341 "type": "system",
2342 "sharable": False,
2343 "read_only": mode!="w",
2344 "other_config": {"location": uname}
2347 vdi_ref = server.xenapi.VDI.create(vdi_record)
2349 # Now create new VBD
2351 vbd_record = {
2352 "VM": get_single_vm(dom),
2353 "VDI": vdi_ref,
2354 "device": dev,
2355 "bootable": True,
2356 "mode": mode=="w" and "RW" or "RO",
2357 "type": "Disk",
2358 "qos_algorithm_type": "",
2359 "qos_algorithm_params": {}
2362 server.xenapi.VBD.create(vbd_record)
2364 else:
2365 (dom, vbd) = parse_block_configuration(args)
2366 server.xend.domain.device_create(dom, vbd)
2369 def xm_block_configure(args):
2370 arg_check(args, 'block-configure', 4, 5)
2372 (dom, vbd) = parse_block_configuration(args)
2373 server.xend.domain.device_configure(dom, vbd)
2376 def xm_network_attach(args):
2377 arg_check(args, 'network-attach', 1, 11)
2379 dom = args[0]
2380 vif = ['vif']
2381 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2382 'backend', 'vifname', 'rate', 'model', 'accel']
2384 if serverType == SERVER_XEN_API:
2385 vif_record = {
2386 "device": "eth0",
2387 "network": get_default_Network(),
2388 "VM": get_single_vm(dom),
2389 "MAC": "",
2390 "MTU": "",
2391 "qos_algorithm_type": "",
2392 "qos_algorithm_params": {},
2393 "other_config": {}
2396 def set(keys, val):
2397 record = vif_record
2398 for key in keys[:-1]:
2399 record = record[key]
2400 record[keys[-1]] = val
2402 def get_net_from_bridge(bridge):
2403 # In OSS, we just assert network.name_label == bridge name
2404 networks = dict([(record['name_label'], ref)
2405 for ref, record in server.xenapi.network
2406 .get_all_records().items()])
2407 if bridge not in networks.keys():
2408 raise "Unknown bridge name!"
2409 return networks[bridge]
2411 vif_conv = {
2412 'type':
2413 lambda x: None,
2414 'mac':
2415 lambda x: set(['MAC'], x),
2416 'bridge':
2417 lambda x: set(['network'], get_net_from_bridge(x)),
2418 'ip':
2419 lambda x: set(['other_config', 'ip'], x),
2420 'script':
2421 lambda x: set(['other_config', 'script'], x),
2422 'backend':
2423 lambda x: set(['other_config', 'backend'], x),
2424 'vifname':
2425 lambda x: set(['device'], x),
2426 'rate':
2427 lambda x: set(['qos_algorithm_params', 'rate'], x),
2428 'model':
2429 lambda x: None,
2430 'accel':
2431 lambda x: set(['other_config', 'accel'], x)
2434 for a in args[1:]:
2435 vif_param = a.split("=")
2436 if len(vif_param) != 2 or vif_param[1] == '' or \
2437 vif_param[0] not in vif_params:
2438 err("Invalid argument: %s" % a)
2439 usage('network-attach')
2440 else:
2441 vif_conv[vif_param[0]](vif_param[1])
2443 server.xenapi.VIF.create(vif_record)
2444 else:
2445 for a in args[1:]:
2446 vif_param = a.split("=")
2447 if len(vif_param) != 2 or vif_param[1] == '' or \
2448 vif_param[0] not in vif_params:
2449 err("Invalid argument: %s" % a)
2450 usage('network-attach')
2451 vif.append(vif_param)
2452 server.xend.domain.device_create(dom, vif)
2454 def parse_pci_configuration(args, state, opts = ''):
2455 dom = args[0]
2456 pci_dev_str = args[1]
2457 if len(args) == 3:
2458 vslot = args[2]
2459 else:
2460 vslot = AUTO_PHP_SLOT_STR
2461 pci=['pci']
2462 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
2463 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
2464 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
2465 r"(?P<func>[0-7])$", pci_dev_str)
2466 if pci_match == None:
2467 raise OptionError("Invalid argument: %s %s" % (pci_dev_str, vslot))
2468 pci_dev_info = pci_match.groupdict('0')
2470 try:
2471 pci_bdf =['dev', ['domain', '0x'+ pci_dev_info['domain']], \
2472 ['bus', '0x'+ pci_dev_info['bus']],
2473 ['slot', '0x'+ pci_dev_info['slot']],
2474 ['func', '0x'+ pci_dev_info['func']],
2475 ['requested_vslot', '0x%x' % int(vslot, 16)]]
2476 if len(opts) > 0:
2477 pci_bdf.append(['opts', opts])
2478 pci.append(pci_bdf)
2480 except:
2481 raise OptionError("Invalid argument: %s %s" % (pci_dev_str, vslot))
2482 pci.append(['state', state])
2484 return (dom, pci)
2486 def xm_pci_attach(args):
2487 config_pci_opts = []
2488 (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
2489 for (k, v) in options:
2490 if k in ('-o', '--options'):
2491 if len(v.split('=')) != 2:
2492 err("Invalid pci attach option: %s" % v)
2493 usage('pci-attach')
2494 config_pci_opts.append(v.split('='))
2496 n = len([i for i in params if i != '--'])
2497 if n < 2 or n > 3:
2498 err("Invalid argument for 'xm pci-attach'")
2499 usage('pci-attach')
2501 (dom, pci) = parse_pci_configuration(params, 'Initialising',
2502 config_pci_opts)
2504 if serverType == SERVER_XEN_API:
2506 pci_dev = sxp.children(pci, 'dev')[0]
2507 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2508 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2509 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2510 func = int(sxp.child_value(pci_dev, 'func'), 16)
2511 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2512 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2514 target_ref = None
2515 for ppci_ref in server.xenapi.PPCI.get_all():
2516 if name == server.xenapi.PPCI.get_name(ppci_ref):
2517 target_ref = ppci_ref
2518 break
2519 if target_ref is None:
2520 raise OptionError("Device %s not found" % name)
2522 dpci_record = {
2523 "VM": get_single_vm(dom),
2524 "PPCI": target_ref,
2525 "hotplug_slot": vslot,
2526 "options": dict(config_pci_opts)
2528 server.xenapi.DPCI.create(dpci_record)
2530 else:
2531 server.xend.domain.device_configure(dom, pci)
2533 def parse_scsi_configuration(p_scsi, v_hctl, state):
2534 def get_devid(hctl):
2535 return int(hctl.split(':')[0])
2537 host_mode = 0
2538 scsi_devices = None
2540 if p_scsi is not None:
2541 # xm scsi-attach
2542 if v_hctl == "host":
2543 if serverType == SERVER_XEN_API:
2544 # TODO
2545 raise OptionError("SCSI devices assignment by HBA is not implemeted")
2546 host_mode = 1
2547 scsi_devices = vscsi_util.vscsi_get_scsidevices()
2548 elif len(v_hctl.split(':')) != 4:
2549 raise OptionError("Invalid argument: %s" % v_hctl)
2550 (p_hctl, devname) = \
2551 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
2552 if p_hctl is None:
2553 raise OptionError("Cannot find device '%s'" % p_scsi)
2554 if host_mode:
2555 scsi_info = []
2556 devid = get_devid(p_hctl)
2557 for pHCTL, devname, _, _ in scsi_devices:
2558 if get_devid(pHCTL) == devid:
2559 scsi_info.append([devid, pHCTL, devname, pHCTL])
2560 else:
2561 scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
2562 else:
2563 # xm scsi-detach
2564 if len(v_hctl.split(':')) != 4:
2565 raise OptionError("Invalid argument: %s" % v_hctl)
2566 scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
2568 scsi = ['vscsi', ['feature-host', host_mode]]
2569 for devid, pHCTL, devname, vHCTL in scsi_info:
2570 scsi.append(['dev', \
2571 ['state', state], \
2572 ['devid', devid], \
2573 ['p-dev', pHCTL], \
2574 ['p-devname', devname], \
2575 ['v-dev', vHCTL] \
2576 ])
2577 return scsi
2579 def xm_scsi_attach(args):
2580 arg_check(args, 'scsi-attach', 3, 4)
2581 dom = args[0]
2582 p_scsi = args[1]
2583 v_hctl = args[2]
2584 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2586 if serverType == SERVER_XEN_API:
2588 scsi_dev = sxp.children(scsi, 'dev')[0]
2589 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2590 target_ref = None
2591 for pscsi_ref in server.xenapi.PSCSI.get_all():
2592 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2593 target_ref = pscsi_ref
2594 break
2595 if target_ref is None:
2596 raise OptionError("Cannot find device '%s'" % p_scsi)
2598 dscsi_record = {
2599 "VM": get_single_vm(dom),
2600 "PSCSI": target_ref,
2601 "virtual_HCTL": v_hctl
2603 server.xenapi.DSCSI.create(dscsi_record)
2605 else:
2606 if len(args) == 4:
2607 scsi.append(['backend', args[3]])
2608 server.xend.domain.device_configure(dom, scsi)
2610 def detach(args, deviceClass):
2611 rm_cfg = True
2612 dom = args[0]
2613 dev = args[1]
2614 try:
2615 force = args[2]
2616 if (force != "--force") and (force != "-f"):
2617 print "Ignoring option %s"%(force)
2618 force = None
2619 except IndexError:
2620 force = None
2622 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2625 def xm_block_detach(args):
2626 if serverType == SERVER_XEN_API:
2627 arg_check(args, "block-detach", 2, 3)
2628 dom = args[0]
2629 dev = args[1]
2630 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2631 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2632 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2633 if len(vbd_refs) > 0:
2634 vbd_ref = vbd_refs[0]
2635 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2637 server.xenapi.VBD.destroy(vbd_ref)
2639 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2640 server.xenapi.VDI.destroy(vdi_ref)
2641 else:
2642 raise OptionError("Cannot find device '%s' in domain '%s'"
2643 % (dev,dom))
2644 else:
2645 arg_check(args, 'block-detach', 2, 3)
2646 dom = args[0]
2647 dev = args[1]
2648 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2649 if dc == "tap":
2650 detach(args, 'tap')
2651 else:
2652 detach(args, 'vbd')
2654 def xm_network_detach(args):
2655 if serverType == SERVER_XEN_API:
2656 arg_check(args, "network-detach", 2, 3)
2657 dom = args[0]
2658 devid = args[1]
2659 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2660 vif_refs = [vif_ref for vif_ref in vif_refs
2661 if server.xenapi.VIF.\
2662 get_runtime_properties(vif_ref)["handle"] == devid]
2663 if len(vif_refs) > 0:
2664 vif_ref = vif_refs[0]
2666 server.xenapi.VIF.destroy(vif_ref)
2667 else:
2668 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2669 else:
2670 arg_check(args, 'network-detach', 2, 3)
2671 detach(args, 'vif')
2673 def xm_pci_detach(args):
2674 arg_check(args, 'pci-detach', 2)
2675 (dom, pci) = parse_pci_configuration(args, 'Closing')
2677 if serverType == SERVER_XEN_API:
2679 pci_dev = sxp.children(pci, 'dev')[0]
2680 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2681 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2682 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2683 func = int(sxp.child_value(pci_dev, 'func'), 16)
2684 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2685 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2687 target_ref = None
2688 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2689 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2690 if name == server.xenapi.PPCI.get_name(ppci_ref):
2691 target_ref = ppci_ref
2692 server.xenapi.DPCI.destroy(dpci_ref)
2693 break
2694 if target_ref is None:
2695 raise OptionError("Device %s not assigned" % name)
2697 else:
2698 server.xend.domain.device_configure(dom, pci)
2700 def xm_scsi_detach(args):
2701 arg_check(args, 'scsi-detach', 2)
2702 dom = args[0]
2703 v_hctl = args[1]
2704 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
2706 if serverType == SERVER_XEN_API:
2708 target_ref = None
2709 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
2710 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
2711 target_ref = dscsi_ref
2712 break
2713 if target_ref is None:
2714 raise OptionError("Device %s not assigned" % v_hctl)
2716 server.xenapi.DSCSI.destroy(target_ref)
2718 else:
2719 server.xend.domain.device_configure(dom, scsi)
2721 def xm_vnet_list(args):
2722 xenapi_unsupported()
2723 try:
2724 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2725 except getopt.GetoptError, opterr:
2726 err(opterr)
2727 usage('vnet-list')
2729 use_long = 0
2730 for (k, v) in options:
2731 if k in ['-l', '--long']:
2732 use_long = 1
2734 if params:
2735 use_long = 1
2736 vnets = params
2737 else:
2738 vnets = server.xend_vnets()
2740 for vnet in vnets:
2741 try:
2742 if use_long:
2743 info = server.xend_vnet(vnet)
2744 PrettyPrint.prettyprint(info)
2745 else:
2746 print vnet
2747 except Exception, ex:
2748 print vnet, ex
2750 def xm_vnet_create(args):
2751 xenapi_unsupported()
2752 arg_check(args, "vnet-create", 1)
2753 conf = args[0]
2754 if not os.access(conf, os.R_OK):
2755 print "File not found: %s" % conf
2756 sys.exit(1)
2758 server.xend_vnet_create(conf)
2760 def xm_vnet_delete(args):
2761 xenapi_unsupported()
2762 arg_check(args, "vnet-delete", 1)
2763 vnet = args[0]
2764 server.xend_vnet_delete(vnet)
2766 def xm_network_new(args):
2767 xenapi_only()
2768 arg_check(args, "network-new", 1)
2769 network = args[0]
2771 record = {
2772 "name_label": network,
2773 "name_description": "",
2774 "other_config": {},
2775 "default_gateway": "",
2776 "default_netmask": ""
2779 server.xenapi.network.create(record)
2781 def xm_network_del(args):
2782 xenapi_only()
2783 arg_check(args, "network-del", 1)
2784 network = args[0]
2786 networks = dict([(record['name_label'], ref)
2787 for ref, record in
2788 server.xenapi.network.get_all_records().items()])
2790 if network not in networks.keys():
2791 raise ValueError("'%s' is not a valid network name" % network)
2793 server.xenapi.network.destroy(networks[network])
2795 def xm_network_show(args):
2796 xenapi_only()
2797 arg_check(args, "network-show", 0)
2799 networks = server.xenapi.network.get_all_records()
2800 pifs = server.xenapi.PIF.get_all_records()
2801 vifs = server.xenapi.VIF.get_all_records()
2803 print '%-20s %-40s %-10s' % \
2804 ('Name', 'VIFs', 'PIFs')
2806 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2808 for network_ref, network in networks.items():
2809 for i in range(max(len(network['PIFs']),
2810 len(network['VIFs']), 1)):
2811 if i < len(network['PIFs']):
2812 pif_uuid = network['PIFs'][i]
2813 else:
2814 pif_uuid = None
2816 if i < len(network['VIFs']):
2817 vif_uuid = network['VIFs'][i]
2818 else:
2819 vif_uuid = None
2821 pif = pifs.get(pif_uuid, None)
2822 vif = vifs.get(vif_uuid, None)
2824 if vif:
2825 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2826 vif = "%s.%s" % (dom_name, vif['device'])
2827 else:
2828 vif = ''
2830 if pif:
2831 if int(pif['VLAN']) > -1:
2832 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2833 else:
2834 pif = pif['device']
2835 else:
2836 pif = ''
2838 if i == 0:
2839 r = {'name_label':network['name_label'],
2840 'vif':vif, 'pif':pif}
2841 else:
2842 r = {'name_label':'', 'vif':vif, 'pif':pif}
2844 print format2 % r
2847 commands = {
2848 "shell": xm_shell,
2849 "event-monitor": xm_event_monitor,
2850 # console commands
2851 "console": xm_console,
2852 "vncviewer": xm_vncviewer,
2853 # xenstat commands
2854 "top": xm_top,
2855 # domain commands
2856 "delete": xm_delete,
2857 "destroy": xm_destroy,
2858 "domid": xm_domid,
2859 "domname": xm_domname,
2860 "dump-core": xm_dump_core,
2861 "reboot": xm_reboot,
2862 "rename": xm_rename,
2863 "reset": xm_reset,
2864 "restore": xm_restore,
2865 "resume": xm_resume,
2866 "save": xm_save,
2867 "shutdown": xm_shutdown,
2868 "start": xm_start,
2869 "sysrq": xm_sysrq,
2870 "trigger": xm_trigger,
2871 "uptime": xm_uptime,
2872 "suspend": xm_suspend,
2873 "list": xm_list,
2874 # memory commands
2875 "mem-max": xm_mem_max,
2876 "mem-set": xm_mem_set,
2877 # cpu commands
2878 "vcpu-pin": xm_vcpu_pin,
2879 "vcpu-list": xm_vcpu_list,
2880 "vcpu-set": xm_vcpu_set,
2881 # special
2882 "pause": xm_pause,
2883 "unpause": xm_unpause,
2884 # host commands
2885 "debug-keys": xm_debug_keys,
2886 "dmesg": xm_dmesg,
2887 "info": xm_info,
2888 "log": xm_log,
2889 "serve": xm_serve,
2890 # scheduler
2891 "sched-sedf": xm_sched_sedf,
2892 "sched-credit": xm_sched_credit,
2893 # block
2894 "block-attach": xm_block_attach,
2895 "block-detach": xm_block_detach,
2896 "block-list": xm_block_list,
2897 "block-configure": xm_block_configure,
2898 # network (AKA vifs)
2899 "network-attach": xm_network_attach,
2900 "network-detach": xm_network_detach,
2901 "network-list": xm_network_list,
2902 # network (as in XenAPI)
2903 "network-new": xm_network_new,
2904 "network-del": xm_network_del,
2905 "network-show": xm_network_show,
2906 # vnet
2907 "vnet-list": xm_vnet_list,
2908 "vnet-create": xm_vnet_create,
2909 "vnet-delete": xm_vnet_delete,
2910 # vtpm
2911 "vtpm-list": xm_vtpm_list,
2912 #pci
2913 "pci-attach": xm_pci_attach,
2914 "pci-detach": xm_pci_detach,
2915 "pci-list": xm_pci_list,
2916 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
2917 # vscsi
2918 "scsi-attach": xm_scsi_attach,
2919 "scsi-detach": xm_scsi_detach,
2920 "scsi-list": xm_scsi_list,
2923 ## The commands supported by a separate argument parser in xend.xm.
2924 IMPORTED_COMMANDS = [
2925 'create',
2926 'new',
2927 'migrate',
2928 'labels',
2929 'dumppolicy',
2930 'addlabel',
2931 'rmlabel',
2932 'getlabel',
2933 'dry-run',
2934 'resources',
2935 'getpolicy',
2936 'setpolicy',
2937 'resetpolicy',
2940 for c in IMPORTED_COMMANDS:
2941 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2943 aliases = {
2944 "balloon": "mem-set",
2945 "set-vcpus": "vcpu-set",
2946 "vif-list": "network-list",
2947 "vbd-create": "block-attach",
2948 "vbd-destroy": "block-detach",
2949 "vbd-list": "block-list",
2953 def xm_lookup_cmd(cmd):
2954 if commands.has_key(cmd):
2955 return commands[cmd]
2956 elif aliases.has_key(cmd):
2957 deprecated(cmd,aliases[cmd])
2958 return commands[aliases[cmd]]
2959 elif cmd == 'help':
2960 longHelp()
2961 sys.exit(0)
2962 else:
2963 # simulate getopt's prefix matching behaviour
2964 if len(cmd) > 1:
2965 same_prefix_cmds = [commands[c] for c in commands.keys() \
2966 if c[:len(cmd)] == cmd]
2967 # only execute if there is only 1 match
2968 if len(same_prefix_cmds) == 1:
2969 return same_prefix_cmds[0]
2970 return None
2972 def deprecated(old,new):
2973 print >>sys.stderr, (
2974 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2976 def main(argv=sys.argv):
2977 if len(argv) < 2:
2978 usage()
2980 # intercept --help(-h) and output our own help
2981 for help in ['--help', '-h']:
2982 if help in argv[1:]:
2983 if help == argv[1]:
2984 longHelp()
2985 sys.exit(0)
2986 else:
2987 usage(argv[1])
2989 cmd_name = argv[1]
2990 cmd = xm_lookup_cmd(cmd_name)
2991 if cmd:
2992 # strip off prog name and subcmd
2993 args = argv[2:]
2994 _, rc = _run_cmd(cmd, cmd_name, args)
2995 sys.exit(rc)
2996 else:
2997 err('Subcommand %s not found!' % cmd_name)
2998 usage()
3000 def _run_cmd(cmd, cmd_name, args):
3001 global server
3003 try:
3004 if server is None:
3005 if serverType == SERVER_XEN_API:
3006 server = XenAPI.Session(serverURI)
3007 username, password = parseAuthentication()
3008 server.login_with_password(username, password)
3009 def logout():
3010 try:
3011 server.xenapi.session.logout()
3012 except:
3013 pass
3014 atexit.register(logout)
3015 else:
3016 server = ServerProxy(serverURI)
3018 return True, cmd(args)
3019 except socket.error, ex:
3020 if os.geteuid() != 0:
3021 err("Most commands need root access. Please try again as root.")
3022 else:
3023 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
3024 except KeyboardInterrupt:
3025 print "Interrupted."
3026 return True, ''
3027 except IOError, ex:
3028 if os.geteuid() != 0:
3029 err("Most commands need root access. Please try again as root.")
3030 else:
3031 err("Unable to connect to xend: %s." % ex[1])
3032 except SystemExit, code:
3033 return code == 0, code
3034 except XenAPI.Failure, exn:
3035 for line in [''] + wrap(str(exn), 80) + ['']:
3036 print >>sys.stderr, line
3037 except xmlrpclib.Fault, ex:
3038 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
3039 err("Domain '%s' does not exist." % ex.faultString)
3040 return False, ex.faultCode
3041 else:
3042 err(ex.faultString)
3043 _usage(cmd_name)
3044 except xmlrpclib.ProtocolError, ex:
3045 if ex.errcode == -1:
3046 print >>sys.stderr, (
3047 "Xend has probably crashed! Invalid or missing HTTP "
3048 "status code.")
3049 else:
3050 print >>sys.stderr, (
3051 "Xend has probably crashed! ProtocolError(%d, %s)." %
3052 (ex.errcode, ex.errmsg))
3053 except (ValueError, OverflowError):
3054 err("Invalid argument.")
3055 _usage(cmd_name)
3056 except OptionError, e:
3057 err(str(e))
3058 _usage(cmd_name)
3059 print e.usage
3060 except XenAPIUnsupportedException, e:
3061 err(str(e))
3062 except XSMError, e:
3063 err(str(e))
3064 except Exception, e:
3065 if serverType != SERVER_XEN_API:
3066 import xen.util.xsm.xsm as security
3067 if isinstance(e, security.XSMError):
3068 err(str(e))
3069 return False, 1
3070 print "Unexpected error:", sys.exc_info()[0]
3071 print
3072 print "Please report to xen-devel@lists.xensource.com"
3073 raise
3075 return False, 1
3077 if __name__ == "__main__":
3078 main()