ia64/xen-unstable

view tools/python/xen/xm/main.py @ 15610:ee7a5ddc1847

Improve xm uptime command for inactive managed domains
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Tue Jul 17 10:36:33 2007 +0100 (2007-07-17)
parents 23a171f65b15
children e934846666e6
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
40 from xen.util.blkif import blkdev_name_to_number
42 import warnings
43 warnings.filterwarnings('ignore', category=FutureWarning)
45 from xen.xend import PrettyPrint
46 from xen.xend import sxp
47 from xen.xend import XendClient
48 from xen.xend.XendConstants import *
50 from xen.xm.opts import OptionError, Opts, wrap, set_true
51 from xen.xm import console
52 from xen.util.xmlrpcclient import ServerProxy
53 from xen.util.security import ACMError
55 import XenAPI
58 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
59 # getopt.getopt if gnu_getopt is not available. This will mean that options
60 # may only be specified before positional arguments.
61 if not hasattr(getopt, 'gnu_getopt'):
62 getopt.gnu_getopt = getopt.getopt
64 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
65 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
67 # Supported types of server
68 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
69 SERVER_XEN_API = 'Xen-API'
71 # General help message
73 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
74 "Control, list, and manipulate Xen guest instances.\n"
76 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
77 'For more help on \'xm\' see the xm(1) man page.\n' \
78 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
79 ' man page.\n'
81 # Help strings are indexed by subcommand name in this way:
82 # 'subcommand': (argstring, description)
84 SUBCOMMAND_HELP = {
85 # common commands
87 'shell' : ('', 'Launch an interactive shell.'),
89 'console' : ('[-q|--quiet] <Domain>',
90 'Attach to <Domain>\'s console.'),
91 'create' : ('<ConfigFile> [options] [vars]',
92 'Create a domain based on <ConfigFile>.'),
93 'destroy' : ('<Domain>',
94 'Terminate a domain immediately.'),
95 'help' : ('', 'Display this message.'),
96 'list' : ('[options] [Domain, ...]',
97 'List information about all/some domains.'),
98 'mem-max' : ('<Domain> <Mem>',
99 'Set the maximum amount reservation for a domain.'),
100 'mem-set' : ('<Domain> <Mem>',
101 'Set the current memory usage for a domain.'),
102 'migrate' : ('<Domain> <Host>',
103 'Migrate a domain to another machine.'),
104 'pause' : ('<Domain>', 'Pause execution of a domain.'),
105 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
106 'restore' : ('<CheckpointFile> [-p]',
107 'Restore a domain from a saved state.'),
108 'save' : ('[-c] <Domain> <CheckpointFile>',
109 'Save a domain state to restore later.'),
110 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
111 'top' : ('', 'Monitor a host and the domains in real time.'),
112 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
113 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
115 # Life cycle xm commands
116 'new' : ('<ConfigFile> [options] [vars]',
117 'Adds a domain to Xend domain management'),
118 'delete' : ('<DomainName>',
119 'Remove a domain from Xend domain management.'),
120 'start' : ('<DomainName>', 'Start a Xend managed domain'),
121 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
122 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
124 # less used commands
126 'dmesg' : ('[-c|--clear]',
127 'Read and/or clear Xend\'s message buffer.'),
128 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
129 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
130 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
131 'Dump core for a specific domain.'),
132 'info' : ('', 'Get information about Xen host.'),
133 'log' : ('', 'Print Xend log'),
134 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
135 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
136 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
137 'Get/set credit scheduler parameters.'),
138 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
139 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
140 'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
141 'Send a trigger to a domain.'),
142 'vcpu-list' : ('[<Domain>]',
143 'List the VCPUs for a domain or all domains.'),
144 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
145 'Set which CPUs a VCPU can use.'),
146 'vcpu-set' : ('<Domain> <vCPUs>',
147 'Set the number of active VCPUs for allowed for the'
148 ' domain.'),
150 # device commands
152 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
153 'Create a new virtual block device.'),
154 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
155 'Change block device configuration'),
156 'block-detach' : ('<Domain> <DevId> [-f|--force]',
157 'Destroy a domain\'s virtual block device.'),
158 'block-list' : ('<Domain> [--long]',
159 'List virtual block devices for a domain.'),
160 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
161 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
162 '[vifname=<name>] [rate=<rate>] [model=<model>]',
163 'Create a new virtual network device.'),
164 'network-detach': ('<Domain> <DevId> [-f|--force]',
165 'Destroy a domain\'s virtual network device.'),
166 'network-list' : ('<Domain> [--long]',
167 'List virtual network interfaces for a domain.'),
168 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
169 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
170 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
171 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
173 # security
175 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n'
176 ' [<policy>]',
177 'Add security label to domain.'),
178 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}',
179 'Remove a security label from domain.'),
180 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}',
181 'Show security label for domain or resource.'),
182 'dry-run' : ('<ConfigFile>',
183 'Test if a domain can access its resources.'),
184 'resources' : ('', 'Show info for each labeled resource.'),
185 'cfgbootpolicy' : ('<policy> [boot-title]',
186 'Add policy to boot configuration.'),
187 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
188 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
189 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
190 'files.'),
191 'setpolicy' : ('<policytype> <policyfile> [options]',
192 'Set the policy of the system.'),
193 'getpolicy' : ('[options]', 'Get the policy of the system.'),
194 'activatepolicy': ('[options]', 'Activate the xend-managed policy.'),
195 'labels' : ('[policy] [type=dom|res|any]',
196 'List <type> labels for (active) policy.'),
197 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
198 }
200 SUBCOMMAND_OPTIONS = {
201 'sched-sedf': (
202 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
203 ('-s [MS]', '--slice[=MS]' ,
204 'Worst-case execution time(ms). (slice < period)'),
205 ('-l [MS]', '--latency[=MS]',
206 'Scaled period (ms) when domain performs heavy I/O'),
207 ('-e [FLAG]', '--extra[=FLAG]',
208 'Flag (0 or 1) controls if domain can run in extra time.'),
209 ('-w [FLOAT]', '--weight[=FLOAT]',
210 'CPU Period/slice (do not set with --period/--slice)'),
211 ),
212 'sched-credit': (
213 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
214 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
215 ('-c CAP', '--cap=CAP', 'Cap (int)'),
216 ),
217 'list': (
218 ('-l', '--long', 'Output all VM details in SXP'),
219 ('', '--label', 'Include security labels'),
220 ('', '--state=<state>', 'Select only VMs with the specified state'),
221 ),
222 'console': (
223 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
224 ),
225 'dmesg': (
226 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
227 ),
228 'vnet-list': (
229 ('-l', '--long', 'List Vnets as SXP'),
230 ),
231 'network-list': (
232 ('-l', '--long', 'List resources as SXP'),
233 ),
234 'dump-core': (
235 ('-L', '--live', 'Dump core without pausing the domain'),
236 ('-C', '--crash', 'Crash domain after dumping core'),
237 ),
238 'start': (
239 ('-p', '--paused', 'Do not unpause domain after starting it'),
240 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
241 ),
242 'resume': (
243 ('-p', '--paused', 'Do not unpause domain after resuming it'),
244 ),
245 'save': (
246 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
247 ),
248 'restore': (
249 ('-p', '--paused', 'Do not unpause domain after restoring it'),
250 ),
251 }
253 common_commands = [
254 "console",
255 "create",
256 "new",
257 "delete",
258 "destroy",
259 "dump-core",
260 "help",
261 "list",
262 "mem-set",
263 "migrate",
264 "pause",
265 "reboot",
266 "restore",
267 "resume",
268 "save",
269 "shell",
270 "shutdown",
271 "start",
272 "suspend",
273 "top",
274 "unpause",
275 "uptime",
276 "vcpu-set",
277 ]
279 domain_commands = [
280 "console",
281 "create",
282 "new",
283 "delete",
284 "destroy",
285 "domid",
286 "domname",
287 "dump-core",
288 "list",
289 "mem-max",
290 "mem-set",
291 "migrate",
292 "pause",
293 "reboot",
294 "rename",
295 "restore",
296 "resume",
297 "save",
298 "shutdown",
299 "start",
300 "suspend",
301 "sysrq",
302 "trigger",
303 "top",
304 "unpause",
305 "uptime",
306 "vcpu-list",
307 "vcpu-pin",
308 "vcpu-set",
309 ]
311 host_commands = [
312 "debug-keys",
313 "dmesg",
314 "info",
315 "log",
316 "serve",
317 ]
319 scheduler_commands = [
320 "sched-credit",
321 "sched-sedf",
322 ]
324 device_commands = [
325 "block-attach",
326 "block-detach",
327 "block-list",
328 "block-configure",
329 "network-attach",
330 "network-detach",
331 "network-list",
332 "vtpm-list",
333 ]
335 vnet_commands = [
336 "vnet-list",
337 "vnet-create",
338 "vnet-delete",
339 ]
341 acm_commands = [
342 "labels",
343 "addlabel",
344 "rmlabel",
345 "getlabel",
346 "dry-run",
347 "resources",
348 "makepolicy",
349 "loadpolicy",
350 "cfgbootpolicy",
351 "dumppolicy",
352 "activatepolicy",
353 "setpolicy",
354 "getpolicy",
355 ]
357 all_commands = (domain_commands + host_commands + scheduler_commands +
358 device_commands + vnet_commands + acm_commands +
359 ['shell', 'event-monitor'])
362 ##
363 # Configuration File Parsing
364 ##
366 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
367 config = None
368 if os.path.isfile(xmConfigFile):
369 try:
370 config = xml.dom.minidom.parse(xmConfigFile)
371 except:
372 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
373 xmConfigFile)
375 def parseServer():
376 if config:
377 server = config.getElementsByTagName('server')
378 if server:
379 st = server[0].getAttribute('type')
380 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
381 print >>sys.stderr, ('Invalid server type %s; using %s.' %
382 (st, SERVER_LEGACY_XMLRPC))
383 st = SERVER_LEGACY_XMLRPC
384 return (st, server[0].getAttribute('uri'))
386 return SERVER_LEGACY_XMLRPC, XendClient.uri
388 def parseAuthentication():
389 server = config.getElementsByTagName('server')[0]
390 return (server.getAttribute('username'),
391 server.getAttribute('password'))
393 serverType, serverURI = parseServer()
394 server = None
397 ####################################################################
398 #
399 # Help/usage printing functions
400 #
401 ####################################################################
403 def cmdHelp(cmd):
404 """Print help for a specific subcommand."""
406 for fc in SUBCOMMAND_HELP.keys():
407 if fc[:len(cmd)] == cmd:
408 cmd = fc
409 break
411 try:
412 args, desc = SUBCOMMAND_HELP[cmd]
413 except KeyError:
414 shortHelp()
415 return
417 print 'Usage: xm %s %s' % (cmd, args)
418 print
419 print desc
421 try:
422 # If options help message is defined, print this.
423 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
424 if shortopt and longopt:
425 optdesc = '%s, %s' % (shortopt, longopt)
426 elif shortopt:
427 optdesc = shortopt
428 elif longopt:
429 optdesc = longopt
431 wrapped_desc = wrap(desc, 43)
432 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
433 for line in wrapped_desc[1:]:
434 print ' ' * 33 + line
435 print
436 except KeyError:
437 # if the command is an external module, we grab usage help
438 # from the module itself.
439 if cmd in IMPORTED_COMMANDS:
440 try:
441 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
442 cmd_usage = getattr(cmd_module, "help", None)
443 if cmd_usage:
444 print cmd_usage()
445 except ImportError:
446 pass
448 def shortHelp():
449 """Print out generic help when xm is called without subcommand."""
451 print USAGE_HELP
452 print 'Common \'xm\' commands:\n'
454 for command in common_commands:
455 try:
456 args, desc = SUBCOMMAND_HELP[command]
457 except KeyError:
458 continue
459 wrapped_desc = wrap(desc, 50)
460 print ' %-20s %-50s' % (command, wrapped_desc[0])
461 for line in wrapped_desc[1:]:
462 print ' ' * 22 + line
464 print
465 print USAGE_FOOTER
466 print 'For a complete list of subcommands run \'xm help\'.'
468 def longHelp():
469 """Print out full help when xm is called with xm --help or xm help"""
471 print USAGE_HELP
472 print 'xm full list of subcommands:\n'
474 for command in all_commands:
475 try:
476 args, desc = SUBCOMMAND_HELP[command]
477 except KeyError:
478 continue
480 wrapped_desc = wrap(desc, 50)
481 print ' %-20s %-50s' % (command, wrapped_desc[0])
482 for line in wrapped_desc[1:]:
483 print ' ' * 22 + line
485 print
486 print USAGE_FOOTER
488 def _usage(cmd):
489 """ Print help usage information """
490 if cmd:
491 cmdHelp(cmd)
492 else:
493 shortHelp()
495 def usage(cmd = None):
496 """ Print help usage information and exits """
497 _usage(cmd)
498 sys.exit(1)
501 ####################################################################
502 #
503 # Utility functions
504 #
505 ####################################################################
507 def get_default_SR():
508 return [sr_ref
509 for sr_ref in server.xenapi.SR.get_all()
510 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
512 def get_default_Network():
513 return [network_ref
514 for network_ref in server.xenapi.network.get_all()][0]
516 class XenAPIUnsupportedException(Exception):
517 pass
519 def xenapi_unsupported():
520 if serverType == SERVER_XEN_API:
521 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
523 def xenapi_only():
524 if serverType != SERVER_XEN_API:
525 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
527 def map2sxp(m):
528 return [[k, m[k]] for k in m.keys()]
530 def arg_check(args, name, lo, hi = -1):
531 n = len([i for i in args if i != '--'])
533 if hi == -1:
534 if n != lo:
535 err("'xm %s' requires %d argument%s.\n" % (name, lo,
536 lo == 1 and '' or 's'))
537 usage(name)
538 else:
539 if n < lo or n > hi:
540 err("'xm %s' requires between %d and %d arguments.\n" %
541 (name, lo, hi))
542 usage(name)
545 def unit(c):
546 if not c.isalpha():
547 return 0
548 base = 1
549 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
550 elif c == 'M' or c == 'm': base = 1024 * 1024
551 elif c == 'K' or c == 'k': base = 1024
552 else:
553 print 'ignoring unknown unit'
554 return base
556 def int_unit(str, dest):
557 base = unit(str[-1])
558 if not base:
559 return int(str)
561 value = int(str[:-1])
562 dst_base = unit(dest)
563 if dst_base == 0:
564 dst_base = 1
565 if dst_base > base:
566 return value / (dst_base / base)
567 else:
568 return value * (base / dst_base)
570 def err(msg):
571 print >>sys.stderr, "Error:", msg
574 def get_single_vm(dom):
575 if serverType == SERVER_XEN_API:
576 uuids = server.xenapi.VM.get_by_name_label(dom)
577 if len(uuids) > 0:
578 return uuids[0]
580 refs = []
582 try:
583 domid = int(dom)
584 refs = [vm_ref
585 for vm_ref in server.xenapi.VM.get_all()
586 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
587 except:
588 pass
590 if len(refs) > 0:
591 return refs[0]
593 raise OptionError("Domain '%s' not found." % dom)
594 else:
595 dominfo = server.xend.domain(dom, False)
596 return dominfo['uuid']
598 ##
599 #
600 # Xen-API Shell
601 #
602 ##
604 class Shell(cmd.Cmd):
605 def __init__(self):
606 cmd.Cmd.__init__(self)
607 self.prompt = "xm> "
608 if serverType == SERVER_XEN_API:
609 try:
610 res = server.xenapi.host.list_methods()
611 for f in res:
612 setattr(Shell, 'do_' + f + ' ', self.default)
613 except:
614 pass
616 def preloop(self):
617 cmd.Cmd.preloop(self)
618 readline.set_completer_delims(' ')
620 def default(self, line):
621 words = shlex.split(line)
622 if len(words) > 0 and words[0] == 'xm':
623 words = words[1:]
624 if len(words) > 0:
625 cmd = xm_lookup_cmd(words[0])
626 if cmd:
627 _run_cmd(cmd, words[0], words[1:])
628 elif serverType == SERVER_XEN_API:
629 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
630 tuple(x)),
631 words[0], words[1:])
632 if ok and res is not None and res != '':
633 pprint.pprint(res)
634 else:
635 print '*** Unknown command: %s' % words[0]
636 return False
638 def completedefault(self, text, line, begidx, endidx):
639 words = shlex.split(line[:begidx])
640 clas, func = words[0].split('.')
641 if len(words) > 1 or \
642 func.startswith('get_by_') or \
643 func == 'get_all':
644 return []
645 uuids = server.xenapi_request('%s.get_all' % clas, ())
646 return [u + " " for u in uuids if u.startswith(text)]
648 def emptyline(self):
649 pass
651 def do_EOF(self, line):
652 print
653 sys.exit(0)
655 def do_help(self, line):
656 _usage(line)
659 def xm_shell(args):
660 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
663 def xm_event_monitor(args):
664 if serverType == SERVER_XEN_API:
665 while True:
666 server.xenapi.event.register(args)
667 events = server.xenapi.event.next()
668 for e in events:
669 print e
670 else:
671 err("Event monitoring not supported unless using Xen-API.")
674 #########################################################################
675 #
676 # Main xm functions
677 #
678 #########################################################################
680 def xm_save(args):
682 arg_check(args, "save", 2, 3)
684 try:
685 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
686 except getopt.GetoptError, opterr:
687 err(opterr)
688 sys.exit(1)
690 dom = params[0]
691 savefile = params[1]
693 checkpoint = False
694 for (k, v) in options:
695 if k in ['-c', '--checkpoint']:
696 checkpoint = True
698 if len(params) != 2:
699 err("Wrong number of parameters")
700 usage('save')
701 sys.exit(1)
703 savefile = os.path.abspath(savefile)
705 if not os.access(os.path.dirname(savefile), os.W_OK):
706 err("xm save: Unable to create file %s" % savefile)
707 sys.exit(1)
709 if serverType == SERVER_XEN_API:
710 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
711 else:
712 server.xend.domain.save(dom, savefile, checkpoint)
714 def xm_restore(args):
715 arg_check(args, "restore", 1, 2)
717 try:
718 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
719 except getopt.GetoptError, opterr:
720 err(opterr)
721 usage('restore')
723 paused = False
724 for (k, v) in options:
725 if k in ['-p', '--paused']:
726 paused = True
728 if len(params) != 1:
729 err("Wrong number of parameters")
730 usage('restore')
732 savefile = os.path.abspath(params[0])
734 if not os.access(savefile, os.R_OK):
735 err("xm restore: Unable to read file %s" % savefile)
736 sys.exit(1)
738 try:
739 if serverType == SERVER_XEN_API:
740 server.xenapi.VM.restore(savefile, paused)
741 else:
742 server.xend.domain.restore(savefile, paused)
743 except Exception, ex:
744 err("%s" % ex.faultString)
747 def datetime_to_secs(v):
748 unwanted = ":-."
749 for c in unwanted:
750 v = str(v).replace(c, "")
751 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
753 def getDomains(domain_names, state, full = 0):
754 if serverType == SERVER_XEN_API:
755 doms_sxp = []
756 doms_dict = []
758 dom_recs = server.xenapi.VM.get_all_records()
759 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
761 for dom_ref, dom_rec in dom_recs.items():
762 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
764 states = ('running', 'blocked', 'paused', 'shutdown',
765 'crashed', 'dying')
766 def state_on_off(state):
767 if state in dom_metrics_rec['state']:
768 return state[0]
769 else:
770 return "-"
771 state_str = "".join([state_on_off(state)
772 for state in states])
774 dom_rec.update({'name': dom_rec['name_label'],
775 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
776 'vcpus': dom_metrics_rec['VCPUs_number'],
777 'state': state_str,
778 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
779 'start_time': datetime_to_secs(
780 dom_metrics_rec['start_time'])})
782 doms_sxp.append(['domain'] + map2sxp(dom_rec))
783 doms_dict.append(dom_rec)
785 if domain_names:
786 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
787 if dom["name"] in domain_names]
789 if len(doms) > 0:
790 return doms
791 else:
792 print "Error: no domain%s named %s" % \
793 (len(domain_names) > 1 and 's' or '',
794 ', '.join(domain_names))
795 sys.exit(-1)
796 else:
797 return doms_sxp
798 else:
799 if domain_names:
800 return [server.xend.domain(dom, full) for dom in domain_names]
801 else:
802 return server.xend.domains_with_state(True, state, full)
805 def xm_list(args):
806 use_long = 0
807 show_vcpus = 0
808 show_labels = 0
809 state = 'all'
810 try:
811 (options, params) = getopt.gnu_getopt(args, 'lv',
812 ['long','vcpus','label',
813 'state='])
814 except getopt.GetoptError, opterr:
815 err(opterr)
816 usage('list')
818 for (k, v) in options:
819 if k in ['-l', '--long']:
820 use_long = 1
821 if k in ['-v', '--vcpus']:
822 show_vcpus = 1
823 if k in ['--label']:
824 show_labels = 1
825 if k in ['--state']:
826 state = v
828 if state != 'all' and len(params) > 0:
829 raise OptionError(
830 "You may specify either a state or a particular VM, but not both")
832 if show_vcpus:
833 print >>sys.stderr, (
834 "xm list -v is deprecated. Please use xm vcpu-list.")
835 xm_vcpu_list(params)
836 return
838 doms = getDomains(params, state, use_long)
840 if use_long:
841 map(PrettyPrint.prettyprint, doms)
842 elif show_labels:
843 xm_label_list(doms)
844 else:
845 xm_brief_list(doms)
848 def parse_doms_info(info):
849 def get_info(n, t, d):
850 return t(sxp.child_value(info, n, d))
852 def get_status(n, t, d):
853 return DOM_STATES[t(sxp.child_value(info, n, d))]
855 start_time = get_info('start_time', float, -1)
856 if start_time == -1:
857 up_time = float(-1)
858 else:
859 up_time = time.time() - start_time
861 parsed_info = {
862 'domid' : get_info('domid', str, ''),
863 'name' : get_info('name', str, '??'),
864 'state' : get_info('state', str, ''),
866 # VCPUs is the number online when the VM is up, or the number
867 # configured otherwise.
868 'vcpus' : get_info('online_vcpus', int,
869 get_info('vcpus', int, 0)),
870 'up_time' : up_time
871 }
873 security_label = get_info('security_label', str, '')
874 tmp = security_label.split(":")
875 if len(tmp) != 3:
876 seclabel = ""
877 else:
878 seclabel = tmp[2]
879 parsed_info['seclabel'] = seclabel
881 if serverType == SERVER_XEN_API:
882 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
883 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
884 if sum(cpu_times.values()) > 0:
885 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
886 else:
887 parsed_info['cpu_time'] = 0
888 else:
889 parsed_info['mem'] = get_info('memory', int,0)
890 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
892 return parsed_info
894 def check_sched_type(sched):
895 if serverType == SERVER_XEN_API:
896 current = server.xenapi.host.get_sched_policy(
897 server.xenapi.session.get_this_host(server.getSession()))
898 else:
899 current = 'unknown'
900 for x in server.xend.node.info()[1:]:
901 if len(x) > 1 and x[0] == 'xen_scheduler':
902 current = x[1]
903 break
904 if sched != current:
905 err("Xen is running with the %s scheduler" % current)
906 sys.exit(1)
908 def parse_sedf_info(info):
909 def get_info(n, t, d):
910 return t(sxp.child_value(info, n, d))
912 return {
913 'domid' : get_info('domid', int, -1),
914 'period' : get_info('period', int, -1),
915 'slice' : get_info('slice', int, -1),
916 'latency' : get_info('latency', int, -1),
917 'extratime': get_info('extratime', int, -1),
918 'weight' : get_info('weight', int, -1),
919 }
921 def domid_match(domid, info):
922 return domid is None or domid == info['name'] or \
923 domid == str(info['domid'])
925 def xm_brief_list(doms):
926 print '%-40s %5s %5s %5s %10s %9s' % \
927 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
929 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
930 "%(cpu_time)8.1f"
932 for dom in doms:
933 d = parse_doms_info(dom)
934 print format % d
936 def xm_label_list(doms):
937 print '%-32s %5s %5s %5s %10s %9s %-8s' % \
938 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
940 output = []
941 format = '%(name)-32s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
942 '%(cpu_time)8.1f %(seclabel)9s'
944 from xen.util import security
946 for dom in doms:
947 d = parse_doms_info(dom)
948 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
949 if not d['seclabel']:
950 d['seclabel'] = 'ERROR'
951 elif security.active_policy in ['DEFAULT']:
952 d['seclabel'] = 'DEFAULT'
953 else:
954 d['seclabel'] = 'INACTIVE'
956 output.append((format % d, d['seclabel']))
958 #sort by labels
959 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
960 for line, label in output:
961 print line
964 def xm_vcpu_list(args):
965 if serverType == SERVER_XEN_API:
966 if args:
967 vm_refs = map(get_single_vm, args)
968 else:
969 vm_refs = server.xenapi.VM.get_all()
971 vm_records = dict(map(lambda vm_ref:
972 (vm_ref, server.xenapi.VM.get_record(
973 vm_ref)),
974 vm_refs))
976 vm_metrics = dict(map(lambda (ref, record):
977 (ref,
978 server.xenapi.VM_metrics.get_record(
979 record['metrics'])),
980 vm_records.items()))
982 dominfo = []
984 # vcpu_list doesn't list 'managed' domains
985 # when they are not running, so filter them out
987 vm_refs = [vm_ref
988 for vm_ref in vm_refs
989 if vm_records[vm_ref]["power_state"] != "Halted"]
991 for vm_ref in vm_refs:
992 info = ['domain',
993 ['domid', vm_records[vm_ref]['domid']],
994 ['name', vm_records[vm_ref]['name_label']],
995 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
997 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
998 def chk_flag(flag):
999 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
1000 and 1 or 0
1002 vcpu_info = ['vcpu',
1003 ['number',
1004 i],
1005 ['online',
1006 chk_flag("online")],
1007 ['blocked',
1008 chk_flag("blocked")],
1009 ['running',
1010 chk_flag("running")],
1011 ['cpu_time',
1012 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1013 ['cpu',
1014 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1015 ['cpumap',
1016 vm_metrics[vm_ref]['VCPUs_params']\
1017 ['cpumap%i' % i].split(",")]]
1019 info.append(vcpu_info)
1021 dominfo.append(info)
1022 else:
1023 if args:
1024 dominfo = map(server.xend.domain.getVCPUInfo, args)
1025 else:
1026 doms = server.xend.domains(False)
1027 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1029 print '%-32s %5s %5s %5s %5s %9s %s' % \
1030 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1032 format = '%(name)-32s %(domid)5d %(number)5d %(c)5s %(s)5s ' \
1033 ' %(cpu_time)8.1f %(cpumap)s'
1035 for dom in dominfo:
1036 def get_info(n):
1037 return sxp.child_value(dom, n)
1040 # convert a list of integers into a list of pairs indicating
1041 # continuous sequences in the list:
1043 # [0,1,2,3] -> [(0,3)]
1044 # [1,2,4,5] -> [(1,2),(4,5)]
1045 # [0] -> [(0,0)]
1046 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1048 def list_to_rangepairs(cmap):
1049 cmap.sort()
1050 pairs = []
1051 x = y = 0
1052 for i in range(0,len(cmap)):
1053 try:
1054 if ((cmap[y+1] - cmap[i]) > 1):
1055 pairs.append((cmap[x],cmap[y]))
1056 x = y = i+1
1057 else:
1058 y = y + 1
1059 # if we go off the end, then just add x to y
1060 except IndexError:
1061 pairs.append((cmap[x],cmap[y]))
1063 return pairs
1066 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1068 def format_pairs(pairs):
1069 if not pairs:
1070 return "no cpus"
1071 out = ""
1072 for f,s in pairs:
1073 if (f==s):
1074 out += '%d'%f
1075 else:
1076 out += '%d-%d'%(f,s)
1077 out += ','
1078 # trim trailing ','
1079 return out[:-1]
1081 def format_cpumap(cpumap):
1082 cpumap = map(lambda x: int(x), cpumap)
1083 cpumap.sort()
1085 if serverType == SERVER_XEN_API:
1086 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1087 server.xenapi.session.get_this_host(server.getSession())))
1088 else:
1089 for x in server.xend.node.info()[1:]:
1090 if len(x) > 1 and x[0] == 'nr_cpus':
1091 nr_cpus = int(x[1])
1093 # normalize cpumap by modulus nr_cpus, and drop duplicates
1094 cpumap = dict.fromkeys(
1095 map(lambda x: x % nr_cpus, cpumap)).keys()
1096 if len(cpumap) == nr_cpus:
1097 return "any cpu"
1099 return format_pairs(list_to_rangepairs(cpumap))
1101 name = get_info('name')
1102 domid = int(get_info('domid'))
1104 for vcpu in sxp.children(dom, 'vcpu'):
1105 def vinfo(n, t):
1106 return t(sxp.child_value(vcpu, n))
1108 number = vinfo('number', int)
1109 cpu = vinfo('cpu', int)
1110 cpumap = format_cpumap(vinfo('cpumap', list))
1111 online = vinfo('online', int)
1112 cpu_time = vinfo('cpu_time', float)
1113 running = vinfo('running', int)
1114 blocked = vinfo('blocked', int)
1116 if online:
1117 c = str(cpu)
1118 if running:
1119 s = 'r'
1120 else:
1121 s = '-'
1122 if blocked:
1123 s += 'b'
1124 else:
1125 s += '-'
1126 s += '-'
1127 else:
1128 c = "-"
1129 s = "--p"
1131 print format % locals()
1133 def start_do_console(domain_name):
1134 cpid = os.fork()
1135 if cpid != 0:
1136 for i in range(10):
1137 # Catch failure of the create process
1138 time.sleep(1)
1139 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1140 if os.WIFEXITED(rv):
1141 if os.WEXITSTATUS(rv) != 0:
1142 sys.exit(os.WEXITSTATUS(rv))
1143 try:
1144 # Acquire the console of the created dom
1145 if serverType == SERVER_XEN_API:
1146 domid = server.xenapi.VM.get_domid(
1147 get_single_vm(domain_name))
1148 else:
1149 dom = server.xend.domain(domain_name)
1150 domid = int(sxp.child_value(dom, 'domid', '-1'))
1151 console.execConsole(domid)
1152 except:
1153 pass
1154 print("Could not start console\n");
1155 sys.exit(0)
1157 def xm_start(args):
1159 paused = False
1160 console_autoconnect = False
1162 try:
1163 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused'])
1164 for (k, v) in options:
1165 if k in ('-p', '--paused'):
1166 paused = True
1167 if k in ('-c', '--console_autoconnect'):
1168 console_autoconnect = True
1170 if len(params) != 1:
1171 raise OptionError("Expects 1 argument")
1172 except getopt.GetoptError, opterr:
1173 err(opterr)
1174 usage('start')
1176 dom = params[0]
1178 if console_autoconnect:
1179 start_do_console(dom)
1181 try:
1182 if serverType == SERVER_XEN_API:
1183 server.xenapi.VM.start(get_single_vm(dom), paused)
1184 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1185 else:
1186 server.xend.domain.start(dom, paused)
1187 info = server.xend.domain(dom)
1188 domid = int(sxp.child_value(info, 'domid', '-1'))
1189 except:
1190 raise
1192 if domid == -1:
1193 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1195 def xm_delete(args):
1196 arg_check(args, "delete", 1)
1197 dom = args[0]
1198 if serverType == SERVER_XEN_API:
1199 server.xenapi.VM.destroy(get_single_vm(dom))
1200 else:
1201 server.xend.domain.delete(dom)
1203 def xm_suspend(args):
1204 arg_check(args, "suspend", 1)
1205 dom = args[0]
1206 if serverType == SERVER_XEN_API:
1207 server.xenapi.VM.suspend(get_single_vm(dom))
1208 else:
1209 server.xend.domain.suspend(dom)
1211 def xm_resume(args):
1212 arg_check(args, "resume", 1, 2)
1214 try:
1215 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1216 except getopt.GetoptError, opterr:
1217 err(opterr)
1218 usage('resume')
1220 paused = False
1221 for (k, v) in options:
1222 if k in ['-p', '--paused']:
1223 paused = True
1225 if len(params) != 1:
1226 err("Wrong number of parameters")
1227 usage('resume')
1229 dom = params[0]
1230 if serverType == SERVER_XEN_API:
1231 server.xenapi.VM.resume(get_single_vm(dom), paused)
1232 else:
1233 server.xend.domain.resume(dom, paused)
1235 def xm_reboot(args):
1236 arg_check(args, "reboot", 1, 3)
1237 from xen.xm import shutdown
1238 shutdown.main(["shutdown", "-R"] + args)
1240 def xm_shutdown(args):
1241 arg_check(args, "shutdown", 1, 4)
1242 from xen.xm import shutdown
1243 shutdown.main(["shutdown"] + args)
1245 def xm_pause(args):
1246 arg_check(args, "pause", 1)
1247 dom = args[0]
1249 if serverType == SERVER_XEN_API:
1250 server.xenapi.VM.pause(get_single_vm(dom))
1251 else:
1252 server.xend.domain.pause(dom)
1254 def xm_unpause(args):
1255 arg_check(args, "unpause", 1)
1256 dom = args[0]
1258 if serverType == SERVER_XEN_API:
1259 server.xenapi.VM.unpause(get_single_vm(dom))
1260 else:
1261 server.xend.domain.unpause(dom)
1263 def xm_dump_core(args):
1264 live = False
1265 crash = False
1266 try:
1267 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1268 for (k, v) in options:
1269 if k in ('-L', '--live'):
1270 live = True
1271 if k in ('-C', '--crash'):
1272 crash = True
1274 if len(params) not in (1, 2):
1275 raise OptionError("Expects 1 or 2 argument(s)")
1276 except getopt.GetoptError, e:
1277 raise OptionError(str(e))
1279 dom = params[0]
1280 if len(params) == 2:
1281 filename = os.path.abspath(params[1])
1282 else:
1283 filename = None
1285 if not live:
1286 server.xend.domain.pause(dom)
1288 try:
1289 print "Dumping core of domain: %s ..." % str(dom)
1290 server.xend.domain.dump(dom, filename, live, crash)
1291 finally:
1292 if not live:
1293 server.xend.domain.unpause(dom)
1295 if crash:
1296 print "Destroying domain: %s ..." % str(dom)
1297 server.xend.domain.destroy(dom)
1299 def xm_rename(args):
1300 arg_check(args, "rename", 2)
1302 if serverType == SERVER_XEN_API:
1303 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1304 else:
1305 server.xend.domain.setName(args[0], args[1])
1307 def xm_importcommand(command, args):
1308 cmd = __import__(command, globals(), locals(), 'xen.xm')
1309 cmd.main([command] + args)
1312 #############################################################
1314 def xm_vcpu_pin(args):
1315 arg_check(args, "vcpu-pin", 3)
1317 def cpu_make_map(cpulist):
1318 cpus = []
1319 for c in cpulist.split(','):
1320 if c.find('-') != -1:
1321 (x,y) = c.split('-')
1322 for i in range(int(x),int(y)+1):
1323 cpus.append(int(i))
1324 else:
1325 # remove this element from the list
1326 if c[0] == '^':
1327 cpus = [x for x in cpus if x != int(c[1:])]
1328 else:
1329 cpus.append(int(c))
1330 cpus.sort()
1331 return cpus
1333 dom = args[0]
1334 vcpu = args[1]
1335 if args[2] == 'all':
1336 cpumap = cpu_make_map('0-63')
1337 else:
1338 cpumap = cpu_make_map(args[2])
1340 if serverType == SERVER_XEN_API:
1341 cpumap = map(str, cpumap)
1342 server.xenapi.VM.add_to_VCPUs_params_live(
1343 get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap))
1344 else:
1345 server.xend.domain.pincpu(dom, vcpu, cpumap)
1347 def xm_mem_max(args):
1348 arg_check(args, "mem-max", 2)
1350 dom = args[0]
1352 if serverType == SERVER_XEN_API:
1353 mem = int_unit(args[1], 'k') * 1024
1354 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1355 else:
1356 mem = int_unit(args[1], 'm')
1357 server.xend.domain.maxmem_set(dom, mem)
1359 def xm_mem_set(args):
1360 arg_check(args, "mem-set", 2)
1362 dom = args[0]
1364 if serverType == SERVER_XEN_API:
1365 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1366 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1367 mem_target)
1368 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1369 mem_target)
1370 else:
1371 mem_target = int_unit(args[1], 'm')
1372 server.xend.domain.setMemoryTarget(dom, mem_target)
1374 def xm_vcpu_set(args):
1375 arg_check(args, "vcpu-set", 2)
1377 dom = args[0]
1378 vcpus = int(args[1])
1380 if serverType == SERVER_XEN_API:
1381 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1382 else:
1383 server.xend.domain.setVCpuCount(dom, vcpus)
1385 def xm_destroy(args):
1386 arg_check(args, "destroy", 1)
1388 dom = args[0]
1390 if serverType == SERVER_XEN_API:
1391 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1392 else:
1393 server.xend.domain.destroy(dom)
1395 def xm_domid(args):
1396 arg_check(args, "domid", 1)
1398 name = args[0]
1400 if serverType == SERVER_XEN_API:
1401 print server.xenapi.VM.get_domid(get_single_vm(name))
1402 else:
1403 dom = server.xend.domain(name)
1404 print sxp.child_value(dom, 'domid')
1406 def xm_domname(args):
1407 arg_check(args, "domname", 1)
1409 name = args[0]
1411 if serverType == SERVER_XEN_API:
1412 print server.xenapi.VM.get_name_label(get_single_vm(name))
1413 else:
1414 dom = server.xend.domain(name)
1415 print sxp.child_value(dom, 'name')
1417 def xm_sched_sedf(args):
1418 xenapi_unsupported()
1420 def ns_to_ms(val):
1421 return float(val) * 0.000001
1423 def ms_to_ns(val):
1424 return (float(val) / 0.000001)
1426 def print_sedf(info):
1427 info['period'] = ns_to_ms(info['period'])
1428 info['slice'] = ns_to_ms(info['slice'])
1429 info['latency'] = ns_to_ms(info['latency'])
1430 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1431 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1433 check_sched_type('sedf')
1435 # we want to just display current info if no parameters are passed
1436 if len(args) == 0:
1437 domid = None
1438 else:
1439 # we expect at least a domain id (name or number)
1440 # and at most a domid up to 5 options with values
1441 arg_check(args, "sched-sedf", 1, 11)
1442 domid = args[0]
1443 # drop domid from args since get_opt doesn't recognize it
1444 args = args[1:]
1446 opts = {}
1447 try:
1448 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1449 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1450 except getopt.GetoptError, opterr:
1451 err(opterr)
1452 usage('sched-sedf')
1454 # convert to nanoseconds if needed
1455 for (k, v) in options:
1456 if k in ['-p', '--period']:
1457 opts['period'] = ms_to_ns(v)
1458 elif k in ['-s', '--slice']:
1459 opts['slice'] = ms_to_ns(v)
1460 elif k in ['-l', '--latency']:
1461 opts['latency'] = ms_to_ns(v)
1462 elif k in ['-e', '--extratime']:
1463 opts['extratime'] = v
1464 elif k in ['-w', '--weight']:
1465 opts['weight'] = v
1467 doms = filter(lambda x : domid_match(domid, x),
1468 [parse_doms_info(dom)
1469 for dom in getDomains(None, 'running')])
1470 if domid is not None and doms == []:
1471 err("Domain '%s' does not exist." % domid)
1472 usage('sched-sedf')
1474 # print header if we aren't setting any parameters
1475 if len(opts.keys()) == 0:
1476 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1477 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1478 'Extra','Weight')
1480 for d in doms:
1481 # fetch current values so as not to clobber them
1482 try:
1483 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1484 except xmlrpclib.Fault:
1485 # domain does not support sched-sedf?
1486 sedf_raw = {}
1488 sedf_info = parse_sedf_info(sedf_raw)
1489 sedf_info['name'] = d['name']
1490 # update values in case of call to set
1491 if len(opts.keys()) > 0:
1492 for k in opts.keys():
1493 sedf_info[k]=opts[k]
1495 # send the update, converting user input
1496 v = map(int, [sedf_info['period'], sedf_info['slice'],
1497 sedf_info['latency'],sedf_info['extratime'],
1498 sedf_info['weight']])
1499 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1500 if int(rv) != 0:
1501 err("Failed to set sedf parameters (rv=%d)."%(rv))
1503 # not setting values, display info
1504 else:
1505 print_sedf(sedf_info)
1507 def xm_sched_credit(args):
1508 """Get/Set options for Credit Scheduler."""
1510 check_sched_type('credit')
1512 try:
1513 opts, params = getopt.getopt(args, "d:w:c:",
1514 ["domain=", "weight=", "cap="])
1515 except getopt.GetoptError, opterr:
1516 err(opterr)
1517 usage('sched-credit')
1519 domid = None
1520 weight = None
1521 cap = None
1523 for o, a in opts:
1524 if o == "-d":
1525 domid = a
1526 elif o == "-w":
1527 weight = int(a)
1528 elif o == "-c":
1529 cap = int(a);
1531 doms = filter(lambda x : domid_match(domid, x),
1532 [parse_doms_info(dom)
1533 for dom in getDomains(None, 'all')])
1535 if weight is None and cap is None:
1536 if domid is not None and doms == []:
1537 err("Domain '%s' does not exist." % domid)
1538 usage('sched-credit')
1539 # print header if we aren't setting any parameters
1540 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1542 for d in doms:
1543 try:
1544 if serverType == SERVER_XEN_API:
1545 info = server.xenapi.VM_metrics.get_VCPUs_params(
1546 server.xenapi.VM.get_metrics(
1547 get_single_vm(d['name'])))
1548 else:
1549 info = server.xend.domain.sched_credit_get(d['name'])
1550 except xmlrpclib.Fault:
1551 pass
1553 if 'weight' not in info or 'cap' not in info:
1554 # domain does not support sched-credit?
1555 info = {'weight': -1, 'cap': -1}
1557 info['weight'] = int(info['weight'])
1558 info['cap'] = int(info['cap'])
1560 info['name'] = d['name']
1561 info['domid'] = str(d['domid'])
1562 print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
1563 else:
1564 if domid is None:
1565 # place holder for system-wide scheduler parameters
1566 err("No domain given.")
1567 usage('sched-credit')
1569 if serverType == SERVER_XEN_API:
1570 if doms[0]['domid']:
1571 server.xenapi.VM.add_to_VCPUs_params_live(
1572 get_single_vm(domid),
1573 "weight",
1574 weight)
1575 server.xenapi.VM.add_to_VCPUs_params_live(
1576 get_single_vm(domid),
1577 "cap",
1578 cap)
1579 else:
1580 server.xenapi.VM.add_to_VCPUs_params(
1581 get_single_vm(domid),
1582 "weight",
1583 weight)
1584 server.xenapi.VM.add_to_VCPUs_params(
1585 get_single_vm(domid),
1586 "cap",
1587 cap)
1588 else:
1589 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1590 if result != 0:
1591 err(str(result))
1593 def xm_info(args):
1594 arg_check(args, "info", 0)
1596 if serverType == SERVER_XEN_API:
1598 # Need to fake out old style xm info as people rely on parsing it
1600 host_record = server.xenapi.host.get_record(
1601 server.xenapi.session.get_this_host(server.getSession()))
1603 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1605 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1607 def getVal(keys, default=""):
1608 data = host_record
1609 for key in keys:
1610 if key in data:
1611 data = data[key]
1612 else:
1613 return default
1614 return data
1616 def getCpuMhz():
1617 cpu_speeds = [int(host_cpu_record["speed"])
1618 for host_cpu_record in host_cpu_records
1619 if "speed" in host_cpu_record]
1620 if len(cpu_speeds) > 0:
1621 return sum(cpu_speeds) / len(cpu_speeds)
1622 else:
1623 return 0
1625 getCpuMhz()
1627 def getCpuFeatures():
1628 if len(host_cpu_records) > 0:
1629 return host_cpu_records[0].get("features", "")
1630 else:
1631 return ""
1633 info = {
1634 "host": getVal(["name_label"]),
1635 "release": getVal(["software_version", "release"]),
1636 "version": getVal(["software_version", "version"]),
1637 "machine": getVal(["software_version", "machine"]),
1638 "nr_cpus": len(getVal(["host_CPUs"], [])),
1639 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1640 "sockets_per_node": getVal(["cpu_configuration", "sockets_per_node"]),
1641 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1642 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1643 "cpu_mhz": getCpuMhz(),
1644 "hw_caps": getCpuFeatures(),
1645 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1646 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1647 "xen_major": getVal(["software_version", "xen_major"]),
1648 "xen_minor": getVal(["software_version", "xen_minor"]),
1649 "xen_extra": getVal(["software_version", "xen_extra"]),
1650 "xen_caps": " ".join(getVal(["capabilities"], [])),
1651 "xen_scheduler": getVal(["sched_policy"]),
1652 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1653 "platform_params": getVal(["other_config", "platform_params"]),
1654 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1655 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1656 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1657 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1658 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1659 "xend_config_format":getVal(["software_version", "xend_config_format"])
1662 sorted = info.items()
1663 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1665 for (k, v) in sorted:
1666 print "%-23s:" % k, v
1667 else:
1668 info = server.xend.node.info()
1669 for x in info[1:]:
1670 if len(x) < 2:
1671 print "%-23s: (none)" % x[0]
1672 else:
1673 print "%-23s:" % x[0], x[1]
1675 def xm_console(args):
1676 arg_check(args, "console", 1, 2)
1678 quiet = False;
1680 try:
1681 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1682 except getopt.GetoptError, opterr:
1683 err(opterr)
1684 usage('console')
1686 for (k, v) in options:
1687 if k in ['-q', '--quiet']:
1688 quiet = True
1689 else:
1690 assert False
1692 if len(params) != 1:
1693 err('No domain given')
1694 usage('console')
1696 dom = params[0]
1698 try:
1699 if serverType == SERVER_XEN_API:
1700 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1701 else:
1702 info = server.xend.domain(dom)
1703 domid = int(sxp.child_value(info, 'domid', '-1'))
1704 except:
1705 if quiet:
1706 sys.exit(1)
1707 else:
1708 raise
1710 if domid == -1:
1711 if quiet:
1712 sys.exit(1)
1713 else:
1714 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1716 console.execConsole(domid)
1719 def xm_uptime(args):
1720 short_mode = 0
1722 try:
1723 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1724 except getopt.GetoptError, opterr:
1725 err(opterr)
1726 usage('uptime')
1728 for (k, v) in options:
1729 if k in ['-s', '--short']:
1730 short_mode = 1
1732 doms = getDomains(params, 'all')
1734 if short_mode == 0:
1735 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1737 for dom in doms:
1738 d = parse_doms_info(dom)
1739 if d['domid'] == '':
1740 uptime = 0
1741 elif int(d['domid']) > 0:
1742 uptime = int(round(d['up_time']))
1743 else:
1744 f=open('/proc/uptime', 'r')
1745 upfile = f.read()
1746 uptime = int(round(float(upfile.split(' ')[0])))
1747 f.close()
1749 days = int(uptime / 86400)
1750 uptime -= (days * 86400)
1751 hours = int(uptime / 3600)
1752 uptime -= (hours * 3600)
1753 minutes = int(uptime / 60)
1754 uptime -= (minutes * 60)
1755 seconds = uptime
1757 upstring = ""
1758 if days > 0:
1759 upstring += str(days) + " day"
1760 if days > 1:
1761 upstring += "s"
1762 upstring += ", "
1763 upstring += '%(hours)2d:%(minutes)02d' % vars()
1765 if short_mode:
1766 now = datetime.datetime.now()
1767 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1768 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1769 else:
1770 upstring += ':%(seconds)02d' % vars()
1771 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1773 print upstring
1775 def xm_sysrq(args):
1776 arg_check(args, "sysrq", 2)
1777 dom = args[0]
1778 req = args[1]
1779 if serverType == SERVER_XEN_API:
1780 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1781 else:
1782 server.xend.domain.send_sysrq(dom, req)
1784 def xm_trigger(args):
1785 vcpu = 0
1787 arg_check(args, "trigger", 2, 3)
1788 dom = args[0]
1789 trigger = args[1]
1790 if len(args) == 3:
1791 vcpu = int(args[2])
1793 if serverType == SERVER_XEN_API:
1794 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1795 else:
1796 server.xend.domain.send_trigger(dom, trigger, vcpu)
1798 def xm_debug_keys(args):
1799 arg_check(args, "debug-keys", 1)
1801 keys = str(args[0])
1803 if serverType == SERVER_XEN_API:
1804 server.xenapi.host.send_debug_keys(
1805 server.xenapi.session.get_this_host(server.getSession()),
1806 keys)
1807 else:
1808 server.xend.node.send_debug_keys(keys)
1810 def xm_top(args):
1811 arg_check(args, "top", 0)
1813 os.execvp('xentop', ['xentop'])
1815 def xm_dmesg(args):
1816 arg_check(args, "dmesg", 0, 1)
1818 try:
1819 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1820 except getopt.GetoptError, opterr:
1821 err(opterr)
1822 usage('dmesg')
1824 use_clear = 0
1825 for (k, v) in options:
1826 if k in ['-c', '--clear']:
1827 use_clear = 1
1829 if len(params) :
1830 err("No parameter required")
1831 usage('dmesg')
1833 if serverType == SERVER_XEN_API:
1834 host = server.xenapi.session.get_this_host(server.getSession())
1835 if use_clear:
1836 print server.xenapi.host.dmesg_clear(host),
1837 else:
1838 print server.xenapi.host.dmesg(host),
1839 else:
1840 if not use_clear:
1841 print server.xend.node.dmesg.info(),
1842 else:
1843 print server.xend.node.dmesg.clear(),
1845 def xm_log(args):
1846 arg_check(args, "log", 0)
1848 if serverType == SERVER_XEN_API:
1849 print server.xenapi.host.get_log(
1850 server.xenapi.session.get_this_host(server.getSession()))
1851 else:
1852 print server.xend.node.log()
1854 def xm_serve(args):
1855 if serverType == SERVER_XEN_API:
1856 print "Not supported with XenAPI"
1857 sys.exit(-1)
1859 arg_check(args, "serve", 0)
1861 from fcntl import fcntl, F_SETFL
1863 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1864 s.connect(XendClient.XML_RPC_SOCKET)
1865 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1867 while True:
1868 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1869 if s in iwtd:
1870 data = s.recv(4096)
1871 if len(data) > 0:
1872 sys.stdout.write(data)
1873 sys.stdout.flush()
1874 else:
1875 break
1876 if sys.stdin in iwtd:
1877 data = sys.stdin.read(4096)
1878 if len(data) > 0:
1879 s.sendall(data)
1880 else:
1881 break
1882 s.close()
1884 def parse_dev_info(info):
1885 def get_info(n, t, d):
1886 i = 0
1887 while i < len(info):
1888 if (info[i][0] == n):
1889 return t(info[i][1])
1890 i = i + 1
1891 return t(d)
1892 return {
1893 #common
1894 'backend-id' : get_info('backend-id', int, -1),
1895 'handle' : get_info('handle', int, 0),
1896 'state' : get_info('state', int, -1),
1897 'be-path' : get_info('backend', str, '??'),
1898 'event-ch' : get_info('event-channel',int, -1),
1899 #network specific
1900 'virtual-device' : get_info('virtual-device', str, '??'),
1901 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1902 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1903 'mac' : get_info('mac', str, '??'),
1904 #block-device specific
1905 'ring-ref' : get_info('ring-ref', int, -1),
1908 def arg_check_for_resource_list(args, name):
1909 use_long = 0
1910 try:
1911 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1912 except getopt.GetoptError, opterr:
1913 err(opterr)
1914 sys.exit(1)
1916 for (k, v) in options:
1917 if k in ['-l', '--long']:
1918 use_long = 1
1920 if len(params) == 0:
1921 print 'No domain parameter given'
1922 usage(name)
1923 if len(params) > 1:
1924 print 'No multiple domain parameters allowed'
1925 usage(name)
1927 return (use_long, params)
1929 def xm_network_list(args):
1930 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1932 dom = params[0]
1934 if serverType == SERVER_XEN_API:
1935 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1936 vif_properties = \
1937 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1938 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
1939 zip(range(len(vif_properties)), vif_properties))
1940 else:
1941 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1943 if use_long:
1944 map(PrettyPrint.prettyprint, devs)
1945 else:
1946 hdr = 0
1947 for x in devs:
1948 if hdr == 0:
1949 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1950 hdr = 1
1951 ni = parse_dev_info(x[1])
1952 ni['idx'] = int(x[0])
1953 print ("%(idx)-3d "
1954 "%(backend-id)-3d"
1955 "%(mac)-17s "
1956 "%(handle)-3d "
1957 "%(state)-3d "
1958 "%(event-ch)-3d "
1959 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1960 "%(be-path)-30s "
1961 % ni)
1963 def xm_block_list(args):
1964 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1966 dom = params[0]
1968 if serverType == SERVER_XEN_API:
1969 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1970 vbd_properties = \
1971 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
1972 vbd_devs = \
1973 map(server.xenapi.VBD.get_device, vbd_refs)
1974 vbd_devids = \
1975 map(blkdev_name_to_number, vbd_devs)
1976 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
1977 zip(vbd_devids, vbd_properties))
1978 else:
1979 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1981 if use_long:
1982 map(PrettyPrint.prettyprint, devs)
1983 else:
1984 hdr = 0
1985 for x in devs:
1986 if hdr == 0:
1987 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1988 hdr = 1
1989 ni = parse_dev_info(x[1])
1990 ni['idx'] = int(x[0])
1991 print ("%(idx)-3d "
1992 "%(backend-id)-3d "
1993 "%(handle)-3d "
1994 "%(state)-3d "
1995 "%(event-ch)-3d "
1996 "%(ring-ref)-5d "
1997 "%(be-path)-30s "
1998 % ni)
2000 def xm_vtpm_list(args):
2001 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
2003 dom = params[0]
2005 if serverType == SERVER_XEN_API:
2006 vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom))
2007 vtpm_properties = \
2008 map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs)
2009 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
2010 zip(range(len(vtpm_properties)), vtpm_properties))
2011 else:
2012 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
2014 if use_long:
2015 map(PrettyPrint.prettyprint, devs)
2016 else:
2017 hdr = 0
2018 for x in devs:
2019 if hdr == 0:
2020 print 'Idx BE handle state evt-ch ring-ref BE-path'
2021 hdr = 1
2022 ni = parse_dev_info(x[1])
2023 ni['idx'] = int(x[0])
2024 print ("%(idx)-3d "
2025 "%(backend-id)-3d "
2026 "%(handle)-3d "
2027 "%(state)-3d "
2028 "%(event-ch)-3d "
2029 "%(ring-ref)-5d "
2030 "%(be-path)-30s "
2031 % ni)
2034 def parse_block_configuration(args):
2035 dom = args[0]
2037 if args[1].startswith('tap:'):
2038 cls = 'tap'
2039 else:
2040 cls = 'vbd'
2042 vbd = [cls,
2043 ['uname', args[1]],
2044 ['dev', args[2]],
2045 ['mode', args[3]]]
2046 if len(args) == 5:
2047 vbd.append(['backend', args[4]])
2049 return (dom, vbd)
2052 def xm_block_attach(args):
2053 arg_check(args, 'block-attach', 4, 5)
2055 if serverType == SERVER_XEN_API:
2056 dom = args[0]
2057 uname = args[1]
2058 dev = args[2]
2059 mode = args[3]
2061 # First create new VDI
2062 vdi_record = {
2063 "name_label": "vdi" + str(uname.__hash__()),
2064 "name_description": "",
2065 "SR": get_default_SR(),
2066 "virtual_size": 0,
2067 "sector_size": 512,
2068 "type": "system",
2069 "sharable": False,
2070 "read_only": mode!="w",
2071 "other_config": {"location": uname}
2074 vdi_ref = server.xenapi.VDI.create(vdi_record)
2076 # Now create new VBD
2078 vbd_record = {
2079 "VM": get_single_vm(dom),
2080 "VDI": vdi_ref,
2081 "device": dev,
2082 "bootable": True,
2083 "mode": mode=="w" and "RW" or "RO",
2084 "type": "Disk",
2085 "qos_algorithm_type": "",
2086 "qos_algorithm_params": {}
2089 server.xenapi.VBD.create(vbd_record)
2091 else:
2092 (dom, vbd) = parse_block_configuration(args)
2093 server.xend.domain.device_create(dom, vbd)
2096 def xm_block_configure(args):
2097 arg_check(args, 'block-configure', 4, 5)
2099 (dom, vbd) = parse_block_configuration(args)
2100 server.xend.domain.device_configure(dom, vbd)
2103 def xm_network_attach(args):
2104 arg_check(args, 'network-attach', 1, 10)
2106 dom = args[0]
2107 vif = ['vif']
2108 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2109 'backend', 'vifname', 'rate', 'model']
2111 if serverType == SERVER_XEN_API:
2112 vif_record = {
2113 "device": "eth0",
2114 "network": get_default_Network(),
2115 "VM": get_single_vm(dom),
2116 "MAC": "",
2117 "MTU": "",
2118 "qos_algorithm_type": "",
2119 "qos_algorithm_params": {},
2120 "other_config": {}
2123 def set(keys, val):
2124 record = vif_record
2125 for key in keys[:-1]:
2126 record = record[key]
2127 record[keys[-1]] = val
2129 def get_net_from_bridge(bridge):
2130 # In OSS, we just assert network.name_label == bridge name
2131 networks = dict([(record['name_label'], ref)
2132 for ref, record in server.xenapi.network
2133 .get_all_records().items()])
2134 if bridge not in networks.keys():
2135 raise "Unknown bridge name!"
2136 return networks[bridge]
2138 vif_conv = {
2139 'type':
2140 lambda x: None,
2141 'mac':
2142 lambda x: set(['MAC'], x),
2143 'bridge':
2144 lambda x: set(['network'], get_net_from_bridge(x)),
2145 'ip':
2146 lambda x: set(['other_config', 'ip'], x),
2147 'script':
2148 lambda x: set(['other_config', 'script'], x),
2149 'backend':
2150 lambda x: set(['other_config', 'backend'], x),
2151 'vifname':
2152 lambda x: set(['device'], x),
2153 'rate':
2154 lambda x: set(['qos_algorithm_params', 'rate'], x),
2155 'model':
2156 lambda x: None
2159 for a in args[1:]:
2160 vif_param = a.split("=")
2161 if len(vif_param) != 2 or vif_param[1] == '' or \
2162 vif_param[0] not in vif_params:
2163 err("Invalid argument: %s" % a)
2164 usage('network-attach')
2165 else:
2166 vif_conv[vif_param[0]](vif_param[1])
2168 server.xenapi.VIF.create(vif_record)
2169 else:
2170 for a in args[1:]:
2171 vif_param = a.split("=")
2172 if len(vif_param) != 2 or vif_param[1] == '' or \
2173 vif_param[0] not in vif_params:
2174 err("Invalid argument: %s" % a)
2175 usage('network-attach')
2176 vif.append(vif_param)
2177 server.xend.domain.device_create(dom, vif)
2180 def detach(args, deviceClass):
2181 dom = args[0]
2182 dev = args[1]
2183 try:
2184 force = args[2]
2185 if (force != "--force") and (force != "-f"):
2186 print "Ignoring option %s"%(force)
2187 force = None
2188 except IndexError:
2189 force = None
2191 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
2194 def xm_block_detach(args):
2195 if serverType == SERVER_XEN_API:
2196 arg_check(args, "xm_block_detach", 2, 3)
2197 dom = args[0]
2198 dev = args[1]
2199 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2200 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2201 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2202 if len(vbd_refs) > 0:
2203 vbd_ref = vbd_refs[0]
2204 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2206 server.xenapi.VBD.destroy(vbd_ref)
2208 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2209 server.xenapi.VDI.destroy(vdi_ref)
2210 else:
2211 raise OptionError("Cannot find device '%s' in domain '%s'"
2212 % (dev,dom))
2213 else:
2214 arg_check(args, 'block-detach', 2, 3)
2215 try:
2216 detach(args, 'vbd')
2217 return
2218 except:
2219 pass
2220 detach(args, 'tap')
2222 def xm_network_detach(args):
2223 if serverType == SERVER_XEN_API:
2224 arg_check(args, "xm_network_detach", 2, 3)
2225 dom = args[0]
2226 devid = args[1]
2227 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2228 vif_refs = [vif_ref for vif_ref in vif_refs
2229 if server.xenapi.VIF.\
2230 get_runtime_properties(vif_ref)["handle"] == devid]
2231 if len(vif_refs) > 0:
2232 vif_ref = vif_refs[0]
2234 server.xenapi.VIF.destroy(vif_ref)
2235 else:
2236 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2237 else:
2238 arg_check(args, 'network-detach', 2, 3)
2239 detach(args, 'vif')
2242 def xm_vnet_list(args):
2243 xenapi_unsupported()
2244 try:
2245 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2246 except getopt.GetoptError, opterr:
2247 err(opterr)
2248 usage('vnet-list')
2250 use_long = 0
2251 for (k, v) in options:
2252 if k in ['-l', '--long']:
2253 use_long = 1
2255 if params:
2256 use_long = 1
2257 vnets = params
2258 else:
2259 vnets = server.xend_vnets()
2261 for vnet in vnets:
2262 try:
2263 if use_long:
2264 info = server.xend_vnet(vnet)
2265 PrettyPrint.prettyprint(info)
2266 else:
2267 print vnet
2268 except Exception, ex:
2269 print vnet, ex
2271 def xm_vnet_create(args):
2272 xenapi_unsupported()
2273 arg_check(args, "vnet-create", 1)
2274 conf = args[0]
2275 if not os.access(conf, os.R_OK):
2276 print "File not found: %s" % conf
2277 sys.exit(1)
2279 server.xend_vnet_create(conf)
2281 def xm_vnet_delete(args):
2282 xenapi_unsupported()
2283 arg_check(args, "vnet-delete", 1)
2284 vnet = args[0]
2285 server.xend_vnet_delete(vnet)
2287 def xm_network_new(args):
2288 xenapi_only()
2289 arg_check(args, "network-new", 1)
2290 network = args[0]
2292 record = {
2293 "name_label": network,
2294 "name_description": "",
2295 "other_config": {},
2296 "default_gateway": "",
2297 "default_netmask": ""
2300 server.xenapi.network.create(record)
2302 def xm_network_del(args):
2303 xenapi_only()
2304 arg_check(args, "network-del", 1)
2305 network = args[0]
2307 networks = dict([(record['name_label'], ref)
2308 for ref, record in
2309 server.xenapi.network.get_all_records().items()])
2311 if network not in networks.keys():
2312 raise ValueError("'%s' is not a valid network name" % network)
2314 server.xenapi.network.destroy(networks[network])
2316 def xm_network_show(args):
2317 xenapi_only()
2318 arg_check(args, "network-show", 0)
2320 networks = server.xenapi.network.get_all_records()
2321 pifs = server.xenapi.PIF.get_all_records()
2322 vifs = server.xenapi.VIF.get_all_records()
2324 print '%-20s %-40s %-10s' % \
2325 ('Name', 'VIFs', 'PIFs')
2327 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2329 for network_ref, network in networks.items():
2330 for i in range(max(len(network['PIFs']),
2331 len(network['VIFs']), 1)):
2332 if i < len(network['PIFs']):
2333 pif_uuid = network['PIFs'][i]
2334 else:
2335 pif_uuid = None
2337 if i < len(network['VIFs']):
2338 vif_uuid = network['VIFs'][i]
2339 else:
2340 vif_uuid = None
2342 pif = pifs.get(pif_uuid, None)
2343 vif = vifs.get(vif_uuid, None)
2345 if vif:
2346 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2347 vif = "%s.%s" % (dom_name, vif['device'])
2348 else:
2349 vif = ''
2351 if pif:
2352 if int(pif['VLAN']) > -1:
2353 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2354 else:
2355 pif = pif['device']
2356 else:
2357 pif = ''
2359 if i == 0:
2360 r = {'name_label':network['name_label'],
2361 'vif':vif, 'pif':pif}
2362 else:
2363 r = {'name_label':'', 'vif':vif, 'pif':pif}
2365 print format2 % r
2368 commands = {
2369 "shell": xm_shell,
2370 "event-monitor": xm_event_monitor,
2371 # console commands
2372 "console": xm_console,
2373 # xenstat commands
2374 "top": xm_top,
2375 # domain commands
2376 "delete": xm_delete,
2377 "destroy": xm_destroy,
2378 "domid": xm_domid,
2379 "domname": xm_domname,
2380 "dump-core": xm_dump_core,
2381 "reboot": xm_reboot,
2382 "rename": xm_rename,
2383 "restore": xm_restore,
2384 "resume": xm_resume,
2385 "save": xm_save,
2386 "shutdown": xm_shutdown,
2387 "start": xm_start,
2388 "sysrq": xm_sysrq,
2389 "trigger": xm_trigger,
2390 "uptime": xm_uptime,
2391 "suspend": xm_suspend,
2392 "list": xm_list,
2393 # memory commands
2394 "mem-max": xm_mem_max,
2395 "mem-set": xm_mem_set,
2396 # cpu commands
2397 "vcpu-pin": xm_vcpu_pin,
2398 "vcpu-list": xm_vcpu_list,
2399 "vcpu-set": xm_vcpu_set,
2400 # special
2401 "pause": xm_pause,
2402 "unpause": xm_unpause,
2403 # host commands
2404 "debug-keys": xm_debug_keys,
2405 "dmesg": xm_dmesg,
2406 "info": xm_info,
2407 "log": xm_log,
2408 "serve": xm_serve,
2409 # scheduler
2410 "sched-sedf": xm_sched_sedf,
2411 "sched-credit": xm_sched_credit,
2412 # block
2413 "block-attach": xm_block_attach,
2414 "block-detach": xm_block_detach,
2415 "block-list": xm_block_list,
2416 "block-configure": xm_block_configure,
2417 # network (AKA vifs)
2418 "network-attach": xm_network_attach,
2419 "network-detach": xm_network_detach,
2420 "network-list": xm_network_list,
2421 # network (as in XenAPI)
2422 "network-new": xm_network_new,
2423 "network-del": xm_network_del,
2424 "network-show": xm_network_show,
2425 # vnet
2426 "vnet-list": xm_vnet_list,
2427 "vnet-create": xm_vnet_create,
2428 "vnet-delete": xm_vnet_delete,
2429 # vtpm
2430 "vtpm-list": xm_vtpm_list,
2433 ## The commands supported by a separate argument parser in xend.xm.
2434 IMPORTED_COMMANDS = [
2435 'create',
2436 'new',
2437 'migrate',
2438 'labels',
2439 'cfgbootpolicy',
2440 'makepolicy',
2441 'loadpolicy',
2442 'dumppolicy',
2443 'addlabel',
2444 'rmlabel',
2445 'getlabel',
2446 'dry-run',
2447 'resources',
2448 'getpolicy',
2449 'setpolicy',
2450 'activatepolicy',
2453 for c in IMPORTED_COMMANDS:
2454 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2456 aliases = {
2457 "balloon": "mem-set",
2458 "set-vcpus": "vcpu-set",
2459 "vif-list": "network-list",
2460 "vbd-create": "block-attach",
2461 "vbd-destroy": "block-detach",
2462 "vbd-list": "block-list",
2466 def xm_lookup_cmd(cmd):
2467 if commands.has_key(cmd):
2468 return commands[cmd]
2469 elif aliases.has_key(cmd):
2470 deprecated(cmd,aliases[cmd])
2471 return commands[aliases[cmd]]
2472 elif cmd == 'help':
2473 longHelp()
2474 sys.exit(0)
2475 else:
2476 # simulate getopt's prefix matching behaviour
2477 if len(cmd) > 1:
2478 same_prefix_cmds = [commands[c] for c in commands.keys() \
2479 if c[:len(cmd)] == cmd]
2480 # only execute if there is only 1 match
2481 if len(same_prefix_cmds) == 1:
2482 return same_prefix_cmds[0]
2483 return None
2485 def deprecated(old,new):
2486 print >>sys.stderr, (
2487 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2489 def main(argv=sys.argv):
2490 if len(argv) < 2:
2491 usage()
2493 # intercept --help(-h) and output our own help
2494 for help in ['--help', '-h']:
2495 if help in argv[1:]:
2496 if help == argv[1]:
2497 longHelp()
2498 sys.exit(0)
2499 else:
2500 usage(argv[1])
2502 cmd_name = argv[1]
2503 cmd = xm_lookup_cmd(cmd_name)
2504 if cmd:
2505 # strip off prog name and subcmd
2506 args = argv[2:]
2507 _, rc = _run_cmd(cmd, cmd_name, args)
2508 sys.exit(rc)
2509 else:
2510 err('Subcommand %s not found!' % cmd_name)
2511 usage()
2513 def _run_cmd(cmd, cmd_name, args):
2514 global server
2516 try:
2517 if server is None:
2518 if serverType == SERVER_XEN_API:
2519 server = XenAPI.Session(serverURI)
2520 username, password = parseAuthentication()
2521 server.login_with_password(username, password)
2522 def logout():
2523 try:
2524 server.xenapi.session.logout()
2525 except:
2526 pass
2527 atexit.register(logout)
2528 else:
2529 server = ServerProxy(serverURI)
2531 return True, cmd(args)
2532 except socket.error, ex:
2533 if os.geteuid() != 0:
2534 err("Most commands need root access. Please try again as root.")
2535 else:
2536 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2537 except KeyboardInterrupt:
2538 print "Interrupted."
2539 return True, ''
2540 except IOError, ex:
2541 if os.geteuid() != 0:
2542 err("Most commands need root access. Please try again as root.")
2543 else:
2544 err("Unable to connect to xend: %s." % ex[1])
2545 except SystemExit, code:
2546 return code == 0, code
2547 except XenAPI.Failure, exn:
2548 for line in [''] + wrap(str(exn), 80) + ['']:
2549 print >>sys.stderr, line
2550 except xmlrpclib.Fault, ex:
2551 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2552 err("Domain '%s' does not exist." % ex.faultString)
2553 else:
2554 err(ex.faultString)
2555 _usage(cmd_name)
2556 except xmlrpclib.ProtocolError, ex:
2557 if ex.errcode == -1:
2558 print >>sys.stderr, (
2559 "Xend has probably crashed! Invalid or missing HTTP "
2560 "status code.")
2561 else:
2562 print >>sys.stderr, (
2563 "Xend has probably crashed! ProtocolError(%d, %s)." %
2564 (ex.errcode, ex.errmsg))
2565 except (ValueError, OverflowError):
2566 err("Invalid argument.")
2567 _usage(cmd_name)
2568 except OptionError, e:
2569 err(str(e))
2570 _usage(cmd_name)
2571 print e.usage
2572 except XenAPIUnsupportedException, e:
2573 err(str(e))
2574 except ACMError, e:
2575 err(str(e))
2576 except Exception, e:
2577 if serverType != SERVER_XEN_API:
2578 from xen.util import security
2579 if isinstance(e, security.ACMError):
2580 err(str(e))
2581 return False, 1
2582 print "Unexpected error:", sys.exc_info()[0]
2583 print
2584 print "Please report to xen-devel@lists.xensource.com"
2585 raise
2587 return False, 1
2589 if __name__ == "__main__":
2590 main()