ia64/xen-unstable

view tools/python/xen/xm/main.py @ 14998:0e57b064f17a

[XM] Fix get_single_vm bug

Stops traceback when given a bad domain name

signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Tom Wilkie <tom.wilkie@gmail.com>
date Tue May 01 11:36:44 2007 +0100 (2007-05-01)
parents 0063e11206d5
children e046da853ffc
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> <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 ),
235 'resume': (
236 ('-p', '--paused', 'Do not unpause domain after resuming it'),
237 ),
238 'save': (
239 ('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
240 ),
241 'restore': (
242 ('-p', '--paused', 'Do not unpause domain after restoring it'),
243 ),
244 }
246 common_commands = [
247 "console",
248 "create",
249 "new",
250 "delete",
251 "destroy",
252 "dump-core",
253 "help",
254 "list",
255 "mem-set",
256 "migrate",
257 "pause",
258 "reboot",
259 "restore",
260 "resume",
261 "save",
262 "shell",
263 "shutdown",
264 "start",
265 "suspend",
266 "top",
267 "unpause",
268 "uptime",
269 "vcpu-set",
270 ]
272 domain_commands = [
273 "console",
274 "create",
275 "new",
276 "delete",
277 "destroy",
278 "domid",
279 "domname",
280 "dump-core",
281 "list",
282 "mem-max",
283 "mem-set",
284 "migrate",
285 "pause",
286 "reboot",
287 "rename",
288 "restore",
289 "resume",
290 "save",
291 "shutdown",
292 "start",
293 "suspend",
294 "sysrq",
295 "trigger",
296 "top",
297 "unpause",
298 "uptime",
299 "vcpu-list",
300 "vcpu-pin",
301 "vcpu-set",
302 ]
304 host_commands = [
305 "debug-keys",
306 "dmesg",
307 "info",
308 "log",
309 "serve",
310 ]
312 scheduler_commands = [
313 "sched-credit",
314 "sched-sedf",
315 ]
317 device_commands = [
318 "block-attach",
319 "block-detach",
320 "block-list",
321 "block-configure",
322 "network-attach",
323 "network-detach",
324 "network-list",
325 "vtpm-list",
326 ]
328 vnet_commands = [
329 "vnet-list",
330 "vnet-create",
331 "vnet-delete",
332 ]
334 acm_commands = [
335 "labels",
336 "addlabel",
337 "rmlabel",
338 "getlabel",
339 "dry-run",
340 "resources",
341 "makepolicy",
342 "loadpolicy",
343 "cfgbootpolicy",
344 "dumppolicy",
345 ]
347 all_commands = (domain_commands + host_commands + scheduler_commands +
348 device_commands + vnet_commands + acm_commands +
349 ['shell', 'event-monitor'])
352 ##
353 # Configuration File Parsing
354 ##
356 xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
357 config = None
358 if os.path.isfile(xmConfigFile):
359 try:
360 config = xml.dom.minidom.parse(xmConfigFile)
361 except:
362 print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
363 xmConfigFile)
365 def parseServer():
366 if config:
367 server = config.getElementsByTagName('server')
368 if server:
369 st = server[0].getAttribute('type')
370 if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC:
371 print >>sys.stderr, ('Invalid server type %s; using %s.' %
372 (st, SERVER_LEGACY_XMLRPC))
373 st = SERVER_LEGACY_XMLRPC
374 return (st, server[0].getAttribute('uri'))
376 return SERVER_LEGACY_XMLRPC, XendClient.uri
378 def parseAuthentication():
379 server = config.getElementsByTagName('server')[0]
380 return (server.getAttribute('username'),
381 server.getAttribute('password'))
383 serverType, serverURI = parseServer()
384 server = None
387 ####################################################################
388 #
389 # Help/usage printing functions
390 #
391 ####################################################################
393 def cmdHelp(cmd):
394 """Print help for a specific subcommand."""
396 for fc in SUBCOMMAND_HELP.keys():
397 if fc[:len(cmd)] == cmd:
398 cmd = fc
399 break
401 try:
402 args, desc = SUBCOMMAND_HELP[cmd]
403 except KeyError:
404 shortHelp()
405 return
407 print 'Usage: xm %s %s' % (cmd, args)
408 print
409 print desc
411 try:
412 # If options help message is defined, print this.
413 for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
414 if shortopt and longopt:
415 optdesc = '%s, %s' % (shortopt, longopt)
416 elif shortopt:
417 optdesc = shortopt
418 elif longopt:
419 optdesc = longopt
421 wrapped_desc = wrap(desc, 43)
422 print ' %-30s %-43s' % (optdesc, wrapped_desc[0])
423 for line in wrapped_desc[1:]:
424 print ' ' * 33 + line
425 print
426 except KeyError:
427 # if the command is an external module, we grab usage help
428 # from the module itself.
429 if cmd in IMPORTED_COMMANDS:
430 try:
431 cmd_module = __import__(cmd, globals(), locals(), 'xen.xm')
432 cmd_usage = getattr(cmd_module, "help", None)
433 if cmd_usage:
434 print cmd_usage()
435 except ImportError:
436 pass
438 def shortHelp():
439 """Print out generic help when xm is called without subcommand."""
441 print USAGE_HELP
442 print 'Common \'xm\' commands:\n'
444 for command in common_commands:
445 try:
446 args, desc = SUBCOMMAND_HELP[command]
447 except KeyError:
448 continue
449 wrapped_desc = wrap(desc, 50)
450 print ' %-20s %-50s' % (command, wrapped_desc[0])
451 for line in wrapped_desc[1:]:
452 print ' ' * 22 + line
454 print
455 print USAGE_FOOTER
456 print 'For a complete list of subcommands run \'xm help\'.'
458 def longHelp():
459 """Print out full help when xm is called with xm --help or xm help"""
461 print USAGE_HELP
462 print 'xm full list of subcommands:\n'
464 for command in all_commands:
465 try:
466 args, desc = SUBCOMMAND_HELP[command]
467 except KeyError:
468 continue
470 wrapped_desc = wrap(desc, 50)
471 print ' %-20s %-50s' % (command, wrapped_desc[0])
472 for line in wrapped_desc[1:]:
473 print ' ' * 22 + line
475 print
476 print USAGE_FOOTER
478 def _usage(cmd):
479 """ Print help usage information """
480 if cmd:
481 cmdHelp(cmd)
482 else:
483 shortHelp()
485 def usage(cmd = None):
486 """ Print help usage information and exits """
487 _usage(cmd)
488 sys.exit(1)
491 ####################################################################
492 #
493 # Utility functions
494 #
495 ####################################################################
497 def get_default_SR():
498 return [sr_ref
499 for sr_ref in server.xenapi.SR.get_all()
500 if server.xenapi.SR.get_type(sr_ref) == "local"][0]
502 def get_default_Network():
503 return [network_ref
504 for network_ref in server.xenapi.network.get_all()][0]
506 class XenAPIUnsupportedException(Exception):
507 pass
509 def xenapi_unsupported():
510 if serverType == SERVER_XEN_API:
511 raise XenAPIUnsupportedException, "This function is not supported by Xen-API"
513 def xenapi_only():
514 if serverType != SERVER_XEN_API:
515 raise XenAPIUnsupportedException, "This function is only supported by Xen-API"
517 def map2sxp(m):
518 return [[k, m[k]] for k in m.keys()]
520 def arg_check(args, name, lo, hi = -1):
521 n = len([i for i in args if i != '--'])
523 if hi == -1:
524 if n != lo:
525 err("'xm %s' requires %d argument%s.\n" % (name, lo,
526 lo == 1 and '' or 's'))
527 usage(name)
528 else:
529 if n < lo or n > hi:
530 err("'xm %s' requires between %d and %d arguments.\n" %
531 (name, lo, hi))
532 usage(name)
535 def unit(c):
536 if not c.isalpha():
537 return 0
538 base = 1
539 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
540 elif c == 'M' or c == 'm': base = 1024 * 1024
541 elif c == 'K' or c == 'k': base = 1024
542 else:
543 print 'ignoring unknown unit'
544 return base
546 def int_unit(str, dest):
547 base = unit(str[-1])
548 if not base:
549 return int(str)
551 value = int(str[:-1])
552 dst_base = unit(dest)
553 if dst_base == 0:
554 dst_base = 1
555 if dst_base > base:
556 return value / (dst_base / base)
557 else:
558 return value * (base / dst_base)
560 def err(msg):
561 print >>sys.stderr, "Error:", msg
564 def get_single_vm(dom):
565 if serverType == SERVER_XEN_API:
566 uuids = server.xenapi.VM.get_by_name_label(dom)
567 if len(uuids) > 0:
568 return uuids[0]
570 refs = []
572 try:
573 domid = int(dom)
574 refs = [vm_ref
575 for vm_ref in server.xenapi.VM.get_all()
576 if int(server.xenapi.VM.get_domid(vm_ref)) == domid]
577 except:
578 pass
580 if len(refs) > 0:
581 return refs[0]
583 raise OptionError("Domain '%s' not found." % dom)
584 else:
585 dominfo = server.xend.domain(dom, False)
586 return dominfo['uuid']
588 ##
589 #
590 # Xen-API Shell
591 #
592 ##
594 class Shell(cmd.Cmd):
595 def __init__(self):
596 cmd.Cmd.__init__(self)
597 self.prompt = "xm> "
598 if serverType == SERVER_XEN_API:
599 try:
600 res = server.xenapi.host.list_methods()
601 for f in res:
602 setattr(Shell, 'do_' + f + ' ', self.default)
603 except:
604 pass
606 def preloop(self):
607 cmd.Cmd.preloop(self)
608 readline.set_completer_delims(' ')
610 def default(self, line):
611 words = shlex.split(line)
612 if len(words) > 0 and words[0] == 'xm':
613 words = words[1:]
614 if len(words) > 0:
615 cmd = xm_lookup_cmd(words[0])
616 if cmd:
617 _run_cmd(cmd, words[0], words[1:])
618 elif serverType == SERVER_XEN_API:
619 ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
620 tuple(x)),
621 words[0], words[1:])
622 if ok and res is not None and res != '':
623 pprint.pprint(res)
624 else:
625 print '*** Unknown command: %s' % words[0]
626 return False
628 def completedefault(self, text, line, begidx, endidx):
629 words = shlex.split(line[:begidx])
630 clas, func = words[0].split('.')
631 if len(words) > 1 or \
632 func.startswith('get_by_') or \
633 func == 'get_all':
634 return []
635 uuids = server.xenapi_request('%s.get_all' % clas, ())
636 return [u + " " for u in uuids if u.startswith(text)]
638 def emptyline(self):
639 pass
641 def do_EOF(self, line):
642 print
643 sys.exit(0)
645 def do_help(self, line):
646 _usage(line)
649 def xm_shell(args):
650 Shell().cmdloop('The Xen Master. Type "help" for a list of functions.')
653 def xm_event_monitor(args):
654 if serverType == SERVER_XEN_API:
655 while True:
656 server.xenapi.event.register(args)
657 events = server.xenapi.event.next()
658 for e in events:
659 print e
660 else:
661 err("Event monitoring not supported unless using Xen-API.")
664 #########################################################################
665 #
666 # Main xm functions
667 #
668 #########################################################################
670 def xm_save(args):
672 arg_check(args, "save", 2, 3)
674 try:
675 (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
676 except getopt.GetoptError, opterr:
677 err(opterr)
678 sys.exit(1)
680 dom = params[0]
681 savefile = params[1]
683 checkpoint = False
684 for (k, v) in options:
685 if k in ['-c', '--checkpoint']:
686 checkpoint = True
688 if len(params) != 2:
689 err("Wrong number of parameters")
690 usage('save')
691 sys.exit(1)
693 savefile = os.path.abspath(savefile)
695 if not os.access(os.path.dirname(savefile), os.W_OK):
696 err("xm save: Unable to create file %s" % savefile)
697 sys.exit(1)
699 if serverType == SERVER_XEN_API:
700 server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
701 else:
702 try:
703 dominfo = parse_doms_info(server.xend.domain(dom))
704 except xmlrpclib.Fault, ex:
705 raise ex
707 domid = dominfo['domid']
708 server.xend.domain.save(domid, savefile, checkpoint)
710 def xm_restore(args):
711 arg_check(args, "restore", 1, 2)
713 try:
714 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
715 except getopt.GetoptError, opterr:
716 err(opterr)
717 usage('restore')
719 paused = False
720 for (k, v) in options:
721 if k in ['-p', '--paused']:
722 paused = True
724 if len(params) != 1:
725 err("Wrong number of parameters")
726 usage('restore')
728 savefile = os.path.abspath(params[0])
730 if not os.access(savefile, os.R_OK):
731 err("xm restore: Unable to read file %s" % savefile)
732 sys.exit(1)
734 if serverType == SERVER_XEN_API:
735 server.xenapi.VM.restore(savefile, paused)
736 else:
737 server.xend.domain.restore(savefile, paused)
740 def datetime_to_secs(v):
741 unwanted = ":-."
742 for c in unwanted:
743 v = str(v).replace(c, "")
744 return time.mktime(time.strptime(v[0:14], '%Y%m%dT%H%M%S'))
746 def getDomains(domain_names, state, full = 0):
747 if serverType == SERVER_XEN_API:
748 doms_sxp = []
749 doms_dict = []
751 dom_recs = server.xenapi.VM.get_all_records()
752 dom_metrics_recs = server.xenapi.VM_metrics.get_all_records()
754 for dom_ref, dom_rec in dom_recs.items():
755 dom_metrics_rec = dom_metrics_recs[dom_rec['metrics']]
757 states = ('running', 'blocked', 'paused', 'shutdown',
758 'crashed', 'dying')
759 def state_on_off(state):
760 if state in dom_metrics_rec['state']:
761 return state[0]
762 else:
763 return "-"
764 state_str = "".join([state_on_off(state)
765 for state in states])
767 dom_rec.update({'name': dom_rec['name_label'],
768 'memory_actual': int(dom_metrics_rec['memory_actual'])/1024,
769 'vcpus': dom_metrics_rec['VCPUs_number'],
770 'state': state_str,
771 'cpu_time': dom_metrics_rec['VCPUs_utilisation'],
772 'start_time': datetime_to_secs(
773 dom_metrics_rec['start_time'])})
775 doms_sxp.append(['domain'] + map2sxp(dom_rec))
776 doms_dict.append(dom_rec)
778 if domain_names:
779 doms = [['domain'] + map2sxp(dom) for dom in doms_dict
780 if dom["name"] in domain_names]
782 if len(doms) > 0:
783 return doms
784 else:
785 print "Error: no domain%s named %s" % \
786 (len(domain_names) > 1 and 's' or '',
787 ', '.join(domain_names))
788 sys.exit(-1)
789 else:
790 return doms_sxp
791 else:
792 if domain_names:
793 return [server.xend.domain(dom, full) for dom in domain_names]
794 else:
795 return server.xend.domains_with_state(True, state, full)
798 def xm_list(args):
799 use_long = 0
800 show_vcpus = 0
801 show_labels = 0
802 state = 'all'
803 try:
804 (options, params) = getopt.gnu_getopt(args, 'lv',
805 ['long','vcpus','label',
806 'state='])
807 except getopt.GetoptError, opterr:
808 err(opterr)
809 usage('list')
811 for (k, v) in options:
812 if k in ['-l', '--long']:
813 use_long = 1
814 if k in ['-v', '--vcpus']:
815 show_vcpus = 1
816 if k in ['--label']:
817 show_labels = 1
818 if k in ['--state']:
819 state = v
821 if state != 'all' and len(params) > 0:
822 raise OptionError(
823 "You may specify either a state or a particular VM, but not both")
825 if show_vcpus:
826 print >>sys.stderr, (
827 "xm list -v is deprecated. Please use xm vcpu-list.")
828 xm_vcpu_list(params)
829 return
831 doms = getDomains(params, state, use_long)
833 if use_long:
834 map(PrettyPrint.prettyprint, doms)
835 elif show_labels:
836 xm_label_list(doms)
837 else:
838 xm_brief_list(doms)
841 def parse_doms_info(info):
842 def get_info(n, t, d):
843 return t(sxp.child_value(info, n, d))
845 def get_status(n, t, d):
846 return DOM_STATES[t(sxp.child_value(info, n, d))]
848 start_time = get_info('start_time', float, -1)
849 if start_time == -1:
850 up_time = float(-1)
851 else:
852 up_time = time.time() - start_time
854 parsed_info = {
855 'domid' : get_info('domid', str, ''),
856 'name' : get_info('name', str, '??'),
857 'state' : get_info('state', str, ''),
859 # VCPUs is the number online when the VM is up, or the number
860 # configured otherwise.
861 'vcpus' : get_info('online_vcpus', int,
862 get_info('vcpus', int, 0)),
863 'up_time' : up_time
864 }
866 # We're not supporting security stuff just yet via XenAPI
868 if serverType != SERVER_XEN_API:
869 from xen.util import security
870 parsed_info['seclabel'] = security.get_security_printlabel(info)
871 else:
872 parsed_info['seclabel'] = ""
874 if serverType == SERVER_XEN_API:
875 parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
876 cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
877 if sum(cpu_times.values()) > 0:
878 parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
879 else:
880 parsed_info['cpu_time'] = 0
881 else:
882 parsed_info['mem'] = get_info('memory', int,0)
883 parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
885 return parsed_info
887 def check_sched_type(sched):
888 if serverType == SERVER_XEN_API:
889 current = server.xenapi.host.get_sched_policy(
890 server.xenapi.session.get_this_host(server.getSession()))
891 else:
892 current = 'unknown'
893 for x in server.xend.node.info()[1:]:
894 if len(x) > 1 and x[0] == 'xen_scheduler':
895 current = x[1]
896 break
897 if sched != current:
898 err("Xen is running with the %s scheduler" % current)
899 sys.exit(1)
901 def parse_sedf_info(info):
902 def get_info(n, t, d):
903 return t(sxp.child_value(info, n, d))
905 return {
906 'domid' : get_info('domid', int, -1),
907 'period' : get_info('period', int, -1),
908 'slice' : get_info('slice', int, -1),
909 'latency' : get_info('latency', int, -1),
910 'extratime': get_info('extratime', int, -1),
911 'weight' : get_info('weight', int, -1),
912 }
914 def domid_match(domid, info):
915 return domid is None or domid == info['name'] or \
916 domid == str(info['domid'])
918 def xm_brief_list(doms):
919 print '%-40s %3s %5s %5s %10s %9s' % \
920 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
922 format = "%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s " \
923 "%(cpu_time)8.1f"
925 for dom in doms:
926 d = parse_doms_info(dom)
927 print format % d
929 def xm_label_list(doms):
930 print '%-32s %3s %5s %5s %5s %9s %-8s' % \
931 ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
933 output = []
934 format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
935 '%(cpu_time)8.1f %(seclabel)9s'
937 if serverType != SERVER_XEN_API:
938 from xen.util import security
940 for dom in doms:
941 d = parse_doms_info(dom)
943 if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
944 if not d['seclabel']:
945 d['seclabel'] = 'ERROR'
946 elif security.active_policy in ['DEFAULT']:
947 d['seclabel'] = 'DEFAULT'
948 else:
949 d['seclabel'] = 'INACTIVE'
951 output.append((format % d, d['seclabel']))
953 #sort by labels
954 output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
955 for line, label in output:
956 print line
959 def xm_vcpu_list(args):
960 if serverType == SERVER_XEN_API:
961 if args:
962 vm_refs = map(get_single_vm, args)
963 else:
964 vm_refs = server.xenapi.VM.get_all()
966 vm_records = dict(map(lambda vm_ref:
967 (vm_ref, server.xenapi.VM.get_record(
968 vm_ref)),
969 vm_refs))
971 vm_metrics = dict(map(lambda (ref, record):
972 (ref,
973 server.xenapi.VM_metrics.get_record(
974 record['metrics'])),
975 vm_records.items()))
977 dominfo = []
979 # vcpu_list doesn't list 'managed' domains
980 # when they are not running, so filter them out
982 vm_refs = [vm_ref
983 for vm_ref in vm_refs
984 if vm_records[vm_ref]["power_state"] != "Halted"]
986 for vm_ref in vm_refs:
987 info = ['domain',
988 ['domid', vm_records[vm_ref]['domid']],
989 ['name', vm_records[vm_ref]['name_label']],
990 ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]]
992 for i in range(int(vm_records[vm_ref]['VCPUs_max'])):
993 def chk_flag(flag):
994 return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \
995 and 1 or 0
997 vcpu_info = ['vcpu',
998 ['number',
999 i],
1000 ['online',
1001 chk_flag("online")],
1002 ['blocked',
1003 chk_flag("blocked")],
1004 ['running',
1005 chk_flag("running")],
1006 ['cpu_time',
1007 vm_metrics[vm_ref]['VCPUs_utilisation'][str(i)]],
1008 ['cpu',
1009 vm_metrics[vm_ref]['VCPUs_CPU'][str(i)]],
1010 ['cpumap',
1011 vm_metrics[vm_ref]['VCPUs_params']\
1012 ['cpumap%i' % i].split(",")]]
1014 info.append(vcpu_info)
1016 dominfo.append(info)
1017 else:
1018 if args:
1019 dominfo = map(server.xend.domain.getVCPUInfo, args)
1020 else:
1021 doms = server.xend.domains(False)
1022 dominfo = map(server.xend.domain.getVCPUInfo, doms)
1024 print '%-32s %3s %5s %5s %5s %9s %s' % \
1025 ('Name', 'ID', 'VCPU', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
1027 format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
1028 ' %(cpu_time)8.1f %(cpumap)s'
1030 for dom in dominfo:
1031 def get_info(n):
1032 return sxp.child_value(dom, n)
1035 # convert a list of integers into a list of pairs indicating
1036 # continuous sequences in the list:
1038 # [0,1,2,3] -> [(0,3)]
1039 # [1,2,4,5] -> [(1,2),(4,5)]
1040 # [0] -> [(0,0)]
1041 # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
1043 def list_to_rangepairs(cmap):
1044 cmap.sort()
1045 pairs = []
1046 x = y = 0
1047 for i in range(0,len(cmap)):
1048 try:
1049 if ((cmap[y+1] - cmap[i]) > 1):
1050 pairs.append((cmap[x],cmap[y]))
1051 x = y = i+1
1052 else:
1053 y = y + 1
1054 # if we go off the end, then just add x to y
1055 except IndexError:
1056 pairs.append((cmap[x],cmap[y]))
1058 return pairs
1061 # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
1063 def format_pairs(pairs):
1064 if not pairs:
1065 return "no cpus"
1066 out = ""
1067 for f,s in pairs:
1068 if (f==s):
1069 out += '%d'%f
1070 else:
1071 out += '%d-%d'%(f,s)
1072 out += ','
1073 # trim trailing ','
1074 return out[:-1]
1076 def format_cpumap(cpumap):
1077 cpumap = map(lambda x: int(x), cpumap)
1078 cpumap.sort()
1080 if serverType == SERVER_XEN_API:
1081 nr_cpus = len(server.xenapi.host.get_host_CPUs(
1082 server.xenapi.session.get_this_host(server.getSession())))
1083 else:
1084 for x in server.xend.node.info()[1:]:
1085 if len(x) > 1 and x[0] == 'nr_cpus':
1086 nr_cpus = int(x[1])
1088 # normalize cpumap by modulus nr_cpus, and drop duplicates
1089 cpumap = dict.fromkeys(
1090 map(lambda x: x % nr_cpus, cpumap)).keys()
1091 if len(cpumap) == nr_cpus:
1092 return "any cpu"
1094 return format_pairs(list_to_rangepairs(cpumap))
1096 name = get_info('name')
1097 domid = int(get_info('domid'))
1099 for vcpu in sxp.children(dom, 'vcpu'):
1100 def vinfo(n, t):
1101 return t(sxp.child_value(vcpu, n))
1103 number = vinfo('number', int)
1104 cpu = vinfo('cpu', int)
1105 cpumap = format_cpumap(vinfo('cpumap', list))
1106 online = vinfo('online', int)
1107 cpu_time = vinfo('cpu_time', float)
1108 running = vinfo('running', int)
1109 blocked = vinfo('blocked', int)
1111 if online:
1112 c = str(cpu)
1113 if running:
1114 s = 'r'
1115 else:
1116 s = '-'
1117 if blocked:
1118 s += 'b'
1119 else:
1120 s += '-'
1121 s += '-'
1122 else:
1123 c = "-"
1124 s = "--p"
1126 print format % locals()
1128 def xm_start(args):
1129 arg_check(args, "start", 1, 2)
1131 try:
1132 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1133 except getopt.GetoptError, opterr:
1134 err(opterr)
1135 usage('start')
1137 paused = False
1138 for (k, v) in options:
1139 if k in ['-p', '--paused']:
1140 paused = True
1142 if len(params) != 1:
1143 err("Wrong number of parameters")
1144 usage('start')
1146 dom = params[0]
1147 if serverType == SERVER_XEN_API:
1148 server.xenapi.VM.start(get_single_vm(dom), paused)
1149 else:
1150 server.xend.domain.start(dom, paused)
1152 def xm_delete(args):
1153 arg_check(args, "delete", 1)
1154 dom = args[0]
1155 if serverType == SERVER_XEN_API:
1156 server.xenapi.VM.destroy(get_single_vm(dom))
1157 else:
1158 server.xend.domain.delete(dom)
1160 def xm_suspend(args):
1161 arg_check(args, "suspend", 1)
1162 dom = args[0]
1163 if serverType == SERVER_XEN_API:
1164 server.xenapi.VM.suspend(get_single_vm(dom))
1165 else:
1166 server.xend.domain.suspend(dom)
1168 def xm_resume(args):
1169 arg_check(args, "resume", 1, 2)
1171 try:
1172 (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
1173 except getopt.GetoptError, opterr:
1174 err(opterr)
1175 usage('resume')
1177 paused = False
1178 for (k, v) in options:
1179 if k in ['-p', '--paused']:
1180 paused = True
1182 if len(params) != 1:
1183 err("Wrong number of parameters")
1184 usage('resume')
1186 dom = params[0]
1187 if serverType == SERVER_XEN_API:
1188 server.xenapi.VM.resume(get_single_vm(dom), paused)
1189 else:
1190 server.xend.domain.resume(dom, paused)
1192 def xm_reboot(args):
1193 arg_check(args, "reboot", 1, 3)
1194 from xen.xm import shutdown
1195 shutdown.main(["shutdown", "-R"] + args)
1197 def xm_shutdown(args):
1198 arg_check(args, "shutdown", 1, 4)
1199 from xen.xm import shutdown
1200 shutdown.main(["shutdown"] + args)
1202 def xm_pause(args):
1203 arg_check(args, "pause", 1)
1204 dom = args[0]
1206 if serverType == SERVER_XEN_API:
1207 server.xenapi.VM.pause(get_single_vm(dom))
1208 else:
1209 server.xend.domain.pause(dom)
1211 def xm_unpause(args):
1212 arg_check(args, "unpause", 1)
1213 dom = args[0]
1215 if serverType == SERVER_XEN_API:
1216 server.xenapi.VM.unpause(get_single_vm(dom))
1217 else:
1218 server.xend.domain.unpause(dom)
1220 def xm_dump_core(args):
1221 live = False
1222 crash = False
1223 try:
1224 (options, params) = getopt.gnu_getopt(args, 'LC', ['live','crash'])
1225 for (k, v) in options:
1226 if k in ('-L', '--live'):
1227 live = True
1228 if k in ('-C', '--crash'):
1229 crash = True
1231 if len(params) not in (1, 2):
1232 raise OptionError("Expects 1 or 2 argument(s)")
1233 except getopt.GetoptError, e:
1234 raise OptionError(str(e))
1236 dom = params[0]
1237 if len(params) == 2:
1238 filename = os.path.abspath(params[1])
1239 else:
1240 filename = None
1242 if not live:
1243 server.xend.domain.pause(dom)
1245 try:
1246 print "Dumping core of domain: %s ..." % str(dom)
1247 server.xend.domain.dump(dom, filename, live, crash)
1248 finally:
1249 if not live:
1250 server.xend.domain.unpause(dom)
1252 if crash:
1253 print "Destroying domain: %s ..." % str(dom)
1254 server.xend.domain.destroy(dom)
1256 def xm_rename(args):
1257 arg_check(args, "rename", 2)
1259 if serverType == SERVER_XEN_API:
1260 server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1])
1261 else:
1262 server.xend.domain.setName(args[0], args[1])
1264 def xm_importcommand(command, args):
1265 cmd = __import__(command, globals(), locals(), 'xen.xm')
1266 cmd.main([command] + args)
1269 #############################################################
1271 def xm_vcpu_pin(args):
1272 arg_check(args, "vcpu-pin", 3)
1274 def cpu_make_map(cpulist):
1275 cpus = []
1276 for c in cpulist.split(','):
1277 if c.find('-') != -1:
1278 (x,y) = c.split('-')
1279 for i in range(int(x),int(y)+1):
1280 cpus.append(int(i))
1281 else:
1282 # remove this element from the list
1283 if c[0] == '^':
1284 cpus = [x for x in cpus if x != int(c[1:])]
1285 else:
1286 cpus.append(int(c))
1287 cpus.sort()
1288 return cpus
1290 dom = args[0]
1291 vcpu = int(args[1])
1292 if args[2] == 'all':
1293 cpumap = cpu_make_map('0-63')
1294 else:
1295 cpumap = cpu_make_map(args[2])
1297 if serverType == SERVER_XEN_API:
1298 cpumap = map(str, cpumap)
1299 server.xenapi.VM.add_to_VCPUs_params_live(
1300 get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap))
1301 else:
1302 server.xend.domain.pincpu(dom, vcpu, cpumap)
1304 def xm_mem_max(args):
1305 arg_check(args, "mem-max", 2)
1307 dom = args[0]
1309 if serverType == SERVER_XEN_API:
1310 mem = int_unit(args[1], 'k') * 1024
1311 server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem)
1312 else:
1313 mem = int_unit(args[1], 'm')
1314 server.xend.domain.maxmem_set(dom, mem)
1316 def xm_mem_set(args):
1317 arg_check(args, "mem-set", 2)
1319 dom = args[0]
1321 if serverType == SERVER_XEN_API:
1322 mem_target = int_unit(args[1], 'm') * 1024 * 1024
1323 server.xenapi.VM.set_memory_dynamic_max_live(get_single_vm(dom),
1324 mem_target)
1325 server.xenapi.VM.set_memory_dynamic_min_live(get_single_vm(dom),
1326 mem_target)
1327 else:
1328 mem_target = int_unit(args[1], 'm')
1329 server.xend.domain.setMemoryTarget(dom, mem_target)
1331 def xm_vcpu_set(args):
1332 arg_check(args, "vcpu-set", 2)
1334 dom = args[0]
1335 vcpus = int(args[1])
1337 if serverType == SERVER_XEN_API:
1338 server.xenapi.VM.set_VCPUs_number_live(get_single_vm(dom), vcpus)
1339 else:
1340 server.xend.domain.setVCpuCount(dom, vcpus)
1342 def xm_destroy(args):
1343 arg_check(args, "destroy", 1)
1345 dom = args[0]
1347 if serverType == SERVER_XEN_API:
1348 server.xenapi.VM.hard_shutdown(get_single_vm(dom))
1349 else:
1350 server.xend.domain.destroy(dom)
1352 def xm_domid(args):
1353 arg_check(args, "domid", 1)
1355 name = args[0]
1357 if serverType == SERVER_XEN_API:
1358 print server.xenapi.VM.get_domid(get_single_vm(name))
1359 else:
1360 dom = server.xend.domain(name)
1361 print sxp.child_value(dom, 'domid')
1363 def xm_domname(args):
1364 arg_check(args, "domname", 1)
1366 name = args[0]
1368 if serverType == SERVER_XEN_API:
1369 print server.xenapi.VM.get_name_label(get_single_vm(name))
1370 else:
1371 dom = server.xend.domain(name)
1372 print sxp.child_value(dom, 'name')
1374 def xm_sched_sedf(args):
1375 xenapi_unsupported()
1377 def ns_to_ms(val):
1378 return float(val) * 0.000001
1380 def ms_to_ns(val):
1381 return (float(val) / 0.000001)
1383 def print_sedf(info):
1384 info['period'] = ns_to_ms(info['period'])
1385 info['slice'] = ns_to_ms(info['slice'])
1386 info['latency'] = ns_to_ms(info['latency'])
1387 print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
1388 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
1390 check_sched_type('sedf')
1392 # we want to just display current info if no parameters are passed
1393 if len(args) == 0:
1394 domid = None
1395 else:
1396 # we expect at least a domain id (name or number)
1397 # and at most a domid up to 5 options with values
1398 arg_check(args, "sched-sedf", 1, 11)
1399 domid = args[0]
1400 # drop domid from args since get_opt doesn't recognize it
1401 args = args[1:]
1403 opts = {}
1404 try:
1405 (options, params) = getopt.gnu_getopt(args, 'p:s:l:e:w:',
1406 ['period=', 'slice=', 'latency=', 'extratime=', 'weight='])
1407 except getopt.GetoptError, opterr:
1408 err(opterr)
1409 usage('sched-sedf')
1411 # convert to nanoseconds if needed
1412 for (k, v) in options:
1413 if k in ['-p', '--period']:
1414 opts['period'] = ms_to_ns(v)
1415 elif k in ['-s', '--slice']:
1416 opts['slice'] = ms_to_ns(v)
1417 elif k in ['-l', '--latency']:
1418 opts['latency'] = ms_to_ns(v)
1419 elif k in ['-e', '--extratime']:
1420 opts['extratime'] = v
1421 elif k in ['-w', '--weight']:
1422 opts['weight'] = v
1424 doms = filter(lambda x : domid_match(domid, x),
1425 [parse_doms_info(dom)
1426 for dom in getDomains(None, 'running')])
1427 if domid is not None and doms == []:
1428 err("Domain '%s' does not exist." % domid)
1429 usage('sched-sedf')
1431 # print header if we aren't setting any parameters
1432 if len(opts.keys()) == 0:
1433 print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
1434 ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
1435 'Extra','Weight')
1437 for d in doms:
1438 # fetch current values so as not to clobber them
1439 try:
1440 sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
1441 except xmlrpclib.Fault:
1442 # domain does not support sched-sedf?
1443 sedf_raw = {}
1445 sedf_info = parse_sedf_info(sedf_raw)
1446 sedf_info['name'] = d['name']
1447 # update values in case of call to set
1448 if len(opts.keys()) > 0:
1449 for k in opts.keys():
1450 sedf_info[k]=opts[k]
1452 # send the update, converting user input
1453 v = map(int, [sedf_info['period'], sedf_info['slice'],
1454 sedf_info['latency'],sedf_info['extratime'],
1455 sedf_info['weight']])
1456 rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
1457 if int(rv) != 0:
1458 err("Failed to set sedf parameters (rv=%d)."%(rv))
1460 # not setting values, display info
1461 else:
1462 print_sedf(sedf_info)
1464 def xm_sched_credit(args):
1465 """Get/Set options for Credit Scheduler."""
1467 check_sched_type('credit')
1469 try:
1470 opts, params = getopt.getopt(args, "d:w:c:",
1471 ["domain=", "weight=", "cap="])
1472 except getopt.GetoptError, opterr:
1473 err(opterr)
1474 usage('sched-credit')
1476 domid = None
1477 weight = None
1478 cap = None
1480 for o, a in opts:
1481 if o == "-d":
1482 domid = a
1483 elif o == "-w":
1484 weight = int(a)
1485 elif o == "-c":
1486 cap = int(a);
1488 doms = filter(lambda x : domid_match(domid, x),
1489 [parse_doms_info(dom)
1490 for dom in getDomains(None, 'running')])
1492 if weight is None and cap is None:
1493 if domid is not None and doms == []:
1494 err("Domain '%s' does not exist." % domid)
1495 usage('sched-credit')
1496 # print header if we aren't setting any parameters
1497 print '%-33s %-2s %-6s %-4s' % ('Name','ID','Weight','Cap')
1499 for d in doms:
1500 try:
1501 if serverType == SERVER_XEN_API:
1502 info = server.xenapi.VM_metrics.get_VCPUs_params(
1503 server.xenapi.VM.get_metrics(
1504 get_single_vm(d['name'])))
1505 else:
1506 info = server.xend.domain.sched_credit_get(d['domid'])
1507 except xmlrpclib.Fault:
1508 pass
1510 if 'weight' not in info or 'cap' not in info:
1511 # domain does not support sched-credit?
1512 info = {'weight': -1, 'cap': -1}
1514 info['weight'] = int(info['weight'])
1515 info['cap'] = int(info['cap'])
1517 info['name'] = d['name']
1518 info['domid'] = int(d['domid'])
1519 print( ("%(name)-32s %(domid)3d %(weight)6d %(cap)4d") % info)
1520 else:
1521 if domid is None:
1522 # place holder for system-wide scheduler parameters
1523 err("No domain given.")
1524 usage('sched-credit')
1526 if serverType == SERVER_XEN_API:
1527 server.xenapi.VM.add_to_VCPUs_params_live(
1528 get_single_vm(domid),
1529 "weight",
1530 weight)
1531 server.xenapi.VM.add_to_VCPUs_params_live(
1532 get_single_vm(domid),
1533 "cap",
1534 cap)
1535 else:
1536 result = server.xend.domain.sched_credit_set(domid, weight, cap)
1537 if result != 0:
1538 err(str(result))
1540 def xm_info(args):
1541 arg_check(args, "info", 0)
1543 if serverType == SERVER_XEN_API:
1545 # Need to fake out old style xm info as people rely on parsing it
1547 host_record = server.xenapi.host.get_record(
1548 server.xenapi.session.get_this_host(server.getSession()))
1550 host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"])
1552 host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"])
1554 def getVal(keys, default=""):
1555 data = host_record
1556 for key in keys:
1557 if key in data:
1558 data = data[key]
1559 else:
1560 return default
1561 return data
1563 def getCpuMhz():
1564 cpu_speeds = [int(host_cpu_record["speed"])
1565 for host_cpu_record in host_cpu_records
1566 if "speed" in host_cpu_record]
1567 if len(cpu_speeds) > 0:
1568 return sum(cpu_speeds) / len(cpu_speeds)
1569 else:
1570 return 0
1572 getCpuMhz()
1574 def getCpuFeatures():
1575 if len(host_cpu_records) > 0:
1576 return host_cpu_records[0].get("features", "")
1577 else:
1578 return ""
1580 info = {
1581 "host": getVal(["name_label"]),
1582 "release": getVal(["software_version", "release"]),
1583 "version": getVal(["software_version", "version"]),
1584 "machine": getVal(["software_version", "machine"]),
1585 "nr_cpus": len(getVal(["host_CPUs"], [])),
1586 "nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
1587 "sockets_per_node": getVal(["cpu_configuration", "sockets_per_node"]),
1588 "cores_per_socket": getVal(["cpu_configuration", "cores_per_socket"]),
1589 "threads_per_core": getVal(["cpu_configuration", "threads_per_core"]),
1590 "cpu_mhz": getCpuMhz(),
1591 "hw_caps": getCpuFeatures(),
1592 "total_memory": int(host_metrics_record["memory_total"])/1024/1024,
1593 "free_memory": int(host_metrics_record["memory_free"])/1024/1024,
1594 "xen_major": getVal(["software_version", "xen_major"]),
1595 "xen_minor": getVal(["software_version", "xen_minor"]),
1596 "xen_extra": getVal(["software_version", "xen_extra"]),
1597 "xen_caps": " ".join(getVal(["capabilities"], [])),
1598 "xen_scheduler": getVal(["sched_policy"]),
1599 "xen_pagesize": getVal(["other_config", "xen_pagesize"]),
1600 "platform_params": getVal(["other_config", "platform_params"]),
1601 "xen_changeset": getVal(["software_version", "xen_changeset"]),
1602 "cc_compiler": getVal(["software_version", "cc_compiler"]),
1603 "cc_compile_by": getVal(["software_version", "cc_compile_by"]),
1604 "cc_compile_domain": getVal(["software_version", "cc_compile_domain"]),
1605 "cc_compile_date": getVal(["software_version", "cc_compile_date"]),
1606 "xend_config_format":getVal(["software_version", "xend_config_format"])
1609 sorted = info.items()
1610 sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
1612 for (k, v) in sorted:
1613 print "%-23s:" % k, v
1614 else:
1615 info = server.xend.node.info()
1616 for x in info[1:]:
1617 if len(x) < 2:
1618 print "%-23s: (none)" % x[0]
1619 else:
1620 print "%-23s:" % x[0], x[1]
1622 def xm_console(args):
1623 arg_check(args, "console", 1, 2)
1625 quiet = False;
1627 try:
1628 (options, params) = getopt.gnu_getopt(args, 'q', ['quiet'])
1629 except getopt.GetoptError, opterr:
1630 err(opterr)
1631 usage('console')
1633 for (k, v) in options:
1634 if k in ['-q', '--quiet']:
1635 quiet = True
1636 else:
1637 assert False
1639 if len(params) != 1:
1640 err('No domain given')
1641 usage('console')
1643 dom = params[0]
1645 try:
1646 if serverType == SERVER_XEN_API:
1647 domid = int(server.xenapi.VM.get_domid(get_single_vm(dom)))
1648 else:
1649 info = server.xend.domain(dom)
1650 domid = int(sxp.child_value(info, 'domid', '-1'))
1651 except:
1652 if quiet:
1653 sys.exit(1)
1654 else:
1655 raise
1657 if domid == -1:
1658 if quiet:
1659 sys.exit(1)
1660 else:
1661 raise xmlrpclib.Fault(0, "Domain '%s' is not started" % dom)
1663 console.execConsole(domid)
1666 def xm_uptime(args):
1667 short_mode = 0
1669 try:
1670 (options, params) = getopt.gnu_getopt(args, 's', ['short'])
1671 except getopt.GetoptError, opterr:
1672 err(opterr)
1673 usage('uptime')
1675 for (k, v) in options:
1676 if k in ['-s', '--short']:
1677 short_mode = 1
1679 doms = getDomains(params, 'running')
1681 if short_mode == 0:
1682 print 'Name ID Uptime'
1684 for dom in doms:
1685 d = parse_doms_info(dom)
1686 if int(d['domid']) > 0:
1687 uptime = int(round(d['up_time']))
1688 else:
1689 f=open('/proc/uptime', 'r')
1690 upfile = f.read()
1691 uptime = int(round(float(upfile.split(' ')[0])))
1692 f.close()
1694 days = int(uptime / 86400)
1695 uptime -= (days * 86400)
1696 hours = int(uptime / 3600)
1697 uptime -= (hours * 3600)
1698 minutes = int(uptime / 60)
1699 uptime -= (minutes * 60)
1700 seconds = uptime
1702 upstring = ""
1703 if days > 0:
1704 upstring += str(days) + " day"
1705 if days > 1:
1706 upstring += "s"
1707 upstring += ", "
1708 upstring += '%(hours)2d:%(minutes)02d' % vars()
1710 if short_mode:
1711 now = datetime.datetime.now()
1712 upstring = now.strftime(" %H:%M:%S") + " up " + upstring
1713 upstring += ", " + d['name'] + " (" + d['domid'] + ")"
1714 else:
1715 upstring += ':%(seconds)02d' % vars()
1716 upstring = ("%(name)-32s %(domid)3s " % d) + upstring
1718 print upstring
1720 def xm_sysrq(args):
1721 arg_check(args, "sysrq", 2)
1722 dom = args[0]
1723 req = args[1]
1724 if serverType == SERVER_XEN_API:
1725 server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
1726 else:
1727 server.xend.domain.send_sysrq(dom, req)
1729 def xm_trigger(args):
1730 vcpu = 0
1732 arg_check(args, "trigger", 2, 3)
1733 dom = args[0]
1734 trigger = args[1]
1735 if len(args) == 3:
1736 vcpu = int(args[2])
1738 if serverType == SERVER_XEN_API:
1739 server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
1740 else:
1741 server.xend.domain.send_trigger(dom, trigger, vcpu)
1743 def xm_debug_keys(args):
1744 arg_check(args, "debug-keys", 1)
1746 keys = str(args[0])
1748 if serverType == SERVER_XEN_API:
1749 server.xenapi.host.send_debug_keys(
1750 server.xenapi.session.get_this_host(server.getSession()),
1751 keys)
1752 else:
1753 server.xend.node.send_debug_keys(keys)
1755 def xm_top(args):
1756 arg_check(args, "top", 0)
1758 os.execvp('xentop', ['xentop'])
1760 def xm_dmesg(args):
1761 arg_check(args, "dmesg", 0, 1)
1763 try:
1764 (options, params) = getopt.gnu_getopt(args, 'c', ['clear'])
1765 except getopt.GetoptError, opterr:
1766 err(opterr)
1767 usage('dmesg')
1769 use_clear = 0
1770 for (k, v) in options:
1771 if k in ['-c', '--clear']:
1772 use_clear = 1
1774 if len(params) :
1775 err("No parameter required")
1776 usage('dmesg')
1778 if serverType == SERVER_XEN_API:
1779 host = server.xenapi.session.get_this_host(server.getSession())
1780 if use_clear:
1781 print server.xenapi.host.dmesg_clear(host),
1782 else:
1783 print server.xenapi.host.dmesg(host),
1784 else:
1785 if not use_clear:
1786 print server.xend.node.dmesg.info(),
1787 else:
1788 print server.xend.node.dmesg.clear(),
1790 def xm_log(args):
1791 arg_check(args, "log", 0)
1793 if serverType == SERVER_XEN_API:
1794 print server.xenapi.host.get_log(
1795 server.xenapi.session.get_this_host(server.getSession()))
1796 else:
1797 print server.xend.node.log()
1799 def xm_serve(args):
1800 if serverType == SERVER_XEN_API:
1801 print "Not supported with XenAPI"
1802 sys.exit(-1)
1804 arg_check(args, "serve", 0)
1806 from fcntl import fcntl, F_SETFL
1808 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1809 s.connect(XendClient.XML_RPC_SOCKET)
1810 fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
1812 while True:
1813 iwtd, owtd, ewtd = select([sys.stdin, s], [], [])
1814 if s in iwtd:
1815 data = s.recv(4096)
1816 if len(data) > 0:
1817 sys.stdout.write(data)
1818 sys.stdout.flush()
1819 else:
1820 break
1821 if sys.stdin in iwtd:
1822 data = sys.stdin.read(4096)
1823 if len(data) > 0:
1824 s.sendall(data)
1825 else:
1826 break
1827 s.close()
1829 def parse_dev_info(info):
1830 def get_info(n, t, d):
1831 i = 0
1832 while i < len(info):
1833 if (info[i][0] == n):
1834 return t(info[i][1])
1835 i = i + 1
1836 return t(d)
1837 return {
1838 #common
1839 'backend-id' : get_info('backend-id', int, -1),
1840 'handle' : get_info('handle', int, 0),
1841 'state' : get_info('state', int, -1),
1842 'be-path' : get_info('backend', str, '??'),
1843 'event-ch' : get_info('event-channel',int, -1),
1844 #network specific
1845 'virtual-device' : get_info('virtual-device', str, '??'),
1846 'tx-ring-ref': get_info('tx-ring-ref', int, -1),
1847 'rx-ring-ref': get_info('rx-ring-ref', int, -1),
1848 'mac' : get_info('mac', str, '??'),
1849 #block-device specific
1850 'ring-ref' : get_info('ring-ref', int, -1),
1853 def arg_check_for_resource_list(args, name):
1854 use_long = 0
1855 try:
1856 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
1857 except getopt.GetoptError, opterr:
1858 err(opterr)
1859 sys.exit(1)
1861 for (k, v) in options:
1862 if k in ['-l', '--long']:
1863 use_long = 1
1865 if len(params) == 0:
1866 print 'No domain parameter given'
1867 usage(name)
1868 if len(params) > 1:
1869 print 'No multiple domain parameters allowed'
1870 usage(name)
1872 return (use_long, params)
1874 def xm_network_list(args):
1875 (use_long, params) = arg_check_for_resource_list(args, "network-list")
1877 dom = params[0]
1879 if serverType == SERVER_XEN_API:
1880 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
1881 vif_properties = \
1882 map(server.xenapi.VIF.get_runtime_properties, vif_refs)
1883 devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
1884 zip(range(len(vif_properties)), vif_properties))
1885 else:
1886 devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
1888 if use_long:
1889 map(PrettyPrint.prettyprint, devs)
1890 else:
1891 hdr = 0
1892 for x in devs:
1893 if hdr == 0:
1894 print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
1895 hdr = 1
1896 ni = parse_dev_info(x[1])
1897 ni['idx'] = int(x[0])
1898 print ("%(idx)-3d "
1899 "%(backend-id)-3d"
1900 "%(mac)-17s "
1901 "%(handle)-3d "
1902 "%(state)-3d "
1903 "%(event-ch)-3d "
1904 "%(tx-ring-ref)-5d/%(rx-ring-ref)-5d "
1905 "%(be-path)-30s "
1906 % ni)
1908 def xm_block_list(args):
1909 (use_long, params) = arg_check_for_resource_list(args, "block-list")
1911 dom = params[0]
1913 if serverType == SERVER_XEN_API:
1914 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
1915 vbd_properties = \
1916 map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
1917 vbd_devs = \
1918 map(server.xenapi.VBD.get_device, vbd_refs)
1919 vbd_devids = \
1920 map(blkdev_name_to_number, vbd_devs)
1921 devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
1922 zip(vbd_devids, vbd_properties))
1923 else:
1924 devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
1926 if use_long:
1927 map(PrettyPrint.prettyprint, devs)
1928 else:
1929 hdr = 0
1930 for x in devs:
1931 if hdr == 0:
1932 print 'Vdev BE handle state evt-ch ring-ref BE-path'
1933 hdr = 1
1934 ni = parse_dev_info(x[1])
1935 ni['idx'] = int(x[0])
1936 print ("%(idx)-3d "
1937 "%(backend-id)-3d "
1938 "%(handle)-3d "
1939 "%(state)-3d "
1940 "%(event-ch)-3d "
1941 "%(ring-ref)-5d "
1942 "%(be-path)-30s "
1943 % ni)
1945 def xm_vtpm_list(args):
1946 xenapi_unsupported()
1947 (use_long, params) = arg_check_for_resource_list(args, "vtpm-list")
1949 dom = params[0]
1950 if use_long:
1951 devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm')
1952 map(PrettyPrint.prettyprint, devs)
1953 else:
1954 hdr = 0
1955 for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'):
1956 if hdr == 0:
1957 print 'Idx BE handle state evt-ch ring-ref BE-path'
1958 hdr = 1
1959 ni = parse_dev_info(x[1])
1960 ni['idx'] = int(x[0])
1961 print ("%(idx)-3d "
1962 "%(backend-id)-3d "
1963 "%(handle)-3d "
1964 "%(state)-3d "
1965 "%(event-ch)-3d "
1966 "%(ring-ref)-5d "
1967 "%(be-path)-30s "
1968 % ni)
1971 def parse_block_configuration(args):
1972 dom = args[0]
1974 if args[1].startswith('tap:'):
1975 cls = 'tap'
1976 else:
1977 cls = 'vbd'
1979 vbd = [cls,
1980 ['uname', args[1]],
1981 ['dev', args[2]],
1982 ['mode', args[3]]]
1983 if len(args) == 5:
1984 vbd.append(['backend', args[4]])
1986 if serverType != SERVER_XEN_API:
1987 # verify that policy permits attaching this resource
1988 from xen.util import security
1990 if security.on():
1991 dominfo = server.xend.domain(dom)
1992 label = security.get_security_printlabel(dominfo)
1993 else:
1994 label = None
1996 security.res_security_check(args[1], label)
1998 return (dom, vbd)
2001 def xm_block_attach(args):
2002 arg_check(args, 'block-attach', 4, 5)
2004 if serverType == SERVER_XEN_API:
2005 dom = args[0]
2006 uname = args[1]
2007 dev = args[2]
2008 mode = args[3]
2010 # First create new VDI
2011 vdi_record = {
2012 "name_label": "vdi" + str(uname.__hash__()),
2013 "name_description": "",
2014 "SR": get_default_SR(),
2015 "virtual_size": 0,
2016 "sector_size": 512,
2017 "type": "system",
2018 "sharable": False,
2019 "read_only": mode!="w",
2020 "other_config": {"location": uname}
2023 vdi_ref = server.xenapi.VDI.create(vdi_record)
2025 # Now create new VBD
2027 vbd_record = {
2028 "VM": get_single_vm(dom),
2029 "VDI": vdi_ref,
2030 "device": dev,
2031 "bootable": True,
2032 "mode": mode=="w" and "RW" or "RO",
2033 "type": "Disk",
2034 "qos_algorithm_type": "",
2035 "qos_algorithm_params": {}
2038 server.xenapi.VBD.create(vbd_record)
2040 else:
2041 (dom, vbd) = parse_block_configuration(args)
2042 server.xend.domain.device_create(dom, vbd)
2045 def xm_block_configure(args):
2046 arg_check(args, 'block-configure', 4, 5)
2048 (dom, vbd) = parse_block_configuration(args)
2049 server.xend.domain.device_configure(dom, vbd)
2052 def xm_network_attach(args):
2053 arg_check(args, 'network-attach', 1, 10)
2055 dom = args[0]
2056 vif = ['vif']
2057 vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
2058 'backend', 'vifname', 'rate', 'model']
2060 if serverType == SERVER_XEN_API:
2061 vif_record = {
2062 "device": "eth0",
2063 "network": get_default_Network(),
2064 "VM": get_single_vm(dom),
2065 "MAC": "",
2066 "MTU": "",
2067 "qos_algorithm_type": "",
2068 "qos_algorithm_params": {},
2069 "other_config": {}
2072 def set(keys, val):
2073 record = vif_record
2074 for key in keys[:-1]:
2075 record = record[key]
2076 record[keys[-1]] = val
2078 def get_net_from_bridge(bridge):
2079 # In OSS, we just assert network.name_label == bridge name
2080 networks = dict([(record['name_label'], ref)
2081 for ref, record in server.xenapi.network
2082 .get_all_records().items()])
2083 if bridge not in networks.keys():
2084 raise "Unknown bridge name!"
2085 return networks[bridge]
2087 vif_conv = {
2088 'type':
2089 lambda x: None,
2090 'mac':
2091 lambda x: set(['MAC'], x),
2092 'bridge':
2093 lambda x: set(['network'], get_net_from_bridge(x)),
2094 'ip':
2095 lambda x: set(['other_config', 'ip'], x),
2096 'script':
2097 lambda x: set(['other_config', 'script'], x),
2098 'backend':
2099 lambda x: set(['other_config', 'backend'], x),
2100 'vifname':
2101 lambda x: set(['device'], x),
2102 'rate':
2103 lambda x: set(['qos_algorithm_params', 'rate'], x),
2104 'model':
2105 lambda x: None
2108 for a in args[1:]:
2109 vif_param = a.split("=")
2110 if len(vif_param) != 2 or vif_param[1] == '' or \
2111 vif_param[0] not in vif_params:
2112 err("Invalid argument: %s" % a)
2113 usage('network-attach')
2114 else:
2115 vif_conv[vif_param[0]](vif_param[1])
2117 server.xenapi.VIF.create(vif_record)
2118 else:
2119 for a in args[1:]:
2120 vif_param = a.split("=")
2121 if len(vif_param) != 2 or vif_param[1] == '' or \
2122 vif_param[0] not in vif_params:
2123 err("Invalid argument: %s" % a)
2124 usage('network-attach')
2125 vif.append(vif_param)
2126 server.xend.domain.device_create(dom, vif)
2129 def detach(args, command, deviceClass):
2130 arg_check(args, command, 2, 3)
2132 dom = args[0]
2133 dev = args[1]
2134 try:
2135 force = args[2]
2136 if (force != "--force") and (force != "-f"):
2137 print "Ignoring option %s"%(force)
2138 force = None
2139 except IndexError:
2140 force = None
2142 server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
2145 def xm_block_detach(args):
2146 if serverType == SERVER_XEN_API:
2147 arg_check(args, "xm_block_detach", 2, 3)
2148 dom = args[0]
2149 dev = args[1]
2150 vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
2151 vbd_refs = [vbd_ref for vbd_ref in vbd_refs
2152 if server.xenapi.VBD.get_device(vbd_ref) == dev]
2153 if len(vbd_refs) > 0:
2154 vbd_ref = vbd_refs[0]
2155 vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
2157 server.xenapi.VBD.destroy(vbd_ref)
2159 if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
2160 server.xenapi.VDI.destroy(vdi_ref)
2161 else:
2162 raise OptionError("Cannot find device '%s' in domain '%s'"
2163 % (dev,dom))
2164 else:
2165 try:
2166 detach(args, 'block-detach', 'vbd')
2167 return
2168 except:
2169 pass
2170 detach(args, 'block-detach', 'tap')
2172 def xm_network_detach(args):
2173 if serverType == SERVER_XEN_API:
2174 arg_check(args, "xm_block_detach", 2, 3)
2175 dom = args[0]
2176 devid = args[1]
2177 vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
2178 vif_refs = [vif_ref for vif_ref in vif_refs
2179 if server.xenapi.VIF.\
2180 get_runtime_properties(vif_ref)["handle"] == devid]
2181 if len(vif_refs) > 0:
2182 vif_ref = vif_refs[0]
2184 server.xenapi.VIF.destroy(vif_ref)
2185 else:
2186 print "Cannot find device '%s' in domain '%s'" % (devid,dom)
2187 else:
2188 detach(args, 'network-detach', 'vif')
2191 def xm_vnet_list(args):
2192 xenapi_unsupported()
2193 try:
2194 (options, params) = getopt.gnu_getopt(args, 'l', ['long'])
2195 except getopt.GetoptError, opterr:
2196 err(opterr)
2197 usage('vnet-list')
2199 use_long = 0
2200 for (k, v) in options:
2201 if k in ['-l', '--long']:
2202 use_long = 1
2204 if params:
2205 use_long = 1
2206 vnets = params
2207 else:
2208 vnets = server.xend_vnets()
2210 for vnet in vnets:
2211 try:
2212 if use_long:
2213 info = server.xend_vnet(vnet)
2214 PrettyPrint.prettyprint(info)
2215 else:
2216 print vnet
2217 except Exception, ex:
2218 print vnet, ex
2220 def xm_vnet_create(args):
2221 xenapi_unsupported()
2222 arg_check(args, "vnet-create", 1)
2223 conf = args[0]
2224 if not os.access(conf, os.R_OK):
2225 print "File not found: %s" % conf
2226 sys.exit(1)
2228 server.xend_vnet_create(conf)
2230 def xm_vnet_delete(args):
2231 xenapi_unsupported()
2232 arg_check(args, "vnet-delete", 1)
2233 vnet = args[0]
2234 server.xend_vnet_delete(vnet)
2236 def xm_network_new(args):
2237 xenapi_only()
2238 arg_check(args, "network-new", 1)
2239 network = args[0]
2241 record = {
2242 "name_label": network,
2243 "name_description": "",
2244 "other_config": {},
2245 "default_gateway": "",
2246 "default_netmask": ""
2249 server.xenapi.network.create(record)
2251 def xm_network_del(args):
2252 xenapi_only()
2253 arg_check(args, "network-del", 1)
2254 network = args[0]
2256 networks = dict([(record['name_label'], ref)
2257 for ref, record in
2258 server.xenapi.network.get_all_records().items()])
2260 if network not in networks.keys():
2261 raise ValueError("'%s' is not a valid network name" % network)
2263 server.xenapi.network.destroy(networks[network])
2265 def xm_network_show(args):
2266 xenapi_only()
2267 arg_check(args, "network-show", 0)
2269 networks = server.xenapi.network.get_all_records()
2270 pifs = server.xenapi.PIF.get_all_records()
2271 vifs = server.xenapi.VIF.get_all_records()
2273 print '%-20s %-40s %-10s' % \
2274 ('Name', 'VIFs', 'PIFs')
2276 format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s"
2278 for network_ref, network in networks.items():
2279 for i in range(max(len(network['PIFs']),
2280 len(network['VIFs']), 1)):
2281 if i < len(network['PIFs']):
2282 pif_uuid = network['PIFs'][i]
2283 else:
2284 pif_uuid = None
2286 if i < len(network['VIFs']):
2287 vif_uuid = network['VIFs'][i]
2288 else:
2289 vif_uuid = None
2291 pif = pifs.get(pif_uuid, None)
2292 vif = vifs.get(vif_uuid, None)
2294 if vif:
2295 dom_name = server.xenapi.VM.get_name_label(vif['VM'])
2296 vif = "%s.%s" % (dom_name, vif['device'])
2297 else:
2298 vif = ''
2300 if pif:
2301 if int(pif['VLAN']) > -1:
2302 pif = '%s.%s' % (pif['device'], pif['VLAN'])
2303 else:
2304 pif = pif['device']
2305 else:
2306 pif = ''
2308 if i == 0:
2309 r = {'name_label':network['name_label'],
2310 'vif':vif, 'pif':pif}
2311 else:
2312 r = {'name_label':'', 'vif':vif, 'pif':pif}
2314 print format2 % r
2317 commands = {
2318 "shell": xm_shell,
2319 "event-monitor": xm_event_monitor,
2320 # console commands
2321 "console": xm_console,
2322 # xenstat commands
2323 "top": xm_top,
2324 # domain commands
2325 "delete": xm_delete,
2326 "destroy": xm_destroy,
2327 "domid": xm_domid,
2328 "domname": xm_domname,
2329 "dump-core": xm_dump_core,
2330 "reboot": xm_reboot,
2331 "rename": xm_rename,
2332 "restore": xm_restore,
2333 "resume": xm_resume,
2334 "save": xm_save,
2335 "shutdown": xm_shutdown,
2336 "start": xm_start,
2337 "sysrq": xm_sysrq,
2338 "trigger": xm_trigger,
2339 "uptime": xm_uptime,
2340 "suspend": xm_suspend,
2341 "list": xm_list,
2342 # memory commands
2343 "mem-max": xm_mem_max,
2344 "mem-set": xm_mem_set,
2345 # cpu commands
2346 "vcpu-pin": xm_vcpu_pin,
2347 "vcpu-list": xm_vcpu_list,
2348 "vcpu-set": xm_vcpu_set,
2349 # special
2350 "pause": xm_pause,
2351 "unpause": xm_unpause,
2352 # host commands
2353 "debug-keys": xm_debug_keys,
2354 "dmesg": xm_dmesg,
2355 "info": xm_info,
2356 "log": xm_log,
2357 "serve": xm_serve,
2358 # scheduler
2359 "sched-sedf": xm_sched_sedf,
2360 "sched-credit": xm_sched_credit,
2361 # block
2362 "block-attach": xm_block_attach,
2363 "block-detach": xm_block_detach,
2364 "block-list": xm_block_list,
2365 "block-configure": xm_block_configure,
2366 # network (AKA vifs)
2367 "network-attach": xm_network_attach,
2368 "network-detach": xm_network_detach,
2369 "network-list": xm_network_list,
2370 # network (as in XenAPI)
2371 "network-new": xm_network_new,
2372 "network-del": xm_network_del,
2373 "network-show": xm_network_show,
2374 # vnet
2375 "vnet-list": xm_vnet_list,
2376 "vnet-create": xm_vnet_create,
2377 "vnet-delete": xm_vnet_delete,
2378 # vtpm
2379 "vtpm-list": xm_vtpm_list,
2382 ## The commands supported by a separate argument parser in xend.xm.
2383 IMPORTED_COMMANDS = [
2384 'create',
2385 'new',
2386 'migrate',
2387 'labels',
2388 'cfgbootpolicy',
2389 'makepolicy',
2390 'loadpolicy',
2391 'dumppolicy',
2392 'addlabel',
2393 'rmlabel',
2394 'getlabel',
2395 'dry-run',
2396 'resources',
2399 for c in IMPORTED_COMMANDS:
2400 commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
2402 aliases = {
2403 "balloon": "mem-set",
2404 "set-vcpus": "vcpu-set",
2405 "vif-list": "network-list",
2406 "vbd-create": "block-attach",
2407 "vbd-destroy": "block-detach",
2408 "vbd-list": "block-list",
2412 def xm_lookup_cmd(cmd):
2413 if commands.has_key(cmd):
2414 return commands[cmd]
2415 elif aliases.has_key(cmd):
2416 deprecated(cmd,aliases[cmd])
2417 return commands[aliases[cmd]]
2418 elif cmd == 'help':
2419 longHelp()
2420 sys.exit(0)
2421 else:
2422 # simulate getopt's prefix matching behaviour
2423 if len(cmd) > 1:
2424 same_prefix_cmds = [commands[c] for c in commands.keys() \
2425 if c[:len(cmd)] == cmd]
2426 # only execute if there is only 1 match
2427 if len(same_prefix_cmds) == 1:
2428 return same_prefix_cmds[0]
2429 return None
2431 def deprecated(old,new):
2432 print >>sys.stderr, (
2433 "Command %s is deprecated. Please use xm %s instead." % (old, new))
2435 def main(argv=sys.argv):
2436 if len(argv) < 2:
2437 usage()
2439 # intercept --help(-h) and output our own help
2440 for help in ['--help', '-h']:
2441 if help in argv[1:]:
2442 if help == argv[1]:
2443 longHelp()
2444 sys.exit(0)
2445 else:
2446 usage(argv[1])
2448 cmd_name = argv[1]
2449 cmd = xm_lookup_cmd(cmd_name)
2450 if cmd:
2451 # strip off prog name and subcmd
2452 args = argv[2:]
2453 _, rc = _run_cmd(cmd, cmd_name, args)
2454 sys.exit(rc)
2455 else:
2456 err('Subcommand %s not found!' % cmd_name)
2457 usage()
2459 def _run_cmd(cmd, cmd_name, args):
2460 global server
2462 try:
2463 if server is None:
2464 if serverType == SERVER_XEN_API:
2465 server = XenAPI.Session(serverURI)
2466 username, password = parseAuthentication()
2467 server.login_with_password(username, password)
2468 def logout():
2469 try:
2470 server.xenapi.session.logout()
2471 except:
2472 pass
2473 atexit.register(logout)
2474 else:
2475 server = ServerProxy(serverURI)
2477 return True, cmd(args)
2478 except socket.error, ex:
2479 if os.geteuid() != 0:
2480 err("Most commands need root access. Please try again as root.")
2481 else:
2482 err("Unable to connect to xend: %s. Is xend running?" % ex[1])
2483 except KeyboardInterrupt:
2484 print "Interrupted."
2485 return True, ''
2486 except IOError, ex:
2487 if os.geteuid() != 0:
2488 err("Most commands need root access. Please try again as root.")
2489 else:
2490 err("Unable to connect to xend: %s." % ex[1])
2491 except SystemExit, code:
2492 return code == 0, code
2493 except XenAPI.Failure, exn:
2494 for line in [''] + wrap(str(exn), 80) + ['']:
2495 print >>sys.stderr, line
2496 except xmlrpclib.Fault, ex:
2497 if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
2498 err("Domain '%s' does not exist." % ex.faultString)
2499 else:
2500 err(ex.faultString)
2501 _usage(cmd_name)
2502 except xmlrpclib.ProtocolError, ex:
2503 if ex.errcode == -1:
2504 print >>sys.stderr, (
2505 "Xend has probably crashed! Invalid or missing HTTP "
2506 "status code.")
2507 else:
2508 print >>sys.stderr, (
2509 "Xend has probably crashed! ProtocolError(%d, %s)." %
2510 (ex.errcode, ex.errmsg))
2511 except (ValueError, OverflowError):
2512 err("Invalid argument.")
2513 _usage(cmd_name)
2514 except OptionError, e:
2515 err(str(e))
2516 _usage(cmd_name)
2517 print e.usage
2518 except XenAPIUnsupportedException, e:
2519 err(str(e))
2520 except Exception, e:
2521 if serverType != SERVER_XEN_API:
2522 from xen.util import security
2523 if isinstance(e, security.ACMError):
2524 err(str(e))
2525 return False, 1
2526 print "Unexpected error:", sys.exc_info()[0]
2527 print
2528 print "Please report to xen-devel@lists.xensource.com"
2529 raise
2531 return False, 1
2533 if __name__ == "__main__":
2534 main()