ia64/xen-unstable

view tools/python/xen/xm/main.py @ 19792:407e2e7dca5b

Allow tools to see the hypervisor command line.

This is useful from tools in the same way /proc/cmdline is useful for
the domain 0 kernel.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:20:45 2009 +0100 (2009-06-18)
parents 85fdfb7da88c
children
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)
2179 def xm_pci_list(args):
2180 (use_long, params) = arg_check_for_resource_list(args, "pci-list")
2182 dom = params[0]
2184 devs = []
2185 if serverType == SERVER_XEN_API:
2186 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2187 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2188 ppci_record = server.xenapi.PPCI.get_record(ppci_ref)
2189 dev = {
2190 "domain": int(ppci_record["domain"]),
2191 "bus": int(ppci_record["bus"]),
2192 "slot": int(ppci_record["slot"]),
2193 "func": int(ppci_record["func"]),
2194 "vslot": int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref))
2196 devs.append(dev)
2198 else:
2199 for x in server.xend.domain.getDeviceSxprs(dom, 'pci'):
2200 dev = {
2201 "domain": int(x["domain"], 16),
2202 "bus": int(x["bus"], 16),
2203 "slot": int(x["slot"], 16),
2204 "func": int(x["func"], 16),
2205 "vslot": int(x["vslot"], 16)
2207 devs.append(dev)
2209 if len(devs) == 0:
2210 return
2212 devs.sort(None, lambda x: x['vslot'] << 32 | PCI_BDF(x['domain'], x['bus'],
2213 x['slot'], x['func']))
2215 has_vslot = False
2216 for x in devs:
2217 if x['vslot'] == AUTO_PHP_SLOT:
2218 x['show_vslot'] = '-'
2219 else:
2220 x['show_vslot'] = "0x%02x" % x['vslot']
2221 has_vslot = True
2223 hdr_str = 'domain bus slot func'
2224 fmt_str = '0x%(domain)04x 0x%(bus)02x 0x%(slot)02x 0x%(func)x'
2225 if has_vslot:
2226 hdr_str = 'VSlt ' + hdr_str
2227 fmt_str = '%(show_vslot)-4s ' + fmt_str
2229 print hdr_str
2230 for x in devs:
2231 print fmt_str % x
2234 def parse_pci_info(info):
2235 def get_info(n, t, d):
2236 return t(sxp.child_value(info, n, d))
2237 return {
2238 'domain' : get_info('domain', parse_hex, 0),
2239 'bus' : get_info('bus', parse_hex, -1),
2240 'slot' : get_info('slot', parse_hex, -1),
2241 'func' : get_info('func', parse_hex, -1)
2244 def xm_pci_list_assignable_devices(args):
2245 xenapi_unsupported()
2246 arg_check(args, "pci-list-assignable-devices", 0)
2248 devs = server.xend.node.pciinfo()
2250 fmt_str = "%(domain)04x:%(bus)02x:%(slot)02x.%(func)01x"
2251 for x in devs:
2252 pci = parse_pci_info(x)
2253 print fmt_str % pci
2256 def vscsi_sort(devs):
2257 def sort_hctl(ds, l):
2258 s = []
2259 for d1 in ds:
2260 for d2 in d1:
2261 v_dev = sxp.child_value(d2, 'v-dev')
2262 n = int(v_dev.split(':')[l])
2263 try:
2264 j = s[n]
2265 except IndexError:
2266 j = []
2267 s.extend([ [] for _ in range(len(s), n+1) ])
2268 j.append(d2)
2269 s[n] = j
2270 return s
2272 for i in range(len(devs)):
2273 ds1 = [ devs[i][1][0][1] ]
2274 ds1 = sort_hctl(ds1, 3)
2275 ds1 = sort_hctl(ds1, 2)
2276 ds1 = sort_hctl(ds1, 1)
2277 ds2 = []
2278 for d in ds1:
2279 ds2.extend(d)
2280 devs[i][1][0][1] = ds2
2281 return devs
2283 def vscsi_convert_sxp_to_dict(dev_sxp):
2284 dev_dict = {}
2285 for opt_val in dev_sxp[1:]:
2286 try:
2287 opt, val = opt_val
2288 dev_dict[opt] = val
2289 except TypeError:
2290 pass
2291 return dev_dict
2293 def xm_scsi_list(args):
2294 (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
2296 dom = params[0]
2298 devs = []
2299 if serverType == SERVER_XEN_API:
2301 dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
2302 dscsi_properties = \
2303 map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
2304 dscsi_dict = {}
2305 for dscsi_property in dscsi_properties:
2306 devid = int(dscsi_property['dev']['devid'])
2307 try:
2308 dscsi_sxp = dscsi_dict[devid]
2309 except:
2310 dscsi_sxp = [['devs', []]]
2311 for key, value in dscsi_property.items():
2312 if key != 'dev':
2313 dscsi_sxp.append([key, value])
2314 dev_sxp = ['dev']
2315 dev_sxp.extend(map2sxp(dscsi_property['dev']))
2316 dscsi_sxp[0][1].append(dev_sxp)
2317 dscsi_dict[devid] = dscsi_sxp
2318 devs = map2sxp(dscsi_dict)
2320 else:
2321 devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
2323 # Sort devs by virtual HCTL.
2324 devs = vscsi_sort(devs)
2326 if use_long:
2327 map(PrettyPrint.prettyprint, devs)
2328 else:
2329 hdr = 0
2330 for x in devs:
2331 if hdr == 0:
2332 print "%-3s %-3s %-5s %-4s %-10s %-5s %-10s %-4s" \
2333 % ('Idx', 'BE', 'state', 'host', 'phy-hctl', 'phy', 'vir-hctl', 'devstate')
2334 hdr = 1
2335 ni = parse_dev_info(x[1])
2336 ni['idx'] = int(x[0])
2337 for dev in x[1][0][1]:
2338 mi = vscsi_convert_sxp_to_dict(dev)
2339 print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
2340 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
2342 def parse_block_configuration(args):
2343 dom = args[0]
2345 if args[1].startswith('tap:'):
2346 cls = 'tap'
2347 else:
2348 cls = 'vbd'
2350 vbd = [cls,
2351 ['uname', args[1]],
2352 ['dev', args[2]],
2353 ['mode', args[3]]]
2354 if len(args) == 5:
2355 vbd.append(['backend', args[4]])
2357 return (dom, vbd)
2360 def xm_block_attach(args):
2361 arg_check(args, 'block-attach', 4, 5)
2363 if serverType == SERVER_XEN_API:
2364 dom = args[0]
2365 uname = args[1]
2366 dev = args[2]
2367 mode = args[3]
2369 # First create new VDI
2370 vdi_record = {
2371 "name_label": "vdi" + str(uname.__hash__()),
2372 "name_description": "",
2373 "SR": get_default_SR(),
2374 "virtual_size": 0,
2375 "sector_size": 512,
2376 "type": "system",
2377 "sharable": False,
2378 "read_only": mode!="w",
2379 "other_config": {"location": uname}
2382 vdi_ref = server.xenapi.VDI.create(vdi_record)
2384 # Now create new VBD
2386 vbd_record = {
2387 "VM": get_single_vm(dom),
2388 "VDI": vdi_ref,
2389 "device": dev,
2390 "bootable": True,
2391 "mode": mode=="w" and "RW" or "RO",
2392 "type": "Disk",
2393 "qos_algorithm_type": "",
2394 "qos_algorithm_params": {}
2397 server.xenapi.VBD.create(vbd_record)
2399 else:
2400 (dom, vbd) = parse_block_configuration(args)
2401 server.xend.domain.device_create(dom, vbd)
2404 def xm_block_configure(args):
2405 arg_check(args, 'block-configure', 4, 5)
2407 (dom, vbd) = parse_block_configuration(args)
2408 server.xend.domain.device_configure(dom, vbd)
2411 def xm_network_attach(args):
2412 arg_check(args, 'network-attach', 1, 11)
2414 dom = args[0]
2415 vif = ['vif']
2416 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2417 'backend', 'vifname', 'rate', 'model', 'accel']
2419 if serverType == SERVER_XEN_API:
2420 vif_record = {
2421 "device": "eth0",
2422 "network": get_default_Network(),
2423 "VM": get_single_vm(dom),
2424 "MAC": "",
2425 "MTU": "",
2426 "qos_algorithm_type": "",
2427 "qos_algorithm_params": {},
2428 "other_config": {}
2431 def set(keys, val):
2432 record = vif_record
2433 for key in keys[:-1]:
2434 record = record[key]
2435 record[keys[-1]] = val
2437 def get_net_from_bridge(bridge):
2438 # In OSS, we just assert network.name_label == bridge name
2439 networks = dict([(record['name_label'], ref)
2440 for ref, record in server.xenapi.network
2441 .get_all_records().items()])
2442 if bridge not in networks.keys():
2443 raise "Unknown bridge name!"
2444 return networks[bridge]
2446 vif_conv = {
2447 'type':
2448 lambda x: None,
2449 'mac':
2450 lambda x: set(['MAC'], x),
2451 'bridge':
2452 lambda x: set(['network'], get_net_from_bridge(x)),
2453 'ip':
2454 lambda x: set(['other_config', 'ip'], x),
2455 'script':
2456 lambda x: set(['other_config', 'script'], x),
2457 'backend':
2458 lambda x: set(['other_config', 'backend'], x),
2459 'vifname':
2460 lambda x: set(['device'], x),
2461 'rate':
2462 lambda x: set(['qos_algorithm_params', 'rate'], x),
2463 'model':
2464 lambda x: None,
2465 'accel':
2466 lambda x: set(['other_config', 'accel'], x)
2469 for a in args[1:]:
2470 vif_param = a.split("=")
2471 if len(vif_param) != 2 or vif_param[1] == '' or \
2472 vif_param[0] not in vif_params:
2473 err("Invalid argument: %s" % a)
2474 usage('network-attach')
2475 else:
2476 vif_conv[vif_param[0]](vif_param[1])
2478 server.xenapi.VIF.create(vif_record)
2479 else:
2480 for a in args[1:]:
2481 vif_param = a.split("=")
2482 if len(vif_param) != 2 or vif_param[1] == '' or \
2483 vif_param[0] not in vif_params:
2484 err("Invalid argument: %s" % a)
2485 usage('network-attach')
2486 vif.append(vif_param)
2487 server.xend.domain.device_create(dom, vif)
2489 def parse_pci_configuration(args, state, opts = ''):
2490 dom = args[0]
2491 pci_dev_str = args[1]
2492 if len(args) == 3:
2493 pci_dev_str += '@' + args[2]
2494 if len(opts) > 0:
2495 pci_dev_str += ',' + serialise_pci_opts(opts)
2497 try:
2498 pci_dev = parse_pci_name_extended(pci_dev_str)
2499 except PciDeviceParseError, ex:
2500 raise OptionError(str(ex))
2502 return (dom, pci_convert_dict_to_sxp(pci_dev, state))
2504 def xm_pci_attach(args):
2505 config_pci_opts = []
2506 (options, params) = getopt.gnu_getopt(args, 'o:', ['options='])
2507 for (k, v) in options:
2508 if k in ('-o', '--options'):
2509 if len(v.split('=')) != 2:
2510 err("Invalid pci attach option: %s" % v)
2511 usage('pci-attach')
2512 config_pci_opts.append(v.split('='))
2514 n = len([i for i in params if i != '--'])
2515 if n < 2 or n > 3:
2516 err("Invalid argument for 'xm pci-attach'")
2517 usage('pci-attach')
2519 (dom, pci) = parse_pci_configuration(params, 'Initialising',
2520 config_pci_opts)
2522 if serverType == SERVER_XEN_API:
2524 pci_dev = sxp.children(pci, 'dev')[0]
2525 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2526 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2527 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2528 func = int(sxp.child_value(pci_dev, 'func'), 16)
2529 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2530 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2532 target_ref = None
2533 for ppci_ref in server.xenapi.PPCI.get_all():
2534 if name == server.xenapi.PPCI.get_name(ppci_ref):
2535 target_ref = ppci_ref
2536 break
2537 if target_ref is None:
2538 raise OptionError("Device %s not found" % name)
2540 dpci_record = {
2541 "VM": get_single_vm(dom),
2542 "PPCI": target_ref,
2543 "hotplug_slot": vslot,
2544 "options": dict(config_pci_opts)
2546 server.xenapi.DPCI.create(dpci_record)
2548 else:
2549 server.xend.domain.device_configure(dom, pci)
2551 def parse_scsi_configuration(p_scsi, v_hctl, state):
2552 def get_devid(hctl):
2553 return int(hctl.split(':')[0])
2555 host_mode = 0
2556 scsi_devices = None
2558 if p_scsi is not None:
2559 # xm scsi-attach
2560 if v_hctl == "host":
2561 if serverType == SERVER_XEN_API:
2562 # TODO
2563 raise OptionError("SCSI devices assignment by HBA is not implemeted")
2564 host_mode = 1
2565 scsi_devices = vscsi_util.vscsi_get_scsidevices()
2566 elif len(v_hctl.split(':')) != 4:
2567 raise OptionError("Invalid argument: %s" % v_hctl)
2568 (p_hctl, devname) = \
2569 vscsi_util.vscsi_get_hctl_and_devname_by(p_scsi, scsi_devices)
2570 if p_hctl is None:
2571 raise OptionError("Cannot find device '%s'" % p_scsi)
2572 if host_mode:
2573 scsi_info = []
2574 devid = get_devid(p_hctl)
2575 for pHCTL, devname, _, _ in scsi_devices:
2576 if get_devid(pHCTL) == devid:
2577 scsi_info.append([devid, pHCTL, devname, pHCTL])
2578 else:
2579 scsi_info = [[get_devid(v_hctl), p_hctl, devname, v_hctl]]
2580 else:
2581 # xm scsi-detach
2582 if len(v_hctl.split(':')) != 4:
2583 raise OptionError("Invalid argument: %s" % v_hctl)
2584 scsi_info = [[get_devid(v_hctl), None, None, v_hctl]]
2586 scsi = ['vscsi', ['feature-host', host_mode]]
2587 for devid, pHCTL, devname, vHCTL in scsi_info:
2588 scsi.append(['dev', \
2589 ['state', state], \
2590 ['devid', devid], \
2591 ['p-dev', pHCTL], \
2592 ['p-devname', devname], \
2593 ['v-dev', vHCTL] \
2594 ])
2595 return scsi
2597 def xm_scsi_attach(args):
2598 arg_check(args, 'scsi-attach', 3, 4)
2599 dom = args[0]
2600 p_scsi = args[1]
2601 v_hctl = args[2]
2602 scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
2604 if serverType == SERVER_XEN_API:
2606 scsi_dev = sxp.children(scsi, 'dev')[0]
2607 p_hctl = sxp.child_value(scsi_dev, 'p-dev')
2608 target_ref = None
2609 for pscsi_ref in server.xenapi.PSCSI.get_all():
2610 if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
2611 target_ref = pscsi_ref
2612 break
2613 if target_ref is None:
2614 raise OptionError("Cannot find device '%s'" % p_scsi)
2616 dscsi_record = {
2617 "VM": get_single_vm(dom),
2618 "PSCSI": target_ref,
2619 "virtual_HCTL": v_hctl
2621 server.xenapi.DSCSI.create(dscsi_record)
2623 else:
2624 if len(args) == 4:
2625 scsi.append(['backend', args[3]])
2626 server.xend.domain.device_configure(dom, scsi)
2628 def detach(args, deviceClass):
2629 rm_cfg = True
2630 dom = args[0]
2631 dev = args[1]
2632 try:
2633 force = args[2]
2634 if (force != "--force") and (force != "-f"):
2635 print "Ignoring option %s"%(force)
2636 force = None
2637 except IndexError:
2638 force = None
2640 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2643 def xm_block_detach(args):
2644 if serverType == SERVER_XEN_API:
2645 arg_check(args, "block-detach", 2, 3)
2646 dom = args[0]
2647 dev = args[1]
2648 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2649 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2650 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2651 if len(vbd_refs) > 0:
2652 vbd_ref = vbd_refs[0]
2653 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2655 server.xenapi.VBD.destroy(vbd_ref)
2657 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2658 server.xenapi.VDI.destroy(vdi_ref)
2659 else:
2660 raise OptionError("Cannot find device '%s' in domain '%s'"
2661 % (dev,dom))
2662 else:
2663 arg_check(args, 'block-detach', 2, 3)
2664 dom = args[0]
2665 dev = args[1]
2666 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2667 if dc == "tap":
2668 detach(args, 'tap')
2669 else:
2670 detach(args, 'vbd')
2672 def xm_network_detach(args):
2673 if serverType == SERVER_XEN_API:
2674 arg_check(args, "network-detach", 2, 3)
2675 dom = args[0]
2676 devid = args[1]
2677 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2678 vif_refs = [vif_ref for vif_ref in vif_refs
2679 if server.xenapi.VIF.\
2680 get_runtime_properties(vif_ref)["handle"] == devid]
2681 if len(vif_refs) > 0:
2682 vif_ref = vif_refs[0]
2684 server.xenapi.VIF.destroy(vif_ref)
2685 else:
2686 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2687 else:
2688 arg_check(args, 'network-detach', 2, 3)
2689 detach(args, 'vif')
2691 def xm_pci_detach(args):
2692 arg_check(args, 'pci-detach', 2)
2693 (dom, pci) = parse_pci_configuration(args, 'Closing')
2695 if serverType == SERVER_XEN_API:
2697 pci_dev = sxp.children(pci, 'dev')[0]
2698 domain = int(sxp.child_value(pci_dev, 'domain'), 16)
2699 bus = int(sxp.child_value(pci_dev, 'bus'), 16)
2700 slot = int(sxp.child_value(pci_dev, 'slot'), 16)
2701 func = int(sxp.child_value(pci_dev, 'func'), 16)
2702 vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
2703 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
2705 target_ref = None
2706 for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
2707 ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
2708 if name == server.xenapi.PPCI.get_name(ppci_ref):
2709 target_ref = ppci_ref
2710 server.xenapi.DPCI.destroy(dpci_ref)
2711 break
2712 if target_ref is None:
2713 raise OptionError("Device %s not assigned" % name)
2715 else:
2716 server.xend.domain.device_configure(dom, pci)
2718 def xm_scsi_detach(args):
2719 arg_check(args, 'scsi-detach', 2)
2720 dom = args[0]
2721 v_hctl = args[1]
2722 scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
2724 if serverType == SERVER_XEN_API:
2726 target_ref = None
2727 for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
2728 if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
2729 target_ref = dscsi_ref
2730 break
2731 if target_ref is None:
2732 raise OptionError("Device %s not assigned" % v_hctl)
2734 server.xenapi.DSCSI.destroy(target_ref)
2736 else:
2737 server.xend.domain.device_configure(dom, scsi)
2739 def xm_vnet_list(args):
2740 xenapi_unsupported()
2741 try:
2742 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2743 except getopt.GetoptError, opterr:
2744 err(opterr)
2745 usage('vnet-list')
2747 use_long = 0
2748 for (k, v) in options:
2749 if k in ['-l', '--long']:
2750 use_long = 1
2752 if params:
2753 use_long = 1
2754 vnets = params
2755 else:
2756 vnets = server.xend_vnets()
2758 for vnet in vnets:
2759 try:
2760 if use_long:
2761 info = server.xend_vnet(vnet)
2762 PrettyPrint.prettyprint(info)
2763 else:
2764 print vnet
2765 except Exception, ex:
2766 print vnet, ex
2768 def xm_vnet_create(args):
2769 xenapi_unsupported()
2770 arg_check(args, "vnet-create", 1)
2771 conf = args[0]
2772 if not os.access(conf, os.R_OK):
2773 print "File not found: %s" % conf
2774 sys.exit(1)
2776 server.xend_vnet_create(conf)
2778 def xm_vnet_delete(args):
2779 xenapi_unsupported()
2780 arg_check(args, "vnet-delete", 1)
2781 vnet = args[0]
2782 server.xend_vnet_delete(vnet)
2784 def xm_network_new(args):
2785 xenapi_only()
2786 arg_check(args, "network-new", 1)
2787 network = args[0]
2789 record = {
2790 "name_label": network,
2791 "name_description": "",
2792 "other_config": {},
2793 "default_gateway": "",
2794 "default_netmask": ""
2797 server.xenapi.network.create(record)
2799 def xm_network_del(args):
2800 xenapi_only()
2801 arg_check(args, "network-del", 1)
2802 network = args[0]
2804 networks = dict([(record['name_label'], ref)
2805 for ref, record in
2806 server.xenapi.network.get_all_records().items()])
2808 if network not in networks.keys():
2809 raise ValueError("'%s' is not a valid network name" % network)
2811 server.xenapi.network.destroy(networks[network])
2813 def xm_network_show(args):
2814 xenapi_only()
2815 arg_check(args, "network-show", 0)
2817 networks = server.xenapi.network.get_all_records()
2818 pifs = server.xenapi.PIF.get_all_records()
2819 vifs = server.xenapi.VIF.get_all_records()
2821 print '%-20s %-40s %-10s' % \
2822 ('Name', 'VIFs', 'PIFs')
2824 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2826 for network_ref, network in networks.items():
2827 for i in range(max(len(network['PIFs']),
2828 len(network['VIFs']), 1)):
2829 if i < len(network['PIFs']):
2830 pif_uuid = network['PIFs'][i]
2831 else:
2832 pif_uuid = None
2834 if i < len(network['VIFs']):
2835 vif_uuid = network['VIFs'][i]
2836 else:
2837 vif_uuid = None
2839 pif = pifs.get(pif_uuid, None)
2840 vif = vifs.get(vif_uuid, None)
2842 if vif:
2843 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2844 vif = "%s.%s" % (dom_name, vif['device'])
2845 else:
2846 vif = ''
2848 if pif:
2849 if int(pif['VLAN']) > -1:
2850 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2851 else:
2852 pif = pif['device']
2853 else:
2854 pif = ''
2856 if i == 0:
2857 r = {'name_label':network['name_label'],
2858 'vif':vif, 'pif':pif}
2859 else:
2860 r = {'name_label':'', 'vif':vif, 'pif':pif}
2862 print format2 % r
2864 def xm_tmem_list(args):
2865 try:
2866 (options, params) = getopt.gnu_getopt(args, 'la', ['long','all'])
2867 except getopt.GetoptError, opterr:
2868 err(opterr)
2869 usage('tmem-list')
2871 use_long = False
2872 for (k, v) in options:
2873 if k in ['-l', '--long']:
2874 use_long = True
2876 all = False
2877 for (k, v) in options:
2878 if k in ['-a', '--all']:
2879 all = True
2881 if not all and len(params) == 0:
2882 err('You must specify -a or --all or a domain id.')
2883 usage('tmem-list')
2885 if all:
2886 domid = -1
2887 else:
2888 try:
2889 domid = int(params[0])
2890 params = params[1:]
2891 except:
2892 err('Unrecognized domain id: %s' % params[0])
2893 usage('tmem-list')
2895 if serverType == SERVER_XEN_API:
2896 print server.xenapi.host.tmem_list(domid,use_long)
2897 else:
2898 print server.xend.node.tmem_list(domid,use_long)
2900 def parse_tmem_args(args, name):
2901 try:
2902 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
2903 except getopt.GetoptError, opterr:
2904 err(opterr)
2905 usage(name)
2907 all = False
2908 for (k, v) in options:
2909 if k in ['-a', '--all']:
2910 all = True
2912 if not all and len(params) == 0:
2913 err('You must specify -a or --all or a domain id.')
2914 usage(name)
2916 if all:
2917 domid = -1
2918 else:
2919 try:
2920 domid = int(params[0])
2921 params = params[1:]
2922 except:
2923 err('Unrecognized domain id: %s' % params[0])
2924 usage(name)
2926 return domid, params
2928 def xm_tmem_destroy(args):
2929 (domid, _) = parse_tmem_args(args, 'tmem-destroy')
2930 if serverType == SERVER_XEN_API:
2931 server.xenapi.host.tmem_destroy(domid)
2932 else:
2933 server.xend.node.tmem_destroy(domid)
2935 def xm_tmem_thaw(args):
2936 (domid, _) = parse_tmem_args(args, 'tmem-thaw')
2937 if serverType == SERVER_XEN_API:
2938 server.xenapi.host.tmem_thaw(domid)
2939 else:
2940 server.xend.node.tmem_thaw(domid)
2942 def xm_tmem_freeze(args):
2943 (domid, _) = parse_tmem_args(args, 'tmem-freeze')
2944 if serverType == SERVER_XEN_API:
2945 server.xenapi.host.tmem_freeze(domid)
2946 else:
2947 server.xend.node.tmem_freeze(domid)
2949 def xm_tmem_flush(args):
2950 try:
2951 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
2952 except getopt.GetoptError, opterr:
2953 err(opterr)
2954 usage(name)
2956 all = False
2957 for (k, v) in options:
2958 if k in ['-a', '--all']:
2959 all = True
2961 if not all and len(params) == 0:
2962 err('You must specify -a or --all or a domain id.')
2963 usage('tmem-flush')
2965 if all:
2966 domid = -1
2967 else:
2968 try:
2969 domid = int(params[0])
2970 params = params[1:]
2971 except:
2972 err('Unrecognized domain id: %s' % params[0])
2973 usage('tmem-flush')
2975 pages = -1
2976 for (k, v) in options:
2977 if k in ['-p', '--pages']:
2978 pages = v
2980 if serverType == SERVER_XEN_API:
2981 server.xenapi.host.tmem_flush(domid,pages)
2982 else:
2983 server.xend.node.tmem_flush(domid,pages)
2985 def xm_tmem_set(args):
2986 try:
2987 (options, params) = getopt.gnu_getopt(args, 'a', ['all'])
2988 except getopt.GetoptError, opterr:
2989 err(opterr)
2990 usage(name)
2992 all = False
2993 for (k, v) in options:
2994 if k in ['-a', '--all']:
2995 all = True
2997 if not all and len(params) == 0:
2998 err('You must specify -a or --all or a domain id.')
2999 usage('tmem-set')
3001 if all:
3002 domid = -1
3003 else:
3004 try:
3005 domid = int(params[0])
3006 params = params[1:]
3007 except:
3008 err('Unrecognized domain id: %s' % params[0])
3009 usage('tmem-set')
3011 weight = None
3012 cap = None
3013 compress = None
3014 for item in params:
3015 if item.startswith('weight='):
3016 try:
3017 weight = int(item[7:])
3018 except:
3019 err('weight should be a integer')
3020 usage('tmem-set')
3021 if item.startswith('cap='):
3022 cap = int(item[4:])
3023 if item.startswith('compress='):
3024 compress = int(item[9:])
3026 if weight is None and cap is None and compress is None:
3027 err('Unrecognized tmem configuration option: %s' % item)
3028 usage('tmem-set')
3030 if serverType == SERVER_XEN_API:
3031 if weight is not None:
3032 server.xenapi.host.tmem_set_weight(domid, weight)
3033 if cap is not None:
3034 server.xenapi.host.tmem_set_cap(domid, cap)
3035 if compress is not None:
3036 server.xenapi.host.tmem_set_compress(domid, compress)
3037 else:
3038 if weight is not None:
3039 server.xend.node.tmem_set_weight(domid, weight)
3040 if cap is not None:
3041 server.xend.node.tmem_set_cap(domid, cap)
3042 if compress is not None:
3043 server.xend.node.tmem_set_compress(domid, compress)
3046 commands = {
3047 "shell": xm_shell,
3048 "event-monitor": xm_event_monitor,
3049 # console commands
3050 "console": xm_console,
3051 "vncviewer": xm_vncviewer,
3052 # xenstat commands
3053 "top": xm_top,
3054 # domain commands
3055 "delete": xm_delete,
3056 "destroy": xm_destroy,
3057 "domid": xm_domid,
3058 "domname": xm_domname,
3059 "dump-core": xm_dump_core,
3060 "reboot": xm_reboot,
3061 "rename": xm_rename,
3062 "reset": xm_reset,
3063 "restore": xm_restore,
3064 "resume": xm_resume,
3065 "save": xm_save,
3066 "shutdown": xm_shutdown,
3067 "start": xm_start,
3068 "sysrq": xm_sysrq,
3069 "trigger": xm_trigger,
3070 "uptime": xm_uptime,
3071 "suspend": xm_suspend,
3072 "list": xm_list,
3073 # memory commands
3074 "mem-max": xm_mem_max,
3075 "mem-set": xm_mem_set,
3076 # cpu commands
3077 "vcpu-pin": xm_vcpu_pin,
3078 "vcpu-list": xm_vcpu_list,
3079 "vcpu-set": xm_vcpu_set,
3080 # special
3081 "pause": xm_pause,
3082 "unpause": xm_unpause,
3083 # host commands
3084 "debug-keys": xm_debug_keys,
3085 "dmesg": xm_dmesg,
3086 "info": xm_info,
3087 "log": xm_log,
3088 "serve": xm_serve,
3089 # scheduler
3090 "sched-sedf": xm_sched_sedf,
3091 "sched-credit": xm_sched_credit,
3092 # block
3093 "block-attach": xm_block_attach,
3094 "block-detach": xm_block_detach,
3095 "block-list": xm_block_list,
3096 "block-configure": xm_block_configure,
3097 # network (AKA vifs)
3098 "network-attach": xm_network_attach,
3099 "network-detach": xm_network_detach,
3100 "network-list": xm_network_list,
3101 # network (as in XenAPI)
3102 "network-new": xm_network_new,
3103 "network-del": xm_network_del,
3104 "network-show": xm_network_show,
3105 # vnet
3106 "vnet-list": xm_vnet_list,
3107 "vnet-create": xm_vnet_create,
3108 "vnet-delete": xm_vnet_delete,
3109 # vtpm
3110 "vtpm-list": xm_vtpm_list,
3111 #pci
3112 "pci-attach": xm_pci_attach,
3113 "pci-detach": xm_pci_detach,
3114 "pci-list": xm_pci_list,
3115 "pci-list-assignable-devices": xm_pci_list_assignable_devices,
3116 # vscsi
3117 "scsi-attach": xm_scsi_attach,
3118 "scsi-detach": xm_scsi_detach,
3119 "scsi-list": xm_scsi_list,
3120 # tmem
3121 "tmem-thaw": xm_tmem_thaw,
3122 "tmem-freeze": xm_tmem_freeze,
3123 "tmem-flush": xm_tmem_flush,
3124 "tmem-destroy": xm_tmem_destroy,
3125 "tmem-list": xm_tmem_list,
3126 "tmem-set": xm_tmem_set,
3129 ## The commands supported by a separate argument parser in xend.xm.
3130 IMPORTED_COMMANDS = [
3131 'create',
3132 'new',
3133 'migrate',
3134 'labels',
3135 'dumppolicy',
3136 'addlabel',
3137 'rmlabel',
3138 'getlabel',
3139 'dry-run',
3140 'resources',
3141 'getpolicy',
3142 'setpolicy',
3143 'resetpolicy',
3146 for c in IMPORTED_COMMANDS:
3147 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
3149 aliases = {
3150 "balloon": "mem-set",
3151 "set-vcpus": "vcpu-set",
3152 "vif-list": "network-list",
3153 "vbd-create": "block-attach",
3154 "vbd-destroy": "block-detach",
3155 "vbd-list": "block-list",
3159 def xm_lookup_cmd(cmd):
3160 if commands.has_key(cmd):
3161 return commands[cmd]
3162 elif aliases.has_key(cmd):
3163 deprecated(cmd,aliases[cmd])
3164 return commands[aliases[cmd]]
3165 elif cmd == 'help':
3166 longHelp()
3167 sys.exit(0)
3168 else:
3169 # simulate getopt's prefix matching behaviour
3170 if len(cmd) > 1:
3171 same_prefix_cmds = [commands[c] for c in commands.keys() \
3172 if c[:len(cmd)] == cmd]
3173 # only execute if there is only 1 match
3174 if len(same_prefix_cmds) == 1:
3175 return same_prefix_cmds[0]
3176 return None
3178 def deprecated(old,new):
3179 print >>sys.stderr, (
3180 "Command %s is deprecated. Please use xm %s instead." % (old, new))
3182 def main(argv=sys.argv):
3183 if len(argv) < 2:
3184 usage()
3186 # intercept --help(-h) and output our own help
3187 for help in ['--help', '-h']:
3188 if help in argv[1:]:
3189 if help == argv[1]:
3190 longHelp()
3191 sys.exit(0)
3192 else:
3193 usage(argv[1])
3195 cmd_name = argv[1]
3196 cmd = xm_lookup_cmd(cmd_name)
3197 if cmd:
3198 # strip off prog name and subcmd
3199 args = argv[2:]
3200 _, rc = _run_cmd(cmd, cmd_name, args)
3201 sys.exit(rc)
3202 else:
3203 err('Subcommand %s not found!' % cmd_name)
3204 usage()
3206 def _run_cmd(cmd, cmd_name, args):
3207 global server
3209 try:
3210 if server is None:
3211 if serverType == SERVER_XEN_API:
3212 server = XenAPI.Session(serverURI)
3213 username, password = parseAuthentication()
3214 server.login_with_password(username, password)
3215 def logout():
3216 try:
3217 server.xenapi.session.logout()
3218 except:
3219 pass
3220 atexit.register(logout)
3221 else:
3222 server = ServerProxy(serverURI)
3224 return True, cmd(args)
3225 except socket.error, ex:
3226 if os.geteuid() != 0:
3227 err("Most commands need root access. Please try again as root.")
3228 else:
3229 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
3230 except KeyboardInterrupt:
3231 print "Interrupted."
3232 return True, ''
3233 except IOError, ex:
3234 if os.geteuid() != 0:
3235 err("Most commands need root access. Please try again as root.")
3236 else:
3237 err("Unable to connect to xend: %s." % ex[1])
3238 except SystemExit, code:
3239 return code == 0, code
3240 except XenAPI.Failure, exn:
3241 for line in [''] + wrap(str(exn), 80) + ['']:
3242 print >>sys.stderr, line
3243 except xmlrpclib.Fault, ex:
3244 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
3245 err("Domain '%s' does not exist." % ex.faultString)
3246 return False, ex.faultCode
3247 else:
3248 err(ex.faultString)
3249 _usage(cmd_name)
3250 except xmlrpclib.ProtocolError, ex:
3251 if ex.errcode == -1:
3252 print >>sys.stderr, (
3253 "Xend has probably crashed! Invalid or missing HTTP "
3254 "status code.")
3255 else:
3256 print >>sys.stderr, (
3257 "Xend has probably crashed! ProtocolError(%d, %s)." %
3258 (ex.errcode, ex.errmsg))
3259 except (ValueError, OverflowError):
3260 err("Invalid argument.")
3261 _usage(cmd_name)
3262 except OptionError, e:
3263 err(str(e))
3264 _usage(cmd_name)
3265 print e.usage
3266 except XenAPIUnsupportedException, e:
3267 err(str(e))
3268 except XSMError, e:
3269 err(str(e))
3270 except Exception, e:
3271 if serverType != SERVER_XEN_API:
3272 import xen.util.xsm.xsm as security
3273 if isinstance(e, security.XSMError):
3274 err(str(e))
3275 return False, 1
3276 print "Unexpected error:", sys.exc_info()[0]
3277 print
3278 print "Please report to xen-devel@lists.xensource.com"
3279 raise
3281 return False, 1
3283 if __name__ == "__main__":
3284 main()