debuggers.hg

view tools/python/scripts/xapi.py @ 13654:b111908dd70b

[XEND] Preliminary console support in Xen API

Made serial/vnc consoles a 'fake' device so that we can take advantage
of storing state information in xenstore.

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Thu Jan 25 18:54:25 2007 +0000 (2007-01-25)
parents a94363b85e19
children bb2b1b6662fa
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'
43 CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(uri)-32s'
45 COMMANDS = {
46 'host-info': ('', 'Get Xen Host Info'),
47 'host-set-name': ('', 'Set host name'),
48 'pif-list': ('', 'List all PIFs'),
49 'sr-list': ('', 'List all SRs'),
50 'vbd-list': ('', 'List all VBDs'),
51 'vbd-create': ('<domname> <pycfg> [opts]',
52 'Create VBD attached to domname'),
53 'vdi-create': ('<pycfg> [opts]', 'Create a VDI'),
54 'vdi-list' : ('', 'List all VDI'),
55 'vdi-rename': ('<vdi_uuid> <new_name>', 'Rename VDI'),
56 'vdi-destroy': ('<vdi_uuid>', 'Delete VDI'),
57 'vif-create': ('<domname> <pycfg>', 'Create VIF attached to domname'),
58 'vtpm-create' : ('<domname> <pycfg>', 'Create VTPM attached to domname'),
60 'vm-create': ('<pycfg>', 'Create VM with python config'),
61 'vm-destroy': ('<domname>', 'Delete VM'),
63 'vm-list': ('[--long]', 'List all domains.'),
64 'vm-name': ('<uuid>', 'Name of UUID.'),
65 'vm-shutdown': ('<name> [opts]', 'Shutdown VM with name'),
66 'vm-start': ('<name>', 'Start VM with name'),
67 'vm-uuid': ('<name>', 'UUID of a domain by name.'),
68 'async-vm-start': ('<name>', 'Start VM asynchronously'),
69 }
71 OPTIONS = {
72 'sr-list': [(('-l', '--long'),
73 {'action':'store_true',
74 'help':'List all properties of SR'})
75 ],
77 'vdi-list': [(('-l', '--long'),
78 {'action':'store_true',
79 'help':'List all properties of VDI'})
80 ],
81 'vif-list': [(('-l', '--long'),
82 {'action':'store_true',
83 'help':'List all properties of VIF'})
84 ],
85 'vm-list': [(('-l', '--long'),
86 {'action':'store_true',
87 'help':'List all properties of VMs'})
88 ],
89 'vm-shutdown': [(('-f', '--force'), {'help': 'Shutdown Forcefully',
90 'action': 'store_true'})],
92 'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
93 (('--name-description',), {'help': 'Description for VDI'}),
94 (('--sector-size',), {'type': 'int',
95 'help': 'Sector size',
96 'default': 0}),
97 (('--virtual-size',), {'type': 'int',
98 'default': 0,
99 'help': 'Size of VDI in sectors'}),
100 (('--type',), {'choices': ['system', 'user', 'ephemeral'],
101 'default': 'system',
102 'help': 'VDI type'}),
103 (('--sharable',), {'action': 'store_true',
104 'help': 'VDI sharable'}),
105 (('--read-only',), {'action': 'store_true',
106 'help': 'Read only'}),
107 (('--sr',), {})],
109 'vbd-create': [(('--VDI',), {'help': 'UUID of VDI to attach to.'}),
110 (('--mode',), {'choices': ['RO', 'RW'],
111 'help': 'device mount mode'}),
112 (('--driver',), {'choices':['paravirtualised', 'ioemu'],
113 'help': 'Driver for VBD'}),
114 (('--device',), {'help': 'Device name on guest domain'})]
116 }
118 class OptionError(Exception):
119 pass
121 class XenAPIError(Exception):
122 pass
124 #
125 # Extra utility functions
126 #
128 class IterableValues(Values):
129 """Better interface to the list of values from optparse."""
131 def __iter__(self):
132 for opt, val in self.__dict__.items():
133 if opt[0] == '_' or callable(val):
134 continue
135 yield opt, val
138 def parse_args(cmd_name, args, set_defaults = False):
139 argstring, desc = COMMANDS[cmd_name]
140 parser = OptionParser(usage = 'xapi %s %s' % (cmd_name, argstring),
141 description = desc)
142 if cmd_name in OPTIONS:
143 for optargs, optkwds in OPTIONS[cmd_name]:
144 parser.add_option(*optargs, **optkwds)
146 if set_defaults:
147 default_values = parser.get_default_values()
148 defaults = IterableValues(default_values.__dict__)
149 else:
150 defaults = IterableValues()
151 (opts, extraargs) = parser.parse_args(args = list(args),
152 values = defaults)
153 return opts, extraargs
155 def execute(server, fn, args, async = False):
156 if async:
157 func = eval('server.Async.%s' % fn)
158 else:
159 func = eval('server.%s' % fn)
161 result = func(*args)
162 if type(result) != DictType:
163 raise TypeError("Function returned object of type: %s" %
164 str(type(result)))
165 if 'Value' not in result:
166 raise XenAPIError(*result['ErrorDescription'])
167 return result['Value']
169 _initialised = False
170 _server = None
171 _session = None
172 def connect(*args):
173 global _server, _session, _initialised
175 if not _initialised:
176 # try without password
177 try:
178 _server = ServerProxy('http://localhost:9363/')
179 _session = execute(_server.session, 'login_with_password',
180 ('',''))
181 except:
182 login = raw_input("Login: ")
183 password = getpass()
184 creds = (login, password)
185 _server = ServerProxy('http://localhost:9363/')
186 _session = execute(_server.session, 'login_with_password',
187 creds)
189 _initialised = True
190 return (_server, _session)
192 def _stringify(adict):
193 return dict([(k, str(v)) for k, v in adict.items()])
195 def _read_python_cfg(filename):
196 cfg = {}
197 execfile(filename, {}, cfg)
198 return cfg
200 def resolve_vm(server, session, vm_name):
201 vm_uuid = execute(server, 'VM.get_by_name_label', (session, vm_name))
202 if not vm_uuid:
203 return None
204 else:
205 return vm_uuid[0]
207 def resolve_vdi(server, session, vdi_name):
208 vdi_uuid = execute(server, 'VDI.get_by_name_label', (session, vdi_name))
209 if not vdi_uuid:
210 return None
211 else:
212 return vdi_uuid[0]
214 #
215 # Actual commands
216 #
218 def xapi_host_info(args, async = False):
219 server, session = connect()
220 hosts = execute(server, 'host.get_all', (session,))
221 for host in hosts: # there is only one, but ..
222 hostinfo = execute(server, 'host.get_record', (session, host))
223 print HOST_INFO_FORMAT % ('Name', hostinfo['name_label'])
224 print HOST_INFO_FORMAT % ('Version', hostinfo['software_version'])
225 print HOST_INFO_FORMAT % ('CPUs', len(hostinfo['host_CPUs']))
226 print HOST_INFO_FORMAT % ('VMs', len(hostinfo['resident_VMs']))
227 print HOST_INFO_FORMAT % ('UUID', host)
229 for host_cpu_uuid in hostinfo['host_CPUs']:
230 host_cpu = execute(server, 'host_cpu.get_record',
231 (session, host_cpu_uuid))
232 print 'CPU %s Util: %.2f' % (host_cpu['number'],
233 float(host_cpu['utilisation']))
235 def xapi_host_set_name(args, async = False):
236 if len(args) < 1:
237 raise OptionError("No hostname specified")
239 server, session = connect()
240 hosts = execute(server, 'host.get_all', (session,))
241 if len(hosts) > 0:
242 execute(server, 'host.set_name_label', (session, hosts[0], args[0]))
243 print 'Hostname: %s' % execute(server, 'host.get_name_label',
244 (session, hosts[0]))
246 def xapi_vm_uuid(args, async = False):
247 if len(args) < 1:
248 raise OptionError("No domain name specified")
250 server, session = connect()
251 vm_uuid = resolve_vm(server, session, args[0])
252 print vm_uuid
254 def xapi_vm_name(args, async = False):
255 if len(args) < 1:
256 raise OptionError("No UUID specified")
258 server, session = connect()
259 vm_name = execute(server, 'VM.get_name_label', (session, args[0]))
260 print vm_name
262 def xapi_vm_list(args, async = False):
263 opts, args = parse_args('vm-list', args, set_defaults = True)
264 is_long = opts and opts.long
266 server, session = connect()
267 vm_uuids = execute(server, 'VM.get_all', (session,))
268 if not is_long:
269 print VM_LIST_FORMAT % {'name_label':'Name',
270 'memory_actual':'Mem',
271 'VCPUs_number': 'VCPUs',
272 'power_state': 'State',
273 'uuid': 'UUID'}
275 for uuid in vm_uuids:
276 vm_info = execute(server, 'VM.get_record', (session, uuid))
277 if is_long:
278 vbds = vm_info['VBDs']
279 vifs = vm_info['VIFs']
280 vtpms = vm_info['VTPMs']
281 vif_infos = []
282 vbd_infos = []
283 vtpm_infos = []
284 for vbd in vbds:
285 vbd_info = execute(server, 'VBD.get_record', (session, vbd))
286 vbd_infos.append(vbd_info)
287 for vif in vifs:
288 vif_info = execute(server, 'VIF.get_record', (session, vif))
289 vif_infos.append(vif_info)
290 for vtpm in vtpms:
291 vtpm_info = execute(server, 'VTPM.get_record', (session, vtpm))
292 vtpm_infos.append(vtpm_info)
293 vm_info['VBDs'] = vbd_infos
294 vm_info['VIFs'] = vif_infos
295 vm_info['VTPMs'] = vtpm_infos
296 pprint(vm_info)
297 else:
298 print VM_LIST_FORMAT % _stringify(vm_info)
300 def xapi_vm_create(args, async = False):
301 if len(args) < 1:
302 raise OptionError("Configuration file not specified")
304 filename = args[0]
305 cfg = _read_python_cfg(filename)
307 print 'Creating VM from %s ..' % filename
308 server, session = connect()
309 uuid = execute(server, 'VM.create', (session, cfg), async = async)
310 print 'Done. (%s)' % uuid
311 print uuid
313 def xapi_vm_destroy(args, async = False):
314 if len(args) < 1:
315 raise OptionError("No domain name specified.")
317 server, session = connect()
318 vm_uuid = resolve_vm(server, session, args[0])
319 print 'Destroying VM %s (%s)' % (args[0], vm_uuid)
320 success = execute(server, 'VM.destroy', (session, vm_uuid), async = async)
321 print 'Done.'
324 def xapi_vm_start(args, async = False):
325 if len(args) < 1:
326 raise OptionError("No Domain name specified.")
328 server, session = connect()
329 vm_uuid = resolve_vm(server, session, args[0])
330 print 'Starting VM %s (%s)' % (args[0], vm_uuid)
331 success = execute(server, 'VM.start', (session, vm_uuid, False), async = async)
332 if async:
333 print 'Task started: %s' % success
334 else:
335 print 'Done.'
337 def xapi_vm_suspend(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 'Suspending VM %s (%s)' % (args[0], vm_uuid)
344 success = execute(server, 'VM.suspend', (session, vm_uuid), async = async)
345 if async:
346 print 'Task started: %s' % success
347 else:
348 print 'Done.'
351 def xapi_vm_resume(args, async = False):
352 if len(args) < 1:
353 raise OptionError("No Domain name specified.")
355 server, session = connect()
356 vm_uuid = resolve_vm(server, session, args[0])
357 print 'Resuming VM %s (%s)' % (args[0], vm_uuid)
358 success = execute(server, 'VM.resume', (session, vm_uuid, False), async = async)
359 if async:
360 print 'Task started: %s' % success
361 else:
362 print 'Done.'
364 def xapi_vm_pause(args, async = False):
365 if len(args) < 1:
366 raise OptionError("No Domain name specified.")
368 server, session = connect()
369 vm_uuid = resolve_vm(server, session, args[0])
370 print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
371 success = execute(server, 'VM.pause', (session, vm_uuid), async = async)
372 if async:
373 print 'Task started: %s' % success
374 else:
375 print 'Done.'
377 def xapi_vm_unpause(args, async = False):
378 if len(args) < 1:
379 raise OptionError("No Domain name specified.")
381 server, session = connect()
382 vm_uuid = resolve_vm(server, session, args[0])
383 print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
384 success = execute(server, 'VM.unpause', (session, vm_uuid), async = async)
385 if async:
386 print 'Task started: %s' % success
387 else:
388 print 'Done.'
390 def xapi_task_list(args, async = False):
391 server, session = connect()
392 all_tasks = execute(server, 'task.get_all', (session,))
394 print TASK_LIST_FORMAT % {'name_label': 'Task Name',
395 'uuid': 'UUID',
396 'status': 'Status',
397 'progress': '%'}
399 for task_uuid in all_tasks:
400 task = execute(server, 'task.get_record', (session, task_uuid))
401 print TASK_LIST_FORMAT % task
403 def xapi_task_clear(args, async = False):
404 server, session = connect()
405 all_tasks = execute(server, 'task.get_all', (session,))
406 for task_uuid in all_tasks:
407 success = execute(server, 'task.destroy', (session, task_uuid))
408 print 'Destroyed Task %s' % task_uuid
410 def xapi_vm_shutdown(args, async = False):
411 opts, args = parse_args("vm-shutdown", args, set_defaults = True)
413 if len(args) < 1:
414 raise OptionError("No Domain name specified.")
416 server, session = connect()
417 vm_uuid = resolve_vm(server, session, args[0])
418 if opts.force:
419 print 'Forcefully shutting down VM %s (%s)' % (args[0], vm_uuid)
420 success = execute(server, 'VM.hard_shutdown', (session, vm_uuid), async = async)
421 else:
422 print 'Shutting down VM %s (%s)' % (args[0], vm_uuid)
423 success = execute(server, 'VM.clean_shutdown', (session, vm_uuid), async = async)
425 if async:
426 print 'Task started: %s' % success
427 else:
428 print 'Done.'
430 def xapi_vbd_create(args, async = False):
431 opts, args = parse_args('vbd-create', args)
433 if len(args) < 2:
434 raise OptionError("Configuration file and domain not specified")
436 domname = args[0]
438 if len(args) > 1:
439 filename = args[1]
440 cfg = _read_python_cfg(filename)
441 else:
442 cfg = {}
444 for opt, val in opts:
445 cfg[opt] = val
447 print 'Creating VBD ...',
448 server, session = connect()
449 vm_uuid = resolve_vm(server, session, domname)
450 cfg['VM'] = vm_uuid
451 vbd_uuid = execute(server, 'VBD.create', (session, cfg), async = async)
452 if async:
453 print 'Task started: %s' % vbd_uuid
454 else:
455 print 'Done. (%s)' % vbd_uuid
457 def xapi_vif_create(args, async = False):
458 if len(args) < 2:
459 raise OptionError("Configuration file not specified")
461 domname = args[0]
462 filename = args[1]
463 cfg = _read_python_cfg(filename)
465 print 'Creating VIF from %s ..' % filename
466 server, session = connect()
467 vm_uuid = resolve_vm(server, session, domname)
468 cfg['VM'] = vm_uuid
469 vif_uuid = execute(server, 'VIF.create', (session, cfg), async = async)
470 if async:
471 print 'Task started: %s' % vif_uuid
472 else:
473 print 'Done. (%s)' % vif_uuid
475 def xapi_vbd_list(args, async = False):
476 server, session = connect()
477 domname = args[0]
479 dom_uuid = resolve_vm(server, session, domname)
480 vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
482 print VBD_LIST_FORMAT % {'device': 'Device',
483 'uuid' : 'UUID',
484 'VDI': 'VDI'}
486 for vbd in vbds:
487 vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
488 print VBD_LIST_FORMAT % vbd_struct
491 def xapi_vbd_stats(args, async = False):
492 server, session = connect()
493 domname = args[0]
494 dom_uuid = resolve_vm(server, session, domname)
496 vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
497 for vbd_uuid in vbds:
498 print execute(server, 'VBD.get_io_read_kbs', (session, vbd_uuid))
500 def xapi_vif_list(args, async = False):
501 server, session = connect()
502 opts, args = parse_args('vdi-list', args, set_defaults = True)
503 is_long = opts and opts.long
505 domname = args[0]
507 dom_uuid = resolve_vm(server, session, domname)
508 vifs = execute(server, 'VM.get_VIFs', (session, dom_uuid))
510 if not is_long:
511 print VIF_LIST_FORMAT % {'name': 'Name',
512 'device': 'Device',
513 'uuid' : 'UUID',
514 'MAC': 'MAC'}
516 for vif in vifs:
517 vif_struct = execute(server, 'VIF.get_record', (session, vif))
518 print VIF_LIST_FORMAT % vif_struct
519 else:
520 for vif in vifs:
521 vif_struct = execute(server, 'VIF.get_record', (session, vif))
522 pprint(vif_struct)
524 def xapi_console_list(args, async = False):
525 server, session = connect()
526 opts, args = parse_args('vdi-list', args, set_defaults = True)
527 is_long = opts and opts.long
529 domname = args[0]
531 dom_uuid = resolve_vm(server, session, domname)
532 consoles = execute(server, 'VM.get_consoles', (session, dom_uuid))
534 if not is_long:
535 print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol',
536 'uri': 'URI',
537 'uuid': 'UUID'}
539 for console in consoles:
540 console_struct = execute(server, 'console.get_record',
541 (session, console))
542 print CONSOLE_LIST_FORMAT % console_struct
543 else:
544 for console in consoles:
545 console_struct = execute(server, 'console.get_record',
546 (session, console))
547 pprint(console_struct)
550 def xapi_vdi_list(args, async = False):
551 opts, args = parse_args('vdi-list', args, set_defaults = True)
552 is_long = opts and opts.long
554 server, session = connect()
555 vdis = execute(server, 'VDI.get_all', (session,))
557 if not is_long:
558 print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
559 'uuid' : 'UUID',
560 'virtual_size': 'Sectors',
561 'sector_size': 'Sector Size'}
563 for vdi in vdis:
564 vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
565 print VDI_LIST_FORMAT % vdi_struct
567 else:
568 for vdi in vdis:
569 vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
570 pprint(vdi_struct)
572 def xapi_sr_list(args, async = False):
573 opts, args = parse_args('sr-list', args, set_defaults = True)
574 is_long = opts and opts.long
576 server, session = connect()
577 srs = execute(server, 'SR.get_all', (session,))
578 if not is_long:
579 print SR_LIST_FORMAT % {'name_label': 'SR Label',
580 'uuid' : 'UUID',
581 'physical_size': 'Size (MB)',
582 'type': 'Type'}
584 for sr in srs:
585 sr_struct = execute(server, 'SR.get_record', (session, sr))
586 sr_struct['physical_size'] = int(sr_struct['physical_size'])/MB
587 print SR_LIST_FORMAT % sr_struct
588 else:
589 for sr in srs:
590 sr_struct = execute(server, 'SR.get_record', (session, sr))
591 pprint(sr_struct)
593 def xapi_sr_rename(args, async = False):
594 server, session = connect()
595 sr = execute(server, 'SR.get_by_name_label', (session, args[0]))
596 execute(server, 'SR.set_name_label', (session, sr[0], args[1]))
598 def xapi_vdi_create(args, async = False):
599 opts, args = parse_args('vdi-create', args)
601 if len(args) > 0:
602 cfg = _read_python_cfg(args[0])
603 else:
604 cfg = {}
606 for opt, val in opts:
607 cfg[opt] = val
609 server, session = connect()
610 srs = []
611 if cfg.get('SR'):
612 srs = execute(server, 'SR.get_by_name_label', (session, cfg['SR']))
613 else:
614 srs = execute(server, 'SR.get_all', (session,))
616 sr = srs[0]
617 cfg['SR'] = sr
619 size = (cfg['virtual_size'] * cfg['sector_size'])/MB
620 print 'Creating VDI of size: %dMB ..' % size,
621 uuid = execute(server, 'VDI.create', (session, cfg), async = async)
622 if async:
623 print 'Task started: %s' % uuid
624 else:
625 print 'Done. (%s)' % uuid
628 def xapi_vdi_destroy(args, async = False):
629 server, session = connect()
630 if len(args) < 1:
631 raise OptionError('Not enough arguments')
633 vdi_uuid = args[0]
634 print 'Deleting VDI %s' % vdi_uuid
635 result = execute(server, 'VDI.destroy', (session, vdi_uuid), async = async)
636 if async:
637 print 'Task started: %s' % result
638 else:
639 print 'Done.'
641 def xapi_vdi_rename(args, async = False):
642 server, session = connect()
643 if len(args) < 2:
644 raise OptionError('Not enough arguments')
646 vdi_uuid = execute(server, 'VDI.get_by_name_label', session, args[0])
647 vdi_name = args[1]
649 print 'Renaming VDI %s to %s' % (vdi_uuid[0], vdi_name)
650 result = execute(server, 'VDI.set_name_label',
651 (session, vdi_uuid[0], vdi_name), async = async)
652 if async:
653 print 'Task started: %s' % result
654 else:
655 print 'Done.'
659 def xapi_vtpm_create(args, async = False):
660 server, session = connect()
661 domname = args[0]
662 cfg = _read_python_cfg(args[1])
664 vm_uuid = resolve_vm(server, session, domname)
665 cfg['VM'] = vm_uuid
666 print "Creating vTPM with cfg = %s" % cfg
667 vtpm_uuid = execute(server, 'VTPM.create', (session, cfg))
668 print "Done. (%s)" % vtpm_uuid
669 vtpm_id = execute(server, 'VTPM.get_instance', (session, vtpm_uuid))
670 print "Has instance number '%s'" % vtpm_id
671 vtpm_be = execute(server, 'VTPM.get_backend', (session, vtpm_uuid))
672 print "Has backend in '%s'" % vtpm_be
673 driver = execute(server, 'VTPM.get_driver', (session, vtpm_uuid))
674 print "Has driver type '%s'" % driver
675 vtpm_rec = execute(server, 'VTPM.get_record', (session, vtpm_uuid))
676 print "Has vtpm record '%s'" % vtpm_rec
679 def xapi_pif_list(args, async = False):
680 server, session = connect()
681 pif_uuids = execute(server, 'PIF.get_all', (session,))
682 for pif_uuid in pif_uuids:
683 pif = execute(server, 'PIF.get_record', (session, pif_uuid))
684 print pif
687 def xapi_debug_wait(args, async = False):
688 secs = 10
689 if len(args) > 0:
690 secs = int(args[0])
691 server, session = connect()
692 task_uuid = execute(server, 'debug.wait', (session, secs), async=async)
693 print 'Task UUID: %s' % task_uuid
695 #
696 # Command Line Utils
697 #
698 import cmd
699 import shlex
701 class XenAPICmd(cmd.Cmd):
702 def __init__(self, server, session):
703 cmd.Cmd.__init__(self)
704 self.server = server
705 self.session = session
706 self.prompt = ">>> "
708 def default(self, line):
709 words = shlex.split(line)
710 if len(words) > 0:
711 cmd_name = words[0].replace('-', '_')
712 is_async = 'async' in cmd_name
713 if is_async:
714 cmd_name = re.sub('async_', '', cmd_name)
716 func_name = 'xapi_%s' % cmd_name
717 func = globals().get(func_name)
719 if func:
720 try:
721 args = tuple(words[1:])
722 func(args, async = is_async)
723 return True
724 except SystemExit:
725 return False
726 except OptionError, e:
727 print 'Error:', str(e)
728 return False
729 except Exception, e:
730 import traceback
731 traceback.print_exc()
732 return False
733 print '*** Unknown command: %s' % words[0]
734 return False
736 def do_EOF(self, line):
737 print
738 sys.exit(0)
740 def do_help(self, line):
741 usage(print_usage = False)
743 def emptyline(self):
744 pass
746 def postcmd(self, stop, line):
747 return False
749 def precmd(self, line):
750 words = shlex.split(line)
751 if len(words) > 0:
752 words0 = words[0].replace('-', '_')
753 return ' '.join([words0] + words[1:])
754 else:
755 return line
757 def shell():
758 server, session = connect()
759 x = XenAPICmd(server, session)
760 x.cmdloop('Xen API Prompt. Type "help" for a list of functions')
762 def usage(command = None, print_usage = True):
763 if not command:
764 if print_usage:
765 print 'Usage: xapi <subcommand> [options] [args]'
766 print
767 print 'Subcommands:'
768 print
770 for func in sorted(globals().keys()):
771 if func.startswith('xapi_'):
772 command = func[5:].replace('_', '-')
773 args, description = COMMANDS.get(command, ('', ''))
774 print '%-16s %-40s' % (command, description)
775 print
776 else:
777 parse_args(command, ['-h'])
779 def main(args):
781 if len(args) < 1 or args[0] in ('-h', '--help', 'help'):
782 usage()
783 sys.exit(1)
785 subcmd = args[0].replace('-', '_')
786 is_async = 'async' in subcmd
787 if is_async:
788 subcmd = re.sub('async_', '', subcmd)
789 subcmd_func_name = 'xapi_' + subcmd
790 subcmd_func = globals().get(subcmd_func_name, None)
792 if subcmd == 'shell':
793 shell()
794 elif not subcmd_func or not callable(subcmd_func):
795 print 'Error: Unable to find subcommand \'%s\'' % subcmd
796 usage()
797 sys.exit(1)
799 if '-h' in args[1:] or '--help' in args[1:]:
800 usage(subcmd)
801 sys.exit(1)
803 try:
804 subcmd_func(args[1:], async = is_async)
805 except XenAPIError, e:
806 print 'Error: %s' % str(e.args[0])
807 sys.exit(2)
808 except OptionError, e:
809 print 'Error: %s' % e
811 sys.exit(0)
813 if __name__ == "__main__":
814 import sys
815 main(sys.argv[1:])