ia64/xen-unstable

view tools/python/xen/xm/main.py @ 19356:3c1a88dc6fbe

xend: Fix domain core-dumping about reset option

This patch moves a call processing of a domain reset processing
from xm to xend. Also, it adds a reset argument to do_dump() of
SrvDomain.py.

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