debuggers.hg

view tools/python/scripts/xapi.py @ 13625:072ce22bcc91

[XENAPI] Update test scripts to move from VBD.image to creating VDI's
with the uri attribute.

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Wed Jan 24 15:48:58 2007 +0000 (2007-01-24)
parents 9292da5e9a27
children f000f963bbfd
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 sys.path.append('/usr/lib/python')
24 from xen.util.xmlrpclib2 import ServerProxy
25 from optparse import *
26 from pprint import pprint
27 from types import DictType
28 from getpass import getpass
31 MB = 1024 * 1024
33 HOST_INFO_FORMAT = '%-20s: %-50s'
34 VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
35 ' %(power_state)-10s %(uuid)-36s'
36 SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
37 '%(type)-10s'
38 VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\
39 '%(sector_size)-8s'
40 VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
41 TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
42 VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
44 COMMANDS = {
45 'host-info': ('', 'Get Xen Host Info'),
46 'host-set-name': ('', 'Set host name'),
47 'pif-list': ('', 'List all PIFs'),
48 'sr-list': ('', 'List all SRs'),
49 'vbd-list': ('', 'List all VBDs'),
50 'vbd-create': ('<domname> <pycfg> [opts]',
51 'Create VBD attached to domname'),
52 'vdi-create': ('<pycfg> [opts]', 'Create a VDI'),
53 'vdi-list' : ('', 'List all VDI'),
54 'vdi-rename': ('<vdi_uuid> <new_name>', 'Rename VDI'),
55 'vdi-destroy': ('<vdi_uuid>', 'Delete VDI'),
56 'vif-create': ('<domname> <pycfg>', 'Create VIF attached to domname'),
57 'vtpm-create' : ('<domname> <pycfg>', 'Create VTPM attached to domname'),
59 'vm-create': ('<pycfg>', 'Create VM with python config'),
60 'vm-destroy': ('<domname>', 'Delete VM'),
62 'vm-list': ('[--long]', 'List all domains.'),
63 'vm-name': ('<uuid>', 'Name of UUID.'),
64 'vm-shutdown': ('<name> [opts]', 'Shutdown VM with name'),
65 'vm-start': ('<name>', 'Start VM with name'),
66 'vm-uuid': ('<name>', 'UUID of a domain by name.'),
67 'async-vm-start': ('<name>', 'Start VM asynchronously'),
68 }
70 OPTIONS = {
71 'sr-list': [(('-l', '--long'),
72 {'action':'store_true',
73 'help':'List all properties of SR'})
74 ],
76 'vdi-list': [(('-l', '--long'),
77 {'action':'store_true',
78 'help':'List all properties of VDI'})
79 ],
80 'vm-list': [(('-l', '--long'),
81 {'action':'store_true',
82 'help':'List all properties of VMs'})
83 ],
84 'vm-shutdown': [(('-f', '--force'), {'help': 'Shutdown Forcefully',
85 'action': 'store_true'})],
87 'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
88 (('--name-description',), {'help': 'Description for VDI'}),
89 (('--sector-size',), {'type': 'int',
90 'help': 'Sector size',
91 'default': 0}),
92 (('--virtual-size',), {'type': 'int',
93 'default': 0,
94 'help': 'Size of VDI in sectors'}),
95 (('--type',), {'choices': ['system', 'user', 'ephemeral'],
96 'default': 'system',
97 'help': 'VDI type'}),
98 (('--sharable',), {'action': 'store_true',
99 'help': 'VDI sharable'}),
100 (('--read-only',), {'action': 'store_true',
101 'help': 'Read only'}),
102 (('--sr',), {})],
104 'vbd-create': [(('--VDI',), {'help': 'UUID of VDI to attach to.'}),
105 (('--mode',), {'choices': ['RO', 'RW'],
106 'help': 'device mount mode'}),
107 (('--driver',), {'choices':['paravirtualised', 'ioemu'],
108 'help': 'Driver for VBD'}),
109 (('--device',), {'help': 'Device name on guest domain'})]
111 }
113 class OptionError(Exception):
114 pass
116 class XenAPIError(Exception):
117 pass
119 #
120 # Extra utility functions
121 #
123 class IterableValues(Values):
124 """Better interface to the list of values from optparse."""
126 def __iter__(self):
127 for opt, val in self.__dict__.items():
128 if opt[0] == '_' or callable(val):
129 continue
130 yield opt, val
133 def parse_args(cmd_name, args, set_defaults = False):
134 argstring, desc = COMMANDS[cmd_name]
135 parser = OptionParser(usage = 'xapi %s %s' % (cmd_name, argstring),
136 description = desc)
137 if cmd_name in OPTIONS:
138 for optargs, optkwds in OPTIONS[cmd_name]:
139 parser.add_option(*optargs, **optkwds)
141 if set_defaults:
142 default_values = parser.get_default_values()
143 defaults = IterableValues(default_values.__dict__)
144 else:
145 defaults = IterableValues()
146 (opts, extraargs) = parser.parse_args(args = list(args),
147 values = defaults)
148 return opts, extraargs
150 def execute(server, fn, args, async = False):
151 if async:
152 func = eval('server.Async.%s' % fn)
153 else:
154 func = eval('server.%s' % fn)
156 result = func(*args)
157 if type(result) != DictType:
158 raise TypeError("Function returned object of type: %s" %
159 str(type(result)))
160 if 'Value' not in result:
161 raise XenAPIError(*result['ErrorDescription'])
162 return result['Value']
164 _initialised = False
165 _server = None
166 _session = None
167 def connect(*args):
168 global _server, _session, _initialised
169 if not _initialised:
170 _server = ServerProxy('http://localhost:9363/')
171 login = raw_input("Login: ")
172 password = getpass()
173 creds = (login, password)
174 _session = execute(_server.session, 'login_with_password', creds)
175 _initialised = True
176 return (_server, _session)
178 def _stringify(adict):
179 return dict([(k, str(v)) for k, v in adict.items()])
181 def _read_python_cfg(filename):
182 cfg = {}
183 execfile(filename, {}, cfg)
184 return cfg
186 def resolve_vm(server, session, vm_name):
187 vm_uuid = execute(server, 'VM.get_by_name_label', (session, vm_name))
188 if not vm_uuid:
189 return None
190 else:
191 return vm_uuid[0]
193 def resolve_vdi(server, session, vdi_name):
194 vdi_uuid = execute(server, 'VDI.get_by_name_label', (session, vdi_name))
195 if not vdi_uuid:
196 return None
197 else:
198 return vdi_uuid[0]
200 #
201 # Actual commands
202 #
204 def xapi_host_info(args, async = False):
205 server, session = connect()
206 hosts = execute(server, 'host.get_all', (session,))
207 for host in hosts: # there is only one, but ..
208 hostinfo = execute(server, 'host.get_record', (session, host))
209 print HOST_INFO_FORMAT % ('Name', hostinfo['name_label'])
210 print HOST_INFO_FORMAT % ('Version', hostinfo['software_version'])
211 print HOST_INFO_FORMAT % ('CPUs', len(hostinfo['host_CPUs']))
212 print HOST_INFO_FORMAT % ('VMs', len(hostinfo['resident_VMs']))
213 print HOST_INFO_FORMAT % ('UUID', host)
215 for host_cpu_uuid in hostinfo['host_CPUs']:
216 host_cpu = execute(server, 'host_cpu.get_record',
217 (session, host_cpu_uuid))
218 print 'CPU %s Util: %.2f' % (host_cpu['number'],
219 float(host_cpu['utilisation']))
221 def xapi_host_set_name(args, async = False):
222 if len(args) < 1:
223 raise OptionError("No hostname specified")
225 server, session = connect()
226 hosts = execute(server, 'host.get_all', (session,))
227 if len(hosts) > 0:
228 execute(server, 'host.set_name_label', (session, hosts[0], args[0]))
229 print 'Hostname: %s' % execute(server, 'host.get_name_label',
230 (session, hosts[0]))
232 def xapi_vm_uuid(args, async = False):
233 if len(args) < 1:
234 raise OptionError("No domain name specified")
236 server, session = connect()
237 vm_uuid = resolve_vm(server, session, args[0])
238 print vm_uuid
240 def xapi_vm_name(args, async = False):
241 if len(args) < 1:
242 raise OptionError("No UUID specified")
244 server, session = connect()
245 vm_name = execute(server, 'VM.get_name_label', (session, args[0]))
246 print vm_name
248 def xapi_vm_list(args, async = False):
249 opts, args = parse_args('vm-list', args, set_defaults = True)
250 is_long = opts and opts.long
252 server, session = connect()
253 vm_uuids = execute(server, 'VM.get_all', (session,))
254 if not is_long:
255 print VM_LIST_FORMAT % {'name_label':'Name',
256 'memory_actual':'Mem',
257 'VCPUs_number': 'VCPUs',
258 'power_state': 'State',
259 'uuid': 'UUID'}
261 for uuid in vm_uuids:
262 vm_info = execute(server, 'VM.get_record', (session, uuid))
263 if is_long:
264 vbds = vm_info['VBDs']
265 vifs = vm_info['VIFs']
266 vtpms = vm_info['VTPMs']
267 vif_infos = []
268 vbd_infos = []
269 vtpm_infos = []
270 for vbd in vbds:
271 vbd_info = execute(server, 'VBD.get_record', (session, vbd))
272 vbd_infos.append(vbd_info)
273 for vif in vifs:
274 vif_info = execute(server, 'VIF.get_record', (session, vif))
275 vif_infos.append(vif_info)
276 for vtpm in vtpms:
277 vtpm_info = execute(server, 'VTPM.get_record', (session, vtpm))
278 vtpm_infos.append(vtpm_info)
279 vm_info['VBDs'] = vbd_infos
280 vm_info['VIFs'] = vif_infos
281 vm_info['VTPMs'] = vtpm_infos
282 pprint(vm_info)
283 else:
284 print VM_LIST_FORMAT % _stringify(vm_info)
286 def xapi_vm_create(args, async = False):
287 if len(args) < 1:
288 raise OptionError("Configuration file not specified")
290 filename = args[0]
291 cfg = _read_python_cfg(filename)
293 print 'Creating VM from %s ..' % filename
294 server, session = connect()
295 uuid = execute(server, 'VM.create', (session, cfg), async = async)
296 print 'Done. (%s)' % uuid
297 print uuid
299 def xapi_vm_destroy(args, async = False):
300 if len(args) < 1:
301 raise OptionError("No domain name specified.")
303 server, session = connect()
304 vm_uuid = resolve_vm(server, session, args[0])
305 print 'Destroying VM %s (%s)' % (args[0], vm_uuid)
306 success = execute(server, 'VM.destroy', (session, vm_uuid), async = async)
307 print 'Done.'
310 def xapi_vm_start(args, async = False):
311 if len(args) < 1:
312 raise OptionError("No Domain name specified.")
314 server, session = connect()
315 vm_uuid = resolve_vm(server, session, args[0])
316 print 'Starting VM %s (%s)' % (args[0], vm_uuid)
317 success = execute(server, 'VM.start', (session, vm_uuid, False), async = async)
318 if async:
319 print 'Task started: %s' % success
320 else:
321 print 'Done.'
323 def xapi_vm_suspend(args, async = False):
324 if len(args) < 1:
325 raise OptionError("No Domain name specified.")
327 server, session = connect()
328 vm_uuid = resolve_vm(server, session, args[0])
329 print 'Suspending VM %s (%s)' % (args[0], vm_uuid)
330 success = execute(server, 'VM.suspend', (session, vm_uuid), async = async)
331 if async:
332 print 'Task started: %s' % success
333 else:
334 print 'Done.'
337 def xapi_vm_resume(args, async = False):
338 if len(args) < 1:
339 raise OptionError("No Domain name specified.")
341 server, session = connect()
342 vm_uuid = resolve_vm(server, session, args[0])
343 print 'Resuming VM %s (%s)' % (args[0], vm_uuid)
344 success = execute(server, 'VM.resume', (session, vm_uuid, False), async = async)
345 if async:
346 print 'Task started: %s' % success
347 else:
348 print 'Done.'
350 def xapi_vm_pause(args, async = False):
351 if len(args) < 1:
352 raise OptionError("No Domain name specified.")
354 server, session = connect()
355 vm_uuid = resolve_vm(server, session, args[0])
356 print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
357 success = execute(server, 'VM.pause', (session, vm_uuid), async = async)
358 if async:
359 print 'Task started: %s' % success
360 else:
361 print 'Done.'
363 def xapi_vm_unpause(args, async = False):
364 if len(args) < 1:
365 raise OptionError("No Domain name specified.")
367 server, session = connect()
368 vm_uuid = resolve_vm(server, session, args[0])
369 print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
370 success = execute(server, 'VM.unpause', (session, vm_uuid), async = async)
371 if async:
372 print 'Task started: %s' % success
373 else:
374 print 'Done.'
376 def xapi_task_list(args, async = False):
377 server, session = connect()
378 all_tasks = execute(server, 'task.get_all', (session,))
380 print TASK_LIST_FORMAT % {'name_label': 'Task Name',
381 'uuid': 'UUID',
382 'status': 'Status',
383 'progress': '%'}
385 for task_uuid in all_tasks:
386 task = execute(server, 'task.get_record', (session, task_uuid))
387 print TASK_LIST_FORMAT % task
389 def xapi_task_clear(args, async = False):
390 server, session = connect()
391 all_tasks = execute(server, 'task.get_all', (session,))
392 for task_uuid in all_tasks:
393 success = execute(server, 'task.destroy', (session, task_uuid))
394 print 'Destroyed Task %s' % task_uuid
396 def xapi_vm_shutdown(args, async = False):
397 opts, args = parse_args("vm-shutdown", args, set_defaults = True)
399 if len(args) < 1:
400 raise OptionError("No Domain name specified.")
402 server, session = connect()
403 vm_uuid = resolve_vm(server, session, args[0])
404 if opts.force:
405 print 'Forcefully shutting down VM %s (%s)' % (args[0], vm_uuid)
406 success = execute(server, 'VM.hard_shutdown', (session, vm_uuid), async = async)
407 else:
408 print 'Shutting down VM %s (%s)' % (args[0], vm_uuid)
409 success = execute(server, 'VM.clean_shutdown', (session, vm_uuid), async = async)
411 if async:
412 print 'Task started: %s' % success
413 else:
414 print 'Done.'
416 def xapi_vbd_create(args, async = False):
417 opts, args = parse_args('vbd-create', args)
419 if len(args) < 2:
420 raise OptionError("Configuration file and domain not specified")
422 domname = args[0]
424 if len(args) > 1:
425 filename = args[1]
426 cfg = _read_python_cfg(filename)
427 else:
428 cfg = {}
430 for opt, val in opts:
431 cfg[opt] = val
433 print 'Creating VBD ...',
434 server, session = connect()
435 vm_uuid = resolve_vm(server, session, domname)
436 cfg['VM'] = vm_uuid
437 vbd_uuid = execute(server, 'VBD.create', (session, cfg), async = async)
438 if async:
439 print 'Task started: %s' % vbd_uuid
440 else:
441 print 'Done. (%s)' % vbd_uuid
443 def xapi_vif_create(args, async = False):
444 if len(args) < 2:
445 raise OptionError("Configuration file not specified")
447 domname = args[0]
448 filename = args[1]
449 cfg = _read_python_cfg(filename)
451 print 'Creating VIF from %s ..' % filename
452 server, session = connect()
453 vm_uuid = resolve_vm(server, session, domname)
454 cfg['VM'] = vm_uuid
455 vif_uuid = execute(server, 'VIF.create', (session, cfg), async = async)
456 if async:
457 print 'Task started: %s' % vif_uuid
458 else:
459 print 'Done. (%s)' % vif_uuid
461 def xapi_vbd_list(args, async = False):
462 server, session = connect()
463 domname = args[0]
465 dom_uuid = resolve_vm(server, session, domname)
466 vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
468 print VBD_LIST_FORMAT % {'device': 'Device',
469 'uuid' : 'UUID',
470 'VDI': 'VDI'}
472 for vbd in vbds:
473 vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
474 print VBD_LIST_FORMAT % vbd_struct
476 def xapi_vif_list(args, async = False):
477 server, session = connect()
478 domname = args[0]
480 dom_uuid = resolve_vm(server, session, domname)
481 vifs = execute(server, 'VM.get_VIFs', (session, dom_uuid))
483 print VIF_LIST_FORMAT % {'name': 'Name',
484 'device': 'Device',
485 'uuid' : 'UUID',
486 'MAC': 'MAC'}
488 for vif in vifs:
489 vif_struct = execute(server, 'VIF.get_record', (session, vif))
490 print VIF_LIST_FORMAT % vif_struct
492 def xapi_vdi_list(args, async = False):
493 opts, args = parse_args('vdi-list', args, set_defaults = True)
494 is_long = opts and opts.long
496 server, session = connect()
497 vdis = execute(server, 'VDI.get_all', (session,))
499 if not is_long:
500 print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
501 'uuid' : 'UUID',
502 'virtual_size': 'Sectors',
503 'sector_size': 'Sector Size'}
505 for vdi in vdis:
506 vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
507 print VDI_LIST_FORMAT % vdi_struct
509 else:
510 for vdi in vdis:
511 vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
512 pprint(vdi_struct)
514 def xapi_sr_list(args, async = False):
515 opts, args = parse_args('sr-list', args, set_defaults = True)
516 is_long = opts and opts.long
518 server, session = connect()
519 srs = execute(server, 'SR.get_all', (session,))
520 if not is_long:
521 print SR_LIST_FORMAT % {'name_label': 'SR Label',
522 'uuid' : 'UUID',
523 'physical_size': 'Size (MB)',
524 'type': 'Type'}
526 for sr in srs:
527 sr_struct = execute(server, 'SR.get_record', (session, sr))
528 sr_struct['physical_size'] = int(sr_struct['physical_size'])/MB
529 print SR_LIST_FORMAT % sr_struct
530 else:
531 for sr in srs:
532 sr_struct = execute(server, 'SR.get_record', (session, sr))
533 pprint(sr_struct)
535 def xapi_sr_rename(args, async = False):
536 server, session = connect()
537 sr = execute(server, 'SR.get_by_name_label', (session, args[0]))
538 execute(server, 'SR.set_name_label', (session, sr[0], args[1]))
540 def xapi_vdi_create(args, async = False):
541 opts, args = parse_args('vdi-create', args)
543 if len(args) > 0:
544 cfg = _read_python_cfg(args[0])
545 else:
546 cfg = {}
548 for opt, val in opts:
549 cfg[opt] = val
551 server, session = connect()
552 srs = []
553 if cfg.get('SR'):
554 srs = execute(server, 'SR.get_by_name_label', (session, cfg['SR']))
555 else:
556 srs = execute(server, 'SR.get_all', (session,))
558 sr = srs[0]
559 cfg['SR'] = sr
561 size = (cfg['virtual_size'] * cfg['sector_size'])/MB
562 print 'Creating VDI of size: %dMB ..' % size,
563 uuid = execute(server, 'VDI.create', (session, cfg), async = async)
564 if async:
565 print 'Task started: %s' % uuid
566 else:
567 print 'Done. (%s)' % uuid
570 def xapi_vdi_destroy(args, async = False):
571 server, session = connect()
572 if len(args) < 1:
573 raise OptionError('Not enough arguments')
575 vdi_uuid = args[0]
576 print 'Deleting VDI %s' % vdi_uuid
577 result = execute(server, 'VDI.destroy', (session, vdi_uuid), async = async)
578 if async:
579 print 'Task started: %s' % result
580 else:
581 print 'Done.'
583 def xapi_vdi_rename(args, async = False):
584 server, session = connect()
585 if len(args) < 2:
586 raise OptionError('Not enough arguments')
588 vdi_uuid = execute(server, 'VDI.get_by_name_label', session, args[0])
589 vdi_name = args[1]
591 print 'Renaming VDI %s to %s' % (vdi_uuid[0], vdi_name)
592 result = execute(server, 'VDI.set_name_label',
593 (session, vdi_uuid[0], vdi_name), async = async)
594 if async:
595 print 'Task started: %s' % result
596 else:
597 print 'Done.'
601 def xapi_vtpm_create(args, async = False):
602 server, session = connect()
603 domname = args[0]
604 cfg = _read_python_cfg(args[1])
606 vm_uuid = resolve_vm(server, session, domname)
607 cfg['VM'] = vm_uuid
608 print "Creating vTPM with cfg = %s" % cfg
609 vtpm_uuid = execute(server, 'VTPM.create', (session, cfg))
610 print "Done. (%s)" % vtpm_uuid
611 vtpm_id = execute(server, 'VTPM.get_instance', (session, vtpm_uuid))
612 print "Has instance number '%s'" % vtpm_id
613 vtpm_be = execute(server, 'VTPM.get_backend', (session, vtpm_uuid))
614 print "Has backend in '%s'" % vtpm_be
615 driver = execute(server, 'VTPM.get_driver', (session, vtpm_uuid))
616 print "Has driver type '%s'" % driver
617 vtpm_rec = execute(server, 'VTPM.get_record', (session, vtpm_uuid))
618 print "Has vtpm record '%s'" % vtpm_rec
621 def xapi_pif_list(args, async = False):
622 server, session = connect()
623 pif_uuids = execute(server, 'PIF.get_all', (session,))
624 for pif_uuid in pif_uuids:
625 pif = execute(server, 'PIF.get_record', (session, pif_uuid))
626 print pif
629 def xapi_debug_wait(args, async = False):
630 secs = 10
631 if len(args) > 0:
632 secs = int(args[0])
633 server, session = connect()
634 task_uuid = execute(server, 'Debug.wait', (session, secs), async=async)
635 print 'Task UUID: %s' % task_uuid
637 #
638 # Command Line Utils
639 #
640 import cmd
641 import shlex
643 class XenAPICmd(cmd.Cmd):
644 def __init__(self, server, session):
645 cmd.Cmd.__init__(self)
646 self.server = server
647 self.session = session
648 self.prompt = ">>> "
650 def default(self, line):
651 words = shlex.split(line)
652 if len(words) > 0:
653 cmd_name = words[0].replace('-', '_')
654 is_async = 'async' in cmd_name
655 if is_async:
656 cmd_name = re.sub('async_', '', cmd_name)
658 func_name = 'xapi_%s' % cmd_name
659 func = globals().get(func_name)
661 if func:
662 try:
663 args = tuple(words[1:])
664 func(args, async = is_async)
665 return True
666 except SystemExit:
667 return False
668 except OptionError, e:
669 print 'Error:', str(e)
670 return False
671 except Exception, e:
672 import traceback
673 traceback.print_exc()
674 return False
675 print '*** Unknown command: %s' % words[0]
676 return False
678 def do_EOF(self, line):
679 print
680 sys.exit(0)
682 def do_help(self, line):
683 usage(print_usage = False)
685 def emptyline(self):
686 pass
688 def postcmd(self, stop, line):
689 return False
691 def precmd(self, line):
692 words = shlex.split(line)
693 if len(words) > 0:
694 words0 = words[0].replace('-', '_')
695 return ' '.join([words0] + words[1:])
696 else:
697 return line
699 def shell():
700 server, session = connect()
701 x = XenAPICmd(server, session)
702 x.cmdloop('Xen API Prompt. Type "help" for a list of functions')
704 def usage(command = None, print_usage = True):
705 if not command:
706 if print_usage:
707 print 'Usage: xapi <subcommand> [options] [args]'
708 print
709 print 'Subcommands:'
710 print
712 for func in sorted(globals().keys()):
713 if func.startswith('xapi_'):
714 command = func[5:].replace('_', '-')
715 args, description = COMMANDS.get(command, ('', ''))
716 print '%-16s %-40s' % (command, description)
717 print
718 else:
719 parse_args(command, ['-h'])
721 def main(args):
723 if len(args) < 1 or args[0] in ('-h', '--help', 'help'):
724 usage()
725 sys.exit(1)
727 subcmd = args[0].replace('-', '_')
728 is_async = 'async' in subcmd
729 if is_async:
730 subcmd = re.sub('async_', '', subcmd)
731 subcmd_func_name = 'xapi_' + subcmd
732 subcmd_func = globals().get(subcmd_func_name, None)
734 if subcmd == 'shell':
735 shell()
736 elif not subcmd_func or not callable(subcmd_func):
737 print 'Error: Unable to find subcommand \'%s\'' % subcmd
738 usage()
739 sys.exit(1)
741 if '-h' in args[1:] or '--help' in args[1:]:
742 usage(subcmd)
743 sys.exit(1)
745 try:
746 subcmd_func(args[1:], async = is_async)
747 except XenAPIError, e:
748 print 'Error: %s' % str(e.args[0])
749 sys.exit(2)
750 except OptionError, e:
751 print 'Error: %s' % e
753 sys.exit(0)
755 if __name__ == "__main__":
756 import sys
757 main(sys.argv[1:])