source: trunk/packages/xen-common/xen-common/tools/python/scripts/xapi.py @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

  • Property svn:mime-type set to text/script
File size: 28.6 KB
Line 
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#============================================================================
18
19import sys
20import time
21import re
22import os
23sys.path.append('/usr/lib/python')
24
25from xen.util.xmlrpclib2 import ServerProxy
26from optparse import *
27from pprint import pprint
28from types import DictType
29from getpass import getpass
30
31# Get default values from the environment
32SERVER_URI = os.environ.get('XAPI_SERVER_URI', 'http://localhost:9363/')
33SERVER_USER = os.environ.get('XAPI_SERVER_USER', '')
34SERVER_PASS = os.environ.get('XAPI_SERVER_PASS', '')
35
36MB = 1024 * 1024
37
38HOST_INFO_FORMAT = '%-20s: %-50s'
39VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
40                 ' %(power_state)-10s %(uuid)-36s'
41SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
42                 '%(type)-10s'
43VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
44VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
45TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
46VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
47CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(location)-32s'
48
49COMMANDS = {
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'),
63
64    'vm-create': ('<pycfg>', 'Create VM with python config'),
65    'vm-destroy': ('<domname>', 'Delete VM'),
66   
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}
74
75OPTIONS = {
76    'sr-list': [(('-l', '--long'),
77                 {'action':'store_true',
78                  'help':'List all properties of SR'})
79               ],
80
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'})],
95   
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',), {})],
109   
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'})]
116                   
117}
118
119class OptionError(Exception):
120    pass
121
122class XenAPIError(Exception):
123    pass
124
125#
126# Extra utility functions
127#
128
129class IterableValues(Values):
130    """Better interface to the list of values from optparse."""
131
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       
137
138
139def 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)
146
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
155
156def execute(server, fn, args, async = False):
157    if async:
158        func = eval('server.Async.%s' % fn)
159    else:
160        func = eval('server.%s' % fn)
161       
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']
169
170_initialised = False
171_server = None
172_session = None
173def connect(*args):
174    global _server, _session, _initialised
175   
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)
189
190        _initialised = True
191    return (_server, _session)
192
193def _stringify(adict):
194    return dict([(k, str(v)) for k, v in adict.items()])
195
196def _read_python_cfg(filename):
197    cfg = {}
198    execfile(filename, {}, cfg)
199    return cfg
200
201def 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]
207
208def 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]
214
215#
216# Actual commands
217#
218
219def 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)       
229
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']))
235       
236def xapi_host_set_name(args, async = False):
237    if len(args) < 1:
238        raise OptionError("No hostname specified")
239   
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]))
246
247def xapi_vm_uuid(args, async = False):
248    if len(args) < 1:
249        raise OptionError("No domain name specified")
250   
251    server, session = connect()
252    vm_uuid = resolve_vm(server, session, args[0])
253    print vm_uuid
254
255def xapi_vm_name(args, async = False):
256    if len(args) < 1:
257        raise OptionError("No UUID specified")
258   
259    server, session = connect()
260    vm_name = execute(server, 'VM.get_name_label', (session, args[0]))
261    print vm_name
262
263def xapi_vm_list(args, async = False):
264    opts, args = parse_args('vm-list', args, set_defaults = True)
265    is_long = opts and opts.long
266
267    list_only = args
268   
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'}
277
278    for uuid in vm_uuids:
279        vm_info = execute(server, 'VM.get_record', (session, uuid))
280
281        # skip domain if we don't want
282        if list_only and vm_info['name_label'] not in list_only:
283            continue
284       
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)
307
308def xapi_vm_create(args, async = False):
309    if len(args) < 1:
310        raise OptionError("Configuration file not specified")
311
312    filename = args[0]
313    cfg = _read_python_cfg(filename)
314
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
320
321def xapi_vm_destroy(args, async = False):
322    if len(args) < 1:
323        raise OptionError("No domain name specified.")
324   
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.'
330   
331
332def xapi_vm_start(args, async = False):
333    if len(args) < 1:
334        raise OptionError("No Domain name specified.")
335   
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.'
344
345def xapi_vm_suspend(args, async = False):
346    if len(args) < 1:
347        raise OptionError("No Domain name specified.")
348   
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.'       
357
358
359def xapi_vm_resume(args, async = False):
360    if len(args) < 1:
361        raise OptionError("No Domain name specified.")
362   
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.'
371
372def xapi_vm_pause(args, async = False):
373    if len(args) < 1:
374        raise OptionError("No Domain name specified.")
375   
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.'
384
385def xapi_vm_unpause(args, async = False):
386    if len(args) < 1:
387        raise OptionError("No Domain name specified.")
388   
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.'                       
397
398def xapi_task_list(args, async = False):
399    server, session = connect()
400    all_tasks = execute(server, 'task.get_all', (session,))
401
402    print TASK_LIST_FORMAT % {'name_label': 'Task Name',
403                              'uuid': 'UUID',
404                              'status': 'Status',
405                              'progress': '%'}
406   
407    for task_uuid in all_tasks:
408        task = execute(server, 'task.get_record', (session, task_uuid))
409        print TASK_LIST_FORMAT % task
410
411def 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
417
418def xapi_vm_shutdown(args, async = False):
419    opts, args = parse_args("vm-shutdown", args, set_defaults = True)
420   
421    if len(args) < 1:
422        raise OptionError("No Domain name specified.")
423
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)
432
433    if async:
434        print 'Task started: %s' % success
435    else:
436        print 'Done.'
437
438def xapi_vbd_create(args, async = False):
439    opts, args = parse_args('vbd-create', args)
440
441    if len(args) < 2:
442        raise OptionError("Configuration file and domain not specified")
443
444    domname = args[0]
445
446    if len(args) > 1:
447        filename = args[1]
448        cfg = _read_python_cfg(filename)
449    else:
450        cfg = {}
451       
452    for opt, val in opts:
453        cfg[opt] = val
454   
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
464
465def xapi_vif_create(args, async = False):
466    if len(args) < 2:
467        raise OptionError("Configuration file not specified")
468
469    domname = args[0]
470    filename = args[1]
471    cfg = _read_python_cfg(filename)
472   
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
482
483def xapi_vbd_list(args, async = False):
484    server, session = connect()
485    domname = args[0]
486   
487    dom_uuid = resolve_vm(server, session, domname)
488    vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
489   
490    print VBD_LIST_FORMAT % {'device': 'Device',
491                             'uuid' : 'UUID',
492                             'VDI': 'VDI'}
493   
494    for vbd in vbds:
495        vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
496        print VBD_LIST_FORMAT % vbd_struct
497       
498       
499def xapi_vbd_stats(args, async = False):
500    server, session = connect()
501    domname = args[0]
502    dom_uuid = resolve_vm(server, session, domname)
503
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))
507 
508def 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
512   
513    domname = args[0]
514   
515    dom_uuid = resolve_vm(server, session, domname)
516    vifs = execute(server, 'VM.get_VIFs', (session, dom_uuid))
517
518    if not is_long:
519        print VIF_LIST_FORMAT % {'name': 'Name',
520                                 'device': 'Device',
521                                 'uuid' : 'UUID',
522                                 'MAC': 'MAC'}
523       
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)
531
532def 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
536   
537    domname = args[0]
538   
539    dom_uuid = resolve_vm(server, session, domname)
540    consoles = execute(server, 'VM.get_consoles', (session, dom_uuid))
541
542    if not is_long:
543        print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol',
544                                     'location': 'Location',
545                                     'uuid': 'UUID'}
546
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)           
556
557
558def xapi_vdi_list(args, async = False):
559    opts, args = parse_args('vdi-list', args, set_defaults = True)
560    is_long = opts and opts.long
561
562    server, session = connect()
563    vdis = execute(server, 'VDI.get_all', (session,))
564
565    if not is_long:
566        print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
567                                 'uuid' : 'UUID',
568                                 'virtual_size': 'Bytes'}
569       
570        for vdi in vdis:
571            vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
572            print VDI_LIST_FORMAT % vdi_struct
573
574    else:
575        for vdi in vdis:
576            vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
577            pprint(vdi_struct)
578
579def xapi_sr_list(args, async = False):
580    opts, args = parse_args('sr-list', args, set_defaults = True)
581    is_long = opts and opts.long
582   
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'}
590       
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)
599
600def 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]))
604
605def xapi_vdi_create(args, async = False):
606    opts, args = parse_args('vdi-create', args)
607
608    if len(args) > 0:
609        cfg = _read_python_cfg(args[0])
610    else:
611        cfg = {}
612       
613    for opt, val in opts:
614        cfg[opt] = val
615
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,))
622
623    sr = srs[0]
624    cfg['SR'] = sr
625
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
633   
634
635def xapi_vdi_destroy(args, async = False):
636    server, session = connect()
637    if len(args) < 1:
638        raise OptionError('Not enough arguments')
639
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.'
647
648def xapi_vdi_rename(args, async = False):
649    server, session = connect()
650    if len(args) < 2:
651        raise OptionError('Not enough arguments')
652
653    vdi_uuid = execute(server, 'VDI.get_by_name_label', session, args[0])
654    vdi_name = args[1]
655   
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.'
663
664
665
666def xapi_vtpm_create(args, async = False):
667    server, session = connect()
668    domname = args[0]
669    cfg = _read_python_cfg(args[1])
670
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
676
677
678def 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
684
685
686def 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
693
694def xapi_vm_stat(args, async = False):
695    domname = args[0]
696   
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))
703
704    for vcpu_num in sorted(vcpus_utils.keys()):
705        print 'CPU %s : %5.2f%%' % (vcpu_num, vcpus_utils[vcpu_num] * 100)
706       
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
715       
716#
717# Command Line Utils
718#
719import cmd
720import shlex
721
722class 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 = ">>> "
728
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)
736               
737            func_name = 'xapi_%s' % cmd_name
738            func = globals().get(func_name)
739           
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
756
757    def do_EOF(self, line):
758        print
759        sys.exit(0)
760
761    def do_help(self, line):
762        usage(print_usage = False)
763
764    def emptyline(self):
765        pass
766
767    def postcmd(self, stop, line):
768        return False
769
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
777
778def shell():
779    server, session = connect()
780    x = XenAPICmd(server, session)
781    x.cmdloop('Xen API Prompt. Type "help" for a list of functions')
782
783def 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
790
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'])
799
800def main(args):
801   
802    # poor man's optparse that doesn't abort on unrecognised opts
803
804    options = {}
805    remaining = []
806   
807    arg_n = 0
808    while args:
809        arg = args.pop(0)
810       
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)
821
822    # abort here if these conditions are true
823
824    if options.get('help') and not remaining:
825        usage()
826        sys.exit(1)
827
828    if options.get('help') and remaining:
829        usage(remaining[0])
830        sys.exit(1)
831
832    if not remaining:
833        usage()
834        sys.exit(1)
835
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']
840
841    if options.get('user'):
842        global SERVER_USER
843        SERVER_USER = options['user']
844
845    if options.get('password'):
846        global SERVER_PASS
847        SERVER_PASS = options['password']
848
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)
855
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)
862
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
870
871    sys.exit(0)
872   
873if __name__ == "__main__":
874    import sys
875    main(sys.argv[1:])
Note: See TracBrowser for help on using the repository browser.