direct-io.hg

view tools/python/xen/xm/main.py @ 14374:3f45afc6b025

In xm shell, add a space to the function names when tab-completing.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Mar 13 22:12:18 2007 +0000 (2007-03-13)
parents 127bee61972b
children 0c354aa0bb4a
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 readline
29 import shlex
30 import sys
31 import re
32 import getopt
33 import socket
34 import traceback
35 import xmlrpclib
36 import traceback
37 import time
38 import datetime
39 from select import select
40 import xml.dom.minidom
42 import warnings
43 warnings.filterwarnings('ignore', category=FutureWarning)
45 from xen.xend import PrettyPrint
46 from xen.xend import sxp
47 from xen.xend import XendClient
48 from xen.xend.XendConstants import *
50 from xen.xm.opts import OptionError, Opts, wrap, set_true
51 from xen.xm import console
52 from xen.util import security
53 from xen.util.xmlrpclib2 import ServerProxy
55 import XenAPI
57 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
58 # getopt.getopt if gnu_getopt is not available. This will mean that options
59 # may only be specified before positional arguments.
60 if not hasattr(getopt, 'gnu_getopt'):
61 getopt.gnu_getopt = getopt.getopt
63 XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
65 # Supported types of server
66 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
67 SERVER_XEN_API = 'Xen-API'
69 # General help message
71 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
72 "Control, list, and manipulate Xen guest instances.\n"
74 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
75 'For more help on \'xm\' see the xm(1) man page.\n' \
76 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
77 ' man page.\n'
79 # Help strings are indexed by subcommand name in this way:
80 # 'subcommand': (argstring, description)
82 SUBCOMMAND_HELP = {
83 # common commands
85 'shell' : ('', 'Launch an interactive shell.'),
87 'console' : ('[-q|--quiet] <Domain>',
88 'Attach to <Domain>\'s console.'),
89 'create' : ('<ConfigFile> [options] [vars]',
90 'Create a domain based on <ConfigFile>.'),
91 'destroy' : ('<Domain>',
92 'Terminate a domain immediately.'),
93 'help' : ('', 'Display this message.'),
94 'list' : ('[options] [Domain, ...]',
95 'List information about all/some domains.'),
96 'mem-max' : ('<Domain> <Mem>',
97 'Set the maximum amount reservation for a domain.'),
98 'mem-set' : ('<Domain> <Mem>',
99 'Set the current memory usage for a domain.'),
100 'migrate' : ('<Domain> <Host>',
101 'Migrate a domain to another machine.'),
102 'pause' : ('<Domain>', 'Pause execution of a domain.'),
103 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
104 'restore' : ('<CheckpointFile> [-p]',
105 'Restore a domain from a saved state.'),
106 'save' : ('[-c] <Domain> <CheckpointFile>',
107 'Save a domain state to restore later.'),
108 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
109 'top' : ('', 'Monitor a host and the domains in real time.'),
110 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
111 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
113 # Life cycle xm commands
114 'new' : ('<ConfigFile> [options] [vars]',
115 'Adds a domain to Xend domain management'),
116 'delete' : ('<DomainName>',
117 'Remove a domain from Xend domain management.'),
118 'start' : ('<DomainName>', 'Start a Xend managed domain'),
119 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
120 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
122 # less used commands
124 'dmesg' : ('[-c|--clear]',
125 'Read and/or clear Xend\'s message buffer.'),
126 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
127 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
128 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
129 'Dump core for a specific domain.'),
130 'info' : ('', 'Get information about Xen host.'),
131 'log' : ('', 'Print Xend log'),
132 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
133 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
134 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
135 'Get/set credit scheduler parameters.'),
136 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
137 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
138 'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
139 'Send a trigger to a domain.'),
140 'vcpu-list' : ('[<Domain>]',
141 'List the VCPUs for a domain or all domains.'),
142 'vcpu-pin' : ('<Domain> <VCPU> <CPUs|all>',
143 'Set which CPUs a VCPU can use.'),
144 'vcpu-set' : ('<Domain> <vCPUs>',
145 'Set the number of active VCPUs for allowed for the'
146 ' domain.'),
148 # device commands
150 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
151 'Create a new virtual block device.'),
152 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
153 'Change block device configuration'),
154 'block-detach' : ('<Domain> <DevId> [-f|--force]',
155 'Destroy a domain\'s virtual block device.'),
156 'block-list' : ('<Domain> [--long]',
157 'List virtual block devices for a domain.'),
158 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
159 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
160 '[vifname=<name>] [rate=<rate>] [model=<model>]',
161 'Create a new virtual network device.'),
162 'network-detach': ('<Domain> <DevId> [-f|--force]',
163 'Destroy a domain\'s virtual network device.'),
164 'network-list' : ('<Domain> [--long]',
165 'List virtual network interfaces for a domain.'),
166 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
167 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
168 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
169 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
171 # security
173 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
174 'Add security label to domain.'),
175 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
176 'Remove a security label from domain.'),
177 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
178 'Show security label for domain or resource.'),
179 'dry-run' : ('<ConfigFile>',
180 'Test if a domain can access its resources.'),
181 'resources' : ('', 'Show info for each labeled resource.'),
182 'cfgbootpolicy' : ('<policy> [boot-title]',
183 'Add policy to boot configuration.'),
184 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
185 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
186 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
187 'files.'),
188 'labels' : ('[policy] [type=dom|res|any]',
189 'List <type> labels for (active) policy.'),
190 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
191 }
193 SUBCOMMAND_OPTIONS = {
194 'sched-sedf': (
195 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
196 ('-s [MS]', '--slice[=MS]' ,
197 'Worst-case execution time(ms). (slice < period)'),
198 ('-l [MS]', '--latency[=MS]',
199 'Scaled period (ms) when domain performs heavy I/O'),
200 ('-e [FLAG]', '--extra[=FLAG]',
201 'Flag (0 or 1) controls if domain can run in extra time.'),
202 ('-w [FLOAT]', '--weight[=FLOAT]',
203 'CPU Period/slice (do not set with --period/--slice)'),
204 ),
205 'sched-credit': (
206 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
207 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
208 ('-c CAP', '--cap=CAP', 'Cap (int)'),
209 ),
210 'list': (
211 ('-l', '--long', 'Output all VM details in SXP'),
212 ('', '--label', 'Include security labels'),
213 ('', '--state=<state>', 'Select only VMs with the specified state'),
214 ),
215 'console': (
216 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
217 ),
218 'dmesg': (
219 ('-c', '--clear', 'Clear dmesg buffer'),
220 ),
221 'vnet-list': (
222 ('-l', '--long', 'List Vnets as SXP'),
223 ),
224 'network-list': (
225 ('-l', '--long', 'List resources as SXP'),
226 ),
227 'dump-core': (
228 ('-L', '--live', 'Dump core without pausing the domain'),
229 ('-C', '--crash', 'Crash domain after dumping core'),
230 ),
231 'start': (
232 ('-p', '--paused', 'Do not unpause domain after starting it'),
233 ),
234 'resume': (
235 ('-p', '--paused', 'Do not unpause domain after resuming it'),
236 ),
237 'save': (
238 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
239 ),
240 'restore': (
241 ('-p', '--paused', 'Do not unpause domain after restoring it'),
242 ),
243 }
245 common_commands = [
246 "console",
247 "create",
248 "new",
249 "delete",
250 "destroy",
251 "dump-core",
252 "help",
253 "list",
254 "mem-set",
255 "migrate",
256 "pause",
257 "reboot",
258 "restore",
259 "resume",
260 "save",
261 "shell",
262 "shutdown",
263 "start",
264 "suspend",
265 "top",
266 "unpause",
267 "uptime",
268 "vcpu-set",
269 ]
271 domain_commands = [
272 "console",
273 "create",
274 "new",
275 "delete",
276 "destroy",
277 "domid",
278 "domname",
279 "dump-core",
280 "list",
281 "mem-max",
282 "mem-set",
283 "migrate",
284 "pause",
285 "reboot",
286 "rename",
287 "restore",
288 "resume",
289 "save",
290 "shutdown",
291 "start",
292 "suspend",
293 "sysrq",
294 "trigger",
295 "top",
296 "unpause",
297 "uptime",
298 "vcpu-list",
299 "vcpu-pin",
300 "vcpu-set",
301 ]
303 host_commands = [
304 "debug-keys",
305 "dmesg",
306 "info",
307 "log",
308 "serve",
309 ]
311 scheduler_commands = [
312 "sched-credit",
313 "sched-sedf",
314 ]
316 device_commands = [
317 "block-attach",
318 "block-detach",
319 "block-list",
320 "block-configure",
321 "network-attach",
322 "network-detach",
323 "network-list",
324 "vtpm-list",
325 ]
327 vnet_commands = [
328 "vnet-list",
329 "vnet-create",
330 "vnet-delete",
331 ]
333 acm_commands = [
334 "labels",
335 "addlabel",
336 "rmlabel",
337 "getlabel",
338 "dry-run",
339 "resources",
340 "makepolicy",
341 "loadpolicy",
342 "cfgbootpolicy",
343 "dumppolicy",
344 ]
346 all_commands = (domain_commands + host_commands + scheduler_commands +
347 device_commands + vnet_commands + acm_commands + ['shell'])
350 ##
351 # Configuration File Parsing
352 ##
354 config = None
355 if os.path.isfile(XM_CONFIG_FILE):
356 try:
357 config = xml.dom.minidom.parse(XM_CONFIG_FILE)
358 except:
359 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
360 XM_CONFIG_FILE)
362 def parseServer():
363 if config:
364 server = config.getElementsByTagName('server')
365 if server:
366 st = server[0].getAttribute('type')
367 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
368 print >>sys.stderr, ('Invalid server type %s; using %s.' %
369 (st, SERVER_LEGACY_XMLRPC))
370 st = SERVER_LEGACY_XMLRPC
371 return (st, server[0].getAttribute('uri'))
373 return SERVER_LEGACY_XMLRPC, XendClient.uri
375 def parseAuthentication():
376 server = config.getElementsByTagName('server')[0]
377 return (server.getAttribute('username'),
378 server.getAttribute('password'))
380 serverType, serverURI = parseServer()
381 server = None
384 ####################################################################
385 #
386 # Help/usage printing functions
387 #
388 ####################################################################
390 def cmdHelp(cmd):
391 """Print help for a specific subcommand."""
393 for fc in SUBCOMMAND_HELP.keys():
394 if fc[:len(cmd)] == cmd:
395 cmd = fc
396 break
398 try:
399 args, desc = SUBCOMMAND_HELP[cmd]
400 except KeyError:
401 shortHelp()
402 return
404 print 'Usage: xm %s %s' % (cmd, args)
405 print
406 print desc
408 try:
409 # If options help message is defined, print this.
410 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
411 if shortopt and longopt:
412 optdesc = '%s, %s' % (shortopt, longopt)
413 elif shortopt:
414 optdesc = shortopt
415 elif longopt:
416 optdesc = longopt
418 wrapped_desc = wrap(desc, 43)
419 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
420 for line in wrapped_desc[1:]:
421 print ' ' * 33 + line
422 print
423 except KeyError:
424 # if the command is an external module, we grab usage help
425 # from the module itself.
426 if cmd in IMPORTED_COMMANDS:
427 try:
428 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
429 cmd_usage = getattr(cmd_module, "help", None)
430 if cmd_usage:
431 print cmd_usage()
432 except ImportError:
433 pass
435 def shortHelp():
436 """Print out generic help when xm is called without subcommand."""
438 print USAGE_HELP
439 print 'Common \'xm\' commands:\n'
441 for command in common_commands:
442 try:
443 args, desc = SUBCOMMAND_HELP[command]
444 except KeyError:
445 continue
446 wrapped_desc = wrap(desc, 50)
447 print ' %-20s %-50s' % (command, wrapped_desc[0])
448 for line in wrapped_desc[1:]:
449 print ' ' * 22 + line
451 print
452 print USAGE_FOOTER
453 print 'For a complete list of subcommands run \'xm help\'.'
455 def longHelp():
456 """Print out full help when xm is called with xm --help or xm help"""
458 print USAGE_HELP
459 print 'xm full list of subcommands:\n'
461 for command in all_commands:
462 try:
463 args, desc = SUBCOMMAND_HELP[command]
464 except KeyError:
465 continue
467 wrapped_desc = wrap(desc, 50)
468 print ' %-20s %-50s' % (command, wrapped_desc[0])
469 for line in wrapped_desc[1:]:
470 print ' ' * 22 + line
472 print
473 print USAGE_FOOTER
475 def _usage(cmd):
476 """ Print help usage information """
477 if cmd:
478 cmdHelp(cmd)
479 else:
480 shortHelp()
482 def usage(cmd = None):
483 """ Print help usage information and exits """
484 _usage(cmd)
485 sys.exit(1)
488 ####################################################################
489 #
490 # Utility functions
491 #
492 ####################################################################
494 def arg_check(args, name, lo, hi = -1):
495 n = len([i for i in args if i != '--'])
497 if hi == -1:
498 if n != lo:
499 err("'xm %s' requires %d argument%s.\n" % (name, lo,
500 lo == 1 and '' or 's'))
501 usage(name)
502 else:
503 if n < lo or n > hi:
504 err("'xm %s' requires between %d and %d arguments.\n" %
505 (name, lo, hi))
506 usage(name)
509 def unit(c):
510 if not c.isalpha():
511 return 0
512 base = 1
513 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
514 elif c == 'M' or c == 'm': base = 1024 * 1024
515 elif c == 'K' or c == 'k': base = 1024
516 else:
517 print 'ignoring unknown unit'
518 return base
520 def int_unit(str, dest):
521 base = unit(str[-1])
522 if not base:
523 return int(str)
525 value = int(str[:-1])
526 dst_base = unit(dest)
527 if dst_base == 0:
528 dst_base = 1
529 if dst_base > base:
530 return value / (dst_base / base)
531 else:
532 return value * (base / dst_base)
534 def err(msg):
535 print >>sys.stderr, "Error:", msg
538 def get_single_vm(dom):
539 uuids = server.xenapi.VM.get_by_name_label(dom)
540 n = len(uuids)
541 if n == 1:
542 return uuids[0]
543 else:
544 dominfo = server.xend.domain(dom, False)
545 return dominfo['uuid']
547 ##
548 #
549 # Xen-API Shell
550 #
551 ##
553 class Shell(cmd.Cmd):
554 def __init__(self):
555 cmd.Cmd.__init__(self)
556 self.prompt = "xm> "
557 if serverType == SERVER_XEN_API:
558 res = server.xenapi._UNSUPPORTED_list_all_methods()
559 for f in res:
560 setattr(Shell, 'do_' + f + ' ', self.default)
562 def preloop(self):
563 cmd.Cmd.preloop(self)
564 readline.set_completer_delims(' ')
566 def default(self, line):
567 words = shlex.split(line)
568 if len(words) > 0 and words[0] == 'xm':
569 words = words[1:]
570 if len(words) > 0:
571 cmd = xm_lookup_cmd(words[0])
572 if cmd:
573 _run_cmd(cmd, words[0], words[1:])
574 elif serverType == SERVER_XEN_API:
575 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
576 tuple(x)),
577 words[0], words[1:])
578 if ok and res is not None and res != '':
579 pprint.pprint(res)
580 else:
581 print '*** Unknown command: %s' % words[0]
582 return False
584 def completedefault(self, text, line, begidx, endidx):
585 words = shlex.split(line[:begidx])
586 clas, func = words[0].split('.')
587 if len(words) > 1 or \
588 func.startswith('get_by_') or \
589 func == 'get_all':
590 return []
591 uuids = server.xenapi_request('%s.get_all' % clas, ())
592 return [u + " " for u in uuids if u.startswith(text)]
594 def emptyline(self):
595 pass
597 def do_EOF(self, line):
598 print
599 sys.exit(0)
601 def do_help(self, line):
602 _usage(line)
605 def xm_shell(args):
606 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
609 #########################################################################
610 #
611 # Main xm functions
612 #
613 #########################################################################
615 def xm_save(args):
616 arg_check(args, "save", 2, 3)
618 try:
619 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
620 except getopt.GetoptError, opterr:
621 err(opterr)
622 sys.exit(1)
624 checkpoint = False
625 for (k, v) in options:
626 if k in ['-c', '--checkpoint']:
627 checkpoint = True
629 if len(params) != 2:
630 err("Wrong number of parameters")
631 usage('save')
632 sys.exit(1)
634 try:
635 dominfo = parse_doms_info(server.xend.domain(params[0]))
636 except xmlrpclib.Fault, ex:
637 raise ex
639 domid = dominfo['domid']
640 savefile = os.path.abspath(params[1])
642 if not os.access(os.path.dirname(savefile), os.W_OK):
643 err("xm save: Unable to create file %s" % savefile)
644 sys.exit(1)
646 server.xend.domain.save(domid, savefile, checkpoint)
648 def xm_restore(args):
649 arg_check(args, "restore", 1, 2)
651 try:
652 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
653 except getopt.GetoptError, opterr:
654 err(opterr)
655 usage('restore')
657 paused = False
658 for (k, v) in options:
659 if k in ['-p', '--paused']:
660 paused = True
662 if len(params) != 1:
663 err("Wrong number of parameters")
664 usage('restore')
666 savefile = os.path.abspath(params[0])
668 if not os.access(savefile, os.R_OK):
669 err("xm restore: Unable to read file %s" % savefile)
670 sys.exit(1)
672 server.xend.domain.restore(savefile, paused)
675 def getDomains(domain_names, state, full = 0):
676 if domain_names:
677 return [server.xend.domain(dom, full) for dom in domain_names]
678 else:
679 return server.xend.domains_with_state(True, state, full)
682 def xm_list(args):
683 use_long = 0
684 show_vcpus = 0
685 show_labels = 0
686 state = 'all'
687 try:
688 (options, params) = getopt.gnu_getopt(args, 'lv',
689 ['long','vcpus','label',
690 'state='])
691 except getopt.GetoptError, opterr:
692 err(opterr)
693 usage('list')
695 for (k, v) in options:
696 if k in ['-l', '--long']:
697 use_long = 1
698 if k in ['-v', '--vcpus']:
699 show_vcpus = 1
700 if k in ['--label']:
701 show_labels = 1
702 if k in ['--state']:
703 state = v
705 if state != 'all' and len(params) > 0:
706 raise OptionError(
707 "You may specify either a state or a particular VM, but not both")
709 if show_vcpus:
710 print >>sys.stderr, (
711 "xm list -v is deprecated. Please use xm vcpu-list.")
712 xm_vcpu_list(params)
713 return
715 doms = getDomains(params, state, use_long)
717 if use_long:
718 map(PrettyPrint.prettyprint, doms)
719 elif show_labels:
720 xm_label_list(doms)
721 else:
722 xm_brief_list(doms)
725 def parse_doms_info(info):
726 def get_info(n, t, d):
727 return t(sxp.child_value(info, n, d))
729 def get_status(n, t, d):
730 return DOM_STATES[t(sxp.child_value(info, n, d))]
732 start_time = get_info('start_time', float, -1)
733 if start_time == -1:
734 up_time = float(-1)
735 else:
736 up_time = time.time() - start_time
738 return {
739 'domid' : get_info('domid', str, ''),
740 'name' : get_info('name', str, '??'),
741 'mem' : get_info('memory_dynamic_min', int, 0),
742 'state' : get_info('state', str, ''),
743 'cpu_time' : get_info('cpu_time', float, 0.0),
744 # VCPUs is the number online when the VM is up, or the number
745 # configured otherwise.
746 'vcpus' : get_info('online_vcpus', int,
747 get_info('vcpus', int, 0)),
748 'up_time' : up_time,
749 'seclabel' : security.get_security_printlabel(info),
750 }
752 def check_sched_type(sched):
753 current = 'unknown'
754 for x in server.xend.node.info()[1:]:
755 if len(x) > 1 and x[0] == 'xen_scheduler':
756 current = x[1]
757 break
758 if sched != current:
759 err("Xen is running with the %s scheduler" % current)
760 sys.exit(1)
762 def parse_sedf_info(info):
763 def get_info(n, t, d):
764 return t(sxp.child_value(info, n, d))
766 return {
767 'domid' : get_info('domid', int, -1),
768 'period' : get_info('period', int, -1),
769 'slice' : get_info('slice', int, -1),
770 'latency' : get_info('latency', int, -1),
771 'extratime': get_info('extratime', int, -1),
772 'weight' : get_info('weight', int, -1),
773 }
775 def domid_match(domid, info):
776 return domid is None or domid == info['name'] or \
777 domid == str(info['domid'])
779 def xm_brief_list(doms):
780 print '%-40s %3s %5s %5s %10s %9s' % \
781 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
783 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
784 "%(cpu_time)8.1f"
786 for dom in doms:
787 d = parse_doms_info(dom)
788 print format % d
790 def xm_label_list(doms):
791 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
792 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
794 output = []
795 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
796 '%(cpu_time)8.1f %(seclabel)9s'
798 for dom in doms:
799 d = parse_doms_info(dom)
800 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
801 if not d['seclabel']:
802 d['seclabel'] = 'ERROR'
803 elif security.active_policy in ['DEFAULT']:
804 d['seclabel'] = 'DEFAULT'
805 else:
806 d['seclabel'] = 'INACTIVE'
807 output.append((format % d, d['seclabel']))
809 #sort by labels
810 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
811 for line, label in output:
812 print line
815 def xm_vcpu_list(args):
817 if args:
818 dominfo = map(server.xend.domain.getVCPUInfo, args)
819 else:
820 doms = server.xend.domains(False)
821 dominfo = map(server.xend.domain.getVCPUInfo, doms)
823 print '%-32s %3s %5s %5s %5s %9s %s' % \
824 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
826 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
827 ' %(cpu_time)8.1f %(cpumap)s'
829 for dom in dominfo:
830 def get_info(n):
831 return sxp.child_value(dom, n)
833 #
834 # convert a list of integers into a list of pairs indicating
835 # continuous sequences in the list:
836 #
837 # [0,1,2,3] -> [(0,3)]
838 # [1,2,4,5] -> [(1,2),(4,5)]
839 # [0] -> [(0,0)]
840 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
841 #
842 def list_to_rangepairs(cmap):
843 cmap.sort()
844 pairs = []
845 x = y = 0
846 for i in range(0,len(cmap)):
847 try:
848 if ((cmap[y+1] - cmap[i]) > 1):
849 pairs.append((cmap[x],cmap[y]))
850 x = y = i+1
851 else:
852 y = y + 1
853 # if we go off the end, then just add x to y
854 except IndexError:
855 pairs.append((cmap[x],cmap[y]))
857 return pairs
859 #
860 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
861 #
862 def format_pairs(pairs):
863 if not pairs:
864 return "no cpus"
865 out = ""
866 for f,s in pairs:
867 if (f==s):
868 out += '%d'%f
869 else:
870 out += '%d-%d'%(f,s)
871 out += ','
872 # trim trailing ','
873 return out[:-1]
875 def format_cpumap(cpumap):
876 cpumap = map(lambda x: int(x), cpumap)
877 cpumap.sort()
879 for x in server.xend.node.info()[1:]:
880 if len(x) > 1 and x[0] == 'nr_cpus':
881 nr_cpus = int(x[1])
882 # normalize cpumap by modulus nr_cpus, and drop duplicates
883 cpumap = dict.fromkeys(
884 map(lambda x: x % nr_cpus, cpumap)).keys()
885 if len(cpumap) == nr_cpus:
886 return "any cpu"
887 break
889 return format_pairs(list_to_rangepairs(cpumap))
891 name = get_info('name')
892 domid = int(get_info('domid'))
894 for vcpu in sxp.children(dom, 'vcpu'):
895 def vinfo(n, t):
896 return t(sxp.child_value(vcpu, n))
898 number = vinfo('number', int)
899 cpu = vinfo('cpu', int)
900 cpumap = format_cpumap(vinfo('cpumap', list))
901 online = vinfo('online', int)
902 cpu_time = vinfo('cpu_time', float)
903 running = vinfo('running', int)
904 blocked = vinfo('blocked', int)
906 if online:
907 c = str(cpu)
908 if running:
909 s = 'r'
910 else:
911 s = '-'
912 if blocked:
913 s += 'b'
914 else:
915 s += '-'
916 s += '-'
917 else:
918 c = "-"
919 s = "--p"
921 print format % locals()
923 def xm_start(args):
924 arg_check(args, "start", 1, 2)
926 try:
927 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
928 except getopt.GetoptError, opterr:
929 err(opterr)
930 usage('start')
932 paused = False
933 for (k, v) in options:
934 if k in ['-p', '--paused']:
935 paused = True
937 if len(params) != 1:
938 err("Wrong number of parameters")
939 usage('start')
941 dom = params[0]
942 if serverType == SERVER_XEN_API:
943 server.xenapi.VM.start(get_single_vm(dom), paused)
944 else:
945 server.xend.domain.start(dom, paused)
947 def xm_delete(args):
948 arg_check(args, "delete", 1)
949 dom = args[0]
950 if serverType == SERVER_XEN_API:
951 server.xenapi.VM.destroy(get_single_vm(dom))
952 else:
953 server.xend.domain.delete(dom)
955 def xm_suspend(args):
956 arg_check(args, "suspend", 1)
957 dom = args[0]
958 if serverType == SERVER_XEN_API:
959 server.xenapi.VM.suspend(get_single_vm(dom))
960 else:
961 server.xend.domain.suspend(dom)
963 def xm_resume(args):
964 arg_check(args, "resume", 1, 2)
966 try:
967 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
968 except getopt.GetoptError, opterr:
969 err(opterr)
970 usage('resume')
972 paused = False
973 for (k, v) in options:
974 if k in ['-p', '--paused']:
975 paused = True
977 if len(params) != 1:
978 err("Wrong number of parameters")
979 usage('resume')
981 dom = params[0]
982 if serverType == SERVER_XEN_API:
983 server.xenapi.VM.resume(get_single_vm(dom), paused)
984 else:
985 server.xend.domain.resume(dom, paused)
987 def xm_reboot(args):
988 arg_check(args, "reboot", 1, 3)
989 from xen.xm import shutdown
990 shutdown.main(["shutdown", "-R"] + args)
992 def xm_shutdown(args):
993 arg_check(args, "shutdown", 1, 4)
994 from xen.xm import shutdown
995 shutdown.main(["shutdown"] + args)
997 def xm_pause(args):
998 arg_check(args, "pause", 1)
999 dom = args[0]
1001 if serverType == SERVER_XEN_API:
1002 server.xenapi.VM.pause(get_single_vm(dom))
1003 else:
1004 server.xend.domain.pause(dom)
1006 def xm_unpause(args):
1007 arg_check(args, "unpause", 1)
1008 dom = args[0]
1010 if serverType == SERVER_XEN_API:
1011 server.xenapi.VM.unpause(get_single_vm(dom))
1012 else:
1013 server.xend.domain.unpause(dom)
1015 def xm_dump_core(args):
1016 live = False
1017 crash = False
1018 try:
1019 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1020 for (k, v) in options:
1021 if k in ('-L', '--live'):
1022 live = True
1023 if k in ('-C', '--crash'):
1024 crash = True
1026 if len(params) not in (1, 2):
1027 raise OptionError("Expects 1 or 2 argument(s)")
1028 except getopt.GetoptError, e:
1029 raise OptionError(str(e))
1031 dom = params[0]
1032 if len(params) == 2:
1033 filename = os.path.abspath(params[1])
1034 else:
1035 filename = None
1037 if not live:
1038 server.xend.domain.pause(dom)
1040 try:
1041 print "Dumping core of domain: %s ..." % str(dom)
1042 server.xend.domain.dump(dom, filename, live, crash)
1043 finally:
1044 if not live:
1045 server.xend.domain.unpause(dom)
1047 if crash:
1048 print "Destroying domain: %s ..." % str(dom)
1049 server.xend.domain.destroy(dom)
1051 def xm_rename(args):
1052 arg_check(args, "rename", 2)
1054 if serverType == SERVER_XEN_API:
1055 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1056 else:
1057 server.xend.domain.setName(args[0], args[1])
1059 def xm_importcommand(command, args):
1060 cmd = __import__(command, globals(), locals(), 'xen.xm')
1061 cmd.main([command] + args)
1064 #############################################################
1066 def xm_vcpu_pin(args):
1067 arg_check(args, "vcpu-pin", 3)
1069 def cpu_make_map(cpulist):
1070 cpus = []
1071 for c in cpulist.split(','):
1072 if c.find('-') != -1:
1073 (x,y) = c.split('-')
1074 for i in range(int(x),int(y)+1):
1075 cpus.append(int(i))
1076 else:
1077 # remove this element from the list
1078 if c[0] == '^':
1079 cpus = [x for x in cpus if x != int(c[1:])]
1080 else:
1081 cpus.append(int(c))
1082 cpus.sort()
1083 return cpus
1085 dom = args[0]
1086 vcpu = args[1]
1087 if args[2] == 'all':
1088 cpumap = cpu_make_map('0-63')
1089 else:
1090 cpumap = cpu_make_map(args[2])
1092 server.xend.domain.pincpu(dom, vcpu, cpumap)
1094 def xm_mem_max(args):
1095 arg_check(args, "mem-max", 2)
1097 dom = args[0]
1098 mem = int_unit(args[1], 'm')
1100 server.xend.domain.maxmem_set(dom, mem)
1102 def xm_mem_set(args):
1103 arg_check(args, "mem-set", 2)
1105 dom = args[0]
1106 mem_target = int_unit(args[1], 'm')
1108 server.xend.domain.setMemoryTarget(dom, mem_target)
1110 def xm_vcpu_set(args):
1111 arg_check(args, "vcpu-set", 2)
1113 server.xend.domain.setVCpuCount(args[0], int(args[1]))
1116 def xm_destroy(args):
1117 arg_check(args, "destroy", 1)
1119 dom = args[0]
1120 if serverType == SERVER_XEN_API:
1121 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1122 else:
1123 server.xend.domain.destroy(dom)
1126 def xm_domid(args):
1127 arg_check(args, "domid", 1)
1129 name = args[0]
1131 dom = server.xend.domain(name)
1132 print sxp.child_value(dom, 'domid')
1134 def xm_domname(args):
1135 arg_check(args, "domname", 1)
1137 name = args[0]
1139 dom = server.xend.domain(name)
1140 print sxp.child_value(dom, 'name')
1142 def xm_sched_sedf(args):
1143 def ns_to_ms(val):
1144 return float(val) * 0.000001
1146 def ms_to_ns(val):
1147 return (float(val) / 0.000001)
1149 def print_sedf(info):
1150 info['period'] = ns_to_ms(info['period'])
1151 info['slice'] = ns_to_ms(info['slice'])
1152 info['latency'] = ns_to_ms(info['latency'])
1153 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1154 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1156 check_sched_type('sedf')
1158 # we want to just display current info if no parameters are passed
1159 if len(args) == 0:
1160 domid = None
1161 else:
1162 # we expect at least a domain id (name or number)
1163 # and at most a domid up to 5 options with values
1164 arg_check(args, "sched-sedf", 1, 11)
1165 domid = args[0]
1166 # drop domid from args since get_opt doesn't recognize it
1167 args = args[1:]
1169 opts = {}
1170 try:
1171 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1172 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1173 except getopt.GetoptError, opterr:
1174 err(opterr)
1175 usage('sched-sedf')
1177 # convert to nanoseconds if needed
1178 for (k, v) in options:
1179 if k in ['-p', '--period']:
1180 opts['period'] = ms_to_ns(v)
1181 elif k in ['-s', '--slice']:
1182 opts['slice'] = ms_to_ns(v)
1183 elif k in ['-l', '--latency']:
1184 opts['latency'] = ms_to_ns(v)
1185 elif k in ['-e', '--extratime']:
1186 opts['extratime'] = v
1187 elif k in ['-w', '--weight']:
1188 opts['weight'] = v
1190 doms = filter(lambda x : domid_match(domid, x),
1191 [parse_doms_info(dom)
1192 for dom in getDomains(None, 'running')])
1193 if domid is not None and doms == []:
1194 err("Domain '%s' does not exist." % domid)
1195 usage('sched-sedf')
1197 # print header if we aren't setting any parameters
1198 if len(opts.keys()) == 0:
1199 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1200 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1201 'Extra','Weight')
1203 for d in doms:
1204 # fetch current values so as not to clobber them
1205 try:
1206 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1207 except xmlrpclib.Fault:
1208 # domain does not support sched-sedf?
1209 sedf_raw = {}
1211 sedf_info = parse_sedf_info(sedf_raw)
1212 sedf_info['name'] = d['name']
1213 # update values in case of call to set
1214 if len(opts.keys()) > 0:
1215 for k in opts.keys():
1216 sedf_info[k]=opts[k]
1218 # send the update, converting user input
1219 v = map(int, [sedf_info['period'], sedf_info['slice'],
1220 sedf_info['latency'],sedf_info['extratime'],
1221 sedf_info['weight']])
1222 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1223 if int(rv) != 0:
1224 err("Failed to set sedf parameters (rv=%d)."%(rv))
1226 # not setting values, display info
1227 else:
1228 print_sedf(sedf_info)
1230 def xm_sched_credit(args):
1231 """Get/Set options for Credit Scheduler."""
1233 check_sched_type('credit')
1235 try:
1236 opts, params = getopt.getopt(args, "d:w:c:",
1237 ["domain=", "weight=", "cap="])
1238 except getopt.GetoptError, opterr:
1239 err(opterr)
1240 usage('sched-credit')
1242 domid = None
1243 weight = None
1244 cap = None
1246 for o, a in opts:
1247 if o == "-d":
1248 domid = a
1249 elif o == "-w":
1250 weight = int(a)
1251 elif o == "-c":
1252 cap = int(a);
1254 doms = filter(lambda x : domid_match(domid, x),
1255 [parse_doms_info(dom)
1256 for dom in getDomains(None, 'running')])
1258 if weight is None and cap is None:
1259 if domid is not None and doms == []:
1260 err("Domain '%s' does not exist." % domid)
1261 usage('sched-credit')
1262 # print header if we aren't setting any parameters
1263 print '%-33s %-2s %-6s %-4s' % ('Name','ID','Weight','Cap')
1265 for d in doms:
1266 try:
1267 info = server.xend.domain.sched_credit_get(d['domid'])
1268 except xmlrpclib.Fault:
1269 # domain does not support sched-credit?
1270 info = {'weight': -1, 'cap': -1}
1272 info['name'] = d['name']
1273 info['domid'] = int(d['domid'])
1274 print( ("%(name)-32s %(domid)3d %(weight)6d %(cap)4d") % info)
1275 else:
1276 if domid is None:
1277 # place holder for system-wide scheduler parameters
1278 err("No domain given.")
1279 usage('sched-credit')
1281 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1282 if result != 0:
1283 err(str(result))
1285 def xm_info(args):
1286 arg_check(args, "info", 0)
1288 info = server.xend.node.info()
1290 for x in info[1:]:
1291 if len(x) < 2:
1292 print "%-23s: (none)" % x[0]
1293 else:
1294 print "%-23s:" % x[0], x[1]
1296 def xm_console(args):
1297 arg_check(args, "console", 1, 2)
1299 quiet = False;
1301 try:
1302 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1303 except getopt.GetoptError, opterr:
1304 err(opterr)
1305 usage('console')
1307 for (k, v) in options:
1308 if k in ['-q', '--quiet']:
1309 quiet = True
1310 else:
1311 assert False
1313 if len(params) != 1:
1314 err('No domain given')
1315 usage('console')
1317 dom = params[0]
1319 try:
1320 info = server.xend.domain(dom)
1321 except:
1322 if quiet:
1323 sys.exit(1)
1324 else:
1325 raise
1326 domid = int(sxp.child_value(info, 'domid', '-1'))
1327 if domid == -1:
1328 if quiet:
1329 sys.exit(1)
1330 else:
1331 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1333 console.execConsole(domid)
1336 def xm_uptime(args):
1337 short_mode = 0
1339 try:
1340 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1341 except getopt.GetoptError, opterr:
1342 err(opterr)
1343 usage('uptime')
1345 for (k, v) in options:
1346 if k in ['-s', '--short']:
1347 short_mode = 1
1349 doms = getDomains(params, 'running')
1351 if short_mode == 0:
1352 print 'Name ID Uptime'
1354 for dom in doms:
1355 d = parse_doms_info(dom)
1356 if int(d['domid']) > 0:
1357 uptime = int(round(d['up_time']))
1358 else:
1359 f=open('/proc/uptime', 'r')
1360 upfile = f.read()
1361 uptime = int(round(float(upfile.split(' ')[0])))
1362 f.close()
1364 days = int(uptime / 86400)
1365 uptime -= (days * 86400)
1366 hours = int(uptime / 3600)
1367 uptime -= (hours * 3600)
1368 minutes = int(uptime / 60)
1369 uptime -= (minutes * 60)
1370 seconds = uptime
1372 upstring = ""
1373 if days > 0:
1374 upstring += str(days) + " day"
1375 if days > 1:
1376 upstring += "s"
1377 upstring += ", "
1378 upstring += '%(hours)2d:%(minutes)02d' % vars()
1380 if short_mode:
1381 now = datetime.datetime.now()
1382 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1383 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1384 else:
1385 upstring += ':%(seconds)02d' % vars()
1386 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1388 print upstring
1390 def xm_sysrq(args):
1391 arg_check(args, "sysrq", 2)
1392 dom = args[0]
1393 req = args[1]
1394 server.xend.domain.send_sysrq(dom, req)
1396 def xm_trigger(args):
1397 vcpu = 0
1399 arg_check(args, "trigger", 2, 3)
1400 dom = args[0]
1401 trigger = args[1]
1402 if len(args) == 3:
1403 vcpu = int(args[2])
1405 server.xend.domain.send_trigger(dom, trigger, vcpu)
1407 def xm_debug_keys(args):
1408 arg_check(args, "debug-keys", 1)
1409 server.xend.node.send_debug_keys(str(args[0]))
1411 def xm_top(args):
1412 arg_check(args, "top", 0)
1414 os.execvp('xentop', ['xentop'])
1416 def xm_dmesg(args):
1417 arg_check(args, "dmesg", 0, 1)
1419 try:
1420 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1421 except getopt.GetoptError, opterr:
1422 err(opterr)
1423 usage('dmesg')
1425 use_clear = 0
1426 for (k, v) in options:
1427 if k in ['-c', '--clear']:
1428 use_clear = 1
1430 if len(params) :
1431 err("No parameter required")
1432 usage('dmesg')
1434 if not use_clear:
1435 print server.xend.node.dmesg.info()
1436 else:
1437 server.xend.node.dmesg.clear()
1439 def xm_log(args):
1440 arg_check(args, "log", 0)
1442 print server.xend.node.log()
1444 def xm_serve(args):
1445 arg_check(args, "serve", 0)
1447 from fcntl import fcntl, F_SETFL
1449 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1450 s.connect(XendClient.XML_RPC_SOCKET)
1451 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1453 while True:
1454 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1455 if s in iwtd:
1456 data = s.recv(4096)
1457 if len(data) > 0:
1458 sys.stdout.write(data)
1459 sys.stdout.flush()
1460 else:
1461 break
1462 if sys.stdin in iwtd:
1463 data = sys.stdin.read(4096)
1464 if len(data) > 0:
1465 s.sendall(data)
1466 else:
1467 break
1468 s.close()
1470 def parse_dev_info(info):
1471 def get_info(n, t, d):
1472 i = 0
1473 while i < len(info):
1474 if (info[i][0] == n):
1475 return t(info[i][1])
1476 i = i + 1
1477 return t(d)
1478 return {
1479 #common
1480 'backend-id' : get_info('backend-id', int, -1),
1481 'handle' : get_info('handle', int, 0),
1482 'state' : get_info('state', int, -1),
1483 'be-path' : get_info('backend', str, '??'),
1484 'event-ch' : get_info('event-channel',int, -1),
1485 #network specific
1486 'virtual-device' : get_info('virtual-device', str, '??'),
1487 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1488 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1489 'mac' : get_info('mac', str, '??'),
1490 #block-device specific
1491 'ring-ref' : get_info('ring-ref', int, -1),
1494 def arg_check_for_resource_list(args, name):
1495 use_long = 0
1496 try:
1497 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1498 except getopt.GetoptError, opterr:
1499 err(opterr)
1500 sys.exit(1)
1502 for (k, v) in options:
1503 if k in ['-l', '--long']:
1504 use_long = 1
1506 if len(params) == 0:
1507 print 'No domain parameter given'
1508 usage(name)
1509 if len(params) > 1:
1510 print 'No multiple domain parameters allowed'
1511 usage(name)
1513 return (use_long, params)
1515 def xm_network_list(args):
1516 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1518 dom = params[0]
1519 if use_long:
1520 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1521 map(PrettyPrint.prettyprint, devs)
1522 else:
1523 hdr = 0
1524 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
1525 if hdr == 0:
1526 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1527 hdr = 1
1528 ni = parse_dev_info(x[1])
1529 ni['idx'] = int(x[0])
1530 print ("%(idx)-3d "
1531 "%(backend-id)-3d"
1532 "%(mac)-17s "
1533 "%(handle)-3d "
1534 "%(state)-3d "
1535 "%(event-ch)-3d "
1536 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1537 "%(be-path)-30s "
1538 % ni)
1540 def xm_block_list(args):
1541 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1543 dom = params[0]
1544 if use_long:
1545 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1546 map(PrettyPrint.prettyprint, devs)
1547 else:
1548 hdr = 0
1549 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
1550 if hdr == 0:
1551 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1552 hdr = 1
1553 ni = parse_dev_info(x[1])
1554 ni['idx'] = int(x[0])
1555 print ("%(idx)-3d "
1556 "%(backend-id)-3d "
1557 "%(handle)-3d "
1558 "%(state)-3d "
1559 "%(event-ch)-3d "
1560 "%(ring-ref)-5d "
1561 "%(be-path)-30s "
1562 % ni)
1564 def xm_vtpm_list(args):
1565 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1567 dom = params[0]
1568 if use_long:
1569 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1570 map(PrettyPrint.prettyprint, devs)
1571 else:
1572 hdr = 0
1573 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1574 if hdr == 0:
1575 print 'Idx BE handle state evt-ch ring-ref BE-path'
1576 hdr = 1
1577 ni = parse_dev_info(x[1])
1578 ni['idx'] = int(x[0])
1579 print ("%(idx)-3d "
1580 "%(backend-id)-3d "
1581 "%(handle)-3d "
1582 "%(state)-3d "
1583 "%(event-ch)-3d "
1584 "%(ring-ref)-5d "
1585 "%(be-path)-30s "
1586 % ni)
1589 def parse_block_configuration(args):
1590 dom = args[0]
1592 if args[1].startswith('tap:'):
1593 cls = 'tap'
1594 else:
1595 cls = 'vbd'
1597 vbd = [cls,
1598 ['uname', args[1]],
1599 ['dev', args[2]],
1600 ['mode', args[3]]]
1601 if len(args) == 5:
1602 vbd.append(['backend', args[4]])
1604 # verify that policy permits attaching this resource
1605 if security.on():
1606 dominfo = server.xend.domain(dom)
1607 label = security.get_security_printlabel(dominfo)
1608 else:
1609 label = None
1610 security.res_security_check(args[1], label)
1612 return (dom, vbd)
1615 def xm_block_attach(args):
1616 arg_check(args, 'block-attach', 4, 5)
1618 (dom, vbd) = parse_block_configuration(args)
1619 server.xend.domain.device_create(dom, vbd)
1622 def xm_block_configure(args):
1623 arg_check(args, 'block-configure', 4, 5)
1625 (dom, vbd) = parse_block_configuration(args)
1626 server.xend.domain.device_configure(dom, vbd)
1629 def xm_network_attach(args):
1630 arg_check(args, 'network-attach', 1, 10)
1632 dom = args[0]
1633 vif = ['vif']
1634 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
1635 'backend', 'vifname', 'rate', 'model']
1637 for a in args[1:]:
1638 vif_param = a.split("=")
1639 if len(vif_param) != 2 or vif_param[1] == '' or \
1640 vif_param[0] not in vif_params:
1641 err("Invalid argument: %s" % a)
1642 usage('network-attach')
1643 vif.append(vif_param)
1645 server.xend.domain.device_create(dom, vif)
1648 def detach(args, command, deviceClass):
1649 arg_check(args, command, 2, 3)
1651 dom = args[0]
1652 dev = args[1]
1653 try:
1654 force = args[2]
1655 if (force != "--force") and (force != "-f"):
1656 print "Ignoring option %s"%(force)
1657 force = None
1658 except IndexError:
1659 force = None
1661 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
1664 def xm_block_detach(args):
1665 try:
1666 detach(args, 'block-detach', 'vbd')
1667 return
1668 except:
1669 pass
1670 detach(args, 'block-detach', 'tap')
1673 def xm_network_detach(args):
1674 detach(args, 'network-detach', 'vif')
1677 def xm_vnet_list(args):
1678 try:
1679 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1680 except getopt.GetoptError, opterr:
1681 err(opterr)
1682 usage('vnet-list')
1684 use_long = 0
1685 for (k, v) in options:
1686 if k in ['-l', '--long']:
1687 use_long = 1
1689 if params:
1690 use_long = 1
1691 vnets = params
1692 else:
1693 vnets = server.xend_vnets()
1695 for vnet in vnets:
1696 try:
1697 if use_long:
1698 info = server.xend_vnet(vnet)
1699 PrettyPrint.prettyprint(info)
1700 else:
1701 print vnet
1702 except Exception, ex:
1703 print vnet, ex
1705 def xm_vnet_create(args):
1706 arg_check(args, "vnet-create", 1)
1707 conf = args[0]
1708 if not os.access(conf, os.R_OK):
1709 print "File not found: %s" % conf
1710 sys.exit(1)
1712 server.xend_vnet_create(conf)
1714 def xm_vnet_delete(args):
1715 arg_check(args, "vnet-delete", 1)
1716 vnet = args[0]
1717 server.xend_vnet_delete(vnet)
1719 commands = {
1720 "shell": xm_shell,
1721 # console commands
1722 "console": xm_console,
1723 # xenstat commands
1724 "top": xm_top,
1725 # domain commands
1726 "delete": xm_delete,
1727 "destroy": xm_destroy,
1728 "domid": xm_domid,
1729 "domname": xm_domname,
1730 "dump-core": xm_dump_core,
1731 "reboot": xm_reboot,
1732 "rename": xm_rename,
1733 "restore": xm_restore,
1734 "resume": xm_resume,
1735 "save": xm_save,
1736 "shutdown": xm_shutdown,
1737 "start": xm_start,
1738 "sysrq": xm_sysrq,
1739 "trigger": xm_trigger,
1740 "uptime": xm_uptime,
1741 "suspend": xm_suspend,
1742 "list": xm_list,
1743 # memory commands
1744 "mem-max": xm_mem_max,
1745 "mem-set": xm_mem_set,
1746 # cpu commands
1747 "vcpu-pin": xm_vcpu_pin,
1748 "vcpu-list": xm_vcpu_list,
1749 "vcpu-set": xm_vcpu_set,
1750 # special
1751 "pause": xm_pause,
1752 "unpause": xm_unpause,
1753 # host commands
1754 "debug-keys": xm_debug_keys,
1755 "dmesg": xm_dmesg,
1756 "info": xm_info,
1757 "log": xm_log,
1758 "serve": xm_serve,
1759 # scheduler
1760 "sched-sedf": xm_sched_sedf,
1761 "sched-credit": xm_sched_credit,
1762 # block
1763 "block-attach": xm_block_attach,
1764 "block-detach": xm_block_detach,
1765 "block-list": xm_block_list,
1766 "block-configure": xm_block_configure,
1767 # network
1768 "network-attach": xm_network_attach,
1769 "network-detach": xm_network_detach,
1770 "network-list": xm_network_list,
1771 # vnet
1772 "vnet-list": xm_vnet_list,
1773 "vnet-create": xm_vnet_create,
1774 "vnet-delete": xm_vnet_delete,
1775 # vtpm
1776 "vtpm-list": xm_vtpm_list,
1779 ## The commands supported by a separate argument parser in xend.xm.
1780 IMPORTED_COMMANDS = [
1781 'create',
1782 'new',
1783 'migrate',
1784 'labels',
1785 'cfgbootpolicy',
1786 'makepolicy',
1787 'loadpolicy',
1788 'dumppolicy',
1789 'addlabel',
1790 'rmlabel',
1791 'getlabel',
1792 'dry-run',
1793 'resources',
1796 for c in IMPORTED_COMMANDS:
1797 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
1799 aliases = {
1800 "balloon": "mem-set",
1801 "set-vcpus": "vcpu-set",
1802 "vif-list": "network-list",
1803 "vbd-create": "block-attach",
1804 "vbd-destroy": "block-detach",
1805 "vbd-list": "block-list",
1809 def xm_lookup_cmd(cmd):
1810 if commands.has_key(cmd):
1811 return commands[cmd]
1812 elif aliases.has_key(cmd):
1813 deprecated(cmd,aliases[cmd])
1814 return commands[aliases[cmd]]
1815 elif cmd == 'help':
1816 longHelp()
1817 sys.exit(0)
1818 else:
1819 # simulate getopt's prefix matching behaviour
1820 if len(cmd) > 1:
1821 same_prefix_cmds = [commands[c] for c in commands.keys() \
1822 if c[:len(cmd)] == cmd]
1823 # only execute if there is only 1 match
1824 if len(same_prefix_cmds) == 1:
1825 return same_prefix_cmds[0]
1826 return None
1828 def deprecated(old,new):
1829 print >>sys.stderr, (
1830 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1832 def main(argv=sys.argv):
1833 if len(argv) < 2:
1834 usage()
1836 # intercept --help(-h) and output our own help
1837 for help in ['--help', '-h']:
1838 if help in argv[1:]:
1839 if help == argv[1]:
1840 longHelp()
1841 sys.exit(0)
1842 else:
1843 usage(argv[1])
1845 cmd_name = argv[1]
1846 cmd = xm_lookup_cmd(cmd_name)
1847 if cmd:
1848 # strip off prog name and subcmd
1849 args = argv[2:]
1850 _, rc = _run_cmd(cmd, cmd_name, args)
1851 sys.exit(rc)
1852 else:
1853 err('Subcommand %s not found!' % cmd_name)
1854 usage()
1856 def _run_cmd(cmd, cmd_name, args):
1857 global server
1859 try:
1860 if server is None:
1861 if serverType == SERVER_XEN_API:
1862 server = XenAPI.Session(serverURI)
1863 username, password = parseAuthentication()
1864 server.login_with_password(username, password)
1865 def logout():
1866 try:
1867 server.xenapi.session.logout()
1868 except:
1869 pass
1870 atexit.register(logout)
1871 else:
1872 server = ServerProxy(serverURI)
1874 return True, cmd(args)
1875 except socket.error, ex:
1876 if os.geteuid() != 0:
1877 err("Most commands need root access. Please try again as root.")
1878 else:
1879 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
1880 except KeyboardInterrupt:
1881 print "Interrupted."
1882 return True, ''
1883 except IOError, ex:
1884 if os.geteuid() != 0:
1885 err("Most commands need root access. Please try again as root.")
1886 else:
1887 err("Unable to connect to xend: %s." % ex[1])
1888 except SystemExit, code:
1889 return code == 0, code
1890 except XenAPI.Failure, exn:
1891 for line in [''] + wrap(str(exn), 80) + ['']:
1892 print >>sys.stderr, line
1893 except xmlrpclib.Fault, ex:
1894 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
1895 err("Domain '%s' does not exist." % ex.faultString)
1896 else:
1897 err(ex.faultString)
1898 _usage(cmd_name)
1899 except xmlrpclib.ProtocolError, ex:
1900 if ex.errcode == -1:
1901 print >>sys.stderr, (
1902 "Xend has probably crashed! Invalid or missing HTTP "
1903 "status code.")
1904 else:
1905 print >>sys.stderr, (
1906 "Xend has probably crashed! ProtocolError(%d, %s)." %
1907 (ex.errcode, ex.errmsg))
1908 except (ValueError, OverflowError):
1909 err("Invalid argument.")
1910 _usage(cmd_name)
1911 except OptionError, e:
1912 err(str(e))
1913 _usage(cmd_name)
1914 print e.usage
1915 except security.ACMError, e:
1916 err(str(e))
1917 except:
1918 print "Unexpected error:", sys.exc_info()[0]
1919 print
1920 print "Please report to xen-devel@lists.xensource.com"
1921 raise
1923 return False, 1
1925 if __name__ == "__main__":
1926 main()