ia64/xen-unstable

view tools/python/xen/xm/main.py @ 14487:a6d888593117

Tidy the error message from getDomains when using the Xen-API and no domain
is found.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Mar 20 16:55:29 2007 +0000 (2007-03-20)
parents d86957cea8b8
children 9f9d04ce1eaf
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 time
37 import datetime
38 from select import select
39 import xml.dom.minidom
41 import warnings
42 warnings.filterwarnings('ignore', category=FutureWarning)
44 from xen.xend import PrettyPrint
45 from xen.xend import sxp
46 from xen.xend import XendClient
47 from xen.xend.XendConstants import *
49 from xen.xm.opts import OptionError, Opts, wrap, set_true
50 from xen.xm import console
51 from xen.util.xmlrpclib2 import ServerProxy
53 import XenAPI
56 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
57 # getopt.getopt if gnu_getopt is not available. This will mean that options
58 # may only be specified before positional arguments.
59 if not hasattr(getopt, 'gnu_getopt'):
60 getopt.gnu_getopt = getopt.getopt
62 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
63 XM_CONFIG_FILE_DEFAULT = '/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 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
355 config = None
356 if os.path.isfile(xmConfigFile):
357 try:
358 config = xml.dom.minidom.parse(xmConfigFile)
359 except:
360 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
361 xmConfigFile)
363 def parseServer():
364 if config:
365 server = config.getElementsByTagName('server')
366 if server:
367 st = server[0].getAttribute('type')
368 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
369 print >>sys.stderr, ('Invalid server type %s; using %s.' %
370 (st, SERVER_LEGACY_XMLRPC))
371 st = SERVER_LEGACY_XMLRPC
372 return (st, server[0].getAttribute('uri'))
374 return SERVER_LEGACY_XMLRPC, XendClient.uri
376 def parseAuthentication():
377 server = config.getElementsByTagName('server')[0]
378 return (server.getAttribute('username'),
379 server.getAttribute('password'))
381 serverType, serverURI = parseServer()
382 server = None
385 ####################################################################
386 #
387 # Help/usage printing functions
388 #
389 ####################################################################
391 def cmdHelp(cmd):
392 """Print help for a specific subcommand."""
394 for fc in SUBCOMMAND_HELP.keys():
395 if fc[:len(cmd)] == cmd:
396 cmd = fc
397 break
399 try:
400 args, desc = SUBCOMMAND_HELP[cmd]
401 except KeyError:
402 shortHelp()
403 return
405 print 'Usage: xm %s %s' % (cmd, args)
406 print
407 print desc
409 try:
410 # If options help message is defined, print this.
411 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
412 if shortopt and longopt:
413 optdesc = '%s, %s' % (shortopt, longopt)
414 elif shortopt:
415 optdesc = shortopt
416 elif longopt:
417 optdesc = longopt
419 wrapped_desc = wrap(desc, 43)
420 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
421 for line in wrapped_desc[1:]:
422 print ' ' * 33 + line
423 print
424 except KeyError:
425 # if the command is an external module, we grab usage help
426 # from the module itself.
427 if cmd in IMPORTED_COMMANDS:
428 try:
429 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
430 cmd_usage = getattr(cmd_module, "help", None)
431 if cmd_usage:
432 print cmd_usage()
433 except ImportError:
434 pass
436 def shortHelp():
437 """Print out generic help when xm is called without subcommand."""
439 print USAGE_HELP
440 print 'Common \'xm\' commands:\n'
442 for command in common_commands:
443 try:
444 args, desc = SUBCOMMAND_HELP[command]
445 except KeyError:
446 continue
447 wrapped_desc = wrap(desc, 50)
448 print ' %-20s %-50s' % (command, wrapped_desc[0])
449 for line in wrapped_desc[1:]:
450 print ' ' * 22 + line
452 print
453 print USAGE_FOOTER
454 print 'For a complete list of subcommands run \'xm help\'.'
456 def longHelp():
457 """Print out full help when xm is called with xm --help or xm help"""
459 print USAGE_HELP
460 print 'xm full list of subcommands:\n'
462 for command in all_commands:
463 try:
464 args, desc = SUBCOMMAND_HELP[command]
465 except KeyError:
466 continue
468 wrapped_desc = wrap(desc, 50)
469 print ' %-20s %-50s' % (command, wrapped_desc[0])
470 for line in wrapped_desc[1:]:
471 print ' ' * 22 + line
473 print
474 print USAGE_FOOTER
476 def _usage(cmd):
477 """ Print help usage information """
478 if cmd:
479 cmdHelp(cmd)
480 else:
481 shortHelp()
483 def usage(cmd = None):
484 """ Print help usage information and exits """
485 _usage(cmd)
486 sys.exit(1)
489 ####################################################################
490 #
491 # Utility functions
492 #
493 ####################################################################
495 def get_default_SR():
496 return [sr_ref
497 for sr_ref in server.xenapi.SR.get_all()
498 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
500 def get_default_Network():
501 return [network_ref
502 for network_ref in server.xenapi.network.get_all()][0]
504 def map2sxp(m):
505 return [[k, m[k]] for k in m.keys()]
507 def arg_check(args, name, lo, hi = -1):
508 n = len([i for i in args if i != '--'])
510 if hi == -1:
511 if n != lo:
512 err("'xm %s' requires %d argument%s.\n" % (name, lo,
513 lo == 1 and '' or 's'))
514 usage(name)
515 else:
516 if n < lo or n > hi:
517 err("'xm %s' requires between %d and %d arguments.\n" %
518 (name, lo, hi))
519 usage(name)
522 def unit(c):
523 if not c.isalpha():
524 return 0
525 base = 1
526 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
527 elif c == 'M' or c == 'm': base = 1024 * 1024
528 elif c == 'K' or c == 'k': base = 1024
529 else:
530 print 'ignoring unknown unit'
531 return base
533 def int_unit(str, dest):
534 base = unit(str[-1])
535 if not base:
536 return int(str)
538 value = int(str[:-1])
539 dst_base = unit(dest)
540 if dst_base == 0:
541 dst_base = 1
542 if dst_base > base:
543 return value / (dst_base / base)
544 else:
545 return value * (base / dst_base)
547 def err(msg):
548 print >>sys.stderr, "Error:", msg
551 def get_single_vm(dom):
552 uuids = server.xenapi.VM.get_by_name_label(dom)
553 n = len(uuids)
554 if n == 1:
555 return uuids[0]
556 else:
557 dominfo = server.xend.domain(dom, False)
558 return dominfo['uuid']
560 ##
561 #
562 # Xen-API Shell
563 #
564 ##
566 class Shell(cmd.Cmd):
567 def __init__(self):
568 cmd.Cmd.__init__(self)
569 self.prompt = "xm> "
570 if serverType == SERVER_XEN_API:
571 res = server.xenapi._UNSUPPORTED_list_all_methods()
572 for f in res:
573 setattr(Shell, 'do_' + f + ' ', self.default)
575 def preloop(self):
576 cmd.Cmd.preloop(self)
577 readline.set_completer_delims(' ')
579 def default(self, line):
580 words = shlex.split(line)
581 if len(words) > 0 and words[0] == 'xm':
582 words = words[1:]
583 if len(words) > 0:
584 cmd = xm_lookup_cmd(words[0])
585 if cmd:
586 _run_cmd(cmd, words[0], words[1:])
587 elif serverType == SERVER_XEN_API:
588 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
589 tuple(x)),
590 words[0], words[1:])
591 if ok and res is not None and res != '':
592 pprint.pprint(res)
593 else:
594 print '*** Unknown command: %s' % words[0]
595 return False
597 def completedefault(self, text, line, begidx, endidx):
598 words = shlex.split(line[:begidx])
599 clas, func = words[0].split('.')
600 if len(words) > 1 or \
601 func.startswith('get_by_') or \
602 func == 'get_all':
603 return []
604 uuids = server.xenapi_request('%s.get_all' % clas, ())
605 return [u + " " for u in uuids if u.startswith(text)]
607 def emptyline(self):
608 pass
610 def do_EOF(self, line):
611 print
612 sys.exit(0)
614 def do_help(self, line):
615 _usage(line)
618 def xm_shell(args):
619 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
622 #########################################################################
623 #
624 # Main xm functions
625 #
626 #########################################################################
628 def xm_save(args):
629 arg_check(args, "save", 2, 3)
631 try:
632 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
633 except getopt.GetoptError, opterr:
634 err(opterr)
635 sys.exit(1)
637 checkpoint = False
638 for (k, v) in options:
639 if k in ['-c', '--checkpoint']:
640 checkpoint = True
642 if len(params) != 2:
643 err("Wrong number of parameters")
644 usage('save')
645 sys.exit(1)
647 try:
648 dominfo = parse_doms_info(server.xend.domain(params[0]))
649 except xmlrpclib.Fault, ex:
650 raise ex
652 domid = dominfo['domid']
653 savefile = os.path.abspath(params[1])
655 if not os.access(os.path.dirname(savefile), os.W_OK):
656 err("xm save: Unable to create file %s" % savefile)
657 sys.exit(1)
659 server.xend.domain.save(domid, savefile, checkpoint)
661 def xm_restore(args):
662 arg_check(args, "restore", 1, 2)
664 try:
665 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
666 except getopt.GetoptError, opterr:
667 err(opterr)
668 usage('restore')
670 paused = False
671 for (k, v) in options:
672 if k in ['-p', '--paused']:
673 paused = True
675 if len(params) != 1:
676 err("Wrong number of parameters")
677 usage('restore')
679 savefile = os.path.abspath(params[0])
681 if not os.access(savefile, os.R_OK):
682 err("xm restore: Unable to read file %s" % savefile)
683 sys.exit(1)
685 server.xend.domain.restore(savefile, paused)
688 def getDomains(domain_names, state, full = 0):
689 if serverType == SERVER_XEN_API:
690 doms_sxp = []
691 doms_dict = []
692 dom_refs = server.xenapi.VM.get_all()
693 for dom_ref in dom_refs:
694 dom_rec = server.xenapi.VM.get_record(dom_ref)
695 dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref)
696 dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref)
697 dom_rec.update({'name': dom_rec['name_label'],
698 'memory_actual': int(dom_metrics['memory_actual'])/1024,
699 'vcpus': dom_metrics['vcpus_number'],
700 'state': '-----',
701 'cpu_time': dom_metrics['vcpus_utilisation']})
703 doms_sxp.append(['domain'] + map2sxp(dom_rec))
704 doms_dict.append(dom_rec)
706 if domain_names:
707 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
708 if dom["name"] in domain_names]
710 if len(doms) > 0:
711 return doms
712 else:
713 print "Error: no domain%s named %s" % \
714 (len(domain_names) > 1 and 's' or '',
715 ', '.join(domain_names))
716 sys.exit(-1)
717 else:
718 return doms_sxp
719 else:
720 if domain_names:
721 return [server.xend.domain(dom, full) for dom in domain_names]
722 else:
723 return server.xend.domains_with_state(True, state, full)
726 def xm_list(args):
727 use_long = 0
728 show_vcpus = 0
729 show_labels = 0
730 state = 'all'
731 try:
732 (options, params) = getopt.gnu_getopt(args, 'lv',
733 ['long','vcpus','label',
734 'state='])
735 except getopt.GetoptError, opterr:
736 err(opterr)
737 usage('list')
739 for (k, v) in options:
740 if k in ['-l', '--long']:
741 use_long = 1
742 if k in ['-v', '--vcpus']:
743 show_vcpus = 1
744 if k in ['--label']:
745 show_labels = 1
746 if k in ['--state']:
747 state = v
749 if state != 'all' and len(params) > 0:
750 raise OptionError(
751 "You may specify either a state or a particular VM, but not both")
753 if show_vcpus:
754 print >>sys.stderr, (
755 "xm list -v is deprecated. Please use xm vcpu-list.")
756 xm_vcpu_list(params)
757 return
759 doms = getDomains(params, state, use_long)
761 if use_long:
762 map(PrettyPrint.prettyprint, doms)
763 elif show_labels:
764 xm_label_list(doms)
765 else:
766 xm_brief_list(doms)
769 def parse_doms_info(info):
770 def get_info(n, t, d):
771 return t(sxp.child_value(info, n, d))
773 def get_status(n, t, d):
774 return DOM_STATES[t(sxp.child_value(info, n, d))]
776 start_time = get_info('start_time', float, -1)
777 if start_time == -1:
778 up_time = float(-1)
779 else:
780 up_time = time.time() - start_time
782 parsed_info = {
783 'domid' : get_info('domid', str, ''),
784 'name' : get_info('name', str, '??'),
785 'state' : get_info('state', str, ''),
787 # VCPUs is the number online when the VM is up, or the number
788 # configured otherwise.
789 'vcpus' : get_info('online_vcpus', int,
790 get_info('vcpus', int, 0)),
791 'up_time' : up_time
792 }
794 # We're not supporting security stuff just yet via XenAPI
796 if serverType != SERVER_XEN_API:
797 from xen.util import security
798 parsed_info['seclabel'] = security.get_security_printlabel(info)
799 else:
800 parsed_info['seclabel'] = ""
802 if serverType == SERVER_XEN_API:
803 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
804 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
805 if sum(cpu_times.values()) > 0:
806 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
807 else:
808 parsed_info['cpu_time'] = 0
809 else:
810 parsed_info['mem'] = get_info('memory', int,0)
811 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
813 return parsed_info
815 def check_sched_type(sched):
816 if serverType == SERVER_XEN_API:
817 current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host())
818 else:
819 current = 'unknown'
820 for x in server.xend.node.info()[1:]:
821 if len(x) > 1 and x[0] == 'xen_scheduler':
822 current = x[1]
823 break
824 if sched != current:
825 err("Xen is running with the %s scheduler" % current)
826 sys.exit(1)
828 def parse_sedf_info(info):
829 def get_info(n, t, d):
830 return t(sxp.child_value(info, n, d))
832 return {
833 'domid' : get_info('domid', int, -1),
834 'period' : get_info('period', int, -1),
835 'slice' : get_info('slice', int, -1),
836 'latency' : get_info('latency', int, -1),
837 'extratime': get_info('extratime', int, -1),
838 'weight' : get_info('weight', int, -1),
839 }
841 def domid_match(domid, info):
842 return domid is None or domid == info['name'] or \
843 domid == str(info['domid'])
845 def xm_brief_list(doms):
846 print '%-40s %3s %5s %5s %10s %9s' % \
847 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
849 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
850 "%(cpu_time)8.1f"
852 for dom in doms:
853 d = parse_doms_info(dom)
854 print format % d
856 def xm_label_list(doms):
857 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
858 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
860 output = []
861 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
862 '%(cpu_time)8.1f %(seclabel)9s'
864 if serverType != SERVER_XEN_API:
865 from xen.util import security
867 for dom in doms:
868 d = parse_doms_info(dom)
870 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
871 if not d['seclabel']:
872 d['seclabel'] = 'ERROR'
873 elif security.active_policy in ['DEFAULT']:
874 d['seclabel'] = 'DEFAULT'
875 else:
876 d['seclabel'] = 'INACTIVE'
878 output.append((format % d, d['seclabel']))
880 #sort by labels
881 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
882 for line, label in output:
883 print line
886 def xm_vcpu_list(args):
887 if args:
888 dominfo = map(server.xend.domain.getVCPUInfo, args)
889 else:
890 doms = server.xend.domains(False)
891 dominfo = map(server.xend.domain.getVCPUInfo, doms)
893 print '%-32s %3s %5s %5s %5s %9s %s' % \
894 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
896 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
897 ' %(cpu_time)8.1f %(cpumap)s'
899 for dom in dominfo:
900 def get_info(n):
901 return sxp.child_value(dom, n)
903 #
904 # convert a list of integers into a list of pairs indicating
905 # continuous sequences in the list:
906 #
907 # [0,1,2,3] -> [(0,3)]
908 # [1,2,4,5] -> [(1,2),(4,5)]
909 # [0] -> [(0,0)]
910 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
911 #
912 def list_to_rangepairs(cmap):
913 cmap.sort()
914 pairs = []
915 x = y = 0
916 for i in range(0,len(cmap)):
917 try:
918 if ((cmap[y+1] - cmap[i]) > 1):
919 pairs.append((cmap[x],cmap[y]))
920 x = y = i+1
921 else:
922 y = y + 1
923 # if we go off the end, then just add x to y
924 except IndexError:
925 pairs.append((cmap[x],cmap[y]))
927 return pairs
929 #
930 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
931 #
932 def format_pairs(pairs):
933 if not pairs:
934 return "no cpus"
935 out = ""
936 for f,s in pairs:
937 if (f==s):
938 out += '%d'%f
939 else:
940 out += '%d-%d'%(f,s)
941 out += ','
942 # trim trailing ','
943 return out[:-1]
945 def format_cpumap(cpumap):
946 cpumap = map(lambda x: int(x), cpumap)
947 cpumap.sort()
949 for x in server.xend.node.info()[1:]:
950 if len(x) > 1 and x[0] == 'nr_cpus':
951 nr_cpus = int(x[1])
952 # normalize cpumap by modulus nr_cpus, and drop duplicates
953 cpumap = dict.fromkeys(
954 map(lambda x: x % nr_cpus, cpumap)).keys()
955 if len(cpumap) == nr_cpus:
956 return "any cpu"
957 break
959 return format_pairs(list_to_rangepairs(cpumap))
961 name = get_info('name')
962 domid = int(get_info('domid'))
964 for vcpu in sxp.children(dom, 'vcpu'):
965 def vinfo(n, t):
966 return t(sxp.child_value(vcpu, n))
968 number = vinfo('number', int)
969 cpu = vinfo('cpu', int)
970 cpumap = format_cpumap(vinfo('cpumap', list))
971 online = vinfo('online', int)
972 cpu_time = vinfo('cpu_time', float)
973 running = vinfo('running', int)
974 blocked = vinfo('blocked', int)
976 if online:
977 c = str(cpu)
978 if running:
979 s = 'r'
980 else:
981 s = '-'
982 if blocked:
983 s += 'b'
984 else:
985 s += '-'
986 s += '-'
987 else:
988 c = "-"
989 s = "--p"
991 print format % locals()
993 def xm_start(args):
994 arg_check(args, "start", 1, 2)
996 try:
997 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
998 except getopt.GetoptError, opterr:
999 err(opterr)
1000 usage('start')
1002 paused = False
1003 for (k, v) in options:
1004 if k in ['-p', '--paused']:
1005 paused = True
1007 if len(params) != 1:
1008 err("Wrong number of parameters")
1009 usage('start')
1011 dom = params[0]
1012 if serverType == SERVER_XEN_API:
1013 server.xenapi.VM.start(get_single_vm(dom), paused)
1014 else:
1015 server.xend.domain.start(dom, paused)
1017 def xm_delete(args):
1018 arg_check(args, "delete", 1)
1019 dom = args[0]
1020 if serverType == SERVER_XEN_API:
1021 server.xenapi.VM.destroy(get_single_vm(dom))
1022 else:
1023 server.xend.domain.delete(dom)
1025 def xm_suspend(args):
1026 arg_check(args, "suspend", 1)
1027 dom = args[0]
1028 if serverType == SERVER_XEN_API:
1029 server.xenapi.VM.suspend(get_single_vm(dom))
1030 else:
1031 server.xend.domain.suspend(dom)
1033 def xm_resume(args):
1034 arg_check(args, "resume", 1, 2)
1036 try:
1037 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1038 except getopt.GetoptError, opterr:
1039 err(opterr)
1040 usage('resume')
1042 paused = False
1043 for (k, v) in options:
1044 if k in ['-p', '--paused']:
1045 paused = True
1047 if len(params) != 1:
1048 err("Wrong number of parameters")
1049 usage('resume')
1051 dom = params[0]
1052 if serverType == SERVER_XEN_API:
1053 server.xenapi.VM.resume(get_single_vm(dom), paused)
1054 else:
1055 server.xend.domain.resume(dom, paused)
1057 def xm_reboot(args):
1058 arg_check(args, "reboot", 1, 3)
1059 from xen.xm import shutdown
1060 shutdown.main(["shutdown", "-R"] + args)
1062 def xm_shutdown(args):
1063 arg_check(args, "shutdown", 1, 4)
1064 from xen.xm import shutdown
1065 shutdown.main(["shutdown"] + args)
1067 def xm_pause(args):
1068 arg_check(args, "pause", 1)
1069 dom = args[0]
1071 if serverType == SERVER_XEN_API:
1072 server.xenapi.VM.pause(get_single_vm(dom))
1073 else:
1074 server.xend.domain.pause(dom)
1076 def xm_unpause(args):
1077 arg_check(args, "unpause", 1)
1078 dom = args[0]
1080 if serverType == SERVER_XEN_API:
1081 server.xenapi.VM.unpause(get_single_vm(dom))
1082 else:
1083 server.xend.domain.unpause(dom)
1085 def xm_dump_core(args):
1086 live = False
1087 crash = False
1088 try:
1089 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1090 for (k, v) in options:
1091 if k in ('-L', '--live'):
1092 live = True
1093 if k in ('-C', '--crash'):
1094 crash = True
1096 if len(params) not in (1, 2):
1097 raise OptionError("Expects 1 or 2 argument(s)")
1098 except getopt.GetoptError, e:
1099 raise OptionError(str(e))
1101 dom = params[0]
1102 if len(params) == 2:
1103 filename = os.path.abspath(params[1])
1104 else:
1105 filename = None
1107 if not live:
1108 server.xend.domain.pause(dom)
1110 try:
1111 print "Dumping core of domain: %s ..." % str(dom)
1112 server.xend.domain.dump(dom, filename, live, crash)
1113 finally:
1114 if not live:
1115 server.xend.domain.unpause(dom)
1117 if crash:
1118 print "Destroying domain: %s ..." % str(dom)
1119 server.xend.domain.destroy(dom)
1121 def xm_rename(args):
1122 arg_check(args, "rename", 2)
1124 if serverType == SERVER_XEN_API:
1125 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1126 else:
1127 server.xend.domain.setName(args[0], args[1])
1129 def xm_importcommand(command, args):
1130 cmd = __import__(command, globals(), locals(), 'xen.xm')
1131 cmd.main([command] + args)
1134 #############################################################
1136 def xm_vcpu_pin(args):
1137 arg_check(args, "vcpu-pin", 3)
1139 def cpu_make_map(cpulist):
1140 cpus = []
1141 for c in cpulist.split(','):
1142 if c.find('-') != -1:
1143 (x,y) = c.split('-')
1144 for i in range(int(x),int(y)+1):
1145 cpus.append(int(i))
1146 else:
1147 # remove this element from the list
1148 if c[0] == '^':
1149 cpus = [x for x in cpus if x != int(c[1:])]
1150 else:
1151 cpus.append(int(c))
1152 cpus.sort()
1153 return cpus
1155 dom = args[0]
1156 vcpu = args[1]
1157 if args[2] == 'all':
1158 cpumap = cpu_make_map('0-63')
1159 else:
1160 cpumap = cpu_make_map(args[2])
1162 server.xend.domain.pincpu(dom, vcpu, cpumap)
1164 def xm_mem_max(args):
1165 arg_check(args, "mem-max", 2)
1167 dom = args[0]
1169 if serverType == SERVER_XEN_API:
1170 mem = int_unit(args[1], 'k') * 1024
1171 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1172 else:
1173 mem = int_unit(args[1], 'm')
1174 server.xend.domain.maxmem_set(dom, mem)
1176 def xm_mem_set(args):
1177 arg_check(args, "mem-set", 2)
1179 dom = args[0]
1181 if serverType == SERVER_XEN_API:
1182 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1183 server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target)
1184 server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target)
1185 else:
1186 mem_target = int_unit(args[1], 'm')
1187 server.xend.domain.setMemoryTarget(dom, mem_target)
1189 def xm_vcpu_set(args):
1190 arg_check(args, "vcpu-set", 2)
1192 dom = args[0]
1193 vcpus = int(args[1])
1195 if serverType == SERVER_XEN_API:
1196 server.xenapi.VM.set_vcpus_live(get_single_vm(dom), vcpus)
1197 else:
1198 server.xend.domain.setVCpuCount(dom, vcpus)
1200 def xm_destroy(args):
1201 arg_check(args, "destroy", 1)
1203 dom = args[0]
1205 if serverType == SERVER_XEN_API:
1206 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1207 else:
1208 server.xend.domain.destroy(dom)
1210 def xm_domid(args):
1211 arg_check(args, "domid", 1)
1213 name = args[0]
1215 if serverType == SERVER_XEN_API:
1216 print server.xenapi.VM.get_domid(get_single_vm(name))
1217 else:
1218 dom = server.xend.domain(name)
1219 print sxp.child_value(dom, 'domid')
1221 def xm_domname(args):
1222 arg_check(args, "domname", 1)
1224 name = args[0]
1226 if serverType == SERVER_XEN_API:
1227 print server.xenapi.VM.get_name_label(get_single_vm(name))
1228 else:
1229 dom = server.xend.domain(name)
1230 print sxp.child_value(dom, 'name')
1232 def xm_sched_sedf(args):
1233 def ns_to_ms(val):
1234 return float(val) * 0.000001
1236 def ms_to_ns(val):
1237 return (float(val) / 0.000001)
1239 def print_sedf(info):
1240 info['period'] = ns_to_ms(info['period'])
1241 info['slice'] = ns_to_ms(info['slice'])
1242 info['latency'] = ns_to_ms(info['latency'])
1243 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1244 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1246 check_sched_type('sedf')
1248 # we want to just display current info if no parameters are passed
1249 if len(args) == 0:
1250 domid = None
1251 else:
1252 # we expect at least a domain id (name or number)
1253 # and at most a domid up to 5 options with values
1254 arg_check(args, "sched-sedf", 1, 11)
1255 domid = args[0]
1256 # drop domid from args since get_opt doesn't recognize it
1257 args = args[1:]
1259 opts = {}
1260 try:
1261 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1262 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1263 except getopt.GetoptError, opterr:
1264 err(opterr)
1265 usage('sched-sedf')
1267 # convert to nanoseconds if needed
1268 for (k, v) in options:
1269 if k in ['-p', '--period']:
1270 opts['period'] = ms_to_ns(v)
1271 elif k in ['-s', '--slice']:
1272 opts['slice'] = ms_to_ns(v)
1273 elif k in ['-l', '--latency']:
1274 opts['latency'] = ms_to_ns(v)
1275 elif k in ['-e', '--extratime']:
1276 opts['extratime'] = v
1277 elif k in ['-w', '--weight']:
1278 opts['weight'] = v
1280 doms = filter(lambda x : domid_match(domid, x),
1281 [parse_doms_info(dom)
1282 for dom in getDomains(None, 'running')])
1283 if domid is not None and doms == []:
1284 err("Domain '%s' does not exist." % domid)
1285 usage('sched-sedf')
1287 # print header if we aren't setting any parameters
1288 if len(opts.keys()) == 0:
1289 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1290 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1291 'Extra','Weight')
1293 for d in doms:
1294 # fetch current values so as not to clobber them
1295 try:
1296 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1297 except xmlrpclib.Fault:
1298 # domain does not support sched-sedf?
1299 sedf_raw = {}
1301 sedf_info = parse_sedf_info(sedf_raw)
1302 sedf_info['name'] = d['name']
1303 # update values in case of call to set
1304 if len(opts.keys()) > 0:
1305 for k in opts.keys():
1306 sedf_info[k]=opts[k]
1308 # send the update, converting user input
1309 v = map(int, [sedf_info['period'], sedf_info['slice'],
1310 sedf_info['latency'],sedf_info['extratime'],
1311 sedf_info['weight']])
1312 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1313 if int(rv) != 0:
1314 err("Failed to set sedf parameters (rv=%d)."%(rv))
1316 # not setting values, display info
1317 else:
1318 print_sedf(sedf_info)
1320 def xm_sched_credit(args):
1321 """Get/Set options for Credit Scheduler."""
1323 check_sched_type('credit')
1325 try:
1326 opts, params = getopt.getopt(args, "d:w:c:",
1327 ["domain=", "weight=", "cap="])
1328 except getopt.GetoptError, opterr:
1329 err(opterr)
1330 usage('sched-credit')
1332 domid = None
1333 weight = None
1334 cap = None
1336 for o, a in opts:
1337 if o == "-d":
1338 domid = a
1339 elif o == "-w":
1340 weight = int(a)
1341 elif o == "-c":
1342 cap = int(a);
1344 doms = filter(lambda x : domid_match(domid, x),
1345 [parse_doms_info(dom)
1346 for dom in getDomains(None, 'running')])
1348 if weight is None and cap is None:
1349 if domid is not None and doms == []:
1350 err("Domain '%s' does not exist." % domid)
1351 usage('sched-credit')
1352 # print header if we aren't setting any parameters
1353 print '%-33s %-2s %-6s %-4s' % ('Name','ID','Weight','Cap')
1355 for d in doms:
1356 try:
1357 info = server.xend.domain.sched_credit_get(d['domid'])
1358 except xmlrpclib.Fault:
1359 # domain does not support sched-credit?
1360 info = {'weight': -1, 'cap': -1}
1362 info['name'] = d['name']
1363 info['domid'] = int(d['domid'])
1364 print( ("%(name)-32s %(domid)3d %(weight)6d %(cap)4d") % info)
1365 else:
1366 if domid is None:
1367 # place holder for system-wide scheduler parameters
1368 err("No domain given.")
1369 usage('sched-credit')
1371 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1372 if result != 0:
1373 err(str(result))
1375 def xm_info(args):
1376 arg_check(args, "info", 0)
1378 if serverType == SERVER_XEN_API:
1380 # Need to fake out old style xm info as people rely on parsing it
1382 host_record = server.xenapi.host.get_record(
1383 server.xenapi.session.get_this_host())
1385 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1387 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1389 info = {
1390 "host": host_record["name_label"],
1391 "release": host_record["software_version"]["release"],
1392 "version": host_record["software_version"]["version"],
1393 "machine": host_record["software_version"]["machine"],
1394 "nr_cpus": len(host_record["host_CPUs"]),
1395 "nr_nodes": host_record["cpu_configuration"]["nr_nodes"],
1396 "sockets_per_node": host_record["cpu_configuration"]["sockets_per_node"],
1397 "cores_per_socket": host_record["cpu_configuration"]["cores_per_socket"],
1398 "threads_per_core": host_record["cpu_configuration"]["threads_per_core"],
1399 "cpu_mhz": sum([int(host_cpu_record["speed"]) for host_cpu_record in host_cpu_records])
1400 / len(host_cpu_records),
1401 "hw_caps": host_cpu_records[0]["features"],
1402 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1403 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1404 "xen_major": host_record["software_version"]["xen_major"],
1405 "xen_minor": host_record["software_version"]["xen_minor"],
1406 "xen_extra": host_record["software_version"]["xen_extra"],
1407 "xen_caps": " ".join(host_record["capabilities"]),
1408 "xen_scheduler": host_record["sched_policy"],
1409 "xen_pagesize": host_record["other_config"]["xen_pagesize"],
1410 "platform_params": host_record["other_config"]["platform_params"],
1411 "xen_changeset": host_record["software_version"]["xen_changeset"],
1412 "cc_compiler": host_record["software_version"]["cc_compiler"],
1413 "cc_compile_by": host_record["software_version"]["cc_compile_by"],
1414 "cc_compile_domain": host_record["software_version"]["cc_compile_domain"],
1415 "cc_compile_date": host_record["software_version"]["cc_compile_date"],
1416 "xend_config_format":host_record["software_version"]["xend_config_format"]
1419 sorted = info.items()
1420 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1422 for (k, v) in sorted:
1423 print "%-23s:" % k, v
1424 else:
1425 info = server.xend.node.info()
1426 for x in info[1:]:
1427 if len(x) < 2:
1428 print "%-23s: (none)" % x[0]
1429 else:
1430 print "%-23s:" % x[0], x[1]
1432 def xm_console(args):
1433 arg_check(args, "console", 1, 2)
1435 quiet = False;
1437 try:
1438 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1439 except getopt.GetoptError, opterr:
1440 err(opterr)
1441 usage('console')
1443 for (k, v) in options:
1444 if k in ['-q', '--quiet']:
1445 quiet = True
1446 else:
1447 assert False
1449 if len(params) != 1:
1450 err('No domain given')
1451 usage('console')
1453 dom = params[0]
1455 try:
1456 if serverType == SERVER_XEN_API:
1457 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1458 else:
1459 info = server.xend.domain(dom)
1460 domid = int(sxp.child_value(info, 'domid', '-1'))
1461 except:
1462 if quiet:
1463 sys.exit(1)
1464 else:
1465 raise
1467 if domid == -1:
1468 if quiet:
1469 sys.exit(1)
1470 else:
1471 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1473 console.execConsole(domid)
1476 def xm_uptime(args):
1477 short_mode = 0
1479 try:
1480 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1481 except getopt.GetoptError, opterr:
1482 err(opterr)
1483 usage('uptime')
1485 for (k, v) in options:
1486 if k in ['-s', '--short']:
1487 short_mode = 1
1489 doms = getDomains(params, 'running')
1491 if short_mode == 0:
1492 print 'Name ID Uptime'
1494 for dom in doms:
1495 d = parse_doms_info(dom)
1496 if int(d['domid']) > 0:
1497 uptime = int(round(d['up_time']))
1498 else:
1499 f=open('/proc/uptime', 'r')
1500 upfile = f.read()
1501 uptime = int(round(float(upfile.split(' ')[0])))
1502 f.close()
1504 days = int(uptime / 86400)
1505 uptime -= (days * 86400)
1506 hours = int(uptime / 3600)
1507 uptime -= (hours * 3600)
1508 minutes = int(uptime / 60)
1509 uptime -= (minutes * 60)
1510 seconds = uptime
1512 upstring = ""
1513 if days > 0:
1514 upstring += str(days) + " day"
1515 if days > 1:
1516 upstring += "s"
1517 upstring += ", "
1518 upstring += '%(hours)2d:%(minutes)02d' % vars()
1520 if short_mode:
1521 now = datetime.datetime.now()
1522 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1523 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1524 else:
1525 upstring += ':%(seconds)02d' % vars()
1526 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1528 print upstring
1530 def xm_sysrq(args):
1531 arg_check(args, "sysrq", 2)
1532 dom = args[0]
1533 req = args[1]
1534 if serverType == SERVER_XEN_API:
1535 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1536 else:
1537 server.xend.domain.send_sysrq(dom, req)
1539 def xm_trigger(args):
1540 vcpu = 0
1542 arg_check(args, "trigger", 2, 3)
1543 dom = args[0]
1544 trigger = args[1]
1545 if len(args) == 3:
1546 vcpu = int(args[2])
1548 server.xend.domain.send_trigger(dom, trigger, vcpu)
1550 def xm_debug_keys(args):
1551 arg_check(args, "debug-keys", 1)
1552 server.xend.node.send_debug_keys(str(args[0]))
1554 def xm_top(args):
1555 arg_check(args, "top", 0)
1557 os.execvp('xentop', ['xentop'])
1559 def xm_dmesg(args):
1560 arg_check(args, "dmesg", 0, 1)
1562 try:
1563 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1564 except getopt.GetoptError, opterr:
1565 err(opterr)
1566 usage('dmesg')
1568 use_clear = 0
1569 for (k, v) in options:
1570 if k in ['-c', '--clear']:
1571 use_clear = 1
1573 if len(params) :
1574 err("No parameter required")
1575 usage('dmesg')
1577 if serverType == SERVER_XEN_API:
1578 if not use_clear:
1579 print server.xenapi.host.dmesg(
1580 server.xenapi.session.get_this_host(),0)
1581 else:
1582 server.xenapi.host.dmesg(
1583 server.xenapi.session.get_this_host(),1)
1584 else:
1585 if not use_clear:
1586 print server.xend.node.dmesg.info()
1587 else:
1588 server.xend.node.dmesg.clear()
1590 def xm_log(args):
1591 arg_check(args, "log", 0)
1593 if serverType == SERVER_XEN_API:
1594 print server.xenapi.host.get_log(
1595 server.xenapi.session.get_this_host())
1596 else:
1597 print server.xend.node.log()
1599 def xm_serve(args):
1600 if serverType == SERVER_XEN_API:
1601 print "Not supported with XenAPI"
1602 sys.exit(-1)
1604 arg_check(args, "serve", 0)
1606 from fcntl import fcntl, F_SETFL
1608 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1609 s.connect(XendClient.XML_RPC_SOCKET)
1610 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1612 while True:
1613 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1614 if s in iwtd:
1615 data = s.recv(4096)
1616 if len(data) > 0:
1617 sys.stdout.write(data)
1618 sys.stdout.flush()
1619 else:
1620 break
1621 if sys.stdin in iwtd:
1622 data = sys.stdin.read(4096)
1623 if len(data) > 0:
1624 s.sendall(data)
1625 else:
1626 break
1627 s.close()
1629 def parse_dev_info(info):
1630 def get_info(n, t, d):
1631 i = 0
1632 while i < len(info):
1633 if (info[i][0] == n):
1634 return t(info[i][1])
1635 i = i + 1
1636 return t(d)
1637 return {
1638 #common
1639 'backend-id' : get_info('backend-id', int, -1),
1640 'handle' : get_info('handle', int, 0),
1641 'state' : get_info('state', int, -1),
1642 'be-path' : get_info('backend', str, '??'),
1643 'event-ch' : get_info('event-channel',int, -1),
1644 #network specific
1645 'virtual-device' : get_info('virtual-device', str, '??'),
1646 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1647 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1648 'mac' : get_info('mac', str, '??'),
1649 #block-device specific
1650 'ring-ref' : get_info('ring-ref', int, -1),
1653 def arg_check_for_resource_list(args, name):
1654 use_long = 0
1655 try:
1656 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1657 except getopt.GetoptError, opterr:
1658 err(opterr)
1659 sys.exit(1)
1661 for (k, v) in options:
1662 if k in ['-l', '--long']:
1663 use_long = 1
1665 if len(params) == 0:
1666 print 'No domain parameter given'
1667 usage(name)
1668 if len(params) > 1:
1669 print 'No multiple domain parameters allowed'
1670 usage(name)
1672 return (use_long, params)
1674 def xm_network_list(args):
1675 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1677 dom = params[0]
1679 if serverType == SERVER_XEN_API:
1680 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1681 vif_properties = \
1682 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1683 devs = map(lambda x: [x.get('handle'), map2sxp(x)], vif_properties)
1684 else:
1685 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1687 if use_long:
1688 map(PrettyPrint.prettyprint, devs)
1689 else:
1690 hdr = 0
1691 for x in devs:
1692 if hdr == 0:
1693 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1694 hdr = 1
1695 ni = parse_dev_info(x[1])
1696 ni['idx'] = int(x[0])
1697 print ("%(idx)-3d "
1698 "%(backend-id)-3d"
1699 "%(mac)-17s "
1700 "%(handle)-3d "
1701 "%(state)-3d "
1702 "%(event-ch)-3d "
1703 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1704 "%(be-path)-30s "
1705 % ni)
1707 def xm_block_list(args):
1708 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1710 dom = params[0]
1712 if serverType == SERVER_XEN_API:
1713 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1714 vbd_properties = \
1715 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
1716 devs = map(lambda x: [x.get('virtual-device'), map2sxp(x)], vbd_properties)
1717 else:
1718 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1720 if use_long:
1721 map(PrettyPrint.prettyprint, devs)
1722 else:
1723 hdr = 0
1724 for x in devs:
1725 if hdr == 0:
1726 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1727 hdr = 1
1728 ni = parse_dev_info(x[1])
1729 ni['idx'] = int(x[0])
1730 print ("%(idx)-3d "
1731 "%(backend-id)-3d "
1732 "%(handle)-3d "
1733 "%(state)-3d "
1734 "%(event-ch)-3d "
1735 "%(ring-ref)-5d "
1736 "%(be-path)-30s "
1737 % ni)
1739 def xm_vtpm_list(args):
1740 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1742 dom = params[0]
1743 if use_long:
1744 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1745 map(PrettyPrint.prettyprint, devs)
1746 else:
1747 hdr = 0
1748 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1749 if hdr == 0:
1750 print 'Idx BE handle state evt-ch ring-ref BE-path'
1751 hdr = 1
1752 ni = parse_dev_info(x[1])
1753 ni['idx'] = int(x[0])
1754 print ("%(idx)-3d "
1755 "%(backend-id)-3d "
1756 "%(handle)-3d "
1757 "%(state)-3d "
1758 "%(event-ch)-3d "
1759 "%(ring-ref)-5d "
1760 "%(be-path)-30s "
1761 % ni)
1764 def parse_block_configuration(args):
1765 dom = args[0]
1767 if args[1].startswith('tap:'):
1768 cls = 'tap'
1769 else:
1770 cls = 'vbd'
1772 vbd = [cls,
1773 ['uname', args[1]],
1774 ['dev', args[2]],
1775 ['mode', args[3]]]
1776 if len(args) == 5:
1777 vbd.append(['backend', args[4]])
1779 if serverType != SERVER_XEN_API:
1780 # verify that policy permits attaching this resource
1781 from xen.util import security
1783 if security.on():
1784 dominfo = server.xend.domain(dom)
1785 label = security.get_security_printlabel(dominfo)
1786 else:
1787 label = None
1789 security.res_security_check(args[1], label)
1791 return (dom, vbd)
1794 def xm_block_attach(args):
1795 arg_check(args, 'block-attach', 4, 5)
1797 if serverType == SERVER_XEN_API:
1798 dom = args[0]
1799 uname = args[1]
1800 dev = args[2]
1801 mode = args[3]
1803 # First create new VDI
1804 vdi_record = {
1805 "name_label": "vdi" + str(uname.__hash__()),
1806 "name_description": "",
1807 "SR": get_default_SR(),
1808 "virtual_size": 0,
1809 "sector_size": 512,
1810 "type": "system",
1811 "sharable": False,
1812 "read_only": mode!="w",
1813 "other_config": {"location": uname}
1816 vdi_ref = server.xenapi.VDI.create(vdi_record)
1818 # Now create new VBD
1820 vbd_record = {
1821 "VM": get_single_vm(dom),
1822 "VDI": vdi_ref,
1823 "device": dev,
1824 "bootable": True,
1825 "mode": mode=="w" and "RW" or "RO",
1826 "type": "Disk",
1827 "qos_algorithm_type": "",
1828 "qos_algorithm_params": {}
1831 server.xenapi.VBD.create(vbd_record)
1833 else:
1834 (dom, vbd) = parse_block_configuration(args)
1835 server.xend.domain.device_create(dom, vbd)
1838 def xm_block_configure(args):
1839 arg_check(args, 'block-configure', 4, 5)
1841 (dom, vbd) = parse_block_configuration(args)
1842 server.xend.domain.device_configure(dom, vbd)
1845 def xm_network_attach(args):
1846 arg_check(args, 'network-attach', 1, 10)
1848 dom = args[0]
1849 vif = ['vif']
1850 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
1851 'backend', 'vifname', 'rate', 'model']
1853 if serverType == SERVER_XEN_API:
1854 vif_record = {
1855 "device": "eth0",
1856 "network": get_default_Network(),
1857 "VM": get_single_vm(dom),
1858 "MAC": "",
1859 "MTU": "",
1860 "qos_algorithm_type": "",
1861 "qos_algorithm_params": {},
1862 "other_config": {}
1865 def set(keys, val):
1866 record = vif_record
1867 for key in keys[:-1]:
1868 record = record[key]
1869 record[keys[-1]] = val
1871 vif_conv = {
1872 'type':
1873 lambda x: None,
1874 'mac':
1875 lambda x: set(['MAC'], x),
1876 'bridge':
1877 lambda x: set(['network'], get_net_from_bridge(x)),
1878 'ip':
1879 lambda x: set(['other_config', 'ip'], x),
1880 'script':
1881 lambda x: set(['other_config', 'script'], x),
1882 'backend':
1883 lambda x: set(['other_config', 'backend'], x),
1884 'vifname':
1885 lambda x: set(['device'], x),
1886 'rate':
1887 lambda x: set(['qos_algorithm_params', 'rate'], x),
1888 'model':
1889 lambda x: None
1892 for a in args[1:]:
1893 vif_param = a.split("=")
1894 if len(vif_param) != 2 or vif_param[1] == '' or \
1895 vif_param[0] not in vif_params:
1896 err("Invalid argument: %s" % a)
1897 usage('network-attach')
1898 else:
1899 vif_conv[vif_param[0]](vif_param[1])
1901 print str(vif_record)
1902 server.xenapi.VIF.create(vif_record)
1903 else:
1904 for a in args[1:]:
1905 vif_param = a.split("=")
1906 if len(vif_param) != 2 or vif_param[1] == '' or \
1907 vif_param[0] not in vif_params:
1908 err("Invalid argument: %s" % a)
1909 usage('network-attach')
1910 vif.append(vif_param)
1911 server.xend.domain.device_create(dom, vif)
1914 def detach(args, command, deviceClass):
1915 arg_check(args, command, 2, 3)
1917 dom = args[0]
1918 dev = args[1]
1919 try:
1920 force = args[2]
1921 if (force != "--force") and (force != "-f"):
1922 print "Ignoring option %s"%(force)
1923 force = None
1924 except IndexError:
1925 force = None
1927 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
1930 def xm_block_detach(args):
1931 if serverType == SERVER_XEN_API:
1932 arg_check(args, "xm_block_detach", 2, 3)
1933 dom = args[0]
1934 dev = args[1]
1935 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1936 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
1937 if server.xenapi.VBD.get_device(vbd_ref) == dev]
1938 if len(vbd_refs) > 0:
1939 vbd_ref = vbd_refs[0]
1940 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
1942 server.xenapi.VBD.destroy(vbd_ref)
1944 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
1945 server.xenapi.VDI.destroy(vdi_ref)
1946 else:
1947 print "Cannot find device '%s' in domain '%s'" % (dev,dom)
1948 else:
1949 try:
1950 detach(args, 'block-detach', 'vbd')
1951 return
1952 except:
1953 pass
1954 detach(args, 'block-detach', 'tap')
1956 def xm_network_detach(args):
1957 if serverType == SERVER_XEN_API:
1958 arg_check(args, "xm_block_detach", 2, 3)
1959 dom = args[0]
1960 devid = args[1]
1961 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1962 vif_refs = [vif_ref for vif_ref in vif_refs
1963 if server.xenapi.VIF.\
1964 get_runtime_properties(vif_ref)["handle"] == devid]
1965 if len(vif_refs) > 0:
1966 vif_ref = vif_refs[0]
1968 server.xenapi.VIF.destroy(vif_ref)
1969 else:
1970 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
1971 else:
1972 detach(args, 'network-detach', 'vif')
1975 def xm_vnet_list(args):
1976 try:
1977 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1978 except getopt.GetoptError, opterr:
1979 err(opterr)
1980 usage('vnet-list')
1982 use_long = 0
1983 for (k, v) in options:
1984 if k in ['-l', '--long']:
1985 use_long = 1
1987 if params:
1988 use_long = 1
1989 vnets = params
1990 else:
1991 vnets = server.xend_vnets()
1993 for vnet in vnets:
1994 try:
1995 if use_long:
1996 info = server.xend_vnet(vnet)
1997 PrettyPrint.prettyprint(info)
1998 else:
1999 print vnet
2000 except Exception, ex:
2001 print vnet, ex
2003 def xm_vnet_create(args):
2004 arg_check(args, "vnet-create", 1)
2005 conf = args[0]
2006 if not os.access(conf, os.R_OK):
2007 print "File not found: %s" % conf
2008 sys.exit(1)
2010 server.xend_vnet_create(conf)
2012 def xm_vnet_delete(args):
2013 arg_check(args, "vnet-delete", 1)
2014 vnet = args[0]
2015 server.xend_vnet_delete(vnet)
2017 commands = {
2018 "shell": xm_shell,
2019 # console commands
2020 "console": xm_console,
2021 # xenstat commands
2022 "top": xm_top,
2023 # domain commands
2024 "delete": xm_delete,
2025 "destroy": xm_destroy,
2026 "domid": xm_domid,
2027 "domname": xm_domname,
2028 "dump-core": xm_dump_core,
2029 "reboot": xm_reboot,
2030 "rename": xm_rename,
2031 "restore": xm_restore,
2032 "resume": xm_resume,
2033 "save": xm_save,
2034 "shutdown": xm_shutdown,
2035 "start": xm_start,
2036 "sysrq": xm_sysrq,
2037 "trigger": xm_trigger,
2038 "uptime": xm_uptime,
2039 "suspend": xm_suspend,
2040 "list": xm_list,
2041 # memory commands
2042 "mem-max": xm_mem_max,
2043 "mem-set": xm_mem_set,
2044 # cpu commands
2045 "vcpu-pin": xm_vcpu_pin,
2046 "vcpu-list": xm_vcpu_list,
2047 "vcpu-set": xm_vcpu_set,
2048 # special
2049 "pause": xm_pause,
2050 "unpause": xm_unpause,
2051 # host commands
2052 "debug-keys": xm_debug_keys,
2053 "dmesg": xm_dmesg,
2054 "info": xm_info,
2055 "log": xm_log,
2056 "serve": xm_serve,
2057 # scheduler
2058 "sched-sedf": xm_sched_sedf,
2059 "sched-credit": xm_sched_credit,
2060 # block
2061 "block-attach": xm_block_attach,
2062 "block-detach": xm_block_detach,
2063 "block-list": xm_block_list,
2064 "block-configure": xm_block_configure,
2065 # network
2066 "network-attach": xm_network_attach,
2067 "network-detach": xm_network_detach,
2068 "network-list": xm_network_list,
2069 # vnet
2070 "vnet-list": xm_vnet_list,
2071 "vnet-create": xm_vnet_create,
2072 "vnet-delete": xm_vnet_delete,
2073 # vtpm
2074 "vtpm-list": xm_vtpm_list,
2077 ## The commands supported by a separate argument parser in xend.xm.
2078 IMPORTED_COMMANDS = [
2079 'create',
2080 'new',
2081 'migrate',
2082 'labels',
2083 'cfgbootpolicy',
2084 'makepolicy',
2085 'loadpolicy',
2086 'dumppolicy',
2087 'addlabel',
2088 'rmlabel',
2089 'getlabel',
2090 'dry-run',
2091 'resources',
2094 for c in IMPORTED_COMMANDS:
2095 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2097 aliases = {
2098 "balloon": "mem-set",
2099 "set-vcpus": "vcpu-set",
2100 "vif-list": "network-list",
2101 "vbd-create": "block-attach",
2102 "vbd-destroy": "block-detach",
2103 "vbd-list": "block-list",
2107 def xm_lookup_cmd(cmd):
2108 if commands.has_key(cmd):
2109 return commands[cmd]
2110 elif aliases.has_key(cmd):
2111 deprecated(cmd,aliases[cmd])
2112 return commands[aliases[cmd]]
2113 elif cmd == 'help':
2114 longHelp()
2115 sys.exit(0)
2116 else:
2117 # simulate getopt's prefix matching behaviour
2118 if len(cmd) > 1:
2119 same_prefix_cmds = [commands[c] for c in commands.keys() \
2120 if c[:len(cmd)] == cmd]
2121 # only execute if there is only 1 match
2122 if len(same_prefix_cmds) == 1:
2123 return same_prefix_cmds[0]
2124 return None
2126 def deprecated(old,new):
2127 print >>sys.stderr, (
2128 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2130 def main(argv=sys.argv):
2131 if len(argv) < 2:
2132 usage()
2134 # intercept --help(-h) and output our own help
2135 for help in ['--help', '-h']:
2136 if help in argv[1:]:
2137 if help == argv[1]:
2138 longHelp()
2139 sys.exit(0)
2140 else:
2141 usage(argv[1])
2143 cmd_name = argv[1]
2144 cmd = xm_lookup_cmd(cmd_name)
2145 if cmd:
2146 # strip off prog name and subcmd
2147 args = argv[2:]
2148 _, rc = _run_cmd(cmd, cmd_name, args)
2149 sys.exit(rc)
2150 else:
2151 err('Subcommand %s not found!' % cmd_name)
2152 usage()
2154 def _run_cmd(cmd, cmd_name, args):
2155 global server
2157 try:
2158 if server is None:
2159 if serverType == SERVER_XEN_API:
2160 server = XenAPI.Session(serverURI)
2161 username, password = parseAuthentication()
2162 server.login_with_password(username, password)
2163 def logout():
2164 try:
2165 server.xenapi.session.logout()
2166 except:
2167 pass
2168 atexit.register(logout)
2169 else:
2170 server = ServerProxy(serverURI)
2172 return True, cmd(args)
2173 except socket.error, ex:
2174 if os.geteuid() != 0:
2175 err("Most commands need root access. Please try again as root.")
2176 else:
2177 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2178 except KeyboardInterrupt:
2179 print "Interrupted."
2180 return True, ''
2181 except IOError, ex:
2182 if os.geteuid() != 0:
2183 err("Most commands need root access. Please try again as root.")
2184 else:
2185 err("Unable to connect to xend: %s." % ex[1])
2186 except SystemExit, code:
2187 return code == 0, code
2188 except XenAPI.Failure, exn:
2189 for line in [''] + wrap(str(exn), 80) + ['']:
2190 print >>sys.stderr, line
2191 except xmlrpclib.Fault, ex:
2192 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2193 err("Domain '%s' does not exist." % ex.faultString)
2194 else:
2195 err(ex.faultString)
2196 _usage(cmd_name)
2197 except xmlrpclib.ProtocolError, ex:
2198 if ex.errcode == -1:
2199 print >>sys.stderr, (
2200 "Xend has probably crashed! Invalid or missing HTTP "
2201 "status code.")
2202 else:
2203 print >>sys.stderr, (
2204 "Xend has probably crashed! ProtocolError(%d, %s)." %
2205 (ex.errcode, ex.errmsg))
2206 except (ValueError, OverflowError):
2207 err("Invalid argument.")
2208 _usage(cmd_name)
2209 except OptionError, e:
2210 err(str(e))
2211 _usage(cmd_name)
2212 print e.usage
2213 except Exception, e:
2214 if serverType != SERVER_XEN_API:
2215 from xen.util import security
2216 if isinstance(e, security.ACMError):
2217 err(str(e))
2218 return False, 1
2219 else:
2220 print "Unexpected error:", sys.exc_info()[0]
2221 print
2222 print "Please report to xen-devel@lists.xensource.com"
2223 raise
2225 return False, 1
2227 if __name__ == "__main__":
2228 main()