debuggers.hg

view tools/python/xen/xm/main.py @ 19975:e845326ae203

python: Remove tab indents.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 14 14:43:19 2009 +0100 (2009-07-14)
parents 4afd6669a351
children 261f4a127616
line source
1 # (C) Copyright IBM Corp. 2005
2 # Copyright (C) 2004 Mike Wray
3 # Copyright (c) 2005-2006 XenSource Ltd.
4 #
5 # Authors:
6 # Sean Dague <sean at dague dot net>
7 # Mike Wray <mike dot wray at hp dot com>
8 #
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of version 2.1 of the GNU Lesser General Public
11 # License as published by the Free Software Foundation.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 """Grand unified management application for Xen.
23 """
24 import atexit
25 import cmd
26 import os
27 import pprint
28 import shlex
29 import sys
30 import re
31 import getopt
32 import socket
33 import traceback
34 import xmlrpclib
35 import time
36 import datetime
37 from select import select
38 import xml.dom.minidom
39 from xen.util.blkif import blkdev_name_to_number
40 from xen.util import vscsi_util
41 from xen.util.pci import *
43 import warnings
44 warnings.filterwarnings('ignore', category=FutureWarning)
46 from xen.xend import PrettyPrint
47 from xen.xend import sxp
48 from xen.xend import XendClient
49 from xen.xend.XendConstants import *
50 from xen.xend.server.DevConstants import xenbusState
52 from xen.xm.opts import OptionError, Opts, wrap, set_true
53 from xen.xm import console
54 from xen.util.xmlrpcclient import ServerProxy
55 import xen.util.xsm.xsm as security
56 from xen.util.xsm.xsm import XSMError
57 from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
58 from xen.util import auxbin
60 import XenAPI
62 import inspect
63 from xen.xend import XendOptions
64 xoptions = XendOptions.instance()
66 import signal
67 signal.signal(signal.SIGINT, signal.SIG_DFL)
69 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
70 # getopt.getopt if gnu_getopt is not available. This will mean that options
71 # may only be specified before positional arguments.
72 if not hasattr(getopt, 'gnu_getopt'):
73 getopt.gnu_getopt = getopt.getopt
75 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
76 XM_CONFIG_FILE_DEFAULT = auxbin.xen_configdir() + '/xm-config.xml'
78 # Supported types of server
79 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
80 SERVER_XEN_API = 'Xen-API'
82 # General help message
84 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
85 "Control, list, and manipulate Xen guest instances.\n"
87 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
88 'For more help on \'xm\' see the xm(1) man page.\n' \
89 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
90 ' man page.\n'
92 # Help strings are indexed by subcommand name in this way:
93 # 'subcommand': (argstring, description)
95 SUBCOMMAND_HELP = {
96 # common commands
98 'shell' : ('', 'Launch an interactive shell.'),
100 'console' : ('[-q|--quiet] <Domain>',
101 'Attach to <Domain>\'s console.'),
102 'vncviewer' : ('[--[vncviewer-]autopass] <Domain>',
103 'Attach to <Domain>\'s VNC server.'),
104 'create' : ('<ConfigFile> [options] [vars]',
105 'Create a domain based on <ConfigFile>.'),
106 'destroy' : ('<Domain>',
107 'Terminate a domain immediately.'),
108 'help' : ('', 'Display this message.'),
109 'list' : ('[options] [Domain, ...]',
110 'List information about all/some domains.'),
111 'mem-max' : ('<Domain> <Mem>',
112 'Set the maximum amount reservation for a domain.'),
113 'mem-set' : ('<Domain> <Mem>',
114 'Set the current memory usage for a domain.'),
115 'migrate' : ('<Domain> <Host>',
116 'Migrate a domain to another machine.'),
117 'pause' : ('<Domain>', 'Pause execution of a domain.'),
118 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
119 'reset' : ('<Domain>', 'Reset a domain.'),
120 'restore' : ('<CheckpointFile> [-p]',
121 'Restore a domain from a saved state.'),
122 'save' : ('[-c] <Domain> <CheckpointFile>',
123 'Save a domain state to restore later.'),
124 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
125 'top' : ('', 'Monitor a host and the domains in real time.'),
126 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
127 'uptime' : ('[-s] [Domain, ...]',
128 'Print uptime for all/some domains.'),
130 # Life cycle xm commands
131 'new' : ('<ConfigFile> [options] [vars]',
132 'Adds a domain to Xend domain management'),
133 'delete' : ('<DomainName>',
134 'Remove a domain from Xend domain management.'),
135 'start' : ('<DomainName>', 'Start a Xend managed domain'),
136 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
137 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
139 # less used commands
141 'dmesg' : ('[-c|--clear]',
142 'Read and/or clear Xend\'s message buffer.'),
143 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
144 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
145 'dump-core' : ('[-L|--live] [-C|--crash] [-R|--reset] <Domain> [Filename]',
146 'Dump core for a specific domain.'),
147 'info' : ('[-c|--config]', 'Get information about Xen host.'),
148 'log' : ('', 'Print Xend log'),
149 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
150 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
151 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
152 'Get/set credit scheduler parameters.'),
153 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
154 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
155 'trigger' : ('<Domain> <nmi|reset|init|s3resume|power> [<VCPU>]',
156 'Send a trigger to a domain.'),
157 'vcpu-list' : ('[Domain, ...]',
158 'List the VCPUs for all/some domains.'),
159 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
160 'Set which CPUs a VCPU can use.'),
161 'vcpu-set' : ('<Domain> <vCPUs>',
162 'Set the number of active VCPUs for allowed for the'
163 ' domain.'),
165 # device commands
167 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
168 'Create a new virtual block device.'),
169 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
170 'Change block device configuration'),
171 'block-detach' : ('<Domain> <DevId> [-f|--force]',
172 'Destroy a domain\'s virtual block device.'),
173 'block-list' : ('<Domain> [--long]',
174 'List virtual block devices for a domain.'),
175 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
176 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
177 '[vifname=<name>] [rate=<rate>] [model=<model>]'
178 '[accel=<accel>]',
179 'Create a new virtual network device.'),
180 'network-detach': ('<Domain> <DevId> [-f|--force]',
181 'Destroy a domain\'s virtual network device.'),
182 'network-list' : ('<Domain> [--long]',
183 'List virtual network interfaces for a domain.'),
184 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
185 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
186 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
187 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
188 'pci-attach' : ('[-o|--options=<opt>] <Domain> <domain:bus:slot.func> [virtual slot]',
189 'Insert a new pass-through pci device.'),
190 'pci-detach' : ('<Domain> <domain:bus:slot.func>',
191 'Remove a domain\'s pass-through pci device.'),
192 'pci-list' : ('<Domain>',
193 'List pass-through pci devices for a domain.'),
194 'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
195 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
196 'Attach a new SCSI device.'),
197 'scsi-detach' : ('<Domain> <VirtDevice>',
198 'Detach a specified SCSI device.'),
199 'scsi-list' : ('<Domain> [--long]',
200 'List all SCSI devices currently attached.'),
202 # tmem
203 'tmem-list' : ('[-l|--long] [<Domain>|-a|--all]', 'List tmem pools.'),
204 'tmem-thaw' : ('[<Domain>|-a|--all]', 'Thaw tmem pools.'),
205 'tmem-freeze' : ('[<Domain>|-a|--all]', 'Freeze tmem pools.'),
206 'tmem-destroy' : ('[<Domain>|-a|--all]', 'Destroy tmem pools.'),
207 'tmem-set' : ('[<Domain>|-a|--all] [weight=<weight>] [cap=<cap>] '
208 '[compress=<compress>]',
209 'Change tmem settings.'),
211 # security
213 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
214 ' [<policy>]',
215 'Add security label to domain.'),
216 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
217 'Remove a security label from domain.'),
218 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
219 'Show security label for domain or resource.'),
220 'dry-run' : ('<ConfigFile>',
221 'Test if a domain can access its resources.'),
222 'resources' : ('', 'Show info for each labeled resource.'),
223 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
224 'setpolicy' : ('<policytype> <policyfile> [options]',
225 'Set the policy of the system.'),
226 'resetpolicy' : ('',
227 'Set the policy of the system to the default policy.'),
228 'getpolicy' : ('[options]', 'Get the policy of the system.'),
229 'labels' : ('[policy] [type=dom|res|any]',
230 'List <type> labels for (active) policy.'),
231 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
232 }
234 SUBCOMMAND_OPTIONS = {
235 'sched-sedf': (
236 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
237 ('-s [MS]', '--slice[=MS]' ,
238 'Worst-case execution time(ms). (slice < period)'),
239 ('-l [MS]', '--latency[=MS]',
240 'Scaled period (ms) when domain performs heavy I/O'),
241 ('-e [FLAG]', '--extra[=FLAG]',
242 'Flag (0 or 1) controls if domain can run in extra time.'),
243 ('-w [FLOAT]', '--weight[=FLOAT]',
244 'CPU Period/slice (do not set with --period/--slice)'),
245 ),
246 'sched-credit': (
247 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
248 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
249 ('-c CAP', '--cap=CAP', 'Cap (int)'),
250 ),
251 'list': (
252 ('-l', '--long', 'Output all VM details in SXP'),
253 ('', '--label', 'Include security labels'),
254 ('', '--state=<state>', 'Select only VMs with the specified state'),
255 ),
256 'console': (
257 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
258 ),
259 'vncviewer': (
260 ('', '--autopass', 'Pass VNC password to viewer via stdin and -autopass'),
261 ('', '--vncviewer-autopass', '(consistency alias for --autopass)'),
262 ),
263 'dmesg': (
264 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
265 ),
266 'vnet-list': (
267 ('-l', '--long', 'List Vnets as SXP'),
268 ),
269 'network-list': (
270 ('-l', '--long', 'List resources as SXP'),
271 ),
272 'dump-core': (
273 ('-L', '--live', 'Dump core without pausing the domain'),
274 ('-C', '--crash', 'Crash domain after dumping core'),
275 ('-R', '--reset', 'Reset domain after dumping core'),
276 ),
277 'start': (
278 ('-p', '--paused', 'Do not unpause domain after starting it'),
279 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
280 ('', '--vncviewer', 'Connect to display via VNC after the domain is created'),
281 ('', '--vncviewer-autopass', 'Pass VNC password to viewer via stdin and -autopass'),
282 ),
283 'resume': (
284 ('-p', '--paused', 'Do not unpause domain after resuming it'),
285 ),
286 'save': (
287 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
288 ),
289 'restore': (
290 ('-p', '--paused', 'Do not unpause domain after restoring it'),
291 ),
292 'info': (
293 ('-c', '--config', 'List Xend configuration parameters'),
294 ),
295 'tmem-list': (
296 ('-l', '--long', 'List tmem stats.'),
297 ),
298 'tmem-thaw': (
299 ('-a', '--all', 'Thaw all tmem.'),
300 ),
301 'tmem-freeze': (
302 ('-a', '--all', 'Freeze all tmem.'),
303 ),
304 'tmem-destroy': (
305 ('-a', '--all', 'Destroy all tmem.'),
306 ),
307 'tmem-set': (
308 ('-a', '--all', 'Operate on all tmem.'),
309 ),
310 }
312 common_commands = [
313 "console",
314 "vncviewer",
315 "create",
316 "new",
317 "delete",
318 "destroy",
319 "dump-core",
320 "help",
321 "list",
322 "mem-set",
323 "migrate",
324 "pause",
325 "reboot",
326 "reset",
327 "restore",
328 "resume",
329 "save",
330 "shell",
331 "shutdown",
332 "start",
333 "suspend",
334 "top",
335 "unpause",
336 "uptime",
337 "vcpu-set",
338 ]
340 domain_commands = [
341 "console",
342 "vncviewer",
343 "create",
344 "new",
345 "delete",
346 "destroy",
347 "domid",
348 "domname",
349 "dump-core",
350 "list",
351 "mem-max",
352 "mem-set",
353 "migrate",
354 "pause",
355 "reboot",
356 "rename",
357 "reset",
358 "restore",
359 "resume",
360 "save",
361 "shutdown",
362 "start",
363 "suspend",
364 "sysrq",
365 "trigger",
366 "top",
367 "unpause",
368 "uptime",
369 "vcpu-list",
370 "vcpu-pin",
371 "vcpu-set",
372 ]
374 host_commands = [
375 "debug-keys",
376 "dmesg",
377 "info",
378 "log",
379 "serve",
380 ]
382 scheduler_commands = [
383 "sched-credit",
384 "sched-sedf",
385 ]
387 device_commands = [
388 "block-attach",
389 "block-detach",
390 "block-list",
391 "block-configure",
392 "network-attach",
393 "network-detach",
394 "network-list",
395 "vtpm-list",
396 "pci-attach",
397 "pci-detach",
398 "pci-list",
399 "pci-list-assignable-devices",
400 "scsi-attach",
401 "scsi-detach",
402 "scsi-list",
403 ]
405 vnet_commands = [
406 "vnet-list",
407 "vnet-create",
408 "vnet-delete",
409 ]
411 acm_commands = [
412 "labels",
413 "addlabel",
414 "rmlabel",
415 "getlabel",
416 "dry-run",
417 "resources",
418 "dumppolicy",
419 "setpolicy",
420 "resetpolicy",
421 "getpolicy",
422 ]
424 tmem_commands = [
425 "tmem-list",
426 "tmem-thaw",
427 "tmem-freeze",
428 "tmem-destroy",
429 "tmem-set",
430 ]
432 all_commands = (domain_commands + host_commands + scheduler_commands +
433 device_commands + vnet_commands + acm_commands +
434 tmem_commands + ['shell', 'event-monitor'])
437 ##
438 # Configuration File Parsing
439 ##
441 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
442 config = None
443 if os.path.isfile(xmConfigFile):
444 try:
445 config = xml.dom.minidom.parse(xmConfigFile)
446 except:
447 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
448 xmConfigFile)
450 def parseServer():
451 if config:
452 server = config.getElementsByTagName('server')
453 if server:
454 st = server[0].getAttribute('type')
455 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
456 print >>sys.stderr, ('Invalid server type %s; using %s.' %
457 (st, SERVER_LEGACY_XMLRPC))
458 st = SERVER_LEGACY_XMLRPC
459 return (st, server[0].getAttribute('uri'))
461 return SERVER_LEGACY_XMLRPC, XendClient.uri
463 def parseAuthentication():
464 server = config.getElementsByTagName('server')[0]
465 return (server.getAttribute('username'),
466 server.getAttribute('password'))
468 serverType, serverURI = parseServer()
469 server = None
472 ####################################################################
473 #
474 # Help/usage printing functions
475 #
476 ####################################################################
478 def cmdHelp(cmd):
479 """Print help for a specific subcommand."""
481 if not SUBCOMMAND_HELP.has_key(cmd):
482 for fc in SUBCOMMAND_HELP.keys():
483 if fc[:len(cmd)] == cmd:
484 cmd = fc
485 break
487 try:
488 args, desc = SUBCOMMAND_HELP[cmd]
489 except KeyError:
490 shortHelp()
491 return
493 print 'Usage: xm %s %s' % (cmd, args)
494 print
495 print desc
497 try:
498 # If options help message is defined, print this.
499 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
500 if shortopt and longopt:
501 optdesc = '%s, %s' % (shortopt, longopt)
502 elif shortopt:
503 optdesc = shortopt
504 elif longopt:
505 optdesc = longopt
507 wrapped_desc = wrap(desc, 43)
508 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
509 for line in wrapped_desc[1:]:
510 print ' ' * 33 + line
511 print
512 except KeyError:
513 # if the command is an external module, we grab usage help
514 # from the module itself.
515 if cmd in IMPORTED_COMMANDS:
516 try:
517 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
518 cmd_usage = getattr(cmd_module, "help", None)
519 if cmd_usage:
520 print cmd_usage()
521 except ImportError:
522 pass
524 def shortHelp():
525 """Print out generic help when xm is called without subcommand."""
527 print USAGE_HELP
528 print 'Common \'xm\' commands:\n'
530 for command in common_commands:
531 try:
532 args, desc = SUBCOMMAND_HELP[command]
533 except KeyError:
534 continue
535 wrapped_desc = wrap(desc, 50)
536 print ' %-20s %-50s' % (command, wrapped_desc[0])
537 for line in wrapped_desc[1:]:
538 print ' ' * 22 + line
540 print
541 print USAGE_FOOTER
542 print 'For a complete list of subcommands run \'xm help\'.'
544 def longHelp():
545 """Print out full help when xm is called with xm --help or xm help"""
547 print USAGE_HELP
548 print 'xm full list of subcommands:\n'
550 for command in all_commands:
551 try:
552 args, desc = SUBCOMMAND_HELP[command]
553 except KeyError:
554 continue
556 wrapped_desc = wrap(desc, 50)
557 print ' %-20s %-50s' % (command, wrapped_desc[0])
558 for line in wrapped_desc[1:]:
559 print ' ' * 22 + line
561 print
562 print USAGE_FOOTER
564 def _usage(cmd):
565 """ Print help usage information """
566 if cmd:
567 cmdHelp(cmd)
568 else:
569 shortHelp()
571 def usage(cmd = None):
572 """ Print help usage information and exits """
573 _usage(cmd)
574 sys.exit(1)
577 ####################################################################
578 #
579 # Utility functions
580 #
581 ####################################################################
583 def get_default_SR():
584 return [sr_ref
585 for sr_ref in server.xenapi.SR.get_all()
586 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
588 def get_default_Network():
589 return [network_ref
590 for network_ref in server.xenapi.network.get_all()][0]
592 class XenAPIUnsupportedException(Exception):
593 pass
595 def xenapi_unsupported():
596 if serverType == SERVER_XEN_API:
597 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
599 def xenapi_only():
600 if serverType != SERVER_XEN_API:
601 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
603 def map2sxp(m):
604 return [[k, m[k]] for k in m.keys()]
606 def arg_check(args, name, lo, hi = -1):
607 n = len([i for i in args if i != '--'])
609 if hi == -1:
610 if n != lo:
611 err("'xm %s' requires %d argument%s.\n" % (name, lo,
612 lo == 1 and '' or 's'))
613 usage(name)
614 else:
615 if n < lo or n > hi:
616 err("'xm %s' requires between %d and %d arguments.\n" %
617 (name, lo, hi))
618 usage(name)
621 def unit(c):
622 if not c.isalpha():
623 return 0
624 base = 1
625 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
626 elif c == 'M' or c == 'm': base = 1024 * 1024
627 elif c == 'K' or c == 'k': base = 1024
628 else:
629 print 'ignoring unknown unit'
630 return base
632 def int_unit(str, dest):
633 base = unit(str[-1])
634 if not base:
635 return int(str)
637 value = int(str[:-1])
638 dst_base = unit(dest)
639 if dst_base == 0:
640 dst_base = 1
641 if dst_base > base:
642 return value / (dst_base / base)
643 else:
644 return value * (base / dst_base)
646 def err(msg):
647 print >>sys.stderr, "Error:", msg
650 def get_single_vm(dom):
651 if serverType == SERVER_XEN_API:
652 uuids = server.xenapi.VM.get_by_name_label(dom)
653 if len(uuids) > 0:
654 return uuids[0]
656 refs = []
658 try:
659 domid = int(dom)
660 refs = [vm_ref
661 for vm_ref in server.xenapi.VM.get_all()
662 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
663 except:
664 pass
666 if len(refs) > 0:
667 return refs[0]
669 raise OptionError("Domain '%s' not found." % dom)
670 else:
671 dominfo = server.xend.domain(dom, False)
672 return dominfo['uuid']
674 ##
675 #
676 # Xen-API Shell
677 #
678 ##
680 class Shell(cmd.Cmd):
681 def __init__(self):
682 cmd.Cmd.__init__(self)
683 self.prompt = "xm> "
684 if serverType == SERVER_XEN_API:
685 try:
686 res = server.xenapi.host.list_methods()
687 for f in res:
688 setattr(Shell, 'do_' + f + ' ', self.default)
689 except:
690 pass
692 def preloop(self):
693 cmd.Cmd.preloop(self)
694 try:
695 import readline
696 readline.set_completer_delims(' ')
697 except ImportError:
698 pass
700 def default(self, line):
701 words = shlex.split(line)
702 if len(words) > 0 and words[0] == 'xm':
703 words = words[1:]
704 if len(words) > 0:
705 cmd = xm_lookup_cmd(words[0])
706 if cmd:
707 _run_cmd(cmd, words[0], words[1:])
708 elif serverType == SERVER_XEN_API:
709 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
710 tuple(x)),
711 words[0], words[1:])
712 if ok and res is not None and res != '':
713 pprint.pprint(res)
714 else:
715 print '*** Unknown command: %s' % words[0]
716 return False
718 def completedefault(self, text, line, begidx, endidx):
719 words = shlex.split(line[:begidx])
720 clas, func = words[0].split('.')
721 if len(words) > 1 or \
722 func.startswith('get_by_') or \
723 func == 'get_all':
724 return []
725 uuids = server.xenapi_request('%s.get_all' % clas, ())
726 return [u + " " for u in uuids if u.startswith(text)]
728 def emptyline(self):
729 pass
731 def do_EOF(self, line):
732 print
733 sys.exit(0)
735 def do_help(self, line):
736 _usage(line)
739 def xm_shell(args):
740 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
743 def xm_event_monitor(args):
744 if serverType == SERVER_XEN_API:
745 while True:
746 server.xenapi.event.register(args)
747 events = server.xenapi.event.next()
748 for e in events:
749 print e
750 else:
751 err("Event monitoring not supported unless using Xen-API.")
754 #########################################################################
755 #
756 # Main xm functions
757 #
758 #########################################################################
760 def xm_save(args):
762 arg_check(args, "save", 2, 3)
764 try:
765 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
766 except getopt.GetoptError, opterr:
767 err(opterr)
768 usage('save')
770 checkpoint = False
771 for (k, v) in options:
772 if k in ['-c', '--checkpoint']:
773 checkpoint = True
775 if len(params) != 2:
776 err("Wrong number of parameters")
777 usage('save')
779 dom = params[0]
780 savefile = os.path.abspath(params[1])
782 if not os.access(os.path.dirname(savefile), os.W_OK):
783 err("xm save: Unable to create file %s" % savefile)
784 sys.exit(1)
786 if serverType == SERVER_XEN_API:
787 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
788 else:
789 server.xend.domain.save(dom, savefile, checkpoint)
791 def xm_restore(args):
792 arg_check(args, "restore", 1, 2)
794 try:
795 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
796 except getopt.GetoptError, opterr:
797 err(opterr)
798 usage('restore')
800 paused = False
801 for (k, v) in options:
802 if k in ['-p', '--paused']:
803 paused = True
805 if len(params) != 1:
806 err("Wrong number of parameters")
807 usage('restore')
809 savefile = os.path.abspath(params[0])
811 if not os.access(savefile, os.R_OK):
812 err("xm restore: Unable to read file %s" % savefile)
813 sys.exit(1)
815 if serverType == SERVER_XEN_API:
816 server.xenapi.VM.restore(savefile, paused)
817 else:
818 server.xend.domain.restore(savefile, paused)
821 def datetime_to_secs(v):
822 unwanted = ":-."
823 for c in unwanted:
824 v = str(v).replace(c, "")
825 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
827 def getDomains(domain_names, state, full = 0):
828 if serverType == SERVER_XEN_API:
829 doms_sxp = []
830 doms_dict = []
832 dom_recs = server.xenapi.VM.get_all_records()
833 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
835 for dom_ref, dom_rec in dom_recs.items():
836 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
838 states = ('running', 'blocked', 'paused', 'shutdown',
839 'crashed', 'dying')
840 def state_on_off(state):
841 if state in dom_metrics_rec['state']:
842 return state[0]
843 else:
844 return "-"
845 state_str = "".join([state_on_off(state)
846 for state in states])
848 dom_rec.update({'name': dom_rec['name_label'],
849 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
850 'vcpus': dom_metrics_rec['VCPUs_number'],
851 'state': state_str,
852 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
853 'start_time': datetime_to_secs(
854 dom_metrics_rec['start_time'])})
856 doms_sxp.append(['domain'] + map2sxp(dom_rec))
857 doms_dict.append(dom_rec)
859 if domain_names:
860 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
861 if dom["name"] in domain_names]
863 if len(doms) > 0:
864 return doms
865 else:
866 print "Error: no domain%s named %s" % \
867 (len(domain_names) > 1 and 's' or '',
868 ', '.join(domain_names))
869 sys.exit(-1)
870 else:
871 return doms_sxp
872 else:
873 if domain_names:
874 return [server.xend.domain(dom, full) for dom in domain_names]
875 else:
876 return server.xend.domains_with_state(True, state, full)
879 def xm_list(args):
880 use_long = 0
881 show_vcpus = 0
882 show_labels = 0
883 state = 'all'
884 try:
885 (options, params) = getopt.gnu_getopt(args, 'lv',
886 ['long','vcpus','label',
887 'state='])
888 except getopt.GetoptError, opterr:
889 err(opterr)
890 usage('list')
892 for (k, v) in options:
893 if k in ['-l', '--long']:
894 use_long = 1
895 if k in ['-v', '--vcpus']:
896 show_vcpus = 1
897 if k in ['--label']:
898 show_labels = 1
899 if k in ['--state']:
900 state = v
902 if state != 'all' and len(params) > 0:
903 raise OptionError(
904 "You may specify either a state or a particular VM, but not both")
906 if show_vcpus:
907 print >>sys.stderr, (
908 "xm list -v is deprecated. Please use xm vcpu-list.")
909 xm_vcpu_list(params)
910 return
912 doms = getDomains(params, state, use_long)
914 if use_long:
915 map(PrettyPrint.prettyprint, doms)
916 elif show_labels:
917 xm_label_list(doms)
918 else:
919 xm_brief_list(doms)
922 def parse_doms_info(info):
923 def get_info(n, t, d):
924 return t(sxp.child_value(info, n, d))
926 def get_status(n, t, d):
927 return DOM_STATES[t(sxp.child_value(info, n, d))]
929 start_time = get_info('start_time', float, -1)
930 if start_time == -1:
931 up_time = float(-1)
932 else:
933 up_time = time.time() - start_time
935 parsed_info = {
936 'domid' : get_info('domid', str, ''),
937 'name' : get_info('name', str, '??'),
938 'state' : get_info('state', str, ''),
940 # VCPUs is the number online when the VM is up, or the number
941 # configured otherwise.
942 'vcpus' : get_info('online_vcpus', int,
943 get_info('vcpus', int, 0)),
944 'up_time' : up_time
945 }
947 security_label = get_info('security_label', str, '')
948 parsed_info['seclabel'] = security.parse_security_label(security_label)
950 if serverType == SERVER_XEN_API:
951 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
952 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
953 if sum(cpu_times.values()) > 0:
954 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
955 else:
956 parsed_info['cpu_time'] = 0
957 else:
958 parsed_info['mem'] = get_info('memory', int,0)
959 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
961 return parsed_info
963 def check_sched_type(sched):
964 if serverType == SERVER_XEN_API:
965 current = server.xenapi.host.get_sched_policy(
966 server.xenapi.session.get_this_host(server.getSession()))
967 else:
968 current = 'unknown'
969 for x in server.xend.node.info()[1:]:
970 if len(x) > 1 and x[0] == 'xen_scheduler':
971 current = x[1]
972 break
973 if sched != current:
974 err("Xen is running with the %s scheduler" % current)
975 sys.exit(1)
977 def parse_sedf_info(info):
978 def get_info(n, t, d):
979 return t(sxp.child_value(info, n, d))
981 return {
982 'domid' : get_info('domid', int, -1),
983 'period' : get_info('period', int, -1),
984 'slice' : get_info('slice', int, -1),
985 'latency' : get_info('latency', int, -1),
986 'extratime': get_info('extratime', int, -1),
987 'weight' : get_info('weight', int, -1),
988 }
990 def domid_match(domid, info):
991 return domid is None or domid == info['name'] or \
992 domid == str(info['domid'])
994 def xm_brief_list(doms):
995 print '%-40s %5s %5s %5s %10s %9s' % \
996 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
998 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
999 "%(cpu_time)8.1f"
1001 for dom in doms:
1002 d = parse_doms_info(dom)
1003 print format % d
1005 def xm_label_list(doms):
1006 print '%-40s %5s %5s %5s %10s %9s %-10s' % \
1007 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
1009 output = []
1010 format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
1011 '%(cpu_time)8.1f %(seclabel)10s'
1013 for dom in doms:
1014 d = parse_doms_info(dom)
1015 if d['seclabel'] == "" and serverType != SERVER_XEN_API:
1016 seclab = server.xend.security.get_domain_label(d['name'])
1017 if len(seclab) > 0 and seclab[0] == '\'':
1018 seclab = seclab[1:]
1019 d['seclabel'] = seclab
1020 output.append((format % d, d['seclabel']))
1022 #sort by labels
1023 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
1024 for line, label in output:
1025 print line
1028 def xm_vcpu_list(args):
1029 if serverType == SERVER_XEN_API:
1030 if args:
1031 vm_refs = map(get_single_vm, args)
1032 else:
1033 vm_refs = server.xenapi.VM.get_all()
1035 vm_records = dict(map(lambda vm_ref:
1036 (vm_ref, server.xenapi.VM.get_record(
1037 vm_ref)),
1038 vm_refs))
1040 vm_metrics = dict(map(lambda (ref, record):
1041 (ref,
1042 server.xenapi.VM_metrics.get_record(
1043 record['metrics'])),
1044 vm_records.items()))
1046 dominfo = []
1048 # vcpu_list doesn't list 'managed' domains
1049 # when they are not running, so filter them out
1051 vm_refs = [vm_ref
1052 for vm_ref in vm_refs
1053 if vm_records[vm_ref]["power_state"] != "Halted"]
1055 for vm_ref in vm_refs:
1056 info = ['domain',
1057 ['domid', vm_records[vm_ref]['domid']],
1058 ['name', vm_records[vm_ref]['name_label']],
1059 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
1061 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
1062 def chk_flag(flag):
1063 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1064 and 1 or 0
1066 vcpu_info = ['vcpu',
1067 ['number',
1068 i],
1069 ['online',
1070 chk_flag("online")],
1071 ['blocked',
1072 chk_flag("blocked")],
1073 ['running',
1074 chk_flag("running")],
1075 ['cpu_time',
1076 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1077 ['cpu',
1078 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1079 ['cpumap',
1080 vm_metrics[vm_ref]['VCPUs_params']\
1081 ['cpumap%i' % i].split(",")]]
1083 info.append(vcpu_info)
1085 dominfo.append(info)
1086 else:
1087 if args:
1088 dominfo = map(server.xend.domain.getVCPUInfo, args)
1089 else:
1090 doms = server.xend.domains_with_state(False, 'all', False)
1091 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1093 print '%-32s %5s %5s %5s %5s %9s %s' % \
1094 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1096 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1097 ' %(cpu_time)8.1f %(cpumap)s'
1099 for dom in dominfo:
1100 def get_info(n):
1101 return sxp.child_value(dom, n)
1104 # convert a list of integers into a list of pairs indicating
1105 # continuous sequences in the list:
1107 # [0,1,2,3] -> [(0,3)]
1108 # [1,2,4,5] -> [(1,2),(4,5)]
1109 # [0] -> [(0,0)]
1110 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1112 def list_to_rangepairs(cmap):
1113 cmap.sort()
1114 pairs = []
1115 x = y = 0
1116 for i in range(0,len(cmap)):
1117 try:
1118 if ((cmap[y+1] - cmap[i]) > 1):
1119 pairs.append((cmap[x],cmap[y]))
1120 x = y = i+1
1121 else:
1122 y = y + 1
1123 # if we go off the end, then just add x to y
1124 except IndexError:
1125 pairs.append((cmap[x],cmap[y]))
1127 return pairs
1130 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1132 def format_pairs(pairs):
1133 if not pairs:
1134 return "no cpus"
1135 out = ""
1136 for f,s in pairs:
1137 if (f==s):
1138 out += '%d'%f
1139 else:
1140 out += '%d-%d'%(f,s)
1141 out += ','
1142 # trim trailing ','
1143 return out[:-1]
1145 def format_cpumap(cpumap):
1146 cpumap = map(lambda x: int(x), cpumap)
1147 cpumap.sort()
1149 if serverType == SERVER_XEN_API:
1150 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1151 server.xenapi.session.get_this_host(server.getSession())))
1152 else:
1153 for x in server.xend.node.info()[1:]:
1154 if len(x) > 1 and x[0] == 'nr_cpus':
1155 nr_cpus = int(x[1])
1157 # normalize cpumap by modulus nr_cpus, and drop duplicates
1158 cpumap = dict.fromkeys(
1159 filter(lambda x: x < nr_cpus, cpumap)).keys()
1160 if len(cpumap) == nr_cpus:
1161 return "any cpu"
1163 return format_pairs(list_to_rangepairs(cpumap))
1165 name = get_info('name')
1166 domid = get_info('domid')
1167 if domid is not None:
1168 domid = str(domid)
1169 else:
1170 domid = ''
1172 for vcpu in sxp.children(dom, 'vcpu'):
1173 def vinfo(n, t):
1174 return t(sxp.child_value(vcpu, n))
1176 number = vinfo('number', int)
1177 cpu = vinfo('cpu', int)
1178 cpumap = format_cpumap(vinfo('cpumap', list))
1179 online = vinfo('online', int)
1180 cpu_time = vinfo('cpu_time', float)
1181 running = vinfo('running', int)
1182 blocked = vinfo('blocked', int)
1184 if cpu < 0:
1185 c = ''
1186 s = ''
1187 elif online:
1188 c = str(cpu)
1189 if running:
1190 s = 'r'
1191 else:
1192 s = '-'
1193 if blocked:
1194 s += 'b'
1195 else:
1196 s += '-'
1197 s += '-'
1198 else:
1199 c = '-'
1200 s = '--p'
1202 print format % locals()
1204 def start_do_console(domain_name):
1205 cpid = os.fork()
1206 if cpid != 0:
1207 for i in range(10):
1208 # Catch failure of the create process
1209 time.sleep(1)
1210 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1211 if os.WIFEXITED(rv):
1212 if os.WEXITSTATUS(rv) != 0:
1213 sys.exit(os.WEXITSTATUS(rv))
1214 try:
1215 # Acquire the console of the created dom
1216 if serverType == SERVER_XEN_API:
1217 domid = server.xenapi.VM.get_domid(
1218 get_single_vm(domain_name))
1219 else:
1220 dom = server.xend.domain(domain_name)
1221 domid = int(sxp.child_value(dom, 'domid', '-1'))
1222 console.execConsole(domid)
1223 except:
1224 pass
1225 print("Could not start console\n");
1226 sys.exit(0)
1228 def xm_start(args):
1230 paused = False
1231 console_autoconnect = False
1232 vncviewer = False
1233 vncviewer_autopass = False
1235 try:
1236 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused','vncviewer','vncviewer-autopass'])
1237 for (k, v) in options:
1238 if k in ('-p', '--paused'):
1239 paused = True
1240 if k in ('-c', '--console_autoconnect'):
1241 console_autoconnect = True
1242 if k in ('--vncviewer'):
1243 vncviewer = True
1244 if k in ('--vncviewer-autopass'):
1245 vncviewer_autopass = True
1247 if len(params) != 1:
1248 raise OptionError("Expects 1 argument")
1249 except getopt.GetoptError, opterr:
1250 err(opterr)
1251 usage('start')
1253 dom = params[0]
1255 if console_autoconnect:
1256 start_do_console(dom)
1258 try:
1259 if serverType == SERVER_XEN_API:
1260 server.xenapi.VM.start(get_single_vm(dom), paused)
1261 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1262 else:
1263 server.xend.domain.start(dom, paused)
1264 info = server.xend.domain(dom)
1265 domid = int(sxp.child_value(info, 'domid', '-1'))
1266 except:
1267 raise
1269 if domid == -1:
1270 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1272 if vncviewer:
1273 console.runVncViewer(domid, vncviewer_autopass, True)
1276 def xm_delete(args):
1277 arg_check(args, "delete", 1)
1278 dom = args[0]
1279 if serverType == SERVER_XEN_API:
1280 server.xenapi.VM.destroy(get_single_vm(dom))
1281 else:
1282 server.xend.domain.delete(dom)
1284 def xm_suspend(args):
1285 arg_check(args, "suspend", 1)
1286 dom = args[0]
1287 if serverType == SERVER_XEN_API:
1288 server.xenapi.VM.suspend(get_single_vm(dom))
1289 else:
1290 server.xend.domain.suspend(dom)
1292 def xm_resume(args):
1293 arg_check(args, "resume", 1, 2)
1295 try:
1296 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1297 except getopt.GetoptError, opterr:
1298 err(opterr)
1299 usage('resume')
1301 paused = False
1302 for (k, v) in options:
1303 if k in ['-p', '--paused']:
1304 paused = True
1306 if len(params) != 1:
1307 err("Wrong number of parameters")
1308 usage('resume')
1310 dom = params[0]
1311 if serverType == SERVER_XEN_API:
1312 server.xenapi.VM.resume(get_single_vm(dom), paused)
1313 else:
1314 server.xend.domain.resume(dom, paused)
1316 def xm_reboot(args):
1317 arg_check(args, "reboot", 1, 3)
1318 from xen.xm import shutdown
1319 shutdown.main(["shutdown", "-R"] + args)
1321 def xm_shutdown(args):
1322 arg_check(args, "shutdown", 1, 4)
1323 from xen.xm import shutdown
1324 shutdown.main(["shutdown"] + args)
1326 def xm_reset(args):
1327 arg_check(args, "reset", 1)
1328 dom = args[0]
1330 if serverType == SERVER_XEN_API:
1331 server.xenapi.VM.hard_reboot(get_single_vm(dom))
1332 else:
1333 server.xend.domain.reset(dom)
1335 def xm_pause(args):
1336 arg_check(args, "pause", 1)
1337 dom = args[0]
1339 if serverType == SERVER_XEN_API:
1340 server.xenapi.VM.pause(get_single_vm(dom))
1341 else:
1342 server.xend.domain.pause(dom)
1344 def xm_unpause(args):
1345 arg_check(args, "unpause", 1)
1346 dom = args[0]
1348 if serverType == SERVER_XEN_API:
1349 server.xenapi.VM.unpause(get_single_vm(dom))
1350 else:
1351 server.xend.domain.unpause(dom)
1353 def xm_dump_core(args):
1354 live = False
1355 crash = False
1356 reset = False
1357 try:
1358 (options, params) = getopt.gnu_getopt(args, 'LCR', ['live', 'crash', 'reset'])
1359 for (k, v) in options:
1360 if k in ('-L', '--live'):
1361 live = True
1362 elif k in ('-C', '--crash'):
1363 crash = True
1364 elif k in ('-R', '--reset'):
1365 reset = True
1367 if crash and reset:
1368 raise OptionError("You may not specify more than one '-CR' option")
1369 if len(params) not in (1, 2):
1370 raise OptionError("Expects 1 or 2 argument(s)")
1371 except getopt.GetoptError, e:
1372 raise OptionError(str(e))
1374 dom = params[0]
1375 if len(params) == 2:
1376 filename = os.path.abspath(params[1])
1377 else:
1378 filename = None
1380 print "Dumping core of domain: %s ..." % str(dom)
1381 server.xend.domain.dump(dom, filename, live, crash, reset)
1383 def xm_rename(args):
1384 arg_check(args, "rename", 2)
1386 if serverType == SERVER_XEN_API:
1387 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1388 else:
1389 server.xend.domain.setName(args[0], args[1])
1391 def xm_importcommand(command, args):
1392 cmd = __import__(command, globals(), locals(), 'xen.xm')
1393 cmd.main([command] + args)
1396 #############################################################
1398 def xm_vcpu_pin(args):
1399 arg_check(args, "vcpu-pin", 3)
1401 def cpu_make_map(cpulist):
1402 cpus = []
1403 for c in cpulist.split(','):
1404 if c.find('-') != -1:
1405 (x,y) = c.split('-')
1406 for i in range(int(x),int(y)+1):
1407 cpus.append(int(i))
1408 else:
1409 # remove this element from the list
1410 if c[0] == '^':
1411 cpus = [x for x in cpus if x != int(c[1:])]
1412 else:
1413 cpus.append(int(c))
1414 cpus.sort()
1415 return ",".join(map(str, cpus))
1417 dom = args[0]
1418 vcpu = args[1]
1419 if args[2] == 'all':
1420 cpumap = cpu_make_map('0-63')
1421 else:
1422 cpumap = cpu_make_map(args[2])
1424 if serverType == SERVER_XEN_API:
1425 server.xenapi.VM.add_to_VCPUs_params_live(
1426 get_single_vm(dom), "cpumap%i" % int(vcpu), cpumap)
1427 else:
1428 server.xend.domain.pincpu(dom, vcpu, cpumap)
1430 def xm_mem_max(args):
1431 arg_check(args, "mem-max", 2)
1433 dom = args[0]
1435 if serverType == SERVER_XEN_API:
1436 mem = int_unit(args[1], 'k') * 1024
1437 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1438 else:
1439 mem = int_unit(args[1], 'm')
1440 server.xend.domain.maxmem_set(dom, mem)
1442 def xm_mem_set(args):
1443 arg_check(args, "mem-set", 2)
1445 dom = args[0]
1447 if serverType == SERVER_XEN_API:
1448 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1449 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1450 mem_target)
1451 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1452 mem_target)
1453 else:
1454 mem_target = int_unit(args[1], 'm')
1455 server.xend.domain.setMemoryTarget(dom, mem_target)
1457 def xm_vcpu_set(args):
1458 arg_check(args, "vcpu-set", 2)
1460 dom = args[0]
1461 vcpus = int(args[1])
1463 if serverType == SERVER_XEN_API:
1464 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1465 else:
1466 server.xend.domain.setVCpuCount(dom, vcpus)
1468 def xm_destroy(args):
1469 arg_check(args, "destroy", 1)
1471 dom = args[0]
1473 if serverType == SERVER_XEN_API:
1474 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1475 else:
1476 server.xend.domain.destroy(dom)
1478 def xm_domid(args):
1479 arg_check(args, "domid", 1)
1481 name = args[0]
1483 if serverType == SERVER_XEN_API:
1484 print server.xenapi.VM.get_domid(get_single_vm(name))
1485 else:
1486 dom = server.xend.domain(name)
1487 print sxp.child_value(dom, 'domid')
1489 def xm_domname(args):
1490 arg_check(args, "domname", 1)
1492 name = args[0]
1494 if serverType == SERVER_XEN_API:
1495 print server.xenapi.VM.get_name_label(get_single_vm(name))
1496 else:
1497 dom = server.xend.domain(name)
1498 print sxp.child_value(dom, 'name')
1500 def xm_sched_sedf(args):
1501 xenapi_unsupported()
1503 def ns_to_ms(val):
1504 return float(val) * 0.000001
1506 def ms_to_ns(val):
1507 return (float(val) / 0.000001)
1509 def print_sedf(info):
1510 info['period'] = ns_to_ms(info['period'])
1511 info['slice'] = ns_to_ms(info['slice'])
1512 info['latency'] = ns_to_ms(info['latency'])
1513 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1514 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1516 check_sched_type('sedf')
1518 # we want to just display current info if no parameters are passed
1519 if len(args) == 0:
1520 domid = None
1521 else:
1522 # we expect at least a domain id (name or number)
1523 # and at most a domid up to 5 options with values
1524 arg_check(args, "sched-sedf", 1, 11)
1525 domid = args[0]
1526 # drop domid from args since get_opt doesn't recognize it
1527 args = args[1:]
1529 opts = {}
1530 try:
1531 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1532 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1533 except getopt.GetoptError, opterr:
1534 err(opterr)
1535 usage('sched-sedf')
1537 # convert to nanoseconds if needed
1538 for (k, v) in options:
1539 if k in ['-p', '--period']:
1540 opts['period'] = ms_to_ns(v)
1541 elif k in ['-s', '--slice']:
1542 opts['slice'] = ms_to_ns(v)
1543 elif k in ['-l', '--latency']:
1544 opts['latency'] = ms_to_ns(v)
1545 elif k in ['-e', '--extratime']:
1546 opts['extratime'] = v
1547 elif k in ['-w', '--weight']:
1548 opts['weight'] = v
1550 doms = filter(lambda x : domid_match(domid, x),
1551 [parse_doms_info(dom)
1552 for dom in getDomains(None, 'running')])
1553 if domid is not None and doms == []:
1554 err("Domain '%s' does not exist." % domid)
1555 usage('sched-sedf')
1557 # print header if we aren't setting any parameters
1558 if len(opts.keys()) == 0:
1559 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1560 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1561 'Extra','Weight')
1563 for d in doms:
1564 # fetch current values so as not to clobber them
1565 try:
1566 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1567 except xmlrpclib.Fault:
1568 # domain does not support sched-sedf?
1569 sedf_raw = {}
1571 sedf_info = parse_sedf_info(sedf_raw)
1572 sedf_info['name'] = d['name']
1573 # update values in case of call to set
1574 if len(opts.keys()) > 0:
1575 for k in opts.keys():
1576 sedf_info[k]=opts[k]
1578 # send the update, converting user input
1579 v = map(int, [sedf_info['period'], sedf_info['slice'],
1580 sedf_info['latency'],sedf_info['extratime'],
1581 sedf_info['weight']])
1582 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1583 if int(rv) != 0:
1584 err("Failed to set sedf parameters (rv=%d)."%(rv))
1586 # not setting values, display info
1587 else:
1588 print_sedf(sedf_info)
1590 def xm_sched_credit(args):
1591 """Get/Set options for Credit Scheduler."""
1593 check_sched_type('credit')
1595 try:
1596 opts, params = getopt.getopt(args, "d:w:c:",
1597 ["domain=", "weight=", "cap="])
1598 except getopt.GetoptError, opterr:
1599 err(opterr)
1600 usage('sched-credit')
1602 domid = None
1603 weight = None
1604 cap = None
1606 for o, a in opts:
1607 if o in ["-d", "--domain"]:
1608 domid = a
1609 elif o in ["-w", "--weight"]:
1610 weight = int(a)
1611 elif o in ["-c", "--cap"]:
1612 cap = int(a);
1614 doms = filter(lambda x : domid_match(domid, x),
1615 [parse_doms_info(dom)
1616 for dom in getDomains(None, 'all')])
1618 if weight is None and cap is None:
1619 if domid is not None and doms == []:
1620 err("Domain '%s' does not exist." % domid)
1621 usage('sched-credit')
1622 # print header if we aren't setting any parameters
1623 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1625 for d in doms:
1626 try:
1627 if serverType == SERVER_XEN_API:
1628 info = server.xenapi.VM_metrics.get_VCPUs_params(
1629 server.xenapi.VM.get_metrics(
1630 get_single_vm(d['name'])))
1631 else:
1632 info = server.xend.domain.sched_credit_get(d['name'])
1633 except xmlrpclib.Fault:
1634 pass
1636 if 'weight' not in info or 'cap' not in info:
1637 # domain does not support sched-credit?
1638 info = {'weight': -1, 'cap': -1}
1640 info['weight'] = int(info['weight'])
1641 info['cap'] = int(info['cap'])
1643 info['name'] = d['name']
1644 info['domid'] = str(d['domid'])
1645 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1646 else:
1647 if domid is None:
1648 # place holder for system-wide scheduler parameters
1649 err("No domain given.")
1650 usage('sched-credit')
1652 if serverType == SERVER_XEN_API:
1653 if doms[0]['domid']:
1654 server.xenapi.VM.add_to_VCPUs_params_live(
1655 get_single_vm(domid),
1656 "weight",
1657 weight)
1658 server.xenapi.VM.add_to_VCPUs_params_live(
1659 get_single_vm(domid),
1660 "cap",
1661 cap)
1662 else:
1663 server.xenapi.VM.add_to_VCPUs_params(
1664 get_single_vm(domid),
1665 "weight",
1666 weight)
1667 server.xenapi.VM.add_to_VCPUs_params(
1668 get_single_vm(domid),
1669 "cap",
1670 cap)
1671 else:
1672 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1673 if result != 0:
1674 err(str(result))
1676 def xm_info(args):
1677 arg_check(args, "info", 0, 1)
1679 try:
1680 (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
1681 except getopt.GetoptError, opterr:
1682 err(opterr)
1683 usage('info')
1685 show_xend_config = 0
1686 for (k, v) in options:
1687 if k in ['-c', '--config']:
1688 show_xend_config = 1
1690 if show_xend_config:
1691 for name, obj in inspect.getmembers(xoptions):
1692 if not inspect.ismethod(obj):
1693 if name == "config":
1694 for x in obj[1:]:
1695 if len(x) < 2:
1696 print "%-38s: (none)" % x[0]
1697 else:
1698 print "%-38s:" % x[0], x[1]
1699 else:
1700 print "%-38s:" % name, obj
1701 return
1703 if serverType == SERVER_XEN_API:
1705 # Need to fake out old style xm info as people rely on parsing it
1707 host_record = server.xenapi.host.get_record(
1708 server.xenapi.session.get_this_host(server.getSession()))
1710 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1712 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1714 def getVal(keys, default=""):
1715 data = host_record
1716 for key in keys:
1717 if key in data:
1718 data = data[key]
1719 else:
1720 return default
1721 return data
1723 def getCpuMhz():
1724 cpu_speeds = [int(host_cpu_record["speed"])
1725 for host_cpu_record in host_cpu_records
1726 if "speed" in host_cpu_record]
1727 if len(cpu_speeds) > 0:
1728 return sum(cpu_speeds) / len(cpu_speeds)
1729 else:
1730 return 0
1732 getCpuMhz()
1734 def getCpuFeatures():
1735 if len(host_cpu_records) > 0:
1736 return host_cpu_records[0].get("features", "")
1737 else:
1738 return ""
1740 info = {
1741 "host": getVal(["name_label"]),
1742 "release": getVal(["software_version", "release"]),
1743 "version": getVal(["software_version", "version"]),
1744 "machine": getVal(["software_version", "machine"]),
1745 "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
1746 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1747 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1748 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1749 "cpu_mhz": getCpuMhz(),
1750 "hw_caps": getCpuFeatures(),
1751 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1752 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1753 "xen_major": getVal(["software_version", "xen_major"]),
1754 "xen_minor": getVal(["software_version", "xen_minor"]),
1755 "xen_extra": getVal(["software_version", "xen_extra"]),
1756 "xen_caps": " ".join(getVal(["capabilities"], [])),
1757 "xen_scheduler": getVal(["sched_policy"]),
1758 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1759 "platform_params": getVal(["other_config", "platform_params"]),
1760 "xen_commandline": getVal(["other_config", "xen_commandline"]),
1761 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1762 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1763 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1764 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1765 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1766 "xend_config_format":getVal(["software_version", "xend_config_format"])
1769 sorted = info.items()
1770 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1772 for (k, v) in sorted:
1773 print "%-23s:" % k, v
1774 else:
1775 info = server.xend.node.info()
1776 for x in info[1:]:
1777 if len(x) < 2:
1778 print "%-23s: (none)" % x[0]
1779 else:
1780 print "%-23s:" % x[0], x[1]
1782 def xm_console(args):
1783 arg_check(args, "console", 1, 3)
1785 num = 0
1786 quiet = False;
1788 try:
1789 (options, params) = getopt.gnu_getopt(args, 'qn:', ['quiet', 'num'])
1790 except getopt.GetoptError, opterr:
1791 err(opterr)
1792 usage('console')
1794 for (k, v) in options:
1795 if k in ['-q', '--quiet']:
1796 quiet = True
1797 elif k in ['-n', '--num']:
1798 num = int(v[0])
1799 else:
1800 assert False
1802 if len(params) != 1:
1803 err('No domain given')
1804 usage('console')
1806 dom = params[0]
1808 try:
1809 if serverType == SERVER_XEN_API:
1810 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1811 else:
1812 info = server.xend.domain(dom)
1813 domid = int(sxp.child_value(info, 'domid', '-1'))
1814 except:
1815 if quiet:
1816 sys.exit(1)
1817 else:
1818 raise
1820 if domid == -1:
1821 if quiet:
1822 sys.exit(1)
1823 else:
1824 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1826 console.execConsole(domid, num)
1829 def domain_name_to_domid(domain_name):
1830 if serverType == SERVER_XEN_API:
1831 domid = server.xenapi.VM.get_domid(
1832 get_single_vm(domain_name))
1833 else:
1834 dom = server.xend.domain(domain_name)
1835 domid = int(sxp.child_value(dom, 'domid', '-1'))
1836 return int(domid)
1838 def xm_vncviewer(args):
1839 autopass = False;
1841 try:
1842 (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass'])
1843 except getopt.GetoptError, opterr:
1844 err(opterr)
1845 usage('vncviewer')
1847 for (k, v) in options:
1848 if k in ['--autopass','--vncviewer-autopass']:
1849 autopass = True
1850 else:
1851 assert False
1853 if len(params) != 1:
1854 err('No domain given (or several parameters specified)')
1855 usage('vncviewer')
1857 dom = params[0]
1858 domid = domain_name_to_domid(dom)
1860 console.runVncViewer(domid, autopass)
1863 def xm_uptime(args):
1864 short_mode = 0
1866 try:
1867 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1868 except getopt.GetoptError, opterr:
1869 err(opterr)
1870 usage('uptime')
1872 for (k, v) in options:
1873 if k in ['-s', '--short']:
1874 short_mode = 1
1876 doms = getDomains(params, 'all')
1878 if short_mode == 0:
1879 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1881 for dom in doms:
1882 d = parse_doms_info(dom)
1883 if d['domid'] == '':
1884 uptime = 0
1885 elif int(d['domid']) > 0:
1886 uptime = int(round(d['up_time']))
1887 else:
1888 f=open('/proc/uptime', 'r')
1889 upfile = f.read()
1890 uptime = int(round(float(upfile.split(' ')[0])))
1891 f.close()
1893 days = int(uptime / 86400)
1894 uptime -= (days * 86400)
1895 hours = int(uptime / 3600)
1896 uptime -= (hours * 3600)
1897 minutes = int(uptime / 60)
1898 uptime -= (minutes * 60)
1899 seconds = uptime
1901 upstring = ""
1902 if days > 0:
1903 upstring += str(days) + " day"
1904 if days > 1:
1905 upstring += "s"
1906 upstring += ", "
1907 upstring += '%(hours)2d:%(minutes)02d' % vars()
1909 if short_mode:
1910 now = datetime.datetime.now()
1911 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1912 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1913 else:
1914 upstring += ':%(seconds)02d' % vars()
1915 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1917 print upstring
1919 def xm_sysrq(args):
1920 arg_check(args, "sysrq", 2)
1921 dom = args[0]
1922 req = args[1]
1923 if serverType == SERVER_XEN_API:
1924 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1925 else:
1926 server.xend.domain.send_sysrq(dom, req)
1928 def xm_trigger(args):
1929 vcpu = 0
1931 arg_check(args, "trigger", 2, 3)
1932 dom = args[0]
1933 trigger = args[1]
1934 if len(args) == 3:
1935 vcpu = int(args[2])
1937 if serverType == SERVER_XEN_API:
1938 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1939 else:
1940 server.xend.domain.send_trigger(dom, trigger, vcpu)
1942 def xm_debug_keys(args):
1943 arg_check(args, "debug-keys", 1)
1945 keys = str(args[0])
1947 if serverType == SERVER_XEN_API:
1948 server.xenapi.host.send_debug_keys(
1949 server.xenapi.session.get_this_host(server.getSession()),
1950 keys)
1951 else:
1952 server.xend.node.send_debug_keys(keys)
1954 def xm_top(args):
1955 arg_check(args, "top", 0)
1957 os.system('xentop')
1959 def xm_dmesg(args):
1960 arg_check(args, "dmesg", 0, 1)
1962 try:
1963 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1964 except getopt.GetoptError, opterr:
1965 err(opterr)
1966 usage('dmesg')
1968 use_clear = 0
1969 for (k, v) in options:
1970 if k in ['-c', '--clear']:
1971 use_clear = 1
1973 if len(params) :
1974 err("No parameter required")
1975 usage('dmesg')
1977 if serverType == SERVER_XEN_API:
1978 host = server.xenapi.session.get_this_host(server.getSession())
1979 if use_clear:
1980 print server.xenapi.host.dmesg_clear(host),
1981 else:
1982 print server.xenapi.host.dmesg(host),
1983 else:
1984 if not use_clear:
1985 print server.xend.node.dmesg.info(),
1986 else:
1987 print server.xend.node.dmesg.clear(),
1989 def xm_log(args):
1990 arg_check(args, "log", 0)
1992 if serverType == SERVER_XEN_API:
1993 print server.xenapi.host.get_log(
1994 server.xenapi.session.get_this_host(server.getSession()))
1995 else:
1996 print server.xend.node.log()
1998 def xm_serve(args):
1999 if serverType == SERVER_XEN_API:
2000 print "Not supported with XenAPI"
2001 sys.exit(-1)
2003 arg_check(args, "serve", 0)
2005 from fcntl import fcntl, F_SETFL
2007 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
2008 s.connect(XendClient.XML_RPC_SOCKET)
2009 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
2011 while True:
2012 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
2013 if s in iwtd:
2014 data = s.recv(4096)
2015 if len(data) > 0:
2016 sys.stdout.write(data)
2017 sys.stdout.flush()
2018 else:
2019 break
2020 if sys.stdin in iwtd:
2021 data = sys.stdin.read(4096)
2022 if len(data) > 0:
2023 s.sendall(data)
2024 else:
2025 break
2026 s.close()
2028 def parse_dev_info(info):
2029 def get_info(n, t, d):
2030 i = 0
2031 while i < len(info):
2032 if (info[i][0] == n):
2033 return t(info[i][1])
2034 i = i + 1
2035 return t(d)
2036 return {
2037 #common
2038 'backend-id' : get_info('backend-id', int, -1),
2039 'handle' : get_info('handle', int, 0),
2040 'state' : get_info('state', int, -1),
2041 'be-path' : get_info('backend', str, '??'),
2042 'event-ch' : get_info('event-channel',int, -1),
2043 #network specific
2044 'virtual-device' : get_info('virtual-device', str, '??'),
2045 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
2046 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
2047 'mac' : get_info('mac', str, '??'),
2048 #block-device specific
2049 'ring-ref' : get_info('ring-ref', int, -1),
2050 #vscsi specific
2051 'feature-host' : get_info('feature-host', int, -1),
2054 def arg_check_for_resource_list(args, name):
2055 use_long = 0
2056 try:
2057 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2058 except getopt.GetoptError, opterr:
2059 err(opterr)
2060 sys.exit(1)
2062 for (k, v) in options:
2063 if k in ['-l', '--long']:
2064 use_long = 1
2066 if len(params) == 0:
2067 print 'No domain parameter given'
2068 usage(name)
2069 if len(params) > 1:
2070 print 'No multiple domain parameters allowed'
2071 usage(name)
2073 return (use_long, params)
2075 def xm_network_list(args):
2076 (use_long, params) = arg_check_for_resource_list(args, "network-list")
2078 dom = params[0]
2080 if serverType == SERVER_XEN_API:
2081 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2082 vif_properties = \
2083 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
2084 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2085 zip(range(len(vif_properties)), vif_properties))
2086 else:
2087 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
2089 if use_long:
2090 map(PrettyPrint.prettyprint, devs)
2091 else:
2092 hdr = 0
2093 for x in devs:
2094 if hdr == 0:
2095 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
2096 hdr = 1
2097 ni = parse_dev_info(x[1])
2098 ni['idx'] = int(x[0])
2099 print ("%(idx)-3d "
2100 "%(backend-id)-3d"
2101 "%(mac)-17s "
2102 "%(handle)-3d "
2103 "%(state)-3d "
2104 "%(event-ch)-3d "
2105 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
2106 "%(be-path)-30s "
2107 % ni)
2109 def xm_block_list(args):
2110 (use_long, params) = arg_check_for_resource_list(args, "block-list")
2112 dom = params[0]
2114 if serverType == SERVER_XEN_API:
2115 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2116 vbd_properties = \
2117 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2118 vbd_devs = \
2119 map(server.xenapi.VBD.get_device, vbd_refs)
2120 vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
2121 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2122 zip(vbd_devids, vbd_properties))
2123 else:
2124 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2126 if use_long:
2127 map(PrettyPrint.prettyprint, devs)
2128 else:
2129 hdr = 0
2130 for x in devs:
2131 if hdr == 0:
2132 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2133 hdr = 1
2134 ni = parse_dev_info(x[1])
2135 ni['idx'] = int(x[0])
2136 print ("%(idx)-5d "
2137 "%(backend-id)-3d "
2138 "%(handle)-3d "
2139 "%(state)-3d "
2140 "%(event-ch)-3d "
2141 "%(ring-ref)-5d "
2142 "%(be-path)-30s "
2143 % ni)
2145 def xm_vtpm_list(args):
2146 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2148 dom = params[0]
2150 if serverType == SERVER_XEN_API:
2151 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2152 vtpm_properties = \
2153 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2154 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2155 zip(range(len(vtpm_properties)), vtpm_properties))
2156 else:
2157 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2159 if use_long:
2160 map(PrettyPrint.prettyprint, devs)
2161 else:
2162 hdr = 0
2163 for x in devs:
2164 if hdr == 0:
2165 print 'Idx BE handle state evt-ch ring-ref BE-path'
2166 hdr = 1
2167 ni = parse_dev_info(x[1])
2168 ni['idx'] = int(x[0])
2169 print ("%(idx)-3d "
2170 "%(backend-id)-3d "
2171 "%(handle)-3d "
2172 "%(state)-3d "
2173 "%(event-ch)-3d "
2174 "%(ring-ref)-5d "
2175 "%(be-path)-30s "
2176 % ni)
2178 def attached_pci_dict_bin(dom):
2179 devs = []
2180 if serverType == SERVER_XEN_API:
2181 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2182 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2183 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2184 dev = {
2185 'domain': int(ppci_record['domain']),
2186 'bus': int(ppci_record['bus']),
2187 'slot': int(ppci_record['slot']),
2188 'func': int(ppci_record['func']),
2189 'vdevfn': int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref)),
2190 'key': server.xenapi.DPCI.get_key(dpci_ref)
2192 devs.append(dev)
2194 else:
2195 for x in server.xend.domain.getDeviceSxprs(dom, 'pci'):
2196 dev = {
2197 'domain': int(x['domain'], 16),
2198 'bus': int(x['bus'], 16),
2199 'slot': int(x['slot'], 16),
2200 'func': int(x['func'], 16),
2201 'vdevfn': int(x['vdevfn'], 16),
2202 'key': x['key']
2204 devs.append(dev)
2206 return devs
2208 def pci_dict_bin_to_str(pci_dev):
2209 new_dev = pci_dev.copy()
2211 new_dev['domain'] = '0x%04x' % pci_dev['domain']
2212 new_dev['bus'] = '0x%02x' % pci_dev['bus']
2213 new_dev['slot'] = '0x%02x' % pci_dev['slot']
2214 new_dev['func'] = '0x%x' % pci_dev['func']
2215 new_dev['vdevfn'] = '0x%02x' % pci_dev['vdevfn']
2217 return new_dev
2219 def attached_pci_dict(dom):
2220 return map(pci_dict_bin_to_str, attached_pci_dict_bin(dom))
2222 def xm_pci_list(args):
2223 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2225 devs = attached_pci_dict_bin(params[0])
2226 if len(devs) == 0:
2227 return
2229 def f(x):
2230 # The vfunc shouldn't be used for ordering if the vslot hasn't been
2231 # assigned as the output looks odd beacuse the vfunc isn't reported
2232 # but the (physical) function is.
2233 if x['vdevfn'] & AUTO_PHP_SLOT:
2234 vdevfn = AUTO_PHP_SLOT
2235 else:
2236 vdevfn = x['vdevfn']
2237 return (vdevfn << 32) | \
2238 PCI_BDF(x['domain'], x['bus'], x['slot'], x['func'])
2239 devs.sort(None, f)
2241 has_vdevfn = False
2242 for x in devs:
2243 if x['vdevfn'] & AUTO_PHP_SLOT:
2244 x['show_vslot'] = '-'
2245 x['show_vfunc'] = '-'
2246 else:
2247 x['show_vslot'] = "0x%02x" % PCI_SLOT(x['vdevfn'])
2248 x['show_vfunc'] = "0x%x" % PCI_FUNC(x['vdevfn'])
2249 has_vdevfn = True
2251 hdr_str = 'domain bus slot func'
2252 fmt_str = '0x%(domain)04x 0x%(bus)02x 0x%(slot)02x 0x%(func)x'
2253 if has_vdevfn:
2254 hdr_str = 'VSlt VFn ' + hdr_str
2255 fmt_str = '%(show_vslot)-4s %(show_vfunc)-3s ' + fmt_str
2257 print hdr_str
2258 for x in devs:
2259 print fmt_str % x
2262 def parse_pci_info(info):
2263 def get_info(n, t, d):
2264 return t(sxp.child_value(info, n, d))
2265 return {
2266 'domain' : get_info('domain', parse_hex, 0),
2267 'bus' : get_info('bus', parse_hex, -1),
2268 'slot' : get_info('slot', parse_hex, -1),
2269 'func' : get_info('func', parse_hex, -1)
2272 def xm_pci_list_assignable_devices(args):
2273 xenapi_unsupported()
2274 arg_check(args, "pci-list-assignable-devices", 0)
2276 devs = server.xend.node.pciinfo()
2278 fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
2279 for x in devs:
2280 pci = parse_pci_info(x)
2281 print fmt_str % pci
2284 def vscsi_sort(devs):
2285 def sort_hctl(ds, l):
2286 s = []
2287 for d1 in ds:
2288 for d2 in d1:
2289 v_dev = sxp.child_value(d2, 'v-dev')
2290 n = int(v_dev.split(':')[l])
2291 try:
2292 j = s[n]
2293 except IndexError:
2294 j = []
2295 s.extend([ [] for _ in range(len(s), n+1) ])
2296 j.append(d2)
2297 s[n] = j
2298 return s
2300 for i in range(len(devs)):
2301 ds1 = [ devs[i][1][0][1] ]
2302 ds1 = sort_hctl(ds1, 3)
2303 ds1 = sort_hctl(ds1, 2)
2304 ds1 = sort_hctl(ds1, 1)
2305 ds2 = []
2306 for d in ds1:
2307 ds2.extend(d)
2308 devs[i][1][0][1] = ds2
2309 return devs
2311 def vscsi_convert_sxp_to_dict(dev_sxp):
2312 dev_dict = {}
2313 for opt_val in dev_sxp[1:]:
2314 try:
2315 opt, val = opt_val
2316 dev_dict[opt] = val
2317 except TypeError:
2318 pass
2319 return dev_dict
2321 def xm_scsi_list(args):
2322 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2324 dom = params[0]
2326 devs = []
2327 if serverType == SERVER_XEN_API:
2329 dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
2330 dscsi_properties = \
2331 map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
2332 dscsi_dict = {}
2333 for dscsi_property in dscsi_properties:
2334 devid = int(dscsi_property['dev']['devid'])
2335 try:
2336 dscsi_sxp = dscsi_dict[devid]
2337 except:
2338 dscsi_sxp = [['devs', []]]
2339 for key, value in dscsi_property.items():
2340 if key != 'dev':
2341 dscsi_sxp.append([key, value])
2342 dev_sxp = ['dev']
2343 dev_sxp.extend(map2sxp(dscsi_property['dev']))
2344 dscsi_sxp[0][1].append(dev_sxp)
2345 dscsi_dict[devid] = dscsi_sxp
2346 devs = map2sxp(dscsi_dict)
2348 else:
2349 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2351 # Sort devs by virtual HCTL.
2352 devs = vscsi_sort(devs)
2354 if use_long:
2355 map(PrettyPrint.prettyprint, devs)
2356 else:
2357 hdr = 0
2358 for x in devs:
2359 if hdr == 0:
2360 print "%-3s %-3s %-5s %-4s %-10s %-5s %-10s %-4s" \
2361 % ('Idx', 'BE', 'state', 'host', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2362 hdr = 1
2363 ni = parse_dev_info(x[1])
2364 ni['idx'] = int(x[0])
2365 for dev in x[1][0][1]:
2366 mi = vscsi_convert_sxp_to_dict(dev)
2367 print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
2368 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2370 def parse_block_configuration(args):
2371 dom = args[0]
2373 if args[1].startswith('tap:'):
2374 cls = 'tap2'
2375 else:
2376 cls = 'vbd'
2378 vbd = [cls,
2379 ['uname', args[1]],
2380 ['dev', args[2]],
2381 ['mode', args[3]]]
2382 if len(args) == 5:
2383 vbd.append(['backend', args[4]])
2385 return (dom, vbd)
2388 def xm_block_attach(args):
2389 arg_check(args, 'block-attach', 4, 5)
2391 if serverType == SERVER_XEN_API:
2392 dom = args[0]
2393 uname = args[1]
2394 dev = args[2]
2395 mode = args[3]
2397 # First create new VDI
2398 vdi_record = {
2399 "name_label": "vdi" + str(uname.__hash__()),
2400 "name_description": "",
2401 "SR": get_default_SR(),
2402 "virtual_size": 0,
2403 "sector_size": 512,
2404 "type": "system",
2405 "sharable": False,
2406 "read_only": mode!="w",
2407 "other_config": {"location": uname}
2410 vdi_ref = server.xenapi.VDI.create(vdi_record)
2412 # Now create new VBD
2414 vbd_record = {
2415 "VM": get_single_vm(dom),
2416 "VDI": vdi_ref,
2417 "device": dev,
2418 "bootable": True,
2419 "mode": mode=="w" and "RW" or "RO",
2420 "type": "Disk",
2421 "qos_algorithm_type": "",
2422 "qos_algorithm_params": {}
2425 server.xenapi.VBD.create(vbd_record)
2427 else:
2428 (dom, vbd) = parse_block_configuration(args)
2429 server.xend.domain.device_create(dom, vbd)
2432 def xm_block_configure(args):
2433 arg_check(args, 'block-configure', 4, 5)
2435 (dom, vbd) = parse_block_configuration(args)
2436 server.xend.domain.device_configure(dom, vbd)
2439 def xm_network_attach(args):
2440 arg_check(args, 'network-attach', 1, 11)
2442 dom = args[0]
2443 vif = ['vif']
2444 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2445 'backend', 'vifname', 'rate', 'model', 'accel']
2447 if serverType == SERVER_XEN_API:
2448 vif_record = {
2449 "device": "eth0",
2450 "network": get_default_Network(),
2451 "VM": get_single_vm(dom),
2452 "MAC": "",
2453 "MTU": "",
2454 "qos_algorithm_type": "",
2455 "qos_algorithm_params": {},
2456 "other_config": {}
2459 def set(keys, val):
2460 record = vif_record
2461 for key in keys[:-1]:
2462 record = record[key]
2463 record[keys[-1]] = val
2465 def get_net_from_bridge(bridge):
2466 # In OSS, we just assert network.name_label == bridge name
2467 networks = dict([(record['name_label'], ref)
2468 for ref, record in server.xenapi.network
2469 .get_all_records().items()])
2470 if bridge not in networks.keys():
2471 raise "Unknown bridge name!"
2472 return networks[bridge]
2474 vif_conv = {
2475 'type':
2476 lambda x: None,
2477 'mac':
2478 lambda x: set(['MAC'], x),
2479 'bridge':
2480 lambda x: set(['network'], get_net_from_bridge(x)),
2481 'ip':
2482 lambda x: set(['other_config', 'ip'], x),
2483 'script':
2484 lambda x: set(['other_config', 'script'], x),
2485 'backend':
2486 lambda x: set(['other_config', 'backend'], x),
2487 'vifname':
2488 lambda x: set(['device'], x),
2489 'rate':
2490 lambda x: set(['qos_algorithm_params', 'rate'], x),
2491 'model':
2492 lambda x: None,
2493 'accel':
2494 lambda x: set(['other_config', 'accel'], x)
2497 for a in args[1:]:
2498 vif_param = a.split("=")
2499 if len(vif_param) != 2 or vif_param[1] == '' or \
2500 vif_param[0] not in vif_params:
2501 err("Invalid argument: %s" % a)
2502 usage('network-attach')
2503 else:
2504 vif_conv[vif_param[0]](vif_param[1])
2506 server.xenapi.VIF.create(vif_record)
2507 else:
2508 for a in args[1:]:
2509 vif_param = a.split("=")
2510 if len(vif_param) != 2 or vif_param[1] == '' or \
2511 vif_param[0] not in vif_params:
2512 err("Invalid argument: %s" % a)
2513 usage('network-attach')
2514 vif.append(vif_param)
2515 server.xend.domain.device_create(dom, vif)
2517 def parse_pci_configuration(args, opts = ''):
2518 dom = args[0]
2519 pci_dev_str = args[1]
2520 if len(args) == 3:
2521 pci_dev_str += '@' + args[2]
2522 if len(opts) > 0:
2523 pci_dev_str += ',' + serialise_pci_opts(opts)
2525 try:
2526 pci_dev = parse_pci_name_extended(pci_dev_str)
2527 except PciDeviceParseError, ex:
2528 raise OptionError(str(ex))
2530 return (dom, pci_dev)
2532 def xm_pci_attach(args):
2533 config_pci_opts = []
2534 (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
2535 for (k, v) in options:
2536 if k in ('-o', '--options'):
2537 if len(v.split('=')) != 2:
2538 err("Invalid pci attach option: %s" % v)
2539 usage('pci-attach')
2540 config_pci_opts.append(v.split('='))
2542 n = len([i for i in params if i != '--'])
2543 if n < 2 or n > 3:
2544 err("Invalid argument for 'xm pci-attach'")
2545 usage('pci-attach')
2547 (dom, dev) = parse_pci_configuration(params, config_pci_opts)
2549 head_dev = dev.pop(0)
2550 xm_pci_attach_one(dom, head_dev)
2552 # That is all for single-function virtual devices
2553 if len(dev) == 0:
2554 return
2556 # If the slot wasn't spefified in the args then use the slot
2557 # assigned to the head by qemu-xen for the rest of the functions
2558 if int(head_dev['vdevfn'], 16) & AUTO_PHP_SLOT:
2559 vdevfn = int(find_attached_devfn(attached_pci_dict(dom), head_dev), 16)
2560 if not vdevfn & AUTO_PHP_SLOT:
2561 vslot = PCI_SLOT(vdevfn)
2562 for i in dev:
2563 i['vdevfn'] = '0x%02x' % \
2564 PCI_DEVFN(vslot, PCI_FUNC(int(i['vdevfn'], 16)))
2566 for i in dev:
2567 xm_pci_attach_one(dom, i)
2569 def xm_pci_attach_one(dom, pci_dev):
2570 if serverType == SERVER_XEN_API:
2571 name = pci_dict_to_bdf_str(pci_dev)
2572 target_ref = None
2573 for ppci_ref in server.xenapi.PPCI.get_all():
2574 if name == server.xenapi.PPCI.get_name(ppci_ref):
2575 target_ref = ppci_ref
2576 break
2577 if target_ref is None:
2578 raise OptionError("Device %s not found" % name)
2580 dpci_record = {
2581 "VM": get_single_vm(dom),
2582 "PPCI": target_ref,
2583 "hotplug_slot": int(pci_dev['vdevfn'], 16),
2584 "options": dict(pci_dev.get('opts', [])),
2585 "key": pci_dev['key']
2587 server.xenapi.DPCI.create(dpci_record)
2589 else:
2590 pci = pci_convert_dict_to_sxp(pci_dev, 'Initialising')
2591 server.xend.domain.device_configure(dom, pci)
2593 def parse_scsi_configuration(p_scsi, v_hctl, state):
2594 def get_devid(hctl):
2595 return int(hctl.split(':')[0])
2597 host_mode = 0
2598 scsi_devices = None
2600 if p_scsi is not None:
2601 # xm scsi-attach
2602 if v_hctl == "host":
2603 if serverType == SERVER_XEN_API:
2604 # TODO
2605 raise OptionError("SCSI devices assignment by HBA is not implemeted")
2606 host_mode = 1
2607 scsi_devices = vscsi_util.vscsi_get_scsidevices()
2608 elif len(v_hctl.split(':')) != 4:
2609 raise OptionError("Invalid argument: %s" % v_hctl)
2610 (p_hctl, devname) = \
2611 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
2612 if p_hctl is None:
2613 raise OptionError("Cannot find device '%s'" % p_scsi)
2614 if host_mode:
2615 scsi_info = []
2616 devid = get_devid(p_hctl)
2617 for pHCTL, devname, _, _ in scsi_devices:
2618 if get_devid(pHCTL) == devid:
2619 scsi_info.append([devid, pHCTL, devname, pHCTL])
2620 else:
2621 scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
2622 else:
2623 # xm scsi-detach
2624 if len(v_hctl.split(':')) != 4:
2625 raise OptionError("Invalid argument: %s" % v_hctl)
2626 scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
2628 scsi = ['vscsi', ['feature-host', host_mode]]
2629 for devid, pHCTL, devname, vHCTL in scsi_info:
2630 scsi.append(['dev', \
2631 ['state', state], \
2632 ['devid', devid], \
2633 ['p-dev', pHCTL], \
2634 ['p-devname', devname], \
2635 ['v-dev', vHCTL] \
2636 ])
2637 return scsi
2639 def xm_scsi_attach(args):
2640 arg_check(args, 'scsi-attach', 3, 4)
2641 dom = args[0]
2642 p_scsi = args[1]
2643 v_hctl = args[2]
2644 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2646 if serverType == SERVER_XEN_API:
2648 scsi_dev = sxp.children(scsi, 'dev')[0]
2649 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2650 target_ref = None
2651 for pscsi_ref in server.xenapi.PSCSI.get_all():
2652 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2653 target_ref = pscsi_ref
2654 break
2655 if target_ref is None:
2656 raise OptionError("Cannot find device '%s'" % p_scsi)
2658 dscsi_record = {
2659 "VM": get_single_vm(dom),
2660 "PSCSI": target_ref,
2661 "virtual_HCTL": v_hctl
2663 server.xenapi.DSCSI.create(dscsi_record)
2665 else:
2666 if len(args) == 4:
2667 scsi.append(['backend', args[3]])
2668 server.xend.domain.device_configure(dom, scsi)
2670 def detach(args, deviceClass):
2671 rm_cfg = True
2672 dom = args[0]
2673 dev = args[1]
2674 try:
2675 force = args[2]
2676 if (force != "--force") and (force != "-f"):
2677 print "Ignoring option %s"%(force)
2678 force = None
2679 except IndexError:
2680 force = None
2682 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2685 def xm_block_detach(args):
2686 if serverType == SERVER_XEN_API:
2687 arg_check(args, "block-detach", 2, 3)
2688 dom = args[0]
2689 dev = args[1]
2690 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2691 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2692 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2693 if len(vbd_refs) > 0:
2694 vbd_ref = vbd_refs[0]
2695 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2697 server.xenapi.VBD.destroy(vbd_ref)
2699 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2700 server.xenapi.VDI.destroy(vdi_ref)
2701 else:
2702 raise OptionError("Cannot find device '%s' in domain '%s'"
2703 % (dev,dom))
2704 else:
2705 arg_check(args, 'block-detach', 2, 3)
2706 dom = args[0]
2707 dev = args[1]
2708 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2709 if dc == "tap2":
2710 detach(args, 'tap2')
2711 elif dc == "tap":
2712 detach(args, 'tap')
2713 else:
2714 detach(args, 'vbd')
2716 def xm_network_detach(args):
2717 if serverType == SERVER_XEN_API:
2718 arg_check(args, "network-detach", 2, 3)
2719 dom = args[0]
2720 devid = args[1]
2721 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2722 vif_refs = [vif_ref for vif_ref in vif_refs
2723 if server.xenapi.VIF.\
2724 get_runtime_properties(vif_ref)["handle"] == devid]
2725 if len(vif_refs) > 0:
2726 vif_ref = vif_refs[0]
2728 server.xenapi.VIF.destroy(vif_ref)
2729 else:
2730 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2731 else:
2732 arg_check(args, 'network-detach', 2, 3)
2733 detach(args, 'vif')
2735 def find_attached(attached, key):
2736 l = filter(lambda dev: pci_dict_cmp(dev, key), attached)
2738 if len(l) == 0:
2739 raise OptionError("pci: device is not attached: " +
2740 pci_dict_to_bdf_str(key))
2742 # There shouldn't ever be more than one match,
2743 # but perhaps an exception should be thrown if there is
2744 return l[0]
2746 def find_attached_devfn(attached, key):
2747 pci_dev = find_attached(attached, key)
2748 return pci_dev['vdevfn']
2750 def xm_pci_detach(args):
2751 arg_check(args, 'pci-detach', 2)
2753 (dom, dev) = parse_pci_configuration(args)
2754 attached = attached_pci_dict(dom)
2756 attached_dev = map(lambda x: find_attached(attached, x), dev)
2758 def f(pci_dev):
2759 vdevfn = int(pci_dev['vdevfn'], 16)
2760 return PCI_SLOT(vdevfn) | (vdevfn & AUTO_PHP_SLOT)
2761 vdevfns = map(f, attached_dev)
2762 if len(set(vdevfns)) > 1:
2763 err_str = map(lambda x: "\t%s is in slot 0x%02x\n" %
2764 (pci_dict_to_bdf_str(x),
2765 PCI_SLOT(int(x['vdevfn'], 16))), dev)
2766 raise OptionError("More than one slot used by specified devices\n"
2767 + ''.join(err_str))
2769 attached_to_slot = filter(lambda x:
2770 f(x) == vdevfns[0] and
2771 attached_dev[0]["key"] ==
2772 x["key"], attached_dev)
2774 if len(attached_to_slot) != len(dev):
2775 err_str_ = map(lambda x: '\t%s\n' % pci_dict_to_bdf_str(x), dev)
2776 err_str = "Requested:\n" + ''.join(err_str_)
2777 err_str_ = map(lambda x: '\t%s (%s)\n' %
2778 (pci_dict_to_bdf_str(x), x['key']),
2779 attached_to_slot)
2780 err_str += "Present:\n" + ''.join(err_str_)
2781 raise OptionError(("Not all functions in slot 0x%02x have had "
2782 "detachment requested.\n" % vdevfns[0]) + err_str)
2784 for i in dev:
2785 xm_pci_detach_one(dom, i)
2787 def xm_pci_detach_one(dom, pci_dev):
2788 if serverType == SERVER_XEN_API:
2789 name = pci_dict_to_bdf_str(pci_dev)
2790 target_ref = None
2791 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2792 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2793 if name == server.xenapi.PPCI.get_name(ppci_ref):
2794 target_ref = ppci_ref
2795 server.xenapi.DPCI.destroy(dpci_ref)
2796 break
2797 if target_ref is None:
2798 raise OptionError("Device %s not assigned" % name)
2800 else:
2801 pci = pci_convert_dict_to_sxp(pci_dev, 'Closing')
2802 server.xend.domain.device_configure(dom, pci)
2804 def xm_scsi_detach(args):
2805 arg_check(args, 'scsi-detach', 2)
2806 dom = args[0]
2807 v_hctl = args[1]
2808 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
2810 if serverType == SERVER_XEN_API:
2812 target_ref = None
2813 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
2814 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
2815 target_ref = dscsi_ref
2816 break
2817 if target_ref is None:
2818 raise OptionError("Device %s not assigned" % v_hctl)
2820 server.xenapi.DSCSI.destroy(target_ref)
2822 else:
2823 server.xend.domain.device_configure(dom, scsi)
2825 def xm_vnet_list(args):
2826 xenapi_unsupported()
2827 try:
2828 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2829 except getopt.GetoptError, opterr:
2830 err(opterr)
2831 usage('vnet-list')
2833 use_long = 0
2834 for (k, v) in options:
2835 if k in ['-l', '--long']:
2836 use_long = 1
2838 if params:
2839 use_long = 1
2840 vnets = params
2841 else:
2842 vnets = server.xend_vnets()
2844 for vnet in vnets:
2845 try:
2846 if use_long:
2847 info = server.xend_vnet(vnet)
2848 PrettyPrint.prettyprint(info)
2849 else:
2850 print vnet
2851 except Exception, ex:
2852 print vnet, ex
2854 def xm_vnet_create(args):
2855 xenapi_unsupported()
2856 arg_check(args, "vnet-create", 1)
2857 conf = args[0]
2858 if not os.access(conf, os.R_OK):
2859 print "File not found: %s" % conf
2860 sys.exit(1)
2862 server.xend_vnet_create(conf)
2864 def xm_vnet_delete(args):
2865 xenapi_unsupported()
2866 arg_check(args, "vnet-delete", 1)
2867 vnet = args[0]
2868 server.xend_vnet_delete(vnet)
2870 def xm_network_new(args):
2871 xenapi_only()
2872 arg_check(args, "network-new", 1)
2873 network = args[0]
2875 record = {
2876 "name_label": network,
2877 "name_description": "",
2878 "other_config": {},
2879 "default_gateway": "",
2880 "default_netmask": ""
2883 server.xenapi.network.create(record)
2885 def xm_network_del(args):
2886 xenapi_only()
2887 arg_check(args, "network-del", 1)
2888 network = args[0]
2890 networks = dict([(record['name_label'], ref)
2891 for ref, record in
2892 server.xenapi.network.get_all_records().items()])
2894 if network not in networks.keys():
2895 raise ValueError("'%s' is not a valid network name" % network)
2897 server.xenapi.network.destroy(networks[network])
2899 def xm_network_show(args):
2900 xenapi_only()
2901 arg_check(args, "network-show", 0)
2903 networks = server.xenapi.network.get_all_records()
2904 pifs = server.xenapi.PIF.get_all_records()
2905 vifs = server.xenapi.VIF.get_all_records()
2907 print '%-20s %-40s %-10s' % \
2908 ('Name', 'VIFs', 'PIFs')
2910 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2912 for network_ref, network in networks.items():
2913 for i in range(max(len(network['PIFs']),
2914 len(network['VIFs']), 1)):
2915 if i < len(network['PIFs']):
2916 pif_uuid = network['PIFs'][i]
2917 else:
2918 pif_uuid = None
2920 if i < len(network['VIFs']):
2921 vif_uuid = network['VIFs'][i]
2922 else:
2923 vif_uuid = None
2925 pif = pifs.get(pif_uuid, None)
2926 vif = vifs.get(vif_uuid, None)
2928 if vif:
2929 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2930 vif = "%s.%s" % (dom_name, vif['device'])
2931 else:
2932 vif = ''
2934 if pif:
2935 if int(pif['VLAN']) > -1:
2936 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2937 else:
2938 pif = pif['device']
2939 else:
2940 pif = ''
2942 if i == 0:
2943 r = {'name_label':network['name_label'],
2944 'vif':vif, 'pif':pif}
2945 else:
2946 r = {'name_label':'', 'vif':vif, 'pif':pif}
2948 print format2 % r
2950 def xm_tmem_list(args):
2951 try:
2952 (options, params) = getopt.gnu_getopt(args, 'la', ['long','all'])
2953 except getopt.GetoptError, opterr:
2954 err(opterr)
2955 usage('tmem-list')
2957 use_long = False
2958 for (k, v) in options:
2959 if k in ['-l', '--long']:
2960 use_long = True
2962 all = False
2963 for (k, v) in options:
2964 if k in ['-a', '--all']:
2965 all = True
2967 if not all and len(params) == 0:
2968 err('You must specify -a or --all or a domain id.')
2969 usage('tmem-list')
2971 if all:
2972 domid = -1
2973 else:
2974 try:
2975 domid = int(params[0])
2976 params = params[1:]
2977 except:
2978 err('Unrecognized domain id: %s' % params[0])
2979 usage('tmem-list')
2981 if serverType == SERVER_XEN_API:
2982 print server.xenapi.host.tmem_list(domid,use_long)
2983 else:
2984 print server.xend.node.tmem_list(domid,use_long)
2986 def parse_tmem_args(args, name):
2987 try:
2988 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
2989 except getopt.GetoptError, opterr:
2990 err(opterr)
2991 usage(name)
2993 all = False
2994 for (k, v) in options:
2995 if k in ['-a', '--all']:
2996 all = True
2998 if not all and len(params) == 0:
2999 err('You must specify -a or --all or a domain id.')
3000 usage(name)
3002 if all:
3003 domid = -1
3004 else:
3005 try:
3006 domid = int(params[0])
3007 params = params[1:]
3008 except:
3009 err('Unrecognized domain id: %s' % params[0])
3010 usage(name)
3012 return domid, params
3014 def xm_tmem_destroy(args):
3015 (domid, _) = parse_tmem_args(args, 'tmem-destroy')
3016 if serverType == SERVER_XEN_API:
3017 server.xenapi.host.tmem_destroy(domid)
3018 else:
3019 server.xend.node.tmem_destroy(domid)
3021 def xm_tmem_thaw(args):
3022 (domid, _) = parse_tmem_args(args, 'tmem-thaw')
3023 if serverType == SERVER_XEN_API:
3024 server.xenapi.host.tmem_thaw(domid)
3025 else:
3026 server.xend.node.tmem_thaw(domid)
3028 def xm_tmem_freeze(args):
3029 (domid, _) = parse_tmem_args(args, 'tmem-freeze')
3030 if serverType == SERVER_XEN_API:
3031 server.xenapi.host.tmem_freeze(domid)
3032 else:
3033 server.xend.node.tmem_freeze(domid)
3035 def xm_tmem_flush(args):
3036 try:
3037 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
3038 except getopt.GetoptError, opterr:
3039 err(opterr)
3040 usage(name)
3042 all = False
3043 for (k, v) in options:
3044 if k in ['-a', '--all']:
3045 all = True
3047 if not all and len(params) == 0:
3048 err('You must specify -a or --all or a domain id.')
3049 usage('tmem-flush')
3051 if all:
3052 domid = -1
3053 else:
3054 try:
3055 domid = int(params[0])
3056 params = params[1:]
3057 except:
3058 err('Unrecognized domain id: %s' % params[0])
3059 usage('tmem-flush')
3061 pages = -1
3062 for (k, v) in options:
3063 if k in ['-p', '--pages']:
3064 pages = v
3066 if serverType == SERVER_XEN_API:
3067 server.xenapi.host.tmem_flush(domid,pages)
3068 else:
3069 server.xend.node.tmem_flush(domid,pages)
3071 def xm_tmem_set(args):
3072 try:
3073 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
3074 except getopt.GetoptError, opterr:
3075 err(opterr)
3076 usage(name)
3078 all = False
3079 for (k, v) in options:
3080 if k in ['-a', '--all']:
3081 all = True
3083 if not all and len(params) == 0:
3084 err('You must specify -a or --all or a domain id.')
3085 usage('tmem-set')
3087 if all:
3088 domid = -1
3089 else:
3090 try:
3091 domid = int(params[0])
3092 params = params[1:]
3093 except:
3094 err('Unrecognized domain id: %s' % params[0])
3095 usage('tmem-set')
3097 weight = None
3098 cap = None
3099 compress = None
3100 for item in params:
3101 if item.startswith('weight='):
3102 try:
3103 weight = int(item[7:])
3104 except:
3105 err('weight should be a integer')
3106 usage('tmem-set')
3107 if item.startswith('cap='):
3108 cap = int(item[4:])
3109 if item.startswith('compress='):
3110 compress = int(item[9:])
3112 if weight is None and cap is None and compress is None:
3113 err('Unrecognized tmem configuration option: %s' % item)
3114 usage('tmem-set')
3116 if serverType == SERVER_XEN_API:
3117 if weight is not None:
3118 server.xenapi.host.tmem_set_weight(domid, weight)
3119 if cap is not None:
3120 server.xenapi.host.tmem_set_cap(domid, cap)
3121 if compress is not None:
3122 server.xenapi.host.tmem_set_compress(domid, compress)
3123 else:
3124 if weight is not None:
3125 server.xend.node.tmem_set_weight(domid, weight)
3126 if cap is not None:
3127 server.xend.node.tmem_set_cap(domid, cap)
3128 if compress is not None:
3129 server.xend.node.tmem_set_compress(domid, compress)
3132 commands = {
3133 "shell": xm_shell,
3134 "event-monitor": xm_event_monitor,
3135 # console commands
3136 "console": xm_console,
3137 "vncviewer": xm_vncviewer,
3138 # xenstat commands
3139 "top": xm_top,
3140 # domain commands
3141 "delete": xm_delete,
3142 "destroy": xm_destroy,
3143 "domid": xm_domid,
3144 "domname": xm_domname,
3145 "dump-core": xm_dump_core,
3146 "reboot": xm_reboot,
3147 "rename": xm_rename,
3148 "reset": xm_reset,
3149 "restore": xm_restore,
3150 "resume": xm_resume,
3151 "save": xm_save,
3152 "shutdown": xm_shutdown,
3153 "start": xm_start,
3154 "sysrq": xm_sysrq,
3155 "trigger": xm_trigger,
3156 "uptime": xm_uptime,
3157 "suspend": xm_suspend,
3158 "list": xm_list,
3159 # memory commands
3160 "mem-max": xm_mem_max,
3161 "mem-set": xm_mem_set,
3162 # cpu commands
3163 "vcpu-pin": xm_vcpu_pin,
3164 "vcpu-list": xm_vcpu_list,
3165 "vcpu-set": xm_vcpu_set,
3166 # special
3167 "pause": xm_pause,
3168 "unpause": xm_unpause,
3169 # host commands
3170 "debug-keys": xm_debug_keys,
3171 "dmesg": xm_dmesg,
3172 "info": xm_info,
3173 "log": xm_log,
3174 "serve": xm_serve,
3175 # scheduler
3176 "sched-sedf": xm_sched_sedf,
3177 "sched-credit": xm_sched_credit,
3178 # block
3179 "block-attach": xm_block_attach,
3180 "block-detach": xm_block_detach,
3181 "block-list": xm_block_list,
3182 "block-configure": xm_block_configure,
3183 # network (AKA vifs)
3184 "network-attach": xm_network_attach,
3185 "network-detach": xm_network_detach,
3186 "network-list": xm_network_list,
3187 # network (as in XenAPI)
3188 "network-new": xm_network_new,
3189 "network-del": xm_network_del,
3190 "network-show": xm_network_show,
3191 # vnet
3192 "vnet-list": xm_vnet_list,
3193 "vnet-create": xm_vnet_create,
3194 "vnet-delete": xm_vnet_delete,
3195 # vtpm
3196 "vtpm-list": xm_vtpm_list,
3197 #pci
3198 "pci-attach": xm_pci_attach,
3199 "pci-detach": xm_pci_detach,
3200 "pci-list": xm_pci_list,
3201 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
3202 # vscsi
3203 "scsi-attach": xm_scsi_attach,
3204 "scsi-detach": xm_scsi_detach,
3205 "scsi-list": xm_scsi_list,
3206 # tmem
3207 "tmem-thaw": xm_tmem_thaw,
3208 "tmem-freeze": xm_tmem_freeze,
3209 "tmem-flush": xm_tmem_flush,
3210 "tmem-destroy": xm_tmem_destroy,
3211 "tmem-list": xm_tmem_list,
3212 "tmem-set": xm_tmem_set,
3215 ## The commands supported by a separate argument parser in xend.xm.
3216 IMPORTED_COMMANDS = [
3217 'create',
3218 'new',
3219 'migrate',
3220 'labels',
3221 'dumppolicy',
3222 'addlabel',
3223 'rmlabel',
3224 'getlabel',
3225 'dry-run',
3226 'resources',
3227 'getpolicy',
3228 'setpolicy',
3229 'resetpolicy',
3232 for c in IMPORTED_COMMANDS:
3233 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
3235 aliases = {
3236 "balloon": "mem-set",
3237 "set-vcpus": "vcpu-set",
3238 "vif-list": "network-list",
3239 "vbd-create": "block-attach",
3240 "vbd-destroy": "block-detach",
3241 "vbd-list": "block-list",
3245 def xm_lookup_cmd(cmd):
3246 if commands.has_key(cmd):
3247 return commands[cmd]
3248 elif aliases.has_key(cmd):
3249 deprecated(cmd,aliases[cmd])
3250 return commands[aliases[cmd]]
3251 elif cmd == 'help':
3252 longHelp()
3253 sys.exit(0)
3254 else:
3255 # simulate getopt's prefix matching behaviour
3256 if len(cmd) > 1:
3257 same_prefix_cmds = [commands[c] for c in commands.keys() \
3258 if c[:len(cmd)] == cmd]
3259 # only execute if there is only 1 match
3260 if len(same_prefix_cmds) == 1:
3261 return same_prefix_cmds[0]
3262 return None
3264 def deprecated(old,new):
3265 print >>sys.stderr, (
3266 "Command %s is deprecated. Please use xm %s instead." % (old, new))
3268 def main(argv=sys.argv):
3269 if len(argv) < 2:
3270 usage()
3272 # intercept --help(-h) and output our own help
3273 for help in ['--help', '-h']:
3274 if help in argv[1:]:
3275 if help == argv[1]:
3276 longHelp()
3277 sys.exit(0)
3278 else:
3279 usage(argv[1])
3281 cmd_name = argv[1]
3282 cmd = xm_lookup_cmd(cmd_name)
3283 if cmd:
3284 # strip off prog name and subcmd
3285 args = argv[2:]
3286 _, rc = _run_cmd(cmd, cmd_name, args)
3287 sys.exit(rc)
3288 else:
3289 err('Subcommand %s not found!' % cmd_name)
3290 usage()
3292 def _run_cmd(cmd, cmd_name, args):
3293 global server
3295 try:
3296 if server is None:
3297 if serverType == SERVER_XEN_API:
3298 server = XenAPI.Session(serverURI)
3299 username, password = parseAuthentication()
3300 server.login_with_password(username, password)
3301 def logout():
3302 try:
3303 server.xenapi.session.logout()
3304 except:
3305 pass
3306 atexit.register(logout)
3307 else:
3308 server = ServerProxy(serverURI)
3310 return True, cmd(args)
3311 except socket.error, ex:
3312 if os.geteuid() != 0:
3313 err("Most commands need root access. Please try again as root.")
3314 else:
3315 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
3316 except KeyboardInterrupt:
3317 print "Interrupted."
3318 return True, ''
3319 except IOError, ex:
3320 if os.geteuid() != 0:
3321 err("Most commands need root access. Please try again as root.")
3322 else:
3323 err("Unable to connect to xend: %s." % ex[1])
3324 except SystemExit, code:
3325 return code == 0, code
3326 except XenAPI.Failure, exn:
3327 for line in [''] + wrap(str(exn), 80) + ['']:
3328 print >>sys.stderr, line
3329 except xmlrpclib.Fault, ex:
3330 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
3331 err("Domain '%s' does not exist." % ex.faultString)
3332 return False, ex.faultCode
3333 else:
3334 err(ex.faultString)
3335 _usage(cmd_name)
3336 except xmlrpclib.ProtocolError, ex:
3337 if ex.errcode == -1:
3338 print >>sys.stderr, (
3339 "Xend has probably crashed! Invalid or missing HTTP "
3340 "status code.")
3341 else:
3342 print >>sys.stderr, (
3343 "Xend has probably crashed! ProtocolError(%d, %s)." %
3344 (ex.errcode, ex.errmsg))
3345 except (ValueError, OverflowError):
3346 err("Invalid argument.")
3347 _usage(cmd_name)
3348 except OptionError, e:
3349 err(str(e))
3350 _usage(cmd_name)
3351 print e.usage
3352 except XenAPIUnsupportedException, e:
3353 err(str(e))
3354 except XSMError, e:
3355 err(str(e))
3356 except Exception, e:
3357 if serverType != SERVER_XEN_API:
3358 import xen.util.xsm.xsm as security
3359 if isinstance(e, security.XSMError):
3360 err(str(e))
3361 return False, 1
3362 print "Unexpected error:", sys.exc_info()[0]
3363 print
3364 print "Please report to xen-devel@lists.xensource.com"
3365 raise
3367 return False, 1
3369 if __name__ == "__main__":
3370 main()