debuggers.hg

view tools/python/xen/xm/main.py @ 19656:780041c4a96d

xend: Fix xm pci commands for inactive managed domains.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 19 02:23:32 2009 +0100 (2009-05-19)
parents a1a0bd345acc
children 23f9857f642f
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 inspect
62 from xen.xend import XendOptions
63 xoptions = XendOptions.instance()
65 import signal
66 signal.signal(signal.SIGINT, signal.SIG_DFL)
68 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
69 # getopt.getopt if gnu_getopt is not available. This will mean that options
70 # may only be specified before positional arguments.
71 if not hasattr(getopt, 'gnu_getopt'):
72 getopt.gnu_getopt = getopt.getopt
74 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
75 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
77 # Supported types of server
78 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
79 SERVER_XEN_API = 'Xen-API'
81 # General help message
83 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
84 "Control, list, and manipulate Xen guest instances.\n"
86 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
87 'For more help on \'xm\' see the xm(1) man page.\n' \
88 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
89 ' man page.\n'
91 # Help strings are indexed by subcommand name in this way:
92 # 'subcommand': (argstring, description)
94 SUBCOMMAND_HELP = {
95 # common commands
97 'shell' : ('', 'Launch an interactive shell.'),
99 'console' : ('[-q|--quiet] <Domain>',
100 'Attach to <Domain>\'s console.'),
101 'vncviewer' : ('[--[vncviewer-]autopass] <Domain>',
102 'Attach to <Domain>\'s VNC server.'),
103 'create' : ('<ConfigFile> [options] [vars]',
104 'Create a domain based on <ConfigFile>.'),
105 'destroy' : ('<Domain>',
106 'Terminate a domain immediately.'),
107 'help' : ('', 'Display this message.'),
108 'list' : ('[options] [Domain, ...]',
109 'List information about all/some domains.'),
110 'mem-max' : ('<Domain> <Mem>',
111 'Set the maximum amount reservation for a domain.'),
112 'mem-set' : ('<Domain> <Mem>',
113 'Set the current memory usage for a domain.'),
114 'migrate' : ('<Domain> <Host>',
115 'Migrate a domain to another machine.'),
116 'pause' : ('<Domain>', 'Pause execution of a domain.'),
117 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
118 'reset' : ('<Domain>', 'Reset a domain.'),
119 'restore' : ('<CheckpointFile> [-p]',
120 'Restore a domain from a saved state.'),
121 'save' : ('[-c] <Domain> <CheckpointFile>',
122 'Save a domain state to restore later.'),
123 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
124 'top' : ('', 'Monitor a host and the domains in real time.'),
125 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
126 'uptime' : ('[-s] [Domain, ...]',
127 'Print uptime for all/some domains.'),
129 # Life cycle xm commands
130 'new' : ('<ConfigFile> [options] [vars]',
131 'Adds a domain to Xend domain management'),
132 'delete' : ('<DomainName>',
133 'Remove a domain from Xend domain management.'),
134 'start' : ('<DomainName>', 'Start a Xend managed domain'),
135 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
136 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
138 # less used commands
140 'dmesg' : ('[-c|--clear]',
141 'Read and/or clear Xend\'s message buffer.'),
142 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
143 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
144 'dump-core' : ('[-L|--live] [-C|--crash] [-R|--reset] <Domain> [Filename]',
145 'Dump core for a specific domain.'),
146 'info' : ('[-c|--config]', 'Get information about Xen host.'),
147 'log' : ('', 'Print Xend log'),
148 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
149 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
150 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
151 'Get/set credit scheduler parameters.'),
152 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
153 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
154 'trigger' : ('<Domain> <nmi|reset|init|s3resume|power> [<VCPU>]',
155 'Send a trigger to a domain.'),
156 'vcpu-list' : ('[Domain, ...]',
157 'List the VCPUs for all/some domains.'),
158 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
159 'Set which CPUs a VCPU can use.'),
160 'vcpu-set' : ('<Domain> <vCPUs>',
161 'Set the number of active VCPUs for allowed for the'
162 ' domain.'),
164 # device commands
166 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
167 'Create a new virtual block device.'),
168 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
169 'Change block device configuration'),
170 'block-detach' : ('<Domain> <DevId> [-f|--force]',
171 'Destroy a domain\'s virtual block device.'),
172 'block-list' : ('<Domain> [--long]',
173 'List virtual block devices for a domain.'),
174 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
175 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
176 '[vifname=<name>] [rate=<rate>] [model=<model>]'
177 '[accel=<accel>]',
178 'Create a new virtual network device.'),
179 'network-detach': ('<Domain> <DevId> [-f|--force]',
180 'Destroy a domain\'s virtual network device.'),
181 'network-list' : ('<Domain> [--long]',
182 'List virtual network interfaces for a domain.'),
183 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
184 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
185 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
186 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
187 'pci-attach' : ('[-o|--options=<opt>] <Domain> <domain:bus:slot.func> [virtual slot]',
188 'Insert a new pass-through pci device.'),
189 'pci-detach' : ('<Domain> <domain:bus:slot.func>',
190 'Remove a domain\'s pass-through pci device.'),
191 'pci-list' : ('<Domain>',
192 'List pass-through pci devices for a domain.'),
193 'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
194 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
195 'Attach a new SCSI device.'),
196 'scsi-detach' : ('<Domain> <VirtDevice>',
197 'Detach a specified SCSI device.'),
198 'scsi-list' : ('<Domain> [--long]',
199 'List all SCSI devices currently attached.'),
201 # security
203 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
204 ' [<policy>]',
205 'Add security label to domain.'),
206 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
207 'Remove a security label from domain.'),
208 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
209 'Show security label for domain or resource.'),
210 'dry-run' : ('<ConfigFile>',
211 'Test if a domain can access its resources.'),
212 'resources' : ('', 'Show info for each labeled resource.'),
213 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
214 'setpolicy' : ('<policytype> <policyfile> [options]',
215 'Set the policy of the system.'),
216 'resetpolicy' : ('',
217 'Set the policy of the system to the default policy.'),
218 'getpolicy' : ('[options]', 'Get the policy of the system.'),
219 'labels' : ('[policy] [type=dom|res|any]',
220 'List <type> labels for (active) policy.'),
221 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
222 }
224 SUBCOMMAND_OPTIONS = {
225 'sched-sedf': (
226 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
227 ('-s [MS]', '--slice[=MS]' ,
228 'Worst-case execution time(ms). (slice < period)'),
229 ('-l [MS]', '--latency[=MS]',
230 'Scaled period (ms) when domain performs heavy I/O'),
231 ('-e [FLAG]', '--extra[=FLAG]',
232 'Flag (0 or 1) controls if domain can run in extra time.'),
233 ('-w [FLOAT]', '--weight[=FLOAT]',
234 'CPU Period/slice (do not set with --period/--slice)'),
235 ),
236 'sched-credit': (
237 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
238 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
239 ('-c CAP', '--cap=CAP', 'Cap (int)'),
240 ),
241 'list': (
242 ('-l', '--long', 'Output all VM details in SXP'),
243 ('', '--label', 'Include security labels'),
244 ('', '--state=<state>', 'Select only VMs with the specified state'),
245 ),
246 'console': (
247 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
248 ),
249 'vncviewer': (
250 ('', '--autopass', 'Pass VNC password to viewer via stdin and -autopass'),
251 ('', '--vncviewer-autopass', '(consistency alias for --autopass)'),
252 ),
253 'dmesg': (
254 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
255 ),
256 'vnet-list': (
257 ('-l', '--long', 'List Vnets as SXP'),
258 ),
259 'network-list': (
260 ('-l', '--long', 'List resources as SXP'),
261 ),
262 'dump-core': (
263 ('-L', '--live', 'Dump core without pausing the domain'),
264 ('-C', '--crash', 'Crash domain after dumping core'),
265 ('-R', '--reset', 'Reset domain after dumping core'),
266 ),
267 'start': (
268 ('-p', '--paused', 'Do not unpause domain after starting it'),
269 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
270 ('', '--vncviewer', 'Connect to display via VNC after the domain is created'),
271 ('', '--vncviewer-autopass', 'Pass VNC password to viewer via stdin and -autopass'),
272 ),
273 'resume': (
274 ('-p', '--paused', 'Do not unpause domain after resuming it'),
275 ),
276 'save': (
277 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
278 ),
279 'restore': (
280 ('-p', '--paused', 'Do not unpause domain after restoring it'),
281 ),
282 'info': (
283 ('-c', '--config', 'List Xend configuration parameters'),
284 ),
285 }
287 common_commands = [
288 "console",
289 "vncviewer",
290 "create",
291 "new",
292 "delete",
293 "destroy",
294 "dump-core",
295 "help",
296 "list",
297 "mem-set",
298 "migrate",
299 "pause",
300 "reboot",
301 "reset",
302 "restore",
303 "resume",
304 "save",
305 "shell",
306 "shutdown",
307 "start",
308 "suspend",
309 "top",
310 "unpause",
311 "uptime",
312 "vcpu-set",
313 ]
315 domain_commands = [
316 "console",
317 "vncviewer",
318 "create",
319 "new",
320 "delete",
321 "destroy",
322 "domid",
323 "domname",
324 "dump-core",
325 "list",
326 "mem-max",
327 "mem-set",
328 "migrate",
329 "pause",
330 "reboot",
331 "rename",
332 "reset",
333 "restore",
334 "resume",
335 "save",
336 "shutdown",
337 "start",
338 "suspend",
339 "sysrq",
340 "trigger",
341 "top",
342 "unpause",
343 "uptime",
344 "vcpu-list",
345 "vcpu-pin",
346 "vcpu-set",
347 ]
349 host_commands = [
350 "debug-keys",
351 "dmesg",
352 "info",
353 "log",
354 "serve",
355 ]
357 scheduler_commands = [
358 "sched-credit",
359 "sched-sedf",
360 ]
362 device_commands = [
363 "block-attach",
364 "block-detach",
365 "block-list",
366 "block-configure",
367 "network-attach",
368 "network-detach",
369 "network-list",
370 "vtpm-list",
371 "pci-attach",
372 "pci-detach",
373 "pci-list",
374 "pci-list-assignable-devices",
375 "scsi-attach",
376 "scsi-detach",
377 "scsi-list",
378 ]
380 vnet_commands = [
381 "vnet-list",
382 "vnet-create",
383 "vnet-delete",
384 ]
386 acm_commands = [
387 "labels",
388 "addlabel",
389 "rmlabel",
390 "getlabel",
391 "dry-run",
392 "resources",
393 "dumppolicy",
394 "setpolicy",
395 "resetpolicy",
396 "getpolicy",
397 ]
399 all_commands = (domain_commands + host_commands + scheduler_commands +
400 device_commands + vnet_commands + acm_commands +
401 ['shell', 'event-monitor'])
404 ##
405 # Configuration File Parsing
406 ##
408 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
409 config = None
410 if os.path.isfile(xmConfigFile):
411 try:
412 config = xml.dom.minidom.parse(xmConfigFile)
413 except:
414 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
415 xmConfigFile)
417 def parseServer():
418 if config:
419 server = config.getElementsByTagName('server')
420 if server:
421 st = server[0].getAttribute('type')
422 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
423 print >>sys.stderr, ('Invalid server type %s; using %s.' %
424 (st, SERVER_LEGACY_XMLRPC))
425 st = SERVER_LEGACY_XMLRPC
426 return (st, server[0].getAttribute('uri'))
428 return SERVER_LEGACY_XMLRPC, XendClient.uri
430 def parseAuthentication():
431 server = config.getElementsByTagName('server')[0]
432 return (server.getAttribute('username'),
433 server.getAttribute('password'))
435 serverType, serverURI = parseServer()
436 server = None
439 ####################################################################
440 #
441 # Help/usage printing functions
442 #
443 ####################################################################
445 def cmdHelp(cmd):
446 """Print help for a specific subcommand."""
448 if not SUBCOMMAND_HELP.has_key(cmd):
449 for fc in SUBCOMMAND_HELP.keys():
450 if fc[:len(cmd)] == cmd:
451 cmd = fc
452 break
454 try:
455 args, desc = SUBCOMMAND_HELP[cmd]
456 except KeyError:
457 shortHelp()
458 return
460 print 'Usage: xm %s %s' % (cmd, args)
461 print
462 print desc
464 try:
465 # If options help message is defined, print this.
466 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
467 if shortopt and longopt:
468 optdesc = '%s, %s' % (shortopt, longopt)
469 elif shortopt:
470 optdesc = shortopt
471 elif longopt:
472 optdesc = longopt
474 wrapped_desc = wrap(desc, 43)
475 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
476 for line in wrapped_desc[1:]:
477 print ' ' * 33 + line
478 print
479 except KeyError:
480 # if the command is an external module, we grab usage help
481 # from the module itself.
482 if cmd in IMPORTED_COMMANDS:
483 try:
484 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
485 cmd_usage = getattr(cmd_module, "help", None)
486 if cmd_usage:
487 print cmd_usage()
488 except ImportError:
489 pass
491 def shortHelp():
492 """Print out generic help when xm is called without subcommand."""
494 print USAGE_HELP
495 print 'Common \'xm\' commands:\n'
497 for command in common_commands:
498 try:
499 args, desc = SUBCOMMAND_HELP[command]
500 except KeyError:
501 continue
502 wrapped_desc = wrap(desc, 50)
503 print ' %-20s %-50s' % (command, wrapped_desc[0])
504 for line in wrapped_desc[1:]:
505 print ' ' * 22 + line
507 print
508 print USAGE_FOOTER
509 print 'For a complete list of subcommands run \'xm help\'.'
511 def longHelp():
512 """Print out full help when xm is called with xm --help or xm help"""
514 print USAGE_HELP
515 print 'xm full list of subcommands:\n'
517 for command in all_commands:
518 try:
519 args, desc = SUBCOMMAND_HELP[command]
520 except KeyError:
521 continue
523 wrapped_desc = wrap(desc, 50)
524 print ' %-20s %-50s' % (command, wrapped_desc[0])
525 for line in wrapped_desc[1:]:
526 print ' ' * 22 + line
528 print
529 print USAGE_FOOTER
531 def _usage(cmd):
532 """ Print help usage information """
533 if cmd:
534 cmdHelp(cmd)
535 else:
536 shortHelp()
538 def usage(cmd = None):
539 """ Print help usage information and exits """
540 _usage(cmd)
541 sys.exit(1)
544 ####################################################################
545 #
546 # Utility functions
547 #
548 ####################################################################
550 def get_default_SR():
551 return [sr_ref
552 for sr_ref in server.xenapi.SR.get_all()
553 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
555 def get_default_Network():
556 return [network_ref
557 for network_ref in server.xenapi.network.get_all()][0]
559 class XenAPIUnsupportedException(Exception):
560 pass
562 def xenapi_unsupported():
563 if serverType == SERVER_XEN_API:
564 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
566 def xenapi_only():
567 if serverType != SERVER_XEN_API:
568 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
570 def map2sxp(m):
571 return [[k, m[k]] for k in m.keys()]
573 def arg_check(args, name, lo, hi = -1):
574 n = len([i for i in args if i != '--'])
576 if hi == -1:
577 if n != lo:
578 err("'xm %s' requires %d argument%s.\n" % (name, lo,
579 lo == 1 and '' or 's'))
580 usage(name)
581 else:
582 if n < lo or n > hi:
583 err("'xm %s' requires between %d and %d arguments.\n" %
584 (name, lo, hi))
585 usage(name)
588 def unit(c):
589 if not c.isalpha():
590 return 0
591 base = 1
592 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
593 elif c == 'M' or c == 'm': base = 1024 * 1024
594 elif c == 'K' or c == 'k': base = 1024
595 else:
596 print 'ignoring unknown unit'
597 return base
599 def int_unit(str, dest):
600 base = unit(str[-1])
601 if not base:
602 return int(str)
604 value = int(str[:-1])
605 dst_base = unit(dest)
606 if dst_base == 0:
607 dst_base = 1
608 if dst_base > base:
609 return value / (dst_base / base)
610 else:
611 return value * (base / dst_base)
613 def err(msg):
614 print >>sys.stderr, "Error:", msg
617 def get_single_vm(dom):
618 if serverType == SERVER_XEN_API:
619 uuids = server.xenapi.VM.get_by_name_label(dom)
620 if len(uuids) > 0:
621 return uuids[0]
623 refs = []
625 try:
626 domid = int(dom)
627 refs = [vm_ref
628 for vm_ref in server.xenapi.VM.get_all()
629 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
630 except:
631 pass
633 if len(refs) > 0:
634 return refs[0]
636 raise OptionError("Domain '%s' not found." % dom)
637 else:
638 dominfo = server.xend.domain(dom, False)
639 return dominfo['uuid']
641 ##
642 #
643 # Xen-API Shell
644 #
645 ##
647 class Shell(cmd.Cmd):
648 def __init__(self):
649 cmd.Cmd.__init__(self)
650 self.prompt = "xm> "
651 if serverType == SERVER_XEN_API:
652 try:
653 res = server.xenapi.host.list_methods()
654 for f in res:
655 setattr(Shell, 'do_' + f + ' ', self.default)
656 except:
657 pass
659 def preloop(self):
660 cmd.Cmd.preloop(self)
661 try:
662 import readline
663 readline.set_completer_delims(' ')
664 except ImportError:
665 pass
667 def default(self, line):
668 words = shlex.split(line)
669 if len(words) > 0 and words[0] == 'xm':
670 words = words[1:]
671 if len(words) > 0:
672 cmd = xm_lookup_cmd(words[0])
673 if cmd:
674 _run_cmd(cmd, words[0], words[1:])
675 elif serverType == SERVER_XEN_API:
676 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
677 tuple(x)),
678 words[0], words[1:])
679 if ok and res is not None and res != '':
680 pprint.pprint(res)
681 else:
682 print '*** Unknown command: %s' % words[0]
683 return False
685 def completedefault(self, text, line, begidx, endidx):
686 words = shlex.split(line[:begidx])
687 clas, func = words[0].split('.')
688 if len(words) > 1 or \
689 func.startswith('get_by_') or \
690 func == 'get_all':
691 return []
692 uuids = server.xenapi_request('%s.get_all' % clas, ())
693 return [u + " " for u in uuids if u.startswith(text)]
695 def emptyline(self):
696 pass
698 def do_EOF(self, line):
699 print
700 sys.exit(0)
702 def do_help(self, line):
703 _usage(line)
706 def xm_shell(args):
707 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
710 def xm_event_monitor(args):
711 if serverType == SERVER_XEN_API:
712 while True:
713 server.xenapi.event.register(args)
714 events = server.xenapi.event.next()
715 for e in events:
716 print e
717 else:
718 err("Event monitoring not supported unless using Xen-API.")
721 #########################################################################
722 #
723 # Main xm functions
724 #
725 #########################################################################
727 def xm_save(args):
729 arg_check(args, "save", 2, 3)
731 try:
732 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
733 except getopt.GetoptError, opterr:
734 err(opterr)
735 usage('save')
737 checkpoint = False
738 for (k, v) in options:
739 if k in ['-c', '--checkpoint']:
740 checkpoint = True
742 if len(params) != 2:
743 err("Wrong number of parameters")
744 usage('save')
746 dom = params[0]
747 savefile = os.path.abspath(params[1])
749 if not os.access(os.path.dirname(savefile), os.W_OK):
750 err("xm save: Unable to create file %s" % savefile)
751 sys.exit(1)
753 if serverType == SERVER_XEN_API:
754 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
755 else:
756 server.xend.domain.save(dom, savefile, checkpoint)
758 def xm_restore(args):
759 arg_check(args, "restore", 1, 2)
761 try:
762 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
763 except getopt.GetoptError, opterr:
764 err(opterr)
765 usage('restore')
767 paused = False
768 for (k, v) in options:
769 if k in ['-p', '--paused']:
770 paused = True
772 if len(params) != 1:
773 err("Wrong number of parameters")
774 usage('restore')
776 savefile = os.path.abspath(params[0])
778 if not os.access(savefile, os.R_OK):
779 err("xm restore: Unable to read file %s" % savefile)
780 sys.exit(1)
782 if serverType == SERVER_XEN_API:
783 server.xenapi.VM.restore(savefile, paused)
784 else:
785 server.xend.domain.restore(savefile, paused)
788 def datetime_to_secs(v):
789 unwanted = ":-."
790 for c in unwanted:
791 v = str(v).replace(c, "")
792 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
794 def getDomains(domain_names, state, full = 0):
795 if serverType == SERVER_XEN_API:
796 doms_sxp = []
797 doms_dict = []
799 dom_recs = server.xenapi.VM.get_all_records()
800 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
802 for dom_ref, dom_rec in dom_recs.items():
803 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
805 states = ('running', 'blocked', 'paused', 'shutdown',
806 'crashed', 'dying')
807 def state_on_off(state):
808 if state in dom_metrics_rec['state']:
809 return state[0]
810 else:
811 return "-"
812 state_str = "".join([state_on_off(state)
813 for state in states])
815 dom_rec.update({'name': dom_rec['name_label'],
816 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
817 'vcpus': dom_metrics_rec['VCPUs_number'],
818 'state': state_str,
819 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
820 'start_time': datetime_to_secs(
821 dom_metrics_rec['start_time'])})
823 doms_sxp.append(['domain'] + map2sxp(dom_rec))
824 doms_dict.append(dom_rec)
826 if domain_names:
827 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
828 if dom["name"] in domain_names]
830 if len(doms) > 0:
831 return doms
832 else:
833 print "Error: no domain%s named %s" % \
834 (len(domain_names) > 1 and 's' or '',
835 ', '.join(domain_names))
836 sys.exit(-1)
837 else:
838 return doms_sxp
839 else:
840 if domain_names:
841 return [server.xend.domain(dom, full) for dom in domain_names]
842 else:
843 return server.xend.domains_with_state(True, state, full)
846 def xm_list(args):
847 use_long = 0
848 show_vcpus = 0
849 show_labels = 0
850 state = 'all'
851 try:
852 (options, params) = getopt.gnu_getopt(args, 'lv',
853 ['long','vcpus','label',
854 'state='])
855 except getopt.GetoptError, opterr:
856 err(opterr)
857 usage('list')
859 for (k, v) in options:
860 if k in ['-l', '--long']:
861 use_long = 1
862 if k in ['-v', '--vcpus']:
863 show_vcpus = 1
864 if k in ['--label']:
865 show_labels = 1
866 if k in ['--state']:
867 state = v
869 if state != 'all' and len(params) > 0:
870 raise OptionError(
871 "You may specify either a state or a particular VM, but not both")
873 if show_vcpus:
874 print >>sys.stderr, (
875 "xm list -v is deprecated. Please use xm vcpu-list.")
876 xm_vcpu_list(params)
877 return
879 doms = getDomains(params, state, use_long)
881 if use_long:
882 map(PrettyPrint.prettyprint, doms)
883 elif show_labels:
884 xm_label_list(doms)
885 else:
886 xm_brief_list(doms)
889 def parse_doms_info(info):
890 def get_info(n, t, d):
891 return t(sxp.child_value(info, n, d))
893 def get_status(n, t, d):
894 return DOM_STATES[t(sxp.child_value(info, n, d))]
896 start_time = get_info('start_time', float, -1)
897 if start_time == -1:
898 up_time = float(-1)
899 else:
900 up_time = time.time() - start_time
902 parsed_info = {
903 'domid' : get_info('domid', str, ''),
904 'name' : get_info('name', str, '??'),
905 'state' : get_info('state', str, ''),
907 # VCPUs is the number online when the VM is up, or the number
908 # configured otherwise.
909 'vcpus' : get_info('online_vcpus', int,
910 get_info('vcpus', int, 0)),
911 'up_time' : up_time
912 }
914 security_label = get_info('security_label', str, '')
915 parsed_info['seclabel'] = security.parse_security_label(security_label)
917 if serverType == SERVER_XEN_API:
918 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
919 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
920 if sum(cpu_times.values()) > 0:
921 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
922 else:
923 parsed_info['cpu_time'] = 0
924 else:
925 parsed_info['mem'] = get_info('memory', int,0)
926 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
928 return parsed_info
930 def check_sched_type(sched):
931 if serverType == SERVER_XEN_API:
932 current = server.xenapi.host.get_sched_policy(
933 server.xenapi.session.get_this_host(server.getSession()))
934 else:
935 current = 'unknown'
936 for x in server.xend.node.info()[1:]:
937 if len(x) > 1 and x[0] == 'xen_scheduler':
938 current = x[1]
939 break
940 if sched != current:
941 err("Xen is running with the %s scheduler" % current)
942 sys.exit(1)
944 def parse_sedf_info(info):
945 def get_info(n, t, d):
946 return t(sxp.child_value(info, n, d))
948 return {
949 'domid' : get_info('domid', int, -1),
950 'period' : get_info('period', int, -1),
951 'slice' : get_info('slice', int, -1),
952 'latency' : get_info('latency', int, -1),
953 'extratime': get_info('extratime', int, -1),
954 'weight' : get_info('weight', int, -1),
955 }
957 def domid_match(domid, info):
958 return domid is None or domid == info['name'] or \
959 domid == str(info['domid'])
961 def xm_brief_list(doms):
962 print '%-40s %5s %5s %5s %10s %9s' % \
963 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
965 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
966 "%(cpu_time)8.1f"
968 for dom in doms:
969 d = parse_doms_info(dom)
970 print format % d
972 def xm_label_list(doms):
973 print '%-40s %5s %5s %5s %10s %9s %-10s' % \
974 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
976 output = []
977 format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
978 '%(cpu_time)8.1f %(seclabel)10s'
980 for dom in doms:
981 d = parse_doms_info(dom)
982 if d['seclabel'] == "" and serverType != SERVER_XEN_API:
983 seclab = server.xend.security.get_domain_label(d['name'])
984 if len(seclab) > 0 and seclab[0] == '\'':
985 seclab = seclab[1:]
986 d['seclabel'] = seclab
987 output.append((format % d, d['seclabel']))
989 #sort by labels
990 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
991 for line, label in output:
992 print line
995 def xm_vcpu_list(args):
996 if serverType == SERVER_XEN_API:
997 if args:
998 vm_refs = map(get_single_vm, args)
999 else:
1000 vm_refs = server.xenapi.VM.get_all()
1002 vm_records = dict(map(lambda vm_ref:
1003 (vm_ref, server.xenapi.VM.get_record(
1004 vm_ref)),
1005 vm_refs))
1007 vm_metrics = dict(map(lambda (ref, record):
1008 (ref,
1009 server.xenapi.VM_metrics.get_record(
1010 record['metrics'])),
1011 vm_records.items()))
1013 dominfo = []
1015 # vcpu_list doesn't list 'managed' domains
1016 # when they are not running, so filter them out
1018 vm_refs = [vm_ref
1019 for vm_ref in vm_refs
1020 if vm_records[vm_ref]["power_state"] != "Halted"]
1022 for vm_ref in vm_refs:
1023 info = ['domain',
1024 ['domid', vm_records[vm_ref]['domid']],
1025 ['name', vm_records[vm_ref]['name_label']],
1026 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
1028 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
1029 def chk_flag(flag):
1030 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1031 and 1 or 0
1033 vcpu_info = ['vcpu',
1034 ['number',
1035 i],
1036 ['online',
1037 chk_flag("online")],
1038 ['blocked',
1039 chk_flag("blocked")],
1040 ['running',
1041 chk_flag("running")],
1042 ['cpu_time',
1043 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1044 ['cpu',
1045 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1046 ['cpumap',
1047 vm_metrics[vm_ref]['VCPUs_params']\
1048 ['cpumap%i' % i].split(",")]]
1050 info.append(vcpu_info)
1052 dominfo.append(info)
1053 else:
1054 if args:
1055 dominfo = map(server.xend.domain.getVCPUInfo, args)
1056 else:
1057 doms = server.xend.domains_with_state(False, 'all', False)
1058 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1060 print '%-32s %5s %5s %5s %5s %9s %s' % \
1061 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1063 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1064 ' %(cpu_time)8.1f %(cpumap)s'
1066 for dom in dominfo:
1067 def get_info(n):
1068 return sxp.child_value(dom, n)
1071 # convert a list of integers into a list of pairs indicating
1072 # continuous sequences in the list:
1074 # [0,1,2,3] -> [(0,3)]
1075 # [1,2,4,5] -> [(1,2),(4,5)]
1076 # [0] -> [(0,0)]
1077 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1079 def list_to_rangepairs(cmap):
1080 cmap.sort()
1081 pairs = []
1082 x = y = 0
1083 for i in range(0,len(cmap)):
1084 try:
1085 if ((cmap[y+1] - cmap[i]) > 1):
1086 pairs.append((cmap[x],cmap[y]))
1087 x = y = i+1
1088 else:
1089 y = y + 1
1090 # if we go off the end, then just add x to y
1091 except IndexError:
1092 pairs.append((cmap[x],cmap[y]))
1094 return pairs
1097 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1099 def format_pairs(pairs):
1100 if not pairs:
1101 return "no cpus"
1102 out = ""
1103 for f,s in pairs:
1104 if (f==s):
1105 out += '%d'%f
1106 else:
1107 out += '%d-%d'%(f,s)
1108 out += ','
1109 # trim trailing ','
1110 return out[:-1]
1112 def format_cpumap(cpumap):
1113 cpumap = map(lambda x: int(x), cpumap)
1114 cpumap.sort()
1116 if serverType == SERVER_XEN_API:
1117 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1118 server.xenapi.session.get_this_host(server.getSession())))
1119 else:
1120 for x in server.xend.node.info()[1:]:
1121 if len(x) > 1 and x[0] == 'nr_cpus':
1122 nr_cpus = int(x[1])
1124 # normalize cpumap by modulus nr_cpus, and drop duplicates
1125 cpumap = dict.fromkeys(
1126 filter(lambda x: x < nr_cpus, cpumap)).keys()
1127 if len(cpumap) == nr_cpus:
1128 return "any cpu"
1130 return format_pairs(list_to_rangepairs(cpumap))
1132 name = get_info('name')
1133 domid = get_info('domid')
1134 if domid is not None:
1135 domid = str(domid)
1136 else:
1137 domid = ''
1139 for vcpu in sxp.children(dom, 'vcpu'):
1140 def vinfo(n, t):
1141 return t(sxp.child_value(vcpu, n))
1143 number = vinfo('number', int)
1144 cpu = vinfo('cpu', int)
1145 cpumap = format_cpumap(vinfo('cpumap', list))
1146 online = vinfo('online', int)
1147 cpu_time = vinfo('cpu_time', float)
1148 running = vinfo('running', int)
1149 blocked = vinfo('blocked', int)
1151 if cpu < 0:
1152 c = ''
1153 s = ''
1154 elif online:
1155 c = str(cpu)
1156 if running:
1157 s = 'r'
1158 else:
1159 s = '-'
1160 if blocked:
1161 s += 'b'
1162 else:
1163 s += '-'
1164 s += '-'
1165 else:
1166 c = '-'
1167 s = '--p'
1169 print format % locals()
1171 def start_do_console(domain_name):
1172 cpid = os.fork()
1173 if cpid != 0:
1174 for i in range(10):
1175 # Catch failure of the create process
1176 time.sleep(1)
1177 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1178 if os.WIFEXITED(rv):
1179 if os.WEXITSTATUS(rv) != 0:
1180 sys.exit(os.WEXITSTATUS(rv))
1181 try:
1182 # Acquire the console of the created dom
1183 if serverType == SERVER_XEN_API:
1184 domid = server.xenapi.VM.get_domid(
1185 get_single_vm(domain_name))
1186 else:
1187 dom = server.xend.domain(domain_name)
1188 domid = int(sxp.child_value(dom, 'domid', '-1'))
1189 console.execConsole(domid)
1190 except:
1191 pass
1192 print("Could not start console\n");
1193 sys.exit(0)
1195 def xm_start(args):
1197 paused = False
1198 console_autoconnect = False
1199 vncviewer = False
1200 vncviewer_autopass = False
1202 try:
1203 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused','vncviewer','vncviewer-autopass'])
1204 for (k, v) in options:
1205 if k in ('-p', '--paused'):
1206 paused = True
1207 if k in ('-c', '--console_autoconnect'):
1208 console_autoconnect = True
1209 if k in ('--vncviewer'):
1210 vncviewer = True
1211 if k in ('--vncviewer-autopass'):
1212 vncviewer_autopass = True
1214 if len(params) != 1:
1215 raise OptionError("Expects 1 argument")
1216 except getopt.GetoptError, opterr:
1217 err(opterr)
1218 usage('start')
1220 dom = params[0]
1222 if console_autoconnect:
1223 start_do_console(dom)
1225 try:
1226 if serverType == SERVER_XEN_API:
1227 server.xenapi.VM.start(get_single_vm(dom), paused)
1228 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1229 else:
1230 server.xend.domain.start(dom, paused)
1231 info = server.xend.domain(dom)
1232 domid = int(sxp.child_value(info, 'domid', '-1'))
1233 except:
1234 raise
1236 if domid == -1:
1237 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1239 if vncviewer:
1240 console.runVncViewer(domid, vncviewer_autopass, True)
1243 def xm_delete(args):
1244 arg_check(args, "delete", 1)
1245 dom = args[0]
1246 if serverType == SERVER_XEN_API:
1247 server.xenapi.VM.destroy(get_single_vm(dom))
1248 else:
1249 server.xend.domain.delete(dom)
1251 def xm_suspend(args):
1252 arg_check(args, "suspend", 1)
1253 dom = args[0]
1254 if serverType == SERVER_XEN_API:
1255 server.xenapi.VM.suspend(get_single_vm(dom))
1256 else:
1257 server.xend.domain.suspend(dom)
1259 def xm_resume(args):
1260 arg_check(args, "resume", 1, 2)
1262 try:
1263 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1264 except getopt.GetoptError, opterr:
1265 err(opterr)
1266 usage('resume')
1268 paused = False
1269 for (k, v) in options:
1270 if k in ['-p', '--paused']:
1271 paused = True
1273 if len(params) != 1:
1274 err("Wrong number of parameters")
1275 usage('resume')
1277 dom = params[0]
1278 if serverType == SERVER_XEN_API:
1279 server.xenapi.VM.resume(get_single_vm(dom), paused)
1280 else:
1281 server.xend.domain.resume(dom, paused)
1283 def xm_reboot(args):
1284 arg_check(args, "reboot", 1, 3)
1285 from xen.xm import shutdown
1286 shutdown.main(["shutdown", "-R"] + args)
1288 def xm_shutdown(args):
1289 arg_check(args, "shutdown", 1, 4)
1290 from xen.xm import shutdown
1291 shutdown.main(["shutdown"] + args)
1293 def xm_reset(args):
1294 arg_check(args, "reset", 1)
1295 dom = args[0]
1297 if serverType == SERVER_XEN_API:
1298 server.xenapi.VM.hard_reboot(get_single_vm(dom))
1299 else:
1300 server.xend.domain.reset(dom)
1302 def xm_pause(args):
1303 arg_check(args, "pause", 1)
1304 dom = args[0]
1306 if serverType == SERVER_XEN_API:
1307 server.xenapi.VM.pause(get_single_vm(dom))
1308 else:
1309 server.xend.domain.pause(dom)
1311 def xm_unpause(args):
1312 arg_check(args, "unpause", 1)
1313 dom = args[0]
1315 if serverType == SERVER_XEN_API:
1316 server.xenapi.VM.unpause(get_single_vm(dom))
1317 else:
1318 server.xend.domain.unpause(dom)
1320 def xm_dump_core(args):
1321 live = False
1322 crash = False
1323 reset = False
1324 try:
1325 (options, params) = getopt.gnu_getopt(args, 'LCR', ['live', 'crash', 'reset'])
1326 for (k, v) in options:
1327 if k in ('-L', '--live'):
1328 live = True
1329 elif k in ('-C', '--crash'):
1330 crash = True
1331 elif k in ('-R', '--reset'):
1332 reset = True
1334 if crash and reset:
1335 raise OptionError("You may not specify more than one '-CR' option")
1336 if len(params) not in (1, 2):
1337 raise OptionError("Expects 1 or 2 argument(s)")
1338 except getopt.GetoptError, e:
1339 raise OptionError(str(e))
1341 dom = params[0]
1342 if len(params) == 2:
1343 filename = os.path.abspath(params[1])
1344 else:
1345 filename = None
1347 print "Dumping core of domain: %s ..." % str(dom)
1348 server.xend.domain.dump(dom, filename, live, crash, reset)
1350 def xm_rename(args):
1351 arg_check(args, "rename", 2)
1353 if serverType == SERVER_XEN_API:
1354 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1355 else:
1356 server.xend.domain.setName(args[0], args[1])
1358 def xm_importcommand(command, args):
1359 cmd = __import__(command, globals(), locals(), 'xen.xm')
1360 cmd.main([command] + args)
1363 #############################################################
1365 def xm_vcpu_pin(args):
1366 arg_check(args, "vcpu-pin", 3)
1368 def cpu_make_map(cpulist):
1369 cpus = []
1370 for c in cpulist.split(','):
1371 if c.find('-') != -1:
1372 (x,y) = c.split('-')
1373 for i in range(int(x),int(y)+1):
1374 cpus.append(int(i))
1375 else:
1376 # remove this element from the list
1377 if c[0] == '^':
1378 cpus = [x for x in cpus if x != int(c[1:])]
1379 else:
1380 cpus.append(int(c))
1381 cpus.sort()
1382 return ",".join(map(str, cpus))
1384 dom = args[0]
1385 vcpu = args[1]
1386 if args[2] == 'all':
1387 cpumap = cpu_make_map('0-63')
1388 else:
1389 cpumap = cpu_make_map(args[2])
1391 if serverType == SERVER_XEN_API:
1392 server.xenapi.VM.add_to_VCPUs_params_live(
1393 get_single_vm(dom), "cpumap%i" % int(vcpu), cpumap)
1394 else:
1395 server.xend.domain.pincpu(dom, vcpu, cpumap)
1397 def xm_mem_max(args):
1398 arg_check(args, "mem-max", 2)
1400 dom = args[0]
1402 if serverType == SERVER_XEN_API:
1403 mem = int_unit(args[1], 'k') * 1024
1404 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1405 else:
1406 mem = int_unit(args[1], 'm')
1407 server.xend.domain.maxmem_set(dom, mem)
1409 def xm_mem_set(args):
1410 arg_check(args, "mem-set", 2)
1412 dom = args[0]
1414 if serverType == SERVER_XEN_API:
1415 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1416 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1417 mem_target)
1418 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1419 mem_target)
1420 else:
1421 mem_target = int_unit(args[1], 'm')
1422 server.xend.domain.setMemoryTarget(dom, mem_target)
1424 def xm_vcpu_set(args):
1425 arg_check(args, "vcpu-set", 2)
1427 dom = args[0]
1428 vcpus = int(args[1])
1430 if serverType == SERVER_XEN_API:
1431 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1432 else:
1433 server.xend.domain.setVCpuCount(dom, vcpus)
1435 def xm_destroy(args):
1436 arg_check(args, "destroy", 1)
1438 dom = args[0]
1440 if serverType == SERVER_XEN_API:
1441 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1442 else:
1443 server.xend.domain.destroy(dom)
1445 def xm_domid(args):
1446 arg_check(args, "domid", 1)
1448 name = args[0]
1450 if serverType == SERVER_XEN_API:
1451 print server.xenapi.VM.get_domid(get_single_vm(name))
1452 else:
1453 dom = server.xend.domain(name)
1454 print sxp.child_value(dom, 'domid')
1456 def xm_domname(args):
1457 arg_check(args, "domname", 1)
1459 name = args[0]
1461 if serverType == SERVER_XEN_API:
1462 print server.xenapi.VM.get_name_label(get_single_vm(name))
1463 else:
1464 dom = server.xend.domain(name)
1465 print sxp.child_value(dom, 'name')
1467 def xm_sched_sedf(args):
1468 xenapi_unsupported()
1470 def ns_to_ms(val):
1471 return float(val) * 0.000001
1473 def ms_to_ns(val):
1474 return (float(val) / 0.000001)
1476 def print_sedf(info):
1477 info['period'] = ns_to_ms(info['period'])
1478 info['slice'] = ns_to_ms(info['slice'])
1479 info['latency'] = ns_to_ms(info['latency'])
1480 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1481 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1483 check_sched_type('sedf')
1485 # we want to just display current info if no parameters are passed
1486 if len(args) == 0:
1487 domid = None
1488 else:
1489 # we expect at least a domain id (name or number)
1490 # and at most a domid up to 5 options with values
1491 arg_check(args, "sched-sedf", 1, 11)
1492 domid = args[0]
1493 # drop domid from args since get_opt doesn't recognize it
1494 args = args[1:]
1496 opts = {}
1497 try:
1498 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1499 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1500 except getopt.GetoptError, opterr:
1501 err(opterr)
1502 usage('sched-sedf')
1504 # convert to nanoseconds if needed
1505 for (k, v) in options:
1506 if k in ['-p', '--period']:
1507 opts['period'] = ms_to_ns(v)
1508 elif k in ['-s', '--slice']:
1509 opts['slice'] = ms_to_ns(v)
1510 elif k in ['-l', '--latency']:
1511 opts['latency'] = ms_to_ns(v)
1512 elif k in ['-e', '--extratime']:
1513 opts['extratime'] = v
1514 elif k in ['-w', '--weight']:
1515 opts['weight'] = v
1517 doms = filter(lambda x : domid_match(domid, x),
1518 [parse_doms_info(dom)
1519 for dom in getDomains(None, 'running')])
1520 if domid is not None and doms == []:
1521 err("Domain '%s' does not exist." % domid)
1522 usage('sched-sedf')
1524 # print header if we aren't setting any parameters
1525 if len(opts.keys()) == 0:
1526 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1527 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1528 'Extra','Weight')
1530 for d in doms:
1531 # fetch current values so as not to clobber them
1532 try:
1533 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1534 except xmlrpclib.Fault:
1535 # domain does not support sched-sedf?
1536 sedf_raw = {}
1538 sedf_info = parse_sedf_info(sedf_raw)
1539 sedf_info['name'] = d['name']
1540 # update values in case of call to set
1541 if len(opts.keys()) > 0:
1542 for k in opts.keys():
1543 sedf_info[k]=opts[k]
1545 # send the update, converting user input
1546 v = map(int, [sedf_info['period'], sedf_info['slice'],
1547 sedf_info['latency'],sedf_info['extratime'],
1548 sedf_info['weight']])
1549 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1550 if int(rv) != 0:
1551 err("Failed to set sedf parameters (rv=%d)."%(rv))
1553 # not setting values, display info
1554 else:
1555 print_sedf(sedf_info)
1557 def xm_sched_credit(args):
1558 """Get/Set options for Credit Scheduler."""
1560 check_sched_type('credit')
1562 try:
1563 opts, params = getopt.getopt(args, "d:w:c:",
1564 ["domain=", "weight=", "cap="])
1565 except getopt.GetoptError, opterr:
1566 err(opterr)
1567 usage('sched-credit')
1569 domid = None
1570 weight = None
1571 cap = None
1573 for o, a in opts:
1574 if o in ["-d", "--domain"]:
1575 domid = a
1576 elif o in ["-w", "--weight"]:
1577 weight = int(a)
1578 elif o in ["-c", "--cap"]:
1579 cap = int(a);
1581 doms = filter(lambda x : domid_match(domid, x),
1582 [parse_doms_info(dom)
1583 for dom in getDomains(None, 'all')])
1585 if weight is None and cap is None:
1586 if domid is not None and doms == []:
1587 err("Domain '%s' does not exist." % domid)
1588 usage('sched-credit')
1589 # print header if we aren't setting any parameters
1590 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1592 for d in doms:
1593 try:
1594 if serverType == SERVER_XEN_API:
1595 info = server.xenapi.VM_metrics.get_VCPUs_params(
1596 server.xenapi.VM.get_metrics(
1597 get_single_vm(d['name'])))
1598 else:
1599 info = server.xend.domain.sched_credit_get(d['name'])
1600 except xmlrpclib.Fault:
1601 pass
1603 if 'weight' not in info or 'cap' not in info:
1604 # domain does not support sched-credit?
1605 info = {'weight': -1, 'cap': -1}
1607 info['weight'] = int(info['weight'])
1608 info['cap'] = int(info['cap'])
1610 info['name'] = d['name']
1611 info['domid'] = str(d['domid'])
1612 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1613 else:
1614 if domid is None:
1615 # place holder for system-wide scheduler parameters
1616 err("No domain given.")
1617 usage('sched-credit')
1619 if serverType == SERVER_XEN_API:
1620 if doms[0]['domid']:
1621 server.xenapi.VM.add_to_VCPUs_params_live(
1622 get_single_vm(domid),
1623 "weight",
1624 weight)
1625 server.xenapi.VM.add_to_VCPUs_params_live(
1626 get_single_vm(domid),
1627 "cap",
1628 cap)
1629 else:
1630 server.xenapi.VM.add_to_VCPUs_params(
1631 get_single_vm(domid),
1632 "weight",
1633 weight)
1634 server.xenapi.VM.add_to_VCPUs_params(
1635 get_single_vm(domid),
1636 "cap",
1637 cap)
1638 else:
1639 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1640 if result != 0:
1641 err(str(result))
1643 def xm_info(args):
1644 arg_check(args, "info", 0, 1)
1646 try:
1647 (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
1648 except getopt.GetoptError, opterr:
1649 err(opterr)
1650 usage('info')
1652 show_xend_config = 0
1653 for (k, v) in options:
1654 if k in ['-c', '--config']:
1655 show_xend_config = 1
1657 if show_xend_config:
1658 for name, obj in inspect.getmembers(xoptions):
1659 if not inspect.ismethod(obj):
1660 if name == "config":
1661 for x in obj[1:]:
1662 if len(x) < 2:
1663 print "%-38s: (none)" % x[0]
1664 else:
1665 print "%-38s:" % x[0], x[1]
1666 else:
1667 print "%-38s:" % name, obj
1668 return
1670 if serverType == SERVER_XEN_API:
1672 # Need to fake out old style xm info as people rely on parsing it
1674 host_record = server.xenapi.host.get_record(
1675 server.xenapi.session.get_this_host(server.getSession()))
1677 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1679 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1681 def getVal(keys, default=""):
1682 data = host_record
1683 for key in keys:
1684 if key in data:
1685 data = data[key]
1686 else:
1687 return default
1688 return data
1690 def getCpuMhz():
1691 cpu_speeds = [int(host_cpu_record["speed"])
1692 for host_cpu_record in host_cpu_records
1693 if "speed" in host_cpu_record]
1694 if len(cpu_speeds) > 0:
1695 return sum(cpu_speeds) / len(cpu_speeds)
1696 else:
1697 return 0
1699 getCpuMhz()
1701 def getCpuFeatures():
1702 if len(host_cpu_records) > 0:
1703 return host_cpu_records[0].get("features", "")
1704 else:
1705 return ""
1707 info = {
1708 "host": getVal(["name_label"]),
1709 "release": getVal(["software_version", "release"]),
1710 "version": getVal(["software_version", "version"]),
1711 "machine": getVal(["software_version", "machine"]),
1712 "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
1713 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1714 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1715 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1716 "cpu_mhz": getCpuMhz(),
1717 "hw_caps": getCpuFeatures(),
1718 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1719 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1720 "xen_major": getVal(["software_version", "xen_major"]),
1721 "xen_minor": getVal(["software_version", "xen_minor"]),
1722 "xen_extra": getVal(["software_version", "xen_extra"]),
1723 "xen_caps": " ".join(getVal(["capabilities"], [])),
1724 "xen_scheduler": getVal(["sched_policy"]),
1725 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1726 "platform_params": getVal(["other_config", "platform_params"]),
1727 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1728 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1729 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1730 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1731 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1732 "xend_config_format":getVal(["software_version", "xend_config_format"])
1735 sorted = info.items()
1736 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1738 for (k, v) in sorted:
1739 print "%-23s:" % k, v
1740 else:
1741 info = server.xend.node.info()
1742 for x in info[1:]:
1743 if len(x) < 2:
1744 print "%-23s: (none)" % x[0]
1745 else:
1746 print "%-23s:" % x[0], x[1]
1748 def xm_console(args):
1749 arg_check(args, "console", 1, 2)
1751 quiet = False;
1753 try:
1754 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1755 except getopt.GetoptError, opterr:
1756 err(opterr)
1757 usage('console')
1759 for (k, v) in options:
1760 if k in ['-q', '--quiet']:
1761 quiet = True
1762 else:
1763 assert False
1765 if len(params) != 1:
1766 err('No domain given')
1767 usage('console')
1769 dom = params[0]
1771 try:
1772 if serverType == SERVER_XEN_API:
1773 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1774 else:
1775 info = server.xend.domain(dom)
1776 domid = int(sxp.child_value(info, 'domid', '-1'))
1777 except:
1778 if quiet:
1779 sys.exit(1)
1780 else:
1781 raise
1783 if domid == -1:
1784 if quiet:
1785 sys.exit(1)
1786 else:
1787 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1789 console.execConsole(domid)
1792 def domain_name_to_domid(domain_name):
1793 if serverType == SERVER_XEN_API:
1794 domid = server.xenapi.VM.get_domid(
1795 get_single_vm(domain_name))
1796 else:
1797 dom = server.xend.domain(domain_name)
1798 domid = int(sxp.child_value(dom, 'domid', '-1'))
1799 return int(domid)
1801 def xm_vncviewer(args):
1802 autopass = False;
1804 try:
1805 (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass'])
1806 except getopt.GetoptError, opterr:
1807 err(opterr)
1808 usage('vncviewer')
1810 for (k, v) in options:
1811 if k in ['--autopass','--vncviewer-autopass']:
1812 autopass = True
1813 else:
1814 assert False
1816 if len(params) != 1:
1817 err('No domain given (or several parameters specified)')
1818 usage('vncviewer')
1820 dom = params[0]
1821 domid = domain_name_to_domid(dom)
1823 console.runVncViewer(domid, autopass)
1826 def xm_uptime(args):
1827 short_mode = 0
1829 try:
1830 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1831 except getopt.GetoptError, opterr:
1832 err(opterr)
1833 usage('uptime')
1835 for (k, v) in options:
1836 if k in ['-s', '--short']:
1837 short_mode = 1
1839 doms = getDomains(params, 'all')
1841 if short_mode == 0:
1842 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1844 for dom in doms:
1845 d = parse_doms_info(dom)
1846 if d['domid'] == '':
1847 uptime = 0
1848 elif int(d['domid']) > 0:
1849 uptime = int(round(d['up_time']))
1850 else:
1851 f=open('/proc/uptime', 'r')
1852 upfile = f.read()
1853 uptime = int(round(float(upfile.split(' ')[0])))
1854 f.close()
1856 days = int(uptime / 86400)
1857 uptime -= (days * 86400)
1858 hours = int(uptime / 3600)
1859 uptime -= (hours * 3600)
1860 minutes = int(uptime / 60)
1861 uptime -= (minutes * 60)
1862 seconds = uptime
1864 upstring = ""
1865 if days > 0:
1866 upstring += str(days) + " day"
1867 if days > 1:
1868 upstring += "s"
1869 upstring += ", "
1870 upstring += '%(hours)2d:%(minutes)02d' % vars()
1872 if short_mode:
1873 now = datetime.datetime.now()
1874 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1875 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1876 else:
1877 upstring += ':%(seconds)02d' % vars()
1878 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1880 print upstring
1882 def xm_sysrq(args):
1883 arg_check(args, "sysrq", 2)
1884 dom = args[0]
1885 req = args[1]
1886 if serverType == SERVER_XEN_API:
1887 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1888 else:
1889 server.xend.domain.send_sysrq(dom, req)
1891 def xm_trigger(args):
1892 vcpu = 0
1894 arg_check(args, "trigger", 2, 3)
1895 dom = args[0]
1896 trigger = args[1]
1897 if len(args) == 3:
1898 vcpu = int(args[2])
1900 if serverType == SERVER_XEN_API:
1901 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1902 else:
1903 server.xend.domain.send_trigger(dom, trigger, vcpu)
1905 def xm_debug_keys(args):
1906 arg_check(args, "debug-keys", 1)
1908 keys = str(args[0])
1910 if serverType == SERVER_XEN_API:
1911 server.xenapi.host.send_debug_keys(
1912 server.xenapi.session.get_this_host(server.getSession()),
1913 keys)
1914 else:
1915 server.xend.node.send_debug_keys(keys)
1917 def xm_top(args):
1918 arg_check(args, "top", 0)
1920 os.system('xentop')
1922 def xm_dmesg(args):
1923 arg_check(args, "dmesg", 0, 1)
1925 try:
1926 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1927 except getopt.GetoptError, opterr:
1928 err(opterr)
1929 usage('dmesg')
1931 use_clear = 0
1932 for (k, v) in options:
1933 if k in ['-c', '--clear']:
1934 use_clear = 1
1936 if len(params) :
1937 err("No parameter required")
1938 usage('dmesg')
1940 if serverType == SERVER_XEN_API:
1941 host = server.xenapi.session.get_this_host(server.getSession())
1942 if use_clear:
1943 print server.xenapi.host.dmesg_clear(host),
1944 else:
1945 print server.xenapi.host.dmesg(host),
1946 else:
1947 if not use_clear:
1948 print server.xend.node.dmesg.info(),
1949 else:
1950 print server.xend.node.dmesg.clear(),
1952 def xm_log(args):
1953 arg_check(args, "log", 0)
1955 if serverType == SERVER_XEN_API:
1956 print server.xenapi.host.get_log(
1957 server.xenapi.session.get_this_host(server.getSession()))
1958 else:
1959 print server.xend.node.log()
1961 def xm_serve(args):
1962 if serverType == SERVER_XEN_API:
1963 print "Not supported with XenAPI"
1964 sys.exit(-1)
1966 arg_check(args, "serve", 0)
1968 from fcntl import fcntl, F_SETFL
1970 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1971 s.connect(XendClient.XML_RPC_SOCKET)
1972 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1974 while True:
1975 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1976 if s in iwtd:
1977 data = s.recv(4096)
1978 if len(data) > 0:
1979 sys.stdout.write(data)
1980 sys.stdout.flush()
1981 else:
1982 break
1983 if sys.stdin in iwtd:
1984 data = sys.stdin.read(4096)
1985 if len(data) > 0:
1986 s.sendall(data)
1987 else:
1988 break
1989 s.close()
1991 def parse_dev_info(info):
1992 def get_info(n, t, d):
1993 i = 0
1994 while i < len(info):
1995 if (info[i][0] == n):
1996 return t(info[i][1])
1997 i = i + 1
1998 return t(d)
1999 return {
2000 #common
2001 'backend-id' : get_info('backend-id', int, -1),
2002 'handle' : get_info('handle', int, 0),
2003 'state' : get_info('state', int, -1),
2004 'be-path' : get_info('backend', str, '??'),
2005 'event-ch' : get_info('event-channel',int, -1),
2006 #network specific
2007 'virtual-device' : get_info('virtual-device', str, '??'),
2008 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
2009 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
2010 'mac' : get_info('mac', str, '??'),
2011 #block-device specific
2012 'ring-ref' : get_info('ring-ref', int, -1),
2013 #vscsi specific
2014 'feature-host' : get_info('feature-host', int, -1),
2017 def arg_check_for_resource_list(args, name):
2018 use_long = 0
2019 try:
2020 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2021 except getopt.GetoptError, opterr:
2022 err(opterr)
2023 sys.exit(1)
2025 for (k, v) in options:
2026 if k in ['-l', '--long']:
2027 use_long = 1
2029 if len(params) == 0:
2030 print 'No domain parameter given'
2031 usage(name)
2032 if len(params) > 1:
2033 print 'No multiple domain parameters allowed'
2034 usage(name)
2036 return (use_long, params)
2038 def xm_network_list(args):
2039 (use_long, params) = arg_check_for_resource_list(args, "network-list")
2041 dom = params[0]
2043 if serverType == SERVER_XEN_API:
2044 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2045 vif_properties = \
2046 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
2047 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2048 zip(range(len(vif_properties)), vif_properties))
2049 else:
2050 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
2052 if use_long:
2053 map(PrettyPrint.prettyprint, devs)
2054 else:
2055 hdr = 0
2056 for x in devs:
2057 if hdr == 0:
2058 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
2059 hdr = 1
2060 ni = parse_dev_info(x[1])
2061 ni['idx'] = int(x[0])
2062 print ("%(idx)-3d "
2063 "%(backend-id)-3d"
2064 "%(mac)-17s "
2065 "%(handle)-3d "
2066 "%(state)-3d "
2067 "%(event-ch)-3d "
2068 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
2069 "%(be-path)-30s "
2070 % ni)
2072 def xm_block_list(args):
2073 (use_long, params) = arg_check_for_resource_list(args, "block-list")
2075 dom = params[0]
2077 if serverType == SERVER_XEN_API:
2078 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2079 vbd_properties = \
2080 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2081 vbd_devs = \
2082 map(server.xenapi.VBD.get_device, vbd_refs)
2083 vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
2084 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2085 zip(vbd_devids, vbd_properties))
2086 else:
2087 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2089 if use_long:
2090 map(PrettyPrint.prettyprint, devs)
2091 else:
2092 hdr = 0
2093 for x in devs:
2094 if hdr == 0:
2095 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2096 hdr = 1
2097 ni = parse_dev_info(x[1])
2098 ni['idx'] = int(x[0])
2099 print ("%(idx)-5d "
2100 "%(backend-id)-3d "
2101 "%(handle)-3d "
2102 "%(state)-3d "
2103 "%(event-ch)-3d "
2104 "%(ring-ref)-5d "
2105 "%(be-path)-30s "
2106 % ni)
2108 def xm_vtpm_list(args):
2109 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2111 dom = params[0]
2113 if serverType == SERVER_XEN_API:
2114 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2115 vtpm_properties = \
2116 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2117 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2118 zip(range(len(vtpm_properties)), vtpm_properties))
2119 else:
2120 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2122 if use_long:
2123 map(PrettyPrint.prettyprint, devs)
2124 else:
2125 hdr = 0
2126 for x in devs:
2127 if hdr == 0:
2128 print 'Idx BE handle state evt-ch ring-ref BE-path'
2129 hdr = 1
2130 ni = parse_dev_info(x[1])
2131 ni['idx'] = int(x[0])
2132 print ("%(idx)-3d "
2133 "%(backend-id)-3d "
2134 "%(handle)-3d "
2135 "%(state)-3d "
2136 "%(event-ch)-3d "
2137 "%(ring-ref)-5d "
2138 "%(be-path)-30s "
2139 % ni)
2142 def xm_pci_list(args):
2143 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2145 dom = params[0]
2147 devs = []
2148 if serverType == SERVER_XEN_API:
2149 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2150 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2151 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2152 dev = {
2153 "domain": "0x%04x" % int(ppci_record["domain"]),
2154 "bus": "0x%02x" % int(ppci_record["bus"]),
2155 "slot": "0x%02x" % int(ppci_record["slot"]),
2156 "func": "0x%01x" % int(ppci_record["func"]),
2157 "vslot": "0x%02x" % \
2158 int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref))
2160 devs.append(dev)
2162 else:
2163 devs = server.xend.domain.getDeviceSxprs(dom, 'pci')
2165 if len(devs) == 0:
2166 return
2168 has_vslot = False
2169 for x in devs:
2170 if x.has_key('vslot'):
2171 if x['vslot'] == "0x%s" % AUTO_PHP_SLOT_STR:
2172 x['vslot'] = '-'
2173 else:
2174 has_vslot = True
2175 elif not x.has_key('requested_vslot'):
2176 x['vslot'] = '-'
2177 elif x['requested_vslot'] == "0x%s" % AUTO_PHP_SLOT_STR:
2178 x['vslot'] = '-'
2179 else:
2180 has_vslot = True
2181 x['vslot'] = x['requested_vslot']
2183 if has_vslot:
2184 hdr_str = 'VSlt domain bus slot func'
2185 fmt_str = "%(vslot)-4s %(domain)-6s %(bus)-4s %(slot)-4s %(func)-3s "
2186 else:
2187 hdr_str = 'domain bus slot func'
2188 fmt_str = "%(domain)-6s %(bus)-4s %(slot)-4s %(func)-3s "
2189 hdr = 0
2191 for x in devs:
2192 if hdr == 0:
2193 print (hdr_str)
2194 hdr = 1
2195 print ( fmt_str % x )
2198 def parse_pci_info(info):
2199 def get_info(n, t, d):
2200 return t(sxp.child_value(info, n, d))
2201 return {
2202 'domain' : get_info('domain', parse_hex, 0),
2203 'bus' : get_info('bus', parse_hex, -1),
2204 'slot' : get_info('slot', parse_hex, -1),
2205 'func' : get_info('func', parse_hex, -1)
2208 def xm_pci_list_assignable_devices(args):
2209 xenapi_unsupported()
2210 arg_check(args, "pci-list-assignable-devices", 0)
2212 devs = server.xend.node.pciinfo()
2214 fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
2215 for x in devs:
2216 pci = parse_pci_info(x)
2217 print fmt_str % pci
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 vslot = args[2]
2458 else:
2459 vslot = AUTO_PHP_SLOT_STR
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, vslot))
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 ['requested_vslot', '0x%x' % int(vslot, 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, vslot))
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 vslot = int(sxp.child_value(pci_dev, 'vslot'), 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": vslot,
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 if serverType == SERVER_XEN_API:
2543 # TODO
2544 raise OptionError("SCSI devices assignment by HBA is not implemeted")
2545 host_mode = 1
2546 scsi_devices = vscsi_util.vscsi_get_scsidevices()
2547 elif len(v_hctl.split(':')) != 4:
2548 raise OptionError("Invalid argument: %s" % v_hctl)
2549 (p_hctl, devname) = \
2550 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
2551 if p_hctl is None:
2552 raise OptionError("Cannot find device '%s'" % p_scsi)
2553 if host_mode:
2554 scsi_info = []
2555 devid = get_devid(p_hctl)
2556 for pHCTL, devname, _, _ in scsi_devices:
2557 if get_devid(pHCTL) == devid:
2558 scsi_info.append([devid, pHCTL, devname, pHCTL])
2559 else:
2560 scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
2561 else:
2562 # xm scsi-detach
2563 if len(v_hctl.split(':')) != 4:
2564 raise OptionError("Invalid argument: %s" % v_hctl)
2565 scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
2567 scsi = ['vscsi', ['feature-host', host_mode]]
2568 for devid, pHCTL, devname, vHCTL in scsi_info:
2569 scsi.append(['dev', \
2570 ['state', state], \
2571 ['devid', devid], \
2572 ['p-dev', pHCTL], \
2573 ['p-devname', devname], \
2574 ['v-dev', vHCTL] \
2575 ])
2576 return scsi
2578 def xm_scsi_attach(args):
2579 arg_check(args, 'scsi-attach', 3, 4)
2580 dom = args[0]
2581 p_scsi = args[1]
2582 v_hctl = args[2]
2583 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2585 if serverType == SERVER_XEN_API:
2587 scsi_dev = sxp.children(scsi, 'dev')[0]
2588 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2589 target_ref = None
2590 for pscsi_ref in server.xenapi.PSCSI.get_all():
2591 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2592 target_ref = pscsi_ref
2593 break
2594 if target_ref is None:
2595 raise OptionError("Cannot find device '%s'" % p_scsi)
2597 dscsi_record = {
2598 "VM": get_single_vm(dom),
2599 "PSCSI": target_ref,
2600 "virtual_HCTL": v_hctl
2602 server.xenapi.DSCSI.create(dscsi_record)
2604 else:
2605 if len(args) == 4:
2606 scsi.append(['backend', args[3]])
2607 server.xend.domain.device_configure(dom, scsi)
2609 def detach(args, deviceClass):
2610 rm_cfg = True
2611 dom = args[0]
2612 dev = args[1]
2613 try:
2614 force = args[2]
2615 if (force != "--force") and (force != "-f"):
2616 print "Ignoring option %s"%(force)
2617 force = None
2618 except IndexError:
2619 force = None
2621 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2624 def xm_block_detach(args):
2625 if serverType == SERVER_XEN_API:
2626 arg_check(args, "block-detach", 2, 3)
2627 dom = args[0]
2628 dev = args[1]
2629 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2630 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2631 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2632 if len(vbd_refs) > 0:
2633 vbd_ref = vbd_refs[0]
2634 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2636 server.xenapi.VBD.destroy(vbd_ref)
2638 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2639 server.xenapi.VDI.destroy(vdi_ref)
2640 else:
2641 raise OptionError("Cannot find device '%s' in domain '%s'"
2642 % (dev,dom))
2643 else:
2644 arg_check(args, 'block-detach', 2, 3)
2645 dom = args[0]
2646 dev = args[1]
2647 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2648 if dc == "tap":
2649 detach(args, 'tap')
2650 else:
2651 detach(args, 'vbd')
2653 def xm_network_detach(args):
2654 if serverType == SERVER_XEN_API:
2655 arg_check(args, "network-detach", 2, 3)
2656 dom = args[0]
2657 devid = args[1]
2658 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2659 vif_refs = [vif_ref for vif_ref in vif_refs
2660 if server.xenapi.VIF.\
2661 get_runtime_properties(vif_ref)["handle"] == devid]
2662 if len(vif_refs) > 0:
2663 vif_ref = vif_refs[0]
2665 server.xenapi.VIF.destroy(vif_ref)
2666 else:
2667 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2668 else:
2669 arg_check(args, 'network-detach', 2, 3)
2670 detach(args, 'vif')
2672 def xm_pci_detach(args):
2673 arg_check(args, 'pci-detach', 2)
2674 (dom, pci) = parse_pci_configuration(args, 'Closing')
2676 if serverType == SERVER_XEN_API:
2678 pci_dev = sxp.children(pci, 'dev')[0]
2679 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2680 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2681 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2682 func = int(sxp.child_value(pci_dev, 'func'), 16)
2683 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2684 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2686 target_ref = None
2687 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2688 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2689 if name == server.xenapi.PPCI.get_name(ppci_ref):
2690 target_ref = ppci_ref
2691 server.xenapi.DPCI.destroy(dpci_ref)
2692 break
2693 if target_ref is None:
2694 raise OptionError("Device %s not assigned" % name)
2696 else:
2697 server.xend.domain.device_configure(dom, pci)
2699 def xm_scsi_detach(args):
2700 arg_check(args, 'scsi-detach', 2)
2701 dom = args[0]
2702 v_hctl = args[1]
2703 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
2705 if serverType == SERVER_XEN_API:
2707 target_ref = None
2708 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
2709 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
2710 target_ref = dscsi_ref
2711 break
2712 if target_ref is None:
2713 raise OptionError("Device %s not assigned" % v_hctl)
2715 server.xenapi.DSCSI.destroy(target_ref)
2717 else:
2718 server.xend.domain.device_configure(dom, scsi)
2720 def xm_vnet_list(args):
2721 xenapi_unsupported()
2722 try:
2723 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2724 except getopt.GetoptError, opterr:
2725 err(opterr)
2726 usage('vnet-list')
2728 use_long = 0
2729 for (k, v) in options:
2730 if k in ['-l', '--long']:
2731 use_long = 1
2733 if params:
2734 use_long = 1
2735 vnets = params
2736 else:
2737 vnets = server.xend_vnets()
2739 for vnet in vnets:
2740 try:
2741 if use_long:
2742 info = server.xend_vnet(vnet)
2743 PrettyPrint.prettyprint(info)
2744 else:
2745 print vnet
2746 except Exception, ex:
2747 print vnet, ex
2749 def xm_vnet_create(args):
2750 xenapi_unsupported()
2751 arg_check(args, "vnet-create", 1)
2752 conf = args[0]
2753 if not os.access(conf, os.R_OK):
2754 print "File not found: %s" % conf
2755 sys.exit(1)
2757 server.xend_vnet_create(conf)
2759 def xm_vnet_delete(args):
2760 xenapi_unsupported()
2761 arg_check(args, "vnet-delete", 1)
2762 vnet = args[0]
2763 server.xend_vnet_delete(vnet)
2765 def xm_network_new(args):
2766 xenapi_only()
2767 arg_check(args, "network-new", 1)
2768 network = args[0]
2770 record = {
2771 "name_label": network,
2772 "name_description": "",
2773 "other_config": {},
2774 "default_gateway": "",
2775 "default_netmask": ""
2778 server.xenapi.network.create(record)
2780 def xm_network_del(args):
2781 xenapi_only()
2782 arg_check(args, "network-del", 1)
2783 network = args[0]
2785 networks = dict([(record['name_label'], ref)
2786 for ref, record in
2787 server.xenapi.network.get_all_records().items()])
2789 if network not in networks.keys():
2790 raise ValueError("'%s' is not a valid network name" % network)
2792 server.xenapi.network.destroy(networks[network])
2794 def xm_network_show(args):
2795 xenapi_only()
2796 arg_check(args, "network-show", 0)
2798 networks = server.xenapi.network.get_all_records()
2799 pifs = server.xenapi.PIF.get_all_records()
2800 vifs = server.xenapi.VIF.get_all_records()
2802 print '%-20s %-40s %-10s' % \
2803 ('Name', 'VIFs', 'PIFs')
2805 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2807 for network_ref, network in networks.items():
2808 for i in range(max(len(network['PIFs']),
2809 len(network['VIFs']), 1)):
2810 if i < len(network['PIFs']):
2811 pif_uuid = network['PIFs'][i]
2812 else:
2813 pif_uuid = None
2815 if i < len(network['VIFs']):
2816 vif_uuid = network['VIFs'][i]
2817 else:
2818 vif_uuid = None
2820 pif = pifs.get(pif_uuid, None)
2821 vif = vifs.get(vif_uuid, None)
2823 if vif:
2824 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2825 vif = "%s.%s" % (dom_name, vif['device'])
2826 else:
2827 vif = ''
2829 if pif:
2830 if int(pif['VLAN']) > -1:
2831 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2832 else:
2833 pif = pif['device']
2834 else:
2835 pif = ''
2837 if i == 0:
2838 r = {'name_label':network['name_label'],
2839 'vif':vif, 'pif':pif}
2840 else:
2841 r = {'name_label':'', 'vif':vif, 'pif':pif}
2843 print format2 % r
2846 commands = {
2847 "shell": xm_shell,
2848 "event-monitor": xm_event_monitor,
2849 # console commands
2850 "console": xm_console,
2851 "vncviewer": xm_vncviewer,
2852 # xenstat commands
2853 "top": xm_top,
2854 # domain commands
2855 "delete": xm_delete,
2856 "destroy": xm_destroy,
2857 "domid": xm_domid,
2858 "domname": xm_domname,
2859 "dump-core": xm_dump_core,
2860 "reboot": xm_reboot,
2861 "rename": xm_rename,
2862 "reset": xm_reset,
2863 "restore": xm_restore,
2864 "resume": xm_resume,
2865 "save": xm_save,
2866 "shutdown": xm_shutdown,
2867 "start": xm_start,
2868 "sysrq": xm_sysrq,
2869 "trigger": xm_trigger,
2870 "uptime": xm_uptime,
2871 "suspend": xm_suspend,
2872 "list": xm_list,
2873 # memory commands
2874 "mem-max": xm_mem_max,
2875 "mem-set": xm_mem_set,
2876 # cpu commands
2877 "vcpu-pin": xm_vcpu_pin,
2878 "vcpu-list": xm_vcpu_list,
2879 "vcpu-set": xm_vcpu_set,
2880 # special
2881 "pause": xm_pause,
2882 "unpause": xm_unpause,
2883 # host commands
2884 "debug-keys": xm_debug_keys,
2885 "dmesg": xm_dmesg,
2886 "info": xm_info,
2887 "log": xm_log,
2888 "serve": xm_serve,
2889 # scheduler
2890 "sched-sedf": xm_sched_sedf,
2891 "sched-credit": xm_sched_credit,
2892 # block
2893 "block-attach": xm_block_attach,
2894 "block-detach": xm_block_detach,
2895 "block-list": xm_block_list,
2896 "block-configure": xm_block_configure,
2897 # network (AKA vifs)
2898 "network-attach": xm_network_attach,
2899 "network-detach": xm_network_detach,
2900 "network-list": xm_network_list,
2901 # network (as in XenAPI)
2902 "network-new": xm_network_new,
2903 "network-del": xm_network_del,
2904 "network-show": xm_network_show,
2905 # vnet
2906 "vnet-list": xm_vnet_list,
2907 "vnet-create": xm_vnet_create,
2908 "vnet-delete": xm_vnet_delete,
2909 # vtpm
2910 "vtpm-list": xm_vtpm_list,
2911 #pci
2912 "pci-attach": xm_pci_attach,
2913 "pci-detach": xm_pci_detach,
2914 "pci-list": xm_pci_list,
2915 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
2916 # vscsi
2917 "scsi-attach": xm_scsi_attach,
2918 "scsi-detach": xm_scsi_detach,
2919 "scsi-list": xm_scsi_list,
2922 ## The commands supported by a separate argument parser in xend.xm.
2923 IMPORTED_COMMANDS = [
2924 'create',
2925 'new',
2926 'migrate',
2927 'labels',
2928 'dumppolicy',
2929 'addlabel',
2930 'rmlabel',
2931 'getlabel',
2932 'dry-run',
2933 'resources',
2934 'getpolicy',
2935 'setpolicy',
2936 'resetpolicy',
2939 for c in IMPORTED_COMMANDS:
2940 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2942 aliases = {
2943 "balloon": "mem-set",
2944 "set-vcpus": "vcpu-set",
2945 "vif-list": "network-list",
2946 "vbd-create": "block-attach",
2947 "vbd-destroy": "block-detach",
2948 "vbd-list": "block-list",
2952 def xm_lookup_cmd(cmd):
2953 if commands.has_key(cmd):
2954 return commands[cmd]
2955 elif aliases.has_key(cmd):
2956 deprecated(cmd,aliases[cmd])
2957 return commands[aliases[cmd]]
2958 elif cmd == 'help':
2959 longHelp()
2960 sys.exit(0)
2961 else:
2962 # simulate getopt's prefix matching behaviour
2963 if len(cmd) > 1:
2964 same_prefix_cmds = [commands[c] for c in commands.keys() \
2965 if c[:len(cmd)] == cmd]
2966 # only execute if there is only 1 match
2967 if len(same_prefix_cmds) == 1:
2968 return same_prefix_cmds[0]
2969 return None
2971 def deprecated(old,new):
2972 print >>sys.stderr, (
2973 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2975 def main(argv=sys.argv):
2976 if len(argv) < 2:
2977 usage()
2979 # intercept --help(-h) and output our own help
2980 for help in ['--help', '-h']:
2981 if help in argv[1:]:
2982 if help == argv[1]:
2983 longHelp()
2984 sys.exit(0)
2985 else:
2986 usage(argv[1])
2988 cmd_name = argv[1]
2989 cmd = xm_lookup_cmd(cmd_name)
2990 if cmd:
2991 # strip off prog name and subcmd
2992 args = argv[2:]
2993 _, rc = _run_cmd(cmd, cmd_name, args)
2994 sys.exit(rc)
2995 else:
2996 err('Subcommand %s not found!' % cmd_name)
2997 usage()
2999 def _run_cmd(cmd, cmd_name, args):
3000 global server
3002 try:
3003 if server is None:
3004 if serverType == SERVER_XEN_API:
3005 server = XenAPI.Session(serverURI)
3006 username, password = parseAuthentication()
3007 server.login_with_password(username, password)
3008 def logout():
3009 try:
3010 server.xenapi.session.logout()
3011 except:
3012 pass
3013 atexit.register(logout)
3014 else:
3015 server = ServerProxy(serverURI)
3017 return True, cmd(args)
3018 except socket.error, ex:
3019 if os.geteuid() != 0:
3020 err("Most commands need root access. Please try again as root.")
3021 else:
3022 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
3023 except KeyboardInterrupt:
3024 print "Interrupted."
3025 return True, ''
3026 except IOError, ex:
3027 if os.geteuid() != 0:
3028 err("Most commands need root access. Please try again as root.")
3029 else:
3030 err("Unable to connect to xend: %s." % ex[1])
3031 except SystemExit, code:
3032 return code == 0, code
3033 except XenAPI.Failure, exn:
3034 for line in [''] + wrap(str(exn), 80) + ['']:
3035 print >>sys.stderr, line
3036 except xmlrpclib.Fault, ex:
3037 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
3038 err("Domain '%s' does not exist." % ex.faultString)
3039 return False, ex.faultCode
3040 else:
3041 err(ex.faultString)
3042 _usage(cmd_name)
3043 except xmlrpclib.ProtocolError, ex:
3044 if ex.errcode == -1:
3045 print >>sys.stderr, (
3046 "Xend has probably crashed! Invalid or missing HTTP "
3047 "status code.")
3048 else:
3049 print >>sys.stderr, (
3050 "Xend has probably crashed! ProtocolError(%d, %s)." %
3051 (ex.errcode, ex.errmsg))
3052 except (ValueError, OverflowError):
3053 err("Invalid argument.")
3054 _usage(cmd_name)
3055 except OptionError, e:
3056 err(str(e))
3057 _usage(cmd_name)
3058 print e.usage
3059 except XenAPIUnsupportedException, e:
3060 err(str(e))
3061 except XSMError, e:
3062 err(str(e))
3063 except Exception, e:
3064 if serverType != SERVER_XEN_API:
3065 import xen.util.xsm.xsm as security
3066 if isinstance(e, security.XSMError):
3067 err(str(e))
3068 return False, 1
3069 print "Unexpected error:", sys.exc_info()[0]
3070 print
3071 print "Please report to xen-devel@lists.xensource.com"
3072 raise
3074 return False, 1
3076 if __name__ == "__main__":
3077 main()