ia64/xen-unstable

view tools/python/xen/xm/main.py @ 15853:0c14d0bf369e

Fix error message and wait time for xm block-detach command.

- Wait time
When xm requests a block device detach to xend, xm makes two
requests. At first, xm requests the block device detach by device
class 'vbd'. Next, xm requests the block device detaching by
device class 'tap'.
As a result, the wait time is 200 seconds because each of
the block device detaching requests causes time-out.
- Misleading error message
Because the last request is by device class 'tap' to xend,
the keyword "(tap)" is included in the error message.

This patch fixes the number of times of the block device detaching
request to one time. At first, xm makes inquiries about device
class of a detaching target device to xend. Then xm requires the
block device detaching by xend returned device class. The wait
time becomes 100 seconds because the block device detaching request
is one time. And the error message is also fixed.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Fri Sep 07 11:30:18 2007 +0100 (2007-09-07)
parents 993655d24b55
children 9a7cbde124a5
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
41 import warnings
42 warnings.filterwarnings('ignore', category=FutureWarning)
44 from xen.xend import PrettyPrint
45 from xen.xend import sxp
46 from xen.xend import XendClient
47 from xen.xend.XendConstants import *
49 from xen.xm.opts import OptionError, Opts, wrap, set_true
50 from xen.xm import console
51 from xen.util.xmlrpcclient import ServerProxy
52 import xen.util.xsm.xsm as security
53 from xen.util.xsm.xsm import XSMError
54 from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
56 import XenAPI
59 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
60 # getopt.getopt if gnu_getopt is not available. This will mean that options
61 # may only be specified before positional arguments.
62 if not hasattr(getopt, 'gnu_getopt'):
63 getopt.gnu_getopt = getopt.getopt
65 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
66 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
68 # Supported types of server
69 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
70 SERVER_XEN_API = 'Xen-API'
72 # General help message
74 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
75 "Control, list, and manipulate Xen guest instances.\n"
77 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
78 'For more help on \'xm\' see the xm(1) man page.\n' \
79 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
80 ' man page.\n'
82 # Help strings are indexed by subcommand name in this way:
83 # 'subcommand': (argstring, description)
85 SUBCOMMAND_HELP = {
86 # common commands
88 'shell' : ('', 'Launch an interactive shell.'),
90 'console' : ('[-q|--quiet] <Domain>',
91 'Attach to <Domain>\'s console.'),
92 'create' : ('<ConfigFile> [options] [vars]',
93 'Create a domain based on <ConfigFile>.'),
94 'destroy' : ('<Domain>',
95 'Terminate a domain immediately.'),
96 'help' : ('', 'Display this message.'),
97 'list' : ('[options] [Domain, ...]',
98 'List information about all/some domains.'),
99 'mem-max' : ('<Domain> <Mem>',
100 'Set the maximum amount reservation for a domain.'),
101 'mem-set' : ('<Domain> <Mem>',
102 'Set the current memory usage for a domain.'),
103 'migrate' : ('<Domain> <Host>',
104 'Migrate a domain to another machine.'),
105 'pause' : ('<Domain>', 'Pause execution of a domain.'),
106 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
107 'restore' : ('<CheckpointFile> [-p]',
108 'Restore a domain from a saved state.'),
109 'save' : ('[-c] <Domain> <CheckpointFile>',
110 'Save a domain state to restore later.'),
111 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
112 'top' : ('', 'Monitor a host and the domains in real time.'),
113 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
114 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
116 # Life cycle xm commands
117 'new' : ('<ConfigFile> [options] [vars]',
118 'Adds a domain to Xend domain management'),
119 'delete' : ('<DomainName>',
120 'Remove a domain from Xend domain management.'),
121 'start' : ('<DomainName>', 'Start a Xend managed domain'),
122 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
123 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
125 # less used commands
127 'dmesg' : ('[-c|--clear]',
128 'Read and/or clear Xend\'s message buffer.'),
129 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
130 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
131 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
132 'Dump core for a specific domain.'),
133 'info' : ('', 'Get information about Xen host.'),
134 'log' : ('', 'Print Xend log'),
135 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
136 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
137 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
138 'Get/set credit scheduler parameters.'),
139 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
140 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
141 'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
142 'Send a trigger to a domain.'),
143 'vcpu-list' : ('[<Domain>]',
144 'List the VCPUs for a domain or all domains.'),
145 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
146 'Set which CPUs a VCPU can use.'),
147 'vcpu-set' : ('<Domain> <vCPUs>',
148 'Set the number of active VCPUs for allowed for the'
149 ' domain.'),
151 # device commands
153 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
154 'Create a new virtual block device.'),
155 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
156 'Change block device configuration'),
157 'block-detach' : ('<Domain> <DevId> [-f|--force]',
158 'Destroy a domain\'s virtual block device.'),
159 'block-list' : ('<Domain> [--long]',
160 'List virtual block devices for a domain.'),
161 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
162 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
163 '[vifname=<name>] [rate=<rate>] [model=<model>]',
164 'Create a new virtual network device.'),
165 'network-detach': ('<Domain> <DevId> [-f|--force]',
166 'Destroy a domain\'s virtual network device.'),
167 'network-list' : ('<Domain> [--long]',
168 'List virtual network interfaces for a domain.'),
169 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
170 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
171 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
172 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
174 # security
176 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
177 ' [<policy>]',
178 'Add security label to domain.'),
179 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
180 'Remove a security label from domain.'),
181 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
182 'Show security label for domain or resource.'),
183 'dry-run' : ('<ConfigFile>',
184 'Test if a domain can access its resources.'),
185 'resources' : ('', 'Show info for each labeled resource.'),
186 'cfgbootpolicy' : ('<policy> [boot-title]',
187 'Add policy to boot configuration.'),
188 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
189 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
190 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
191 'files.'),
192 'setpolicy' : ('<policytype> <policyfile> [options]',
193 'Set the policy of the system.'),
194 'getpolicy' : ('[options]', 'Get the policy of the system.'),
195 'activatepolicy': ('[options]', 'Activate the xend-managed policy.'),
196 'labels' : ('[policy] [type=dom|res|any]',
197 'List <type> labels for (active) policy.'),
198 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
199 }
201 SUBCOMMAND_OPTIONS = {
202 'sched-sedf': (
203 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
204 ('-s [MS]', '--slice[=MS]' ,
205 'Worst-case execution time(ms). (slice < period)'),
206 ('-l [MS]', '--latency[=MS]',
207 'Scaled period (ms) when domain performs heavy I/O'),
208 ('-e [FLAG]', '--extra[=FLAG]',
209 'Flag (0 or 1) controls if domain can run in extra time.'),
210 ('-w [FLOAT]', '--weight[=FLOAT]',
211 'CPU Period/slice (do not set with --period/--slice)'),
212 ),
213 'sched-credit': (
214 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
215 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
216 ('-c CAP', '--cap=CAP', 'Cap (int)'),
217 ),
218 'list': (
219 ('-l', '--long', 'Output all VM details in SXP'),
220 ('', '--label', 'Include security labels'),
221 ('', '--state=<state>', 'Select only VMs with the specified state'),
222 ),
223 'console': (
224 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
225 ),
226 'dmesg': (
227 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
228 ),
229 'vnet-list': (
230 ('-l', '--long', 'List Vnets as SXP'),
231 ),
232 'network-list': (
233 ('-l', '--long', 'List resources as SXP'),
234 ),
235 'dump-core': (
236 ('-L', '--live', 'Dump core without pausing the domain'),
237 ('-C', '--crash', 'Crash domain after dumping core'),
238 ),
239 'start': (
240 ('-p', '--paused', 'Do not unpause domain after starting it'),
241 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
242 ),
243 'resume': (
244 ('-p', '--paused', 'Do not unpause domain after resuming it'),
245 ),
246 'save': (
247 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
248 ),
249 'restore': (
250 ('-p', '--paused', 'Do not unpause domain after restoring it'),
251 ),
252 }
254 common_commands = [
255 "console",
256 "create",
257 "new",
258 "delete",
259 "destroy",
260 "dump-core",
261 "help",
262 "list",
263 "mem-set",
264 "migrate",
265 "pause",
266 "reboot",
267 "restore",
268 "resume",
269 "save",
270 "shell",
271 "shutdown",
272 "start",
273 "suspend",
274 "top",
275 "unpause",
276 "uptime",
277 "vcpu-set",
278 ]
280 domain_commands = [
281 "console",
282 "create",
283 "new",
284 "delete",
285 "destroy",
286 "domid",
287 "domname",
288 "dump-core",
289 "list",
290 "mem-max",
291 "mem-set",
292 "migrate",
293 "pause",
294 "reboot",
295 "rename",
296 "restore",
297 "resume",
298 "save",
299 "shutdown",
300 "start",
301 "suspend",
302 "sysrq",
303 "trigger",
304 "top",
305 "unpause",
306 "uptime",
307 "vcpu-list",
308 "vcpu-pin",
309 "vcpu-set",
310 ]
312 host_commands = [
313 "debug-keys",
314 "dmesg",
315 "info",
316 "log",
317 "serve",
318 ]
320 scheduler_commands = [
321 "sched-credit",
322 "sched-sedf",
323 ]
325 device_commands = [
326 "block-attach",
327 "block-detach",
328 "block-list",
329 "block-configure",
330 "network-attach",
331 "network-detach",
332 "network-list",
333 "vtpm-list",
334 ]
336 vnet_commands = [
337 "vnet-list",
338 "vnet-create",
339 "vnet-delete",
340 ]
342 acm_commands = [
343 "labels",
344 "addlabel",
345 "rmlabel",
346 "getlabel",
347 "dry-run",
348 "resources",
349 "makepolicy",
350 "loadpolicy",
351 "cfgbootpolicy",
352 "dumppolicy",
353 "activatepolicy",
354 "setpolicy",
355 "getpolicy",
356 ]
358 all_commands = (domain_commands + host_commands + scheduler_commands +
359 device_commands + vnet_commands + acm_commands +
360 ['shell', 'event-monitor'])
363 ##
364 # Configuration File Parsing
365 ##
367 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
368 config = None
369 if os.path.isfile(xmConfigFile):
370 try:
371 config = xml.dom.minidom.parse(xmConfigFile)
372 except:
373 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
374 xmConfigFile)
376 def parseServer():
377 if config:
378 server = config.getElementsByTagName('server')
379 if server:
380 st = server[0].getAttribute('type')
381 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
382 print >>sys.stderr, ('Invalid server type %s; using %s.' %
383 (st, SERVER_LEGACY_XMLRPC))
384 st = SERVER_LEGACY_XMLRPC
385 return (st, server[0].getAttribute('uri'))
387 return SERVER_LEGACY_XMLRPC, XendClient.uri
389 def parseAuthentication():
390 server = config.getElementsByTagName('server')[0]
391 return (server.getAttribute('username'),
392 server.getAttribute('password'))
394 serverType, serverURI = parseServer()
395 server = None
398 ####################################################################
399 #
400 # Help/usage printing functions
401 #
402 ####################################################################
404 def cmdHelp(cmd):
405 """Print help for a specific subcommand."""
407 for fc in SUBCOMMAND_HELP.keys():
408 if fc[:len(cmd)] == cmd:
409 cmd = fc
410 break
412 try:
413 args, desc = SUBCOMMAND_HELP[cmd]
414 except KeyError:
415 shortHelp()
416 return
418 print 'Usage: xm %s %s' % (cmd, args)
419 print
420 print desc
422 try:
423 # If options help message is defined, print this.
424 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
425 if shortopt and longopt:
426 optdesc = '%s, %s' % (shortopt, longopt)
427 elif shortopt:
428 optdesc = shortopt
429 elif longopt:
430 optdesc = longopt
432 wrapped_desc = wrap(desc, 43)
433 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
434 for line in wrapped_desc[1:]:
435 print ' ' * 33 + line
436 print
437 except KeyError:
438 # if the command is an external module, we grab usage help
439 # from the module itself.
440 if cmd in IMPORTED_COMMANDS:
441 try:
442 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
443 cmd_usage = getattr(cmd_module, "help", None)
444 if cmd_usage:
445 print cmd_usage()
446 except ImportError:
447 pass
449 def shortHelp():
450 """Print out generic help when xm is called without subcommand."""
452 print USAGE_HELP
453 print 'Common \'xm\' commands:\n'
455 for command in common_commands:
456 try:
457 args, desc = SUBCOMMAND_HELP[command]
458 except KeyError:
459 continue
460 wrapped_desc = wrap(desc, 50)
461 print ' %-20s %-50s' % (command, wrapped_desc[0])
462 for line in wrapped_desc[1:]:
463 print ' ' * 22 + line
465 print
466 print USAGE_FOOTER
467 print 'For a complete list of subcommands run \'xm help\'.'
469 def longHelp():
470 """Print out full help when xm is called with xm --help or xm help"""
472 print USAGE_HELP
473 print 'xm full list of subcommands:\n'
475 for command in all_commands:
476 try:
477 args, desc = SUBCOMMAND_HELP[command]
478 except KeyError:
479 continue
481 wrapped_desc = wrap(desc, 50)
482 print ' %-20s %-50s' % (command, wrapped_desc[0])
483 for line in wrapped_desc[1:]:
484 print ' ' * 22 + line
486 print
487 print USAGE_FOOTER
489 def _usage(cmd):
490 """ Print help usage information """
491 if cmd:
492 cmdHelp(cmd)
493 else:
494 shortHelp()
496 def usage(cmd = None):
497 """ Print help usage information and exits """
498 _usage(cmd)
499 sys.exit(1)
502 ####################################################################
503 #
504 # Utility functions
505 #
506 ####################################################################
508 def get_default_SR():
509 return [sr_ref
510 for sr_ref in server.xenapi.SR.get_all()
511 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
513 def get_default_Network():
514 return [network_ref
515 for network_ref in server.xenapi.network.get_all()][0]
517 class XenAPIUnsupportedException(Exception):
518 pass
520 def xenapi_unsupported():
521 if serverType == SERVER_XEN_API:
522 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
524 def xenapi_only():
525 if serverType != SERVER_XEN_API:
526 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
528 def map2sxp(m):
529 return [[k, m[k]] for k in m.keys()]
531 def arg_check(args, name, lo, hi = -1):
532 n = len([i for i in args if i != '--'])
534 if hi == -1:
535 if n != lo:
536 err("'xm %s' requires %d argument%s.\n" % (name, lo,
537 lo == 1 and '' or 's'))
538 usage(name)
539 else:
540 if n < lo or n > hi:
541 err("'xm %s' requires between %d and %d arguments.\n" %
542 (name, lo, hi))
543 usage(name)
546 def unit(c):
547 if not c.isalpha():
548 return 0
549 base = 1
550 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
551 elif c == 'M' or c == 'm': base = 1024 * 1024
552 elif c == 'K' or c == 'k': base = 1024
553 else:
554 print 'ignoring unknown unit'
555 return base
557 def int_unit(str, dest):
558 base = unit(str[-1])
559 if not base:
560 return int(str)
562 value = int(str[:-1])
563 dst_base = unit(dest)
564 if dst_base == 0:
565 dst_base = 1
566 if dst_base > base:
567 return value / (dst_base / base)
568 else:
569 return value * (base / dst_base)
571 def err(msg):
572 print >>sys.stderr, "Error:", msg
575 def get_single_vm(dom):
576 if serverType == SERVER_XEN_API:
577 uuids = server.xenapi.VM.get_by_name_label(dom)
578 if len(uuids) > 0:
579 return uuids[0]
581 refs = []
583 try:
584 domid = int(dom)
585 refs = [vm_ref
586 for vm_ref in server.xenapi.VM.get_all()
587 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
588 except:
589 pass
591 if len(refs) > 0:
592 return refs[0]
594 raise OptionError("Domain '%s' not found." % dom)
595 else:
596 dominfo = server.xend.domain(dom, False)
597 return dominfo['uuid']
599 ##
600 #
601 # Xen-API Shell
602 #
603 ##
605 class Shell(cmd.Cmd):
606 def __init__(self):
607 cmd.Cmd.__init__(self)
608 self.prompt = "xm> "
609 if serverType == SERVER_XEN_API:
610 try:
611 res = server.xenapi.host.list_methods()
612 for f in res:
613 setattr(Shell, 'do_' + f + ' ', self.default)
614 except:
615 pass
617 def preloop(self):
618 cmd.Cmd.preloop(self)
619 import readline
620 readline.set_completer_delims(' ')
622 def default(self, line):
623 words = shlex.split(line)
624 if len(words) > 0 and words[0] == 'xm':
625 words = words[1:]
626 if len(words) > 0:
627 cmd = xm_lookup_cmd(words[0])
628 if cmd:
629 _run_cmd(cmd, words[0], words[1:])
630 elif serverType == SERVER_XEN_API:
631 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
632 tuple(x)),
633 words[0], words[1:])
634 if ok and res is not None and res != '':
635 pprint.pprint(res)
636 else:
637 print '*** Unknown command: %s' % words[0]
638 return False
640 def completedefault(self, text, line, begidx, endidx):
641 words = shlex.split(line[:begidx])
642 clas, func = words[0].split('.')
643 if len(words) > 1 or \
644 func.startswith('get_by_') or \
645 func == 'get_all':
646 return []
647 uuids = server.xenapi_request('%s.get_all' % clas, ())
648 return [u + " " for u in uuids if u.startswith(text)]
650 def emptyline(self):
651 pass
653 def do_EOF(self, line):
654 print
655 sys.exit(0)
657 def do_help(self, line):
658 _usage(line)
661 def xm_shell(args):
662 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
665 def xm_event_monitor(args):
666 if serverType == SERVER_XEN_API:
667 while True:
668 server.xenapi.event.register(args)
669 events = server.xenapi.event.next()
670 for e in events:
671 print e
672 else:
673 err("Event monitoring not supported unless using Xen-API.")
676 #########################################################################
677 #
678 # Main xm functions
679 #
680 #########################################################################
682 def xm_save(args):
684 arg_check(args, "save", 2, 3)
686 try:
687 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
688 except getopt.GetoptError, opterr:
689 err(opterr)
690 sys.exit(1)
692 dom = params[0]
693 savefile = params[1]
695 checkpoint = False
696 for (k, v) in options:
697 if k in ['-c', '--checkpoint']:
698 checkpoint = True
700 if len(params) != 2:
701 err("Wrong number of parameters")
702 usage('save')
703 sys.exit(1)
705 savefile = os.path.abspath(savefile)
707 if not os.access(os.path.dirname(savefile), os.W_OK):
708 err("xm save: Unable to create file %s" % savefile)
709 sys.exit(1)
711 if serverType == SERVER_XEN_API:
712 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
713 else:
714 server.xend.domain.save(dom, savefile, checkpoint)
716 def xm_restore(args):
717 arg_check(args, "restore", 1, 2)
719 try:
720 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
721 except getopt.GetoptError, opterr:
722 err(opterr)
723 usage('restore')
725 paused = False
726 for (k, v) in options:
727 if k in ['-p', '--paused']:
728 paused = True
730 if len(params) != 1:
731 err("Wrong number of parameters")
732 usage('restore')
734 savefile = os.path.abspath(params[0])
736 if not os.access(savefile, os.R_OK):
737 err("xm restore: Unable to read file %s" % savefile)
738 sys.exit(1)
740 try:
741 if serverType == SERVER_XEN_API:
742 server.xenapi.VM.restore(savefile, paused)
743 else:
744 server.xend.domain.restore(savefile, paused)
745 except Exception, ex:
746 err("%s" % ex.faultString)
749 def datetime_to_secs(v):
750 unwanted = ":-."
751 for c in unwanted:
752 v = str(v).replace(c, "")
753 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
755 def getDomains(domain_names, state, full = 0):
756 if serverType == SERVER_XEN_API:
757 doms_sxp = []
758 doms_dict = []
760 dom_recs = server.xenapi.VM.get_all_records()
761 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
763 for dom_ref, dom_rec in dom_recs.items():
764 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
766 states = ('running', 'blocked', 'paused', 'shutdown',
767 'crashed', 'dying')
768 def state_on_off(state):
769 if state in dom_metrics_rec['state']:
770 return state[0]
771 else:
772 return "-"
773 state_str = "".join([state_on_off(state)
774 for state in states])
776 dom_rec.update({'name': dom_rec['name_label'],
777 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
778 'vcpus': dom_metrics_rec['VCPUs_number'],
779 'state': state_str,
780 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
781 'start_time': datetime_to_secs(
782 dom_metrics_rec['start_time'])})
784 doms_sxp.append(['domain'] + map2sxp(dom_rec))
785 doms_dict.append(dom_rec)
787 if domain_names:
788 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
789 if dom["name"] in domain_names]
791 if len(doms) > 0:
792 return doms
793 else:
794 print "Error: no domain%s named %s" % \
795 (len(domain_names) > 1 and 's' or '',
796 ', '.join(domain_names))
797 sys.exit(-1)
798 else:
799 return doms_sxp
800 else:
801 if domain_names:
802 return [server.xend.domain(dom, full) for dom in domain_names]
803 else:
804 return server.xend.domains_with_state(True, state, full)
807 def xm_list(args):
808 use_long = 0
809 show_vcpus = 0
810 show_labels = 0
811 state = 'all'
812 try:
813 (options, params) = getopt.gnu_getopt(args, 'lv',
814 ['long','vcpus','label',
815 'state='])
816 except getopt.GetoptError, opterr:
817 err(opterr)
818 usage('list')
820 for (k, v) in options:
821 if k in ['-l', '--long']:
822 use_long = 1
823 if k in ['-v', '--vcpus']:
824 show_vcpus = 1
825 if k in ['--label']:
826 show_labels = 1
827 if k in ['--state']:
828 state = v
830 if state != 'all' and len(params) > 0:
831 raise OptionError(
832 "You may specify either a state or a particular VM, but not both")
834 if show_vcpus:
835 print >>sys.stderr, (
836 "xm list -v is deprecated. Please use xm vcpu-list.")
837 xm_vcpu_list(params)
838 return
840 doms = getDomains(params, state, use_long)
842 if use_long:
843 map(PrettyPrint.prettyprint, doms)
844 elif show_labels:
845 xm_label_list(doms)
846 else:
847 xm_brief_list(doms)
850 def parse_doms_info(info):
851 def get_info(n, t, d):
852 return t(sxp.child_value(info, n, d))
854 def get_status(n, t, d):
855 return DOM_STATES[t(sxp.child_value(info, n, d))]
857 start_time = get_info('start_time', float, -1)
858 if start_time == -1:
859 up_time = float(-1)
860 else:
861 up_time = time.time() - start_time
863 parsed_info = {
864 'domid' : get_info('domid', str, ''),
865 'name' : get_info('name', str, '??'),
866 'state' : get_info('state', str, ''),
868 # VCPUs is the number online when the VM is up, or the number
869 # configured otherwise.
870 'vcpus' : get_info('online_vcpus', int,
871 get_info('vcpus', int, 0)),
872 'up_time' : up_time
873 }
875 security_label = get_info('security_label', str, '')
876 parsed_info['seclabel'] = security.parse_security_label(security_label)
878 if serverType == SERVER_XEN_API:
879 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
880 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
881 if sum(cpu_times.values()) > 0:
882 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
883 else:
884 parsed_info['cpu_time'] = 0
885 else:
886 parsed_info['mem'] = get_info('memory', int,0)
887 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
889 return parsed_info
891 def check_sched_type(sched):
892 if serverType == SERVER_XEN_API:
893 current = server.xenapi.host.get_sched_policy(
894 server.xenapi.session.get_this_host(server.getSession()))
895 else:
896 current = 'unknown'
897 for x in server.xend.node.info()[1:]:
898 if len(x) > 1 and x[0] == 'xen_scheduler':
899 current = x[1]
900 break
901 if sched != current:
902 err("Xen is running with the %s scheduler" % current)
903 sys.exit(1)
905 def parse_sedf_info(info):
906 def get_info(n, t, d):
907 return t(sxp.child_value(info, n, d))
909 return {
910 'domid' : get_info('domid', int, -1),
911 'period' : get_info('period', int, -1),
912 'slice' : get_info('slice', int, -1),
913 'latency' : get_info('latency', int, -1),
914 'extratime': get_info('extratime', int, -1),
915 'weight' : get_info('weight', int, -1),
916 }
918 def domid_match(domid, info):
919 return domid is None or domid == info['name'] or \
920 domid == str(info['domid'])
922 def xm_brief_list(doms):
923 print '%-40s %5s %5s %5s %10s %9s' % \
924 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
926 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
927 "%(cpu_time)8.1f"
929 for dom in doms:
930 d = parse_doms_info(dom)
931 print format % d
933 def xm_label_list(doms):
934 print '%-40s %3s %5s %5s %10s %9s %-10s' % \
935 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
937 output = []
938 format = '%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
939 '%(cpu_time)8.1f %(seclabel)10s'
941 import xen.util.xsm.xsm as security
943 for dom in doms:
944 d = parse_doms_info(dom)
945 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
946 if not d['seclabel']:
947 d['seclabel'] = ACM_LABEL_UNLABELED_DISPLAY
948 elif security.active_policy in ['DEFAULT']:
949 d['seclabel'] = 'DEFAULT'
950 else:
951 d['seclabel'] = 'INACTIVE'
953 output.append((format % d, d['seclabel']))
955 #sort by labels
956 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
957 for line, label in output:
958 print line
961 def xm_vcpu_list(args):
962 if serverType == SERVER_XEN_API:
963 if args:
964 vm_refs = map(get_single_vm, args)
965 else:
966 vm_refs = server.xenapi.VM.get_all()
968 vm_records = dict(map(lambda vm_ref:
969 (vm_ref, server.xenapi.VM.get_record(
970 vm_ref)),
971 vm_refs))
973 vm_metrics = dict(map(lambda (ref, record):
974 (ref,
975 server.xenapi.VM_metrics.get_record(
976 record['metrics'])),
977 vm_records.items()))
979 dominfo = []
981 # vcpu_list doesn't list 'managed' domains
982 # when they are not running, so filter them out
984 vm_refs = [vm_ref
985 for vm_ref in vm_refs
986 if vm_records[vm_ref]["power_state"] != "Halted"]
988 for vm_ref in vm_refs:
989 info = ['domain',
990 ['domid', vm_records[vm_ref]['domid']],
991 ['name', vm_records[vm_ref]['name_label']],
992 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
994 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
995 def chk_flag(flag):
996 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
997 and 1 or 0
999 vcpu_info = ['vcpu',
1000 ['number',
1001 i],
1002 ['online',
1003 chk_flag("online")],
1004 ['blocked',
1005 chk_flag("blocked")],
1006 ['running',
1007 chk_flag("running")],
1008 ['cpu_time',
1009 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1010 ['cpu',
1011 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1012 ['cpumap',
1013 vm_metrics[vm_ref]['VCPUs_params']\
1014 ['cpumap%i' % i].split(",")]]
1016 info.append(vcpu_info)
1018 dominfo.append(info)
1019 else:
1020 if args:
1021 dominfo = map(server.xend.domain.getVCPUInfo, args)
1022 else:
1023 doms = server.xend.domains_with_state(False, 'all', False)
1024 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1026 print '%-32s %5s %5s %5s %5s %9s %s' % \
1027 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1029 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1030 ' %(cpu_time)8.1f %(cpumap)s'
1032 for dom in dominfo:
1033 def get_info(n):
1034 return sxp.child_value(dom, n)
1037 # convert a list of integers into a list of pairs indicating
1038 # continuous sequences in the list:
1040 # [0,1,2,3] -> [(0,3)]
1041 # [1,2,4,5] -> [(1,2),(4,5)]
1042 # [0] -> [(0,0)]
1043 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1045 def list_to_rangepairs(cmap):
1046 cmap.sort()
1047 pairs = []
1048 x = y = 0
1049 for i in range(0,len(cmap)):
1050 try:
1051 if ((cmap[y+1] - cmap[i]) > 1):
1052 pairs.append((cmap[x],cmap[y]))
1053 x = y = i+1
1054 else:
1055 y = y + 1
1056 # if we go off the end, then just add x to y
1057 except IndexError:
1058 pairs.append((cmap[x],cmap[y]))
1060 return pairs
1063 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1065 def format_pairs(pairs):
1066 if not pairs:
1067 return "no cpus"
1068 out = ""
1069 for f,s in pairs:
1070 if (f==s):
1071 out += '%d'%f
1072 else:
1073 out += '%d-%d'%(f,s)
1074 out += ','
1075 # trim trailing ','
1076 return out[:-1]
1078 def format_cpumap(cpumap):
1079 cpumap = map(lambda x: int(x), cpumap)
1080 cpumap.sort()
1082 if serverType == SERVER_XEN_API:
1083 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1084 server.xenapi.session.get_this_host(server.getSession())))
1085 else:
1086 for x in server.xend.node.info()[1:]:
1087 if len(x) > 1 and x[0] == 'nr_cpus':
1088 nr_cpus = int(x[1])
1090 # normalize cpumap by modulus nr_cpus, and drop duplicates
1091 cpumap = dict.fromkeys(
1092 map(lambda x: x % nr_cpus, cpumap)).keys()
1093 if len(cpumap) == nr_cpus:
1094 return "any cpu"
1096 return format_pairs(list_to_rangepairs(cpumap))
1098 name = get_info('name')
1099 domid = get_info('domid')
1100 if domid is not None:
1101 domid = str(domid)
1102 else:
1103 domid = ''
1105 for vcpu in sxp.children(dom, 'vcpu'):
1106 def vinfo(n, t):
1107 return t(sxp.child_value(vcpu, n))
1109 number = vinfo('number', int)
1110 cpu = vinfo('cpu', int)
1111 cpumap = format_cpumap(vinfo('cpumap', list))
1112 online = vinfo('online', int)
1113 cpu_time = vinfo('cpu_time', float)
1114 running = vinfo('running', int)
1115 blocked = vinfo('blocked', int)
1117 if cpu < 0:
1118 c = ''
1119 s = ''
1120 elif online:
1121 c = str(cpu)
1122 if running:
1123 s = 'r'
1124 else:
1125 s = '-'
1126 if blocked:
1127 s += 'b'
1128 else:
1129 s += '-'
1130 s += '-'
1131 else:
1132 c = '-'
1133 s = '--p'
1135 print format % locals()
1137 def start_do_console(domain_name):
1138 cpid = os.fork()
1139 if cpid != 0:
1140 for i in range(10):
1141 # Catch failure of the create process
1142 time.sleep(1)
1143 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1144 if os.WIFEXITED(rv):
1145 if os.WEXITSTATUS(rv) != 0:
1146 sys.exit(os.WEXITSTATUS(rv))
1147 try:
1148 # Acquire the console of the created dom
1149 if serverType == SERVER_XEN_API:
1150 domid = server.xenapi.VM.get_domid(
1151 get_single_vm(domain_name))
1152 else:
1153 dom = server.xend.domain(domain_name)
1154 domid = int(sxp.child_value(dom, 'domid', '-1'))
1155 console.execConsole(domid)
1156 except:
1157 pass
1158 print("Could not start console\n");
1159 sys.exit(0)
1161 def xm_start(args):
1163 paused = False
1164 console_autoconnect = False
1166 try:
1167 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused'])
1168 for (k, v) in options:
1169 if k in ('-p', '--paused'):
1170 paused = True
1171 if k in ('-c', '--console_autoconnect'):
1172 console_autoconnect = True
1174 if len(params) != 1:
1175 raise OptionError("Expects 1 argument")
1176 except getopt.GetoptError, opterr:
1177 err(opterr)
1178 usage('start')
1180 dom = params[0]
1182 if console_autoconnect:
1183 start_do_console(dom)
1185 try:
1186 if serverType == SERVER_XEN_API:
1187 server.xenapi.VM.start(get_single_vm(dom), paused)
1188 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1189 else:
1190 server.xend.domain.start(dom, paused)
1191 info = server.xend.domain(dom)
1192 domid = int(sxp.child_value(info, 'domid', '-1'))
1193 except:
1194 raise
1196 if domid == -1:
1197 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1199 def xm_delete(args):
1200 arg_check(args, "delete", 1)
1201 dom = args[0]
1202 if serverType == SERVER_XEN_API:
1203 server.xenapi.VM.destroy(get_single_vm(dom))
1204 else:
1205 server.xend.domain.delete(dom)
1207 def xm_suspend(args):
1208 arg_check(args, "suspend", 1)
1209 dom = args[0]
1210 if serverType == SERVER_XEN_API:
1211 server.xenapi.VM.suspend(get_single_vm(dom))
1212 else:
1213 server.xend.domain.suspend(dom)
1215 def xm_resume(args):
1216 arg_check(args, "resume", 1, 2)
1218 try:
1219 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1220 except getopt.GetoptError, opterr:
1221 err(opterr)
1222 usage('resume')
1224 paused = False
1225 for (k, v) in options:
1226 if k in ['-p', '--paused']:
1227 paused = True
1229 if len(params) != 1:
1230 err("Wrong number of parameters")
1231 usage('resume')
1233 dom = params[0]
1234 if serverType == SERVER_XEN_API:
1235 server.xenapi.VM.resume(get_single_vm(dom), paused)
1236 else:
1237 server.xend.domain.resume(dom, paused)
1239 def xm_reboot(args):
1240 arg_check(args, "reboot", 1, 3)
1241 from xen.xm import shutdown
1242 shutdown.main(["shutdown", "-R"] + args)
1244 def xm_shutdown(args):
1245 arg_check(args, "shutdown", 1, 4)
1246 from xen.xm import shutdown
1247 shutdown.main(["shutdown"] + args)
1249 def xm_pause(args):
1250 arg_check(args, "pause", 1)
1251 dom = args[0]
1253 if serverType == SERVER_XEN_API:
1254 server.xenapi.VM.pause(get_single_vm(dom))
1255 else:
1256 server.xend.domain.pause(dom)
1258 def xm_unpause(args):
1259 arg_check(args, "unpause", 1)
1260 dom = args[0]
1262 if serverType == SERVER_XEN_API:
1263 server.xenapi.VM.unpause(get_single_vm(dom))
1264 else:
1265 server.xend.domain.unpause(dom)
1267 def xm_dump_core(args):
1268 live = False
1269 crash = False
1270 try:
1271 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1272 for (k, v) in options:
1273 if k in ('-L', '--live'):
1274 live = True
1275 if k in ('-C', '--crash'):
1276 crash = True
1278 if len(params) not in (1, 2):
1279 raise OptionError("Expects 1 or 2 argument(s)")
1280 except getopt.GetoptError, e:
1281 raise OptionError(str(e))
1283 dom = params[0]
1284 if len(params) == 2:
1285 filename = os.path.abspath(params[1])
1286 else:
1287 filename = None
1289 if not live:
1290 server.xend.domain.pause(dom)
1292 try:
1293 print "Dumping core of domain: %s ..." % str(dom)
1294 server.xend.domain.dump(dom, filename, live, crash)
1295 finally:
1296 if not live:
1297 server.xend.domain.unpause(dom)
1299 if crash:
1300 print "Destroying domain: %s ..." % str(dom)
1301 server.xend.domain.destroy(dom)
1303 def xm_rename(args):
1304 arg_check(args, "rename", 2)
1306 if serverType == SERVER_XEN_API:
1307 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1308 else:
1309 server.xend.domain.setName(args[0], args[1])
1311 def xm_importcommand(command, args):
1312 cmd = __import__(command, globals(), locals(), 'xen.xm')
1313 cmd.main([command] + args)
1316 #############################################################
1318 def xm_vcpu_pin(args):
1319 arg_check(args, "vcpu-pin", 3)
1321 def cpu_make_map(cpulist):
1322 cpus = []
1323 for c in cpulist.split(','):
1324 if c.find('-') != -1:
1325 (x,y) = c.split('-')
1326 for i in range(int(x),int(y)+1):
1327 cpus.append(int(i))
1328 else:
1329 # remove this element from the list
1330 if c[0] == '^':
1331 cpus = [x for x in cpus if x != int(c[1:])]
1332 else:
1333 cpus.append(int(c))
1334 cpus.sort()
1335 return cpus
1337 dom = args[0]
1338 vcpu = args[1]
1339 if args[2] == 'all':
1340 cpumap = cpu_make_map('0-63')
1341 else:
1342 cpumap = cpu_make_map(args[2])
1344 if serverType == SERVER_XEN_API:
1345 cpumap = map(str, cpumap)
1346 server.xenapi.VM.add_to_VCPUs_params_live(
1347 get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap))
1348 else:
1349 server.xend.domain.pincpu(dom, vcpu, cpumap)
1351 def xm_mem_max(args):
1352 arg_check(args, "mem-max", 2)
1354 dom = args[0]
1356 if serverType == SERVER_XEN_API:
1357 mem = int_unit(args[1], 'k') * 1024
1358 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1359 else:
1360 mem = int_unit(args[1], 'm')
1361 server.xend.domain.maxmem_set(dom, mem)
1363 def xm_mem_set(args):
1364 arg_check(args, "mem-set", 2)
1366 dom = args[0]
1368 if serverType == SERVER_XEN_API:
1369 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1370 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1371 mem_target)
1372 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1373 mem_target)
1374 else:
1375 mem_target = int_unit(args[1], 'm')
1376 server.xend.domain.setMemoryTarget(dom, mem_target)
1378 def xm_vcpu_set(args):
1379 arg_check(args, "vcpu-set", 2)
1381 dom = args[0]
1382 vcpus = int(args[1])
1384 if serverType == SERVER_XEN_API:
1385 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1386 else:
1387 server.xend.domain.setVCpuCount(dom, vcpus)
1389 def xm_destroy(args):
1390 arg_check(args, "destroy", 1)
1392 dom = args[0]
1394 if serverType == SERVER_XEN_API:
1395 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1396 else:
1397 server.xend.domain.destroy(dom)
1399 def xm_domid(args):
1400 arg_check(args, "domid", 1)
1402 name = args[0]
1404 if serverType == SERVER_XEN_API:
1405 print server.xenapi.VM.get_domid(get_single_vm(name))
1406 else:
1407 dom = server.xend.domain(name)
1408 print sxp.child_value(dom, 'domid')
1410 def xm_domname(args):
1411 arg_check(args, "domname", 1)
1413 name = args[0]
1415 if serverType == SERVER_XEN_API:
1416 print server.xenapi.VM.get_name_label(get_single_vm(name))
1417 else:
1418 dom = server.xend.domain(name)
1419 print sxp.child_value(dom, 'name')
1421 def xm_sched_sedf(args):
1422 xenapi_unsupported()
1424 def ns_to_ms(val):
1425 return float(val) * 0.000001
1427 def ms_to_ns(val):
1428 return (float(val) / 0.000001)
1430 def print_sedf(info):
1431 info['period'] = ns_to_ms(info['period'])
1432 info['slice'] = ns_to_ms(info['slice'])
1433 info['latency'] = ns_to_ms(info['latency'])
1434 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1435 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1437 check_sched_type('sedf')
1439 # we want to just display current info if no parameters are passed
1440 if len(args) == 0:
1441 domid = None
1442 else:
1443 # we expect at least a domain id (name or number)
1444 # and at most a domid up to 5 options with values
1445 arg_check(args, "sched-sedf", 1, 11)
1446 domid = args[0]
1447 # drop domid from args since get_opt doesn't recognize it
1448 args = args[1:]
1450 opts = {}
1451 try:
1452 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1453 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1454 except getopt.GetoptError, opterr:
1455 err(opterr)
1456 usage('sched-sedf')
1458 # convert to nanoseconds if needed
1459 for (k, v) in options:
1460 if k in ['-p', '--period']:
1461 opts['period'] = ms_to_ns(v)
1462 elif k in ['-s', '--slice']:
1463 opts['slice'] = ms_to_ns(v)
1464 elif k in ['-l', '--latency']:
1465 opts['latency'] = ms_to_ns(v)
1466 elif k in ['-e', '--extratime']:
1467 opts['extratime'] = v
1468 elif k in ['-w', '--weight']:
1469 opts['weight'] = v
1471 doms = filter(lambda x : domid_match(domid, x),
1472 [parse_doms_info(dom)
1473 for dom in getDomains(None, 'running')])
1474 if domid is not None and doms == []:
1475 err("Domain '%s' does not exist." % domid)
1476 usage('sched-sedf')
1478 # print header if we aren't setting any parameters
1479 if len(opts.keys()) == 0:
1480 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1481 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1482 'Extra','Weight')
1484 for d in doms:
1485 # fetch current values so as not to clobber them
1486 try:
1487 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1488 except xmlrpclib.Fault:
1489 # domain does not support sched-sedf?
1490 sedf_raw = {}
1492 sedf_info = parse_sedf_info(sedf_raw)
1493 sedf_info['name'] = d['name']
1494 # update values in case of call to set
1495 if len(opts.keys()) > 0:
1496 for k in opts.keys():
1497 sedf_info[k]=opts[k]
1499 # send the update, converting user input
1500 v = map(int, [sedf_info['period'], sedf_info['slice'],
1501 sedf_info['latency'],sedf_info['extratime'],
1502 sedf_info['weight']])
1503 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1504 if int(rv) != 0:
1505 err("Failed to set sedf parameters (rv=%d)."%(rv))
1507 # not setting values, display info
1508 else:
1509 print_sedf(sedf_info)
1511 def xm_sched_credit(args):
1512 """Get/Set options for Credit Scheduler."""
1514 check_sched_type('credit')
1516 try:
1517 opts, params = getopt.getopt(args, "d:w:c:",
1518 ["domain=", "weight=", "cap="])
1519 except getopt.GetoptError, opterr:
1520 err(opterr)
1521 usage('sched-credit')
1523 domid = None
1524 weight = None
1525 cap = None
1527 for o, a in opts:
1528 if o == "-d":
1529 domid = a
1530 elif o == "-w":
1531 weight = int(a)
1532 elif o == "-c":
1533 cap = int(a);
1535 doms = filter(lambda x : domid_match(domid, x),
1536 [parse_doms_info(dom)
1537 for dom in getDomains(None, 'all')])
1539 if weight is None and cap is None:
1540 if domid is not None and doms == []:
1541 err("Domain '%s' does not exist." % domid)
1542 usage('sched-credit')
1543 # print header if we aren't setting any parameters
1544 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1546 for d in doms:
1547 try:
1548 if serverType == SERVER_XEN_API:
1549 info = server.xenapi.VM_metrics.get_VCPUs_params(
1550 server.xenapi.VM.get_metrics(
1551 get_single_vm(d['name'])))
1552 else:
1553 info = server.xend.domain.sched_credit_get(d['name'])
1554 except xmlrpclib.Fault:
1555 pass
1557 if 'weight' not in info or 'cap' not in info:
1558 # domain does not support sched-credit?
1559 info = {'weight': -1, 'cap': -1}
1561 info['weight'] = int(info['weight'])
1562 info['cap'] = int(info['cap'])
1564 info['name'] = d['name']
1565 info['domid'] = str(d['domid'])
1566 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1567 else:
1568 if domid is None:
1569 # place holder for system-wide scheduler parameters
1570 err("No domain given.")
1571 usage('sched-credit')
1573 if serverType == SERVER_XEN_API:
1574 if doms[0]['domid']:
1575 server.xenapi.VM.add_to_VCPUs_params_live(
1576 get_single_vm(domid),
1577 "weight",
1578 weight)
1579 server.xenapi.VM.add_to_VCPUs_params_live(
1580 get_single_vm(domid),
1581 "cap",
1582 cap)
1583 else:
1584 server.xenapi.VM.add_to_VCPUs_params(
1585 get_single_vm(domid),
1586 "weight",
1587 weight)
1588 server.xenapi.VM.add_to_VCPUs_params(
1589 get_single_vm(domid),
1590 "cap",
1591 cap)
1592 else:
1593 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1594 if result != 0:
1595 err(str(result))
1597 def xm_info(args):
1598 arg_check(args, "info", 0)
1600 if serverType == SERVER_XEN_API:
1602 # Need to fake out old style xm info as people rely on parsing it
1604 host_record = server.xenapi.host.get_record(
1605 server.xenapi.session.get_this_host(server.getSession()))
1607 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1609 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1611 def getVal(keys, default=""):
1612 data = host_record
1613 for key in keys:
1614 if key in data:
1615 data = data[key]
1616 else:
1617 return default
1618 return data
1620 def getCpuMhz():
1621 cpu_speeds = [int(host_cpu_record["speed"])
1622 for host_cpu_record in host_cpu_records
1623 if "speed" in host_cpu_record]
1624 if len(cpu_speeds) > 0:
1625 return sum(cpu_speeds) / len(cpu_speeds)
1626 else:
1627 return 0
1629 getCpuMhz()
1631 def getCpuFeatures():
1632 if len(host_cpu_records) > 0:
1633 return host_cpu_records[0].get("features", "")
1634 else:
1635 return ""
1637 info = {
1638 "host": getVal(["name_label"]),
1639 "release": getVal(["software_version", "release"]),
1640 "version": getVal(["software_version", "version"]),
1641 "machine": getVal(["software_version", "machine"]),
1642 "nr_cpus": len(getVal(["host_CPUs"], [])),
1643 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1644 "sockets_per_node": getVal(["cpu_configuration", "sockets_per_node"]),
1645 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1646 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1647 "cpu_mhz": getCpuMhz(),
1648 "hw_caps": getCpuFeatures(),
1649 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1650 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1651 "xen_major": getVal(["software_version", "xen_major"]),
1652 "xen_minor": getVal(["software_version", "xen_minor"]),
1653 "xen_extra": getVal(["software_version", "xen_extra"]),
1654 "xen_caps": " ".join(getVal(["capabilities"], [])),
1655 "xen_scheduler": getVal(["sched_policy"]),
1656 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1657 "platform_params": getVal(["other_config", "platform_params"]),
1658 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1659 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1660 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1661 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1662 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1663 "xend_config_format":getVal(["software_version", "xend_config_format"])
1666 sorted = info.items()
1667 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1669 for (k, v) in sorted:
1670 print "%-23s:" % k, v
1671 else:
1672 info = server.xend.node.info()
1673 for x in info[1:]:
1674 if len(x) < 2:
1675 print "%-23s: (none)" % x[0]
1676 else:
1677 print "%-23s:" % x[0], x[1]
1679 def xm_console(args):
1680 arg_check(args, "console", 1, 2)
1682 quiet = False;
1684 try:
1685 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1686 except getopt.GetoptError, opterr:
1687 err(opterr)
1688 usage('console')
1690 for (k, v) in options:
1691 if k in ['-q', '--quiet']:
1692 quiet = True
1693 else:
1694 assert False
1696 if len(params) != 1:
1697 err('No domain given')
1698 usage('console')
1700 dom = params[0]
1702 try:
1703 if serverType == SERVER_XEN_API:
1704 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1705 else:
1706 info = server.xend.domain(dom)
1707 domid = int(sxp.child_value(info, 'domid', '-1'))
1708 except:
1709 if quiet:
1710 sys.exit(1)
1711 else:
1712 raise
1714 if domid == -1:
1715 if quiet:
1716 sys.exit(1)
1717 else:
1718 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1720 console.execConsole(domid)
1723 def xm_uptime(args):
1724 short_mode = 0
1726 try:
1727 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1728 except getopt.GetoptError, opterr:
1729 err(opterr)
1730 usage('uptime')
1732 for (k, v) in options:
1733 if k in ['-s', '--short']:
1734 short_mode = 1
1736 doms = getDomains(params, 'all')
1738 if short_mode == 0:
1739 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1741 for dom in doms:
1742 d = parse_doms_info(dom)
1743 if d['domid'] == '':
1744 uptime = 0
1745 elif int(d['domid']) > 0:
1746 uptime = int(round(d['up_time']))
1747 else:
1748 f=open('/proc/uptime', 'r')
1749 upfile = f.read()
1750 uptime = int(round(float(upfile.split(' ')[0])))
1751 f.close()
1753 days = int(uptime / 86400)
1754 uptime -= (days * 86400)
1755 hours = int(uptime / 3600)
1756 uptime -= (hours * 3600)
1757 minutes = int(uptime / 60)
1758 uptime -= (minutes * 60)
1759 seconds = uptime
1761 upstring = ""
1762 if days > 0:
1763 upstring += str(days) + " day"
1764 if days > 1:
1765 upstring += "s"
1766 upstring += ", "
1767 upstring += '%(hours)2d:%(minutes)02d' % vars()
1769 if short_mode:
1770 now = datetime.datetime.now()
1771 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1772 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1773 else:
1774 upstring += ':%(seconds)02d' % vars()
1775 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1777 print upstring
1779 def xm_sysrq(args):
1780 arg_check(args, "sysrq", 2)
1781 dom = args[0]
1782 req = args[1]
1783 if serverType == SERVER_XEN_API:
1784 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1785 else:
1786 server.xend.domain.send_sysrq(dom, req)
1788 def xm_trigger(args):
1789 vcpu = 0
1791 arg_check(args, "trigger", 2, 3)
1792 dom = args[0]
1793 trigger = args[1]
1794 if len(args) == 3:
1795 vcpu = int(args[2])
1797 if serverType == SERVER_XEN_API:
1798 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1799 else:
1800 server.xend.domain.send_trigger(dom, trigger, vcpu)
1802 def xm_debug_keys(args):
1803 arg_check(args, "debug-keys", 1)
1805 keys = str(args[0])
1807 if serverType == SERVER_XEN_API:
1808 server.xenapi.host.send_debug_keys(
1809 server.xenapi.session.get_this_host(server.getSession()),
1810 keys)
1811 else:
1812 server.xend.node.send_debug_keys(keys)
1814 def xm_top(args):
1815 arg_check(args, "top", 0)
1817 os.execvp('xentop', ['xentop'])
1819 def xm_dmesg(args):
1820 arg_check(args, "dmesg", 0, 1)
1822 try:
1823 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1824 except getopt.GetoptError, opterr:
1825 err(opterr)
1826 usage('dmesg')
1828 use_clear = 0
1829 for (k, v) in options:
1830 if k in ['-c', '--clear']:
1831 use_clear = 1
1833 if len(params) :
1834 err("No parameter required")
1835 usage('dmesg')
1837 if serverType == SERVER_XEN_API:
1838 host = server.xenapi.session.get_this_host(server.getSession())
1839 if use_clear:
1840 print server.xenapi.host.dmesg_clear(host),
1841 else:
1842 print server.xenapi.host.dmesg(host),
1843 else:
1844 if not use_clear:
1845 print server.xend.node.dmesg.info(),
1846 else:
1847 print server.xend.node.dmesg.clear(),
1849 def xm_log(args):
1850 arg_check(args, "log", 0)
1852 if serverType == SERVER_XEN_API:
1853 print server.xenapi.host.get_log(
1854 server.xenapi.session.get_this_host(server.getSession()))
1855 else:
1856 print server.xend.node.log()
1858 def xm_serve(args):
1859 if serverType == SERVER_XEN_API:
1860 print "Not supported with XenAPI"
1861 sys.exit(-1)
1863 arg_check(args, "serve", 0)
1865 from fcntl import fcntl, F_SETFL
1867 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1868 s.connect(XendClient.XML_RPC_SOCKET)
1869 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1871 while True:
1872 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1873 if s in iwtd:
1874 data = s.recv(4096)
1875 if len(data) > 0:
1876 sys.stdout.write(data)
1877 sys.stdout.flush()
1878 else:
1879 break
1880 if sys.stdin in iwtd:
1881 data = sys.stdin.read(4096)
1882 if len(data) > 0:
1883 s.sendall(data)
1884 else:
1885 break
1886 s.close()
1888 def parse_dev_info(info):
1889 def get_info(n, t, d):
1890 i = 0
1891 while i < len(info):
1892 if (info[i][0] == n):
1893 return t(info[i][1])
1894 i = i + 1
1895 return t(d)
1896 return {
1897 #common
1898 'backend-id' : get_info('backend-id', int, -1),
1899 'handle' : get_info('handle', int, 0),
1900 'state' : get_info('state', int, -1),
1901 'be-path' : get_info('backend', str, '??'),
1902 'event-ch' : get_info('event-channel',int, -1),
1903 #network specific
1904 'virtual-device' : get_info('virtual-device', str, '??'),
1905 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1906 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1907 'mac' : get_info('mac', str, '??'),
1908 #block-device specific
1909 'ring-ref' : get_info('ring-ref', int, -1),
1912 def arg_check_for_resource_list(args, name):
1913 use_long = 0
1914 try:
1915 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1916 except getopt.GetoptError, opterr:
1917 err(opterr)
1918 sys.exit(1)
1920 for (k, v) in options:
1921 if k in ['-l', '--long']:
1922 use_long = 1
1924 if len(params) == 0:
1925 print 'No domain parameter given'
1926 usage(name)
1927 if len(params) > 1:
1928 print 'No multiple domain parameters allowed'
1929 usage(name)
1931 return (use_long, params)
1933 def xm_network_list(args):
1934 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1936 dom = params[0]
1938 if serverType == SERVER_XEN_API:
1939 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1940 vif_properties = \
1941 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1942 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
1943 zip(range(len(vif_properties)), vif_properties))
1944 else:
1945 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1947 if use_long:
1948 map(PrettyPrint.prettyprint, devs)
1949 else:
1950 hdr = 0
1951 for x in devs:
1952 if hdr == 0:
1953 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1954 hdr = 1
1955 ni = parse_dev_info(x[1])
1956 ni['idx'] = int(x[0])
1957 print ("%(idx)-3d "
1958 "%(backend-id)-3d"
1959 "%(mac)-17s "
1960 "%(handle)-3d "
1961 "%(state)-3d "
1962 "%(event-ch)-3d "
1963 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1964 "%(be-path)-30s "
1965 % ni)
1967 def xm_block_list(args):
1968 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1970 dom = params[0]
1972 if serverType == SERVER_XEN_API:
1973 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1974 vbd_properties = \
1975 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
1976 vbd_devs = \
1977 map(server.xenapi.VBD.get_device, vbd_refs)
1978 vbd_devids = \
1979 map(blkdev_name_to_number, vbd_devs)
1980 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
1981 zip(vbd_devids, vbd_properties))
1982 else:
1983 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1985 if use_long:
1986 map(PrettyPrint.prettyprint, devs)
1987 else:
1988 hdr = 0
1989 for x in devs:
1990 if hdr == 0:
1991 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1992 hdr = 1
1993 ni = parse_dev_info(x[1])
1994 ni['idx'] = int(x[0])
1995 print ("%(idx)-3d "
1996 "%(backend-id)-3d "
1997 "%(handle)-3d "
1998 "%(state)-3d "
1999 "%(event-ch)-3d "
2000 "%(ring-ref)-5d "
2001 "%(be-path)-30s "
2002 % ni)
2004 def xm_vtpm_list(args):
2005 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2007 dom = params[0]
2009 if serverType == SERVER_XEN_API:
2010 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2011 vtpm_properties = \
2012 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2013 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2014 zip(range(len(vtpm_properties)), vtpm_properties))
2015 else:
2016 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2018 if use_long:
2019 map(PrettyPrint.prettyprint, devs)
2020 else:
2021 hdr = 0
2022 for x in devs:
2023 if hdr == 0:
2024 print 'Idx BE handle state evt-ch ring-ref BE-path'
2025 hdr = 1
2026 ni = parse_dev_info(x[1])
2027 ni['idx'] = int(x[0])
2028 print ("%(idx)-3d "
2029 "%(backend-id)-3d "
2030 "%(handle)-3d "
2031 "%(state)-3d "
2032 "%(event-ch)-3d "
2033 "%(ring-ref)-5d "
2034 "%(be-path)-30s "
2035 % ni)
2038 def parse_block_configuration(args):
2039 dom = args[0]
2041 if args[1].startswith('tap:'):
2042 cls = 'tap'
2043 else:
2044 cls = 'vbd'
2046 vbd = [cls,
2047 ['uname', args[1]],
2048 ['dev', args[2]],
2049 ['mode', args[3]]]
2050 if len(args) == 5:
2051 vbd.append(['backend', args[4]])
2053 return (dom, vbd)
2056 def xm_block_attach(args):
2057 arg_check(args, 'block-attach', 4, 5)
2059 if serverType == SERVER_XEN_API:
2060 dom = args[0]
2061 uname = args[1]
2062 dev = args[2]
2063 mode = args[3]
2065 # First create new VDI
2066 vdi_record = {
2067 "name_label": "vdi" + str(uname.__hash__()),
2068 "name_description": "",
2069 "SR": get_default_SR(),
2070 "virtual_size": 0,
2071 "sector_size": 512,
2072 "type": "system",
2073 "sharable": False,
2074 "read_only": mode!="w",
2075 "other_config": {"location": uname}
2078 vdi_ref = server.xenapi.VDI.create(vdi_record)
2080 # Now create new VBD
2082 vbd_record = {
2083 "VM": get_single_vm(dom),
2084 "VDI": vdi_ref,
2085 "device": dev,
2086 "bootable": True,
2087 "mode": mode=="w" and "RW" or "RO",
2088 "type": "Disk",
2089 "qos_algorithm_type": "",
2090 "qos_algorithm_params": {}
2093 server.xenapi.VBD.create(vbd_record)
2095 else:
2096 (dom, vbd) = parse_block_configuration(args)
2097 server.xend.domain.device_create(dom, vbd)
2100 def xm_block_configure(args):
2101 arg_check(args, 'block-configure', 4, 5)
2103 (dom, vbd) = parse_block_configuration(args)
2104 server.xend.domain.device_configure(dom, vbd)
2107 def xm_network_attach(args):
2108 arg_check(args, 'network-attach', 1, 10)
2110 dom = args[0]
2111 vif = ['vif']
2112 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2113 'backend', 'vifname', 'rate', 'model']
2115 if serverType == SERVER_XEN_API:
2116 vif_record = {
2117 "device": "eth0",
2118 "network": get_default_Network(),
2119 "VM": get_single_vm(dom),
2120 "MAC": "",
2121 "MTU": "",
2122 "qos_algorithm_type": "",
2123 "qos_algorithm_params": {},
2124 "other_config": {}
2127 def set(keys, val):
2128 record = vif_record
2129 for key in keys[:-1]:
2130 record = record[key]
2131 record[keys[-1]] = val
2133 def get_net_from_bridge(bridge):
2134 # In OSS, we just assert network.name_label == bridge name
2135 networks = dict([(record['name_label'], ref)
2136 for ref, record in server.xenapi.network
2137 .get_all_records().items()])
2138 if bridge not in networks.keys():
2139 raise "Unknown bridge name!"
2140 return networks[bridge]
2142 vif_conv = {
2143 'type':
2144 lambda x: None,
2145 'mac':
2146 lambda x: set(['MAC'], x),
2147 'bridge':
2148 lambda x: set(['network'], get_net_from_bridge(x)),
2149 'ip':
2150 lambda x: set(['other_config', 'ip'], x),
2151 'script':
2152 lambda x: set(['other_config', 'script'], x),
2153 'backend':
2154 lambda x: set(['other_config', 'backend'], x),
2155 'vifname':
2156 lambda x: set(['device'], x),
2157 'rate':
2158 lambda x: set(['qos_algorithm_params', 'rate'], x),
2159 'model':
2160 lambda x: None
2163 for a in args[1:]:
2164 vif_param = a.split("=")
2165 if len(vif_param) != 2 or vif_param[1] == '' or \
2166 vif_param[0] not in vif_params:
2167 err("Invalid argument: %s" % a)
2168 usage('network-attach')
2169 else:
2170 vif_conv[vif_param[0]](vif_param[1])
2172 server.xenapi.VIF.create(vif_record)
2173 else:
2174 for a in args[1:]:
2175 vif_param = a.split("=")
2176 if len(vif_param) != 2 or vif_param[1] == '' or \
2177 vif_param[0] not in vif_params:
2178 err("Invalid argument: %s" % a)
2179 usage('network-attach')
2180 vif.append(vif_param)
2181 server.xend.domain.device_create(dom, vif)
2184 def detach(args, deviceClass):
2185 rm_cfg = True
2186 dom = args[0]
2187 dev = args[1]
2188 try:
2189 force = args[2]
2190 if (force != "--force") and (force != "-f"):
2191 print "Ignoring option %s"%(force)
2192 force = None
2193 except IndexError:
2194 force = None
2196 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2199 def xm_block_detach(args):
2200 if serverType == SERVER_XEN_API:
2201 arg_check(args, "xm_block_detach", 2, 3)
2202 dom = args[0]
2203 dev = args[1]
2204 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2205 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2206 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2207 if len(vbd_refs) > 0:
2208 vbd_ref = vbd_refs[0]
2209 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2211 server.xenapi.VBD.destroy(vbd_ref)
2213 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2214 server.xenapi.VDI.destroy(vdi_ref)
2215 else:
2216 raise OptionError("Cannot find device '%s' in domain '%s'"
2217 % (dev,dom))
2218 else:
2219 arg_check(args, 'block-detach', 2, 3)
2220 dom = args[0]
2221 dev = args[1]
2222 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2223 if dc == "tap":
2224 detach(args, 'tap')
2225 else:
2226 detach(args, 'vbd')
2228 def xm_network_detach(args):
2229 if serverType == SERVER_XEN_API:
2230 arg_check(args, "xm_network_detach", 2, 3)
2231 dom = args[0]
2232 devid = args[1]
2233 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2234 vif_refs = [vif_ref for vif_ref in vif_refs
2235 if server.xenapi.VIF.\
2236 get_runtime_properties(vif_ref)["handle"] == devid]
2237 if len(vif_refs) > 0:
2238 vif_ref = vif_refs[0]
2240 server.xenapi.VIF.destroy(vif_ref)
2241 else:
2242 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2243 else:
2244 arg_check(args, 'network-detach', 2, 3)
2245 detach(args, 'vif')
2248 def xm_vnet_list(args):
2249 xenapi_unsupported()
2250 try:
2251 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2252 except getopt.GetoptError, opterr:
2253 err(opterr)
2254 usage('vnet-list')
2256 use_long = 0
2257 for (k, v) in options:
2258 if k in ['-l', '--long']:
2259 use_long = 1
2261 if params:
2262 use_long = 1
2263 vnets = params
2264 else:
2265 vnets = server.xend_vnets()
2267 for vnet in vnets:
2268 try:
2269 if use_long:
2270 info = server.xend_vnet(vnet)
2271 PrettyPrint.prettyprint(info)
2272 else:
2273 print vnet
2274 except Exception, ex:
2275 print vnet, ex
2277 def xm_vnet_create(args):
2278 xenapi_unsupported()
2279 arg_check(args, "vnet-create", 1)
2280 conf = args[0]
2281 if not os.access(conf, os.R_OK):
2282 print "File not found: %s" % conf
2283 sys.exit(1)
2285 server.xend_vnet_create(conf)
2287 def xm_vnet_delete(args):
2288 xenapi_unsupported()
2289 arg_check(args, "vnet-delete", 1)
2290 vnet = args[0]
2291 server.xend_vnet_delete(vnet)
2293 def xm_network_new(args):
2294 xenapi_only()
2295 arg_check(args, "network-new", 1)
2296 network = args[0]
2298 record = {
2299 "name_label": network,
2300 "name_description": "",
2301 "other_config": {},
2302 "default_gateway": "",
2303 "default_netmask": ""
2306 server.xenapi.network.create(record)
2308 def xm_network_del(args):
2309 xenapi_only()
2310 arg_check(args, "network-del", 1)
2311 network = args[0]
2313 networks = dict([(record['name_label'], ref)
2314 for ref, record in
2315 server.xenapi.network.get_all_records().items()])
2317 if network not in networks.keys():
2318 raise ValueError("'%s' is not a valid network name" % network)
2320 server.xenapi.network.destroy(networks[network])
2322 def xm_network_show(args):
2323 xenapi_only()
2324 arg_check(args, "network-show", 0)
2326 networks = server.xenapi.network.get_all_records()
2327 pifs = server.xenapi.PIF.get_all_records()
2328 vifs = server.xenapi.VIF.get_all_records()
2330 print '%-20s %-40s %-10s' % \
2331 ('Name', 'VIFs', 'PIFs')
2333 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2335 for network_ref, network in networks.items():
2336 for i in range(max(len(network['PIFs']),
2337 len(network['VIFs']), 1)):
2338 if i < len(network['PIFs']):
2339 pif_uuid = network['PIFs'][i]
2340 else:
2341 pif_uuid = None
2343 if i < len(network['VIFs']):
2344 vif_uuid = network['VIFs'][i]
2345 else:
2346 vif_uuid = None
2348 pif = pifs.get(pif_uuid, None)
2349 vif = vifs.get(vif_uuid, None)
2351 if vif:
2352 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2353 vif = "%s.%s" % (dom_name, vif['device'])
2354 else:
2355 vif = ''
2357 if pif:
2358 if int(pif['VLAN']) > -1:
2359 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2360 else:
2361 pif = pif['device']
2362 else:
2363 pif = ''
2365 if i == 0:
2366 r = {'name_label':network['name_label'],
2367 'vif':vif, 'pif':pif}
2368 else:
2369 r = {'name_label':'', 'vif':vif, 'pif':pif}
2371 print format2 % r
2374 commands = {
2375 "shell": xm_shell,
2376 "event-monitor": xm_event_monitor,
2377 # console commands
2378 "console": xm_console,
2379 # xenstat commands
2380 "top": xm_top,
2381 # domain commands
2382 "delete": xm_delete,
2383 "destroy": xm_destroy,
2384 "domid": xm_domid,
2385 "domname": xm_domname,
2386 "dump-core": xm_dump_core,
2387 "reboot": xm_reboot,
2388 "rename": xm_rename,
2389 "restore": xm_restore,
2390 "resume": xm_resume,
2391 "save": xm_save,
2392 "shutdown": xm_shutdown,
2393 "start": xm_start,
2394 "sysrq": xm_sysrq,
2395 "trigger": xm_trigger,
2396 "uptime": xm_uptime,
2397 "suspend": xm_suspend,
2398 "list": xm_list,
2399 # memory commands
2400 "mem-max": xm_mem_max,
2401 "mem-set": xm_mem_set,
2402 # cpu commands
2403 "vcpu-pin": xm_vcpu_pin,
2404 "vcpu-list": xm_vcpu_list,
2405 "vcpu-set": xm_vcpu_set,
2406 # special
2407 "pause": xm_pause,
2408 "unpause": xm_unpause,
2409 # host commands
2410 "debug-keys": xm_debug_keys,
2411 "dmesg": xm_dmesg,
2412 "info": xm_info,
2413 "log": xm_log,
2414 "serve": xm_serve,
2415 # scheduler
2416 "sched-sedf": xm_sched_sedf,
2417 "sched-credit": xm_sched_credit,
2418 # block
2419 "block-attach": xm_block_attach,
2420 "block-detach": xm_block_detach,
2421 "block-list": xm_block_list,
2422 "block-configure": xm_block_configure,
2423 # network (AKA vifs)
2424 "network-attach": xm_network_attach,
2425 "network-detach": xm_network_detach,
2426 "network-list": xm_network_list,
2427 # network (as in XenAPI)
2428 "network-new": xm_network_new,
2429 "network-del": xm_network_del,
2430 "network-show": xm_network_show,
2431 # vnet
2432 "vnet-list": xm_vnet_list,
2433 "vnet-create": xm_vnet_create,
2434 "vnet-delete": xm_vnet_delete,
2435 # vtpm
2436 "vtpm-list": xm_vtpm_list,
2439 ## The commands supported by a separate argument parser in xend.xm.
2440 IMPORTED_COMMANDS = [
2441 'create',
2442 'new',
2443 'migrate',
2444 'labels',
2445 'cfgbootpolicy',
2446 'makepolicy',
2447 'loadpolicy',
2448 'dumppolicy',
2449 'addlabel',
2450 'rmlabel',
2451 'getlabel',
2452 'dry-run',
2453 'resources',
2454 'getpolicy',
2455 'setpolicy',
2456 'activatepolicy',
2459 for c in IMPORTED_COMMANDS:
2460 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2462 aliases = {
2463 "balloon": "mem-set",
2464 "set-vcpus": "vcpu-set",
2465 "vif-list": "network-list",
2466 "vbd-create": "block-attach",
2467 "vbd-destroy": "block-detach",
2468 "vbd-list": "block-list",
2472 def xm_lookup_cmd(cmd):
2473 if commands.has_key(cmd):
2474 return commands[cmd]
2475 elif aliases.has_key(cmd):
2476 deprecated(cmd,aliases[cmd])
2477 return commands[aliases[cmd]]
2478 elif cmd == 'help':
2479 longHelp()
2480 sys.exit(0)
2481 else:
2482 # simulate getopt's prefix matching behaviour
2483 if len(cmd) > 1:
2484 same_prefix_cmds = [commands[c] for c in commands.keys() \
2485 if c[:len(cmd)] == cmd]
2486 # only execute if there is only 1 match
2487 if len(same_prefix_cmds) == 1:
2488 return same_prefix_cmds[0]
2489 return None
2491 def deprecated(old,new):
2492 print >>sys.stderr, (
2493 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2495 def main(argv=sys.argv):
2496 if len(argv) < 2:
2497 usage()
2499 # intercept --help(-h) and output our own help
2500 for help in ['--help', '-h']:
2501 if help in argv[1:]:
2502 if help == argv[1]:
2503 longHelp()
2504 sys.exit(0)
2505 else:
2506 usage(argv[1])
2508 cmd_name = argv[1]
2509 cmd = xm_lookup_cmd(cmd_name)
2510 if cmd:
2511 # strip off prog name and subcmd
2512 args = argv[2:]
2513 _, rc = _run_cmd(cmd, cmd_name, args)
2514 sys.exit(rc)
2515 else:
2516 err('Subcommand %s not found!' % cmd_name)
2517 usage()
2519 def _run_cmd(cmd, cmd_name, args):
2520 global server
2522 try:
2523 if server is None:
2524 if serverType == SERVER_XEN_API:
2525 server = XenAPI.Session(serverURI)
2526 username, password = parseAuthentication()
2527 server.login_with_password(username, password)
2528 def logout():
2529 try:
2530 server.xenapi.session.logout()
2531 except:
2532 pass
2533 atexit.register(logout)
2534 else:
2535 server = ServerProxy(serverURI)
2537 return True, cmd(args)
2538 except socket.error, ex:
2539 if os.geteuid() != 0:
2540 err("Most commands need root access. Please try again as root.")
2541 else:
2542 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2543 except KeyboardInterrupt:
2544 print "Interrupted."
2545 return True, ''
2546 except IOError, ex:
2547 if os.geteuid() != 0:
2548 err("Most commands need root access. Please try again as root.")
2549 else:
2550 err("Unable to connect to xend: %s." % ex[1])
2551 except SystemExit, code:
2552 return code == 0, code
2553 except XenAPI.Failure, exn:
2554 for line in [''] + wrap(str(exn), 80) + ['']:
2555 print >>sys.stderr, line
2556 except xmlrpclib.Fault, ex:
2557 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2558 err("Domain '%s' does not exist." % ex.faultString)
2559 else:
2560 err(ex.faultString)
2561 _usage(cmd_name)
2562 except xmlrpclib.ProtocolError, ex:
2563 if ex.errcode == -1:
2564 print >>sys.stderr, (
2565 "Xend has probably crashed! Invalid or missing HTTP "
2566 "status code.")
2567 else:
2568 print >>sys.stderr, (
2569 "Xend has probably crashed! ProtocolError(%d, %s)." %
2570 (ex.errcode, ex.errmsg))
2571 except (ValueError, OverflowError):
2572 err("Invalid argument.")
2573 _usage(cmd_name)
2574 except OptionError, e:
2575 err(str(e))
2576 _usage(cmd_name)
2577 print e.usage
2578 except XenAPIUnsupportedException, e:
2579 err(str(e))
2580 except XSMError, e:
2581 err(str(e))
2582 except Exception, e:
2583 if serverType != SERVER_XEN_API:
2584 import xen.util.xsm.xsm as security
2585 if isinstance(e, security.XSMError):
2586 err(str(e))
2587 return False, 1
2588 print "Unexpected error:", sys.exc_info()[0]
2589 print
2590 print "Please report to xen-devel@lists.xensource.com"
2591 raise
2593 return False, 1
2595 if __name__ == "__main__":
2596 main()