ia64/xen-unstable

view tools/python/xen/xm/main.py @ 17179:f76f151a7431

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