ia64/xen-unstable

view tools/python/xen/xm/main.py @ 15332:e1c54c14220a

Fix xm vcpu-pin command for keyword 'all'.

The keyword 'all' was supported as the 2nd argument of xm vcpu-pin
command since changeset 11619. However, we cannot use the keyword
'all' since changeset 14481.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Tue Jun 12 11:29:27 2007 +0100 (2007-06-12)
parents 9073caff4b63
children 7a31e37fec9e
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
54 import XenAPI
57 # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
58 # getopt.getopt if gnu_getopt is not available. This will mean that options
59 # may only be specified before positional arguments.
60 if not hasattr(getopt, 'gnu_getopt'):
61 getopt.gnu_getopt = getopt.getopt
63 XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
64 XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
66 # Supported types of server
67 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
68 SERVER_XEN_API = 'Xen-API'
70 # General help message
72 USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
73 "Control, list, and manipulate Xen guest instances.\n"
75 USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
76 'For more help on \'xm\' see the xm(1) man page.\n' \
77 'For more help on \'xm create\' see the xmdomain.cfg(5) '\
78 ' man page.\n'
80 # Help strings are indexed by subcommand name in this way:
81 # 'subcommand': (argstring, description)
83 SUBCOMMAND_HELP = {
84 # common commands
86 'shell' : ('', 'Launch an interactive shell.'),
88 'console' : ('[-q|--quiet] <Domain>',
89 'Attach to <Domain>\'s console.'),
90 'create' : ('<ConfigFile> [options] [vars]',
91 'Create a domain based on <ConfigFile>.'),
92 'destroy' : ('<Domain>',
93 'Terminate a domain immediately.'),
94 'help' : ('', 'Display this message.'),
95 'list' : ('[options] [Domain, ...]',
96 'List information about all/some domains.'),
97 'mem-max' : ('<Domain> <Mem>',
98 'Set the maximum amount reservation for a domain.'),
99 'mem-set' : ('<Domain> <Mem>',
100 'Set the current memory usage for a domain.'),
101 'migrate' : ('<Domain> <Host>',
102 'Migrate a domain to another machine.'),
103 'pause' : ('<Domain>', 'Pause execution of a domain.'),
104 'reboot' : ('<Domain> [-wa]', 'Reboot a domain.'),
105 'restore' : ('<CheckpointFile> [-p]',
106 'Restore a domain from a saved state.'),
107 'save' : ('[-c] <Domain> <CheckpointFile>',
108 'Save a domain state to restore later.'),
109 'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
110 'top' : ('', 'Monitor a host and the domains in real time.'),
111 'unpause' : ('<Domain>', 'Unpause a paused domain.'),
112 'uptime' : ('[-s] <Domain>', 'Print uptime for a domain.'),
114 # Life cycle xm commands
115 'new' : ('<ConfigFile> [options] [vars]',
116 'Adds a domain to Xend domain management'),
117 'delete' : ('<DomainName>',
118 'Remove a domain from Xend domain management.'),
119 'start' : ('<DomainName>', 'Start a Xend managed domain'),
120 'resume' : ('<DomainName>', 'Resume a Xend managed domain'),
121 'suspend' : ('<DomainName>', 'Suspend a Xend managed domain'),
123 # less used commands
125 'dmesg' : ('[-c|--clear]',
126 'Read and/or clear Xend\'s message buffer.'),
127 'domid' : ('<DomainName>', 'Convert a domain name to domain id.'),
128 'domname' : ('<DomId>', 'Convert a domain id to domain name.'),
129 'dump-core' : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
130 'Dump core for a specific domain.'),
131 'info' : ('', 'Get information about Xen host.'),
132 'log' : ('', 'Print Xend log'),
133 'rename' : ('<Domain> <NewDomainName>', 'Rename a domain.'),
134 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
135 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
136 'Get/set credit scheduler parameters.'),
137 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
138 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
139 'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
140 'Send a trigger to a domain.'),
141 'vcpu-list' : ('[<Domain>]',
142 'List the VCPUs for a domain or all domains.'),
143 'vcpu-pin' : ('<Domain> <VCPU|all> <CPUs|all>',
144 'Set which CPUs a VCPU can use.'),
145 'vcpu-set' : ('<Domain> <vCPUs>',
146 'Set the number of active VCPUs for allowed for the'
147 ' domain.'),
149 # device commands
151 'block-attach' : ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
152 'Create a new virtual block device.'),
153 'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomain]',
154 'Change block device configuration'),
155 'block-detach' : ('<Domain> <DevId> [-f|--force]',
156 'Destroy a domain\'s virtual block device.'),
157 'block-list' : ('<Domain> [--long]',
158 'List virtual block devices for a domain.'),
159 'network-attach': ('<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] '
160 '[ip=<ip>] [script=<script>] [backend=<BackDomain>] '
161 '[vifname=<name>] [rate=<rate>] [model=<model>]',
162 'Create a new virtual network device.'),
163 'network-detach': ('<Domain> <DevId> [-f|--force]',
164 'Destroy a domain\'s virtual network device.'),
165 'network-list' : ('<Domain> [--long]',
166 'List virtual network interfaces for a domain.'),
167 'vnet-create' : ('<ConfigFile>','Create a vnet from ConfigFile.'),
168 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'),
169 'vnet-list' : ('[-l|--long]', 'List Vnets.'),
170 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'),
172 # security
174 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
175 'Add security label to domain.'),
176 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}',
177 'Remove a security label from domain.'),
178 'getlabel' : ('{dom <ConfigFile>|res <Resource>}',
179 'Show security label for domain or resource.'),
180 'dry-run' : ('<ConfigFile>',
181 'Test if a domain can access its resources.'),
182 'resources' : ('', 'Show info for each labeled resource.'),
183 'cfgbootpolicy' : ('<policy> [boot-title]',
184 'Add policy to boot configuration.'),
185 'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
186 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
187 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
188 'files.'),
189 'labels' : ('[policy] [type=dom|res|any]',
190 'List <type> labels for (active) policy.'),
191 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
192 }
194 SUBCOMMAND_OPTIONS = {
195 'sched-sedf': (
196 ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
197 ('-s [MS]', '--slice[=MS]' ,
198 'Worst-case execution time(ms). (slice < period)'),
199 ('-l [MS]', '--latency[=MS]',
200 'Scaled period (ms) when domain performs heavy I/O'),
201 ('-e [FLAG]', '--extra[=FLAG]',
202 'Flag (0 or 1) controls if domain can run in extra time.'),
203 ('-w [FLOAT]', '--weight[=FLOAT]',
204 'CPU Period/slice (do not set with --period/--slice)'),
205 ),
206 'sched-credit': (
207 ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
208 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
209 ('-c CAP', '--cap=CAP', 'Cap (int)'),
210 ),
211 'list': (
212 ('-l', '--long', 'Output all VM details in SXP'),
213 ('', '--label', 'Include security labels'),
214 ('', '--state=<state>', 'Select only VMs with the specified state'),
215 ),
216 'console': (
217 ('-q', '--quiet', 'Do not print an error message if the domain does not exist'),
218 ),
219 'dmesg': (
220 ('-c', '--clear', 'Clear dmesg buffer as well as printing it'),
221 ),
222 'vnet-list': (
223 ('-l', '--long', 'List Vnets as SXP'),
224 ),
225 'network-list': (
226 ('-l', '--long', 'List resources as SXP'),
227 ),
228 'dump-core': (
229 ('-L', '--live', 'Dump core without pausing the domain'),
230 ('-C', '--crash', 'Crash domain after dumping core'),
231 ),
232 'start': (
233 ('-p', '--paused', 'Do not unpause domain after starting it'),
234 ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'),
235 ),
236 'resume': (
237 ('-p', '--paused', 'Do not unpause domain after resuming it'),
238 ),
239 'save': (
240 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
241 ),
242 'restore': (
243 ('-p', '--paused', 'Do not unpause domain after restoring it'),
244 ),
245 }
247 common_commands = [
248 "console",
249 "create",
250 "new",
251 "delete",
252 "destroy",
253 "dump-core",
254 "help",
255 "list",
256 "mem-set",
257 "migrate",
258 "pause",
259 "reboot",
260 "restore",
261 "resume",
262 "save",
263 "shell",
264 "shutdown",
265 "start",
266 "suspend",
267 "top",
268 "unpause",
269 "uptime",
270 "vcpu-set",
271 ]
273 domain_commands = [
274 "console",
275 "create",
276 "new",
277 "delete",
278 "destroy",
279 "domid",
280 "domname",
281 "dump-core",
282 "list",
283 "mem-max",
284 "mem-set",
285 "migrate",
286 "pause",
287 "reboot",
288 "rename",
289 "restore",
290 "resume",
291 "save",
292 "shutdown",
293 "start",
294 "suspend",
295 "sysrq",
296 "trigger",
297 "top",
298 "unpause",
299 "uptime",
300 "vcpu-list",
301 "vcpu-pin",
302 "vcpu-set",
303 ]
305 host_commands = [
306 "debug-keys",
307 "dmesg",
308 "info",
309 "log",
310 "serve",
311 ]
313 scheduler_commands = [
314 "sched-credit",
315 "sched-sedf",
316 ]
318 device_commands = [
319 "block-attach",
320 "block-detach",
321 "block-list",
322 "block-configure",
323 "network-attach",
324 "network-detach",
325 "network-list",
326 "vtpm-list",
327 ]
329 vnet_commands = [
330 "vnet-list",
331 "vnet-create",
332 "vnet-delete",
333 ]
335 acm_commands = [
336 "labels",
337 "addlabel",
338 "rmlabel",
339 "getlabel",
340 "dry-run",
341 "resources",
342 "makepolicy",
343 "loadpolicy",
344 "cfgbootpolicy",
345 "dumppolicy",
346 ]
348 all_commands = (domain_commands + host_commands + scheduler_commands +
349 device_commands + vnet_commands + acm_commands +
350 ['shell', 'event-monitor'])
353 ##
354 # Configuration File Parsing
355 ##
357 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
358 config = None
359 if os.path.isfile(xmConfigFile):
360 try:
361 config = xml.dom.minidom.parse(xmConfigFile)
362 except:
363 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
364 xmConfigFile)
366 def parseServer():
367 if config:
368 server = config.getElementsByTagName('server')
369 if server:
370 st = server[0].getAttribute('type')
371 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
372 print >>sys.stderr, ('Invalid server type %s; using %s.' %
373 (st, SERVER_LEGACY_XMLRPC))
374 st = SERVER_LEGACY_XMLRPC
375 return (st, server[0].getAttribute('uri'))
377 return SERVER_LEGACY_XMLRPC, XendClient.uri
379 def parseAuthentication():
380 server = config.getElementsByTagName('server')[0]
381 return (server.getAttribute('username'),
382 server.getAttribute('password'))
384 serverType, serverURI = parseServer()
385 server = None
388 ####################################################################
389 #
390 # Help/usage printing functions
391 #
392 ####################################################################
394 def cmdHelp(cmd):
395 """Print help for a specific subcommand."""
397 for fc in SUBCOMMAND_HELP.keys():
398 if fc[:len(cmd)] == cmd:
399 cmd = fc
400 break
402 try:
403 args, desc = SUBCOMMAND_HELP[cmd]
404 except KeyError:
405 shortHelp()
406 return
408 print 'Usage: xm %s %s' % (cmd, args)
409 print
410 print desc
412 try:
413 # If options help message is defined, print this.
414 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
415 if shortopt and longopt:
416 optdesc = '%s, %s' % (shortopt, longopt)
417 elif shortopt:
418 optdesc = shortopt
419 elif longopt:
420 optdesc = longopt
422 wrapped_desc = wrap(desc, 43)
423 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
424 for line in wrapped_desc[1:]:
425 print ' ' * 33 + line
426 print
427 except KeyError:
428 # if the command is an external module, we grab usage help
429 # from the module itself.
430 if cmd in IMPORTED_COMMANDS:
431 try:
432 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
433 cmd_usage = getattr(cmd_module, "help", None)
434 if cmd_usage:
435 print cmd_usage()
436 except ImportError:
437 pass
439 def shortHelp():
440 """Print out generic help when xm is called without subcommand."""
442 print USAGE_HELP
443 print 'Common \'xm\' commands:\n'
445 for command in common_commands:
446 try:
447 args, desc = SUBCOMMAND_HELP[command]
448 except KeyError:
449 continue
450 wrapped_desc = wrap(desc, 50)
451 print ' %-20s %-50s' % (command, wrapped_desc[0])
452 for line in wrapped_desc[1:]:
453 print ' ' * 22 + line
455 print
456 print USAGE_FOOTER
457 print 'For a complete list of subcommands run \'xm help\'.'
459 def longHelp():
460 """Print out full help when xm is called with xm --help or xm help"""
462 print USAGE_HELP
463 print 'xm full list of subcommands:\n'
465 for command in all_commands:
466 try:
467 args, desc = SUBCOMMAND_HELP[command]
468 except KeyError:
469 continue
471 wrapped_desc = wrap(desc, 50)
472 print ' %-20s %-50s' % (command, wrapped_desc[0])
473 for line in wrapped_desc[1:]:
474 print ' ' * 22 + line
476 print
477 print USAGE_FOOTER
479 def _usage(cmd):
480 """ Print help usage information """
481 if cmd:
482 cmdHelp(cmd)
483 else:
484 shortHelp()
486 def usage(cmd = None):
487 """ Print help usage information and exits """
488 _usage(cmd)
489 sys.exit(1)
492 ####################################################################
493 #
494 # Utility functions
495 #
496 ####################################################################
498 def get_default_SR():
499 return [sr_ref
500 for sr_ref in server.xenapi.SR.get_all()
501 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
503 def get_default_Network():
504 return [network_ref
505 for network_ref in server.xenapi.network.get_all()][0]
507 class XenAPIUnsupportedException(Exception):
508 pass
510 def xenapi_unsupported():
511 if serverType == SERVER_XEN_API:
512 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
514 def xenapi_only():
515 if serverType != SERVER_XEN_API:
516 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
518 def map2sxp(m):
519 return [[k, m[k]] for k in m.keys()]
521 def arg_check(args, name, lo, hi = -1):
522 n = len([i for i in args if i != '--'])
524 if hi == -1:
525 if n != lo:
526 err("'xm %s' requires %d argument%s.\n" % (name, lo,
527 lo == 1 and '' or 's'))
528 usage(name)
529 else:
530 if n < lo or n > hi:
531 err("'xm %s' requires between %d and %d arguments.\n" %
532 (name, lo, hi))
533 usage(name)
536 def unit(c):
537 if not c.isalpha():
538 return 0
539 base = 1
540 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
541 elif c == 'M' or c == 'm': base = 1024 * 1024
542 elif c == 'K' or c == 'k': base = 1024
543 else:
544 print 'ignoring unknown unit'
545 return base
547 def int_unit(str, dest):
548 base = unit(str[-1])
549 if not base:
550 return int(str)
552 value = int(str[:-1])
553 dst_base = unit(dest)
554 if dst_base == 0:
555 dst_base = 1
556 if dst_base > base:
557 return value / (dst_base / base)
558 else:
559 return value * (base / dst_base)
561 def err(msg):
562 print >>sys.stderr, "Error:", msg
565 def get_single_vm(dom):
566 if serverType == SERVER_XEN_API:
567 uuids = server.xenapi.VM.get_by_name_label(dom)
568 if len(uuids) > 0:
569 return uuids[0]
571 refs = []
573 try:
574 domid = int(dom)
575 refs = [vm_ref
576 for vm_ref in server.xenapi.VM.get_all()
577 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
578 except:
579 pass
581 if len(refs) > 0:
582 return refs[0]
584 raise OptionError("Domain '%s' not found." % dom)
585 else:
586 dominfo = server.xend.domain(dom, False)
587 return dominfo['uuid']
589 ##
590 #
591 # Xen-API Shell
592 #
593 ##
595 class Shell(cmd.Cmd):
596 def __init__(self):
597 cmd.Cmd.__init__(self)
598 self.prompt = "xm> "
599 if serverType == SERVER_XEN_API:
600 try:
601 res = server.xenapi.host.list_methods()
602 for f in res:
603 setattr(Shell, 'do_' + f + ' ', self.default)
604 except:
605 pass
607 def preloop(self):
608 cmd.Cmd.preloop(self)
609 readline.set_completer_delims(' ')
611 def default(self, line):
612 words = shlex.split(line)
613 if len(words) > 0 and words[0] == 'xm':
614 words = words[1:]
615 if len(words) > 0:
616 cmd = xm_lookup_cmd(words[0])
617 if cmd:
618 _run_cmd(cmd, words[0], words[1:])
619 elif serverType == SERVER_XEN_API:
620 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
621 tuple(x)),
622 words[0], words[1:])
623 if ok and res is not None and res != '':
624 pprint.pprint(res)
625 else:
626 print '*** Unknown command: %s' % words[0]
627 return False
629 def completedefault(self, text, line, begidx, endidx):
630 words = shlex.split(line[:begidx])
631 clas, func = words[0].split('.')
632 if len(words) > 1 or \
633 func.startswith('get_by_') or \
634 func == 'get_all':
635 return []
636 uuids = server.xenapi_request('%s.get_all' % clas, ())
637 return [u + " " for u in uuids if u.startswith(text)]
639 def emptyline(self):
640 pass
642 def do_EOF(self, line):
643 print
644 sys.exit(0)
646 def do_help(self, line):
647 _usage(line)
650 def xm_shell(args):
651 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
654 def xm_event_monitor(args):
655 if serverType == SERVER_XEN_API:
656 while True:
657 server.xenapi.event.register(args)
658 events = server.xenapi.event.next()
659 for e in events:
660 print e
661 else:
662 err("Event monitoring not supported unless using Xen-API.")
665 #########################################################################
666 #
667 # Main xm functions
668 #
669 #########################################################################
671 def xm_save(args):
673 arg_check(args, "save", 2, 3)
675 try:
676 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
677 except getopt.GetoptError, opterr:
678 err(opterr)
679 sys.exit(1)
681 dom = params[0]
682 savefile = params[1]
684 checkpoint = False
685 for (k, v) in options:
686 if k in ['-c', '--checkpoint']:
687 checkpoint = True
689 if len(params) != 2:
690 err("Wrong number of parameters")
691 usage('save')
692 sys.exit(1)
694 savefile = os.path.abspath(savefile)
696 if not os.access(os.path.dirname(savefile), os.W_OK):
697 err("xm save: Unable to create file %s" % savefile)
698 sys.exit(1)
700 if serverType == SERVER_XEN_API:
701 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
702 else:
703 try:
704 dominfo = parse_doms_info(server.xend.domain(dom))
705 except xmlrpclib.Fault, ex:
706 raise ex
708 domid = dominfo['domid']
709 server.xend.domain.save(domid, savefile, checkpoint)
711 def xm_restore(args):
712 arg_check(args, "restore", 1, 2)
714 try:
715 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
716 except getopt.GetoptError, opterr:
717 err(opterr)
718 usage('restore')
720 paused = False
721 for (k, v) in options:
722 if k in ['-p', '--paused']:
723 paused = True
725 if len(params) != 1:
726 err("Wrong number of parameters")
727 usage('restore')
729 savefile = os.path.abspath(params[0])
731 if not os.access(savefile, os.R_OK):
732 err("xm restore: Unable to read file %s" % savefile)
733 sys.exit(1)
735 try:
736 if serverType == SERVER_XEN_API:
737 server.xenapi.VM.restore(savefile, paused)
738 else:
739 server.xend.domain.restore(savefile, paused)
740 except Exception, ex:
741 err("%s" % ex.faultString)
744 def datetime_to_secs(v):
745 unwanted = ":-."
746 for c in unwanted:
747 v = str(v).replace(c, "")
748 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
750 def getDomains(domain_names, state, full = 0):
751 if serverType == SERVER_XEN_API:
752 doms_sxp = []
753 doms_dict = []
755 dom_recs = server.xenapi.VM.get_all_records()
756 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
758 for dom_ref, dom_rec in dom_recs.items():
759 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
761 states = ('running', 'blocked', 'paused', 'shutdown',
762 'crashed', 'dying')
763 def state_on_off(state):
764 if state in dom_metrics_rec['state']:
765 return state[0]
766 else:
767 return "-"
768 state_str = "".join([state_on_off(state)
769 for state in states])
771 dom_rec.update({'name': dom_rec['name_label'],
772 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
773 'vcpus': dom_metrics_rec['VCPUs_number'],
774 'state': state_str,
775 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
776 'start_time': datetime_to_secs(
777 dom_metrics_rec['start_time'])})
779 doms_sxp.append(['domain'] + map2sxp(dom_rec))
780 doms_dict.append(dom_rec)
782 if domain_names:
783 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
784 if dom["name"] in domain_names]
786 if len(doms) > 0:
787 return doms
788 else:
789 print "Error: no domain%s named %s" % \
790 (len(domain_names) > 1 and 's' or '',
791 ', '.join(domain_names))
792 sys.exit(-1)
793 else:
794 return doms_sxp
795 else:
796 if domain_names:
797 return [server.xend.domain(dom, full) for dom in domain_names]
798 else:
799 return server.xend.domains_with_state(True, state, full)
802 def xm_list(args):
803 use_long = 0
804 show_vcpus = 0
805 show_labels = 0
806 state = 'all'
807 try:
808 (options, params) = getopt.gnu_getopt(args, 'lv',
809 ['long','vcpus','label',
810 'state='])
811 except getopt.GetoptError, opterr:
812 err(opterr)
813 usage('list')
815 for (k, v) in options:
816 if k in ['-l', '--long']:
817 use_long = 1
818 if k in ['-v', '--vcpus']:
819 show_vcpus = 1
820 if k in ['--label']:
821 show_labels = 1
822 if k in ['--state']:
823 state = v
825 if state != 'all' and len(params) > 0:
826 raise OptionError(
827 "You may specify either a state or a particular VM, but not both")
829 if show_vcpus:
830 print >>sys.stderr, (
831 "xm list -v is deprecated. Please use xm vcpu-list.")
832 xm_vcpu_list(params)
833 return
835 doms = getDomains(params, state, use_long)
837 if use_long:
838 map(PrettyPrint.prettyprint, doms)
839 elif show_labels:
840 xm_label_list(doms)
841 else:
842 xm_brief_list(doms)
845 def parse_doms_info(info):
846 def get_info(n, t, d):
847 return t(sxp.child_value(info, n, d))
849 def get_status(n, t, d):
850 return DOM_STATES[t(sxp.child_value(info, n, d))]
852 start_time = get_info('start_time', float, -1)
853 if start_time == -1:
854 up_time = float(-1)
855 else:
856 up_time = time.time() - start_time
858 parsed_info = {
859 'domid' : get_info('domid', str, ''),
860 'name' : get_info('name', str, '??'),
861 'state' : get_info('state', str, ''),
863 # VCPUs is the number online when the VM is up, or the number
864 # configured otherwise.
865 'vcpus' : get_info('online_vcpus', int,
866 get_info('vcpus', int, 0)),
867 'up_time' : up_time
868 }
870 # We're not supporting security stuff just yet via XenAPI
872 if serverType != SERVER_XEN_API:
873 from xen.util import security
874 parsed_info['seclabel'] = security.get_security_printlabel(info)
875 else:
876 parsed_info['seclabel'] = ""
878 if serverType == SERVER_XEN_API:
879 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
880 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
881 if sum(cpu_times.values()) > 0:
882 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
883 else:
884 parsed_info['cpu_time'] = 0
885 else:
886 parsed_info['mem'] = get_info('memory', int,0)
887 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
889 return parsed_info
891 def check_sched_type(sched):
892 if serverType == SERVER_XEN_API:
893 current = server.xenapi.host.get_sched_policy(
894 server.xenapi.session.get_this_host(server.getSession()))
895 else:
896 current = 'unknown'
897 for x in server.xend.node.info()[1:]:
898 if len(x) > 1 and x[0] == 'xen_scheduler':
899 current = x[1]
900 break
901 if sched != current:
902 err("Xen is running with the %s scheduler" % current)
903 sys.exit(1)
905 def parse_sedf_info(info):
906 def get_info(n, t, d):
907 return t(sxp.child_value(info, n, d))
909 return {
910 'domid' : get_info('domid', int, -1),
911 'period' : get_info('period', int, -1),
912 'slice' : get_info('slice', int, -1),
913 'latency' : get_info('latency', int, -1),
914 'extratime': get_info('extratime', int, -1),
915 'weight' : get_info('weight', int, -1),
916 }
918 def domid_match(domid, info):
919 return domid is None or domid == info['name'] or \
920 domid == str(info['domid'])
922 def xm_brief_list(doms):
923 print '%-40s %5s %5s %5s %10s %9s' % \
924 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
926 format = "%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s " \
927 "%(cpu_time)8.1f"
929 for dom in doms:
930 d = parse_doms_info(dom)
931 print format % d
933 def xm_label_list(doms):
934 print '%-32s %5s %5s %5s %5s %9s %-8s' % \
935 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
937 output = []
938 format = '%(name)-32s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
939 '%(cpu_time)8.1f %(seclabel)9s'
941 if serverType != SERVER_XEN_API:
942 from xen.util import security
944 for dom in doms:
945 d = parse_doms_info(dom)
947 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
948 if not d['seclabel']:
949 d['seclabel'] = 'ERROR'
950 elif security.active_policy in ['DEFAULT']:
951 d['seclabel'] = 'DEFAULT'
952 else:
953 d['seclabel'] = 'INACTIVE'
955 output.append((format % d, d['seclabel']))
957 #sort by labels
958 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
959 for line, label in output:
960 print line
963 def xm_vcpu_list(args):
964 if serverType == SERVER_XEN_API:
965 if args:
966 vm_refs = map(get_single_vm, args)
967 else:
968 vm_refs = server.xenapi.VM.get_all()
970 vm_records = dict(map(lambda vm_ref:
971 (vm_ref, server.xenapi.VM.get_record(
972 vm_ref)),
973 vm_refs))
975 vm_metrics = dict(map(lambda (ref, record):
976 (ref,
977 server.xenapi.VM_metrics.get_record(
978 record['metrics'])),
979 vm_records.items()))
981 dominfo = []
983 # vcpu_list doesn't list 'managed' domains
984 # when they are not running, so filter them out
986 vm_refs = [vm_ref
987 for vm_ref in vm_refs
988 if vm_records[vm_ref]["power_state"] != "Halted"]
990 for vm_ref in vm_refs:
991 info = ['domain',
992 ['domid', vm_records[vm_ref]['domid']],
993 ['name', vm_records[vm_ref]['name_label']],
994 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
996 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
997 def chk_flag(flag):
998 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
999 and 1 or 0
1001 vcpu_info = ['vcpu',
1002 ['number',
1003 i],
1004 ['online',
1005 chk_flag("online")],
1006 ['blocked',
1007 chk_flag("blocked")],
1008 ['running',
1009 chk_flag("running")],
1010 ['cpu_time',
1011 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1012 ['cpu',
1013 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1014 ['cpumap',
1015 vm_metrics[vm_ref]['VCPUs_params']\
1016 ['cpumap%i' % i].split(",")]]
1018 info.append(vcpu_info)
1020 dominfo.append(info)
1021 else:
1022 if args:
1023 dominfo = map(server.xend.domain.getVCPUInfo, args)
1024 else:
1025 doms = server.xend.domains(False)
1026 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1028 print '%-32s %5s %5s %5s %5s %9s %s' % \
1029 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1031 format = '%(name)-32s %(domid)5d %(number)5d %(c)5s %(s)5s ' \
1032 ' %(cpu_time)8.1f %(cpumap)s'
1034 for dom in dominfo:
1035 def get_info(n):
1036 return sxp.child_value(dom, n)
1039 # convert a list of integers into a list of pairs indicating
1040 # continuous sequences in the list:
1042 # [0,1,2,3] -> [(0,3)]
1043 # [1,2,4,5] -> [(1,2),(4,5)]
1044 # [0] -> [(0,0)]
1045 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1047 def list_to_rangepairs(cmap):
1048 cmap.sort()
1049 pairs = []
1050 x = y = 0
1051 for i in range(0,len(cmap)):
1052 try:
1053 if ((cmap[y+1] - cmap[i]) > 1):
1054 pairs.append((cmap[x],cmap[y]))
1055 x = y = i+1
1056 else:
1057 y = y + 1
1058 # if we go off the end, then just add x to y
1059 except IndexError:
1060 pairs.append((cmap[x],cmap[y]))
1062 return pairs
1065 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1067 def format_pairs(pairs):
1068 if not pairs:
1069 return "no cpus"
1070 out = ""
1071 for f,s in pairs:
1072 if (f==s):
1073 out += '%d'%f
1074 else:
1075 out += '%d-%d'%(f,s)
1076 out += ','
1077 # trim trailing ','
1078 return out[:-1]
1080 def format_cpumap(cpumap):
1081 cpumap = map(lambda x: int(x), cpumap)
1082 cpumap.sort()
1084 if serverType == SERVER_XEN_API:
1085 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1086 server.xenapi.session.get_this_host(server.getSession())))
1087 else:
1088 for x in server.xend.node.info()[1:]:
1089 if len(x) > 1 and x[0] == 'nr_cpus':
1090 nr_cpus = int(x[1])
1092 # normalize cpumap by modulus nr_cpus, and drop duplicates
1093 cpumap = dict.fromkeys(
1094 map(lambda x: x % nr_cpus, cpumap)).keys()
1095 if len(cpumap) == nr_cpus:
1096 return "any cpu"
1098 return format_pairs(list_to_rangepairs(cpumap))
1100 name = get_info('name')
1101 domid = int(get_info('domid'))
1103 for vcpu in sxp.children(dom, 'vcpu'):
1104 def vinfo(n, t):
1105 return t(sxp.child_value(vcpu, n))
1107 number = vinfo('number', int)
1108 cpu = vinfo('cpu', int)
1109 cpumap = format_cpumap(vinfo('cpumap', list))
1110 online = vinfo('online', int)
1111 cpu_time = vinfo('cpu_time', float)
1112 running = vinfo('running', int)
1113 blocked = vinfo('blocked', int)
1115 if online:
1116 c = str(cpu)
1117 if running:
1118 s = 'r'
1119 else:
1120 s = '-'
1121 if blocked:
1122 s += 'b'
1123 else:
1124 s += '-'
1125 s += '-'
1126 else:
1127 c = "-"
1128 s = "--p"
1130 print format % locals()
1132 def start_do_console(domain_name):
1133 cpid = os.fork()
1134 if cpid != 0:
1135 for i in range(10):
1136 # Catch failure of the create process
1137 time.sleep(1)
1138 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1139 if os.WIFEXITED(rv):
1140 if os.WEXITSTATUS(rv) != 0:
1141 sys.exit(os.WEXITSTATUS(rv))
1142 try:
1143 # Acquire the console of the created dom
1144 if serverType == SERVER_XEN_API:
1145 domid = server.xenapi.VM.get_domid(
1146 get_single_vm(domain_name))
1147 else:
1148 dom = server.xend.domain(domain_name)
1149 domid = int(sxp.child_value(dom, 'domid', '-1'))
1150 console.execConsole(domid)
1151 except:
1152 pass
1153 print("Could not start console\n");
1154 sys.exit(0)
1156 def xm_start(args):
1158 paused = False
1159 console_autoconnect = False
1161 try:
1162 (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused'])
1163 for (k, v) in options:
1164 if k in ('-p', '--paused'):
1165 paused = True
1166 if k in ('-c', '--console_autoconnect'):
1167 console_autoconnect = True
1169 if len(params) != 1:
1170 raise OptionError("Expects 1 argument")
1171 except getopt.GetoptError, opterr:
1172 err(opterr)
1173 usage('start')
1175 dom = params[0]
1177 if console_autoconnect:
1178 start_do_console(dom)
1180 try:
1181 if serverType == SERVER_XEN_API:
1182 server.xenapi.VM.start(get_single_vm(dom), paused)
1183 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1184 else:
1185 server.xend.domain.start(dom, paused)
1186 info = server.xend.domain(dom)
1187 domid = int(sxp.child_value(info, 'domid', '-1'))
1188 except:
1189 raise
1191 if domid == -1:
1192 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1194 def xm_delete(args):
1195 arg_check(args, "delete", 1)
1196 dom = args[0]
1197 if serverType == SERVER_XEN_API:
1198 server.xenapi.VM.destroy(get_single_vm(dom))
1199 else:
1200 server.xend.domain.delete(dom)
1202 def xm_suspend(args):
1203 arg_check(args, "suspend", 1)
1204 dom = args[0]
1205 if serverType == SERVER_XEN_API:
1206 server.xenapi.VM.suspend(get_single_vm(dom))
1207 else:
1208 server.xend.domain.suspend(dom)
1210 def xm_resume(args):
1211 arg_check(args, "resume", 1, 2)
1213 try:
1214 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1215 except getopt.GetoptError, opterr:
1216 err(opterr)
1217 usage('resume')
1219 paused = False
1220 for (k, v) in options:
1221 if k in ['-p', '--paused']:
1222 paused = True
1224 if len(params) != 1:
1225 err("Wrong number of parameters")
1226 usage('resume')
1228 dom = params[0]
1229 if serverType == SERVER_XEN_API:
1230 server.xenapi.VM.resume(get_single_vm(dom), paused)
1231 else:
1232 server.xend.domain.resume(dom, paused)
1234 def xm_reboot(args):
1235 arg_check(args, "reboot", 1, 3)
1236 from xen.xm import shutdown
1237 shutdown.main(["shutdown", "-R"] + args)
1239 def xm_shutdown(args):
1240 arg_check(args, "shutdown", 1, 4)
1241 from xen.xm import shutdown
1242 shutdown.main(["shutdown"] + args)
1244 def xm_pause(args):
1245 arg_check(args, "pause", 1)
1246 dom = args[0]
1248 if serverType == SERVER_XEN_API:
1249 server.xenapi.VM.pause(get_single_vm(dom))
1250 else:
1251 server.xend.domain.pause(dom)
1253 def xm_unpause(args):
1254 arg_check(args, "unpause", 1)
1255 dom = args[0]
1257 if serverType == SERVER_XEN_API:
1258 server.xenapi.VM.unpause(get_single_vm(dom))
1259 else:
1260 server.xend.domain.unpause(dom)
1262 def xm_dump_core(args):
1263 live = False
1264 crash = False
1265 try:
1266 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1267 for (k, v) in options:
1268 if k in ('-L', '--live'):
1269 live = True
1270 if k in ('-C', '--crash'):
1271 crash = True
1273 if len(params) not in (1, 2):
1274 raise OptionError("Expects 1 or 2 argument(s)")
1275 except getopt.GetoptError, e:
1276 raise OptionError(str(e))
1278 dom = params[0]
1279 if len(params) == 2:
1280 filename = os.path.abspath(params[1])
1281 else:
1282 filename = None
1284 if not live:
1285 server.xend.domain.pause(dom)
1287 try:
1288 print "Dumping core of domain: %s ..." % str(dom)
1289 server.xend.domain.dump(dom, filename, live, crash)
1290 finally:
1291 if not live:
1292 server.xend.domain.unpause(dom)
1294 if crash:
1295 print "Destroying domain: %s ..." % str(dom)
1296 server.xend.domain.destroy(dom)
1298 def xm_rename(args):
1299 arg_check(args, "rename", 2)
1301 if serverType == SERVER_XEN_API:
1302 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1303 else:
1304 server.xend.domain.setName(args[0], args[1])
1306 def xm_importcommand(command, args):
1307 cmd = __import__(command, globals(), locals(), 'xen.xm')
1308 cmd.main([command] + args)
1311 #############################################################
1313 def xm_vcpu_pin(args):
1314 arg_check(args, "vcpu-pin", 3)
1316 def cpu_make_map(cpulist):
1317 cpus = []
1318 for c in cpulist.split(','):
1319 if c.find('-') != -1:
1320 (x,y) = c.split('-')
1321 for i in range(int(x),int(y)+1):
1322 cpus.append(int(i))
1323 else:
1324 # remove this element from the list
1325 if c[0] == '^':
1326 cpus = [x for x in cpus if x != int(c[1:])]
1327 else:
1328 cpus.append(int(c))
1329 cpus.sort()
1330 return cpus
1332 dom = args[0]
1333 vcpu = args[1]
1334 if args[2] == 'all':
1335 cpumap = cpu_make_map('0-63')
1336 else:
1337 cpumap = cpu_make_map(args[2])
1339 if serverType == SERVER_XEN_API:
1340 cpumap = map(str, cpumap)
1341 server.xenapi.VM.add_to_VCPUs_params_live(
1342 get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap))
1343 else:
1344 server.xend.domain.pincpu(dom, vcpu, cpumap)
1346 def xm_mem_max(args):
1347 arg_check(args, "mem-max", 2)
1349 dom = args[0]
1351 if serverType == SERVER_XEN_API:
1352 mem = int_unit(args[1], 'k') * 1024
1353 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1354 else:
1355 mem = int_unit(args[1], 'm')
1356 server.xend.domain.maxmem_set(dom, mem)
1358 def xm_mem_set(args):
1359 arg_check(args, "mem-set", 2)
1361 dom = args[0]
1363 if serverType == SERVER_XEN_API:
1364 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1365 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1366 mem_target)
1367 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1368 mem_target)
1369 else:
1370 mem_target = int_unit(args[1], 'm')
1371 server.xend.domain.setMemoryTarget(dom, mem_target)
1373 def xm_vcpu_set(args):
1374 arg_check(args, "vcpu-set", 2)
1376 dom = args[0]
1377 vcpus = int(args[1])
1379 if serverType == SERVER_XEN_API:
1380 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1381 else:
1382 server.xend.domain.setVCpuCount(dom, vcpus)
1384 def xm_destroy(args):
1385 arg_check(args, "destroy", 1)
1387 dom = args[0]
1389 if serverType == SERVER_XEN_API:
1390 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1391 else:
1392 server.xend.domain.destroy(dom)
1394 def xm_domid(args):
1395 arg_check(args, "domid", 1)
1397 name = args[0]
1399 if serverType == SERVER_XEN_API:
1400 print server.xenapi.VM.get_domid(get_single_vm(name))
1401 else:
1402 dom = server.xend.domain(name)
1403 print sxp.child_value(dom, 'domid')
1405 def xm_domname(args):
1406 arg_check(args, "domname", 1)
1408 name = args[0]
1410 if serverType == SERVER_XEN_API:
1411 print server.xenapi.VM.get_name_label(get_single_vm(name))
1412 else:
1413 dom = server.xend.domain(name)
1414 print sxp.child_value(dom, 'name')
1416 def xm_sched_sedf(args):
1417 xenapi_unsupported()
1419 def ns_to_ms(val):
1420 return float(val) * 0.000001
1422 def ms_to_ns(val):
1423 return (float(val) / 0.000001)
1425 def print_sedf(info):
1426 info['period'] = ns_to_ms(info['period'])
1427 info['slice'] = ns_to_ms(info['slice'])
1428 info['latency'] = ns_to_ms(info['latency'])
1429 print( ("%(name)-32s %(domid)5d %(period)9.1f %(slice)9.1f" +
1430 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1432 check_sched_type('sedf')
1434 # we want to just display current info if no parameters are passed
1435 if len(args) == 0:
1436 domid = None
1437 else:
1438 # we expect at least a domain id (name or number)
1439 # and at most a domid up to 5 options with values
1440 arg_check(args, "sched-sedf", 1, 11)
1441 domid = args[0]
1442 # drop domid from args since get_opt doesn't recognize it
1443 args = args[1:]
1445 opts = {}
1446 try:
1447 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1448 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1449 except getopt.GetoptError, opterr:
1450 err(opterr)
1451 usage('sched-sedf')
1453 # convert to nanoseconds if needed
1454 for (k, v) in options:
1455 if k in ['-p', '--period']:
1456 opts['period'] = ms_to_ns(v)
1457 elif k in ['-s', '--slice']:
1458 opts['slice'] = ms_to_ns(v)
1459 elif k in ['-l', '--latency']:
1460 opts['latency'] = ms_to_ns(v)
1461 elif k in ['-e', '--extratime']:
1462 opts['extratime'] = v
1463 elif k in ['-w', '--weight']:
1464 opts['weight'] = v
1466 doms = filter(lambda x : domid_match(domid, x),
1467 [parse_doms_info(dom)
1468 for dom in getDomains(None, 'running')])
1469 if domid is not None and doms == []:
1470 err("Domain '%s' does not exist." % domid)
1471 usage('sched-sedf')
1473 # print header if we aren't setting any parameters
1474 if len(opts.keys()) == 0:
1475 print '%-33s %4s %-4s %-4s %-7s %-5s %-6s' % \
1476 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1477 'Extra','Weight')
1479 for d in doms:
1480 # fetch current values so as not to clobber them
1481 try:
1482 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1483 except xmlrpclib.Fault:
1484 # domain does not support sched-sedf?
1485 sedf_raw = {}
1487 sedf_info = parse_sedf_info(sedf_raw)
1488 sedf_info['name'] = d['name']
1489 # update values in case of call to set
1490 if len(opts.keys()) > 0:
1491 for k in opts.keys():
1492 sedf_info[k]=opts[k]
1494 # send the update, converting user input
1495 v = map(int, [sedf_info['period'], sedf_info['slice'],
1496 sedf_info['latency'],sedf_info['extratime'],
1497 sedf_info['weight']])
1498 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1499 if int(rv) != 0:
1500 err("Failed to set sedf parameters (rv=%d)."%(rv))
1502 # not setting values, display info
1503 else:
1504 print_sedf(sedf_info)
1506 def xm_sched_credit(args):
1507 """Get/Set options for Credit Scheduler."""
1509 check_sched_type('credit')
1511 try:
1512 opts, params = getopt.getopt(args, "d:w:c:",
1513 ["domain=", "weight=", "cap="])
1514 except getopt.GetoptError, opterr:
1515 err(opterr)
1516 usage('sched-credit')
1518 domid = None
1519 weight = None
1520 cap = None
1522 for o, a in opts:
1523 if o == "-d":
1524 domid = a
1525 elif o == "-w":
1526 weight = int(a)
1527 elif o == "-c":
1528 cap = int(a);
1530 doms = filter(lambda x : domid_match(domid, x),
1531 [parse_doms_info(dom)
1532 for dom in getDomains(None, 'running')])
1534 if weight is None and cap is None:
1535 if domid is not None and doms == []:
1536 err("Domain '%s' does not exist." % domid)
1537 usage('sched-credit')
1538 # print header if we aren't setting any parameters
1539 print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
1541 for d in doms:
1542 try:
1543 if serverType == SERVER_XEN_API:
1544 info = server.xenapi.VM_metrics.get_VCPUs_params(
1545 server.xenapi.VM.get_metrics(
1546 get_single_vm(d['name'])))
1547 else:
1548 info = server.xend.domain.sched_credit_get(d['domid'])
1549 except xmlrpclib.Fault:
1550 pass
1552 if 'weight' not in info or 'cap' not in info:
1553 # domain does not support sched-credit?
1554 info = {'weight': -1, 'cap': -1}
1556 info['weight'] = int(info['weight'])
1557 info['cap'] = int(info['cap'])
1559 info['name'] = d['name']
1560 info['domid'] = int(d['domid'])
1561 print( ("%(name)-32s %(domid)5d %(weight)6d %(cap)4d") % info)
1562 else:
1563 if domid is None:
1564 # place holder for system-wide scheduler parameters
1565 err("No domain given.")
1566 usage('sched-credit')
1568 if serverType == SERVER_XEN_API:
1569 server.xenapi.VM.add_to_VCPUs_params_live(
1570 get_single_vm(domid),
1571 "weight",
1572 weight)
1573 server.xenapi.VM.add_to_VCPUs_params_live(
1574 get_single_vm(domid),
1575 "cap",
1576 cap)
1577 else:
1578 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1579 if result != 0:
1580 err(str(result))
1582 def xm_info(args):
1583 arg_check(args, "info", 0)
1585 if serverType == SERVER_XEN_API:
1587 # Need to fake out old style xm info as people rely on parsing it
1589 host_record = server.xenapi.host.get_record(
1590 server.xenapi.session.get_this_host(server.getSession()))
1592 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1594 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1596 def getVal(keys, default=""):
1597 data = host_record
1598 for key in keys:
1599 if key in data:
1600 data = data[key]
1601 else:
1602 return default
1603 return data
1605 def getCpuMhz():
1606 cpu_speeds = [int(host_cpu_record["speed"])
1607 for host_cpu_record in host_cpu_records
1608 if "speed" in host_cpu_record]
1609 if len(cpu_speeds) > 0:
1610 return sum(cpu_speeds) / len(cpu_speeds)
1611 else:
1612 return 0
1614 getCpuMhz()
1616 def getCpuFeatures():
1617 if len(host_cpu_records) > 0:
1618 return host_cpu_records[0].get("features", "")
1619 else:
1620 return ""
1622 info = {
1623 "host": getVal(["name_label"]),
1624 "release": getVal(["software_version", "release"]),
1625 "version": getVal(["software_version", "version"]),
1626 "machine": getVal(["software_version", "machine"]),
1627 "nr_cpus": len(getVal(["host_CPUs"], [])),
1628 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1629 "sockets_per_node": getVal(["cpu_configuration", "sockets_per_node"]),
1630 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1631 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1632 "cpu_mhz": getCpuMhz(),
1633 "hw_caps": getCpuFeatures(),
1634 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1635 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1636 "xen_major": getVal(["software_version", "xen_major"]),
1637 "xen_minor": getVal(["software_version", "xen_minor"]),
1638 "xen_extra": getVal(["software_version", "xen_extra"]),
1639 "xen_caps": " ".join(getVal(["capabilities"], [])),
1640 "xen_scheduler": getVal(["sched_policy"]),
1641 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1642 "platform_params": getVal(["other_config", "platform_params"]),
1643 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1644 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1645 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1646 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1647 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1648 "xend_config_format":getVal(["software_version", "xend_config_format"])
1651 sorted = info.items()
1652 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1654 for (k, v) in sorted:
1655 print "%-23s:" % k, v
1656 else:
1657 info = server.xend.node.info()
1658 for x in info[1:]:
1659 if len(x) < 2:
1660 print "%-23s: (none)" % x[0]
1661 else:
1662 print "%-23s:" % x[0], x[1]
1664 def xm_console(args):
1665 arg_check(args, "console", 1, 2)
1667 quiet = False;
1669 try:
1670 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1671 except getopt.GetoptError, opterr:
1672 err(opterr)
1673 usage('console')
1675 for (k, v) in options:
1676 if k in ['-q', '--quiet']:
1677 quiet = True
1678 else:
1679 assert False
1681 if len(params) != 1:
1682 err('No domain given')
1683 usage('console')
1685 dom = params[0]
1687 try:
1688 if serverType == SERVER_XEN_API:
1689 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1690 else:
1691 info = server.xend.domain(dom)
1692 domid = int(sxp.child_value(info, 'domid', '-1'))
1693 except:
1694 if quiet:
1695 sys.exit(1)
1696 else:
1697 raise
1699 if domid == -1:
1700 if quiet:
1701 sys.exit(1)
1702 else:
1703 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1705 console.execConsole(domid)
1708 def xm_uptime(args):
1709 short_mode = 0
1711 try:
1712 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1713 except getopt.GetoptError, opterr:
1714 err(opterr)
1715 usage('uptime')
1717 for (k, v) in options:
1718 if k in ['-s', '--short']:
1719 short_mode = 1
1721 doms = getDomains(params, 'running')
1723 if short_mode == 0:
1724 print '%-33s %4s %s ' % ('Name','ID','Uptime')
1726 for dom in doms:
1727 d = parse_doms_info(dom)
1728 if int(d['domid']) > 0:
1729 uptime = int(round(d['up_time']))
1730 else:
1731 f=open('/proc/uptime', 'r')
1732 upfile = f.read()
1733 uptime = int(round(float(upfile.split(' ')[0])))
1734 f.close()
1736 days = int(uptime / 86400)
1737 uptime -= (days * 86400)
1738 hours = int(uptime / 3600)
1739 uptime -= (hours * 3600)
1740 minutes = int(uptime / 60)
1741 uptime -= (minutes * 60)
1742 seconds = uptime
1744 upstring = ""
1745 if days > 0:
1746 upstring += str(days) + " day"
1747 if days > 1:
1748 upstring += "s"
1749 upstring += ", "
1750 upstring += '%(hours)2d:%(minutes)02d' % vars()
1752 if short_mode:
1753 now = datetime.datetime.now()
1754 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1755 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1756 else:
1757 upstring += ':%(seconds)02d' % vars()
1758 upstring = ("%(name)-32s %(domid)5s " % d) + upstring
1760 print upstring
1762 def xm_sysrq(args):
1763 arg_check(args, "sysrq", 2)
1764 dom = args[0]
1765 req = args[1]
1766 if serverType == SERVER_XEN_API:
1767 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1768 else:
1769 server.xend.domain.send_sysrq(dom, req)
1771 def xm_trigger(args):
1772 vcpu = 0
1774 arg_check(args, "trigger", 2, 3)
1775 dom = args[0]
1776 trigger = args[1]
1777 if len(args) == 3:
1778 vcpu = int(args[2])
1780 if serverType == SERVER_XEN_API:
1781 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1782 else:
1783 server.xend.domain.send_trigger(dom, trigger, vcpu)
1785 def xm_debug_keys(args):
1786 arg_check(args, "debug-keys", 1)
1788 keys = str(args[0])
1790 if serverType == SERVER_XEN_API:
1791 server.xenapi.host.send_debug_keys(
1792 server.xenapi.session.get_this_host(server.getSession()),
1793 keys)
1794 else:
1795 server.xend.node.send_debug_keys(keys)
1797 def xm_top(args):
1798 arg_check(args, "top", 0)
1800 os.execvp('xentop', ['xentop'])
1802 def xm_dmesg(args):
1803 arg_check(args, "dmesg", 0, 1)
1805 try:
1806 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1807 except getopt.GetoptError, opterr:
1808 err(opterr)
1809 usage('dmesg')
1811 use_clear = 0
1812 for (k, v) in options:
1813 if k in ['-c', '--clear']:
1814 use_clear = 1
1816 if len(params) :
1817 err("No parameter required")
1818 usage('dmesg')
1820 if serverType == SERVER_XEN_API:
1821 host = server.xenapi.session.get_this_host(server.getSession())
1822 if use_clear:
1823 print server.xenapi.host.dmesg_clear(host),
1824 else:
1825 print server.xenapi.host.dmesg(host),
1826 else:
1827 if not use_clear:
1828 print server.xend.node.dmesg.info(),
1829 else:
1830 print server.xend.node.dmesg.clear(),
1832 def xm_log(args):
1833 arg_check(args, "log", 0)
1835 if serverType == SERVER_XEN_API:
1836 print server.xenapi.host.get_log(
1837 server.xenapi.session.get_this_host(server.getSession()))
1838 else:
1839 print server.xend.node.log()
1841 def xm_serve(args):
1842 if serverType == SERVER_XEN_API:
1843 print "Not supported with XenAPI"
1844 sys.exit(-1)
1846 arg_check(args, "serve", 0)
1848 from fcntl import fcntl, F_SETFL
1850 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1851 s.connect(XendClient.XML_RPC_SOCKET)
1852 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1854 while True:
1855 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1856 if s in iwtd:
1857 data = s.recv(4096)
1858 if len(data) > 0:
1859 sys.stdout.write(data)
1860 sys.stdout.flush()
1861 else:
1862 break
1863 if sys.stdin in iwtd:
1864 data = sys.stdin.read(4096)
1865 if len(data) > 0:
1866 s.sendall(data)
1867 else:
1868 break
1869 s.close()
1871 def parse_dev_info(info):
1872 def get_info(n, t, d):
1873 i = 0
1874 while i < len(info):
1875 if (info[i][0] == n):
1876 return t(info[i][1])
1877 i = i + 1
1878 return t(d)
1879 return {
1880 #common
1881 'backend-id' : get_info('backend-id', int, -1),
1882 'handle' : get_info('handle', int, 0),
1883 'state' : get_info('state', int, -1),
1884 'be-path' : get_info('backend', str, '??'),
1885 'event-ch' : get_info('event-channel',int, -1),
1886 #network specific
1887 'virtual-device' : get_info('virtual-device', str, '??'),
1888 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1889 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1890 'mac' : get_info('mac', str, '??'),
1891 #block-device specific
1892 'ring-ref' : get_info('ring-ref', int, -1),
1895 def arg_check_for_resource_list(args, name):
1896 use_long = 0
1897 try:
1898 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1899 except getopt.GetoptError, opterr:
1900 err(opterr)
1901 sys.exit(1)
1903 for (k, v) in options:
1904 if k in ['-l', '--long']:
1905 use_long = 1
1907 if len(params) == 0:
1908 print 'No domain parameter given'
1909 usage(name)
1910 if len(params) > 1:
1911 print 'No multiple domain parameters allowed'
1912 usage(name)
1914 return (use_long, params)
1916 def xm_network_list(args):
1917 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1919 dom = params[0]
1921 if serverType == SERVER_XEN_API:
1922 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1923 vif_properties = \
1924 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1925 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
1926 zip(range(len(vif_properties)), vif_properties))
1927 else:
1928 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1930 if use_long:
1931 map(PrettyPrint.prettyprint, devs)
1932 else:
1933 hdr = 0
1934 for x in devs:
1935 if hdr == 0:
1936 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1937 hdr = 1
1938 ni = parse_dev_info(x[1])
1939 ni['idx'] = int(x[0])
1940 print ("%(idx)-3d "
1941 "%(backend-id)-3d"
1942 "%(mac)-17s "
1943 "%(handle)-3d "
1944 "%(state)-3d "
1945 "%(event-ch)-3d "
1946 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1947 "%(be-path)-30s "
1948 % ni)
1950 def xm_block_list(args):
1951 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1953 dom = params[0]
1955 if serverType == SERVER_XEN_API:
1956 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1957 vbd_properties = \
1958 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
1959 vbd_devs = \
1960 map(server.xenapi.VBD.get_device, vbd_refs)
1961 vbd_devids = \
1962 map(blkdev_name_to_number, vbd_devs)
1963 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
1964 zip(vbd_devids, vbd_properties))
1965 else:
1966 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1968 if use_long:
1969 map(PrettyPrint.prettyprint, devs)
1970 else:
1971 hdr = 0
1972 for x in devs:
1973 if hdr == 0:
1974 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1975 hdr = 1
1976 ni = parse_dev_info(x[1])
1977 ni['idx'] = int(x[0])
1978 print ("%(idx)-3d "
1979 "%(backend-id)-3d "
1980 "%(handle)-3d "
1981 "%(state)-3d "
1982 "%(event-ch)-3d "
1983 "%(ring-ref)-5d "
1984 "%(be-path)-30s "
1985 % ni)
1987 def xm_vtpm_list(args):
1988 xenapi_unsupported()
1989 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1991 dom = params[0]
1992 if use_long:
1993 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1994 map(PrettyPrint.prettyprint, devs)
1995 else:
1996 hdr = 0
1997 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1998 if hdr == 0:
1999 print 'Idx BE handle state evt-ch ring-ref BE-path'
2000 hdr = 1
2001 ni = parse_dev_info(x[1])
2002 ni['idx'] = int(x[0])
2003 print ("%(idx)-3d "
2004 "%(backend-id)-3d "
2005 "%(handle)-3d "
2006 "%(state)-3d "
2007 "%(event-ch)-3d "
2008 "%(ring-ref)-5d "
2009 "%(be-path)-30s "
2010 % ni)
2013 def parse_block_configuration(args):
2014 dom = args[0]
2016 if args[1].startswith('tap:'):
2017 cls = 'tap'
2018 else:
2019 cls = 'vbd'
2021 vbd = [cls,
2022 ['uname', args[1]],
2023 ['dev', args[2]],
2024 ['mode', args[3]]]
2025 if len(args) == 5:
2026 vbd.append(['backend', args[4]])
2028 if serverType != SERVER_XEN_API:
2029 # verify that policy permits attaching this resource
2030 from xen.util import security
2032 if security.on():
2033 dominfo = server.xend.domain(dom)
2034 label = security.get_security_printlabel(dominfo)
2035 else:
2036 label = None
2038 security.res_security_check(args[1], label)
2040 return (dom, vbd)
2043 def xm_block_attach(args):
2044 arg_check(args, 'block-attach', 4, 5)
2046 if serverType == SERVER_XEN_API:
2047 dom = args[0]
2048 uname = args[1]
2049 dev = args[2]
2050 mode = args[3]
2052 # First create new VDI
2053 vdi_record = {
2054 "name_label": "vdi" + str(uname.__hash__()),
2055 "name_description": "",
2056 "SR": get_default_SR(),
2057 "virtual_size": 0,
2058 "sector_size": 512,
2059 "type": "system",
2060 "sharable": False,
2061 "read_only": mode!="w",
2062 "other_config": {"location": uname}
2065 vdi_ref = server.xenapi.VDI.create(vdi_record)
2067 # Now create new VBD
2069 vbd_record = {
2070 "VM": get_single_vm(dom),
2071 "VDI": vdi_ref,
2072 "device": dev,
2073 "bootable": True,
2074 "mode": mode=="w" and "RW" or "RO",
2075 "type": "Disk",
2076 "qos_algorithm_type": "",
2077 "qos_algorithm_params": {}
2080 server.xenapi.VBD.create(vbd_record)
2082 else:
2083 (dom, vbd) = parse_block_configuration(args)
2084 server.xend.domain.device_create(dom, vbd)
2087 def xm_block_configure(args):
2088 arg_check(args, 'block-configure', 4, 5)
2090 (dom, vbd) = parse_block_configuration(args)
2091 server.xend.domain.device_configure(dom, vbd)
2094 def xm_network_attach(args):
2095 arg_check(args, 'network-attach', 1, 10)
2097 dom = args[0]
2098 vif = ['vif']
2099 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2100 'backend', 'vifname', 'rate', 'model']
2102 if serverType == SERVER_XEN_API:
2103 vif_record = {
2104 "device": "eth0",
2105 "network": get_default_Network(),
2106 "VM": get_single_vm(dom),
2107 "MAC": "",
2108 "MTU": "",
2109 "qos_algorithm_type": "",
2110 "qos_algorithm_params": {},
2111 "other_config": {}
2114 def set(keys, val):
2115 record = vif_record
2116 for key in keys[:-1]:
2117 record = record[key]
2118 record[keys[-1]] = val
2120 def get_net_from_bridge(bridge):
2121 # In OSS, we just assert network.name_label == bridge name
2122 networks = dict([(record['name_label'], ref)
2123 for ref, record in server.xenapi.network
2124 .get_all_records().items()])
2125 if bridge not in networks.keys():
2126 raise "Unknown bridge name!"
2127 return networks[bridge]
2129 vif_conv = {
2130 'type':
2131 lambda x: None,
2132 'mac':
2133 lambda x: set(['MAC'], x),
2134 'bridge':
2135 lambda x: set(['network'], get_net_from_bridge(x)),
2136 'ip':
2137 lambda x: set(['other_config', 'ip'], x),
2138 'script':
2139 lambda x: set(['other_config', 'script'], x),
2140 'backend':
2141 lambda x: set(['other_config', 'backend'], x),
2142 'vifname':
2143 lambda x: set(['device'], x),
2144 'rate':
2145 lambda x: set(['qos_algorithm_params', 'rate'], x),
2146 'model':
2147 lambda x: None
2150 for a in args[1:]:
2151 vif_param = a.split("=")
2152 if len(vif_param) != 2 or vif_param[1] == '' or \
2153 vif_param[0] not in vif_params:
2154 err("Invalid argument: %s" % a)
2155 usage('network-attach')
2156 else:
2157 vif_conv[vif_param[0]](vif_param[1])
2159 server.xenapi.VIF.create(vif_record)
2160 else:
2161 for a in args[1:]:
2162 vif_param = a.split("=")
2163 if len(vif_param) != 2 or vif_param[1] == '' or \
2164 vif_param[0] not in vif_params:
2165 err("Invalid argument: %s" % a)
2166 usage('network-attach')
2167 vif.append(vif_param)
2168 server.xend.domain.device_create(dom, vif)
2171 def detach(args, command, deviceClass):
2172 arg_check(args, command, 2, 3)
2174 dom = args[0]
2175 dev = args[1]
2176 try:
2177 force = args[2]
2178 if (force != "--force") and (force != "-f"):
2179 print "Ignoring option %s"%(force)
2180 force = None
2181 except IndexError:
2182 force = None
2184 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
2187 def xm_block_detach(args):
2188 if serverType == SERVER_XEN_API:
2189 arg_check(args, "xm_block_detach", 2, 3)
2190 dom = args[0]
2191 dev = args[1]
2192 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2193 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2194 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2195 if len(vbd_refs) > 0:
2196 vbd_ref = vbd_refs[0]
2197 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2199 server.xenapi.VBD.destroy(vbd_ref)
2201 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2202 server.xenapi.VDI.destroy(vdi_ref)
2203 else:
2204 raise OptionError("Cannot find device '%s' in domain '%s'"
2205 % (dev,dom))
2206 else:
2207 try:
2208 detach(args, 'block-detach', 'vbd')
2209 return
2210 except:
2211 pass
2212 detach(args, 'block-detach', 'tap')
2214 def xm_network_detach(args):
2215 if serverType == SERVER_XEN_API:
2216 arg_check(args, "xm_block_detach", 2, 3)
2217 dom = args[0]
2218 devid = args[1]
2219 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2220 vif_refs = [vif_ref for vif_ref in vif_refs
2221 if server.xenapi.VIF.\
2222 get_runtime_properties(vif_ref)["handle"] == devid]
2223 if len(vif_refs) > 0:
2224 vif_ref = vif_refs[0]
2226 server.xenapi.VIF.destroy(vif_ref)
2227 else:
2228 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2229 else:
2230 detach(args, 'network-detach', 'vif')
2233 def xm_vnet_list(args):
2234 xenapi_unsupported()
2235 try:
2236 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2237 except getopt.GetoptError, opterr:
2238 err(opterr)
2239 usage('vnet-list')
2241 use_long = 0
2242 for (k, v) in options:
2243 if k in ['-l', '--long']:
2244 use_long = 1
2246 if params:
2247 use_long = 1
2248 vnets = params
2249 else:
2250 vnets = server.xend_vnets()
2252 for vnet in vnets:
2253 try:
2254 if use_long:
2255 info = server.xend_vnet(vnet)
2256 PrettyPrint.prettyprint(info)
2257 else:
2258 print vnet
2259 except Exception, ex:
2260 print vnet, ex
2262 def xm_vnet_create(args):
2263 xenapi_unsupported()
2264 arg_check(args, "vnet-create", 1)
2265 conf = args[0]
2266 if not os.access(conf, os.R_OK):
2267 print "File not found: %s" % conf
2268 sys.exit(1)
2270 server.xend_vnet_create(conf)
2272 def xm_vnet_delete(args):
2273 xenapi_unsupported()
2274 arg_check(args, "vnet-delete", 1)
2275 vnet = args[0]
2276 server.xend_vnet_delete(vnet)
2278 def xm_network_new(args):
2279 xenapi_only()
2280 arg_check(args, "network-new", 1)
2281 network = args[0]
2283 record = {
2284 "name_label": network,
2285 "name_description": "",
2286 "other_config": {},
2287 "default_gateway": "",
2288 "default_netmask": ""
2291 server.xenapi.network.create(record)
2293 def xm_network_del(args):
2294 xenapi_only()
2295 arg_check(args, "network-del", 1)
2296 network = args[0]
2298 networks = dict([(record['name_label'], ref)
2299 for ref, record in
2300 server.xenapi.network.get_all_records().items()])
2302 if network not in networks.keys():
2303 raise ValueError("'%s' is not a valid network name" % network)
2305 server.xenapi.network.destroy(networks[network])
2307 def xm_network_show(args):
2308 xenapi_only()
2309 arg_check(args, "network-show", 0)
2311 networks = server.xenapi.network.get_all_records()
2312 pifs = server.xenapi.PIF.get_all_records()
2313 vifs = server.xenapi.VIF.get_all_records()
2315 print '%-20s %-40s %-10s' % \
2316 ('Name', 'VIFs', 'PIFs')
2318 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2320 for network_ref, network in networks.items():
2321 for i in range(max(len(network['PIFs']),
2322 len(network['VIFs']), 1)):
2323 if i < len(network['PIFs']):
2324 pif_uuid = network['PIFs'][i]
2325 else:
2326 pif_uuid = None
2328 if i < len(network['VIFs']):
2329 vif_uuid = network['VIFs'][i]
2330 else:
2331 vif_uuid = None
2333 pif = pifs.get(pif_uuid, None)
2334 vif = vifs.get(vif_uuid, None)
2336 if vif:
2337 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2338 vif = "%s.%s" % (dom_name, vif['device'])
2339 else:
2340 vif = ''
2342 if pif:
2343 if int(pif['VLAN']) > -1:
2344 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2345 else:
2346 pif = pif['device']
2347 else:
2348 pif = ''
2350 if i == 0:
2351 r = {'name_label':network['name_label'],
2352 'vif':vif, 'pif':pif}
2353 else:
2354 r = {'name_label':'', 'vif':vif, 'pif':pif}
2356 print format2 % r
2359 commands = {
2360 "shell": xm_shell,
2361 "event-monitor": xm_event_monitor,
2362 # console commands
2363 "console": xm_console,
2364 # xenstat commands
2365 "top": xm_top,
2366 # domain commands
2367 "delete": xm_delete,
2368 "destroy": xm_destroy,
2369 "domid": xm_domid,
2370 "domname": xm_domname,
2371 "dump-core": xm_dump_core,
2372 "reboot": xm_reboot,
2373 "rename": xm_rename,
2374 "restore": xm_restore,
2375 "resume": xm_resume,
2376 "save": xm_save,
2377 "shutdown": xm_shutdown,
2378 "start": xm_start,
2379 "sysrq": xm_sysrq,
2380 "trigger": xm_trigger,
2381 "uptime": xm_uptime,
2382 "suspend": xm_suspend,
2383 "list": xm_list,
2384 # memory commands
2385 "mem-max": xm_mem_max,
2386 "mem-set": xm_mem_set,
2387 # cpu commands
2388 "vcpu-pin": xm_vcpu_pin,
2389 "vcpu-list": xm_vcpu_list,
2390 "vcpu-set": xm_vcpu_set,
2391 # special
2392 "pause": xm_pause,
2393 "unpause": xm_unpause,
2394 # host commands
2395 "debug-keys": xm_debug_keys,
2396 "dmesg": xm_dmesg,
2397 "info": xm_info,
2398 "log": xm_log,
2399 "serve": xm_serve,
2400 # scheduler
2401 "sched-sedf": xm_sched_sedf,
2402 "sched-credit": xm_sched_credit,
2403 # block
2404 "block-attach": xm_block_attach,
2405 "block-detach": xm_block_detach,
2406 "block-list": xm_block_list,
2407 "block-configure": xm_block_configure,
2408 # network (AKA vifs)
2409 "network-attach": xm_network_attach,
2410 "network-detach": xm_network_detach,
2411 "network-list": xm_network_list,
2412 # network (as in XenAPI)
2413 "network-new": xm_network_new,
2414 "network-del": xm_network_del,
2415 "network-show": xm_network_show,
2416 # vnet
2417 "vnet-list": xm_vnet_list,
2418 "vnet-create": xm_vnet_create,
2419 "vnet-delete": xm_vnet_delete,
2420 # vtpm
2421 "vtpm-list": xm_vtpm_list,
2424 ## The commands supported by a separate argument parser in xend.xm.
2425 IMPORTED_COMMANDS = [
2426 'create',
2427 'new',
2428 'migrate',
2429 'labels',
2430 'cfgbootpolicy',
2431 'makepolicy',
2432 'loadpolicy',
2433 'dumppolicy',
2434 'addlabel',
2435 'rmlabel',
2436 'getlabel',
2437 'dry-run',
2438 'resources',
2441 for c in IMPORTED_COMMANDS:
2442 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2444 aliases = {
2445 "balloon": "mem-set",
2446 "set-vcpus": "vcpu-set",
2447 "vif-list": "network-list",
2448 "vbd-create": "block-attach",
2449 "vbd-destroy": "block-detach",
2450 "vbd-list": "block-list",
2454 def xm_lookup_cmd(cmd):
2455 if commands.has_key(cmd):
2456 return commands[cmd]
2457 elif aliases.has_key(cmd):
2458 deprecated(cmd,aliases[cmd])
2459 return commands[aliases[cmd]]
2460 elif cmd == 'help':
2461 longHelp()
2462 sys.exit(0)
2463 else:
2464 # simulate getopt's prefix matching behaviour
2465 if len(cmd) > 1:
2466 same_prefix_cmds = [commands[c] for c in commands.keys() \
2467 if c[:len(cmd)] == cmd]
2468 # only execute if there is only 1 match
2469 if len(same_prefix_cmds) == 1:
2470 return same_prefix_cmds[0]
2471 return None
2473 def deprecated(old,new):
2474 print >>sys.stderr, (
2475 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2477 def main(argv=sys.argv):
2478 if len(argv) < 2:
2479 usage()
2481 # intercept --help(-h) and output our own help
2482 for help in ['--help', '-h']:
2483 if help in argv[1:]:
2484 if help == argv[1]:
2485 longHelp()
2486 sys.exit(0)
2487 else:
2488 usage(argv[1])
2490 cmd_name = argv[1]
2491 cmd = xm_lookup_cmd(cmd_name)
2492 if cmd:
2493 # strip off prog name and subcmd
2494 args = argv[2:]
2495 _, rc = _run_cmd(cmd, cmd_name, args)
2496 sys.exit(rc)
2497 else:
2498 err('Subcommand %s not found!' % cmd_name)
2499 usage()
2501 def _run_cmd(cmd, cmd_name, args):
2502 global server
2504 try:
2505 if server is None:
2506 if serverType == SERVER_XEN_API:
2507 server = XenAPI.Session(serverURI)
2508 username, password = parseAuthentication()
2509 server.login_with_password(username, password)
2510 def logout():
2511 try:
2512 server.xenapi.session.logout()
2513 except:
2514 pass
2515 atexit.register(logout)
2516 else:
2517 server = ServerProxy(serverURI)
2519 return True, cmd(args)
2520 except socket.error, ex:
2521 if os.geteuid() != 0:
2522 err("Most commands need root access. Please try again as root.")
2523 else:
2524 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2525 except KeyboardInterrupt:
2526 print "Interrupted."
2527 return True, ''
2528 except IOError, ex:
2529 if os.geteuid() != 0:
2530 err("Most commands need root access. Please try again as root.")
2531 else:
2532 err("Unable to connect to xend: %s." % ex[1])
2533 except SystemExit, code:
2534 return code == 0, code
2535 except XenAPI.Failure, exn:
2536 for line in [''] + wrap(str(exn), 80) + ['']:
2537 print >>sys.stderr, line
2538 except xmlrpclib.Fault, ex:
2539 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2540 err("Domain '%s' does not exist." % ex.faultString)
2541 else:
2542 err(ex.faultString)
2543 _usage(cmd_name)
2544 except xmlrpclib.ProtocolError, ex:
2545 if ex.errcode == -1:
2546 print >>sys.stderr, (
2547 "Xend has probably crashed! Invalid or missing HTTP "
2548 "status code.")
2549 else:
2550 print >>sys.stderr, (
2551 "Xend has probably crashed! ProtocolError(%d, %s)." %
2552 (ex.errcode, ex.errmsg))
2553 except (ValueError, OverflowError):
2554 err("Invalid argument.")
2555 _usage(cmd_name)
2556 except OptionError, e:
2557 err(str(e))
2558 _usage(cmd_name)
2559 print e.usage
2560 except XenAPIUnsupportedException, e:
2561 err(str(e))
2562 except Exception, e:
2563 if serverType != SERVER_XEN_API:
2564 from xen.util import security
2565 if isinstance(e, security.ACMError):
2566 err(str(e))
2567 return False, 1
2568 print "Unexpected error:", sys.exc_info()[0]
2569 print
2570 print "Please report to xen-devel@lists.xensource.com"
2571 raise
2573 return False, 1
2575 if __name__ == "__main__":
2576 main()