ia64/xen-unstable

view tools/python/xen/xm/main.py @ 19758:0573bbe19499

xend: pass-through: sxp.merge() cant deal with values being a list

sxp.merge() can't deal with values being a list so instead
of storing pci options as:

[ 'opts', [ 'key1' 'value1'], [ 'key2', 'value2'], ...]

store them as:

[ 'opts', [ 'key1' 'value1'], ['opts', [ 'key2', 'value2']], ...

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 16 11:37:41 2009 +0100 (2009-06-16)
parents f07a915ecc17
children 85fdfb7da88c
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_changeset": getVal(["software_version", "xen_changeset"]),
1761 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1762 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1763 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1764 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1765 "xend_config_format":getVal(["software_version", "xend_config_format"])
1768 sorted = info.items()
1769 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1771 for (k, v) in sorted:
1772 print "%-23s:" % k, v
1773 else:
1774 info = server.xend.node.info()
1775 for x in info[1:]:
1776 if len(x) < 2:
1777 print "%-23s: (none)" % x[0]
1778 else:
1779 print "%-23s:" % x[0], x[1]
1781 def xm_console(args):
1782 arg_check(args, "console", 1, 3)
1784 num = 0
1785 quiet = False;
1787 try:
1788 (options, params) = getopt.gnu_getopt(args, 'qn:', ['quiet', 'num'])
1789 except getopt.GetoptError, opterr:
1790 err(opterr)
1791 usage('console')
1793 for (k, v) in options:
1794 if k in ['-q', '--quiet']:
1795 quiet = True
1796 elif k in ['-n', '--num']:
1797 num = int(v[0])
1798 else:
1799 assert False
1801 if len(params) != 1:
1802 err('No domain given')
1803 usage('console')
1805 dom = params[0]
1807 try:
1808 if serverType == SERVER_XEN_API:
1809 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1810 else:
1811 info = server.xend.domain(dom)
1812 domid = int(sxp.child_value(info, 'domid', '-1'))
1813 except:
1814 if quiet:
1815 sys.exit(1)
1816 else:
1817 raise
1819 if domid == -1:
1820 if quiet:
1821 sys.exit(1)
1822 else:
1823 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1825 console.execConsole(domid, num)
1828 def domain_name_to_domid(domain_name):
1829 if serverType == SERVER_XEN_API:
1830 domid = server.xenapi.VM.get_domid(
1831 get_single_vm(domain_name))
1832 else:
1833 dom = server.xend.domain(domain_name)
1834 domid = int(sxp.child_value(dom, 'domid', '-1'))
1835 return int(domid)
1837 def xm_vncviewer(args):
1838 autopass = False;
1840 try:
1841 (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass'])
1842 except getopt.GetoptError, opterr:
1843 err(opterr)
1844 usage('vncviewer')
1846 for (k, v) in options:
1847 if k in ['--autopass','--vncviewer-autopass']:
1848 autopass = True
1849 else:
1850 assert False
1852 if len(params) != 1:
1853 err('No domain given (or several parameters specified)')
1854 usage('vncviewer')
1856 dom = params[0]
1857 domid = domain_name_to_domid(dom)
1859 console.runVncViewer(domid, autopass)
1862 def xm_uptime(args):
1863 short_mode = 0
1865 try:
1866 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1867 except getopt.GetoptError, opterr:
1868 err(opterr)
1869 usage('uptime')
1871 for (k, v) in options:
1872 if k in ['-s', '--short']:
1873 short_mode = 1
1875 doms = getDomains(params, 'all')
1877 if short_mode == 0:
1878 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1880 for dom in doms:
1881 d = parse_doms_info(dom)
1882 if d['domid'] == '':
1883 uptime = 0
1884 elif int(d['domid']) > 0:
1885 uptime = int(round(d['up_time']))
1886 else:
1887 f=open('/proc/uptime', 'r')
1888 upfile = f.read()
1889 uptime = int(round(float(upfile.split(' ')[0])))
1890 f.close()
1892 days = int(uptime / 86400)
1893 uptime -= (days * 86400)
1894 hours = int(uptime / 3600)
1895 uptime -= (hours * 3600)
1896 minutes = int(uptime / 60)
1897 uptime -= (minutes * 60)
1898 seconds = uptime
1900 upstring = ""
1901 if days > 0:
1902 upstring += str(days) + " day"
1903 if days > 1:
1904 upstring += "s"
1905 upstring += ", "
1906 upstring += '%(hours)2d:%(minutes)02d' % vars()
1908 if short_mode:
1909 now = datetime.datetime.now()
1910 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1911 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1912 else:
1913 upstring += ':%(seconds)02d' % vars()
1914 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1916 print upstring
1918 def xm_sysrq(args):
1919 arg_check(args, "sysrq", 2)
1920 dom = args[0]
1921 req = args[1]
1922 if serverType == SERVER_XEN_API:
1923 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1924 else:
1925 server.xend.domain.send_sysrq(dom, req)
1927 def xm_trigger(args):
1928 vcpu = 0
1930 arg_check(args, "trigger", 2, 3)
1931 dom = args[0]
1932 trigger = args[1]
1933 if len(args) == 3:
1934 vcpu = int(args[2])
1936 if serverType == SERVER_XEN_API:
1937 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1938 else:
1939 server.xend.domain.send_trigger(dom, trigger, vcpu)
1941 def xm_debug_keys(args):
1942 arg_check(args, "debug-keys", 1)
1944 keys = str(args[0])
1946 if serverType == SERVER_XEN_API:
1947 server.xenapi.host.send_debug_keys(
1948 server.xenapi.session.get_this_host(server.getSession()),
1949 keys)
1950 else:
1951 server.xend.node.send_debug_keys(keys)
1953 def xm_top(args):
1954 arg_check(args, "top", 0)
1956 os.system('xentop')
1958 def xm_dmesg(args):
1959 arg_check(args, "dmesg", 0, 1)
1961 try:
1962 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1963 except getopt.GetoptError, opterr:
1964 err(opterr)
1965 usage('dmesg')
1967 use_clear = 0
1968 for (k, v) in options:
1969 if k in ['-c', '--clear']:
1970 use_clear = 1
1972 if len(params) :
1973 err("No parameter required")
1974 usage('dmesg')
1976 if serverType == SERVER_XEN_API:
1977 host = server.xenapi.session.get_this_host(server.getSession())
1978 if use_clear:
1979 print server.xenapi.host.dmesg_clear(host),
1980 else:
1981 print server.xenapi.host.dmesg(host),
1982 else:
1983 if not use_clear:
1984 print server.xend.node.dmesg.info(),
1985 else:
1986 print server.xend.node.dmesg.clear(),
1988 def xm_log(args):
1989 arg_check(args, "log", 0)
1991 if serverType == SERVER_XEN_API:
1992 print server.xenapi.host.get_log(
1993 server.xenapi.session.get_this_host(server.getSession()))
1994 else:
1995 print server.xend.node.log()
1997 def xm_serve(args):
1998 if serverType == SERVER_XEN_API:
1999 print "Not supported with XenAPI"
2000 sys.exit(-1)
2002 arg_check(args, "serve", 0)
2004 from fcntl import fcntl, F_SETFL
2006 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
2007 s.connect(XendClient.XML_RPC_SOCKET)
2008 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
2010 while True:
2011 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
2012 if s in iwtd:
2013 data = s.recv(4096)
2014 if len(data) > 0:
2015 sys.stdout.write(data)
2016 sys.stdout.flush()
2017 else:
2018 break
2019 if sys.stdin in iwtd:
2020 data = sys.stdin.read(4096)
2021 if len(data) > 0:
2022 s.sendall(data)
2023 else:
2024 break
2025 s.close()
2027 def parse_dev_info(info):
2028 def get_info(n, t, d):
2029 i = 0
2030 while i < len(info):
2031 if (info[i][0] == n):
2032 return t(info[i][1])
2033 i = i + 1
2034 return t(d)
2035 return {
2036 #common
2037 'backend-id' : get_info('backend-id', int, -1),
2038 'handle' : get_info('handle', int, 0),
2039 'state' : get_info('state', int, -1),
2040 'be-path' : get_info('backend', str, '??'),
2041 'event-ch' : get_info('event-channel',int, -1),
2042 #network specific
2043 'virtual-device' : get_info('virtual-device', str, '??'),
2044 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
2045 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
2046 'mac' : get_info('mac', str, '??'),
2047 #block-device specific
2048 'ring-ref' : get_info('ring-ref', int, -1),
2049 #vscsi specific
2050 'feature-host' : get_info('feature-host', int, -1),
2053 def arg_check_for_resource_list(args, name):
2054 use_long = 0
2055 try:
2056 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2057 except getopt.GetoptError, opterr:
2058 err(opterr)
2059 sys.exit(1)
2061 for (k, v) in options:
2062 if k in ['-l', '--long']:
2063 use_long = 1
2065 if len(params) == 0:
2066 print 'No domain parameter given'
2067 usage(name)
2068 if len(params) > 1:
2069 print 'No multiple domain parameters allowed'
2070 usage(name)
2072 return (use_long, params)
2074 def xm_network_list(args):
2075 (use_long, params) = arg_check_for_resource_list(args, "network-list")
2077 dom = params[0]
2079 if serverType == SERVER_XEN_API:
2080 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2081 vif_properties = \
2082 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
2083 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2084 zip(range(len(vif_properties)), vif_properties))
2085 else:
2086 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
2088 if use_long:
2089 map(PrettyPrint.prettyprint, devs)
2090 else:
2091 hdr = 0
2092 for x in devs:
2093 if hdr == 0:
2094 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
2095 hdr = 1
2096 ni = parse_dev_info(x[1])
2097 ni['idx'] = int(x[0])
2098 print ("%(idx)-3d "
2099 "%(backend-id)-3d"
2100 "%(mac)-17s "
2101 "%(handle)-3d "
2102 "%(state)-3d "
2103 "%(event-ch)-3d "
2104 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
2105 "%(be-path)-30s "
2106 % ni)
2108 def xm_block_list(args):
2109 (use_long, params) = arg_check_for_resource_list(args, "block-list")
2111 dom = params[0]
2113 if serverType == SERVER_XEN_API:
2114 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2115 vbd_properties = \
2116 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2117 vbd_devs = \
2118 map(server.xenapi.VBD.get_device, vbd_refs)
2119 vbd_devids = [blkdev_name_to_number(x)[1] for x in vbd_devs]
2120 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2121 zip(vbd_devids, vbd_properties))
2122 else:
2123 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2125 if use_long:
2126 map(PrettyPrint.prettyprint, devs)
2127 else:
2128 hdr = 0
2129 for x in devs:
2130 if hdr == 0:
2131 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2132 hdr = 1
2133 ni = parse_dev_info(x[1])
2134 ni['idx'] = int(x[0])
2135 print ("%(idx)-5d "
2136 "%(backend-id)-3d "
2137 "%(handle)-3d "
2138 "%(state)-3d "
2139 "%(event-ch)-3d "
2140 "%(ring-ref)-5d "
2141 "%(be-path)-30s "
2142 % ni)
2144 def xm_vtpm_list(args):
2145 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2147 dom = params[0]
2149 if serverType == SERVER_XEN_API:
2150 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2151 vtpm_properties = \
2152 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2153 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2154 zip(range(len(vtpm_properties)), vtpm_properties))
2155 else:
2156 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2158 if use_long:
2159 map(PrettyPrint.prettyprint, devs)
2160 else:
2161 hdr = 0
2162 for x in devs:
2163 if hdr == 0:
2164 print 'Idx BE handle state evt-ch ring-ref BE-path'
2165 hdr = 1
2166 ni = parse_dev_info(x[1])
2167 ni['idx'] = int(x[0])
2168 print ("%(idx)-3d "
2169 "%(backend-id)-3d "
2170 "%(handle)-3d "
2171 "%(state)-3d "
2172 "%(event-ch)-3d "
2173 "%(ring-ref)-5d "
2174 "%(be-path)-30s "
2175 % ni)
2178 def xm_pci_list(args):
2179 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2181 dom = params[0]
2183 devs = []
2184 if serverType == SERVER_XEN_API:
2185 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2186 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2187 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2188 dev = {
2189 "domain": int(ppci_record["domain"]),
2190 "bus": int(ppci_record["bus"]),
2191 "slot": int(ppci_record["slot"]),
2192 "func": int(ppci_record["func"]),
2193 "vslot": int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref))
2195 devs.append(dev)
2197 else:
2198 for x in server.xend.domain.getDeviceSxprs(dom, 'pci'):
2199 dev = {
2200 "domain": int(x["domain"], 16),
2201 "bus": int(x["bus"], 16),
2202 "slot": int(x["slot"], 16),
2203 "func": int(x["func"], 16),
2204 "vslot": int(x["vslot"], 16)
2206 devs.append(dev)
2208 if len(devs) == 0:
2209 return
2211 devs.sort(None, lambda x: x['vslot'] << 32 | PCI_BDF(x['domain'], x['bus'],
2212 x['slot'], x['func']))
2214 has_vslot = False
2215 for x in devs:
2216 if x['vslot'] == AUTO_PHP_SLOT:
2217 x['show_vslot'] = '-'
2218 else:
2219 x['show_vslot'] = "0x%02x" % x['vslot']
2220 has_vslot = True
2222 hdr_str = 'domain bus slot func'
2223 fmt_str = '0x%(domain)04x 0x%(bus)02x 0x%(slot)02x 0x%(func)x'
2224 if has_vslot:
2225 hdr_str = 'VSlt ' + hdr_str
2226 fmt_str = '%(show_vslot)-4s ' + fmt_str
2228 print hdr_str
2229 for x in devs:
2230 print fmt_str % x
2233 def parse_pci_info(info):
2234 def get_info(n, t, d):
2235 return t(sxp.child_value(info, n, d))
2236 return {
2237 'domain' : get_info('domain', parse_hex, 0),
2238 'bus' : get_info('bus', parse_hex, -1),
2239 'slot' : get_info('slot', parse_hex, -1),
2240 'func' : get_info('func', parse_hex, -1)
2243 def xm_pci_list_assignable_devices(args):
2244 xenapi_unsupported()
2245 arg_check(args, "pci-list-assignable-devices", 0)
2247 devs = server.xend.node.pciinfo()
2249 fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
2250 for x in devs:
2251 pci = parse_pci_info(x)
2252 print fmt_str % pci
2255 def vscsi_sort(devs):
2256 def sort_hctl(ds, l):
2257 s = []
2258 for d1 in ds:
2259 for d2 in d1:
2260 v_dev = sxp.child_value(d2, 'v-dev')
2261 n = int(v_dev.split(':')[l])
2262 try:
2263 j = s[n]
2264 except IndexError:
2265 j = []
2266 s.extend([ [] for _ in range(len(s), n+1) ])
2267 j.append(d2)
2268 s[n] = j
2269 return s
2271 for i in range(len(devs)):
2272 ds1 = [ devs[i][1][0][1] ]
2273 ds1 = sort_hctl(ds1, 3)
2274 ds1 = sort_hctl(ds1, 2)
2275 ds1 = sort_hctl(ds1, 1)
2276 ds2 = []
2277 for d in ds1:
2278 ds2.extend(d)
2279 devs[i][1][0][1] = ds2
2280 return devs
2282 def vscsi_convert_sxp_to_dict(dev_sxp):
2283 dev_dict = {}
2284 for opt_val in dev_sxp[1:]:
2285 try:
2286 opt, val = opt_val
2287 dev_dict[opt] = val
2288 except TypeError:
2289 pass
2290 return dev_dict
2292 def xm_scsi_list(args):
2293 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2295 dom = params[0]
2297 devs = []
2298 if serverType == SERVER_XEN_API:
2300 dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
2301 dscsi_properties = \
2302 map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
2303 dscsi_dict = {}
2304 for dscsi_property in dscsi_properties:
2305 devid = int(dscsi_property['dev']['devid'])
2306 try:
2307 dscsi_sxp = dscsi_dict[devid]
2308 except:
2309 dscsi_sxp = [['devs', []]]
2310 for key, value in dscsi_property.items():
2311 if key != 'dev':
2312 dscsi_sxp.append([key, value])
2313 dev_sxp = ['dev']
2314 dev_sxp.extend(map2sxp(dscsi_property['dev']))
2315 dscsi_sxp[0][1].append(dev_sxp)
2316 dscsi_dict[devid] = dscsi_sxp
2317 devs = map2sxp(dscsi_dict)
2319 else:
2320 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2322 # Sort devs by virtual HCTL.
2323 devs = vscsi_sort(devs)
2325 if use_long:
2326 map(PrettyPrint.prettyprint, devs)
2327 else:
2328 hdr = 0
2329 for x in devs:
2330 if hdr == 0:
2331 print "%-3s %-3s %-5s %-4s %-10s %-5s %-10s %-4s" \
2332 % ('Idx', 'BE', 'state', 'host', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2333 hdr = 1
2334 ni = parse_dev_info(x[1])
2335 ni['idx'] = int(x[0])
2336 for dev in x[1][0][1]:
2337 mi = vscsi_convert_sxp_to_dict(dev)
2338 print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
2339 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2341 def parse_block_configuration(args):
2342 dom = args[0]
2344 if args[1].startswith('tap:'):
2345 cls = 'tap'
2346 else:
2347 cls = 'vbd'
2349 vbd = [cls,
2350 ['uname', args[1]],
2351 ['dev', args[2]],
2352 ['mode', args[3]]]
2353 if len(args) == 5:
2354 vbd.append(['backend', args[4]])
2356 return (dom, vbd)
2359 def xm_block_attach(args):
2360 arg_check(args, 'block-attach', 4, 5)
2362 if serverType == SERVER_XEN_API:
2363 dom = args[0]
2364 uname = args[1]
2365 dev = args[2]
2366 mode = args[3]
2368 # First create new VDI
2369 vdi_record = {
2370 "name_label": "vdi" + str(uname.__hash__()),
2371 "name_description": "",
2372 "SR": get_default_SR(),
2373 "virtual_size": 0,
2374 "sector_size": 512,
2375 "type": "system",
2376 "sharable": False,
2377 "read_only": mode!="w",
2378 "other_config": {"location": uname}
2381 vdi_ref = server.xenapi.VDI.create(vdi_record)
2383 # Now create new VBD
2385 vbd_record = {
2386 "VM": get_single_vm(dom),
2387 "VDI": vdi_ref,
2388 "device": dev,
2389 "bootable": True,
2390 "mode": mode=="w" and "RW" or "RO",
2391 "type": "Disk",
2392 "qos_algorithm_type": "",
2393 "qos_algorithm_params": {}
2396 server.xenapi.VBD.create(vbd_record)
2398 else:
2399 (dom, vbd) = parse_block_configuration(args)
2400 server.xend.domain.device_create(dom, vbd)
2403 def xm_block_configure(args):
2404 arg_check(args, 'block-configure', 4, 5)
2406 (dom, vbd) = parse_block_configuration(args)
2407 server.xend.domain.device_configure(dom, vbd)
2410 def xm_network_attach(args):
2411 arg_check(args, 'network-attach', 1, 11)
2413 dom = args[0]
2414 vif = ['vif']
2415 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2416 'backend', 'vifname', 'rate', 'model', 'accel']
2418 if serverType == SERVER_XEN_API:
2419 vif_record = {
2420 "device": "eth0",
2421 "network": get_default_Network(),
2422 "VM": get_single_vm(dom),
2423 "MAC": "",
2424 "MTU": "",
2425 "qos_algorithm_type": "",
2426 "qos_algorithm_params": {},
2427 "other_config": {}
2430 def set(keys, val):
2431 record = vif_record
2432 for key in keys[:-1]:
2433 record = record[key]
2434 record[keys[-1]] = val
2436 def get_net_from_bridge(bridge):
2437 # In OSS, we just assert network.name_label == bridge name
2438 networks = dict([(record['name_label'], ref)
2439 for ref, record in server.xenapi.network
2440 .get_all_records().items()])
2441 if bridge not in networks.keys():
2442 raise "Unknown bridge name!"
2443 return networks[bridge]
2445 vif_conv = {
2446 'type':
2447 lambda x: None,
2448 'mac':
2449 lambda x: set(['MAC'], x),
2450 'bridge':
2451 lambda x: set(['network'], get_net_from_bridge(x)),
2452 'ip':
2453 lambda x: set(['other_config', 'ip'], x),
2454 'script':
2455 lambda x: set(['other_config', 'script'], x),
2456 'backend':
2457 lambda x: set(['other_config', 'backend'], x),
2458 'vifname':
2459 lambda x: set(['device'], x),
2460 'rate':
2461 lambda x: set(['qos_algorithm_params', 'rate'], x),
2462 'model':
2463 lambda x: None,
2464 'accel':
2465 lambda x: set(['other_config', 'accel'], x)
2468 for a in args[1:]:
2469 vif_param = a.split("=")
2470 if len(vif_param) != 2 or vif_param[1] == '' or \
2471 vif_param[0] not in vif_params:
2472 err("Invalid argument: %s" % a)
2473 usage('network-attach')
2474 else:
2475 vif_conv[vif_param[0]](vif_param[1])
2477 server.xenapi.VIF.create(vif_record)
2478 else:
2479 for a in args[1:]:
2480 vif_param = a.split("=")
2481 if len(vif_param) != 2 or vif_param[1] == '' or \
2482 vif_param[0] not in vif_params:
2483 err("Invalid argument: %s" % a)
2484 usage('network-attach')
2485 vif.append(vif_param)
2486 server.xend.domain.device_create(dom, vif)
2488 def parse_pci_configuration(args, state, opts = ''):
2489 dom = args[0]
2490 pci_dev_str = args[1]
2491 if len(args) == 3:
2492 vslot = args[2]
2493 else:
2494 vslot = AUTO_PHP_SLOT_STR
2495 pci=['pci']
2496 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
2497 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
2498 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
2499 r"(?P<func>[0-7])$", pci_dev_str)
2500 if pci_match == None:
2501 raise OptionError("Invalid argument: %s %s" % (pci_dev_str, vslot))
2502 pci_dev_info = pci_match.groupdict('0')
2504 try:
2505 pci_bdf =['dev', ['domain', '0x'+ pci_dev_info['domain']], \
2506 ['bus', '0x'+ pci_dev_info['bus']],
2507 ['slot', '0x'+ pci_dev_info['slot']],
2508 ['func', '0x'+ pci_dev_info['func']],
2509 ['vslot', '0x%x' % int(vslot, 16)]]
2510 except:
2511 raise OptionError("Invalid argument: %s %s" % (pci_dev_str, vslot))
2513 try:
2514 check_pci_opts(opts)
2515 except PciDeviceParseError, ex:
2516 raise OptionError(str(ex))
2518 pci.append(sxp.merge(pci_bdf, pci_opts_list_to_sxp(opts)))
2519 pci.append(['state', state])
2521 return (dom, pci)
2523 def xm_pci_attach(args):
2524 config_pci_opts = []
2525 (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
2526 for (k, v) in options:
2527 if k in ('-o', '--options'):
2528 if len(v.split('=')) != 2:
2529 err("Invalid pci attach option: %s" % v)
2530 usage('pci-attach')
2531 config_pci_opts.append(v.split('='))
2533 n = len([i for i in params if i != '--'])
2534 if n < 2 or n > 3:
2535 err("Invalid argument for 'xm pci-attach'")
2536 usage('pci-attach')
2538 (dom, pci) = parse_pci_configuration(params, 'Initialising',
2539 config_pci_opts)
2541 if serverType == SERVER_XEN_API:
2543 pci_dev = sxp.children(pci, 'dev')[0]
2544 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2545 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2546 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2547 func = int(sxp.child_value(pci_dev, 'func'), 16)
2548 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2549 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2551 target_ref = None
2552 for ppci_ref in server.xenapi.PPCI.get_all():
2553 if name == server.xenapi.PPCI.get_name(ppci_ref):
2554 target_ref = ppci_ref
2555 break
2556 if target_ref is None:
2557 raise OptionError("Device %s not found" % name)
2559 dpci_record = {
2560 "VM": get_single_vm(dom),
2561 "PPCI": target_ref,
2562 "hotplug_slot": vslot,
2563 "options": dict(config_pci_opts)
2565 server.xenapi.DPCI.create(dpci_record)
2567 else:
2568 server.xend.domain.device_configure(dom, pci)
2570 def parse_scsi_configuration(p_scsi, v_hctl, state):
2571 def get_devid(hctl):
2572 return int(hctl.split(':')[0])
2574 host_mode = 0
2575 scsi_devices = None
2577 if p_scsi is not None:
2578 # xm scsi-attach
2579 if v_hctl == "host":
2580 if serverType == SERVER_XEN_API:
2581 # TODO
2582 raise OptionError("SCSI devices assignment by HBA is not implemeted")
2583 host_mode = 1
2584 scsi_devices = vscsi_util.vscsi_get_scsidevices()
2585 elif len(v_hctl.split(':')) != 4:
2586 raise OptionError("Invalid argument: %s" % v_hctl)
2587 (p_hctl, devname) = \
2588 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
2589 if p_hctl is None:
2590 raise OptionError("Cannot find device '%s'" % p_scsi)
2591 if host_mode:
2592 scsi_info = []
2593 devid = get_devid(p_hctl)
2594 for pHCTL, devname, _, _ in scsi_devices:
2595 if get_devid(pHCTL) == devid:
2596 scsi_info.append([devid, pHCTL, devname, pHCTL])
2597 else:
2598 scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
2599 else:
2600 # xm scsi-detach
2601 if len(v_hctl.split(':')) != 4:
2602 raise OptionError("Invalid argument: %s" % v_hctl)
2603 scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
2605 scsi = ['vscsi', ['feature-host', host_mode]]
2606 for devid, pHCTL, devname, vHCTL in scsi_info:
2607 scsi.append(['dev', \
2608 ['state', state], \
2609 ['devid', devid], \
2610 ['p-dev', pHCTL], \
2611 ['p-devname', devname], \
2612 ['v-dev', vHCTL] \
2613 ])
2614 return scsi
2616 def xm_scsi_attach(args):
2617 arg_check(args, 'scsi-attach', 3, 4)
2618 dom = args[0]
2619 p_scsi = args[1]
2620 v_hctl = args[2]
2621 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2623 if serverType == SERVER_XEN_API:
2625 scsi_dev = sxp.children(scsi, 'dev')[0]
2626 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2627 target_ref = None
2628 for pscsi_ref in server.xenapi.PSCSI.get_all():
2629 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2630 target_ref = pscsi_ref
2631 break
2632 if target_ref is None:
2633 raise OptionError("Cannot find device '%s'" % p_scsi)
2635 dscsi_record = {
2636 "VM": get_single_vm(dom),
2637 "PSCSI": target_ref,
2638 "virtual_HCTL": v_hctl
2640 server.xenapi.DSCSI.create(dscsi_record)
2642 else:
2643 if len(args) == 4:
2644 scsi.append(['backend', args[3]])
2645 server.xend.domain.device_configure(dom, scsi)
2647 def detach(args, deviceClass):
2648 rm_cfg = True
2649 dom = args[0]
2650 dev = args[1]
2651 try:
2652 force = args[2]
2653 if (force != "--force") and (force != "-f"):
2654 print "Ignoring option %s"%(force)
2655 force = None
2656 except IndexError:
2657 force = None
2659 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2662 def xm_block_detach(args):
2663 if serverType == SERVER_XEN_API:
2664 arg_check(args, "block-detach", 2, 3)
2665 dom = args[0]
2666 dev = args[1]
2667 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2668 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2669 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2670 if len(vbd_refs) > 0:
2671 vbd_ref = vbd_refs[0]
2672 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2674 server.xenapi.VBD.destroy(vbd_ref)
2676 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2677 server.xenapi.VDI.destroy(vdi_ref)
2678 else:
2679 raise OptionError("Cannot find device '%s' in domain '%s'"
2680 % (dev,dom))
2681 else:
2682 arg_check(args, 'block-detach', 2, 3)
2683 dom = args[0]
2684 dev = args[1]
2685 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2686 if dc == "tap":
2687 detach(args, 'tap')
2688 else:
2689 detach(args, 'vbd')
2691 def xm_network_detach(args):
2692 if serverType == SERVER_XEN_API:
2693 arg_check(args, "network-detach", 2, 3)
2694 dom = args[0]
2695 devid = args[1]
2696 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2697 vif_refs = [vif_ref for vif_ref in vif_refs
2698 if server.xenapi.VIF.\
2699 get_runtime_properties(vif_ref)["handle"] == devid]
2700 if len(vif_refs) > 0:
2701 vif_ref = vif_refs[0]
2703 server.xenapi.VIF.destroy(vif_ref)
2704 else:
2705 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2706 else:
2707 arg_check(args, 'network-detach', 2, 3)
2708 detach(args, 'vif')
2710 def xm_pci_detach(args):
2711 arg_check(args, 'pci-detach', 2)
2712 (dom, pci) = parse_pci_configuration(args, 'Closing')
2714 if serverType == SERVER_XEN_API:
2716 pci_dev = sxp.children(pci, 'dev')[0]
2717 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2718 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2719 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2720 func = int(sxp.child_value(pci_dev, 'func'), 16)
2721 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2722 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2724 target_ref = None
2725 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2726 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2727 if name == server.xenapi.PPCI.get_name(ppci_ref):
2728 target_ref = ppci_ref
2729 server.xenapi.DPCI.destroy(dpci_ref)
2730 break
2731 if target_ref is None:
2732 raise OptionError("Device %s not assigned" % name)
2734 else:
2735 server.xend.domain.device_configure(dom, pci)
2737 def xm_scsi_detach(args):
2738 arg_check(args, 'scsi-detach', 2)
2739 dom = args[0]
2740 v_hctl = args[1]
2741 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
2743 if serverType == SERVER_XEN_API:
2745 target_ref = None
2746 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
2747 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
2748 target_ref = dscsi_ref
2749 break
2750 if target_ref is None:
2751 raise OptionError("Device %s not assigned" % v_hctl)
2753 server.xenapi.DSCSI.destroy(target_ref)
2755 else:
2756 server.xend.domain.device_configure(dom, scsi)
2758 def xm_vnet_list(args):
2759 xenapi_unsupported()
2760 try:
2761 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2762 except getopt.GetoptError, opterr:
2763 err(opterr)
2764 usage('vnet-list')
2766 use_long = 0
2767 for (k, v) in options:
2768 if k in ['-l', '--long']:
2769 use_long = 1
2771 if params:
2772 use_long = 1
2773 vnets = params
2774 else:
2775 vnets = server.xend_vnets()
2777 for vnet in vnets:
2778 try:
2779 if use_long:
2780 info = server.xend_vnet(vnet)
2781 PrettyPrint.prettyprint(info)
2782 else:
2783 print vnet
2784 except Exception, ex:
2785 print vnet, ex
2787 def xm_vnet_create(args):
2788 xenapi_unsupported()
2789 arg_check(args, "vnet-create", 1)
2790 conf = args[0]
2791 if not os.access(conf, os.R_OK):
2792 print "File not found: %s" % conf
2793 sys.exit(1)
2795 server.xend_vnet_create(conf)
2797 def xm_vnet_delete(args):
2798 xenapi_unsupported()
2799 arg_check(args, "vnet-delete", 1)
2800 vnet = args[0]
2801 server.xend_vnet_delete(vnet)
2803 def xm_network_new(args):
2804 xenapi_only()
2805 arg_check(args, "network-new", 1)
2806 network = args[0]
2808 record = {
2809 "name_label": network,
2810 "name_description": "",
2811 "other_config": {},
2812 "default_gateway": "",
2813 "default_netmask": ""
2816 server.xenapi.network.create(record)
2818 def xm_network_del(args):
2819 xenapi_only()
2820 arg_check(args, "network-del", 1)
2821 network = args[0]
2823 networks = dict([(record['name_label'], ref)
2824 for ref, record in
2825 server.xenapi.network.get_all_records().items()])
2827 if network not in networks.keys():
2828 raise ValueError("'%s' is not a valid network name" % network)
2830 server.xenapi.network.destroy(networks[network])
2832 def xm_network_show(args):
2833 xenapi_only()
2834 arg_check(args, "network-show", 0)
2836 networks = server.xenapi.network.get_all_records()
2837 pifs = server.xenapi.PIF.get_all_records()
2838 vifs = server.xenapi.VIF.get_all_records()
2840 print '%-20s %-40s %-10s' % \
2841 ('Name', 'VIFs', 'PIFs')
2843 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2845 for network_ref, network in networks.items():
2846 for i in range(max(len(network['PIFs']),
2847 len(network['VIFs']), 1)):
2848 if i < len(network['PIFs']):
2849 pif_uuid = network['PIFs'][i]
2850 else:
2851 pif_uuid = None
2853 if i < len(network['VIFs']):
2854 vif_uuid = network['VIFs'][i]
2855 else:
2856 vif_uuid = None
2858 pif = pifs.get(pif_uuid, None)
2859 vif = vifs.get(vif_uuid, None)
2861 if vif:
2862 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2863 vif = "%s.%s" % (dom_name, vif['device'])
2864 else:
2865 vif = ''
2867 if pif:
2868 if int(pif['VLAN']) > -1:
2869 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2870 else:
2871 pif = pif['device']
2872 else:
2873 pif = ''
2875 if i == 0:
2876 r = {'name_label':network['name_label'],
2877 'vif':vif, 'pif':pif}
2878 else:
2879 r = {'name_label':'', 'vif':vif, 'pif':pif}
2881 print format2 % r
2883 def xm_tmem_list(args):
2884 try:
2885 (options, params) = getopt.gnu_getopt(args, 'la', ['long','all'])
2886 except getopt.GetoptError, opterr:
2887 err(opterr)
2888 usage('tmem-list')
2890 use_long = False
2891 for (k, v) in options:
2892 if k in ['-l', '--long']:
2893 use_long = True
2895 all = False
2896 for (k, v) in options:
2897 if k in ['-a', '--all']:
2898 all = True
2900 if not all and len(params) == 0:
2901 err('You must specify -a or --all or a domain id.')
2902 usage('tmem-list')
2904 if all:
2905 domid = -1
2906 else:
2907 try:
2908 domid = int(params[0])
2909 params = params[1:]
2910 except:
2911 err('Unrecognized domain id: %s' % params[0])
2912 usage('tmem-list')
2914 if serverType == SERVER_XEN_API:
2915 print server.xenapi.host.tmem_list(domid,use_long)
2916 else:
2917 print server.xend.node.tmem_list(domid,use_long)
2919 def parse_tmem_args(args, name):
2920 try:
2921 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
2922 except getopt.GetoptError, opterr:
2923 err(opterr)
2924 usage(name)
2926 all = False
2927 for (k, v) in options:
2928 if k in ['-a', '--all']:
2929 all = True
2931 if not all and len(params) == 0:
2932 err('You must specify -a or --all or a domain id.')
2933 usage(name)
2935 if all:
2936 domid = -1
2937 else:
2938 try:
2939 domid = int(params[0])
2940 params = params[1:]
2941 except:
2942 err('Unrecognized domain id: %s' % params[0])
2943 usage(name)
2945 return domid, params
2947 def xm_tmem_destroy(args):
2948 (domid, _) = parse_tmem_args(args, 'tmem-destroy')
2949 if serverType == SERVER_XEN_API:
2950 server.xenapi.host.tmem_destroy(domid)
2951 else:
2952 server.xend.node.tmem_destroy(domid)
2954 def xm_tmem_thaw(args):
2955 (domid, _) = parse_tmem_args(args, 'tmem-thaw')
2956 if serverType == SERVER_XEN_API:
2957 server.xenapi.host.tmem_thaw(domid)
2958 else:
2959 server.xend.node.tmem_thaw(domid)
2961 def xm_tmem_freeze(args):
2962 (domid, _) = parse_tmem_args(args, 'tmem-freeze')
2963 if serverType == SERVER_XEN_API:
2964 server.xenapi.host.tmem_freeze(domid)
2965 else:
2966 server.xend.node.tmem_freeze(domid)
2968 def xm_tmem_flush(args):
2969 try:
2970 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
2971 except getopt.GetoptError, opterr:
2972 err(opterr)
2973 usage(name)
2975 all = False
2976 for (k, v) in options:
2977 if k in ['-a', '--all']:
2978 all = True
2980 if not all and len(params) == 0:
2981 err('You must specify -a or --all or a domain id.')
2982 usage('tmem-flush')
2984 if all:
2985 domid = -1
2986 else:
2987 try:
2988 domid = int(params[0])
2989 params = params[1:]
2990 except:
2991 err('Unrecognized domain id: %s' % params[0])
2992 usage('tmem-flush')
2994 pages = -1
2995 for (k, v) in options:
2996 if k in ['-p', '--pages']:
2997 pages = v
2999 if serverType == SERVER_XEN_API:
3000 server.xenapi.host.tmem_flush(domid,pages)
3001 else:
3002 server.xend.node.tmem_flush(domid,pages)
3004 def xm_tmem_set(args):
3005 try:
3006 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
3007 except getopt.GetoptError, opterr:
3008 err(opterr)
3009 usage(name)
3011 all = False
3012 for (k, v) in options:
3013 if k in ['-a', '--all']:
3014 all = True
3016 if not all and len(params) == 0:
3017 err('You must specify -a or --all or a domain id.')
3018 usage('tmem-set')
3020 if all:
3021 domid = -1
3022 else:
3023 try:
3024 domid = int(params[0])
3025 params = params[1:]
3026 except:
3027 err('Unrecognized domain id: %s' % params[0])
3028 usage('tmem-set')
3030 weight = None
3031 cap = None
3032 compress = None
3033 for item in params:
3034 if item.startswith('weight='):
3035 try:
3036 weight = int(item[7:])
3037 except:
3038 err('weight should be a integer')
3039 usage('tmem-set')
3040 if item.startswith('cap='):
3041 cap = int(item[4:])
3042 if item.startswith('compress='):
3043 compress = int(item[9:])
3045 if weight is None and cap is None and compress is None:
3046 err('Unrecognized tmem configuration option: %s' % item)
3047 usage('tmem-set')
3049 if serverType == SERVER_XEN_API:
3050 if weight is not None:
3051 server.xenapi.host.tmem_set_weight(domid, weight)
3052 if cap is not None:
3053 server.xenapi.host.tmem_set_cap(domid, cap)
3054 if compress is not None:
3055 server.xenapi.host.tmem_set_compress(domid, compress)
3056 else:
3057 if weight is not None:
3058 server.xend.node.tmem_set_weight(domid, weight)
3059 if cap is not None:
3060 server.xend.node.tmem_set_cap(domid, cap)
3061 if compress is not None:
3062 server.xend.node.tmem_set_compress(domid, compress)
3065 commands = {
3066 "shell": xm_shell,
3067 "event-monitor": xm_event_monitor,
3068 # console commands
3069 "console": xm_console,
3070 "vncviewer": xm_vncviewer,
3071 # xenstat commands
3072 "top": xm_top,
3073 # domain commands
3074 "delete": xm_delete,
3075 "destroy": xm_destroy,
3076 "domid": xm_domid,
3077 "domname": xm_domname,
3078 "dump-core": xm_dump_core,
3079 "reboot": xm_reboot,
3080 "rename": xm_rename,
3081 "reset": xm_reset,
3082 "restore": xm_restore,
3083 "resume": xm_resume,
3084 "save": xm_save,
3085 "shutdown": xm_shutdown,
3086 "start": xm_start,
3087 "sysrq": xm_sysrq,
3088 "trigger": xm_trigger,
3089 "uptime": xm_uptime,
3090 "suspend": xm_suspend,
3091 "list": xm_list,
3092 # memory commands
3093 "mem-max": xm_mem_max,
3094 "mem-set": xm_mem_set,
3095 # cpu commands
3096 "vcpu-pin": xm_vcpu_pin,
3097 "vcpu-list": xm_vcpu_list,
3098 "vcpu-set": xm_vcpu_set,
3099 # special
3100 "pause": xm_pause,
3101 "unpause": xm_unpause,
3102 # host commands
3103 "debug-keys": xm_debug_keys,
3104 "dmesg": xm_dmesg,
3105 "info": xm_info,
3106 "log": xm_log,
3107 "serve": xm_serve,
3108 # scheduler
3109 "sched-sedf": xm_sched_sedf,
3110 "sched-credit": xm_sched_credit,
3111 # block
3112 "block-attach": xm_block_attach,
3113 "block-detach": xm_block_detach,
3114 "block-list": xm_block_list,
3115 "block-configure": xm_block_configure,
3116 # network (AKA vifs)
3117 "network-attach": xm_network_attach,
3118 "network-detach": xm_network_detach,
3119 "network-list": xm_network_list,
3120 # network (as in XenAPI)
3121 "network-new": xm_network_new,
3122 "network-del": xm_network_del,
3123 "network-show": xm_network_show,
3124 # vnet
3125 "vnet-list": xm_vnet_list,
3126 "vnet-create": xm_vnet_create,
3127 "vnet-delete": xm_vnet_delete,
3128 # vtpm
3129 "vtpm-list": xm_vtpm_list,
3130 #pci
3131 "pci-attach": xm_pci_attach,
3132 "pci-detach": xm_pci_detach,
3133 "pci-list": xm_pci_list,
3134 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
3135 # vscsi
3136 "scsi-attach": xm_scsi_attach,
3137 "scsi-detach": xm_scsi_detach,
3138 "scsi-list": xm_scsi_list,
3139 # tmem
3140 "tmem-thaw": xm_tmem_thaw,
3141 "tmem-freeze": xm_tmem_freeze,
3142 "tmem-flush": xm_tmem_flush,
3143 "tmem-destroy": xm_tmem_destroy,
3144 "tmem-list": xm_tmem_list,
3145 "tmem-set": xm_tmem_set,
3148 ## The commands supported by a separate argument parser in xend.xm.
3149 IMPORTED_COMMANDS = [
3150 'create',
3151 'new',
3152 'migrate',
3153 'labels',
3154 'dumppolicy',
3155 'addlabel',
3156 'rmlabel',
3157 'getlabel',
3158 'dry-run',
3159 'resources',
3160 'getpolicy',
3161 'setpolicy',
3162 'resetpolicy',
3165 for c in IMPORTED_COMMANDS:
3166 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
3168 aliases = {
3169 "balloon": "mem-set",
3170 "set-vcpus": "vcpu-set",
3171 "vif-list": "network-list",
3172 "vbd-create": "block-attach",
3173 "vbd-destroy": "block-detach",
3174 "vbd-list": "block-list",
3178 def xm_lookup_cmd(cmd):
3179 if commands.has_key(cmd):
3180 return commands[cmd]
3181 elif aliases.has_key(cmd):
3182 deprecated(cmd,aliases[cmd])
3183 return commands[aliases[cmd]]
3184 elif cmd == 'help':
3185 longHelp()
3186 sys.exit(0)
3187 else:
3188 # simulate getopt's prefix matching behaviour
3189 if len(cmd) > 1:
3190 same_prefix_cmds = [commands[c] for c in commands.keys() \
3191 if c[:len(cmd)] == cmd]
3192 # only execute if there is only 1 match
3193 if len(same_prefix_cmds) == 1:
3194 return same_prefix_cmds[0]
3195 return None
3197 def deprecated(old,new):
3198 print >>sys.stderr, (
3199 "Command %s is deprecated. Please use xm %s instead." % (old, new))
3201 def main(argv=sys.argv):
3202 if len(argv) < 2:
3203 usage()
3205 # intercept --help(-h) and output our own help
3206 for help in ['--help', '-h']:
3207 if help in argv[1:]:
3208 if help == argv[1]:
3209 longHelp()
3210 sys.exit(0)
3211 else:
3212 usage(argv[1])
3214 cmd_name = argv[1]
3215 cmd = xm_lookup_cmd(cmd_name)
3216 if cmd:
3217 # strip off prog name and subcmd
3218 args = argv[2:]
3219 _, rc = _run_cmd(cmd, cmd_name, args)
3220 sys.exit(rc)
3221 else:
3222 err('Subcommand %s not found!' % cmd_name)
3223 usage()
3225 def _run_cmd(cmd, cmd_name, args):
3226 global server
3228 try:
3229 if server is None:
3230 if serverType == SERVER_XEN_API:
3231 server = XenAPI.Session(serverURI)
3232 username, password = parseAuthentication()
3233 server.login_with_password(username, password)
3234 def logout():
3235 try:
3236 server.xenapi.session.logout()
3237 except:
3238 pass
3239 atexit.register(logout)
3240 else:
3241 server = ServerProxy(serverURI)
3243 return True, cmd(args)
3244 except socket.error, ex:
3245 if os.geteuid() != 0:
3246 err("Most commands need root access. Please try again as root.")
3247 else:
3248 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
3249 except KeyboardInterrupt:
3250 print "Interrupted."
3251 return True, ''
3252 except IOError, ex:
3253 if os.geteuid() != 0:
3254 err("Most commands need root access. Please try again as root.")
3255 else:
3256 err("Unable to connect to xend: %s." % ex[1])
3257 except SystemExit, code:
3258 return code == 0, code
3259 except XenAPI.Failure, exn:
3260 for line in [''] + wrap(str(exn), 80) + ['']:
3261 print >>sys.stderr, line
3262 except xmlrpclib.Fault, ex:
3263 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
3264 err("Domain '%s' does not exist." % ex.faultString)
3265 return False, ex.faultCode
3266 else:
3267 err(ex.faultString)
3268 _usage(cmd_name)
3269 except xmlrpclib.ProtocolError, ex:
3270 if ex.errcode == -1:
3271 print >>sys.stderr, (
3272 "Xend has probably crashed! Invalid or missing HTTP "
3273 "status code.")
3274 else:
3275 print >>sys.stderr, (
3276 "Xend has probably crashed! ProtocolError(%d, %s)." %
3277 (ex.errcode, ex.errmsg))
3278 except (ValueError, OverflowError):
3279 err("Invalid argument.")
3280 _usage(cmd_name)
3281 except OptionError, e:
3282 err(str(e))
3283 _usage(cmd_name)
3284 print e.usage
3285 except XenAPIUnsupportedException, e:
3286 err(str(e))
3287 except XSMError, e:
3288 err(str(e))
3289 except Exception, e:
3290 if serverType != SERVER_XEN_API:
3291 import xen.util.xsm.xsm as security
3292 if isinstance(e, security.XSMError):
3293 err(str(e))
3294 return False, 1
3295 print "Unexpected error:", sys.exc_info()[0]
3296 print
3297 print "Please report to xen-devel@lists.xensource.com"
3298 raise
3300 return False, 1
3302 if __name__ == "__main__":
3303 main()