direct-io.hg

view tools/python/xen/xm/main.py @ 14388:b39c0a79d4d5

Added the clear flag to host.dmesg, and added host.get_log. Use these to
implement xm dmesg and xm log using the Xen-API.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Wed Mar 14 23:16:59 2007 +0000 (2007-03-14)
parents 0c354aa0bb4a
children 30a83a0839bd
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 if serverType == SERVER_XEN_API:
754 current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host())
755 else:
756 current = 'unknown'
757 for x in server.xend.node.info()[1:]:
758 if len(x) > 1 and x[0] == 'xen_scheduler':
759 current = x[1]
760 break
761 if sched != current:
762 err("Xen is running with the %s scheduler" % current)
763 sys.exit(1)
765 def parse_sedf_info(info):
766 def get_info(n, t, d):
767 return t(sxp.child_value(info, n, d))
769 return {
770 'domid' : get_info('domid', int, -1),
771 'period' : get_info('period', int, -1),
772 'slice' : get_info('slice', int, -1),
773 'latency' : get_info('latency', int, -1),
774 'extratime': get_info('extratime', int, -1),
775 'weight' : get_info('weight', int, -1),
776 }
778 def domid_match(domid, info):
779 return domid is None or domid == info['name'] or \
780 domid == str(info['domid'])
782 def xm_brief_list(doms):
783 print '%-40s %3s %5s %5s %10s %9s' % \
784 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
786 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
787 "%(cpu_time)8.1f"
789 for dom in doms:
790 d = parse_doms_info(dom)
791 print format % d
793 def xm_label_list(doms):
794 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
795 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
797 output = []
798 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
799 '%(cpu_time)8.1f %(seclabel)9s'
801 for dom in doms:
802 d = parse_doms_info(dom)
803 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
804 if not d['seclabel']:
805 d['seclabel'] = 'ERROR'
806 elif security.active_policy in ['DEFAULT']:
807 d['seclabel'] = 'DEFAULT'
808 else:
809 d['seclabel'] = 'INACTIVE'
810 output.append((format % d, d['seclabel']))
812 #sort by labels
813 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
814 for line, label in output:
815 print line
818 def xm_vcpu_list(args):
820 if args:
821 dominfo = map(server.xend.domain.getVCPUInfo, args)
822 else:
823 doms = server.xend.domains(False)
824 dominfo = map(server.xend.domain.getVCPUInfo, doms)
826 print '%-32s %3s %5s %5s %5s %9s %s' % \
827 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
829 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
830 ' %(cpu_time)8.1f %(cpumap)s'
832 for dom in dominfo:
833 def get_info(n):
834 return sxp.child_value(dom, n)
836 #
837 # convert a list of integers into a list of pairs indicating
838 # continuous sequences in the list:
839 #
840 # [0,1,2,3] -> [(0,3)]
841 # [1,2,4,5] -> [(1,2),(4,5)]
842 # [0] -> [(0,0)]
843 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
844 #
845 def list_to_rangepairs(cmap):
846 cmap.sort()
847 pairs = []
848 x = y = 0
849 for i in range(0,len(cmap)):
850 try:
851 if ((cmap[y+1] - cmap[i]) > 1):
852 pairs.append((cmap[x],cmap[y]))
853 x = y = i+1
854 else:
855 y = y + 1
856 # if we go off the end, then just add x to y
857 except IndexError:
858 pairs.append((cmap[x],cmap[y]))
860 return pairs
862 #
863 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
864 #
865 def format_pairs(pairs):
866 if not pairs:
867 return "no cpus"
868 out = ""
869 for f,s in pairs:
870 if (f==s):
871 out += '%d'%f
872 else:
873 out += '%d-%d'%(f,s)
874 out += ','
875 # trim trailing ','
876 return out[:-1]
878 def format_cpumap(cpumap):
879 cpumap = map(lambda x: int(x), cpumap)
880 cpumap.sort()
882 for x in server.xend.node.info()[1:]:
883 if len(x) > 1 and x[0] == 'nr_cpus':
884 nr_cpus = int(x[1])
885 # normalize cpumap by modulus nr_cpus, and drop duplicates
886 cpumap = dict.fromkeys(
887 map(lambda x: x % nr_cpus, cpumap)).keys()
888 if len(cpumap) == nr_cpus:
889 return "any cpu"
890 break
892 return format_pairs(list_to_rangepairs(cpumap))
894 name = get_info('name')
895 domid = int(get_info('domid'))
897 for vcpu in sxp.children(dom, 'vcpu'):
898 def vinfo(n, t):
899 return t(sxp.child_value(vcpu, n))
901 number = vinfo('number', int)
902 cpu = vinfo('cpu', int)
903 cpumap = format_cpumap(vinfo('cpumap', list))
904 online = vinfo('online', int)
905 cpu_time = vinfo('cpu_time', float)
906 running = vinfo('running', int)
907 blocked = vinfo('blocked', int)
909 if online:
910 c = str(cpu)
911 if running:
912 s = 'r'
913 else:
914 s = '-'
915 if blocked:
916 s += 'b'
917 else:
918 s += '-'
919 s += '-'
920 else:
921 c = "-"
922 s = "--p"
924 print format % locals()
926 def xm_start(args):
927 arg_check(args, "start", 1, 2)
929 try:
930 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
931 except getopt.GetoptError, opterr:
932 err(opterr)
933 usage('start')
935 paused = False
936 for (k, v) in options:
937 if k in ['-p', '--paused']:
938 paused = True
940 if len(params) != 1:
941 err("Wrong number of parameters")
942 usage('start')
944 dom = params[0]
945 if serverType == SERVER_XEN_API:
946 server.xenapi.VM.start(get_single_vm(dom), paused)
947 else:
948 server.xend.domain.start(dom, paused)
950 def xm_delete(args):
951 arg_check(args, "delete", 1)
952 dom = args[0]
953 if serverType == SERVER_XEN_API:
954 server.xenapi.VM.destroy(get_single_vm(dom))
955 else:
956 server.xend.domain.delete(dom)
958 def xm_suspend(args):
959 arg_check(args, "suspend", 1)
960 dom = args[0]
961 if serverType == SERVER_XEN_API:
962 server.xenapi.VM.suspend(get_single_vm(dom))
963 else:
964 server.xend.domain.suspend(dom)
966 def xm_resume(args):
967 arg_check(args, "resume", 1, 2)
969 try:
970 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
971 except getopt.GetoptError, opterr:
972 err(opterr)
973 usage('resume')
975 paused = False
976 for (k, v) in options:
977 if k in ['-p', '--paused']:
978 paused = True
980 if len(params) != 1:
981 err("Wrong number of parameters")
982 usage('resume')
984 dom = params[0]
985 if serverType == SERVER_XEN_API:
986 server.xenapi.VM.resume(get_single_vm(dom), paused)
987 else:
988 server.xend.domain.resume(dom, paused)
990 def xm_reboot(args):
991 arg_check(args, "reboot", 1, 3)
992 from xen.xm import shutdown
993 shutdown.main(["shutdown", "-R"] + args)
995 def xm_shutdown(args):
996 arg_check(args, "shutdown", 1, 4)
997 from xen.xm import shutdown
998 shutdown.main(["shutdown"] + args)
1000 def xm_pause(args):
1001 arg_check(args, "pause", 1)
1002 dom = args[0]
1004 if serverType == SERVER_XEN_API:
1005 server.xenapi.VM.pause(get_single_vm(dom))
1006 else:
1007 server.xend.domain.pause(dom)
1009 def xm_unpause(args):
1010 arg_check(args, "unpause", 1)
1011 dom = args[0]
1013 if serverType == SERVER_XEN_API:
1014 server.xenapi.VM.unpause(get_single_vm(dom))
1015 else:
1016 server.xend.domain.unpause(dom)
1018 def xm_dump_core(args):
1019 live = False
1020 crash = False
1021 try:
1022 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1023 for (k, v) in options:
1024 if k in ('-L', '--live'):
1025 live = True
1026 if k in ('-C', '--crash'):
1027 crash = True
1029 if len(params) not in (1, 2):
1030 raise OptionError("Expects 1 or 2 argument(s)")
1031 except getopt.GetoptError, e:
1032 raise OptionError(str(e))
1034 dom = params[0]
1035 if len(params) == 2:
1036 filename = os.path.abspath(params[1])
1037 else:
1038 filename = None
1040 if not live:
1041 server.xend.domain.pause(dom)
1043 try:
1044 print "Dumping core of domain: %s ..." % str(dom)
1045 server.xend.domain.dump(dom, filename, live, crash)
1046 finally:
1047 if not live:
1048 server.xend.domain.unpause(dom)
1050 if crash:
1051 print "Destroying domain: %s ..." % str(dom)
1052 server.xend.domain.destroy(dom)
1054 def xm_rename(args):
1055 arg_check(args, "rename", 2)
1057 if serverType == SERVER_XEN_API:
1058 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1059 else:
1060 server.xend.domain.setName(args[0], args[1])
1062 def xm_importcommand(command, args):
1063 cmd = __import__(command, globals(), locals(), 'xen.xm')
1064 cmd.main([command] + args)
1067 #############################################################
1069 def xm_vcpu_pin(args):
1070 arg_check(args, "vcpu-pin", 3)
1072 def cpu_make_map(cpulist):
1073 cpus = []
1074 for c in cpulist.split(','):
1075 if c.find('-') != -1:
1076 (x,y) = c.split('-')
1077 for i in range(int(x),int(y)+1):
1078 cpus.append(int(i))
1079 else:
1080 # remove this element from the list
1081 if c[0] == '^':
1082 cpus = [x for x in cpus if x != int(c[1:])]
1083 else:
1084 cpus.append(int(c))
1085 cpus.sort()
1086 return cpus
1088 dom = args[0]
1089 vcpu = args[1]
1090 if args[2] == 'all':
1091 cpumap = cpu_make_map('0-63')
1092 else:
1093 cpumap = cpu_make_map(args[2])
1095 server.xend.domain.pincpu(dom, vcpu, cpumap)
1097 def xm_mem_max(args):
1098 arg_check(args, "mem-max", 2)
1100 dom = args[0]
1102 if serverType == SERVER_XEN_API:
1103 mem = int_unit(args[1], 'k') * 1024
1104 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1105 else:
1106 mem = int_unit(args[1], 'm')
1107 server.xend.domain.maxmem_set(dom, mem)
1109 def xm_mem_set(args):
1110 arg_check(args, "mem-set", 2)
1112 dom = args[0]
1114 if serverType == SERVER_XEN_API:
1115 mem_target = int_unit(args[1], 'k') * 1024
1116 server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target)
1117 server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target)
1118 else:
1119 mem_target = int_unit(args[1], 'm')
1120 server.xend.domain.setMemoryTarget(dom, mem_target)
1122 def xm_vcpu_set(args):
1123 arg_check(args, "vcpu-set", 2)
1125 dom = args[0]
1126 vcpus = int(args[1])
1128 if serverType == SERVER_XEN_API:
1129 server.xenapi.VM.set_vcpus_live(get_single_vm(dom), vcpus)
1130 else:
1131 server.xend.domain.setVCpuCount(dom, vcpus)
1133 def xm_destroy(args):
1134 arg_check(args, "destroy", 1)
1136 dom = args[0]
1138 if serverType == SERVER_XEN_API:
1139 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1140 else:
1141 server.xend.domain.destroy(dom)
1144 def xm_domid(args):
1145 arg_check(args, "domid", 1)
1147 name = args[0]
1149 dom = server.xend.domain(name)
1150 print sxp.child_value(dom, 'domid')
1152 def xm_domname(args):
1153 arg_check(args, "domname", 1)
1155 name = args[0]
1157 if serverType == SERVER_XEN_API:
1158 print server.xenapi.VM.get_domid(get_single_vm(dom))
1159 else:
1160 dom = server.xend.domain(name)
1161 print sxp.child_value(dom, 'name')
1163 def xm_sched_sedf(args):
1164 def ns_to_ms(val):
1165 return float(val) * 0.000001
1167 def ms_to_ns(val):
1168 return (float(val) / 0.000001)
1170 def print_sedf(info):
1171 info['period'] = ns_to_ms(info['period'])
1172 info['slice'] = ns_to_ms(info['slice'])
1173 info['latency'] = ns_to_ms(info['latency'])
1174 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1175 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1177 check_sched_type('sedf')
1179 # we want to just display current info if no parameters are passed
1180 if len(args) == 0:
1181 domid = None
1182 else:
1183 # we expect at least a domain id (name or number)
1184 # and at most a domid up to 5 options with values
1185 arg_check(args, "sched-sedf", 1, 11)
1186 domid = args[0]
1187 # drop domid from args since get_opt doesn't recognize it
1188 args = args[1:]
1190 opts = {}
1191 try:
1192 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1193 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1194 except getopt.GetoptError, opterr:
1195 err(opterr)
1196 usage('sched-sedf')
1198 # convert to nanoseconds if needed
1199 for (k, v) in options:
1200 if k in ['-p', '--period']:
1201 opts['period'] = ms_to_ns(v)
1202 elif k in ['-s', '--slice']:
1203 opts['slice'] = ms_to_ns(v)
1204 elif k in ['-l', '--latency']:
1205 opts['latency'] = ms_to_ns(v)
1206 elif k in ['-e', '--extratime']:
1207 opts['extratime'] = v
1208 elif k in ['-w', '--weight']:
1209 opts['weight'] = v
1211 doms = filter(lambda x : domid_match(domid, x),
1212 [parse_doms_info(dom)
1213 for dom in getDomains(None, 'running')])
1214 if domid is not None and doms == []:
1215 err("Domain '%s' does not exist." % domid)
1216 usage('sched-sedf')
1218 # print header if we aren't setting any parameters
1219 if len(opts.keys()) == 0:
1220 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1221 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1222 'Extra','Weight')
1224 for d in doms:
1225 # fetch current values so as not to clobber them
1226 try:
1227 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1228 except xmlrpclib.Fault:
1229 # domain does not support sched-sedf?
1230 sedf_raw = {}
1232 sedf_info = parse_sedf_info(sedf_raw)
1233 sedf_info['name'] = d['name']
1234 # update values in case of call to set
1235 if len(opts.keys()) > 0:
1236 for k in opts.keys():
1237 sedf_info[k]=opts[k]
1239 # send the update, converting user input
1240 v = map(int, [sedf_info['period'], sedf_info['slice'],
1241 sedf_info['latency'],sedf_info['extratime'],
1242 sedf_info['weight']])
1243 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1244 if int(rv) != 0:
1245 err("Failed to set sedf parameters (rv=%d)."%(rv))
1247 # not setting values, display info
1248 else:
1249 print_sedf(sedf_info)
1251 def xm_sched_credit(args):
1252 """Get/Set options for Credit Scheduler."""
1254 check_sched_type('credit')
1256 try:
1257 opts, params = getopt.getopt(args, "d:w:c:",
1258 ["domain=", "weight=", "cap="])
1259 except getopt.GetoptError, opterr:
1260 err(opterr)
1261 usage('sched-credit')
1263 domid = None
1264 weight = None
1265 cap = None
1267 for o, a in opts:
1268 if o == "-d":
1269 domid = a
1270 elif o == "-w":
1271 weight = int(a)
1272 elif o == "-c":
1273 cap = int(a);
1275 doms = filter(lambda x : domid_match(domid, x),
1276 [parse_doms_info(dom)
1277 for dom in getDomains(None, 'running')])
1279 if weight is None and cap is None:
1280 if domid is not None and doms == []:
1281 err("Domain '%s' does not exist." % domid)
1282 usage('sched-credit')
1283 # print header if we aren't setting any parameters
1284 print '%-33s %-2s %-6s %-4s' % ('Name','ID','Weight','Cap')
1286 for d in doms:
1287 try:
1288 info = server.xend.domain.sched_credit_get(d['domid'])
1289 except xmlrpclib.Fault:
1290 # domain does not support sched-credit?
1291 info = {'weight': -1, 'cap': -1}
1293 info['name'] = d['name']
1294 info['domid'] = int(d['domid'])
1295 print( ("%(name)-32s %(domid)3d %(weight)6d %(cap)4d") % info)
1296 else:
1297 if domid is None:
1298 # place holder for system-wide scheduler parameters
1299 err("No domain given.")
1300 usage('sched-credit')
1302 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1303 if result != 0:
1304 err(str(result))
1306 def xm_info(args):
1307 arg_check(args, "info", 0)
1309 if serverType == SERVER_XEN_API:
1311 # Need to fake out old style xm info as people rely on parsing it
1313 host_record = server.xenapi.host.get_record(
1314 server.xenapi.session.get_this_host())
1316 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1318 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1320 info = {
1321 "host": host_record["name_label"],
1322 "release": host_record["software_version"]["release"],
1323 "version": host_record["software_version"]["version"],
1324 "machine": host_record["software_version"]["machine"],
1325 "nr_cpus": len(host_record["host_CPUs"]),
1326 "nr_nodes": host_record["cpu_configuration"]["nr_nodes"],
1327 "sockets_per_node": host_record["cpu_configuration"]["sockets_per_node"],
1328 "cores_per_socket": host_record["cpu_configuration"]["cores_per_socket"],
1329 "threads_per_core": host_record["cpu_configuration"]["threads_per_core"],
1330 "cpu_mhz": sum([int(host_cpu_record["speed"]) for host_cpu_record in host_cpu_records])
1331 / len(host_cpu_records),
1332 "hw_caps": host_cpu_records[0]["features"],
1333 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1334 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1335 "xen_major": host_record["software_version"]["xen_major"],
1336 "xen_minor": host_record["software_version"]["xen_minor"],
1337 "xen_extra": host_record["software_version"]["xen_extra"],
1338 "xen_caps": " ".join(host_record["capabilities"]),
1339 "xen_scheduler": host_record["sched_policy"],
1340 "xen_pagesize": host_record["other_config"]["xen_pagesize"],
1341 "platform_params": host_record["other_config"]["platform_params"],
1342 "xen_changeset": host_record["software_version"]["xen_changeset"],
1343 "cc_compiler": host_record["software_version"]["cc_compiler"],
1344 "cc_compile_by": host_record["software_version"]["cc_compile_by"],
1345 "cc_compile_domain": host_record["software_version"]["cc_compile_domain"],
1346 "cc_compile_date": host_record["software_version"]["cc_compile_date"],
1347 "xend_config_format":host_record["software_version"]["xend_config_format"]
1350 sorted = info.items()
1351 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1353 for (k, v) in sorted:
1354 print "%-23s:" % k, v
1355 else:
1356 info = server.xend.node.info()
1357 for x in info[1:]:
1358 if len(x) < 2:
1359 print "%-23s: (none)" % x[0]
1360 else:
1361 print "%-23s:" % x[0], x[1]
1363 def xm_console(args):
1364 arg_check(args, "console", 1, 2)
1366 quiet = False;
1368 try:
1369 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1370 except getopt.GetoptError, opterr:
1371 err(opterr)
1372 usage('console')
1374 for (k, v) in options:
1375 if k in ['-q', '--quiet']:
1376 quiet = True
1377 else:
1378 assert False
1380 if len(params) != 1:
1381 err('No domain given')
1382 usage('console')
1384 dom = params[0]
1386 try:
1387 info = server.xend.domain(dom)
1388 except:
1389 if quiet:
1390 sys.exit(1)
1391 else:
1392 raise
1393 domid = int(sxp.child_value(info, 'domid', '-1'))
1394 if domid == -1:
1395 if quiet:
1396 sys.exit(1)
1397 else:
1398 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1400 console.execConsole(domid)
1403 def xm_uptime(args):
1404 short_mode = 0
1406 try:
1407 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1408 except getopt.GetoptError, opterr:
1409 err(opterr)
1410 usage('uptime')
1412 for (k, v) in options:
1413 if k in ['-s', '--short']:
1414 short_mode = 1
1416 doms = getDomains(params, 'running')
1418 if short_mode == 0:
1419 print 'Name ID Uptime'
1421 for dom in doms:
1422 d = parse_doms_info(dom)
1423 if int(d['domid']) > 0:
1424 uptime = int(round(d['up_time']))
1425 else:
1426 f=open('/proc/uptime', 'r')
1427 upfile = f.read()
1428 uptime = int(round(float(upfile.split(' ')[0])))
1429 f.close()
1431 days = int(uptime / 86400)
1432 uptime -= (days * 86400)
1433 hours = int(uptime / 3600)
1434 uptime -= (hours * 3600)
1435 minutes = int(uptime / 60)
1436 uptime -= (minutes * 60)
1437 seconds = uptime
1439 upstring = ""
1440 if days > 0:
1441 upstring += str(days) + " day"
1442 if days > 1:
1443 upstring += "s"
1444 upstring += ", "
1445 upstring += '%(hours)2d:%(minutes)02d' % vars()
1447 if short_mode:
1448 now = datetime.datetime.now()
1449 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1450 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1451 else:
1452 upstring += ':%(seconds)02d' % vars()
1453 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1455 print upstring
1457 def xm_sysrq(args):
1458 arg_check(args, "sysrq", 2)
1459 dom = args[0]
1460 req = args[1]
1461 server.xend.domain.send_sysrq(dom, req)
1463 def xm_trigger(args):
1464 vcpu = 0
1466 arg_check(args, "trigger", 2, 3)
1467 dom = args[0]
1468 trigger = args[1]
1469 if len(args) == 3:
1470 vcpu = int(args[2])
1472 server.xend.domain.send_trigger(dom, trigger, vcpu)
1474 def xm_debug_keys(args):
1475 arg_check(args, "debug-keys", 1)
1476 server.xend.node.send_debug_keys(str(args[0]))
1478 def xm_top(args):
1479 arg_check(args, "top", 0)
1481 os.execvp('xentop', ['xentop'])
1483 def xm_dmesg(args):
1484 arg_check(args, "dmesg", 0, 1)
1486 try:
1487 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1488 except getopt.GetoptError, opterr:
1489 err(opterr)
1490 usage('dmesg')
1492 use_clear = 0
1493 for (k, v) in options:
1494 if k in ['-c', '--clear']:
1495 use_clear = 1
1497 if len(params) :
1498 err("No parameter required")
1499 usage('dmesg')
1501 if serverType == SERVER_XEN_API:
1502 if not use_clear:
1503 print server.xenapi.host.dmesg(
1504 server.xenapi.session.get_this_host(),0)
1505 else:
1506 server.xenapi.host.dmesg(
1507 server.xenapi.session.get_this_host(),1)
1508 else:
1509 if not use_clear:
1510 print server.xend.node.dmesg.info()
1511 else:
1512 server.xend.node.dmesg.clear()
1514 def xm_log(args):
1515 arg_check(args, "log", 0)
1517 if serverType == SERVER_XEN_API:
1518 print server.xenapi.host.get_log(
1519 server.xenapi.session.get_this_host())
1520 else:
1521 print server.xend.node.log()
1523 def xm_serve(args):
1524 if serverType == SERVER_XEN_API:
1525 print "Not supported with XenAPI"
1526 sys.exit(-1)
1528 arg_check(args, "serve", 0)
1530 from fcntl import fcntl, F_SETFL
1532 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1533 s.connect(XendClient.XML_RPC_SOCKET)
1534 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1536 while True:
1537 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1538 if s in iwtd:
1539 data = s.recv(4096)
1540 if len(data) > 0:
1541 sys.stdout.write(data)
1542 sys.stdout.flush()
1543 else:
1544 break
1545 if sys.stdin in iwtd:
1546 data = sys.stdin.read(4096)
1547 if len(data) > 0:
1548 s.sendall(data)
1549 else:
1550 break
1551 s.close()
1553 def parse_dev_info(info):
1554 def get_info(n, t, d):
1555 i = 0
1556 while i < len(info):
1557 if (info[i][0] == n):
1558 return t(info[i][1])
1559 i = i + 1
1560 return t(d)
1561 return {
1562 #common
1563 'backend-id' : get_info('backend-id', int, -1),
1564 'handle' : get_info('handle', int, 0),
1565 'state' : get_info('state', int, -1),
1566 'be-path' : get_info('backend', str, '??'),
1567 'event-ch' : get_info('event-channel',int, -1),
1568 #network specific
1569 'virtual-device' : get_info('virtual-device', str, '??'),
1570 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1571 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1572 'mac' : get_info('mac', str, '??'),
1573 #block-device specific
1574 'ring-ref' : get_info('ring-ref', int, -1),
1577 def arg_check_for_resource_list(args, name):
1578 use_long = 0
1579 try:
1580 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1581 except getopt.GetoptError, opterr:
1582 err(opterr)
1583 sys.exit(1)
1585 for (k, v) in options:
1586 if k in ['-l', '--long']:
1587 use_long = 1
1589 if len(params) == 0:
1590 print 'No domain parameter given'
1591 usage(name)
1592 if len(params) > 1:
1593 print 'No multiple domain parameters allowed'
1594 usage(name)
1596 return (use_long, params)
1598 def xm_network_list(args):
1599 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1601 dom = params[0]
1602 if use_long:
1603 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1604 map(PrettyPrint.prettyprint, devs)
1605 else:
1606 hdr = 0
1607 for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
1608 if hdr == 0:
1609 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1610 hdr = 1
1611 ni = parse_dev_info(x[1])
1612 ni['idx'] = int(x[0])
1613 print ("%(idx)-3d "
1614 "%(backend-id)-3d"
1615 "%(mac)-17s "
1616 "%(handle)-3d "
1617 "%(state)-3d "
1618 "%(event-ch)-3d "
1619 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1620 "%(be-path)-30s "
1621 % ni)
1623 def xm_block_list(args):
1624 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1626 dom = params[0]
1627 if use_long:
1628 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1629 map(PrettyPrint.prettyprint, devs)
1630 else:
1631 hdr = 0
1632 for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
1633 if hdr == 0:
1634 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1635 hdr = 1
1636 ni = parse_dev_info(x[1])
1637 ni['idx'] = int(x[0])
1638 print ("%(idx)-3d "
1639 "%(backend-id)-3d "
1640 "%(handle)-3d "
1641 "%(state)-3d "
1642 "%(event-ch)-3d "
1643 "%(ring-ref)-5d "
1644 "%(be-path)-30s "
1645 % ni)
1647 def xm_vtpm_list(args):
1648 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1650 dom = params[0]
1651 if use_long:
1652 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1653 map(PrettyPrint.prettyprint, devs)
1654 else:
1655 hdr = 0
1656 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1657 if hdr == 0:
1658 print 'Idx BE handle state evt-ch ring-ref BE-path'
1659 hdr = 1
1660 ni = parse_dev_info(x[1])
1661 ni['idx'] = int(x[0])
1662 print ("%(idx)-3d "
1663 "%(backend-id)-3d "
1664 "%(handle)-3d "
1665 "%(state)-3d "
1666 "%(event-ch)-3d "
1667 "%(ring-ref)-5d "
1668 "%(be-path)-30s "
1669 % ni)
1672 def parse_block_configuration(args):
1673 dom = args[0]
1675 if args[1].startswith('tap:'):
1676 cls = 'tap'
1677 else:
1678 cls = 'vbd'
1680 vbd = [cls,
1681 ['uname', args[1]],
1682 ['dev', args[2]],
1683 ['mode', args[3]]]
1684 if len(args) == 5:
1685 vbd.append(['backend', args[4]])
1687 # verify that policy permits attaching this resource
1688 if security.on():
1689 dominfo = server.xend.domain(dom)
1690 label = security.get_security_printlabel(dominfo)
1691 else:
1692 label = None
1693 security.res_security_check(args[1], label)
1695 return (dom, vbd)
1698 def xm_block_attach(args):
1699 arg_check(args, 'block-attach', 4, 5)
1701 (dom, vbd) = parse_block_configuration(args)
1702 server.xend.domain.device_create(dom, vbd)
1705 def xm_block_configure(args):
1706 arg_check(args, 'block-configure', 4, 5)
1708 (dom, vbd) = parse_block_configuration(args)
1709 server.xend.domain.device_configure(dom, vbd)
1712 def xm_network_attach(args):
1713 arg_check(args, 'network-attach', 1, 10)
1715 dom = args[0]
1716 vif = ['vif']
1717 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
1718 'backend', 'vifname', 'rate', 'model']
1720 for a in args[1:]:
1721 vif_param = a.split("=")
1722 if len(vif_param) != 2 or vif_param[1] == '' or \
1723 vif_param[0] not in vif_params:
1724 err("Invalid argument: %s" % a)
1725 usage('network-attach')
1726 vif.append(vif_param)
1728 server.xend.domain.device_create(dom, vif)
1731 def detach(args, command, deviceClass):
1732 arg_check(args, command, 2, 3)
1734 dom = args[0]
1735 dev = args[1]
1736 try:
1737 force = args[2]
1738 if (force != "--force") and (force != "-f"):
1739 print "Ignoring option %s"%(force)
1740 force = None
1741 except IndexError:
1742 force = None
1744 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
1747 def xm_block_detach(args):
1748 try:
1749 detach(args, 'block-detach', 'vbd')
1750 return
1751 except:
1752 pass
1753 detach(args, 'block-detach', 'tap')
1756 def xm_network_detach(args):
1757 detach(args, 'network-detach', 'vif')
1760 def xm_vnet_list(args):
1761 try:
1762 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1763 except getopt.GetoptError, opterr:
1764 err(opterr)
1765 usage('vnet-list')
1767 use_long = 0
1768 for (k, v) in options:
1769 if k in ['-l', '--long']:
1770 use_long = 1
1772 if params:
1773 use_long = 1
1774 vnets = params
1775 else:
1776 vnets = server.xend_vnets()
1778 for vnet in vnets:
1779 try:
1780 if use_long:
1781 info = server.xend_vnet(vnet)
1782 PrettyPrint.prettyprint(info)
1783 else:
1784 print vnet
1785 except Exception, ex:
1786 print vnet, ex
1788 def xm_vnet_create(args):
1789 arg_check(args, "vnet-create", 1)
1790 conf = args[0]
1791 if not os.access(conf, os.R_OK):
1792 print "File not found: %s" % conf
1793 sys.exit(1)
1795 server.xend_vnet_create(conf)
1797 def xm_vnet_delete(args):
1798 arg_check(args, "vnet-delete", 1)
1799 vnet = args[0]
1800 server.xend_vnet_delete(vnet)
1802 commands = {
1803 "shell": xm_shell,
1804 # console commands
1805 "console": xm_console,
1806 # xenstat commands
1807 "top": xm_top,
1808 # domain commands
1809 "delete": xm_delete,
1810 "destroy": xm_destroy,
1811 "domid": xm_domid,
1812 "domname": xm_domname,
1813 "dump-core": xm_dump_core,
1814 "reboot": xm_reboot,
1815 "rename": xm_rename,
1816 "restore": xm_restore,
1817 "resume": xm_resume,
1818 "save": xm_save,
1819 "shutdown": xm_shutdown,
1820 "start": xm_start,
1821 "sysrq": xm_sysrq,
1822 "trigger": xm_trigger,
1823 "uptime": xm_uptime,
1824 "suspend": xm_suspend,
1825 "list": xm_list,
1826 # memory commands
1827 "mem-max": xm_mem_max,
1828 "mem-set": xm_mem_set,
1829 # cpu commands
1830 "vcpu-pin": xm_vcpu_pin,
1831 "vcpu-list": xm_vcpu_list,
1832 "vcpu-set": xm_vcpu_set,
1833 # special
1834 "pause": xm_pause,
1835 "unpause": xm_unpause,
1836 # host commands
1837 "debug-keys": xm_debug_keys,
1838 "dmesg": xm_dmesg,
1839 "info": xm_info,
1840 "log": xm_log,
1841 "serve": xm_serve,
1842 # scheduler
1843 "sched-sedf": xm_sched_sedf,
1844 "sched-credit": xm_sched_credit,
1845 # block
1846 "block-attach": xm_block_attach,
1847 "block-detach": xm_block_detach,
1848 "block-list": xm_block_list,
1849 "block-configure": xm_block_configure,
1850 # network
1851 "network-attach": xm_network_attach,
1852 "network-detach": xm_network_detach,
1853 "network-list": xm_network_list,
1854 # vnet
1855 "vnet-list": xm_vnet_list,
1856 "vnet-create": xm_vnet_create,
1857 "vnet-delete": xm_vnet_delete,
1858 # vtpm
1859 "vtpm-list": xm_vtpm_list,
1862 ## The commands supported by a separate argument parser in xend.xm.
1863 IMPORTED_COMMANDS = [
1864 'create',
1865 'new',
1866 'migrate',
1867 'labels',
1868 'cfgbootpolicy',
1869 'makepolicy',
1870 'loadpolicy',
1871 'dumppolicy',
1872 'addlabel',
1873 'rmlabel',
1874 'getlabel',
1875 'dry-run',
1876 'resources',
1879 for c in IMPORTED_COMMANDS:
1880 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
1882 aliases = {
1883 "balloon": "mem-set",
1884 "set-vcpus": "vcpu-set",
1885 "vif-list": "network-list",
1886 "vbd-create": "block-attach",
1887 "vbd-destroy": "block-detach",
1888 "vbd-list": "block-list",
1892 def xm_lookup_cmd(cmd):
1893 if commands.has_key(cmd):
1894 return commands[cmd]
1895 elif aliases.has_key(cmd):
1896 deprecated(cmd,aliases[cmd])
1897 return commands[aliases[cmd]]
1898 elif cmd == 'help':
1899 longHelp()
1900 sys.exit(0)
1901 else:
1902 # simulate getopt's prefix matching behaviour
1903 if len(cmd) > 1:
1904 same_prefix_cmds = [commands[c] for c in commands.keys() \
1905 if c[:len(cmd)] == cmd]
1906 # only execute if there is only 1 match
1907 if len(same_prefix_cmds) == 1:
1908 return same_prefix_cmds[0]
1909 return None
1911 def deprecated(old,new):
1912 print >>sys.stderr, (
1913 "Command %s is deprecated. Please use xm %s instead." % (old, new))
1915 def main(argv=sys.argv):
1916 if len(argv) < 2:
1917 usage()
1919 # intercept --help(-h) and output our own help
1920 for help in ['--help', '-h']:
1921 if help in argv[1:]:
1922 if help == argv[1]:
1923 longHelp()
1924 sys.exit(0)
1925 else:
1926 usage(argv[1])
1928 cmd_name = argv[1]
1929 cmd = xm_lookup_cmd(cmd_name)
1930 if cmd:
1931 # strip off prog name and subcmd
1932 args = argv[2:]
1933 _, rc = _run_cmd(cmd, cmd_name, args)
1934 sys.exit(rc)
1935 else:
1936 err('Subcommand %s not found!' % cmd_name)
1937 usage()
1939 def _run_cmd(cmd, cmd_name, args):
1940 global server
1942 try:
1943 if server is None:
1944 if serverType == SERVER_XEN_API:
1945 server = XenAPI.Session(serverURI)
1946 username, password = parseAuthentication()
1947 server.login_with_password(username, password)
1948 def logout():
1949 try:
1950 server.xenapi.session.logout()
1951 except:
1952 pass
1953 atexit.register(logout)
1954 else:
1955 server = ServerProxy(serverURI)
1957 return True, cmd(args)
1958 except socket.error, ex:
1959 if os.geteuid() != 0:
1960 err("Most commands need root access. Please try again as root.")
1961 else:
1962 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
1963 except KeyboardInterrupt:
1964 print "Interrupted."
1965 return True, ''
1966 except IOError, ex:
1967 if os.geteuid() != 0:
1968 err("Most commands need root access. Please try again as root.")
1969 else:
1970 err("Unable to connect to xend: %s." % ex[1])
1971 except SystemExit, code:
1972 return code == 0, code
1973 except XenAPI.Failure, exn:
1974 for line in [''] + wrap(str(exn), 80) + ['']:
1975 print >>sys.stderr, line
1976 except xmlrpclib.Fault, ex:
1977 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
1978 err("Domain '%s' does not exist." % ex.faultString)
1979 else:
1980 err(ex.faultString)
1981 _usage(cmd_name)
1982 except xmlrpclib.ProtocolError, ex:
1983 if ex.errcode == -1:
1984 print >>sys.stderr, (
1985 "Xend has probably crashed! Invalid or missing HTTP "
1986 "status code.")
1987 else:
1988 print >>sys.stderr, (
1989 "Xend has probably crashed! ProtocolError(%d, %s)." %
1990 (ex.errcode, ex.errmsg))
1991 except (ValueError, OverflowError):
1992 err("Invalid argument.")
1993 _usage(cmd_name)
1994 except OptionError, e:
1995 err(str(e))
1996 _usage(cmd_name)
1997 print e.usage
1998 except security.ACMError, e:
1999 err(str(e))
2000 except:
2001 print "Unexpected error:", sys.exc_info()[0]
2002 print
2003 print "Please report to xen-devel@lists.xensource.com"
2004 raise
2006 return False, 1
2008 if __name__ == "__main__":
2009 main()