debuggers.hg

view tools/python/scripts/xapi.py @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children dec845b4d9c3
line source
1 #!/usr/bin/python
2 #============================================================================
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of version 2.1 of the GNU Lesser General Public
5 # License as published by the Free Software Foundation.
6 #
7 # This library is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 # Lesser General Public License for more details.
11 #
12 # You should have received a copy of the GNU Lesser General Public
13 # License along with this library; if not, write to the Free Software
14 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 #============================================================================
16 # Copyright (C) 2006 XenSource Ltd.
17 #============================================================================
19 import sys
20 import time
21 import re
22 import os
23 sys.path.append('/usr/lib/python')
25 from xen.util.xmlrpclib2 import ServerProxy
26 from optparse import *
27 from pprint import pprint
28 from types import DictType
29 from getpass import getpass
31 # Get default values from the environment
32 SERVER_URI = os.environ.get('XAPI_SERVER_URI', 'http://localhost:9363/')
33 SERVER_USER = os.environ.get('XAPI_SERVER_USER', '')
34 SERVER_PASS = os.environ.get('XAPI_SERVER_PASS', '')
36 MB = 1024 * 1024
38 HOST_INFO_FORMAT = '%-20s: %-50s'
39 VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
40 ' %(power_state)-10s %(uuid)-36s'
41 SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
42 '%(type)-10s'
43 VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
44 VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
45 TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
46 VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
47 CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(location)-32s'
49 COMMANDS = {
50 'host-info': ('', 'Get Xen Host Info'),
51 'host-set-name': ('', 'Set host name'),
52 'pif-list': ('', 'List all PIFs'),
53 'sr-list': ('', 'List all SRs'),
54 'vbd-list': ('', 'List all VBDs'),
55 'vbd-create': ('<domname> <pycfg> [opts]',
56 'Create VBD attached to domname'),
57 'vdi-create': ('<pycfg> [opts]', 'Create a VDI'),
58 'vdi-list' : ('', 'List all VDI'),
59 'vdi-rename': ('<vdi_uuid> <new_name>', 'Rename VDI'),
60 'vdi-destroy': ('<vdi_uuid>', 'Delete VDI'),
61 'vif-create': ('<domname> <pycfg>', 'Create VIF attached to domname'),
62 'vtpm-create' : ('<domname> <pycfg>', 'Create VTPM attached to domname'),
64 'vm-create': ('<pycfg>', 'Create VM with python config'),
65 'vm-destroy': ('<domname>', 'Delete VM'),
67 'vm-list': ('[--long]', 'List all domains.'),
68 'vm-name': ('<uuid>', 'Name of UUID.'),
69 'vm-shutdown': ('<name> [opts]', 'Shutdown VM with name'),
70 'vm-start': ('<name>', 'Start VM with name'),
71 'vm-uuid': ('<name>', 'UUID of a domain by name.'),
72 'async-vm-start': ('<name>', 'Start VM asynchronously'),
73 }
75 OPTIONS = {
76 'sr-list': [(('-l', '--long'),
77 {'action':'store_true',
78 'help':'List all properties of SR'})
79 ],
81 'vdi-list': [(('-l', '--long'),
82 {'action':'store_true',
83 'help':'List all properties of VDI'})
84 ],
85 'vif-list': [(('-l', '--long'),
86 {'action':'store_true',
87 'help':'List all properties of VIF'})
88 ],
89 'vm-list': [(('-l', '--long'),
90 {'action':'store_true',
91 'help':'List all properties of VMs'})
92 ],
93 'vm-shutdown': [(('-f', '--force'), {'help': 'Shutdown Forcefully',
94 'action': 'store_true'})],
96 'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
97 (('--name-description',), {'help': 'Description for VDI'}),
98 (('--virtual-size',), {'type': 'int',
99 'default': 0,
100 'help': 'Size of VDI in bytes'}),
101 (('--type',), {'choices': ['system', 'user', 'ephemeral'],
102 'default': 'system',
103 'help': 'VDI type'}),
104 (('--sharable',), {'action': 'store_true',
105 'help': 'VDI sharable'}),
106 (('--read-only',), {'action': 'store_true',
107 'help': 'Read only'}),
108 (('--sr',), {})],
110 'vbd-create': [(('--VDI',), {'help': 'UUID of VDI to attach to.'}),
111 (('--mode',), {'choices': ['RO', 'RW'],
112 'help': 'device mount mode'}),
113 (('--driver',), {'choices':['paravirtualised', 'ioemu'],
114 'help': 'Driver for VBD'}),
115 (('--device',), {'help': 'Device name on guest domain'})]
117 }
119 class OptionError(Exception):
120 pass
122 class XenAPIError(Exception):
123 pass
125 #
126 # Extra utility functions
127 #
129 class IterableValues(Values):
130 """Better interface to the list of values from optparse."""
132 def __iter__(self):
133 for opt, val in self.__dict__.items():
134 if opt[0] == '_' or callable(val):
135 continue
136 yield opt, val
139 def parse_args(cmd_name, args, set_defaults = False):
140 argstring, desc = COMMANDS[cmd_name]
141 parser = OptionParser(usage = 'xapi %s %s' % (cmd_name, argstring),
142 description = desc)
143 if cmd_name in OPTIONS:
144 for optargs, optkwds in OPTIONS[cmd_name]:
145 parser.add_option(*optargs, **optkwds)
147 if set_defaults:
148 default_values = parser.get_default_values()
149 defaults = IterableValues(default_values.__dict__)
150 else:
151 defaults = IterableValues()
152 (opts, extraargs) = parser.parse_args(args = list(args),
153 values = defaults)
154 return opts, extraargs
156 def execute(server, fn, args, async = False):
157 if async:
158 func = eval('server.Async.%s' % fn)
159 else:
160 func = eval('server.%s' % fn)
162 result = func(*args)
163 if type(result) != DictType:
164 raise TypeError("Function returned object of type: %s" %
165 str(type(result)))
166 if 'Value' not in result:
167 raise XenAPIError(*result['ErrorDescription'])
168 return result['Value']
170 _initialised = False
171 _server = None
172 _session = None
173 def connect(*args):
174 global _server, _session, _initialised
176 if not _initialised:
177 # try without password or default credentials
178 try:
179 _server = ServerProxy(SERVER_URI)
180 _session = execute(_server.session, 'login_with_password',
181 (SERVER_USER, SERVER_PASS))
182 except:
183 login = raw_input("Login: ")
184 password = getpass()
185 creds = (login, password)
186 _server = ServerProxy(SERVER_URI)
187 _session = execute(_server.session, 'login_with_password',
188 creds)
190 _initialised = True
191 return (_server, _session)
193 def _stringify(adict):
194 return dict([(k, str(v)) for k, v in adict.items()])
196 def _read_python_cfg(filename):
197 cfg = {}
198 execfile(filename, {}, cfg)
199 return cfg
201 def resolve_vm(server, session, vm_name):
202 vm_uuid = execute(server, 'VM.get_by_name_label', (session, vm_name))
203 if not vm_uuid:
204 return None
205 else:
206 return vm_uuid[0]
208 def resolve_vdi(server, session, vdi_name):
209 vdi_uuid = execute(server, 'VDI.get_by_name_label', (session, vdi_name))
210 if not vdi_uuid:
211 return None
212 else:
213 return vdi_uuid[0]
215 #
216 # Actual commands
217 #
219 def xapi_host_info(args, async = False):
220 server, session = connect()
221 hosts = execute(server, 'host.get_all', (session,))
222 for host in hosts: # there is only one, but ..
223 hostinfo = execute(server, 'host.get_record', (session, host))
224 print HOST_INFO_FORMAT % ('Name', hostinfo['name_label'])
225 print HOST_INFO_FORMAT % ('Version', hostinfo['software_version'])
226 print HOST_INFO_FORMAT % ('CPUs', len(hostinfo['host_CPUs']))
227 print HOST_INFO_FORMAT % ('VMs', len(hostinfo['resident_VMs']))
228 print HOST_INFO_FORMAT % ('UUID', host)
230 for host_cpu_uuid in hostinfo['host_CPUs']:
231 host_cpu = execute(server, 'host_cpu.get_record',
232 (session, host_cpu_uuid))
233 print 'CPU %s Util: %.2f' % (host_cpu['number'],
234 float(host_cpu['utilisation']))
236 def xapi_host_set_name(args, async = False):
237 if len(args) < 1:
238 raise OptionError("No hostname specified")
240 server, session = connect()
241 hosts = execute(server, 'host.get_all', (session,))
242 if len(hosts) > 0:
243 execute(server, 'host.set_name_label', (session, hosts[0], args[0]))
244 print 'Hostname: %s' % execute(server, 'host.get_name_label',
245 (session, hosts[0]))
247 def xapi_vm_uuid(args, async = False):
248 if len(args) < 1:
249 raise OptionError("No domain name specified")
251 server, session = connect()
252 vm_uuid = resolve_vm(server, session, args[0])
253 print vm_uuid
255 def xapi_vm_name(args, async = False):
256 if len(args) < 1:
257 raise OptionError("No UUID specified")
259 server, session = connect()
260 vm_name = execute(server, 'VM.get_name_label', (session, args[0]))
261 print vm_name
263 def xapi_vm_list(args, async = False):
264 opts, args = parse_args('vm-list', args, set_defaults = True)
265 is_long = opts and opts.long
267 list_only = args
269 server, session = connect()
270 vm_uuids = execute(server, 'VM.get_all', (session,))
271 if not is_long:
272 print VM_LIST_FORMAT % {'name_label':'Name',
273 'memory_actual':'Mem',
274 'VCPUs_number': 'VCPUs',
275 'power_state': 'State',
276 'uuid': 'UUID'}
278 for uuid in vm_uuids:
279 vm_info = execute(server, 'VM.get_record', (session, uuid))
281 # skip domain if we don't want
282 if list_only and vm_info['name_label'] not in list_only:
283 continue
285 if is_long:
286 vbds = vm_info['VBDs']
287 vifs = vm_info['VIFs']
288 vtpms = vm_info['VTPMs']
289 vif_infos = []
290 vbd_infos = []
291 vtpm_infos = []
292 for vbd in vbds:
293 vbd_info = execute(server, 'VBD.get_record', (session, vbd))
294 vbd_infos.append(vbd_info)
295 for vif in vifs:
296 vif_info = execute(server, 'VIF.get_record', (session, vif))
297 vif_infos.append(vif_info)
298 for vtpm in vtpms:
299 vtpm_info = execute(server, 'VTPM.get_record', (session, vtpm))
300 vtpm_infos.append(vtpm_info)
301 vm_info['VBDs'] = vbd_infos
302 vm_info['VIFs'] = vif_infos
303 vm_info['VTPMs'] = vtpm_infos
304 pprint(vm_info)
305 else:
306 print VM_LIST_FORMAT % _stringify(vm_info)
308 def xapi_vm_create(args, async = False):
309 if len(args) < 1:
310 raise OptionError("Configuration file not specified")
312 filename = args[0]
313 cfg = _read_python_cfg(filename)
315 print 'Creating VM from %s ..' % filename
316 server, session = connect()
317 uuid = execute(server, 'VM.create', (session, cfg), async = async)
318 print 'Done. (%s)' % uuid
319 print uuid
321 def xapi_vm_destroy(args, async = False):
322 if len(args) < 1:
323 raise OptionError("No domain name specified.")
325 server, session = connect()
326 vm_uuid = resolve_vm(server, session, args[0])
327 print 'Destroying VM %s (%s)' % (args[0], vm_uuid)
328 success = execute(server, 'VM.destroy', (session, vm_uuid), async = async)
329 print 'Done.'
332 def xapi_vm_start(args, async = False):
333 if len(args) < 1:
334 raise OptionError("No Domain name specified.")
336 server, session = connect()
337 vm_uuid = resolve_vm(server, session, args[0])
338 print 'Starting VM %s (%s)' % (args[0], vm_uuid)
339 success = execute(server, 'VM.start', (session, vm_uuid, False), async = async)
340 if async:
341 print 'Task started: %s' % success
342 else:
343 print 'Done.'
345 def xapi_vm_suspend(args, async = False):
346 if len(args) < 1:
347 raise OptionError("No Domain name specified.")
349 server, session = connect()
350 vm_uuid = resolve_vm(server, session, args[0])
351 print 'Suspending VM %s (%s)' % (args[0], vm_uuid)
352 success = execute(server, 'VM.suspend', (session, vm_uuid), async = async)
353 if async:
354 print 'Task started: %s' % success
355 else:
356 print 'Done.'
359 def xapi_vm_resume(args, async = False):
360 if len(args) < 1:
361 raise OptionError("No Domain name specified.")
363 server, session = connect()
364 vm_uuid = resolve_vm(server, session, args[0])
365 print 'Resuming VM %s (%s)' % (args[0], vm_uuid)
366 success = execute(server, 'VM.resume', (session, vm_uuid, False), async = async)
367 if async:
368 print 'Task started: %s' % success
369 else:
370 print 'Done.'
372 def xapi_vm_pause(args, async = False):
373 if len(args) < 1:
374 raise OptionError("No Domain name specified.")
376 server, session = connect()
377 vm_uuid = resolve_vm(server, session, args[0])
378 print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
379 success = execute(server, 'VM.pause', (session, vm_uuid), async = async)
380 if async:
381 print 'Task started: %s' % success
382 else:
383 print 'Done.'
385 def xapi_vm_unpause(args, async = False):
386 if len(args) < 1:
387 raise OptionError("No Domain name specified.")
389 server, session = connect()
390 vm_uuid = resolve_vm(server, session, args[0])
391 print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
392 success = execute(server, 'VM.unpause', (session, vm_uuid), async = async)
393 if async:
394 print 'Task started: %s' % success
395 else:
396 print 'Done.'
398 def xapi_task_list(args, async = False):
399 server, session = connect()
400 all_tasks = execute(server, 'task.get_all', (session,))
402 print TASK_LIST_FORMAT % {'name_label': 'Task Name',
403 'uuid': 'UUID',
404 'status': 'Status',
405 'progress': '%'}
407 for task_uuid in all_tasks:
408 task = execute(server, 'task.get_record', (session, task_uuid))
409 print TASK_LIST_FORMAT % task
411 def xapi_task_clear(args, async = False):
412 server, session = connect()
413 all_tasks = execute(server, 'task.get_all', (session,))
414 for task_uuid in all_tasks:
415 success = execute(server, 'task.destroy', (session, task_uuid))
416 print 'Destroyed Task %s' % task_uuid
418 def xapi_vm_shutdown(args, async = False):
419 opts, args = parse_args("vm-shutdown", args, set_defaults = True)
421 if len(args) < 1:
422 raise OptionError("No Domain name specified.")
424 server, session = connect()
425 vm_uuid = resolve_vm(server, session, args[0])
426 if opts.force:
427 print 'Forcefully shutting down VM %s (%s)' % (args[0], vm_uuid)
428 success = execute(server, 'VM.hard_shutdown', (session, vm_uuid), async = async)
429 else:
430 print 'Shutting down VM %s (%s)' % (args[0], vm_uuid)
431 success = execute(server, 'VM.clean_shutdown', (session, vm_uuid), async = async)
433 if async:
434 print 'Task started: %s' % success
435 else:
436 print 'Done.'
438 def xapi_vbd_create(args, async = False):
439 opts, args = parse_args('vbd-create', args)
441 if len(args) < 2:
442 raise OptionError("Configuration file and domain not specified")
444 domname = args[0]
446 if len(args) > 1:
447 filename = args[1]
448 cfg = _read_python_cfg(filename)
449 else:
450 cfg = {}
452 for opt, val in opts:
453 cfg[opt] = val
455 print 'Creating VBD ...',
456 server, session = connect()
457 vm_uuid = resolve_vm(server, session, domname)
458 cfg['VM'] = vm_uuid
459 vbd_uuid = execute(server, 'VBD.create', (session, cfg), async = async)
460 if async:
461 print 'Task started: %s' % vbd_uuid
462 else:
463 print 'Done. (%s)' % vbd_uuid
465 def xapi_vif_create(args, async = False):
466 if len(args) < 2:
467 raise OptionError("Configuration file not specified")
469 domname = args[0]
470 filename = args[1]
471 cfg = _read_python_cfg(filename)
473 print 'Creating VIF from %s ..' % filename
474 server, session = connect()
475 vm_uuid = resolve_vm(server, session, domname)
476 cfg['VM'] = vm_uuid
477 vif_uuid = execute(server, 'VIF.create', (session, cfg), async = async)
478 if async:
479 print 'Task started: %s' % vif_uuid
480 else:
481 print 'Done. (%s)' % vif_uuid
483 def xapi_vbd_list(args, async = False):
484 server, session = connect()
485 domname = args[0]
487 dom_uuid = resolve_vm(server, session, domname)
488 vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
490 print VBD_LIST_FORMAT % {'device': 'Device',
491 'uuid' : 'UUID',
492 'VDI': 'VDI'}
494 for vbd in vbds:
495 vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
496 print VBD_LIST_FORMAT % vbd_struct
499 def xapi_vbd_stats(args, async = False):
500 server, session = connect()
501 domname = args[0]
502 dom_uuid = resolve_vm(server, session, domname)
504 vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
505 for vbd_uuid in vbds:
506 print execute(server, 'VBD.get_io_read_kbs', (session, vbd_uuid))
508 def xapi_vif_list(args, async = False):
509 server, session = connect()
510 opts, args = parse_args('vdi-list', args, set_defaults = True)
511 is_long = opts and opts.long
513 domname = args[0]
515 dom_uuid = resolve_vm(server, session, domname)
516 vifs = execute(server, 'VM.get_VIFs', (session, dom_uuid))
518 if not is_long:
519 print VIF_LIST_FORMAT % {'name': 'Name',
520 'device': 'Device',
521 'uuid' : 'UUID',
522 'MAC': 'MAC'}
524 for vif in vifs:
525 vif_struct = execute(server, 'VIF.get_record', (session, vif))
526 print VIF_LIST_FORMAT % vif_struct
527 else:
528 for vif in vifs:
529 vif_struct = execute(server, 'VIF.get_record', (session, vif))
530 pprint(vif_struct)
532 def xapi_console_list(args, async = False):
533 server, session = connect()
534 opts, args = parse_args('vdi-list', args, set_defaults = True)
535 is_long = opts and opts.long
537 domname = args[0]
539 dom_uuid = resolve_vm(server, session, domname)
540 consoles = execute(server, 'VM.get_consoles', (session, dom_uuid))
542 if not is_long:
543 print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol',
544 'location': 'Location',
545 'uuid': 'UUID'}
547 for console in consoles:
548 console_struct = execute(server, 'console.get_record',
549 (session, console))
550 print CONSOLE_LIST_FORMAT % console_struct
551 else:
552 for console in consoles:
553 console_struct = execute(server, 'console.get_record',
554 (session, console))
555 pprint(console_struct)
558 def xapi_vdi_list(args, async = False):
559 opts, args = parse_args('vdi-list', args, set_defaults = True)
560 is_long = opts and opts.long
562 server, session = connect()
563 vdis = execute(server, 'VDI.get_all', (session,))
565 if not is_long:
566 print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
567 'uuid' : 'UUID',
568 'virtual_size': 'Bytes'}
570 for vdi in vdis:
571 vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
572 print VDI_LIST_FORMAT % vdi_struct
574 else:
575 for vdi in vdis:
576 vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
577 pprint(vdi_struct)
579 def xapi_sr_list(args, async = False):
580 opts, args = parse_args('sr-list', args, set_defaults = True)
581 is_long = opts and opts.long
583 server, session = connect()
584 srs = execute(server, 'SR.get_all', (session,))
585 if not is_long:
586 print SR_LIST_FORMAT % {'name_label': 'SR Label',
587 'uuid' : 'UUID',
588 'physical_size': 'Size (MB)',
589 'type': 'Type'}
591 for sr in srs:
592 sr_struct = execute(server, 'SR.get_record', (session, sr))
593 sr_struct['physical_size'] = int(sr_struct['physical_size'])/MB
594 print SR_LIST_FORMAT % sr_struct
595 else:
596 for sr in srs:
597 sr_struct = execute(server, 'SR.get_record', (session, sr))
598 pprint(sr_struct)
600 def xapi_sr_rename(args, async = False):
601 server, session = connect()
602 sr = execute(server, 'SR.get_by_name_label', (session, args[0]))
603 execute(server, 'SR.set_name_label', (session, sr[0], args[1]))
605 def xapi_vdi_create(args, async = False):
606 opts, args = parse_args('vdi-create', args)
608 if len(args) > 0:
609 cfg = _read_python_cfg(args[0])
610 else:
611 cfg = {}
613 for opt, val in opts:
614 cfg[opt] = val
616 server, session = connect()
617 srs = []
618 if cfg.get('SR'):
619 srs = execute(server, 'SR.get_by_name_label', (session, cfg['SR']))
620 else:
621 srs = execute(server, 'SR.get_all', (session,))
623 sr = srs[0]
624 cfg['SR'] = sr
626 size = cfg['virtual_size']/MB
627 print 'Creating VDI of size: %dMB ..' % size,
628 uuid = execute(server, 'VDI.create', (session, cfg), async = async)
629 if async:
630 print 'Task started: %s' % uuid
631 else:
632 print 'Done. (%s)' % uuid
635 def xapi_vdi_destroy(args, async = False):
636 server, session = connect()
637 if len(args) < 1:
638 raise OptionError('Not enough arguments')
640 vdi_uuid = args[0]
641 print 'Deleting VDI %s' % vdi_uuid
642 result = execute(server, 'VDI.destroy', (session, vdi_uuid), async = async)
643 if async:
644 print 'Task started: %s' % result
645 else:
646 print 'Done.'
648 def xapi_vdi_rename(args, async = False):
649 server, session = connect()
650 if len(args) < 2:
651 raise OptionError('Not enough arguments')
653 vdi_uuid = execute(server, 'VDI.get_by_name_label', session, args[0])
654 vdi_name = args[1]
656 print 'Renaming VDI %s to %s' % (vdi_uuid[0], vdi_name)
657 result = execute(server, 'VDI.set_name_label',
658 (session, vdi_uuid[0], vdi_name), async = async)
659 if async:
660 print 'Task started: %s' % result
661 else:
662 print 'Done.'
666 def xapi_vtpm_create(args, async = False):
667 server, session = connect()
668 domname = args[0]
669 cfg = _read_python_cfg(args[1])
671 vm_uuid = resolve_vm(server, session, domname)
672 cfg['VM'] = vm_uuid
673 print "Creating vTPM with cfg = %s" % cfg
674 vtpm_uuid = execute(server, 'VTPM.create', (session, cfg))
675 print "Done. (%s)" % vtpm_uuid
678 def xapi_pif_list(args, async = False):
679 server, session = connect()
680 pif_uuids = execute(server, 'PIF.get_all', (session,))
681 for pif_uuid in pif_uuids:
682 pif = execute(server, 'PIF.get_record', (session, pif_uuid))
683 print pif
686 def xapi_debug_wait(args, async = False):
687 secs = 10
688 if len(args) > 0:
689 secs = int(args[0])
690 server, session = connect()
691 task_uuid = execute(server, 'debug.wait', (session, secs), async=async)
692 print 'Task UUID: %s' % task_uuid
694 def xapi_vm_stat(args, async = False):
695 domname = args[0]
697 server, session = connect()
698 vm_uuid = resolve_vm(server, session, domname)
699 vif_uuids = execute(server, 'VM.get_VIFs', (session, vm_uuid))
700 vbd_uuids = execute(server, 'VM.get_VBDs', (session, vm_uuid))
701 vcpus_utils = execute(server, 'VM.get_VCPUs_utilisation',
702 (session, vm_uuid))
704 for vcpu_num in sorted(vcpus_utils.keys()):
705 print 'CPU %s : %5.2f%%' % (vcpu_num, vcpus_utils[vcpu_num] * 100)
707 for vif_uuid in vif_uuids:
708 vif = execute(server, 'VIF.get_record', (session, vif_uuid))
709 print '%(device)s: rx: %(io_read_kbs)10.2f tx: %(io_write_kbs)10.2f' \
710 % vif
711 for vbd_uuid in vbd_uuids:
712 vbd = execute(server, 'VBD.get_record', (session, vbd_uuid))
713 print '%(device)s: rd: %(io_read_kbs)10.2f wr: %(io_write_kbs)10.2f' \
714 % vbd
716 #
717 # Command Line Utils
718 #
719 import cmd
720 import shlex
722 class XenAPICmd(cmd.Cmd):
723 def __init__(self, server, session):
724 cmd.Cmd.__init__(self)
725 self.server = server
726 self.session = session
727 self.prompt = ">>> "
729 def default(self, line):
730 words = shlex.split(line)
731 if len(words) > 0:
732 cmd_name = words[0].replace('-', '_')
733 is_async = 'async' in cmd_name
734 if is_async:
735 cmd_name = re.sub('async_', '', cmd_name)
737 func_name = 'xapi_%s' % cmd_name
738 func = globals().get(func_name)
740 if func:
741 try:
742 args = tuple(words[1:])
743 func(args, async = is_async)
744 return True
745 except SystemExit:
746 return False
747 except OptionError, e:
748 print 'Error:', str(e)
749 return False
750 except Exception, e:
751 import traceback
752 traceback.print_exc()
753 return False
754 print '*** Unknown command: %s' % words[0]
755 return False
757 def do_EOF(self, line):
758 print
759 sys.exit(0)
761 def do_help(self, line):
762 usage(print_usage = False)
764 def emptyline(self):
765 pass
767 def postcmd(self, stop, line):
768 return False
770 def precmd(self, line):
771 words = shlex.split(line)
772 if len(words) > 0:
773 words0 = words[0].replace('-', '_')
774 return ' '.join([words0] + words[1:])
775 else:
776 return line
778 def shell():
779 server, session = connect()
780 x = XenAPICmd(server, session)
781 x.cmdloop('Xen API Prompt. Type "help" for a list of functions')
783 def usage(command = None, print_usage = True):
784 if not command:
785 if print_usage:
786 print 'Usage: xapi <subcommand> [options] [args]'
787 print
788 print 'Subcommands:'
789 print
791 for func in sorted(globals().keys()):
792 if func.startswith('xapi_'):
793 command = func[5:].replace('_', '-')
794 args, description = COMMANDS.get(command, ('', ''))
795 print '%-16s %-40s' % (command, description)
796 print
797 else:
798 parse_args(command, ['-h'])
800 def main(args):
802 # poor man's optparse that doesn't abort on unrecognised opts
804 options = {}
805 remaining = []
807 arg_n = 0
808 while args:
809 arg = args.pop(0)
811 if arg in ('--help', '-h'):
812 options['help'] = True
813 elif arg in ('--server', '-s') and args:
814 options['server'] = args.pop(0)
815 elif arg in ('--user', '-u') and args:
816 options['user'] = args.pop(0)
817 elif arg in ('--password', '-p') and args:
818 options['password'] = args.pop(0)
819 else:
820 remaining.append(arg)
822 # abort here if these conditions are true
824 if options.get('help') and not remaining:
825 usage()
826 sys.exit(1)
828 if options.get('help') and remaining:
829 usage(remaining[0])
830 sys.exit(1)
832 if not remaining:
833 usage()
834 sys.exit(1)
836 if options.get('server'):
837 # it is ugly to use a global, but it is simple
838 global SERVER_URI
839 SERVER_URI = options['server']
841 if options.get('user'):
842 global SERVER_USER
843 SERVER_USER = options['user']
845 if options.get('password'):
846 global SERVER_PASS
847 SERVER_PASS = options['password']
849 subcmd = remaining[0].replace('-', '_')
850 is_async = 'async' in subcmd
851 if is_async:
852 subcmd = re.sub('async_', '', subcmd)
853 subcmd_func_name = 'xapi_' + subcmd
854 subcmd_func = globals().get(subcmd_func_name, None)
856 if subcmd == 'shell':
857 shell()
858 elif not subcmd_func or not callable(subcmd_func):
859 print 'Error: Unable to find subcommand \'%s\'' % subcmd
860 usage()
861 sys.exit(1)
863 try:
864 subcmd_func(remaining[1:], async = is_async)
865 except XenAPIError, e:
866 print 'Error: %s' % str(e.args[0])
867 sys.exit(2)
868 except OptionError, e:
869 print 'Error: %s' % e
871 sys.exit(0)
873 if __name__ == "__main__":
874 import sys
875 main(sys.argv[1:])