debuggers.hg

view tools/python/xen/xm/main.py @ 21003:b9a84ded541f

xm: Fix xm network-list for XenAPI

When I use XenAPI, MAC addresses are not shown by xm network-list.
MAC addresses are shown by this patch.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 22 10:00:24 2010 +0000 (2010-02-22)
parents 2e5032921b07
children ec5c9373e821
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 *
42 from xen.util import vusb_util
44 import warnings
45 warnings.filterwarnings('ignore', category=FutureWarning)
47 from xen.xend import PrettyPrint
48 from xen.xend import sxp
49 from xen.xend import XendClient
50 from xen.xend.XendConstants import *
51 from xen.xend.server.DevConstants import xenbusState
53 from xen.xm.opts import OptionError, Opts, wrap, set_true
54 from xen.xm import console
55 from xen.util.xmlrpcclient import ServerProxy
56 import xen.util.xsm.xsm as security
57 from xen.util.xsm.xsm import XSMError
58 from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
59 from xen.util import auxbin
61 import XenAPI
63 import inspect
64 from xen.xend import XendOptions
65 xoptions = XendOptions.instance()
67 import signal
68 signal.signal(signal.SIGINT, signal.SIG_DFL)
70 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
71 # getopt.getopt if gnu_getopt is not available. This will mean that options
72 # may only be specified before positional arguments.
73 if not hasattr(getopt, 'gnu_getopt'):
74 getopt.gnu_getopt = getopt.getopt
76 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
77 XM_CONFIG_FILE_DEFAULT = auxbin.xen_configdir() + '/xm-config.xml'
79 # Supported types of server
80 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
81 SERVER_XEN_API = 'Xen-API'
83 # General help message
85 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
86 "Control, list, and manipulate Xen guest instances.\n"
88 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
89 'For more help on \'xm\' see the xm(1) man page.\n' \
90 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
91 ' man page.\n'
93 # Help strings are indexed by subcommand name in this way:
94 # 'subcommand': (argstring, description)
96 SUBCOMMAND_HELP = {
97 # common commands
99 'shell' : ('', 'Launch an interactive shell.'),
101 'console' : ('[-q|--quiet] <Domain>',
102 'Attach to <Domain>\'s console.'),
103 'vncviewer' : ('[--[vncviewer-]autopass] <Domain>',
104 'Attach to <Domain>\'s VNC server.'),
105 'create' : ('<ConfigFile> [options] [vars]',
106 'Create a domain based on <ConfigFile>.'),
107 'destroy' : ('<Domain>',
108 'Terminate a domain immediately.'),
109 'help' : ('', 'Display this message.'),
110 'list' : ('[options] [Domain, ...]',
111 'List information about all/some domains.'),
112 'mem-max' : ('<Domain> <Mem>',
113 'Set the maximum amount reservation for a domain.'),
114 'mem-set' : ('<Domain> <Mem>',
115 'Set the current memory usage for a domain.'),
116 'migrate' : ('<Domain> <Host>',
117 'Migrate a domain to another machine.'),
118 'pause' : ('<Domain>', 'Pause execution of a domain.'),
119 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
120 'reset' : ('<Domain>', 'Reset a domain.'),
121 'restore' : ('<CheckpointFile> [-p]',
122 'Restore a domain from a saved state.'),
123 'save' : ('[-c] <Domain> <CheckpointFile>',
124 'Save a domain state to restore later.'),
125 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
126 'top' : ('', 'Monitor a host and the domains in real time.'),
127 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
128 'uptime' : ('[-s] [Domain, ...]',
129 'Print uptime for all/some domains.'),
131 # Life cycle xm commands
132 'new' : ('<ConfigFile> [options] [vars]',
133 'Adds a domain to Xend domain management'),
134 'delete' : ('<DomainName>',
135 'Remove a domain from Xend domain management.'),
136 'start' : ('<DomainName>', 'Start a Xend managed domain'),
137 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
138 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
140 # less used commands
142 'dmesg' : ('[-c|--clear]',
143 'Read and/or clear Xend\'s message buffer.'),
144 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
145 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
146 'dump-core' : ('[-L|--live] [-C|--crash] [-R|--reset] <Domain> [Filename]',
147 'Dump core for a specific domain.'),
148 'info' : ('[-c|--config]', 'Get information about Xen host.'),
149 'log' : ('', 'Print Xend log'),
150 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
151 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
152 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
153 'Get/set credit scheduler parameters.'),
154 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
155 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
156 'trigger' : ('<Domain> <nmi|reset|init|s3resume|power> [<VCPU>]',
157 'Send a trigger to a domain.'),
158 'vcpu-list' : ('[Domain, ...]',
159 'List the VCPUs for all/some domains.'),
160 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
161 'Set which CPUs a VCPU can use.'),
162 'vcpu-set' : ('<Domain> <vCPUs>',
163 'Set the number of active VCPUs for allowed for the'
164 ' domain.'),
165 #usb
166 'usb-add' : ('<domain> <[host:bus.addr] [host:vendor_id:product_id]>','Add the usb device to FV VM.'),
167 'usb-del' : ('<domain> <[host:bus.addr] [host:vendor_id:product_id]>','Delete the usb device to FV VM.'),
169 # device commands
171 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
172 'Create a new virtual block device.'),
173 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
174 'Change block device configuration'),
175 'block-detach' : ('<Domain> <DevId> [-f|--force]',
176 'Destroy a domain\'s virtual block device.'),
177 'block-list' : ('<Domain> [--long]',
178 'List virtual block devices for a domain.'),
179 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
180 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
181 '[vifname=<name>] [rate=<rate>] [model=<model>]'
182 '[accel=<accel>]',
183 'Create a new virtual network device.'),
184 'network-detach': ('<Domain> <DevId|mac> [-f|--force]',
185 'Destroy a domain\'s virtual network device.'),
186 'network-list' : ('<Domain> [--long]',
187 'List virtual network interfaces for a domain.'),
188 'network2-attach': ('<Domain> [front_mac=<mac>] [back_mac=<mac>] '
189 '[backend=<BackDomain>] [trusted=<0|1>] '
190 '[back_trusted=<0|1>] [bridge=<bridge>] '
191 '[filter_mac=<0|1>] [front_filter_mac=<0|1>] '
192 '[pdev=<PDEV>] [max_bypasses=n]',
193 'Create a new version 2 virtual network device.'),
194 'network2-detach': ('<Domain> <DevId> [-f|--force]',
195 'Destroy a domain\'s version 2 virtual network device.'),
196 'network2-list' : ('<Domain> [--long]',
197 'List version 2 virtual network interfaces for a domain.'),
198 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
199 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
200 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
201 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
202 'pci-attach' : ('[-o|--options=<opt>] <Domain> <domain:bus:slot.func> [virtual slot]',
203 'Insert a new pass-through pci device.'),
204 'pci-detach' : ('<Domain> <domain:bus:slot.func>',
205 'Remove a domain\'s pass-through pci device.'),
206 'pci-list' : ('<Domain>',
207 'List pass-through pci devices for a domain.'),
208 'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
209 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
210 'Attach a new SCSI device.'),
211 'scsi-detach' : ('<Domain> <VirtDevice>',
212 'Detach a specified SCSI device.'),
213 'scsi-list' : ('<Domain> [--long]',
214 'List all SCSI devices currently attached.'),
215 'usb-attach' : ('<Domain> <DevId> <PortNumber> <BusId>',
216 'Attach a new USB physical bus to domain\'s virtual port.'),
217 'usb-detach' : ('<Domain> <DevId> <PortNumber>',
218 'Detach a USB physical bus from domain\'s virtual port.'),
219 'usb-list' : ('<Domain>',
220 'List domain\'s attachment state of all virtual port .'),
221 'usb-list-assignable-devices' : ('', 'List all the assignable usb devices'),
222 'usb-hc-create' : ('<Domain> <USBSpecVer> <NumberOfPorts>',
223 'Create a domain\'s new virtual USB host controller.'),
224 'usb-hc-destroy' : ('<Domain> <DevId>',
225 'Destroy a domain\'s virtual USB host controller.'),
227 # tmem
228 'tmem-list' : ('[-l|--long] [<Domain>|-a|--all]', 'List tmem pools.'),
229 'tmem-thaw' : ('[<Domain>|-a|--all]', 'Thaw tmem pools.'),
230 'tmem-freeze' : ('[<Domain>|-a|--all]', 'Freeze tmem pools.'),
231 'tmem-destroy' : ('[<Domain>|-a|--all]', 'Destroy tmem pools.'),
232 'tmem-set' : ('[<Domain>|-a|--all] [weight=<weight>] [cap=<cap>] '
233 '[compress=<compress>]',
234 'Change tmem settings.'),
235 'tmem-freeable' : ('', 'Print freeable tmem (in MiB).'),
236 'tmem-shared-auth' : ('[<Domain>|-a|--all] [--uuid=<uuid>] [--auth=<0|1>]', 'De/authenticate shared tmem pool.'),
238 # security
240 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>} [<policy>]',
241 'Add security label to domain.'),
242 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
243 'Remove a security label from domain.'),
244 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
245 'Show security label for domain or resource.'),
246 'dry-run' : ('<ConfigFile>',
247 'Test if a domain can access its resources.'),
248 'resources' : ('', 'Show info for each labeled resource.'),
249 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
250 'setpolicy' : ('<policytype> <policyfile> [options]',
251 'Set the policy of the system.'),
252 'resetpolicy' : ('',
253 'Set the policy of the system to the default policy.'),
254 'getpolicy' : ('[options]', 'Get the policy of the system.'),
255 'labels' : ('[policy] [type=dom|res|any]',
256 'List <type> labels for (active) policy.'),
257 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
258 'getenforce' : ('', 'Returns the current enforcing mode for the Flask XSM module (Enforcing,Permissive)'),
259 'setenforce' : ('[ (Enforcing|1) | (Permissive|0) ]',
260 'Modifies the current enforcing mode for the Flask XSM module'),
261 }
263 SUBCOMMAND_OPTIONS = {
264 'sched-sedf': (
265 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
266 ('-s [MS]', '--slice[=MS]' ,
267 'Worst-case execution time(ms). (slice < period)'),
268 ('-l [MS]', '--latency[=MS]',
269 'Scaled period (ms) when domain performs heavy I/O'),
270 ('-e [FLAG]', '--extra[=FLAG]',
271 'Flag (0 or 1) controls if domain can run in extra time.'),
272 ('-w [FLOAT]', '--weight[=FLOAT]',
273 'CPU Period/slice (do not set with --period/--slice)'),
274 ),
275 'sched-credit': (
276 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
277 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
278 ('-c CAP', '--cap=CAP', 'Cap (int)'),
279 ),
280 'list': (
281 ('-l', '--long', 'Output all VM details in SXP'),
282 ('', '--label', 'Include security labels'),
283 ('', '--state=<state>', 'Select only VMs with the specified state'),
284 ),
285 'console': (
286 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
287 ),
288 'vncviewer': (
289 ('', '--autopass', 'Pass VNC password to viewer via stdin and -autopass'),
290 ('', '--vncviewer-autopass', '(consistency alias for --autopass)'),
291 ),
292 'dmesg': (
293 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
294 ),
295 'vnet-list': (
296 ('-l', '--long', 'List Vnets as SXP'),
297 ),
298 'network-list': (
299 ('-l', '--long', 'List resources as SXP'),
300 ),
301 'dump-core': (
302 ('-L', '--live', 'Dump core without pausing the domain'),
303 ('-C', '--crash', 'Crash domain after dumping core'),
304 ('-R', '--reset', 'Reset domain after dumping core'),
305 ),
306 'start': (
307 ('-p', '--paused', 'Do not unpause domain after starting it'),
308 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
309 ('', '--vncviewer', 'Connect to display via VNC after the domain is created'),
310 ('', '--vncviewer-autopass', 'Pass VNC password to viewer via stdin and -autopass'),
311 ),
312 'resume': (
313 ('-p', '--paused', 'Do not unpause domain after resuming it'),
314 ),
315 'save': (
316 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
317 ),
318 'restore': (
319 ('-p', '--paused', 'Do not unpause domain after restoring it'),
320 ),
321 'info': (
322 ('-c', '--config', 'List Xend configuration parameters'),
323 ),
324 'tmem-list': (
325 ('-l', '--long', 'List tmem stats.'),
326 ),
327 'tmem-thaw': (
328 ('-a', '--all', 'Thaw all tmem.'),
329 ),
330 'tmem-freeze': (
331 ('-a', '--all', 'Freeze all tmem.'),
332 ),
333 'tmem-destroy': (
334 ('-a', '--all', 'Destroy all tmem.'),
335 ),
336 'tmem-set': (
337 ('-a', '--all', 'Operate on all tmem.'),
338 ),
339 'tmem-shared-auth': (
340 ('-a', '--all', 'Authenticate for all tmem pools.'),
341 ('-u', '--uuid', 'Specify uuid (abcdef01-2345-6789-01234567890abcdef).'),
342 ('-A', '--auth', '0=auth,1=deauth'),
343 ),
344 }
346 common_commands = [
347 "console",
348 "vncviewer",
349 "create",
350 "new",
351 "delete",
352 "destroy",
353 "dump-core",
354 "help",
355 "list",
356 "mem-set",
357 "migrate",
358 "pause",
359 "reboot",
360 "reset",
361 "restore",
362 "resume",
363 "save",
364 "shell",
365 "shutdown",
366 "start",
367 "suspend",
368 "top",
369 "unpause",
370 "uptime",
371 "usb-add",
372 "usb-del",
373 "vcpu-set",
374 ]
376 domain_commands = [
377 "console",
378 "vncviewer",
379 "create",
380 "new",
381 "delete",
382 "destroy",
383 "domid",
384 "domname",
385 "dump-core",
386 "list",
387 "mem-max",
388 "mem-set",
389 "migrate",
390 "pause",
391 "reboot",
392 "rename",
393 "reset",
394 "restore",
395 "resume",
396 "save",
397 "shutdown",
398 "start",
399 "suspend",
400 "sysrq",
401 "trigger",
402 "top",
403 "unpause",
404 "uptime",
405 "usb-add",
406 "usb-del",
407 "vcpu-list",
408 "vcpu-pin",
409 "vcpu-set",
410 ]
412 host_commands = [
413 "debug-keys",
414 "dmesg",
415 "info",
416 "log",
417 "serve",
418 ]
420 scheduler_commands = [
421 "sched-credit",
422 "sched-sedf",
423 ]
425 device_commands = [
426 "block-attach",
427 "block-detach",
428 "block-list",
429 "block-configure",
430 "network-attach",
431 "network-detach",
432 "network-list",
433 "network2-attach",
434 "network2-detach",
435 "network2-list",
436 "vtpm-list",
437 "pci-attach",
438 "pci-detach",
439 "pci-list",
440 "pci-list-assignable-devices",
441 "scsi-attach",
442 "scsi-detach",
443 "scsi-list",
444 "usb-attach",
445 "usb-detach",
446 "usb-list",
447 "usb-list-assignable-devices",
448 "usb-hc-create",
449 "usb-hc-destroy",
450 ]
452 vnet_commands = [
453 "vnet-list",
454 "vnet-create",
455 "vnet-delete",
456 ]
458 security_commands = [
459 "setpolicy",
460 ]
462 acm_commands = [
463 "labels",
464 "addlabel",
465 "rmlabel",
466 "getlabel",
467 "dry-run",
468 "resources",
469 "dumppolicy",
470 "resetpolicy",
471 "getpolicy",
472 ]
474 flask_commands = [
475 "getenforce",
476 "setenforce",
477 ]
479 tmem_commands = [
480 "tmem-list",
481 "tmem-thaw",
482 "tmem-freeze",
483 "tmem-destroy",
484 "tmem-set",
485 "tmem-shared-auth",
486 ]
488 all_commands = (domain_commands + host_commands + scheduler_commands +
489 device_commands + vnet_commands + security_commands +
490 acm_commands + flask_commands + tmem_commands +
491 ['shell', 'event-monitor'])
494 ##
495 # Configuration File Parsing
496 ##
498 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
499 config = None
500 if os.path.isfile(xmConfigFile):
501 try:
502 config = xml.dom.minidom.parse(xmConfigFile)
503 except:
504 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
505 xmConfigFile)
507 def parseServer():
508 if config:
509 server = config.getElementsByTagName('server')
510 if server:
511 st = server[0].getAttribute('type')
512 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
513 print >>sys.stderr, ('Invalid server type %s; using %s.' %
514 (st, SERVER_LEGACY_XMLRPC))
515 st = SERVER_LEGACY_XMLRPC
516 return (st, server[0].getAttribute('uri'))
518 return SERVER_LEGACY_XMLRPC, XendClient.uri
520 def parseAuthentication():
521 server = config.getElementsByTagName('server')[0]
522 return (server.getAttribute('username'),
523 server.getAttribute('password'))
525 serverType, serverURI = parseServer()
526 server = None
529 ####################################################################
530 #
531 # Help/usage printing functions
532 #
533 ####################################################################
535 def cmdHelp(cmd):
536 """Print help for a specific subcommand."""
538 if not SUBCOMMAND_HELP.has_key(cmd):
539 for fc in SUBCOMMAND_HELP.keys():
540 if fc[:len(cmd)] == cmd:
541 cmd = fc
542 break
544 try:
545 args, desc = SUBCOMMAND_HELP[cmd]
546 except KeyError:
547 shortHelp()
548 return
550 print 'Usage: xm %s %s' % (cmd, args)
551 print
552 print desc
554 try:
555 # If options help message is defined, print this.
556 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
557 if shortopt and longopt:
558 optdesc = '%s, %s' % (shortopt, longopt)
559 elif shortopt:
560 optdesc = shortopt
561 elif longopt:
562 optdesc = longopt
564 wrapped_desc = wrap(desc, 43)
565 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
566 for line in wrapped_desc[1:]:
567 print ' ' * 33 + line
568 print
569 except KeyError:
570 # if the command is an external module, we grab usage help
571 # from the module itself.
572 if cmd in IMPORTED_COMMANDS:
573 try:
574 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
575 cmd_usage = getattr(cmd_module, "help", None)
576 if cmd_usage:
577 print cmd_usage()
578 except ImportError:
579 pass
581 def shortHelp():
582 """Print out generic help when xm is called without subcommand."""
584 print USAGE_HELP
585 print 'Common \'xm\' commands:\n'
587 for command in common_commands:
588 try:
589 args, desc = SUBCOMMAND_HELP[command]
590 except KeyError:
591 continue
592 wrapped_desc = wrap(desc, 50)
593 print ' %-20s %-50s' % (command, wrapped_desc[0])
594 for line in wrapped_desc[1:]:
595 print ' ' * 22 + line
597 print
598 print USAGE_FOOTER
599 print 'For a complete list of subcommands run \'xm help\'.'
601 def longHelp():
602 """Print out full help when xm is called with xm --help or xm help"""
604 print USAGE_HELP
605 print 'xm full list of subcommands:\n'
607 for command in all_commands:
608 try:
609 args, desc = SUBCOMMAND_HELP[command]
610 except KeyError:
611 continue
613 wrapped_desc = wrap(desc, 50)
614 print ' %-20s %-50s' % (command, wrapped_desc[0])
615 for line in wrapped_desc[1:]:
616 print ' ' * 22 + line
618 print
619 print USAGE_FOOTER
621 def _usage(cmd):
622 """ Print help usage information """
623 if cmd:
624 cmdHelp(cmd)
625 else:
626 shortHelp()
628 def usage(cmd = None):
629 """ Print help usage information and exits """
630 _usage(cmd)
631 sys.exit(1)
634 ####################################################################
635 #
636 # Utility functions
637 #
638 ####################################################################
640 def get_default_SR():
641 return [sr_ref
642 for sr_ref in server.xenapi.SR.get_all()
643 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
645 def get_default_Network():
646 return [network_ref
647 for network_ref in server.xenapi.network.get_all()][0]
649 class XenAPIUnsupportedException(Exception):
650 pass
652 def xenapi_unsupported():
653 if serverType == SERVER_XEN_API:
654 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
656 def xenapi_only():
657 if serverType != SERVER_XEN_API:
658 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
660 def map2sxp(m):
661 return [[k, m[k]] for k in m.keys()]
663 def arg_check(args, name, lo, hi = -1):
664 n = len([i for i in args if i != '--'])
666 if hi == -1:
667 if n != lo:
668 err("'xm %s' requires %d argument%s.\n" % (name, lo,
669 lo == 1 and '' or 's'))
670 usage(name)
671 else:
672 if n < lo or n > hi:
673 err("'xm %s' requires between %d and %d arguments.\n" %
674 (name, lo, hi))
675 usage(name)
678 def unit(c):
679 if not c.isalpha():
680 return 0
681 base = 1
682 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
683 elif c == 'M' or c == 'm': base = 1024 * 1024
684 elif c == 'K' or c == 'k': base = 1024
685 else:
686 print 'ignoring unknown unit'
687 return base
689 def int_unit(str, dest):
690 base = unit(str[-1])
691 if not base:
692 return int(str)
694 value = int(str[:-1])
695 dst_base = unit(dest)
696 if dst_base == 0:
697 dst_base = 1
698 if dst_base > base:
699 return value / (dst_base / base)
700 else:
701 return value * (base / dst_base)
703 def err(msg):
704 print >>sys.stderr, "Error:", msg
707 def get_single_vm(dom):
708 if serverType == SERVER_XEN_API:
709 uuids = server.xenapi.VM.get_by_name_label(dom)
710 if len(uuids) > 0:
711 return uuids[0]
713 refs = []
715 try:
716 domid = int(dom)
717 refs = [vm_ref
718 for vm_ref in server.xenapi.VM.get_all()
719 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
720 except:
721 pass
723 if len(refs) > 0:
724 return refs[0]
726 raise OptionError("Domain '%s' not found." % dom)
727 else:
728 dominfo = server.xend.domain(dom, False)
729 return dominfo['uuid']
731 ##
732 #
733 # Xen-API Shell
734 #
735 ##
737 class Shell(cmd.Cmd):
738 def __init__(self):
739 cmd.Cmd.__init__(self)
740 self.prompt = "xm> "
741 if serverType == SERVER_XEN_API:
742 try:
743 res = server.xenapi.host.list_methods()
744 for f in res:
745 setattr(Shell, 'do_' + f + ' ', self.default)
746 except:
747 pass
749 def preloop(self):
750 cmd.Cmd.preloop(self)
751 try:
752 import readline
753 readline.set_completer_delims(' ')
754 except ImportError:
755 pass
757 def default(self, line):
758 words = shlex.split(line)
759 if len(words) > 0 and words[0] == 'xm':
760 words = words[1:]
761 if len(words) > 0:
762 cmd = xm_lookup_cmd(words[0])
763 if cmd:
764 _run_cmd(cmd, words[0], words[1:])
765 elif serverType == SERVER_XEN_API:
766 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
767 tuple(x)),
768 words[0], words[1:])
769 if ok and res is not None and res != '':
770 pprint.pprint(res)
771 else:
772 print '*** Unknown command: %s' % words[0]
773 return False
775 def completedefault(self, text, line, begidx, endidx):
776 words = shlex.split(line[:begidx])
777 clas, func = words[0].split('.')
778 if len(words) > 1 or \
779 func.startswith('get_by_') or \
780 func == 'get_all':
781 return []
782 uuids = server.xenapi_request('%s.get_all' % clas, ())
783 return [u + " " for u in uuids if u.startswith(text)]
785 def emptyline(self):
786 pass
788 def do_EOF(self, line):
789 print
790 sys.exit(0)
792 def do_help(self, line):
793 _usage(line)
796 def xm_shell(args):
797 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
800 def xm_event_monitor(args):
801 if serverType == SERVER_XEN_API:
802 while True:
803 server.xenapi.event.register(args)
804 events = server.xenapi.event.next()
805 for e in events:
806 print e
807 else:
808 err("Event monitoring not supported unless using Xen-API.")
811 #########################################################################
812 #
813 # Main xm functions
814 #
815 #########################################################################
817 def xm_save(args):
819 arg_check(args, "save", 2, 3)
821 try:
822 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
823 except getopt.GetoptError, opterr:
824 err(opterr)
825 usage('save')
827 checkpoint = False
828 for (k, v) in options:
829 if k in ['-c', '--checkpoint']:
830 checkpoint = True
832 if len(params) != 2:
833 err("Wrong number of parameters")
834 usage('save')
836 dom = params[0]
837 savefile = os.path.abspath(params[1])
839 if not os.access(os.path.dirname(savefile), os.W_OK):
840 err("xm save: Unable to create file %s" % savefile)
841 sys.exit(1)
843 if serverType == SERVER_XEN_API:
844 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
845 else:
846 server.xend.domain.save(dom, savefile, checkpoint)
848 def xm_restore(args):
849 arg_check(args, "restore", 1, 2)
851 try:
852 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
853 except getopt.GetoptError, opterr:
854 err(opterr)
855 usage('restore')
857 paused = False
858 for (k, v) in options:
859 if k in ['-p', '--paused']:
860 paused = True
862 if len(params) != 1:
863 err("Wrong number of parameters")
864 usage('restore')
866 savefile = os.path.abspath(params[0])
868 if not os.access(savefile, os.R_OK):
869 err("xm restore: Unable to read file %s" % savefile)
870 sys.exit(1)
872 if serverType == SERVER_XEN_API:
873 server.xenapi.VM.restore(savefile, paused)
874 else:
875 server.xend.domain.restore(savefile, paused)
878 def datetime_to_secs(v):
879 unwanted = ":-."
880 for c in unwanted:
881 v = str(v).replace(c, "")
882 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
884 def getDomains(domain_names, state, full = 0):
885 if serverType == SERVER_XEN_API:
886 doms_sxp = []
887 doms_dict = []
889 dom_recs = server.xenapi.VM.get_all_records()
890 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
892 for dom_ref, dom_rec in dom_recs.items():
893 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
895 states = ('running', 'blocked', 'paused', 'shutdown',
896 'crashed', 'dying')
897 def state_on_off(state):
898 if state in dom_metrics_rec['state']:
899 return state[0]
900 else:
901 return "-"
902 state_str = "".join([state_on_off(state)
903 for state in states])
905 dom_rec.update({'name': dom_rec['name_label'],
906 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
907 'vcpus': dom_metrics_rec['VCPUs_number'],
908 'state': state_str,
909 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
910 'start_time': datetime_to_secs(
911 dom_metrics_rec['start_time'])})
913 doms_sxp.append(['domain'] + map2sxp(dom_rec))
914 doms_dict.append(dom_rec)
916 if domain_names:
917 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
918 if dom["name"] in domain_names]
920 if len(doms) > 0:
921 return doms
922 else:
923 print "Error: no domain%s named %s" % \
924 (len(domain_names) > 1 and 's' or '',
925 ', '.join(domain_names))
926 sys.exit(-1)
927 else:
928 return doms_sxp
929 else:
930 if domain_names:
931 return [server.xend.domain(dom, full) for dom in domain_names]
932 else:
933 return server.xend.domains_with_state(True, state, full)
936 def xm_list(args):
937 use_long = 0
938 show_vcpus = 0
939 show_labels = 0
940 state = 'all'
941 try:
942 (options, params) = getopt.gnu_getopt(args, 'lv',
943 ['long','vcpus','label',
944 'state='])
945 except getopt.GetoptError, opterr:
946 err(opterr)
947 usage('list')
949 for (k, v) in options:
950 if k in ['-l', '--long']:
951 use_long = 1
952 if k in ['-v', '--vcpus']:
953 show_vcpus = 1
954 if k in ['--label']:
955 show_labels = 1
956 if k in ['--state']:
957 state = v
959 if state != 'all' and len(params) > 0:
960 raise OptionError(
961 "You may specify either a state or a particular VM, but not both")
963 if show_vcpus:
964 print >>sys.stderr, (
965 "xm list -v is deprecated. Please use xm vcpu-list.")
966 xm_vcpu_list(params)
967 return
969 doms = getDomains(params, state, use_long)
971 if use_long:
972 map(PrettyPrint.prettyprint, doms)
973 elif show_labels:
974 xm_label_list(doms)
975 else:
976 xm_brief_list(doms)
979 def parse_doms_info(info):
980 def get_info(n, t, d):
981 return t(sxp.child_value(info, n, d))
983 def get_status(n, t, d):
984 return DOM_STATES[t(sxp.child_value(info, n, d))]
986 start_time = get_info('start_time', float, -1)
987 if start_time == -1:
988 up_time = float(-1)
989 else:
990 up_time = time.time() - start_time
992 parsed_info = {
993 'domid' : get_info('domid', str, ''),
994 'name' : get_info('name', str, '??'),
995 'state' : get_info('state', str, ''),
997 # VCPUs is the number online when the VM is up, or the number
998 # configured otherwise.
999 'vcpus' : get_info('online_vcpus', int,
1000 get_info('vcpus', int, 0)),
1001 'up_time' : up_time
1004 security_label = get_info('security_label', str, '')
1005 parsed_info['seclabel'] = security.parse_security_label(security_label)
1007 if serverType == SERVER_XEN_API:
1008 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
1009 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
1010 if sum(cpu_times.values()) > 0:
1011 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
1012 else:
1013 parsed_info['cpu_time'] = 0
1014 else:
1015 parsed_info['mem'] = get_info('memory', int,0)
1016 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
1018 return parsed_info
1020 def check_sched_type(sched):
1021 if serverType == SERVER_XEN_API:
1022 current = server.xenapi.host.get_sched_policy(
1023 server.xenapi.session.get_this_host(server.getSession()))
1024 else:
1025 current = 'unknown'
1026 for x in server.xend.node.info()[1:]:
1027 if len(x) > 1 and x[0] == 'xen_scheduler':
1028 current = x[1]
1029 break
1030 if sched != current:
1031 err("Xen is running with the %s scheduler" % current)
1032 sys.exit(1)
1034 def parse_sedf_info(info):
1035 def get_info(n, t, d):
1036 return t(sxp.child_value(info, n, d))
1038 return {
1039 'domid' : get_info('domid', int, -1),
1040 'period' : get_info('period', int, -1),
1041 'slice' : get_info('slice', int, -1),
1042 'latency' : get_info('latency', int, -1),
1043 'extratime': get_info('extratime', int, -1),
1044 'weight' : get_info('weight', int, -1),
1047 def domid_match(domid, info):
1048 return domid is None or domid == info['name'] or \
1049 domid == str(info['domid'])
1051 def xm_brief_list(doms):
1052 print '%-40s %5s %5s %5s %10s %9s' % \
1053 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
1055 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
1056 "%(cpu_time)8.1f"
1058 for dom in doms:
1059 d = parse_doms_info(dom)
1060 print format % d
1062 def xm_label_list(doms):
1063 print '%-40s %5s %5s %5s %10s %9s %-10s' % \
1064 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
1066 output = []
1067 format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
1068 '%(cpu_time)8.1f %(seclabel)10s'
1070 for dom in doms:
1071 d = parse_doms_info(dom)
1072 if d['seclabel'] == "" and serverType != SERVER_XEN_API:
1073 seclab = server.xend.security.get_domain_label(d['name'])
1074 if len(seclab) > 0 and seclab[0] == '\'':
1075 seclab = seclab[1:]
1076 d['seclabel'] = seclab
1077 output.append((format % d, d['seclabel']))
1079 #sort by labels
1080 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
1081 for line, label in output:
1082 print line
1085 def xm_vcpu_list(args):
1086 if serverType == SERVER_XEN_API:
1087 if args:
1088 vm_refs = map(get_single_vm, args)
1089 else:
1090 vm_refs = server.xenapi.VM.get_all()
1092 vm_records = dict(map(lambda vm_ref:
1093 (vm_ref, server.xenapi.VM.get_record(
1094 vm_ref)),
1095 vm_refs))
1097 vm_metrics = dict(map(lambda (ref, record):
1098 (ref,
1099 server.xenapi.VM_metrics.get_record(
1100 record['metrics'])),
1101 vm_records.items()))
1103 dominfo = []
1105 # vcpu_list doesn't list 'managed' domains
1106 # when they are not running, so filter them out
1108 vm_refs = [vm_ref
1109 for vm_ref in vm_refs
1110 if vm_records[vm_ref]["power_state"] != "Halted"]
1112 for vm_ref in vm_refs:
1113 info = ['domain',
1114 ['domid', vm_records[vm_ref]['domid']],
1115 ['name', vm_records[vm_ref]['name_label']],
1116 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
1118 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
1119 def chk_flag(flag):
1120 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1121 and 1 or 0
1123 vcpu_info = ['vcpu',
1124 ['number',
1125 i],
1126 ['online',
1127 chk_flag("online")],
1128 ['blocked',
1129 chk_flag("blocked")],
1130 ['running',
1131 chk_flag("running")],
1132 ['cpu_time',
1133 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1134 ['cpu',
1135 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1136 ['cpumap',
1137 vm_metrics[vm_ref]['VCPUs_params']\
1138 ['cpumap%i' % i].split(",")]]
1140 info.append(vcpu_info)
1142 dominfo.append(info)
1143 else:
1144 if args:
1145 dominfo = map(server.xend.domain.getVCPUInfo, args)
1146 else:
1147 doms = server.xend.domains_with_state(False, 'all', False)
1148 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1150 print '%-32s %5s %5s %5s %5s %9s %s' % \
1151 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1153 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1154 ' %(cpu_time)8.1f %(cpumap)s'
1156 for dom in dominfo:
1157 def get_info(n):
1158 return sxp.child_value(dom, n)
1161 # convert a list of integers into a list of pairs indicating
1162 # continuous sequences in the list:
1164 # [0,1,2,3] -> [(0,3)]
1165 # [1,2,4,5] -> [(1,2),(4,5)]
1166 # [0] -> [(0,0)]
1167 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1169 def list_to_rangepairs(cmap):
1170 cmap.sort()
1171 pairs = []
1172 x = y = 0
1173 for i in range(0,len(cmap)):
1174 try:
1175 if ((cmap[y+1] - cmap[i]) > 1):
1176 pairs.append((cmap[x],cmap[y]))
1177 x = y = i+1
1178 else:
1179 y = y + 1
1180 # if we go off the end, then just add x to y
1181 except IndexError:
1182 pairs.append((cmap[x],cmap[y]))
1184 return pairs
1187 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1189 def format_pairs(pairs):
1190 if not pairs:
1191 return "no cpus"
1192 out = ""
1193 for f,s in pairs:
1194 if (f==s):
1195 out += '%d'%f
1196 else:
1197 out += '%d-%d'%(f,s)
1198 out += ','
1199 # trim trailing ','
1200 return out[:-1]
1202 def format_cpumap(cpumap):
1203 cpumap = map(lambda x: int(x), cpumap)
1204 cpumap.sort()
1206 if serverType == SERVER_XEN_API:
1207 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1208 server.xenapi.session.get_this_host(server.getSession())))
1209 else:
1210 for x in server.xend.node.info()[1:]:
1211 if len(x) > 1 and x[0] == 'nr_cpus':
1212 nr_cpus = int(x[1])
1214 # normalize cpumap by modulus nr_cpus, and drop duplicates
1215 cpumap = dict.fromkeys(
1216 filter(lambda x: x < nr_cpus, cpumap)).keys()
1217 if len(cpumap) == nr_cpus:
1218 return "any cpu"
1220 return format_pairs(list_to_rangepairs(cpumap))
1222 name = get_info('name')
1223 domid = get_info('domid')
1224 if domid is not None:
1225 domid = str(domid)
1226 else:
1227 domid = ''
1229 for vcpu in sxp.children(dom, 'vcpu'):
1230 def vinfo(n, t):
1231 return t(sxp.child_value(vcpu, n))
1233 number = vinfo('number', int)
1234 cpu = vinfo('cpu', int)
1235 cpumap = format_cpumap(vinfo('cpumap', list))
1236 online = vinfo('online', int)
1237 cpu_time = vinfo('cpu_time', float)
1238 running = vinfo('running', int)
1239 blocked = vinfo('blocked', int)
1241 if cpu < 0:
1242 c = ''
1243 s = ''
1244 elif online:
1245 c = str(cpu)
1246 if running:
1247 s = 'r'
1248 else:
1249 s = '-'
1250 if blocked:
1251 s += 'b'
1252 else:
1253 s += '-'
1254 s += '-'
1255 else:
1256 c = '-'
1257 s = '--p'
1259 print format % locals()
1261 def start_do_console(domain_name):
1262 cpid = os.fork()
1263 if cpid != 0:
1264 for i in range(10):
1265 # Catch failure of the create process
1266 time.sleep(1)
1267 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1268 if os.WIFEXITED(rv):
1269 if os.WEXITSTATUS(rv) != 0:
1270 sys.exit(os.WEXITSTATUS(rv))
1271 try:
1272 # Acquire the console of the created dom
1273 if serverType == SERVER_XEN_API:
1274 domid = server.xenapi.VM.get_domid(
1275 get_single_vm(domain_name))
1276 else:
1277 dom = server.xend.domain(domain_name)
1278 domid = int(sxp.child_value(dom, 'domid', '-1'))
1279 console.execConsole(domid)
1280 except:
1281 pass
1282 print("Could not start console\n");
1283 sys.exit(0)
1285 def xm_start(args):
1287 paused = False
1288 console_autoconnect = False
1289 vncviewer = False
1290 vncviewer_autopass = False
1292 try:
1293 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused','vncviewer','vncviewer-autopass'])
1294 for (k, v) in options:
1295 if k in ('-p', '--paused'):
1296 paused = True
1297 if k in ('-c', '--console_autoconnect'):
1298 console_autoconnect = True
1299 if k in ('--vncviewer'):
1300 vncviewer = True
1301 if k in ('--vncviewer-autopass'):
1302 vncviewer_autopass = True
1304 if len(params) != 1:
1305 raise OptionError("Expects 1 argument")
1306 except getopt.GetoptError, opterr:
1307 err(opterr)
1308 usage('start')
1310 dom = params[0]
1312 if console_autoconnect:
1313 start_do_console(dom)
1315 try:
1316 if serverType == SERVER_XEN_API:
1317 server.xenapi.VM.start(get_single_vm(dom), paused)
1318 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1319 else:
1320 server.xend.domain.start(dom, paused)
1321 info = server.xend.domain(dom)
1322 domid = int(sxp.child_value(info, 'domid', '-1'))
1323 except:
1324 raise
1326 if domid == -1:
1327 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1329 if vncviewer:
1330 console.runVncViewer(domid, vncviewer_autopass, True)
1333 def xm_delete(args):
1334 arg_check(args, "delete", 1)
1335 dom = args[0]
1336 if serverType == SERVER_XEN_API:
1337 server.xenapi.VM.destroy(get_single_vm(dom))
1338 else:
1339 server.xend.domain.delete(dom)
1341 def xm_suspend(args):
1342 arg_check(args, "suspend", 1)
1343 dom = args[0]
1344 if serverType == SERVER_XEN_API:
1345 server.xenapi.VM.suspend(get_single_vm(dom))
1346 else:
1347 server.xend.domain.suspend(dom)
1349 def xm_resume(args):
1350 arg_check(args, "resume", 1, 2)
1352 try:
1353 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1354 except getopt.GetoptError, opterr:
1355 err(opterr)
1356 usage('resume')
1358 paused = False
1359 for (k, v) in options:
1360 if k in ['-p', '--paused']:
1361 paused = True
1363 if len(params) != 1:
1364 err("Wrong number of parameters")
1365 usage('resume')
1367 dom = params[0]
1368 if serverType == SERVER_XEN_API:
1369 server.xenapi.VM.resume(get_single_vm(dom), paused)
1370 else:
1371 server.xend.domain.resume(dom, paused)
1373 def xm_reboot(args):
1374 arg_check(args, "reboot", 1, 3)
1375 from xen.xm import shutdown
1376 shutdown.main(["shutdown", "-R"] + args)
1378 def xm_shutdown(args):
1379 arg_check(args, "shutdown", 1, 4)
1380 from xen.xm import shutdown
1381 shutdown.main(["shutdown"] + args)
1383 def xm_reset(args):
1384 arg_check(args, "reset", 1)
1385 dom = args[0]
1387 if serverType == SERVER_XEN_API:
1388 server.xenapi.VM.hard_reboot(get_single_vm(dom))
1389 else:
1390 server.xend.domain.reset(dom)
1392 def xm_pause(args):
1393 arg_check(args, "pause", 1)
1394 dom = args[0]
1396 if serverType == SERVER_XEN_API:
1397 server.xenapi.VM.pause(get_single_vm(dom))
1398 else:
1399 server.xend.domain.pause(dom)
1401 def xm_unpause(args):
1402 arg_check(args, "unpause", 1)
1403 dom = args[0]
1405 if serverType == SERVER_XEN_API:
1406 server.xenapi.VM.unpause(get_single_vm(dom))
1407 else:
1408 server.xend.domain.unpause(dom)
1410 def xm_dump_core(args):
1411 live = False
1412 crash = False
1413 reset = False
1414 try:
1415 (options, params) = getopt.gnu_getopt(args, 'LCR', ['live', 'crash', 'reset'])
1416 for (k, v) in options:
1417 if k in ('-L', '--live'):
1418 live = True
1419 elif k in ('-C', '--crash'):
1420 crash = True
1421 elif k in ('-R', '--reset'):
1422 reset = True
1424 if crash and reset:
1425 raise OptionError("You may not specify more than one '-CR' option")
1426 if len(params) not in (1, 2):
1427 raise OptionError("Expects 1 or 2 argument(s)")
1428 except getopt.GetoptError, e:
1429 raise OptionError(str(e))
1431 dom = params[0]
1432 if len(params) == 2:
1433 filename = os.path.abspath(params[1])
1434 else:
1435 filename = None
1437 print "Dumping core of domain: %s ..." % str(dom)
1438 server.xend.domain.dump(dom, filename, live, crash, reset)
1440 def xm_rename(args):
1441 arg_check(args, "rename", 2)
1443 if serverType == SERVER_XEN_API:
1444 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1445 else:
1446 server.xend.domain.setName(args[0], args[1])
1448 def xm_importcommand(command, args):
1449 cmd = __import__(command, globals(), locals(), 'xen.xm')
1450 cmd.main([command] + args)
1453 #############################################################
1455 def xm_vcpu_pin(args):
1456 arg_check(args, "vcpu-pin", 3)
1458 def cpu_make_map(cpulist):
1459 cpus = []
1460 for c in cpulist.split(','):
1461 if c.find('-') != -1:
1462 (x,y) = c.split('-')
1463 for i in range(int(x),int(y)+1):
1464 cpus.append(int(i))
1465 else:
1466 # remove this element from the list
1467 if c[0] == '^':
1468 cpus = [x for x in cpus if x != int(c[1:])]
1469 else:
1470 cpus.append(int(c))
1471 cpus.sort()
1472 return ",".join(map(str, cpus))
1474 dom = args[0]
1475 vcpu = args[1]
1476 if args[2] == 'all':
1477 cpumap = cpu_make_map('0-63')
1478 else:
1479 cpumap = cpu_make_map(args[2])
1481 if serverType == SERVER_XEN_API:
1482 server.xenapi.VM.add_to_VCPUs_params_live(
1483 get_single_vm(dom), "cpumap%i" % int(vcpu), cpumap)
1484 else:
1485 server.xend.domain.pincpu(dom, vcpu, cpumap)
1487 def xm_mem_max(args):
1488 arg_check(args, "mem-max", 2)
1490 dom = args[0]
1492 if serverType == SERVER_XEN_API:
1493 mem = int_unit(args[1], 'k') * 1024
1494 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1495 else:
1496 mem = int_unit(args[1], 'm')
1497 server.xend.domain.maxmem_set(dom, mem)
1499 def xm_mem_set(args):
1500 arg_check(args, "mem-set", 2)
1502 dom = args[0]
1504 if serverType == SERVER_XEN_API:
1505 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1506 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1507 mem_target)
1508 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1509 mem_target)
1510 else:
1511 mem_target = int_unit(args[1], 'm')
1512 server.xend.domain.setMemoryTarget(dom, mem_target)
1514 def xm_usb_add(args):
1515 arg_check(args, "usb-add", 2)
1516 server.xend.domain.usb_add(args[0],args[1])
1518 def xm_usb_del(args):
1519 arg_check(args, "usb-del", 2)
1520 server.xend.domain.usb_del(args[0],args[1])
1522 def xm_vcpu_set(args):
1523 arg_check(args, "vcpu-set", 2)
1525 dom = args[0]
1526 vcpus = int(args[1])
1528 if serverType == SERVER_XEN_API:
1529 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1530 else:
1531 server.xend.domain.setVCpuCount(dom, vcpus)
1533 def xm_destroy(args):
1534 arg_check(args, "destroy", 1)
1536 dom = args[0]
1538 if serverType == SERVER_XEN_API:
1539 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1540 else:
1541 server.xend.domain.destroy(dom)
1543 def xm_domid(args):
1544 arg_check(args, "domid", 1)
1546 name = args[0]
1548 if serverType == SERVER_XEN_API:
1549 print server.xenapi.VM.get_domid(get_single_vm(name))
1550 else:
1551 dom = server.xend.domain(name)
1552 print sxp.child_value(dom, 'domid')
1554 def xm_domname(args):
1555 arg_check(args, "domname", 1)
1557 name = args[0]
1559 if serverType == SERVER_XEN_API:
1560 print server.xenapi.VM.get_name_label(get_single_vm(name))
1561 else:
1562 dom = server.xend.domain(name)
1563 print sxp.child_value(dom, 'name')
1565 def xm_sched_sedf(args):
1566 xenapi_unsupported()
1568 def ns_to_ms(val):
1569 return float(val) * 0.000001
1571 def ms_to_ns(val):
1572 return (float(val) / 0.000001)
1574 def print_sedf(info):
1575 info['period'] = ns_to_ms(info['period'])
1576 info['slice'] = ns_to_ms(info['slice'])
1577 info['latency'] = ns_to_ms(info['latency'])
1578 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1579 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1581 check_sched_type('sedf')
1583 # we want to just display current info if no parameters are passed
1584 if len(args) == 0:
1585 domid = None
1586 else:
1587 # we expect at least a domain id (name or number)
1588 # and at most a domid up to 5 options with values
1589 arg_check(args, "sched-sedf", 1, 11)
1590 domid = args[0]
1591 # drop domid from args since get_opt doesn't recognize it
1592 args = args[1:]
1594 opts = {}
1595 try:
1596 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1597 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1598 except getopt.GetoptError, opterr:
1599 err(opterr)
1600 usage('sched-sedf')
1602 # convert to nanoseconds if needed
1603 for (k, v) in options:
1604 if k in ['-p', '--period']:
1605 opts['period'] = ms_to_ns(v)
1606 elif k in ['-s', '--slice']:
1607 opts['slice'] = ms_to_ns(v)
1608 elif k in ['-l', '--latency']:
1609 opts['latency'] = ms_to_ns(v)
1610 elif k in ['-e', '--extratime']:
1611 opts['extratime'] = v
1612 elif k in ['-w', '--weight']:
1613 opts['weight'] = v
1615 doms = filter(lambda x : domid_match(domid, x),
1616 [parse_doms_info(dom)
1617 for dom in getDomains(None, 'running')])
1618 if domid is not None and doms == []:
1619 err("Domain '%s' does not exist." % domid)
1620 usage('sched-sedf')
1622 # print header if we aren't setting any parameters
1623 if len(opts.keys()) == 0:
1624 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1625 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1626 'Extra','Weight')
1628 for d in doms:
1629 # fetch current values so as not to clobber them
1630 try:
1631 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1632 except xmlrpclib.Fault:
1633 # domain does not support sched-sedf?
1634 sedf_raw = {}
1636 sedf_info = parse_sedf_info(sedf_raw)
1637 sedf_info['name'] = d['name']
1638 # update values in case of call to set
1639 if len(opts.keys()) > 0:
1640 for k in opts.keys():
1641 sedf_info[k]=opts[k]
1643 # send the update, converting user input
1644 v = map(int, [sedf_info['period'], sedf_info['slice'],
1645 sedf_info['latency'],sedf_info['extratime'],
1646 sedf_info['weight']])
1647 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1648 if int(rv) != 0:
1649 err("Failed to set sedf parameters (rv=%d)."%(rv))
1651 # not setting values, display info
1652 else:
1653 print_sedf(sedf_info)
1655 def xm_sched_credit(args):
1656 """Get/Set options for Credit Scheduler."""
1658 check_sched_type('credit')
1660 try:
1661 opts, params = getopt.getopt(args, "d:w:c:",
1662 ["domain=", "weight=", "cap="])
1663 except getopt.GetoptError, opterr:
1664 err(opterr)
1665 usage('sched-credit')
1667 domid = None
1668 weight = None
1669 cap = None
1671 for o, a in opts:
1672 if o in ["-d", "--domain"]:
1673 domid = a
1674 elif o in ["-w", "--weight"]:
1675 weight = int(a)
1676 elif o in ["-c", "--cap"]:
1677 cap = int(a);
1679 doms = filter(lambda x : domid_match(domid, x),
1680 [parse_doms_info(dom)
1681 for dom in getDomains(None, 'all')])
1683 if weight is None and cap is None:
1684 if domid is not None and doms == []:
1685 err("Domain '%s' does not exist." % domid)
1686 usage('sched-credit')
1687 # print header if we aren't setting any parameters
1688 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1690 for d in doms:
1691 try:
1692 if serverType == SERVER_XEN_API:
1693 info = server.xenapi.VM_metrics.get_VCPUs_params(
1694 server.xenapi.VM.get_metrics(
1695 get_single_vm(d['name'])))
1696 else:
1697 info = server.xend.domain.sched_credit_get(d['name'])
1698 except xmlrpclib.Fault:
1699 pass
1701 if 'weight' not in info or 'cap' not in info:
1702 # domain does not support sched-credit?
1703 info = {'weight': -1, 'cap': -1}
1705 info['weight'] = int(info['weight'])
1706 info['cap'] = int(info['cap'])
1708 info['name'] = d['name']
1709 info['domid'] = str(d['domid'])
1710 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1711 else:
1712 if domid is None:
1713 # place holder for system-wide scheduler parameters
1714 err("No domain given.")
1715 usage('sched-credit')
1717 if serverType == SERVER_XEN_API:
1718 if doms[0]['domid']:
1719 server.xenapi.VM.add_to_VCPUs_params_live(
1720 get_single_vm(domid),
1721 "weight",
1722 weight)
1723 server.xenapi.VM.add_to_VCPUs_params_live(
1724 get_single_vm(domid),
1725 "cap",
1726 cap)
1727 else:
1728 server.xenapi.VM.add_to_VCPUs_params(
1729 get_single_vm(domid),
1730 "weight",
1731 weight)
1732 server.xenapi.VM.add_to_VCPUs_params(
1733 get_single_vm(domid),
1734 "cap",
1735 cap)
1736 else:
1737 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1738 if result != 0:
1739 err(str(result))
1741 def xm_info(args):
1742 arg_check(args, "info", 0, 1)
1744 try:
1745 (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
1746 except getopt.GetoptError, opterr:
1747 err(opterr)
1748 usage('info')
1750 show_xend_config = 0
1751 for (k, v) in options:
1752 if k in ['-c', '--config']:
1753 show_xend_config = 1
1755 if show_xend_config:
1756 for name, obj in inspect.getmembers(xoptions):
1757 if not inspect.ismethod(obj):
1758 if name == "config":
1759 for x in obj[1:]:
1760 if len(x) < 2:
1761 print "%-38s: (none)" % x[0]
1762 else:
1763 print "%-38s:" % x[0], x[1]
1764 else:
1765 print "%-38s:" % name, obj
1766 return
1768 if serverType == SERVER_XEN_API:
1770 # Need to fake out old style xm info as people rely on parsing it
1772 host_record = server.xenapi.host.get_record(
1773 server.xenapi.session.get_this_host(server.getSession()))
1775 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1777 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1779 def getVal(keys, default=""):
1780 data = host_record
1781 for key in keys:
1782 if key in data:
1783 data = data[key]
1784 else:
1785 return default
1786 return data
1788 def getCpuMhz():
1789 cpu_speeds = [int(host_cpu_record["speed"])
1790 for host_cpu_record in host_cpu_records
1791 if "speed" in host_cpu_record]
1792 if len(cpu_speeds) > 0:
1793 return sum(cpu_speeds) / len(cpu_speeds)
1794 else:
1795 return 0
1797 getCpuMhz()
1799 def getCpuFeatures():
1800 if len(host_cpu_records) > 0:
1801 return host_cpu_records[0].get("features", "")
1802 else:
1803 return ""
1805 info = {
1806 "host": getVal(["name_label"]),
1807 "release": getVal(["software_version", "release"]),
1808 "version": getVal(["software_version", "version"]),
1809 "machine": getVal(["software_version", "machine"]),
1810 "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
1811 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1812 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1813 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1814 "cpu_mhz": getCpuMhz(),
1815 "hw_caps": getCpuFeatures(),
1816 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1817 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1818 "xen_major": getVal(["software_version", "xen_major"]),
1819 "xen_minor": getVal(["software_version", "xen_minor"]),
1820 "xen_extra": getVal(["software_version", "xen_extra"]),
1821 "xen_caps": " ".join(getVal(["capabilities"], [])),
1822 "xen_scheduler": getVal(["sched_policy"]),
1823 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1824 "platform_params": getVal(["other_config", "platform_params"]),
1825 "xen_commandline": getVal(["other_config", "xen_commandline"]),
1826 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1827 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1828 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1829 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1830 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1831 "xend_config_format":getVal(["software_version", "xend_config_format"])
1834 sorted = info.items()
1835 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1837 for (k, v) in sorted:
1838 print "%-23s:" % k, v
1839 else:
1840 info = server.xend.node.info()
1841 for x in info[1:]:
1842 if len(x) < 2:
1843 print "%-23s: (none)" % x[0]
1844 else:
1845 print "%-23s:" % x[0], x[1]
1847 def xm_console(args):
1848 arg_check(args, "console", 1, 3)
1850 num = 0
1851 quiet = False;
1853 try:
1854 (options, params) = getopt.gnu_getopt(args, 'qn:', ['quiet', 'num'])
1855 except getopt.GetoptError, opterr:
1856 err(opterr)
1857 usage('console')
1859 for (k, v) in options:
1860 if k in ['-q', '--quiet']:
1861 quiet = True
1862 elif k in ['-n', '--num']:
1863 num = int(v[0])
1864 else:
1865 assert False
1867 if len(params) != 1:
1868 err('No domain given')
1869 usage('console')
1871 dom = params[0]
1873 try:
1874 if serverType == SERVER_XEN_API:
1875 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1876 else:
1877 info = server.xend.domain(dom)
1878 domid = int(sxp.child_value(info, 'domid', '-1'))
1879 except:
1880 if quiet:
1881 sys.exit(1)
1882 else:
1883 raise
1885 if domid == -1:
1886 if quiet:
1887 sys.exit(1)
1888 else:
1889 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1891 console.execConsole(domid, num)
1894 def domain_name_to_domid(domain_name):
1895 if serverType == SERVER_XEN_API:
1896 domid = server.xenapi.VM.get_domid(
1897 get_single_vm(domain_name))
1898 else:
1899 dom = server.xend.domain(domain_name)
1900 domid = int(sxp.child_value(dom, 'domid', '-1'))
1901 return int(domid)
1903 def xm_vncviewer(args):
1904 autopass = False;
1906 try:
1907 (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass'])
1908 except getopt.GetoptError, opterr:
1909 err(opterr)
1910 usage('vncviewer')
1912 for (k, v) in options:
1913 if k in ['--autopass','--vncviewer-autopass']:
1914 autopass = True
1915 else:
1916 assert False
1918 if len(params) != 1:
1919 err('No domain given (or several parameters specified)')
1920 usage('vncviewer')
1922 dom = params[0]
1923 domid = domain_name_to_domid(dom)
1925 console.runVncViewer(domid, autopass)
1928 def xm_uptime(args):
1929 short_mode = 0
1931 try:
1932 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1933 except getopt.GetoptError, opterr:
1934 err(opterr)
1935 usage('uptime')
1937 for (k, v) in options:
1938 if k in ['-s', '--short']:
1939 short_mode = 1
1941 doms = getDomains(params, 'all')
1943 if short_mode == 0:
1944 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1946 for dom in doms:
1947 d = parse_doms_info(dom)
1948 if d['domid'] == '':
1949 uptime = 0
1950 elif int(d['domid']) > 0:
1951 uptime = int(round(d['up_time']))
1952 else:
1953 f=open('/proc/uptime', 'r')
1954 upfile = f.read()
1955 uptime = int(round(float(upfile.split(' ')[0])))
1956 f.close()
1958 days = int(uptime / 86400)
1959 uptime -= (days * 86400)
1960 hours = int(uptime / 3600)
1961 uptime -= (hours * 3600)
1962 minutes = int(uptime / 60)
1963 uptime -= (minutes * 60)
1964 seconds = uptime
1966 upstring = ""
1967 if days > 0:
1968 upstring += str(days) + " day"
1969 if days > 1:
1970 upstring += "s"
1971 upstring += ", "
1972 upstring += '%(hours)2d:%(minutes)02d' % vars()
1974 if short_mode:
1975 now = datetime.datetime.now()
1976 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1977 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1978 else:
1979 upstring += ':%(seconds)02d' % vars()
1980 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1982 print upstring
1984 def xm_sysrq(args):
1985 arg_check(args, "sysrq", 2)
1986 dom = args[0]
1987 req = args[1]
1988 if serverType == SERVER_XEN_API:
1989 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1990 else:
1991 server.xend.domain.send_sysrq(dom, req)
1993 def xm_trigger(args):
1994 vcpu = 0
1996 arg_check(args, "trigger", 2, 3)
1997 dom = args[0]
1998 trigger = args[1]
1999 if len(args) == 3:
2000 vcpu = int(args[2])
2002 if serverType == SERVER_XEN_API:
2003 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
2004 else:
2005 server.xend.domain.send_trigger(dom, trigger, vcpu)
2007 def xm_debug_keys(args):
2008 arg_check(args, "debug-keys", 1)
2010 keys = str(args[0])
2012 if serverType == SERVER_XEN_API:
2013 server.xenapi.host.send_debug_keys(
2014 server.xenapi.session.get_this_host(server.getSession()),
2015 keys)
2016 else:
2017 server.xend.node.send_debug_keys(keys)
2019 def xm_top(args):
2020 arg_check(args, "top", 0)
2022 os.system('xentop')
2024 def xm_dmesg(args):
2025 arg_check(args, "dmesg", 0, 1)
2027 try:
2028 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
2029 except getopt.GetoptError, opterr:
2030 err(opterr)
2031 usage('dmesg')
2033 use_clear = 0
2034 for (k, v) in options:
2035 if k in ['-c', '--clear']:
2036 use_clear = 1
2038 if len(params) :
2039 err("No parameter required")
2040 usage('dmesg')
2042 if serverType == SERVER_XEN_API:
2043 host = server.xenapi.session.get_this_host(server.getSession())
2044 if use_clear:
2045 print server.xenapi.host.dmesg_clear(host),
2046 else:
2047 print server.xenapi.host.dmesg(host),
2048 else:
2049 if not use_clear:
2050 print server.xend.node.dmesg.info(),
2051 else:
2052 print server.xend.node.dmesg.clear(),
2054 def xm_log(args):
2055 arg_check(args, "log", 0)
2057 if serverType == SERVER_XEN_API:
2058 print server.xenapi.host.get_log(
2059 server.xenapi.session.get_this_host(server.getSession()))
2060 else:
2061 print server.xend.node.log()
2063 def xm_serve(args):
2064 if serverType == SERVER_XEN_API:
2065 print "Not supported with XenAPI"
2066 sys.exit(-1)
2068 arg_check(args, "serve", 0)
2070 from fcntl import fcntl, F_SETFL
2072 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
2073 s.connect(XendClient.XML_RPC_SOCKET)
2074 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
2076 while True:
2077 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
2078 if s in iwtd:
2079 data = s.recv(4096)
2080 if len(data) > 0:
2081 sys.stdout.write(data)
2082 sys.stdout.flush()
2083 else:
2084 break
2085 if sys.stdin in iwtd:
2086 data = sys.stdin.read(4096)
2087 if len(data) > 0:
2088 s.sendall(data)
2089 else:
2090 break
2091 s.close()
2093 def parse_dev_info(info):
2094 def get_info(n, t, d):
2095 i = 0
2096 while i < len(info):
2097 if (info[i][0] == n):
2098 return t(info[i][1])
2099 i = i + 1
2100 return t(d)
2101 return {
2102 #common
2103 'backend-id' : get_info('backend-id', int, -1),
2104 'handle' : get_info('handle', int, 0),
2105 'state' : get_info('state', int, -1),
2106 'be-path' : get_info('backend', str, '??'),
2107 'event-ch' : get_info('event-channel',int, -1),
2108 #network specific
2109 'virtual-device' : get_info('virtual-device', str, '??'),
2110 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
2111 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
2112 'mac' : get_info('mac', str, '??'),
2113 #block-device specific
2114 'ring-ref' : get_info('ring-ref', int, -1),
2115 #vscsi specific
2116 'feature-host' : get_info('feature-host', int, -1),
2119 def arg_check_for_resource_list(args, name):
2120 use_long = 0
2121 try:
2122 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2123 except getopt.GetoptError, opterr:
2124 err(opterr)
2125 sys.exit(1)
2127 for (k, v) in options:
2128 if k in ['-l', '--long']:
2129 use_long = 1
2131 if len(params) == 0:
2132 print 'No domain parameter given'
2133 usage(name)
2134 if len(params) > 1:
2135 print 'No multiple domain parameters allowed'
2136 usage(name)
2138 return (use_long, params)
2140 def xm_network_list(args):
2141 (use_long, params) = arg_check_for_resource_list(args, "network-list")
2143 dom = params[0]
2145 if serverType == SERVER_XEN_API:
2146 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2147 vif_properties = []
2148 for vif_ref in vif_refs:
2149 vif_property = server.xenapi.VIF.get_runtime_properties(vif_ref)
2150 vif_property['mac'] = server.xenapi.VIF.get_MAC(vif_ref)
2151 vif_properties.append(vif_property)
2152 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2153 zip(range(len(vif_properties)), vif_properties))
2154 else:
2155 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
2157 if use_long:
2158 map(PrettyPrint.prettyprint, devs)
2159 else:
2160 hdr = 0
2161 for x in devs:
2162 if hdr == 0:
2163 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
2164 hdr = 1
2165 ni = parse_dev_info(x[1])
2166 ni['idx'] = int(x[0])
2167 print ("%(idx)-3d "
2168 "%(backend-id)-3d"
2169 "%(mac)-17s "
2170 "%(handle)-3d "
2171 "%(state)-3d "
2172 "%(event-ch)-3d "
2173 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
2174 "%(be-path)-30s "
2175 % ni)
2177 def xm_block_list(args):
2178 (use_long, params) = arg_check_for_resource_list(args, "block-list")
2180 dom = params[0]
2182 if serverType == SERVER_XEN_API:
2183 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2184 vbd_properties = \
2185 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2186 vbd_devs = \
2187 map(server.xenapi.VBD.get_device, vbd_refs)
2188 vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
2189 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2190 zip(vbd_devids, vbd_properties))
2191 else:
2192 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2194 if use_long:
2195 map(PrettyPrint.prettyprint, devs)
2196 else:
2197 hdr = 0
2198 for x in devs:
2199 if hdr == 0:
2200 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2201 hdr = 1
2202 ni = parse_dev_info(x[1])
2203 ni['idx'] = int(x[0])
2204 print ("%(idx)-5d "
2205 "%(backend-id)-3d "
2206 "%(handle)-3d "
2207 "%(state)-3d "
2208 "%(event-ch)-3d "
2209 "%(ring-ref)-5d "
2210 "%(be-path)-30s "
2211 % ni)
2213 def xm_vtpm_list(args):
2214 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2216 dom = params[0]
2218 if serverType == SERVER_XEN_API:
2219 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2220 vtpm_properties = \
2221 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2222 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2223 zip(range(len(vtpm_properties)), vtpm_properties))
2224 else:
2225 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2227 if use_long:
2228 map(PrettyPrint.prettyprint, devs)
2229 else:
2230 hdr = 0
2231 for x in devs:
2232 if hdr == 0:
2233 print 'Idx BE handle state evt-ch ring-ref BE-path'
2234 hdr = 1
2235 ni = parse_dev_info(x[1])
2236 ni['idx'] = int(x[0])
2237 print ("%(idx)-3d "
2238 "%(backend-id)-3d "
2239 "%(handle)-3d "
2240 "%(state)-3d "
2241 "%(event-ch)-3d "
2242 "%(ring-ref)-5d "
2243 "%(be-path)-30s "
2244 % ni)
2246 def attached_pci_dict_bin(dom):
2247 devs = []
2248 if serverType == SERVER_XEN_API:
2249 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2250 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2251 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2252 dev = {
2253 'domain': int(ppci_record['domain']),
2254 'bus': int(ppci_record['bus']),
2255 'slot': int(ppci_record['slot']),
2256 'func': int(ppci_record['func']),
2257 'vdevfn': int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref)),
2258 'key': server.xenapi.DPCI.get_key(dpci_ref)
2260 devs.append(dev)
2262 else:
2263 for x in server.xend.domain.getDeviceSxprs(dom, 'pci'):
2264 dev = {
2265 'domain': int(x['domain'], 16),
2266 'bus': int(x['bus'], 16),
2267 'slot': int(x['slot'], 16),
2268 'func': int(x['func'], 16),
2269 'vdevfn': int(x['vdevfn'], 16),
2270 'key': x['key']
2272 devs.append(dev)
2274 return devs
2276 def pci_dict_bin_to_str(pci_dev):
2277 new_dev = pci_dev.copy()
2279 new_dev['domain'] = '0x%04x' % pci_dev['domain']
2280 new_dev['bus'] = '0x%02x' % pci_dev['bus']
2281 new_dev['slot'] = '0x%02x' % pci_dev['slot']
2282 new_dev['func'] = '0x%x' % pci_dev['func']
2283 new_dev['vdevfn'] = '0x%02x' % pci_dev['vdevfn']
2285 return new_dev
2287 def attached_pci_dict(dom):
2288 return map(pci_dict_bin_to_str, attached_pci_dict_bin(dom))
2290 def xm_pci_list(args):
2291 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2293 devs = attached_pci_dict_bin(params[0])
2294 if len(devs) == 0:
2295 return
2297 devs.sort(None,
2298 lambda x: (x['vdevfn'] - PCI_FUNC(x['vdevfn'])) << 32 |
2299 PCI_BDF(x['domain'], x['bus'], x['slot'], x['func']))
2301 has_vdevfn = False
2302 for x in devs:
2303 if x['vdevfn'] & AUTO_PHP_SLOT:
2304 x['show_vslot'] = '-'
2305 x['show_vfunc'] = '-'
2306 else:
2307 x['show_vslot'] = "0x%02x" % PCI_SLOT(x['vdevfn'])
2308 x['show_vfunc'] = "0x%x" % PCI_FUNC(x['vdevfn'])
2309 has_vdevfn = True
2311 hdr_str = 'domain bus slot func'
2312 fmt_str = '0x%(domain)04x 0x%(bus)02x 0x%(slot)02x 0x%(func)x'
2313 if has_vdevfn:
2314 hdr_str = 'VSlt VFn ' + hdr_str
2315 fmt_str = '%(show_vslot)-4s %(show_vfunc)-3s ' + fmt_str
2317 print hdr_str
2318 for x in devs:
2319 print fmt_str % x
2322 def parse_pci_info(info):
2323 def get_info(n, t, d):
2324 return t(sxp.child_value(info, n, d))
2325 return {
2326 'domain' : get_info('domain', parse_hex, 0),
2327 'bus' : get_info('bus', parse_hex, -1),
2328 'slot' : get_info('slot', parse_hex, -1),
2329 'func' : get_info('func', parse_hex, -1)
2332 def xm_pci_list_assignable_devices(args):
2333 xenapi_unsupported()
2334 arg_check(args, "pci-list-assignable-devices", 0)
2336 devs = server.xend.node.pciinfo()
2337 if devs is None:
2338 print "Error: pciback/pci-stub not loaded?"
2339 return
2341 fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
2342 for x in devs:
2343 pci = parse_pci_info(x)
2344 print fmt_str % pci
2347 def vscsi_sort(devs):
2348 def sort_hctl(ds, l):
2349 s = []
2350 for d1 in ds:
2351 for d2 in d1:
2352 v_dev = sxp.child_value(d2, 'v-dev')
2353 n = int(v_dev.split(':')[l])
2354 try:
2355 j = s[n]
2356 except IndexError:
2357 j = []
2358 s.extend([ [] for _ in range(len(s), n+1) ])
2359 j.append(d2)
2360 s[n] = j
2361 return s
2363 for i in range(len(devs)):
2364 ds1 = [ devs[i][1][0][1] ]
2365 ds1 = sort_hctl(ds1, 3)
2366 ds1 = sort_hctl(ds1, 2)
2367 ds1 = sort_hctl(ds1, 1)
2368 ds2 = []
2369 for d in ds1:
2370 ds2.extend(d)
2371 devs[i][1][0][1] = ds2
2372 return devs
2374 def vscsi_convert_sxp_to_dict(dev_sxp):
2375 dev_dict = {}
2376 for opt_val in dev_sxp[1:]:
2377 try:
2378 opt, val = opt_val
2379 dev_dict[opt] = val
2380 except TypeError:
2381 pass
2382 return dev_dict
2384 def xm_scsi_list(args):
2385 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2387 dom = params[0]
2389 devs = []
2390 if serverType == SERVER_XEN_API:
2392 dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
2393 dscsi_properties = \
2394 map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
2395 dscsi_dict = {}
2396 for dscsi_property in dscsi_properties:
2397 devid = int(dscsi_property['dev']['devid'])
2398 try:
2399 dscsi_sxp = dscsi_dict[devid]
2400 except:
2401 dscsi_sxp = [['devs', []]]
2402 for key, value in dscsi_property.items():
2403 if key != 'dev':
2404 dscsi_sxp.append([key, value])
2405 dev_sxp = ['dev']
2406 dev_sxp.extend(map2sxp(dscsi_property['dev']))
2407 dscsi_sxp[0][1].append(dev_sxp)
2408 dscsi_dict[devid] = dscsi_sxp
2409 devs = map2sxp(dscsi_dict)
2411 else:
2412 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2414 # Sort devs by virtual HCTL.
2415 devs = vscsi_sort(devs)
2417 if use_long:
2418 map(PrettyPrint.prettyprint, devs)
2419 else:
2420 hdr = 0
2421 for x in devs:
2422 if hdr == 0:
2423 print "%-3s %-3s %-5s %-4s %-10s %-5s %-10s %-4s" \
2424 % ('Idx', 'BE', 'state', 'host', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2425 hdr = 1
2426 ni = parse_dev_info(x[1])
2427 ni['idx'] = int(x[0])
2428 for dev in x[1][0][1]:
2429 mi = vscsi_convert_sxp_to_dict(dev)
2430 print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
2431 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2433 def xm_usb_list(args):
2434 xenapi_unsupported()
2435 arg_check(args, 'usb-list', 1)
2436 dom = args[0]
2437 devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
2438 for x in devs:
2439 print "%-3s %-3s %-5s %-7s %-30s" \
2440 % ('Idx', 'BE', 'state', 'usb-ver', 'BE-path')
2441 ni = parse_dev_info(x[1])
2442 ni['idx'] = int(x[0])
2443 usbver = sxp.child_value(x[1], 'usb-ver')
2444 if int(usbver) == 1:
2445 ni['usb-ver'] = 'USB1.1'
2446 else:
2447 ni['usb-ver'] = 'USB2.0'
2448 print "%(idx)-3d %(backend-id)-3d %(state)-5d %(usb-ver)-7s %(be-path)-30s " % ni
2450 ports = sxp.child(x[1], 'port')
2451 for port in ports[1:]:
2452 try:
2453 num, bus = port
2454 if bus != "" and vusb_util.usb_device_is_connected(bus):
2455 idvendor = vusb_util.get_usb_idvendor(bus)
2456 idproduct = vusb_util.get_usb_idproduct(bus)
2457 prodinfo = vusb_util.get_usbdevice_info(bus)
2458 print "port %i: %s [ID %-4s:%-4s %s]" \
2459 % (int(num), str(bus), idvendor, idproduct, prodinfo)
2460 else:
2461 print "port %i: " % int(num) + str(bus)
2462 except TypeError:
2463 pass
2465 def xm_usb_list_assignable_devices(args):
2466 xenapi_unsupported()
2467 arg_check(args, 'usb-list-assignable-devices', 0)
2469 usb_devs = vusb_util.get_usb_devices()
2470 buses = vusb_util.get_assigned_buses()
2472 for x in buses:
2473 try:
2474 usb_devs.remove(x)
2475 except ValueError:
2476 pass
2478 for dev in usb_devs:
2479 idvendor = vusb_util.get_usb_idvendor(dev)
2480 idproduct = vusb_util.get_usb_idproduct(dev)
2481 prodinfo = vusb_util.get_usbdevice_info(dev)
2482 print "%-13s: ID %-4s:%-4s %s" \
2483 % (dev, idvendor, idproduct, prodinfo)
2485 def parse_block_configuration(args):
2486 dom = args[0]
2488 if args[1].startswith('tap:'):
2489 cls = 'tap2'
2490 else:
2491 cls = 'vbd'
2493 vbd = [cls,
2494 ['uname', args[1]],
2495 ['dev', args[2]],
2496 ['mode', args[3]]]
2497 if len(args) == 5:
2498 vbd.append(['backend', args[4]])
2500 return (dom, vbd)
2503 def xm_block_attach(args):
2504 arg_check(args, 'block-attach', 4, 5)
2506 if serverType == SERVER_XEN_API:
2507 dom = args[0]
2508 uname = args[1]
2509 dev = args[2]
2510 mode = args[3]
2512 # First create new VDI
2513 vdi_record = {
2514 "name_label": "vdi" + str(uname.__hash__()),
2515 "name_description": "",
2516 "SR": get_default_SR(),
2517 "virtual_size": 0,
2518 "sector_size": 512,
2519 "type": "system",
2520 "sharable": False,
2521 "read_only": mode!="w",
2522 "other_config": {"location": uname}
2525 vdi_ref = server.xenapi.VDI.create(vdi_record)
2527 # Now create new VBD
2529 vbd_record = {
2530 "VM": get_single_vm(dom),
2531 "VDI": vdi_ref,
2532 "device": dev,
2533 "bootable": True,
2534 "mode": mode=="w" and "RW" or "RO",
2535 "type": "Disk",
2536 "qos_algorithm_type": "",
2537 "qos_algorithm_params": {}
2540 server.xenapi.VBD.create(vbd_record)
2542 else:
2543 (dom, vbd) = parse_block_configuration(args)
2544 server.xend.domain.device_create(dom, vbd)
2547 def xm_block_configure(args):
2548 arg_check(args, 'block-configure', 4, 5)
2550 (dom, vbd) = parse_block_configuration(args)
2551 server.xend.domain.device_configure(dom, vbd)
2554 def xm_network2_attach(args):
2555 xenapi_unsupported()
2556 arg_check(args, 'network2-attach', 1, 11)
2557 dom = args[0]
2558 vif = ['vif2']
2559 vif_params = ['front_mac', 'back_mac', 'backend', 'trusted',
2560 'back_trusted', "front_filter_mac", "filter_mac",
2561 'bridge', 'pdev', "max_bypasses" ]
2562 for a in args[1:]:
2563 vif_param = a.split("=")
2564 if len(vif_param) != 2 or vif_param[1] == "" or \
2565 vif_param[0] not in vif_params:
2566 err("Invalid argument: %s" % a)
2567 usage("network2-attach")
2568 vif.append(vif_param)
2569 server.xend.domain.device_create(dom, vif)
2571 def xm_network2_detach(args):
2572 xenapi_unsupported()
2573 arg_check(args, "network2-detach", 2, 3)
2574 detach(args, "vif2")
2576 def xm_network2_list(args):
2577 xenapi_unsupported()
2578 (use_long, params) = arg_check_for_resource_list(args, "network2-list")
2579 dom = params[0]
2580 devs = server.xend.domain.getDeviceSxprs(dom, 'vif2')
2581 map(PrettyPrint.prettyprint, devs)
2583 def xm_network_attach(args):
2584 arg_check(args, 'network-attach', 1, 11)
2586 dom = args[0]
2587 vif = ['vif']
2588 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2589 'backend', 'vifname', 'rate', 'model', 'accel']
2591 if serverType == SERVER_XEN_API:
2592 vif_record = {
2593 "device": "eth0",
2594 "network": get_default_Network(),
2595 "VM": get_single_vm(dom),
2596 "MAC": "",
2597 "MTU": "",
2598 "qos_algorithm_type": "",
2599 "qos_algorithm_params": {},
2600 "other_config": {}
2603 def set(keys, val):
2604 record = vif_record
2605 for key in keys[:-1]:
2606 record = record[key]
2607 record[keys[-1]] = val
2609 def get_net_from_bridge(bridge):
2610 # In OSS, we just assert network.name_label == bridge name
2611 networks = dict([(record['name_label'], ref)
2612 for ref, record in server.xenapi.network
2613 .get_all_records().items()])
2614 if bridge not in networks.keys():
2615 raise "Unknown bridge name!"
2616 return networks[bridge]
2618 vif_conv = {
2619 'type':
2620 lambda x: None,
2621 'mac':
2622 lambda x: set(['MAC'], x),
2623 'bridge':
2624 lambda x: set(['network'], get_net_from_bridge(x)),
2625 'ip':
2626 lambda x: set(['other_config', 'ip'], x),
2627 'script':
2628 lambda x: set(['other_config', 'script'], x),
2629 'backend':
2630 lambda x: set(['other_config', 'backend'], x),
2631 'vifname':
2632 lambda x: set(['device'], x),
2633 'rate':
2634 lambda x: set(['qos_algorithm_params', 'rate'], x),
2635 'model':
2636 lambda x: None,
2637 'accel':
2638 lambda x: set(['other_config', 'accel'], x)
2641 for a in args[1:]:
2642 vif_param = a.split("=")
2643 if len(vif_param) != 2 or vif_param[1] == '' or \
2644 vif_param[0] not in vif_params:
2645 err("Invalid argument: %s" % a)
2646 usage('network-attach')
2647 else:
2648 vif_conv[vif_param[0]](vif_param[1])
2650 server.xenapi.VIF.create(vif_record)
2651 else:
2652 for a in args[1:]:
2653 vif_param = a.split("=")
2654 if len(vif_param) != 2 or vif_param[1] == '' or \
2655 vif_param[0] not in vif_params:
2656 err("Invalid argument: %s" % a)
2657 usage('network-attach')
2658 vif.append(vif_param)
2659 server.xend.domain.device_create(dom, vif)
2661 def parse_pci_configuration(args, opts = ''):
2662 dom = args[0]
2663 pci_dev_str = args[1]
2664 if len(args) == 3:
2665 pci_dev_str += '@' + args[2]
2666 if len(opts) > 0:
2667 pci_dev_str += ',' + serialise_pci_opts(opts)
2669 try:
2670 pci_dev = parse_pci_name_extended(pci_dev_str)
2671 except PciDeviceParseError, ex:
2672 raise OptionError(str(ex))
2674 return (dom, pci_dev)
2676 def xm_pci_attach(args):
2677 config_pci_opts = []
2678 (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
2679 for (k, v) in options:
2680 if k in ('-o', '--options'):
2681 if len(v.split('=')) != 2:
2682 err("Invalid pci attach option: %s" % v)
2683 usage('pci-attach')
2684 config_pci_opts.append(v.split('='))
2686 n = len([i for i in params if i != '--'])
2687 if n < 2 or n > 3:
2688 err("Invalid argument for 'xm pci-attach'")
2689 usage('pci-attach')
2691 (dom, dev) = parse_pci_configuration(params, config_pci_opts)
2693 attached = attached_pci_dict(dom)
2695 attached_dev = map(lambda x: find_attached(attached, x, False), dev)
2697 head_dev = dev.pop(0)
2698 xm_pci_attach_one(dom, head_dev)
2700 # That is all for single-function virtual devices
2701 if len(dev) == 0:
2702 return
2704 # If the slot wasn't spefified in the args then use the slot
2705 # assigned to the head by qemu-xen for the rest of the functions
2706 if int(head_dev['vdevfn'], 16) & AUTO_PHP_SLOT:
2707 vdevfn = int(find_attached_devfn(attached_pci_dict(dom), head_dev), 16)
2708 if not vdevfn & AUTO_PHP_SLOT:
2709 vslot = PCI_SLOT(vdevfn)
2710 for i in dev:
2711 i['vdevfn'] = '0x%02x' % \
2712 PCI_DEVFN(vslot, PCI_FUNC(int(i['vdevfn'], 16)))
2714 for i in dev:
2715 xm_pci_attach_one(dom, i)
2717 def xm_pci_attach_one(dom, pci_dev):
2718 if serverType == SERVER_XEN_API:
2719 name = pci_dict_to_bdf_str(pci_dev)
2720 target_ref = None
2721 for ppci_ref in server.xenapi.PPCI.get_all():
2722 if name == server.xenapi.PPCI.get_name(ppci_ref):
2723 target_ref = ppci_ref
2724 break
2725 if target_ref is None:
2726 raise OptionError("Device %s not found" % name)
2728 dpci_record = {
2729 "VM": get_single_vm(dom),
2730 "PPCI": target_ref,
2731 "hotplug_slot": int(pci_dev['vdevfn'], 16),
2732 "options": dict(pci_dev.get('opts', [])),
2733 "key": pci_dev['key']
2735 server.xenapi.DPCI.create(dpci_record)
2737 else:
2738 pci = pci_convert_dict_to_sxp(pci_dev, 'Initialising')
2739 server.xend.domain.device_configure(dom, pci)
2741 def parse_scsi_configuration(p_scsi, v_hctl, state):
2742 def get_devid(hctl):
2743 return int(hctl.split(':')[0])
2745 host_mode = 0
2746 scsi_devices = None
2748 if p_scsi is not None:
2749 # xm scsi-attach
2750 if v_hctl == "host":
2751 host_mode = 1
2752 scsi_devices = vscsi_util.vscsi_get_scsidevices()
2753 elif len(v_hctl.split(':')) != 4:
2754 raise OptionError("Invalid argument: %s" % v_hctl)
2755 (p_hctl, devname) = \
2756 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
2757 if p_hctl is None:
2758 raise OptionError("Cannot find device '%s'" % p_scsi)
2759 if host_mode:
2760 scsi_info = []
2761 devid = get_devid(p_hctl)
2762 for pHCTL, devname, _, _ in scsi_devices:
2763 if get_devid(pHCTL) == devid:
2764 scsi_info.append([devid, pHCTL, devname, pHCTL])
2765 else:
2766 scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
2767 else:
2768 # xm scsi-detach
2769 if len(v_hctl.split(':')) != 4:
2770 raise OptionError("Invalid argument: %s" % v_hctl)
2771 scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
2773 scsi = ['vscsi', ['feature-host', host_mode]]
2774 for devid, pHCTL, devname, vHCTL in scsi_info:
2775 scsi.append(['dev', \
2776 ['state', state], \
2777 ['devid', devid], \
2778 ['p-dev', pHCTL], \
2779 ['p-devname', devname], \
2780 ['v-dev', vHCTL] \
2781 ])
2782 return scsi
2784 def xm_scsi_attach(args):
2785 arg_check(args, 'scsi-attach', 3, 4)
2786 dom = args[0]
2787 p_scsi = args[1]
2788 v_hctl = args[2]
2789 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2791 if serverType == SERVER_XEN_API:
2793 scsi_dev = sxp.children(scsi, 'dev')[0]
2795 if sxp.child_value(scsi, 'feature-host'):
2796 p_host = sxp.child_value(scsi_dev, 'devid')
2797 target_ref = None
2798 for pscsi_ref in server.xenapi.PSCSI_HBA.get_all():
2799 if p_host == int(server.xenapi.PSCSI_HBA.get_physical_host(pscsi_ref)):
2800 target_ref = pscsi_ref
2801 break
2802 if target_ref is None:
2803 raise OptionError("Cannot find device '%s'" % p_scsi)
2805 dscsi_record = {
2806 "VM": get_single_vm(dom),
2807 "PSCSI_HBA": target_ref,
2808 "assignment_mode": "HOST"
2810 server.xenapi.DSCSI_HBA.create(dscsi_record)
2811 else:
2812 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2813 target_ref = None
2814 for pscsi_ref in server.xenapi.PSCSI.get_all():
2815 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2816 target_ref = pscsi_ref
2817 break
2818 if target_ref is None:
2819 raise OptionError("Cannot find device '%s'" % p_scsi)
2821 dscsi_record = {
2822 "VM": get_single_vm(dom),
2823 "PSCSI": target_ref,
2824 "virtual_HCTL": v_hctl
2826 server.xenapi.DSCSI.create(dscsi_record)
2828 else:
2829 if len(args) == 4:
2830 scsi.append(['backend', args[3]])
2831 server.xend.domain.device_configure(dom, scsi)
2833 def xm_usb_attach(args):
2834 xenapi_unsupported()
2835 arg_check(args, 'usb-attach', 4)
2836 dom = args[0]
2837 dev = args[1]
2838 port = args[2]
2839 bus = args[3]
2841 dev_exist = 0
2842 num_ports = 0
2843 devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
2844 for x in devs:
2845 if int(x[0]) == int(dev):
2846 dev_exist = 1
2847 num_ports = sxp.child_value(x[1], 'num-ports')
2849 if dev_exist == 0:
2850 print "Cannot find device '%s' in domain '%s'" % (dev,dom)
2851 return False
2853 if int(port) < 1 or int(port) > int(num_ports):
2854 print "Invalid Port Number '%s'" % port
2855 return False
2857 bus_match = re.match(r"(^(?P<bus>[0-9]{1,2})[-,])" + \
2858 r"(?P<root_port>[0-9]{1,2})" + \
2859 r"(?P<port>([\.,]{1}[0-9]{1,2}){0,5})$", bus)
2860 if bus_match is None:
2861 print "Invalid Busid '%s'" % bus
2862 return False
2864 if vusb_util.bus_is_assigned(bus):
2865 print "Cannot assign already attached bus '%s', detach first." % bus
2866 return False
2868 prev_bus = vusb_util.get_assigned_bus(domain_name_to_domid(dom), dev, port)
2869 if not prev_bus == "":
2870 print "Cannot override already attached port '%s', detach first." % port
2871 return False
2873 usb = ['vusb', ['port', [port, str(bus)]]]
2874 server.xend.domain.device_configure(dom, usb, dev)
2876 def xm_usb_hc_create(args):
2877 xenapi_unsupported()
2878 arg_check(args, 'usb-hc-create', 3)
2879 dom = args[0]
2880 ver = args[1]
2881 num = args[2]
2882 vusb_config = ['vusb']
2883 vusb_config.append(['usb-ver', str(ver)])
2884 vusb_config.append(['num-ports', str(num)])
2885 port_config = ['port']
2886 for i in range(1, int(num) + 1):
2887 port_config.append(['%i' % i, ""])
2888 vusb_config.append(port_config)
2889 server.xend.domain.device_create(dom, vusb_config)
2891 def detach(args, deviceClass):
2892 rm_cfg = True
2893 dom = args[0]
2894 dev = args[1]
2895 try:
2896 force = args[2]
2897 if (force != "--force") and (force != "-f"):
2898 print "Ignoring option %s"%(force)
2899 force = None
2900 except IndexError:
2901 force = None
2903 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2906 def xm_block_detach(args):
2907 if serverType == SERVER_XEN_API:
2908 arg_check(args, "block-detach", 2, 3)
2909 dom = args[0]
2910 dev = args[1]
2911 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2912 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2913 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2914 if len(vbd_refs) > 0:
2915 vbd_ref = vbd_refs[0]
2916 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2918 server.xenapi.VBD.destroy(vbd_ref)
2920 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2921 server.xenapi.VDI.destroy(vdi_ref)
2922 else:
2923 raise OptionError("Cannot find device '%s' in domain '%s'"
2924 % (dev,dom))
2925 else:
2926 arg_check(args, 'block-detach', 2, 3)
2927 dom = args[0]
2928 dev = args[1]
2929 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2930 if dc == "tap2":
2931 detach(args, 'tap2')
2932 elif dc == "tap":
2933 detach(args, 'tap')
2934 else:
2935 detach(args, 'vbd')
2937 def xm_network_detach(args):
2938 arg_check(args, "network-detach", 2, 3)
2939 dom = args[0]
2940 devid = args[1]
2941 if serverType == SERVER_XEN_API:
2942 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2943 if len(devid.split(":")) == 6:
2944 mac = devid.lower()
2945 vif_refs = [vif_ref for vif_ref in vif_refs
2946 if server.xenapi.VIF.\
2947 get_record(vif_ref)["MAC"].lower() == mac]
2948 else:
2949 vif_refs = [vif_ref for vif_ref in vif_refs
2950 if server.xenapi.VIF.\
2951 get_runtime_properties(vif_ref)["handle"] == devid]
2953 if len(vif_refs) > 0:
2954 vif_ref = vif_refs[0]
2956 server.xenapi.VIF.destroy(vif_ref)
2957 else:
2958 raise OptionError("Cannot find device '%s' in domain '%s'" % (devid, dom))
2959 else:
2960 if len(devid.split(":")) == 6:
2961 mac = devid.lower()
2962 vifs = server.xend.domain.getDeviceSxprs(dom, "vif")
2963 devids = [vif[0] for vif in vifs
2964 if parse_dev_info(vif[1])["mac"].lower() == mac]
2965 if len(devids) > 0:
2966 devid = str(devids[0])
2967 else:
2968 raise OptionError("Cannot find device '%s' in domain '%s'" % (devid, dom))
2970 vif_args = [dom, devid]
2971 try:
2972 vif_args.append(args[2])
2973 except IndexError:
2974 pass
2975 detach(vif_args, 'vif')
2977 def find_attached(attached, key, detaching):
2978 l = filter(lambda dev: pci_dict_cmp(dev, key), attached)
2980 if detaching:
2981 if len(l) == 0:
2982 raise OptionError("pci: device %s is not attached!" %\
2983 pci_dict_to_bdf_str(key))
2984 # There shouldn't ever be more than one match,
2985 # but perhaps an exception should be thrown if there is
2986 return l[0]
2987 else:
2988 if len(l) == 1:
2989 raise OptionError("pci: device %s has been attached! " %\
2990 pci_dict_to_bdf_str(key))
2991 return None
2993 def find_attached_devfn(attached, key):
2994 pci_dev = find_attached(attached, key, True)
2995 return pci_dev['vdevfn']
2997 def xm_pci_detach(args):
2998 arg_check(args, 'pci-detach', 2)
3000 (dom, dev) = parse_pci_configuration(args)
3001 attached = attached_pci_dict(dom)
3003 attached_dev = map(lambda x: find_attached(attached, x, True), dev)
3005 def f(pci_dev):
3006 vdevfn = int(pci_dev['vdevfn'], 16)
3007 return PCI_SLOT(vdevfn) | (vdevfn & AUTO_PHP_SLOT)
3008 vdevfns = map(f, attached_dev)
3009 if len(set(vdevfns)) > 1:
3010 err_str = map(lambda x: "\t%s is in slot 0x%02x\n" %
3011 (pci_dict_to_bdf_str(x),
3012 PCI_SLOT(int(x['vdevfn'], 16))), dev)
3013 raise OptionError("More than one slot used by specified devices\n"
3014 + ''.join(err_str))
3016 attached_to_slot = filter(lambda x:
3017 f(x) == vdevfns[0] and
3018 attached_dev[0]["key"] ==
3019 x["key"], attached_dev)
3021 if len(attached_to_slot) != len(dev):
3022 err_str_ = map(lambda x: '\t%s\n' % pci_dict_to_bdf_str(x), dev)
3023 err_str = "Requested:\n" + ''.join(err_str_)
3024 err_str_ = map(lambda x: '\t%s (%s)\n' %
3025 (pci_dict_to_bdf_str(x), x['key']),
3026 attached_to_slot)
3027 err_str += "Present:\n" + ''.join(err_str_)
3028 raise OptionError(("Not all functions in slot 0x%02x have had "
3029 "detachment requested.\n" % vdevfns[0]) + err_str)
3031 for i in dev:
3032 xm_pci_detach_one(dom, i)
3034 def xm_pci_detach_one(dom, pci_dev):
3035 if serverType == SERVER_XEN_API:
3036 name = pci_dict_to_bdf_str(pci_dev)
3037 target_ref = None
3038 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
3039 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
3040 if name == server.xenapi.PPCI.get_name(ppci_ref):
3041 target_ref = ppci_ref
3042 server.xenapi.DPCI.destroy(dpci_ref)
3043 break
3044 if target_ref is None:
3045 raise OptionError("Device %s not assigned" % name)
3047 else:
3048 pci = pci_convert_dict_to_sxp(pci_dev, 'Closing')
3049 server.xend.domain.device_configure(dom, pci)
3051 def xm_scsi_detach(args):
3052 arg_check(args, 'scsi-detach', 2)
3053 dom = args[0]
3054 v_hctl = args[1]
3055 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
3057 if serverType == SERVER_XEN_API:
3059 target_ref = None
3060 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
3061 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
3062 target_ref = dscsi_ref
3063 break
3064 if target_ref is None:
3065 raise OptionError("Device %s not assigned" % v_hctl)
3067 target_HBA_ref = server.xenapi.DSCSI.get_HBA(target_ref)
3068 if server.xenapi.DSCSI_HBA.get_assignment_mode(target_HBA_ref) == "HOST":
3069 server.xenapi.DSCSI_HBA.destroy(target_HBA_ref)
3070 else:
3071 server.xenapi.DSCSI.destroy(target_ref)
3073 else:
3074 server.xend.domain.device_configure(dom, scsi)
3076 def xm_usb_detach(args):
3077 xenapi_unsupported()
3078 arg_check(args, 'usb-detach', 3)
3079 dom = args[0]
3080 dev = args[1]
3081 port = args[2]
3082 usb = ['vusb', ['port', [port, '']]]
3083 server.xend.domain.device_configure(dom, usb, dev)
3085 def xm_usb_hc_destroy(args):
3086 xenapi_unsupported()
3087 arg_check(args, 'usb-hc-destroy', 2)
3088 dom = args[0]
3089 dev = args[1]
3090 server.xend.domain.destroyDevice(dom, 'vusb', dev)
3092 def xm_vnet_list(args):
3093 xenapi_unsupported()
3094 try:
3095 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
3096 except getopt.GetoptError, opterr:
3097 err(opterr)
3098 usage('vnet-list')
3100 use_long = 0
3101 for (k, v) in options:
3102 if k in ['-l', '--long']:
3103 use_long = 1
3105 if params:
3106 use_long = 1
3107 vnets = params
3108 else:
3109 vnets = server.xend_vnets()
3111 for vnet in vnets:
3112 try:
3113 if use_long:
3114 info = server.xend_vnet(vnet)
3115 PrettyPrint.prettyprint(info)
3116 else:
3117 print vnet
3118 except Exception, ex:
3119 print vnet, ex
3121 def xm_vnet_create(args):
3122 xenapi_unsupported()
3123 arg_check(args, "vnet-create", 1)
3124 conf = args[0]
3125 if not os.access(conf, os.R_OK):
3126 print "File not found: %s" % conf
3127 sys.exit(1)
3129 server.xend_vnet_create(conf)
3131 def xm_vnet_delete(args):
3132 xenapi_unsupported()
3133 arg_check(args, "vnet-delete", 1)
3134 vnet = args[0]
3135 server.xend_vnet_delete(vnet)
3137 def xm_network_new(args):
3138 xenapi_only()
3139 arg_check(args, "network-new", 1)
3140 network = args[0]
3142 record = {
3143 "name_label": network,
3144 "name_description": "",
3145 "other_config": {},
3146 "default_gateway": "",
3147 "default_netmask": ""
3150 server.xenapi.network.create(record)
3152 def xm_network_del(args):
3153 xenapi_only()
3154 arg_check(args, "network-del", 1)
3155 network = args[0]
3157 networks = dict([(record['name_label'], ref)
3158 for ref, record in
3159 server.xenapi.network.get_all_records().items()])
3161 if network not in networks.keys():
3162 raise ValueError("'%s' is not a valid network name" % network)
3164 server.xenapi.network.destroy(networks[network])
3166 def xm_network_show(args):
3167 xenapi_only()
3168 arg_check(args, "network-show", 0)
3170 networks = server.xenapi.network.get_all_records()
3171 pifs = server.xenapi.PIF.get_all_records()
3172 vifs = server.xenapi.VIF.get_all_records()
3174 print '%-20s %-40s %-10s' % \
3175 ('Name', 'VIFs', 'PIFs')
3177 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
3179 for network_ref, network in networks.items():
3180 for i in range(max(len(network['PIFs']),
3181 len(network['VIFs']), 1)):
3182 if i < len(network['PIFs']):
3183 pif_uuid = network['PIFs'][i]
3184 else:
3185 pif_uuid = None
3187 if i < len(network['VIFs']):
3188 vif_uuid = network['VIFs'][i]
3189 else:
3190 vif_uuid = None
3192 pif = pifs.get(pif_uuid, None)
3193 vif = vifs.get(vif_uuid, None)
3195 if vif:
3196 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
3197 vif = "%s.%s" % (dom_name, vif['device'])
3198 else:
3199 vif = ''
3201 if pif:
3202 if int(pif['VLAN']) > -1:
3203 pif = '%s.%s' % (pif['device'], pif['VLAN'])
3204 else:
3205 pif = pif['device']
3206 else:
3207 pif = ''
3209 if i == 0:
3210 r = {'name_label':network['name_label'],
3211 'vif':vif, 'pif':pif}
3212 else:
3213 r = {'name_label':'', 'vif':vif, 'pif':pif}
3215 print format2 % r
3217 def xm_tmem_list(args):
3218 try:
3219 (options, params) = getopt.gnu_getopt(args, 'la', ['long','all'])
3220 except getopt.GetoptError, opterr:
3221 err(opterr)
3222 usage('tmem-list')
3224 use_long = False
3225 for (k, v) in options:
3226 if k in ['-l', '--long']:
3227 use_long = True
3229 all = False
3230 for (k, v) in options:
3231 if k in ['-a', '--all']:
3232 all = True
3234 if not all and len(params) == 0:
3235 err('You must specify -a or --all or a domain id.')
3236 usage('tmem-list')
3238 if all:
3239 domid = -1
3240 else:
3241 try:
3242 domid = int(params[0])
3243 params = params[1:]
3244 except:
3245 err('Unrecognized domain id: %s' % params[0])
3246 usage('tmem-list')
3248 if serverType == SERVER_XEN_API:
3249 print server.xenapi.host.tmem_list(domid,use_long)
3250 else:
3251 print server.xend.node.tmem_list(domid,use_long)
3253 def parse_tmem_args(args, name):
3254 try:
3255 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
3256 except getopt.GetoptError, opterr:
3257 err(opterr)
3258 usage(name)
3260 all = False
3261 for (k, v) in options:
3262 if k in ['-a', '--all']:
3263 all = True
3265 if not all and len(params) == 0:
3266 err('You must specify -a or --all or a domain id.')
3267 usage(name)
3269 if all:
3270 domid = -1
3271 else:
3272 try:
3273 domid = int(params[0])
3274 params = params[1:]
3275 except:
3276 err('Unrecognized domain id: %s' % params[0])
3277 usage(name)
3279 return domid, params
3281 def xm_tmem_destroy(args):
3282 (domid, _) = parse_tmem_args(args, 'tmem-destroy')
3283 if serverType == SERVER_XEN_API:
3284 server.xenapi.host.tmem_destroy(domid)
3285 else:
3286 server.xend.node.tmem_destroy(domid)
3288 def xm_tmem_thaw(args):
3289 (domid, _) = parse_tmem_args(args, 'tmem-thaw')
3290 if serverType == SERVER_XEN_API:
3291 server.xenapi.host.tmem_thaw(domid)
3292 else:
3293 server.xend.node.tmem_thaw(domid)
3295 def xm_tmem_freeze(args):
3296 (domid, _) = parse_tmem_args(args, 'tmem-freeze')
3297 if serverType == SERVER_XEN_API:
3298 server.xenapi.host.tmem_freeze(domid)
3299 else:
3300 server.xend.node.tmem_freeze(domid)
3302 def xm_tmem_flush(args):
3303 try:
3304 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
3305 except getopt.GetoptError, opterr:
3306 err(opterr)
3307 usage(name)
3309 all = False
3310 for (k, v) in options:
3311 if k in ['-a', '--all']:
3312 all = True
3314 if not all and len(params) == 0:
3315 err('You must specify -a or --all or a domain id.')
3316 usage('tmem-flush')
3318 if all:
3319 domid = -1
3320 else:
3321 try:
3322 domid = int(params[0])
3323 params = params[1:]
3324 except:
3325 err('Unrecognized domain id: %s' % params[0])
3326 usage('tmem-flush')
3328 pages = -1
3329 for (k, v) in options:
3330 if k in ['-p', '--pages']:
3331 pages = v
3333 if serverType == SERVER_XEN_API:
3334 server.xenapi.host.tmem_flush(domid,pages)
3335 else:
3336 server.xend.node.tmem_flush(domid,pages)
3338 def xm_tmem_set(args):
3339 try:
3340 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
3341 except getopt.GetoptError, opterr:
3342 err(opterr)
3343 usage(name)
3345 all = False
3346 for (k, v) in options:
3347 if k in ['-a', '--all']:
3348 all = True
3350 if not all and len(params) == 0:
3351 err('You must specify -a or --all or a domain id.')
3352 usage('tmem-set')
3354 if all:
3355 domid = -1
3356 else:
3357 try:
3358 domid = int(params[0])
3359 params = params[1:]
3360 except:
3361 err('Unrecognized domain id: %s' % params[0])
3362 usage('tmem-set')
3364 weight = None
3365 cap = None
3366 compress = None
3367 for item in params:
3368 if item.startswith('weight='):
3369 try:
3370 weight = int(item[7:])
3371 except:
3372 err('weight should be a integer')
3373 usage('tmem-set')
3374 if item.startswith('cap='):
3375 cap = int(item[4:])
3376 if item.startswith('compress='):
3377 compress = int(item[9:])
3379 if weight is None and cap is None and compress is None:
3380 err('Unrecognized tmem configuration option: %s' % item)
3381 usage('tmem-set')
3383 if serverType == SERVER_XEN_API:
3384 if weight is not None:
3385 server.xenapi.host.tmem_set_weight(domid, weight)
3386 if cap is not None:
3387 server.xenapi.host.tmem_set_cap(domid, cap)
3388 if compress is not None:
3389 server.xenapi.host.tmem_set_compress(domid, compress)
3390 else:
3391 if weight is not None:
3392 server.xend.node.tmem_set_weight(domid, weight)
3393 if cap is not None:
3394 server.xend.node.tmem_set_cap(domid, cap)
3395 if compress is not None:
3396 server.xend.node.tmem_set_compress(domid, compress)
3398 def xm_tmem_freeable_mb(args):
3399 if serverType == SERVER_XEN_API:
3400 print server.xenapi.host.tmem_query_freeable_mb()
3401 else:
3402 print server.xend.node.tmem_query_freeable_mb()
3404 def xm_tmem_shared_auth(args):
3405 try:
3406 (options, params) = getopt.gnu_getopt(args, 'au:A:', ['all','uuid=','auth='])
3407 except getopt.GetoptError, opterr:
3408 err(opterr)
3409 usage('tmem-shared-auth')
3411 all = False
3412 for (k, v) in options:
3413 if k in ['-a', '--all']:
3414 all = True
3416 if not all and len(params) == 0:
3417 err('You must specify -a or --all or a domain id.')
3418 usage('tmem-shared-auth')
3420 if all:
3421 domid = -1
3422 else:
3423 try:
3424 domid = int(params[0])
3425 params = params[1:]
3426 except:
3427 err('Unrecognized domain id: %s' % params[0])
3428 usage('tmem-shared-auth')
3430 for (k, v) in options:
3431 if k in ['-u', '--uuid']:
3432 uuid_str = v
3434 auth = 0
3435 for (k, v) in options:
3436 if k in ['-A', '--auth']:
3437 auth = v
3439 if serverType == SERVER_XEN_API:
3440 return server.xenapi.host.tmem_shared_auth(domid,uuid_str,auth)
3441 else:
3442 return server.xend.node.tmem_shared_auth(domid,uuid_str,auth)
3445 commands = {
3446 "shell": xm_shell,
3447 "event-monitor": xm_event_monitor,
3448 # console commands
3449 "console": xm_console,
3450 "vncviewer": xm_vncviewer,
3451 # xenstat commands
3452 "top": xm_top,
3453 # domain commands
3454 "delete": xm_delete,
3455 "destroy": xm_destroy,
3456 "domid": xm_domid,
3457 "domname": xm_domname,
3458 "dump-core": xm_dump_core,
3459 "reboot": xm_reboot,
3460 "rename": xm_rename,
3461 "reset": xm_reset,
3462 "restore": xm_restore,
3463 "resume": xm_resume,
3464 "save": xm_save,
3465 "shutdown": xm_shutdown,
3466 "start": xm_start,
3467 "sysrq": xm_sysrq,
3468 "trigger": xm_trigger,
3469 "uptime": xm_uptime,
3470 "suspend": xm_suspend,
3471 "list": xm_list,
3472 # memory commands
3473 "mem-max": xm_mem_max,
3474 "mem-set": xm_mem_set,
3475 # cpu commands
3476 "vcpu-pin": xm_vcpu_pin,
3477 "vcpu-list": xm_vcpu_list,
3478 "vcpu-set": xm_vcpu_set,
3479 # special
3480 "pause": xm_pause,
3481 "unpause": xm_unpause,
3482 # host commands
3483 "debug-keys": xm_debug_keys,
3484 "dmesg": xm_dmesg,
3485 "info": xm_info,
3486 "log": xm_log,
3487 "serve": xm_serve,
3488 # scheduler
3489 "sched-sedf": xm_sched_sedf,
3490 "sched-credit": xm_sched_credit,
3491 # block
3492 "block-attach": xm_block_attach,
3493 "block-detach": xm_block_detach,
3494 "block-list": xm_block_list,
3495 "block-configure": xm_block_configure,
3496 # network (AKA vifs)
3497 "network-attach": xm_network_attach,
3498 "network-detach": xm_network_detach,
3499 "network-list": xm_network_list,
3500 "network2-attach": xm_network2_attach,
3501 "network2-detach": xm_network2_detach,
3502 "network2-list": xm_network2_list,
3503 # network (as in XenAPI)
3504 "network-new": xm_network_new,
3505 "network-del": xm_network_del,
3506 "network-show": xm_network_show,
3507 # vnet
3508 "vnet-list": xm_vnet_list,
3509 "vnet-create": xm_vnet_create,
3510 "vnet-delete": xm_vnet_delete,
3511 # vtpm
3512 "vtpm-list": xm_vtpm_list,
3513 #pci
3514 "pci-attach": xm_pci_attach,
3515 "pci-detach": xm_pci_detach,
3516 "pci-list": xm_pci_list,
3517 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
3518 # vscsi
3519 "scsi-attach": xm_scsi_attach,
3520 "scsi-detach": xm_scsi_detach,
3521 "scsi-list": xm_scsi_list,
3522 # vusb
3523 "usb-attach": xm_usb_attach,
3524 "usb-detach": xm_usb_detach,
3525 "usb-list": xm_usb_list,
3526 "usb-list-assignable-devices": xm_usb_list_assignable_devices,
3527 "usb-hc-create": xm_usb_hc_create,
3528 "usb-hc-destroy": xm_usb_hc_destroy,
3529 # tmem
3530 "tmem-thaw": xm_tmem_thaw,
3531 "tmem-freeze": xm_tmem_freeze,
3532 "tmem-flush": xm_tmem_flush,
3533 "tmem-destroy": xm_tmem_destroy,
3534 "tmem-list": xm_tmem_list,
3535 "tmem-set": xm_tmem_set,
3536 "tmem-freeable": xm_tmem_freeable_mb,
3537 "tmem-shared-auth": xm_tmem_shared_auth,
3538 #usb
3539 "usb-add": xm_usb_add,
3540 "usb-del": xm_usb_del,
3543 ## The commands supported by a separate argument parser in xend.xm.
3544 IMPORTED_COMMANDS = [
3545 'create',
3546 'new',
3547 'migrate',
3548 'labels',
3549 'dumppolicy',
3550 'addlabel',
3551 'rmlabel',
3552 'getlabel',
3553 'dry-run',
3554 'resources',
3555 'getpolicy',
3556 'setpolicy',
3557 'resetpolicy',
3558 'getenforce',
3559 'setenforce',
3562 for c in IMPORTED_COMMANDS:
3563 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
3565 aliases = {
3566 "balloon": "mem-set",
3567 "set-vcpus": "vcpu-set",
3568 "vif-list": "network-list",
3569 "vbd-create": "block-attach",
3570 "vbd-destroy": "block-detach",
3571 "vbd-list": "block-list",
3575 def xm_lookup_cmd(cmd):
3576 if commands.has_key(cmd):
3577 return commands[cmd]
3578 elif aliases.has_key(cmd):
3579 deprecated(cmd,aliases[cmd])
3580 return commands[aliases[cmd]]
3581 elif cmd == 'help':
3582 longHelp()
3583 sys.exit(0)
3584 else:
3585 # simulate getopt's prefix matching behaviour
3586 if len(cmd) > 1:
3587 same_prefix_cmds = [commands[c] for c in commands.keys() \
3588 if c[:len(cmd)] == cmd]
3589 # only execute if there is only 1 match
3590 if len(same_prefix_cmds) == 1:
3591 return same_prefix_cmds[0]
3592 return None
3594 def deprecated(old,new):
3595 print >>sys.stderr, (
3596 "Command %s is deprecated. Please use xm %s instead." % (old, new))
3598 def main(argv=sys.argv):
3599 if len(argv) < 2:
3600 usage()
3602 # intercept --help(-h) and output our own help
3603 for help in ['--help', '-h']:
3604 if help in argv[1:]:
3605 if help == argv[1]:
3606 longHelp()
3607 sys.exit(0)
3608 else:
3609 usage(argv[1])
3611 cmd_name = argv[1]
3612 cmd = xm_lookup_cmd(cmd_name)
3613 if cmd:
3614 # strip off prog name and subcmd
3615 args = argv[2:]
3616 _, rc = _run_cmd(cmd, cmd_name, args)
3617 sys.exit(rc)
3618 else:
3619 err('Subcommand %s not found!' % cmd_name)
3620 usage()
3622 def _run_cmd(cmd, cmd_name, args):
3623 global server
3625 try:
3626 if server is None:
3627 if serverType == SERVER_XEN_API:
3628 server = XenAPI.Session(serverURI)
3629 username, password = parseAuthentication()
3630 server.login_with_password(username, password)
3631 def logout():
3632 try:
3633 server.xenapi.session.logout()
3634 except:
3635 pass
3636 atexit.register(logout)
3637 else:
3638 server = ServerProxy(serverURI)
3640 return True, cmd(args)
3641 except socket.error, ex:
3642 if os.geteuid() != 0:
3643 err("Most commands need root access. Please try again as root.")
3644 else:
3645 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
3646 except KeyboardInterrupt:
3647 print "Interrupted."
3648 return True, ''
3649 except IOError, ex:
3650 if os.geteuid() != 0:
3651 err("Most commands need root access. Please try again as root.")
3652 else:
3653 err("Unable to connect to xend: %s." % ex[1])
3654 except SystemExit, code:
3655 return code == 0, code
3656 except XenAPI.Failure, exn:
3657 for line in [''] + wrap(str(exn), 80) + ['']:
3658 print >>sys.stderr, line
3659 except xmlrpclib.Fault, ex:
3660 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
3661 err("Domain '%s' does not exist." % ex.faultString)
3662 return False, ex.faultCode
3663 else:
3664 err(ex.faultString)
3665 _usage(cmd_name)
3666 except xmlrpclib.ProtocolError, ex:
3667 if ex.errcode == -1:
3668 print >>sys.stderr, (
3669 "Xend has probably crashed! Invalid or missing HTTP "
3670 "status code.")
3671 else:
3672 print >>sys.stderr, (
3673 "Xend has probably crashed! ProtocolError(%d, %s)." %
3674 (ex.errcode, ex.errmsg))
3675 except (ValueError, OverflowError):
3676 err("Invalid argument.")
3677 _usage(cmd_name)
3678 except OptionError, e:
3679 err(str(e))
3680 _usage(cmd_name)
3681 print e.usage
3682 except XenAPIUnsupportedException, e:
3683 err(str(e))
3684 except XSMError, e:
3685 err(str(e))
3686 except Exception, e:
3687 if serverType != SERVER_XEN_API:
3688 import xen.util.xsm.xsm as security
3689 if isinstance(e, security.XSMError):
3690 err(str(e))
3691 return False, 1
3692 print "Unexpected error:", sys.exc_info()[0]
3693 print
3694 print "Please report to xen-devel@lists.xensource.com"
3695 raise
3697 return False, 1
3699 if __name__ == "__main__":
3700 main()