ia64/xen-unstable

view tools/python/xen/xm/main.py @ 16355:6d7ea0cf6e5b

xm: Fix long options of xm sched-credit

Long options of xm sched-credit command are ignored (--domain,
--weight, --cap). This patch fixes it.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author Keir Fraser <keir@xensource.com>
date Thu Nov 08 10:23:22 2007 +0000 (2007-11-08)
parents 6df47366830c
children 5255eac35270
line source
1 # (C) Copyright IBM Corp. 2005
2 # Copyright (C) 2004 Mike Wray
3 # Copyright (c) 2005-2006 XenSource Ltd.
4 #
5 # Authors:
6 # Sean Dague <sean at dague dot net>
7 # Mike Wray <mike dot wray at hp dot com>
8 #
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of version 2.1 of the GNU Lesser General Public
11 # License as published by the Free Software Foundation.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 """Grand unified management application for Xen.
23 """
24 import atexit
25 import cmd
26 import os
27 import pprint
28 import shlex
29 import sys
30 import re
31 import getopt
32 import socket
33 import traceback
34 import xmlrpclib
35 import time
36 import datetime
37 from select import select
38 import xml.dom.minidom
39 from xen.util.blkif import blkdev_name_to_number
41 import warnings
42 warnings.filterwarnings('ignore', category=FutureWarning)
44 from xen.xend import PrettyPrint
45 from xen.xend import sxp
46 from xen.xend import XendClient
47 from xen.xend.XendConstants import *
49 from xen.xm.opts import OptionError, Opts, wrap, set_true
50 from xen.xm import console
51 from xen.util.xmlrpcclient import ServerProxy
52 import xen.util.xsm.xsm as security
53 from xen.util.xsm.xsm import XSMError
54 from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
56 import XenAPI
58 import inspect
59 from xen.xend import XendOptions
60 xoptions = XendOptions.instance()
62 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
63 # getopt.getopt if gnu_getopt is not available. This will mean that options
64 # may only be specified before positional arguments.
65 if not hasattr(getopt, 'gnu_getopt'):
66 getopt.gnu_getopt = getopt.getopt
68 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
69 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
71 # Supported types of server
72 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
73 SERVER_XEN_API = 'Xen-API'
75 # General help message
77 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
78 "Control, list, and manipulate Xen guest instances.\n"
80 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
81 'For more help on \'xm\' see the xm(1) man page.\n' \
82 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
83 ' man page.\n'
85 # Help strings are indexed by subcommand name in this way:
86 # 'subcommand': (argstring, description)
88 SUBCOMMAND_HELP = {
89 # common commands
91 'shell' : ('', 'Launch an interactive shell.'),
93 'console' : ('[-q|--quiet] <Domain>',
94 'Attach to <Domain>\'s console.'),
95 'create' : ('<ConfigFile> [options] [vars]',
96 'Create a domain based on <ConfigFile>.'),
97 'destroy' : ('<Domain>',
98 'Terminate a domain immediately.'),
99 'help' : ('', 'Display this message.'),
100 'list' : ('[options] [Domain, ...]',
101 'List information about all/some domains.'),
102 'mem-max' : ('<Domain> <Mem>',
103 'Set the maximum amount reservation for a domain.'),
104 'mem-set' : ('<Domain> <Mem>',
105 'Set the current memory usage for a domain.'),
106 'migrate' : ('<Domain> <Host>',
107 'Migrate a domain to another machine.'),
108 'pause' : ('<Domain>', 'Pause execution of a domain.'),
109 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
110 'restore' : ('<CheckpointFile> [-p]',
111 'Restore a domain from a saved state.'),
112 'save' : ('[-c] <Domain> <CheckpointFile>',
113 'Save a domain state to restore later.'),
114 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
115 'top' : ('', 'Monitor a host and the domains in real time.'),
116 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
117 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
119 # Life cycle xm commands
120 'new' : ('<ConfigFile> [options] [vars]',
121 'Adds a domain to Xend domain management'),
122 'delete' : ('<DomainName>',
123 'Remove a domain from Xend domain management.'),
124 'start' : ('<DomainName>', 'Start a Xend managed domain'),
125 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
126 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
128 # less used commands
130 'dmesg' : ('[-c|--clear]',
131 'Read and/or clear Xend\'s message buffer.'),
132 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
133 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
134 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
135 'Dump core for a specific domain.'),
136 'info' : ('', 'Get information about Xen host.'),
137 'log' : ('', 'Print Xend log'),
138 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
139 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
140 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
141 'Get/set credit scheduler parameters.'),
142 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
143 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
144 'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
145 'Send a trigger to a domain.'),
146 'vcpu-list' : ('[<Domain>]',
147 'List the VCPUs for a domain or all domains.'),
148 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
149 'Set which CPUs a VCPU can use.'),
150 'vcpu-set' : ('<Domain> <vCPUs>',
151 'Set the number of active VCPUs for allowed for the'
152 ' domain.'),
154 # device commands
156 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
157 'Create a new virtual block device.'),
158 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
159 'Change block device configuration'),
160 'block-detach' : ('<Domain> <DevId> [-f|--force]',
161 'Destroy a domain\'s virtual block device.'),
162 'block-list' : ('<Domain> [--long]',
163 'List virtual block devices for a domain.'),
164 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
165 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
166 '[vifname=<name>] [rate=<rate>] [model=<model>]'
167 '[accel=<accel>]',
168 'Create a new virtual network device.'),
169 'network-detach': ('<Domain> <DevId> [-f|--force]',
170 'Destroy a domain\'s virtual network device.'),
171 'network-list' : ('<Domain> [--long]',
172 'List virtual network interfaces for a domain.'),
173 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
174 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
175 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
176 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
178 # security
180 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
181 ' [<policy>]',
182 'Add security label to domain.'),
183 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
184 'Remove a security label from domain.'),
185 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
186 'Show security label for domain or resource.'),
187 'dry-run' : ('<ConfigFile>',
188 'Test if a domain can access its resources.'),
189 'resources' : ('', 'Show info for each labeled resource.'),
190 'cfgbootpolicy' : ('<policy> [boot-title]',
191 'Add policy to boot configuration.'),
192 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
193 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
194 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
195 'files.'),
196 'setpolicy' : ('<policytype> <policyfile> [options]',
197 'Set the policy of the system.'),
198 'getpolicy' : ('[options]', 'Get the policy of the system.'),
199 'activatepolicy': ('[options]', 'Activate the xend-managed policy.'),
200 'labels' : ('[policy] [type=dom|res|any]',
201 'List <type> labels for (active) policy.'),
202 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
203 }
205 SUBCOMMAND_OPTIONS = {
206 'sched-sedf': (
207 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
208 ('-s [MS]', '--slice[=MS]' ,
209 'Worst-case execution time(ms). (slice < period)'),
210 ('-l [MS]', '--latency[=MS]',
211 'Scaled period (ms) when domain performs heavy I/O'),
212 ('-e [FLAG]', '--extra[=FLAG]',
213 'Flag (0 or 1) controls if domain can run in extra time.'),
214 ('-w [FLOAT]', '--weight[=FLOAT]',
215 'CPU Period/slice (do not set with --period/--slice)'),
216 ),
217 'sched-credit': (
218 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
219 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
220 ('-c CAP', '--cap=CAP', 'Cap (int)'),
221 ),
222 'list': (
223 ('-l', '--long', 'Output all VM details in SXP'),
224 ('', '--label', 'Include security labels'),
225 ('', '--state=<state>', 'Select only VMs with the specified state'),
226 ),
227 'console': (
228 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
229 ),
230 'dmesg': (
231 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
232 ),
233 'vnet-list': (
234 ('-l', '--long', 'List Vnets as SXP'),
235 ),
236 'network-list': (
237 ('-l', '--long', 'List resources as SXP'),
238 ),
239 'dump-core': (
240 ('-L', '--live', 'Dump core without pausing the domain'),
241 ('-C', '--crash', 'Crash domain after dumping core'),
242 ),
243 'start': (
244 ('-p', '--paused', 'Do not unpause domain after starting it'),
245 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
246 ),
247 'resume': (
248 ('-p', '--paused', 'Do not unpause domain after resuming it'),
249 ),
250 'save': (
251 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
252 ),
253 'restore': (
254 ('-p', '--paused', 'Do not unpause domain after restoring it'),
255 ),
256 }
258 common_commands = [
259 "console",
260 "create",
261 "new",
262 "delete",
263 "destroy",
264 "dump-core",
265 "help",
266 "list",
267 "mem-set",
268 "migrate",
269 "pause",
270 "reboot",
271 "restore",
272 "resume",
273 "save",
274 "shell",
275 "shutdown",
276 "start",
277 "suspend",
278 "top",
279 "unpause",
280 "uptime",
281 "vcpu-set",
282 ]
284 domain_commands = [
285 "console",
286 "create",
287 "new",
288 "delete",
289 "destroy",
290 "domid",
291 "domname",
292 "dump-core",
293 "list",
294 "mem-max",
295 "mem-set",
296 "migrate",
297 "pause",
298 "reboot",
299 "rename",
300 "restore",
301 "resume",
302 "save",
303 "shutdown",
304 "start",
305 "suspend",
306 "sysrq",
307 "trigger",
308 "top",
309 "unpause",
310 "uptime",
311 "vcpu-list",
312 "vcpu-pin",
313 "vcpu-set",
314 ]
316 host_commands = [
317 "debug-keys",
318 "dmesg",
319 "info",
320 "log",
321 "serve",
322 ]
324 scheduler_commands = [
325 "sched-credit",
326 "sched-sedf",
327 ]
329 device_commands = [
330 "block-attach",
331 "block-detach",
332 "block-list",
333 "block-configure",
334 "network-attach",
335 "network-detach",
336 "network-list",
337 "vtpm-list",
338 ]
340 vnet_commands = [
341 "vnet-list",
342 "vnet-create",
343 "vnet-delete",
344 ]
346 acm_commands = [
347 "labels",
348 "addlabel",
349 "rmlabel",
350 "getlabel",
351 "dry-run",
352 "resources",
353 "makepolicy",
354 "loadpolicy",
355 "cfgbootpolicy",
356 "dumppolicy",
357 "activatepolicy",
358 "setpolicy",
359 "getpolicy",
360 ]
362 all_commands = (domain_commands + host_commands + scheduler_commands +
363 device_commands + vnet_commands + acm_commands +
364 ['shell', 'event-monitor'])
367 ##
368 # Configuration File Parsing
369 ##
371 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
372 config = None
373 if os.path.isfile(xmConfigFile):
374 try:
375 config = xml.dom.minidom.parse(xmConfigFile)
376 except:
377 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
378 xmConfigFile)
380 def parseServer():
381 if config:
382 server = config.getElementsByTagName('server')
383 if server:
384 st = server[0].getAttribute('type')
385 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
386 print >>sys.stderr, ('Invalid server type %s; using %s.' %
387 (st, SERVER_LEGACY_XMLRPC))
388 st = SERVER_LEGACY_XMLRPC
389 return (st, server[0].getAttribute('uri'))
391 return SERVER_LEGACY_XMLRPC, XendClient.uri
393 def parseAuthentication():
394 server = config.getElementsByTagName('server')[0]
395 return (server.getAttribute('username'),
396 server.getAttribute('password'))
398 serverType, serverURI = parseServer()
399 server = None
402 ####################################################################
403 #
404 # Help/usage printing functions
405 #
406 ####################################################################
408 def cmdHelp(cmd):
409 """Print help for a specific subcommand."""
411 for fc in SUBCOMMAND_HELP.keys():
412 if fc[:len(cmd)] == cmd:
413 cmd = fc
414 break
416 try:
417 args, desc = SUBCOMMAND_HELP[cmd]
418 except KeyError:
419 shortHelp()
420 return
422 print 'Usage: xm %s %s' % (cmd, args)
423 print
424 print desc
426 try:
427 # If options help message is defined, print this.
428 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
429 if shortopt and longopt:
430 optdesc = '%s, %s' % (shortopt, longopt)
431 elif shortopt:
432 optdesc = shortopt
433 elif longopt:
434 optdesc = longopt
436 wrapped_desc = wrap(desc, 43)
437 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
438 for line in wrapped_desc[1:]:
439 print ' ' * 33 + line
440 print
441 except KeyError:
442 # if the command is an external module, we grab usage help
443 # from the module itself.
444 if cmd in IMPORTED_COMMANDS:
445 try:
446 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
447 cmd_usage = getattr(cmd_module, "help", None)
448 if cmd_usage:
449 print cmd_usage()
450 except ImportError:
451 pass
453 def shortHelp():
454 """Print out generic help when xm is called without subcommand."""
456 print USAGE_HELP
457 print 'Common \'xm\' commands:\n'
459 for command in common_commands:
460 try:
461 args, desc = SUBCOMMAND_HELP[command]
462 except KeyError:
463 continue
464 wrapped_desc = wrap(desc, 50)
465 print ' %-20s %-50s' % (command, wrapped_desc[0])
466 for line in wrapped_desc[1:]:
467 print ' ' * 22 + line
469 print
470 print USAGE_FOOTER
471 print 'For a complete list of subcommands run \'xm help\'.'
473 def longHelp():
474 """Print out full help when xm is called with xm --help or xm help"""
476 print USAGE_HELP
477 print 'xm full list of subcommands:\n'
479 for command in all_commands:
480 try:
481 args, desc = SUBCOMMAND_HELP[command]
482 except KeyError:
483 continue
485 wrapped_desc = wrap(desc, 50)
486 print ' %-20s %-50s' % (command, wrapped_desc[0])
487 for line in wrapped_desc[1:]:
488 print ' ' * 22 + line
490 print
491 print USAGE_FOOTER
493 def _usage(cmd):
494 """ Print help usage information """
495 if cmd:
496 cmdHelp(cmd)
497 else:
498 shortHelp()
500 def usage(cmd = None):
501 """ Print help usage information and exits """
502 _usage(cmd)
503 sys.exit(1)
506 ####################################################################
507 #
508 # Utility functions
509 #
510 ####################################################################
512 def get_default_SR():
513 return [sr_ref
514 for sr_ref in server.xenapi.SR.get_all()
515 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
517 def get_default_Network():
518 return [network_ref
519 for network_ref in server.xenapi.network.get_all()][0]
521 class XenAPIUnsupportedException(Exception):
522 pass
524 def xenapi_unsupported():
525 if serverType == SERVER_XEN_API:
526 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
528 def xenapi_only():
529 if serverType != SERVER_XEN_API:
530 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
532 def map2sxp(m):
533 return [[k, m[k]] for k in m.keys()]
535 def arg_check(args, name, lo, hi = -1):
536 n = len([i for i in args if i != '--'])
538 if hi == -1:
539 if n != lo:
540 err("'xm %s' requires %d argument%s.\n" % (name, lo,
541 lo == 1 and '' or 's'))
542 usage(name)
543 else:
544 if n < lo or n > hi:
545 err("'xm %s' requires between %d and %d arguments.\n" %
546 (name, lo, hi))
547 usage(name)
550 def unit(c):
551 if not c.isalpha():
552 return 0
553 base = 1
554 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
555 elif c == 'M' or c == 'm': base = 1024 * 1024
556 elif c == 'K' or c == 'k': base = 1024
557 else:
558 print 'ignoring unknown unit'
559 return base
561 def int_unit(str, dest):
562 base = unit(str[-1])
563 if not base:
564 return int(str)
566 value = int(str[:-1])
567 dst_base = unit(dest)
568 if dst_base == 0:
569 dst_base = 1
570 if dst_base > base:
571 return value / (dst_base / base)
572 else:
573 return value * (base / dst_base)
575 def err(msg):
576 print >>sys.stderr, "Error:", msg
579 def get_single_vm(dom):
580 if serverType == SERVER_XEN_API:
581 uuids = server.xenapi.VM.get_by_name_label(dom)
582 if len(uuids) > 0:
583 return uuids[0]
585 refs = []
587 try:
588 domid = int(dom)
589 refs = [vm_ref
590 for vm_ref in server.xenapi.VM.get_all()
591 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
592 except:
593 pass
595 if len(refs) > 0:
596 return refs[0]
598 raise OptionError("Domain '%s' not found." % dom)
599 else:
600 dominfo = server.xend.domain(dom, False)
601 return dominfo['uuid']
603 ##
604 #
605 # Xen-API Shell
606 #
607 ##
609 class Shell(cmd.Cmd):
610 def __init__(self):
611 cmd.Cmd.__init__(self)
612 self.prompt = "xm> "
613 if serverType == SERVER_XEN_API:
614 try:
615 res = server.xenapi.host.list_methods()
616 for f in res:
617 setattr(Shell, 'do_' + f + ' ', self.default)
618 except:
619 pass
621 def preloop(self):
622 cmd.Cmd.preloop(self)
623 import readline
624 readline.set_completer_delims(' ')
626 def default(self, line):
627 words = shlex.split(line)
628 if len(words) > 0 and words[0] == 'xm':
629 words = words[1:]
630 if len(words) > 0:
631 cmd = xm_lookup_cmd(words[0])
632 if cmd:
633 _run_cmd(cmd, words[0], words[1:])
634 elif serverType == SERVER_XEN_API:
635 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
636 tuple(x)),
637 words[0], words[1:])
638 if ok and res is not None and res != '':
639 pprint.pprint(res)
640 else:
641 print '*** Unknown command: %s' % words[0]
642 return False
644 def completedefault(self, text, line, begidx, endidx):
645 words = shlex.split(line[:begidx])
646 clas, func = words[0].split('.')
647 if len(words) > 1 or \
648 func.startswith('get_by_') or \
649 func == 'get_all':
650 return []
651 uuids = server.xenapi_request('%s.get_all' % clas, ())
652 return [u + " " for u in uuids if u.startswith(text)]
654 def emptyline(self):
655 pass
657 def do_EOF(self, line):
658 print
659 sys.exit(0)
661 def do_help(self, line):
662 _usage(line)
665 def xm_shell(args):
666 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
669 def xm_event_monitor(args):
670 if serverType == SERVER_XEN_API:
671 while True:
672 server.xenapi.event.register(args)
673 events = server.xenapi.event.next()
674 for e in events:
675 print e
676 else:
677 err("Event monitoring not supported unless using Xen-API.")
680 #########################################################################
681 #
682 # Main xm functions
683 #
684 #########################################################################
686 def xm_save(args):
688 arg_check(args, "save", 2, 3)
690 try:
691 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
692 except getopt.GetoptError, opterr:
693 err(opterr)
694 sys.exit(1)
696 dom = params[0]
697 savefile = params[1]
699 checkpoint = False
700 for (k, v) in options:
701 if k in ['-c', '--checkpoint']:
702 checkpoint = True
704 if len(params) != 2:
705 err("Wrong number of parameters")
706 usage('save')
707 sys.exit(1)
709 savefile = os.path.abspath(savefile)
711 if not os.access(os.path.dirname(savefile), os.W_OK):
712 err("xm save: Unable to create file %s" % savefile)
713 sys.exit(1)
715 if serverType == SERVER_XEN_API:
716 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
717 else:
718 server.xend.domain.save(dom, savefile, checkpoint)
720 def xm_restore(args):
721 arg_check(args, "restore", 1, 2)
723 try:
724 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
725 except getopt.GetoptError, opterr:
726 err(opterr)
727 usage('restore')
729 paused = False
730 for (k, v) in options:
731 if k in ['-p', '--paused']:
732 paused = True
734 if len(params) != 1:
735 err("Wrong number of parameters")
736 usage('restore')
738 savefile = os.path.abspath(params[0])
740 if not os.access(savefile, os.R_OK):
741 err("xm restore: Unable to read file %s" % savefile)
742 sys.exit(1)
744 try:
745 if serverType == SERVER_XEN_API:
746 server.xenapi.VM.restore(savefile, paused)
747 else:
748 server.xend.domain.restore(savefile, paused)
749 except Exception, ex:
750 err("%s" % ex.faultString)
753 def datetime_to_secs(v):
754 unwanted = ":-."
755 for c in unwanted:
756 v = str(v).replace(c, "")
757 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
759 def getDomains(domain_names, state, full = 0):
760 if serverType == SERVER_XEN_API:
761 doms_sxp = []
762 doms_dict = []
764 dom_recs = server.xenapi.VM.get_all_records()
765 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
767 for dom_ref, dom_rec in dom_recs.items():
768 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
770 states = ('running', 'blocked', 'paused', 'shutdown',
771 'crashed', 'dying')
772 def state_on_off(state):
773 if state in dom_metrics_rec['state']:
774 return state[0]
775 else:
776 return "-"
777 state_str = "".join([state_on_off(state)
778 for state in states])
780 dom_rec.update({'name': dom_rec['name_label'],
781 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
782 'vcpus': dom_metrics_rec['VCPUs_number'],
783 'state': state_str,
784 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
785 'start_time': datetime_to_secs(
786 dom_metrics_rec['start_time'])})
788 doms_sxp.append(['domain'] + map2sxp(dom_rec))
789 doms_dict.append(dom_rec)
791 if domain_names:
792 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
793 if dom["name"] in domain_names]
795 if len(doms) > 0:
796 return doms
797 else:
798 print "Error: no domain%s named %s" % \
799 (len(domain_names) > 1 and 's' or '',
800 ', '.join(domain_names))
801 sys.exit(-1)
802 else:
803 return doms_sxp
804 else:
805 if domain_names:
806 return [server.xend.domain(dom, full) for dom in domain_names]
807 else:
808 return server.xend.domains_with_state(True, state, full)
811 def xm_list(args):
812 use_long = 0
813 show_vcpus = 0
814 show_labels = 0
815 state = 'all'
816 try:
817 (options, params) = getopt.gnu_getopt(args, 'lv',
818 ['long','vcpus','label',
819 'state='])
820 except getopt.GetoptError, opterr:
821 err(opterr)
822 usage('list')
824 for (k, v) in options:
825 if k in ['-l', '--long']:
826 use_long = 1
827 if k in ['-v', '--vcpus']:
828 show_vcpus = 1
829 if k in ['--label']:
830 show_labels = 1
831 if k in ['--state']:
832 state = v
834 if state != 'all' and len(params) > 0:
835 raise OptionError(
836 "You may specify either a state or a particular VM, but not both")
838 if show_vcpus:
839 print >>sys.stderr, (
840 "xm list -v is deprecated. Please use xm vcpu-list.")
841 xm_vcpu_list(params)
842 return
844 doms = getDomains(params, state, use_long)
846 if use_long:
847 map(PrettyPrint.prettyprint, doms)
848 elif show_labels:
849 xm_label_list(doms)
850 else:
851 xm_brief_list(doms)
854 def parse_doms_info(info):
855 def get_info(n, t, d):
856 return t(sxp.child_value(info, n, d))
858 def get_status(n, t, d):
859 return DOM_STATES[t(sxp.child_value(info, n, d))]
861 start_time = get_info('start_time', float, -1)
862 if start_time == -1:
863 up_time = float(-1)
864 else:
865 up_time = time.time() - start_time
867 parsed_info = {
868 'domid' : get_info('domid', str, ''),
869 'name' : get_info('name', str, '??'),
870 'state' : get_info('state', str, ''),
872 # VCPUs is the number online when the VM is up, or the number
873 # configured otherwise.
874 'vcpus' : get_info('online_vcpus', int,
875 get_info('vcpus', int, 0)),
876 'up_time' : up_time
877 }
879 security_label = get_info('security_label', str, '')
880 parsed_info['seclabel'] = security.parse_security_label(security_label)
882 if serverType == SERVER_XEN_API:
883 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
884 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
885 if sum(cpu_times.values()) > 0:
886 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
887 else:
888 parsed_info['cpu_time'] = 0
889 else:
890 parsed_info['mem'] = get_info('memory', int,0)
891 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
893 return parsed_info
895 def check_sched_type(sched):
896 if serverType == SERVER_XEN_API:
897 current = server.xenapi.host.get_sched_policy(
898 server.xenapi.session.get_this_host(server.getSession()))
899 else:
900 current = 'unknown'
901 for x in server.xend.node.info()[1:]:
902 if len(x) > 1 and x[0] == 'xen_scheduler':
903 current = x[1]
904 break
905 if sched != current:
906 err("Xen is running with the %s scheduler" % current)
907 sys.exit(1)
909 def parse_sedf_info(info):
910 def get_info(n, t, d):
911 return t(sxp.child_value(info, n, d))
913 return {
914 'domid' : get_info('domid', int, -1),
915 'period' : get_info('period', int, -1),
916 'slice' : get_info('slice', int, -1),
917 'latency' : get_info('latency', int, -1),
918 'extratime': get_info('extratime', int, -1),
919 'weight' : get_info('weight', int, -1),
920 }
922 def domid_match(domid, info):
923 return domid is None or domid == info['name'] or \
924 domid == str(info['domid'])
926 def xm_brief_list(doms):
927 print '%-40s %5s %5s %5s %10s %9s' % \
928 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
930 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
931 "%(cpu_time)8.1f"
933 for dom in doms:
934 d = parse_doms_info(dom)
935 print format % d
937 def xm_label_list(doms):
938 print '%-40s %5s %5s %5s %10s %9s %-10s' % \
939 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
941 output = []
942 format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
943 '%(cpu_time)8.1f %(seclabel)10s'
945 import xen.util.xsm.xsm as security
947 for dom in doms:
948 d = parse_doms_info(dom)
949 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
950 if not d['seclabel']:
951 d['seclabel'] = ACM_LABEL_UNLABELED_DISPLAY
952 elif security.active_policy in ['DEFAULT']:
953 d['seclabel'] = 'DEFAULT'
954 else:
955 d['seclabel'] = 'INACTIVE'
957 output.append((format % d, d['seclabel']))
959 #sort by labels
960 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
961 for line, label in output:
962 print line
965 def xm_vcpu_list(args):
966 if serverType == SERVER_XEN_API:
967 if args:
968 vm_refs = map(get_single_vm, args)
969 else:
970 vm_refs = server.xenapi.VM.get_all()
972 vm_records = dict(map(lambda vm_ref:
973 (vm_ref, server.xenapi.VM.get_record(
974 vm_ref)),
975 vm_refs))
977 vm_metrics = dict(map(lambda (ref, record):
978 (ref,
979 server.xenapi.VM_metrics.get_record(
980 record['metrics'])),
981 vm_records.items()))
983 dominfo = []
985 # vcpu_list doesn't list 'managed' domains
986 # when they are not running, so filter them out
988 vm_refs = [vm_ref
989 for vm_ref in vm_refs
990 if vm_records[vm_ref]["power_state"] != "Halted"]
992 for vm_ref in vm_refs:
993 info = ['domain',
994 ['domid', vm_records[vm_ref]['domid']],
995 ['name', vm_records[vm_ref]['name_label']],
996 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
998 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
999 def chk_flag(flag):
1000 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1001 and 1 or 0
1003 vcpu_info = ['vcpu',
1004 ['number',
1005 i],
1006 ['online',
1007 chk_flag("online")],
1008 ['blocked',
1009 chk_flag("blocked")],
1010 ['running',
1011 chk_flag("running")],
1012 ['cpu_time',
1013 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1014 ['cpu',
1015 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1016 ['cpumap',
1017 vm_metrics[vm_ref]['VCPUs_params']\
1018 ['cpumap%i' % i].split(",")]]
1020 info.append(vcpu_info)
1022 dominfo.append(info)
1023 else:
1024 if args:
1025 dominfo = map(server.xend.domain.getVCPUInfo, args)
1026 else:
1027 doms = server.xend.domains_with_state(False, 'all', False)
1028 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1030 print '%-32s %5s %5s %5s %5s %9s %s' % \
1031 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1033 format = '%(name)-32s %(domid)5s %(number)5d %(c)5s %(s)5s ' \
1034 ' %(cpu_time)8.1f %(cpumap)s'
1036 for dom in dominfo:
1037 def get_info(n):
1038 return sxp.child_value(dom, n)
1041 # convert a list of integers into a list of pairs indicating
1042 # continuous sequences in the list:
1044 # [0,1,2,3] -> [(0,3)]
1045 # [1,2,4,5] -> [(1,2),(4,5)]
1046 # [0] -> [(0,0)]
1047 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1049 def list_to_rangepairs(cmap):
1050 cmap.sort()
1051 pairs = []
1052 x = y = 0
1053 for i in range(0,len(cmap)):
1054 try:
1055 if ((cmap[y+1] - cmap[i]) > 1):
1056 pairs.append((cmap[x],cmap[y]))
1057 x = y = i+1
1058 else:
1059 y = y + 1
1060 # if we go off the end, then just add x to y
1061 except IndexError:
1062 pairs.append((cmap[x],cmap[y]))
1064 return pairs
1067 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1069 def format_pairs(pairs):
1070 if not pairs:
1071 return "no cpus"
1072 out = ""
1073 for f,s in pairs:
1074 if (f==s):
1075 out += '%d'%f
1076 else:
1077 out += '%d-%d'%(f,s)
1078 out += ','
1079 # trim trailing ','
1080 return out[:-1]
1082 def format_cpumap(cpumap):
1083 cpumap = map(lambda x: int(x), cpumap)
1084 cpumap.sort()
1086 if serverType == SERVER_XEN_API:
1087 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1088 server.xenapi.session.get_this_host(server.getSession())))
1089 else:
1090 for x in server.xend.node.info()[1:]:
1091 if len(x) > 1 and x[0] == 'nr_cpus':
1092 nr_cpus = int(x[1])
1094 # normalize cpumap by modulus nr_cpus, and drop duplicates
1095 cpumap = dict.fromkeys(
1096 map(lambda x: x % nr_cpus, cpumap)).keys()
1097 if len(cpumap) == nr_cpus:
1098 return "any cpu"
1100 return format_pairs(list_to_rangepairs(cpumap))
1102 name = get_info('name')
1103 domid = get_info('domid')
1104 if domid is not None:
1105 domid = str(domid)
1106 else:
1107 domid = ''
1109 for vcpu in sxp.children(dom, 'vcpu'):
1110 def vinfo(n, t):
1111 return t(sxp.child_value(vcpu, n))
1113 number = vinfo('number', int)
1114 cpu = vinfo('cpu', int)
1115 cpumap = format_cpumap(vinfo('cpumap', list))
1116 online = vinfo('online', int)
1117 cpu_time = vinfo('cpu_time', float)
1118 running = vinfo('running', int)
1119 blocked = vinfo('blocked', int)
1121 if cpu < 0:
1122 c = ''
1123 s = ''
1124 elif online:
1125 c = str(cpu)
1126 if running:
1127 s = 'r'
1128 else:
1129 s = '-'
1130 if blocked:
1131 s += 'b'
1132 else:
1133 s += '-'
1134 s += '-'
1135 else:
1136 c = '-'
1137 s = '--p'
1139 print format % locals()
1141 def start_do_console(domain_name):
1142 cpid = os.fork()
1143 if cpid != 0:
1144 for i in range(10):
1145 # Catch failure of the create process
1146 time.sleep(1)
1147 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1148 if os.WIFEXITED(rv):
1149 if os.WEXITSTATUS(rv) != 0:
1150 sys.exit(os.WEXITSTATUS(rv))
1151 try:
1152 # Acquire the console of the created dom
1153 if serverType == SERVER_XEN_API:
1154 domid = server.xenapi.VM.get_domid(
1155 get_single_vm(domain_name))
1156 else:
1157 dom = server.xend.domain(domain_name)
1158 domid = int(sxp.child_value(dom, 'domid', '-1'))
1159 console.execConsole(domid)
1160 except:
1161 pass
1162 print("Could not start console\n");
1163 sys.exit(0)
1165 def xm_start(args):
1167 paused = False
1168 console_autoconnect = False
1170 try:
1171 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused'])
1172 for (k, v) in options:
1173 if k in ('-p', '--paused'):
1174 paused = True
1175 if k in ('-c', '--console_autoconnect'):
1176 console_autoconnect = True
1178 if len(params) != 1:
1179 raise OptionError("Expects 1 argument")
1180 except getopt.GetoptError, opterr:
1181 err(opterr)
1182 usage('start')
1184 dom = params[0]
1186 if console_autoconnect:
1187 start_do_console(dom)
1189 try:
1190 if serverType == SERVER_XEN_API:
1191 server.xenapi.VM.start(get_single_vm(dom), paused)
1192 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1193 else:
1194 server.xend.domain.start(dom, paused)
1195 info = server.xend.domain(dom)
1196 domid = int(sxp.child_value(info, 'domid', '-1'))
1197 except:
1198 raise
1200 if domid == -1:
1201 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1203 def xm_delete(args):
1204 arg_check(args, "delete", 1)
1205 dom = args[0]
1206 if serverType == SERVER_XEN_API:
1207 server.xenapi.VM.destroy(get_single_vm(dom))
1208 else:
1209 server.xend.domain.delete(dom)
1211 def xm_suspend(args):
1212 arg_check(args, "suspend", 1)
1213 dom = args[0]
1214 if serverType == SERVER_XEN_API:
1215 server.xenapi.VM.suspend(get_single_vm(dom))
1216 else:
1217 server.xend.domain.suspend(dom)
1219 def xm_resume(args):
1220 arg_check(args, "resume", 1, 2)
1222 try:
1223 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1224 except getopt.GetoptError, opterr:
1225 err(opterr)
1226 usage('resume')
1228 paused = False
1229 for (k, v) in options:
1230 if k in ['-p', '--paused']:
1231 paused = True
1233 if len(params) != 1:
1234 err("Wrong number of parameters")
1235 usage('resume')
1237 dom = params[0]
1238 if serverType == SERVER_XEN_API:
1239 server.xenapi.VM.resume(get_single_vm(dom), paused)
1240 else:
1241 server.xend.domain.resume(dom, paused)
1243 def xm_reboot(args):
1244 arg_check(args, "reboot", 1, 3)
1245 from xen.xm import shutdown
1246 shutdown.main(["shutdown", "-R"] + args)
1248 def xm_shutdown(args):
1249 arg_check(args, "shutdown", 1, 4)
1250 from xen.xm import shutdown
1251 shutdown.main(["shutdown"] + args)
1253 def xm_pause(args):
1254 arg_check(args, "pause", 1)
1255 dom = args[0]
1257 if serverType == SERVER_XEN_API:
1258 server.xenapi.VM.pause(get_single_vm(dom))
1259 else:
1260 server.xend.domain.pause(dom)
1262 def xm_unpause(args):
1263 arg_check(args, "unpause", 1)
1264 dom = args[0]
1266 if serverType == SERVER_XEN_API:
1267 server.xenapi.VM.unpause(get_single_vm(dom))
1268 else:
1269 server.xend.domain.unpause(dom)
1271 def xm_dump_core(args):
1272 live = False
1273 crash = False
1274 try:
1275 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1276 for (k, v) in options:
1277 if k in ('-L', '--live'):
1278 live = True
1279 if k in ('-C', '--crash'):
1280 crash = True
1282 if len(params) not in (1, 2):
1283 raise OptionError("Expects 1 or 2 argument(s)")
1284 except getopt.GetoptError, e:
1285 raise OptionError(str(e))
1287 dom = params[0]
1288 if len(params) == 2:
1289 filename = os.path.abspath(params[1])
1290 else:
1291 filename = None
1293 if not live:
1294 ds = server.xend.domain.pause(dom, True)
1296 try:
1297 print "Dumping core of domain: %s ..." % str(dom)
1298 server.xend.domain.dump(dom, filename, live, crash)
1299 finally:
1300 if not live and ds == DOM_STATE_RUNNING:
1301 server.xend.domain.unpause(dom)
1303 if crash:
1304 print "Destroying domain: %s ..." % str(dom)
1305 server.xend.domain.destroy(dom)
1307 def xm_rename(args):
1308 arg_check(args, "rename", 2)
1310 if serverType == SERVER_XEN_API:
1311 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1312 else:
1313 server.xend.domain.setName(args[0], args[1])
1315 def xm_importcommand(command, args):
1316 cmd = __import__(command, globals(), locals(), 'xen.xm')
1317 cmd.main([command] + args)
1320 #############################################################
1322 def xm_vcpu_pin(args):
1323 arg_check(args, "vcpu-pin", 3)
1325 def cpu_make_map(cpulist):
1326 cpus = []
1327 for c in cpulist.split(','):
1328 if c.find('-') != -1:
1329 (x,y) = c.split('-')
1330 for i in range(int(x),int(y)+1):
1331 cpus.append(int(i))
1332 else:
1333 # remove this element from the list
1334 if c[0] == '^':
1335 cpus = [x for x in cpus if x != int(c[1:])]
1336 else:
1337 cpus.append(int(c))
1338 cpus.sort()
1339 return cpus
1341 dom = args[0]
1342 vcpu = args[1]
1343 if args[2] == 'all':
1344 cpumap = cpu_make_map('0-63')
1345 else:
1346 cpumap = cpu_make_map(args[2])
1348 if serverType == SERVER_XEN_API:
1349 cpumap = map(str, cpumap)
1350 server.xenapi.VM.add_to_VCPUs_params_live(
1351 get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap))
1352 else:
1353 server.xend.domain.pincpu(dom, vcpu, cpumap)
1355 def xm_mem_max(args):
1356 arg_check(args, "mem-max", 2)
1358 dom = args[0]
1360 if serverType == SERVER_XEN_API:
1361 mem = int_unit(args[1], 'k') * 1024
1362 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1363 else:
1364 mem = int_unit(args[1], 'm')
1365 server.xend.domain.maxmem_set(dom, mem)
1367 def xm_mem_set(args):
1368 arg_check(args, "mem-set", 2)
1370 dom = args[0]
1372 if serverType == SERVER_XEN_API:
1373 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1374 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1375 mem_target)
1376 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1377 mem_target)
1378 else:
1379 mem_target = int_unit(args[1], 'm')
1380 server.xend.domain.setMemoryTarget(dom, mem_target)
1382 def xm_vcpu_set(args):
1383 arg_check(args, "vcpu-set", 2)
1385 dom = args[0]
1386 vcpus = int(args[1])
1388 if serverType == SERVER_XEN_API:
1389 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1390 else:
1391 server.xend.domain.setVCpuCount(dom, vcpus)
1393 def xm_destroy(args):
1394 arg_check(args, "destroy", 1)
1396 dom = args[0]
1398 if serverType == SERVER_XEN_API:
1399 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1400 else:
1401 server.xend.domain.destroy(dom)
1403 def xm_domid(args):
1404 arg_check(args, "domid", 1)
1406 name = args[0]
1408 if serverType == SERVER_XEN_API:
1409 print server.xenapi.VM.get_domid(get_single_vm(name))
1410 else:
1411 dom = server.xend.domain(name)
1412 print sxp.child_value(dom, 'domid')
1414 def xm_domname(args):
1415 arg_check(args, "domname", 1)
1417 name = args[0]
1419 if serverType == SERVER_XEN_API:
1420 print server.xenapi.VM.get_name_label(get_single_vm(name))
1421 else:
1422 dom = server.xend.domain(name)
1423 print sxp.child_value(dom, 'name')
1425 def xm_sched_sedf(args):
1426 xenapi_unsupported()
1428 def ns_to_ms(val):
1429 return float(val) * 0.000001
1431 def ms_to_ns(val):
1432 return (float(val) / 0.000001)
1434 def print_sedf(info):
1435 info['period'] = ns_to_ms(info['period'])
1436 info['slice'] = ns_to_ms(info['slice'])
1437 info['latency'] = ns_to_ms(info['latency'])
1438 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1439 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1441 check_sched_type('sedf')
1443 # we want to just display current info if no parameters are passed
1444 if len(args) == 0:
1445 domid = None
1446 else:
1447 # we expect at least a domain id (name or number)
1448 # and at most a domid up to 5 options with values
1449 arg_check(args, "sched-sedf", 1, 11)
1450 domid = args[0]
1451 # drop domid from args since get_opt doesn't recognize it
1452 args = args[1:]
1454 opts = {}
1455 try:
1456 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1457 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1458 except getopt.GetoptError, opterr:
1459 err(opterr)
1460 usage('sched-sedf')
1462 # convert to nanoseconds if needed
1463 for (k, v) in options:
1464 if k in ['-p', '--period']:
1465 opts['period'] = ms_to_ns(v)
1466 elif k in ['-s', '--slice']:
1467 opts['slice'] = ms_to_ns(v)
1468 elif k in ['-l', '--latency']:
1469 opts['latency'] = ms_to_ns(v)
1470 elif k in ['-e', '--extratime']:
1471 opts['extratime'] = v
1472 elif k in ['-w', '--weight']:
1473 opts['weight'] = v
1475 doms = filter(lambda x : domid_match(domid, x),
1476 [parse_doms_info(dom)
1477 for dom in getDomains(None, 'running')])
1478 if domid is not None and doms == []:
1479 err("Domain '%s' does not exist." % domid)
1480 usage('sched-sedf')
1482 # print header if we aren't setting any parameters
1483 if len(opts.keys()) == 0:
1484 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1485 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1486 'Extra','Weight')
1488 for d in doms:
1489 # fetch current values so as not to clobber them
1490 try:
1491 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1492 except xmlrpclib.Fault:
1493 # domain does not support sched-sedf?
1494 sedf_raw = {}
1496 sedf_info = parse_sedf_info(sedf_raw)
1497 sedf_info['name'] = d['name']
1498 # update values in case of call to set
1499 if len(opts.keys()) > 0:
1500 for k in opts.keys():
1501 sedf_info[k]=opts[k]
1503 # send the update, converting user input
1504 v = map(int, [sedf_info['period'], sedf_info['slice'],
1505 sedf_info['latency'],sedf_info['extratime'],
1506 sedf_info['weight']])
1507 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1508 if int(rv) != 0:
1509 err("Failed to set sedf parameters (rv=%d)."%(rv))
1511 # not setting values, display info
1512 else:
1513 print_sedf(sedf_info)
1515 def xm_sched_credit(args):
1516 """Get/Set options for Credit Scheduler."""
1518 check_sched_type('credit')
1520 try:
1521 opts, params = getopt.getopt(args, "d:w:c:",
1522 ["domain=", "weight=", "cap="])
1523 except getopt.GetoptError, opterr:
1524 err(opterr)
1525 usage('sched-credit')
1527 domid = None
1528 weight = None
1529 cap = None
1531 for o, a in opts:
1532 if o in ["-d", "--domain"]:
1533 domid = a
1534 elif o in ["-w", "--weight"]:
1535 weight = int(a)
1536 elif o in ["-c", "--cap"]:
1537 cap = int(a);
1539 doms = filter(lambda x : domid_match(domid, x),
1540 [parse_doms_info(dom)
1541 for dom in getDomains(None, 'all')])
1543 if weight is None and cap is None:
1544 if domid is not None and doms == []:
1545 err("Domain '%s' does not exist." % domid)
1546 usage('sched-credit')
1547 # print header if we aren't setting any parameters
1548 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1550 for d in doms:
1551 try:
1552 if serverType == SERVER_XEN_API:
1553 info = server.xenapi.VM_metrics.get_VCPUs_params(
1554 server.xenapi.VM.get_metrics(
1555 get_single_vm(d['name'])))
1556 else:
1557 info = server.xend.domain.sched_credit_get(d['name'])
1558 except xmlrpclib.Fault:
1559 pass
1561 if 'weight' not in info or 'cap' not in info:
1562 # domain does not support sched-credit?
1563 info = {'weight': -1, 'cap': -1}
1565 info['weight'] = int(info['weight'])
1566 info['cap'] = int(info['cap'])
1568 info['name'] = d['name']
1569 info['domid'] = str(d['domid'])
1570 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1571 else:
1572 if domid is None:
1573 # place holder for system-wide scheduler parameters
1574 err("No domain given.")
1575 usage('sched-credit')
1577 if serverType == SERVER_XEN_API:
1578 if doms[0]['domid']:
1579 server.xenapi.VM.add_to_VCPUs_params_live(
1580 get_single_vm(domid),
1581 "weight",
1582 weight)
1583 server.xenapi.VM.add_to_VCPUs_params_live(
1584 get_single_vm(domid),
1585 "cap",
1586 cap)
1587 else:
1588 server.xenapi.VM.add_to_VCPUs_params(
1589 get_single_vm(domid),
1590 "weight",
1591 weight)
1592 server.xenapi.VM.add_to_VCPUs_params(
1593 get_single_vm(domid),
1594 "cap",
1595 cap)
1596 else:
1597 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1598 if result != 0:
1599 err(str(result))
1601 def xm_info(args):
1602 arg_check(args, "info", 0, 1)
1604 try:
1605 (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
1606 except getopt.GetoptError, opterr:
1607 err(opterr)
1608 usage('info')
1610 show_xend_config = 0
1611 for (k, v) in options:
1612 if k in ['-c', '--config']:
1613 show_xend_config = 1
1615 if show_xend_config:
1616 for name, obj in inspect.getmembers(xoptions):
1617 if not inspect.ismethod(obj):
1618 if name == "config":
1619 for x in obj[1:]:
1620 if len(x) < 2:
1621 print "%-38s: (none)" % x[0]
1622 else:
1623 print "%-38s:" % x[0], x[1]
1624 else:
1625 print "%-38s:" % name, obj
1626 return
1628 if serverType == SERVER_XEN_API:
1630 # Need to fake out old style xm info as people rely on parsing it
1632 host_record = server.xenapi.host.get_record(
1633 server.xenapi.session.get_this_host(server.getSession()))
1635 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1637 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1639 def getVal(keys, default=""):
1640 data = host_record
1641 for key in keys:
1642 if key in data:
1643 data = data[key]
1644 else:
1645 return default
1646 return data
1648 def getCpuMhz():
1649 cpu_speeds = [int(host_cpu_record["speed"])
1650 for host_cpu_record in host_cpu_records
1651 if "speed" in host_cpu_record]
1652 if len(cpu_speeds) > 0:
1653 return sum(cpu_speeds) / len(cpu_speeds)
1654 else:
1655 return 0
1657 getCpuMhz()
1659 def getCpuFeatures():
1660 if len(host_cpu_records) > 0:
1661 return host_cpu_records[0].get("features", "")
1662 else:
1663 return ""
1665 info = {
1666 "host": getVal(["name_label"]),
1667 "release": getVal(["software_version", "release"]),
1668 "version": getVal(["software_version", "version"]),
1669 "machine": getVal(["software_version", "machine"]),
1670 "nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
1671 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1672 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1673 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1674 "cpu_mhz": getCpuMhz(),
1675 "hw_caps": getCpuFeatures(),
1676 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1677 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1678 "xen_major": getVal(["software_version", "xen_major"]),
1679 "xen_minor": getVal(["software_version", "xen_minor"]),
1680 "xen_extra": getVal(["software_version", "xen_extra"]),
1681 "xen_caps": " ".join(getVal(["capabilities"], [])),
1682 "xen_scheduler": getVal(["sched_policy"]),
1683 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1684 "platform_params": getVal(["other_config", "platform_params"]),
1685 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1686 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1687 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1688 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1689 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1690 "xend_config_format":getVal(["software_version", "xend_config_format"])
1693 sorted = info.items()
1694 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1696 for (k, v) in sorted:
1697 print "%-23s:" % k, v
1698 else:
1699 info = server.xend.node.info()
1700 for x in info[1:]:
1701 if len(x) < 2:
1702 print "%-23s: (none)" % x[0]
1703 else:
1704 print "%-23s:" % x[0], x[1]
1706 def xm_console(args):
1707 arg_check(args, "console", 1, 2)
1709 quiet = False;
1711 try:
1712 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1713 except getopt.GetoptError, opterr:
1714 err(opterr)
1715 usage('console')
1717 for (k, v) in options:
1718 if k in ['-q', '--quiet']:
1719 quiet = True
1720 else:
1721 assert False
1723 if len(params) != 1:
1724 err('No domain given')
1725 usage('console')
1727 dom = params[0]
1729 try:
1730 if serverType == SERVER_XEN_API:
1731 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1732 else:
1733 info = server.xend.domain(dom)
1734 domid = int(sxp.child_value(info, 'domid', '-1'))
1735 except:
1736 if quiet:
1737 sys.exit(1)
1738 else:
1739 raise
1741 if domid == -1:
1742 if quiet:
1743 sys.exit(1)
1744 else:
1745 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1747 console.execConsole(domid)
1750 def xm_uptime(args):
1751 short_mode = 0
1753 try:
1754 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1755 except getopt.GetoptError, opterr:
1756 err(opterr)
1757 usage('uptime')
1759 for (k, v) in options:
1760 if k in ['-s', '--short']:
1761 short_mode = 1
1763 doms = getDomains(params, 'all')
1765 if short_mode == 0:
1766 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1768 for dom in doms:
1769 d = parse_doms_info(dom)
1770 if d['domid'] == '':
1771 uptime = 0
1772 elif int(d['domid']) > 0:
1773 uptime = int(round(d['up_time']))
1774 else:
1775 f=open('/proc/uptime', 'r')
1776 upfile = f.read()
1777 uptime = int(round(float(upfile.split(' ')[0])))
1778 f.close()
1780 days = int(uptime / 86400)
1781 uptime -= (days * 86400)
1782 hours = int(uptime / 3600)
1783 uptime -= (hours * 3600)
1784 minutes = int(uptime / 60)
1785 uptime -= (minutes * 60)
1786 seconds = uptime
1788 upstring = ""
1789 if days > 0:
1790 upstring += str(days) + " day"
1791 if days > 1:
1792 upstring += "s"
1793 upstring += ", "
1794 upstring += '%(hours)2d:%(minutes)02d' % vars()
1796 if short_mode:
1797 now = datetime.datetime.now()
1798 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1799 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1800 else:
1801 upstring += ':%(seconds)02d' % vars()
1802 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1804 print upstring
1806 def xm_sysrq(args):
1807 arg_check(args, "sysrq", 2)
1808 dom = args[0]
1809 req = args[1]
1810 if serverType == SERVER_XEN_API:
1811 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1812 else:
1813 server.xend.domain.send_sysrq(dom, req)
1815 def xm_trigger(args):
1816 vcpu = 0
1818 arg_check(args, "trigger", 2, 3)
1819 dom = args[0]
1820 trigger = args[1]
1821 if len(args) == 3:
1822 vcpu = int(args[2])
1824 if serverType == SERVER_XEN_API:
1825 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1826 else:
1827 server.xend.domain.send_trigger(dom, trigger, vcpu)
1829 def xm_debug_keys(args):
1830 arg_check(args, "debug-keys", 1)
1832 keys = str(args[0])
1834 if serverType == SERVER_XEN_API:
1835 server.xenapi.host.send_debug_keys(
1836 server.xenapi.session.get_this_host(server.getSession()),
1837 keys)
1838 else:
1839 server.xend.node.send_debug_keys(keys)
1841 def xm_top(args):
1842 arg_check(args, "top", 0)
1844 os.execvp('xentop', ['xentop'])
1846 def xm_dmesg(args):
1847 arg_check(args, "dmesg", 0, 1)
1849 try:
1850 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1851 except getopt.GetoptError, opterr:
1852 err(opterr)
1853 usage('dmesg')
1855 use_clear = 0
1856 for (k, v) in options:
1857 if k in ['-c', '--clear']:
1858 use_clear = 1
1860 if len(params) :
1861 err("No parameter required")
1862 usage('dmesg')
1864 if serverType == SERVER_XEN_API:
1865 host = server.xenapi.session.get_this_host(server.getSession())
1866 if use_clear:
1867 print server.xenapi.host.dmesg_clear(host),
1868 else:
1869 print server.xenapi.host.dmesg(host),
1870 else:
1871 if not use_clear:
1872 print server.xend.node.dmesg.info(),
1873 else:
1874 print server.xend.node.dmesg.clear(),
1876 def xm_log(args):
1877 arg_check(args, "log", 0)
1879 if serverType == SERVER_XEN_API:
1880 print server.xenapi.host.get_log(
1881 server.xenapi.session.get_this_host(server.getSession()))
1882 else:
1883 print server.xend.node.log()
1885 def xm_serve(args):
1886 if serverType == SERVER_XEN_API:
1887 print "Not supported with XenAPI"
1888 sys.exit(-1)
1890 arg_check(args, "serve", 0)
1892 from fcntl import fcntl, F_SETFL
1894 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1895 s.connect(XendClient.XML_RPC_SOCKET)
1896 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1898 while True:
1899 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1900 if s in iwtd:
1901 data = s.recv(4096)
1902 if len(data) > 0:
1903 sys.stdout.write(data)
1904 sys.stdout.flush()
1905 else:
1906 break
1907 if sys.stdin in iwtd:
1908 data = sys.stdin.read(4096)
1909 if len(data) > 0:
1910 s.sendall(data)
1911 else:
1912 break
1913 s.close()
1915 def parse_dev_info(info):
1916 def get_info(n, t, d):
1917 i = 0
1918 while i < len(info):
1919 if (info[i][0] == n):
1920 return t(info[i][1])
1921 i = i + 1
1922 return t(d)
1923 return {
1924 #common
1925 'backend-id' : get_info('backend-id', int, -1),
1926 'handle' : get_info('handle', int, 0),
1927 'state' : get_info('state', int, -1),
1928 'be-path' : get_info('backend', str, '??'),
1929 'event-ch' : get_info('event-channel',int, -1),
1930 #network specific
1931 'virtual-device' : get_info('virtual-device', str, '??'),
1932 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1933 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1934 'mac' : get_info('mac', str, '??'),
1935 #block-device specific
1936 'ring-ref' : get_info('ring-ref', int, -1),
1939 def arg_check_for_resource_list(args, name):
1940 use_long = 0
1941 try:
1942 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1943 except getopt.GetoptError, opterr:
1944 err(opterr)
1945 sys.exit(1)
1947 for (k, v) in options:
1948 if k in ['-l', '--long']:
1949 use_long = 1
1951 if len(params) == 0:
1952 print 'No domain parameter given'
1953 usage(name)
1954 if len(params) > 1:
1955 print 'No multiple domain parameters allowed'
1956 usage(name)
1958 return (use_long, params)
1960 def xm_network_list(args):
1961 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1963 dom = params[0]
1965 if serverType == SERVER_XEN_API:
1966 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1967 vif_properties = \
1968 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1969 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
1970 zip(range(len(vif_properties)), vif_properties))
1971 else:
1972 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1974 if use_long:
1975 map(PrettyPrint.prettyprint, devs)
1976 else:
1977 hdr = 0
1978 for x in devs:
1979 if hdr == 0:
1980 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1981 hdr = 1
1982 ni = parse_dev_info(x[1])
1983 ni['idx'] = int(x[0])
1984 print ("%(idx)-3d "
1985 "%(backend-id)-3d"
1986 "%(mac)-17s "
1987 "%(handle)-3d "
1988 "%(state)-3d "
1989 "%(event-ch)-3d "
1990 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1991 "%(be-path)-30s "
1992 % ni)
1994 def xm_block_list(args):
1995 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1997 dom = params[0]
1999 if serverType == SERVER_XEN_API:
2000 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2001 vbd_properties = \
2002 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
2003 vbd_devs = \
2004 map(server.xenapi.VBD.get_device, vbd_refs)
2005 vbd_devids = \
2006 map(blkdev_name_to_number, vbd_devs)
2007 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
2008 zip(vbd_devids, vbd_properties))
2009 else:
2010 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
2012 if use_long:
2013 map(PrettyPrint.prettyprint, devs)
2014 else:
2015 hdr = 0
2016 for x in devs:
2017 if hdr == 0:
2018 print 'Vdev BE handle state evt-ch ring-ref BE-path'
2019 hdr = 1
2020 ni = parse_dev_info(x[1])
2021 ni['idx'] = int(x[0])
2022 print ("%(idx)-3d "
2023 "%(backend-id)-3d "
2024 "%(handle)-3d "
2025 "%(state)-3d "
2026 "%(event-ch)-3d "
2027 "%(ring-ref)-5d "
2028 "%(be-path)-30s "
2029 % ni)
2031 def xm_vtpm_list(args):
2032 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2034 dom = params[0]
2036 if serverType == SERVER_XEN_API:
2037 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2038 vtpm_properties = \
2039 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2040 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2041 zip(range(len(vtpm_properties)), vtpm_properties))
2042 else:
2043 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2045 if use_long:
2046 map(PrettyPrint.prettyprint, devs)
2047 else:
2048 hdr = 0
2049 for x in devs:
2050 if hdr == 0:
2051 print 'Idx BE handle state evt-ch ring-ref BE-path'
2052 hdr = 1
2053 ni = parse_dev_info(x[1])
2054 ni['idx'] = int(x[0])
2055 print ("%(idx)-3d "
2056 "%(backend-id)-3d "
2057 "%(handle)-3d "
2058 "%(state)-3d "
2059 "%(event-ch)-3d "
2060 "%(ring-ref)-5d "
2061 "%(be-path)-30s "
2062 % ni)
2065 def parse_block_configuration(args):
2066 dom = args[0]
2068 if args[1].startswith('tap:'):
2069 cls = 'tap'
2070 else:
2071 cls = 'vbd'
2073 vbd = [cls,
2074 ['uname', args[1]],
2075 ['dev', args[2]],
2076 ['mode', args[3]]]
2077 if len(args) == 5:
2078 vbd.append(['backend', args[4]])
2080 return (dom, vbd)
2083 def xm_block_attach(args):
2084 arg_check(args, 'block-attach', 4, 5)
2086 if serverType == SERVER_XEN_API:
2087 dom = args[0]
2088 uname = args[1]
2089 dev = args[2]
2090 mode = args[3]
2092 # First create new VDI
2093 vdi_record = {
2094 "name_label": "vdi" + str(uname.__hash__()),
2095 "name_description": "",
2096 "SR": get_default_SR(),
2097 "virtual_size": 0,
2098 "sector_size": 512,
2099 "type": "system",
2100 "sharable": False,
2101 "read_only": mode!="w",
2102 "other_config": {"location": uname}
2105 vdi_ref = server.xenapi.VDI.create(vdi_record)
2107 # Now create new VBD
2109 vbd_record = {
2110 "VM": get_single_vm(dom),
2111 "VDI": vdi_ref,
2112 "device": dev,
2113 "bootable": True,
2114 "mode": mode=="w" and "RW" or "RO",
2115 "type": "Disk",
2116 "qos_algorithm_type": "",
2117 "qos_algorithm_params": {}
2120 server.xenapi.VBD.create(vbd_record)
2122 else:
2123 (dom, vbd) = parse_block_configuration(args)
2124 server.xend.domain.device_create(dom, vbd)
2127 def xm_block_configure(args):
2128 arg_check(args, 'block-configure', 4, 5)
2130 (dom, vbd) = parse_block_configuration(args)
2131 server.xend.domain.device_configure(dom, vbd)
2134 def xm_network_attach(args):
2135 arg_check(args, 'network-attach', 1, 11)
2137 dom = args[0]
2138 vif = ['vif']
2139 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2140 'backend', 'vifname', 'rate', 'model', 'accel']
2142 if serverType == SERVER_XEN_API:
2143 vif_record = {
2144 "device": "eth0",
2145 "network": get_default_Network(),
2146 "VM": get_single_vm(dom),
2147 "MAC": "",
2148 "MTU": "",
2149 "qos_algorithm_type": "",
2150 "qos_algorithm_params": {},
2151 "other_config": {}
2154 def set(keys, val):
2155 record = vif_record
2156 for key in keys[:-1]:
2157 record = record[key]
2158 record[keys[-1]] = val
2160 def get_net_from_bridge(bridge):
2161 # In OSS, we just assert network.name_label == bridge name
2162 networks = dict([(record['name_label'], ref)
2163 for ref, record in server.xenapi.network
2164 .get_all_records().items()])
2165 if bridge not in networks.keys():
2166 raise "Unknown bridge name!"
2167 return networks[bridge]
2169 vif_conv = {
2170 'type':
2171 lambda x: None,
2172 'mac':
2173 lambda x: set(['MAC'], x),
2174 'bridge':
2175 lambda x: set(['network'], get_net_from_bridge(x)),
2176 'ip':
2177 lambda x: set(['other_config', 'ip'], x),
2178 'script':
2179 lambda x: set(['other_config', 'script'], x),
2180 'backend':
2181 lambda x: set(['other_config', 'backend'], x),
2182 'vifname':
2183 lambda x: set(['device'], x),
2184 'rate':
2185 lambda x: set(['qos_algorithm_params', 'rate'], x),
2186 'model':
2187 lambda x: None,
2188 'accel':
2189 lambda x: set(['other_config', 'accel'], x)
2192 for a in args[1:]:
2193 vif_param = a.split("=")
2194 if len(vif_param) != 2 or vif_param[1] == '' or \
2195 vif_param[0] not in vif_params:
2196 err("Invalid argument: %s" % a)
2197 usage('network-attach')
2198 else:
2199 vif_conv[vif_param[0]](vif_param[1])
2201 server.xenapi.VIF.create(vif_record)
2202 else:
2203 for a in args[1:]:
2204 vif_param = a.split("=")
2205 if len(vif_param) != 2 or vif_param[1] == '' or \
2206 vif_param[0] not in vif_params:
2207 err("Invalid argument: %s" % a)
2208 usage('network-attach')
2209 vif.append(vif_param)
2210 server.xend.domain.device_create(dom, vif)
2213 def detach(args, deviceClass):
2214 rm_cfg = True
2215 dom = args[0]
2216 dev = args[1]
2217 try:
2218 force = args[2]
2219 if (force != "--force") and (force != "-f"):
2220 print "Ignoring option %s"%(force)
2221 force = None
2222 except IndexError:
2223 force = None
2225 server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
2228 def xm_block_detach(args):
2229 if serverType == SERVER_XEN_API:
2230 arg_check(args, "xm_block_detach", 2, 3)
2231 dom = args[0]
2232 dev = args[1]
2233 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2234 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2235 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2236 if len(vbd_refs) > 0:
2237 vbd_ref = vbd_refs[0]
2238 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2240 server.xenapi.VBD.destroy(vbd_ref)
2242 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2243 server.xenapi.VDI.destroy(vdi_ref)
2244 else:
2245 raise OptionError("Cannot find device '%s' in domain '%s'"
2246 % (dev,dom))
2247 else:
2248 arg_check(args, 'block-detach', 2, 3)
2249 dom = args[0]
2250 dev = args[1]
2251 dc = server.xend.domain.getBlockDeviceClass(dom, dev)
2252 if dc == "tap":
2253 detach(args, 'tap')
2254 else:
2255 detach(args, 'vbd')
2257 def xm_network_detach(args):
2258 if serverType == SERVER_XEN_API:
2259 arg_check(args, "xm_network_detach", 2, 3)
2260 dom = args[0]
2261 devid = args[1]
2262 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2263 vif_refs = [vif_ref for vif_ref in vif_refs
2264 if server.xenapi.VIF.\
2265 get_runtime_properties(vif_ref)["handle"] == devid]
2266 if len(vif_refs) > 0:
2267 vif_ref = vif_refs[0]
2269 server.xenapi.VIF.destroy(vif_ref)
2270 else:
2271 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2272 else:
2273 arg_check(args, 'network-detach', 2, 3)
2274 detach(args, 'vif')
2277 def xm_vnet_list(args):
2278 xenapi_unsupported()
2279 try:
2280 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2281 except getopt.GetoptError, opterr:
2282 err(opterr)
2283 usage('vnet-list')
2285 use_long = 0
2286 for (k, v) in options:
2287 if k in ['-l', '--long']:
2288 use_long = 1
2290 if params:
2291 use_long = 1
2292 vnets = params
2293 else:
2294 vnets = server.xend_vnets()
2296 for vnet in vnets:
2297 try:
2298 if use_long:
2299 info = server.xend_vnet(vnet)
2300 PrettyPrint.prettyprint(info)
2301 else:
2302 print vnet
2303 except Exception, ex:
2304 print vnet, ex
2306 def xm_vnet_create(args):
2307 xenapi_unsupported()
2308 arg_check(args, "vnet-create", 1)
2309 conf = args[0]
2310 if not os.access(conf, os.R_OK):
2311 print "File not found: %s" % conf
2312 sys.exit(1)
2314 server.xend_vnet_create(conf)
2316 def xm_vnet_delete(args):
2317 xenapi_unsupported()
2318 arg_check(args, "vnet-delete", 1)
2319 vnet = args[0]
2320 server.xend_vnet_delete(vnet)
2322 def xm_network_new(args):
2323 xenapi_only()
2324 arg_check(args, "network-new", 1)
2325 network = args[0]
2327 record = {
2328 "name_label": network,
2329 "name_description": "",
2330 "other_config": {},
2331 "default_gateway": "",
2332 "default_netmask": ""
2335 server.xenapi.network.create(record)
2337 def xm_network_del(args):
2338 xenapi_only()
2339 arg_check(args, "network-del", 1)
2340 network = args[0]
2342 networks = dict([(record['name_label'], ref)
2343 for ref, record in
2344 server.xenapi.network.get_all_records().items()])
2346 if network not in networks.keys():
2347 raise ValueError("'%s' is not a valid network name" % network)
2349 server.xenapi.network.destroy(networks[network])
2351 def xm_network_show(args):
2352 xenapi_only()
2353 arg_check(args, "network-show", 0)
2355 networks = server.xenapi.network.get_all_records()
2356 pifs = server.xenapi.PIF.get_all_records()
2357 vifs = server.xenapi.VIF.get_all_records()
2359 print '%-20s %-40s %-10s' % \
2360 ('Name', 'VIFs', 'PIFs')
2362 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2364 for network_ref, network in networks.items():
2365 for i in range(max(len(network['PIFs']),
2366 len(network['VIFs']), 1)):
2367 if i < len(network['PIFs']):
2368 pif_uuid = network['PIFs'][i]
2369 else:
2370 pif_uuid = None
2372 if i < len(network['VIFs']):
2373 vif_uuid = network['VIFs'][i]
2374 else:
2375 vif_uuid = None
2377 pif = pifs.get(pif_uuid, None)
2378 vif = vifs.get(vif_uuid, None)
2380 if vif:
2381 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2382 vif = "%s.%s" % (dom_name, vif['device'])
2383 else:
2384 vif = ''
2386 if pif:
2387 if int(pif['VLAN']) > -1:
2388 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2389 else:
2390 pif = pif['device']
2391 else:
2392 pif = ''
2394 if i == 0:
2395 r = {'name_label':network['name_label'],
2396 'vif':vif, 'pif':pif}
2397 else:
2398 r = {'name_label':'', 'vif':vif, 'pif':pif}
2400 print format2 % r
2403 commands = {
2404 "shell": xm_shell,
2405 "event-monitor": xm_event_monitor,
2406 # console commands
2407 "console": xm_console,
2408 # xenstat commands
2409 "top": xm_top,
2410 # domain commands
2411 "delete": xm_delete,
2412 "destroy": xm_destroy,
2413 "domid": xm_domid,
2414 "domname": xm_domname,
2415 "dump-core": xm_dump_core,
2416 "reboot": xm_reboot,
2417 "rename": xm_rename,
2418 "restore": xm_restore,
2419 "resume": xm_resume,
2420 "save": xm_save,
2421 "shutdown": xm_shutdown,
2422 "start": xm_start,
2423 "sysrq": xm_sysrq,
2424 "trigger": xm_trigger,
2425 "uptime": xm_uptime,
2426 "suspend": xm_suspend,
2427 "list": xm_list,
2428 # memory commands
2429 "mem-max": xm_mem_max,
2430 "mem-set": xm_mem_set,
2431 # cpu commands
2432 "vcpu-pin": xm_vcpu_pin,
2433 "vcpu-list": xm_vcpu_list,
2434 "vcpu-set": xm_vcpu_set,
2435 # special
2436 "pause": xm_pause,
2437 "unpause": xm_unpause,
2438 # host commands
2439 "debug-keys": xm_debug_keys,
2440 "dmesg": xm_dmesg,
2441 "info": xm_info,
2442 "log": xm_log,
2443 "serve": xm_serve,
2444 # scheduler
2445 "sched-sedf": xm_sched_sedf,
2446 "sched-credit": xm_sched_credit,
2447 # block
2448 "block-attach": xm_block_attach,
2449 "block-detach": xm_block_detach,
2450 "block-list": xm_block_list,
2451 "block-configure": xm_block_configure,
2452 # network (AKA vifs)
2453 "network-attach": xm_network_attach,
2454 "network-detach": xm_network_detach,
2455 "network-list": xm_network_list,
2456 # network (as in XenAPI)
2457 "network-new": xm_network_new,
2458 "network-del": xm_network_del,
2459 "network-show": xm_network_show,
2460 # vnet
2461 "vnet-list": xm_vnet_list,
2462 "vnet-create": xm_vnet_create,
2463 "vnet-delete": xm_vnet_delete,
2464 # vtpm
2465 "vtpm-list": xm_vtpm_list,
2468 ## The commands supported by a separate argument parser in xend.xm.
2469 IMPORTED_COMMANDS = [
2470 'create',
2471 'new',
2472 'migrate',
2473 'labels',
2474 'cfgbootpolicy',
2475 'makepolicy',
2476 'loadpolicy',
2477 'dumppolicy',
2478 'addlabel',
2479 'rmlabel',
2480 'getlabel',
2481 'dry-run',
2482 'resources',
2483 'getpolicy',
2484 'setpolicy',
2485 'activatepolicy',
2488 for c in IMPORTED_COMMANDS:
2489 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2491 aliases = {
2492 "balloon": "mem-set",
2493 "set-vcpus": "vcpu-set",
2494 "vif-list": "network-list",
2495 "vbd-create": "block-attach",
2496 "vbd-destroy": "block-detach",
2497 "vbd-list": "block-list",
2501 def xm_lookup_cmd(cmd):
2502 if commands.has_key(cmd):
2503 return commands[cmd]
2504 elif aliases.has_key(cmd):
2505 deprecated(cmd,aliases[cmd])
2506 return commands[aliases[cmd]]
2507 elif cmd == 'help':
2508 longHelp()
2509 sys.exit(0)
2510 else:
2511 # simulate getopt's prefix matching behaviour
2512 if len(cmd) > 1:
2513 same_prefix_cmds = [commands[c] for c in commands.keys() \
2514 if c[:len(cmd)] == cmd]
2515 # only execute if there is only 1 match
2516 if len(same_prefix_cmds) == 1:
2517 return same_prefix_cmds[0]
2518 return None
2520 def deprecated(old,new):
2521 print >>sys.stderr, (
2522 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2524 def main(argv=sys.argv):
2525 if len(argv) < 2:
2526 usage()
2528 # intercept --help(-h) and output our own help
2529 for help in ['--help', '-h']:
2530 if help in argv[1:]:
2531 if help == argv[1]:
2532 longHelp()
2533 sys.exit(0)
2534 else:
2535 usage(argv[1])
2537 cmd_name = argv[1]
2538 cmd = xm_lookup_cmd(cmd_name)
2539 if cmd:
2540 # strip off prog name and subcmd
2541 args = argv[2:]
2542 _, rc = _run_cmd(cmd, cmd_name, args)
2543 sys.exit(rc)
2544 else:
2545 err('Subcommand %s not found!' % cmd_name)
2546 usage()
2548 def _run_cmd(cmd, cmd_name, args):
2549 global server
2551 try:
2552 if server is None:
2553 if serverType == SERVER_XEN_API:
2554 server = XenAPI.Session(serverURI)
2555 username, password = parseAuthentication()
2556 server.login_with_password(username, password)
2557 def logout():
2558 try:
2559 server.xenapi.session.logout()
2560 except:
2561 pass
2562 atexit.register(logout)
2563 else:
2564 server = ServerProxy(serverURI)
2566 return True, cmd(args)
2567 except socket.error, ex:
2568 if os.geteuid() != 0:
2569 err("Most commands need root access. Please try again as root.")
2570 else:
2571 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2572 except KeyboardInterrupt:
2573 print "Interrupted."
2574 return True, ''
2575 except IOError, ex:
2576 if os.geteuid() != 0:
2577 err("Most commands need root access. Please try again as root.")
2578 else:
2579 err("Unable to connect to xend: %s." % ex[1])
2580 except SystemExit, code:
2581 return code == 0, code
2582 except XenAPI.Failure, exn:
2583 for line in [''] + wrap(str(exn), 80) + ['']:
2584 print >>sys.stderr, line
2585 except xmlrpclib.Fault, ex:
2586 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2587 err("Domain '%s' does not exist." % ex.faultString)
2588 else:
2589 err(ex.faultString)
2590 _usage(cmd_name)
2591 except xmlrpclib.ProtocolError, ex:
2592 if ex.errcode == -1:
2593 print >>sys.stderr, (
2594 "Xend has probably crashed! Invalid or missing HTTP "
2595 "status code.")
2596 else:
2597 print >>sys.stderr, (
2598 "Xend has probably crashed! ProtocolError(%d, %s)." %
2599 (ex.errcode, ex.errmsg))
2600 except (ValueError, OverflowError):
2601 err("Invalid argument.")
2602 _usage(cmd_name)
2603 except OptionError, e:
2604 err(str(e))
2605 _usage(cmd_name)
2606 print e.usage
2607 except XenAPIUnsupportedException, e:
2608 err(str(e))
2609 except XSMError, e:
2610 err(str(e))
2611 except Exception, e:
2612 if serverType != SERVER_XEN_API:
2613 import xen.util.xsm.xsm as security
2614 if isinstance(e, security.XSMError):
2615 err(str(e))
2616 return False, 1
2617 print "Unexpected error:", sys.exc_info()[0]
2618 print
2619 print "Please report to xen-devel@lists.xensource.com"
2620 raise
2622 return False, 1
2624 if __name__ == "__main__":
2625 main()