ia64/xen-unstable

view tools/python/xen/xm/main.py @ 19224:a35dffe6f1b6

pvSCSI, xend: add new device assignment mode

You can use "host" mode by specifying keyword "host" as virtual scsi
device. Following is usage example.

xm scsi-attach 1 2:0:3:4 host

In this case, all LUNs under host=2 are attached to guest domain 1.
The channel=0, target=3 and lun=4 are ignored.

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