Files
xen/tools/python/scripts/xapi.py
T
Keir Fraser 11e1149fe0 tools: Always use sane upstream (`native') python paths
Previously, by default we would install our python modules into
/usr/lib/python/xen, for example /usr/lib/python/xen/__init__.py.
Upstream python's standard install location (a) includes the Python
version number and (b) puts things in site-packages by default.

Our best conjecture for the reason for this was an attempt to make the
installs portable between different python versions.  However, that
doesn't work because compiled python modules (.pyc), and C python
extensions corresponding to one version of python, are not compatible
across different versions of python.

This is why upstream include the version number.

site-packages is the standard location for locally-installed packages
and is automatically included on the python search path.

In this change, we abandon our own unusual python path setup:

 * Invoke setup.py in an entirely standard manner.  We pass
   PREFIX and DESTDIR using the appropriate options provided by
   setup.py for those purposes (adding them to setup.py calls
   which were previously lacking them).

 * Since the installation locations are now on the standard
   python path, we no longer need to add anything to the path
   in any of our python utilities.  Therefore remove all that
   code from every python script.  (Many of these scripts
   unconditionally added /usr/lib/python and /usr/lib64/python which
   is wrong even in the old world.)

 * There is no longer any special `Xen python path'.  xen-python-path
   is no longer needed.  It is no longer called by anything in our
   tree.  However since out-of-tree callers may still invoke it, we
   retain it.  It now prints a fixed string referring to a directory
   which does not to exist; callers (who use it to augment their
   python path) will thus add a nonexistent directory to their python
   path which is harmless.

 * Remove various workarounds including use of setup.py --home
   (which is intended for something completely different).

 * Remove tests for the XEN_PYTHON_NATIVE_INSTALL build-time
   environment variable.  The new behaviour is the behaviour which we
   should have had if this variable had been set.  That is, it is now
   as if this variable was always set but also bugs in the resulting
   install have been fixed.

This should be a proper fix for the bug addressed by c/s 19515.

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
2009-04-08 19:13:04 +01:00

875 lines
29 KiB
Python

#!/usr/bin/python
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2006 XenSource Ltd.
#============================================================================
import sys
import time
import re
import os
from xen.util.xmlrpclib2 import ServerProxy
from optparse import *
from pprint import pprint
from types import DictType
from getpass import getpass
# Get default values from the environment
SERVER_URI = os.environ.get('XAPI_SERVER_URI', 'http://localhost:9363/')
SERVER_USER = os.environ.get('XAPI_SERVER_USER', '')
SERVER_PASS = os.environ.get('XAPI_SERVER_PASS', '')
MB = 1024 * 1024
HOST_INFO_FORMAT = '%-20s: %-50s'
VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
' %(power_state)-10s %(uuid)-36s'
SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
'%(type)-10s'
VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(location)-32s'
COMMANDS = {
'host-info': ('', 'Get Xen Host Info'),
'host-set-name': ('', 'Set host name'),
'pif-list': ('', 'List all PIFs'),
'sr-list': ('', 'List all SRs'),
'vbd-list': ('', 'List all VBDs'),
'vbd-create': ('<domname> <pycfg> [opts]',
'Create VBD attached to domname'),
'vdi-create': ('<pycfg> [opts]', 'Create a VDI'),
'vdi-list' : ('', 'List all VDI'),
'vdi-rename': ('<vdi_uuid> <new_name>', 'Rename VDI'),
'vdi-destroy': ('<vdi_uuid>', 'Delete VDI'),
'vif-create': ('<domname> <pycfg>', 'Create VIF attached to domname'),
'vtpm-create' : ('<domname> <pycfg>', 'Create VTPM attached to domname'),
'vm-create': ('<pycfg>', 'Create VM with python config'),
'vm-destroy': ('<domname>', 'Delete VM'),
'vm-list': ('[--long]', 'List all domains.'),
'vm-name': ('<uuid>', 'Name of UUID.'),
'vm-shutdown': ('<name> [opts]', 'Shutdown VM with name'),
'vm-start': ('<name>', 'Start VM with name'),
'vm-uuid': ('<name>', 'UUID of a domain by name.'),
'async-vm-start': ('<name>', 'Start VM asynchronously'),
}
OPTIONS = {
'sr-list': [(('-l', '--long'),
{'action':'store_true',
'help':'List all properties of SR'})
],
'vdi-list': [(('-l', '--long'),
{'action':'store_true',
'help':'List all properties of VDI'})
],
'vif-list': [(('-l', '--long'),
{'action':'store_true',
'help':'List all properties of VIF'})
],
'vm-list': [(('-l', '--long'),
{'action':'store_true',
'help':'List all properties of VMs'})
],
'vm-shutdown': [(('-f', '--force'), {'help': 'Shutdown Forcefully',
'action': 'store_true'})],
'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
(('--name-description',), {'help': 'Description for VDI'}),
(('--virtual-size',), {'type': 'int',
'default': 0,
'help': 'Size of VDI in bytes'}),
(('--type',), {'choices': ['system', 'user', 'ephemeral'],
'default': 'system',
'help': 'VDI type'}),
(('--sharable',), {'action': 'store_true',
'help': 'VDI sharable'}),
(('--read-only',), {'action': 'store_true',
'help': 'Read only'}),
(('--sr',), {})],
'vbd-create': [(('--VDI',), {'help': 'UUID of VDI to attach to.'}),
(('--mode',), {'choices': ['RO', 'RW'],
'help': 'device mount mode'}),
(('--driver',), {'choices':['paravirtualised', 'ioemu'],
'help': 'Driver for VBD'}),
(('--device',), {'help': 'Device name on guest domain'})]
}
class OptionError(Exception):
pass
class XenAPIError(Exception):
pass
#
# Extra utility functions
#
class IterableValues(Values):
"""Better interface to the list of values from optparse."""
def __iter__(self):
for opt, val in self.__dict__.items():
if opt[0] == '_' or callable(val):
continue
yield opt, val
def parse_args(cmd_name, args, set_defaults = False):
argstring, desc = COMMANDS[cmd_name]
parser = OptionParser(usage = 'xapi %s %s' % (cmd_name, argstring),
description = desc)
if cmd_name in OPTIONS:
for optargs, optkwds in OPTIONS[cmd_name]:
parser.add_option(*optargs, **optkwds)
if set_defaults:
default_values = parser.get_default_values()
defaults = IterableValues(default_values.__dict__)
else:
defaults = IterableValues()
(opts, extraargs) = parser.parse_args(args = list(args),
values = defaults)
return opts, extraargs
def execute(server, fn, args, async = False):
if async:
func = eval('server.Async.%s' % fn)
else:
func = eval('server.%s' % fn)
result = func(*args)
if type(result) != DictType:
raise TypeError("Function returned object of type: %s" %
str(type(result)))
if 'Value' not in result:
raise XenAPIError(*result['ErrorDescription'])
return result['Value']
_initialised = False
_server = None
_session = None
def connect(*args):
global _server, _session, _initialised
if not _initialised:
# try without password or default credentials
try:
_server = ServerProxy(SERVER_URI)
_session = execute(_server.session, 'login_with_password',
(SERVER_USER, SERVER_PASS))
except:
login = raw_input("Login: ")
password = getpass()
creds = (login, password)
_server = ServerProxy(SERVER_URI)
_session = execute(_server.session, 'login_with_password',
creds)
_initialised = True
return (_server, _session)
def _stringify(adict):
return dict([(k, str(v)) for k, v in adict.items()])
def _read_python_cfg(filename):
cfg = {}
execfile(filename, {}, cfg)
return cfg
def resolve_vm(server, session, vm_name):
vm_uuid = execute(server, 'VM.get_by_name_label', (session, vm_name))
if not vm_uuid:
return None
else:
return vm_uuid[0]
def resolve_vdi(server, session, vdi_name):
vdi_uuid = execute(server, 'VDI.get_by_name_label', (session, vdi_name))
if not vdi_uuid:
return None
else:
return vdi_uuid[0]
#
# Actual commands
#
def xapi_host_info(args, async = False):
server, session = connect()
hosts = execute(server, 'host.get_all', (session,))
for host in hosts: # there is only one, but ..
hostinfo = execute(server, 'host.get_record', (session, host))
print HOST_INFO_FORMAT % ('Name', hostinfo['name_label'])
print HOST_INFO_FORMAT % ('Version', hostinfo['software_version'])
print HOST_INFO_FORMAT % ('CPUs', len(hostinfo['host_CPUs']))
print HOST_INFO_FORMAT % ('VMs', len(hostinfo['resident_VMs']))
print HOST_INFO_FORMAT % ('UUID', host)
for host_cpu_uuid in hostinfo['host_CPUs']:
host_cpu = execute(server, 'host_cpu.get_record',
(session, host_cpu_uuid))
print 'CPU %s Util: %.2f' % (host_cpu['number'],
float(host_cpu['utilisation']))
def xapi_host_set_name(args, async = False):
if len(args) < 1:
raise OptionError("No hostname specified")
server, session = connect()
hosts = execute(server, 'host.get_all', (session,))
if len(hosts) > 0:
execute(server, 'host.set_name_label', (session, hosts[0], args[0]))
print 'Hostname: %s' % execute(server, 'host.get_name_label',
(session, hosts[0]))
def xapi_vm_uuid(args, async = False):
if len(args) < 1:
raise OptionError("No domain name specified")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
print vm_uuid
def xapi_vm_name(args, async = False):
if len(args) < 1:
raise OptionError("No UUID specified")
server, session = connect()
vm_name = execute(server, 'VM.get_name_label', (session, args[0]))
print vm_name
def xapi_vm_list(args, async = False):
opts, args = parse_args('vm-list', args, set_defaults = True)
is_long = opts and opts.long
list_only = args
server, session = connect()
vm_uuids = execute(server, 'VM.get_all', (session,))
if not is_long:
print VM_LIST_FORMAT % {'name_label':'Name',
'memory_actual':'Mem',
'VCPUs_number': 'VCPUs',
'power_state': 'State',
'uuid': 'UUID'}
for uuid in vm_uuids:
vm_info = execute(server, 'VM.get_record', (session, uuid))
# skip domain if we don't want
if list_only and vm_info['name_label'] not in list_only:
continue
if is_long:
vbds = vm_info['VBDs']
vifs = vm_info['VIFs']
vtpms = vm_info['VTPMs']
vif_infos = []
vbd_infos = []
vtpm_infos = []
for vbd in vbds:
vbd_info = execute(server, 'VBD.get_record', (session, vbd))
vbd_infos.append(vbd_info)
for vif in vifs:
vif_info = execute(server, 'VIF.get_record', (session, vif))
vif_infos.append(vif_info)
for vtpm in vtpms:
vtpm_info = execute(server, 'VTPM.get_record', (session, vtpm))
vtpm_infos.append(vtpm_info)
vm_info['VBDs'] = vbd_infos
vm_info['VIFs'] = vif_infos
vm_info['VTPMs'] = vtpm_infos
pprint(vm_info)
else:
print VM_LIST_FORMAT % _stringify(vm_info)
def xapi_vm_create(args, async = False):
if len(args) < 1:
raise OptionError("Configuration file not specified")
filename = args[0]
cfg = _read_python_cfg(filename)
print 'Creating VM from %s ..' % filename
server, session = connect()
uuid = execute(server, 'VM.create', (session, cfg), async = async)
print 'Done. (%s)' % uuid
print uuid
def xapi_vm_destroy(args, async = False):
if len(args) < 1:
raise OptionError("No domain name specified.")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
print 'Destroying VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.destroy', (session, vm_uuid), async = async)
print 'Done.'
def xapi_vm_start(args, async = False):
if len(args) < 1:
raise OptionError("No Domain name specified.")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
print 'Starting VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.start', (session, vm_uuid, False), async = async)
if async:
print 'Task started: %s' % success
else:
print 'Done.'
def xapi_vm_suspend(args, async = False):
if len(args) < 1:
raise OptionError("No Domain name specified.")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
print 'Suspending VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.suspend', (session, vm_uuid), async = async)
if async:
print 'Task started: %s' % success
else:
print 'Done.'
def xapi_vm_resume(args, async = False):
if len(args) < 1:
raise OptionError("No Domain name specified.")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
print 'Resuming VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.resume', (session, vm_uuid, False), async = async)
if async:
print 'Task started: %s' % success
else:
print 'Done.'
def xapi_vm_pause(args, async = False):
if len(args) < 1:
raise OptionError("No Domain name specified.")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.pause', (session, vm_uuid), async = async)
if async:
print 'Task started: %s' % success
else:
print 'Done.'
def xapi_vm_unpause(args, async = False):
if len(args) < 1:
raise OptionError("No Domain name specified.")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
print 'Pausing VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.unpause', (session, vm_uuid), async = async)
if async:
print 'Task started: %s' % success
else:
print 'Done.'
def xapi_task_list(args, async = False):
server, session = connect()
all_tasks = execute(server, 'task.get_all', (session,))
print TASK_LIST_FORMAT % {'name_label': 'Task Name',
'uuid': 'UUID',
'status': 'Status',
'progress': '%'}
for task_uuid in all_tasks:
task = execute(server, 'task.get_record', (session, task_uuid))
print TASK_LIST_FORMAT % task
def xapi_task_clear(args, async = False):
server, session = connect()
all_tasks = execute(server, 'task.get_all', (session,))
for task_uuid in all_tasks:
success = execute(server, 'task.destroy', (session, task_uuid))
print 'Destroyed Task %s' % task_uuid
def xapi_vm_shutdown(args, async = False):
opts, args = parse_args("vm-shutdown", args, set_defaults = True)
if len(args) < 1:
raise OptionError("No Domain name specified.")
server, session = connect()
vm_uuid = resolve_vm(server, session, args[0])
if opts.force:
print 'Forcefully shutting down VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.hard_shutdown', (session, vm_uuid), async = async)
else:
print 'Shutting down VM %s (%s)' % (args[0], vm_uuid)
success = execute(server, 'VM.clean_shutdown', (session, vm_uuid), async = async)
if async:
print 'Task started: %s' % success
else:
print 'Done.'
def xapi_vbd_create(args, async = False):
opts, args = parse_args('vbd-create', args)
if len(args) < 2:
raise OptionError("Configuration file and domain not specified")
domname = args[0]
if len(args) > 1:
filename = args[1]
cfg = _read_python_cfg(filename)
else:
cfg = {}
for opt, val in opts:
cfg[opt] = val
print 'Creating VBD ...',
server, session = connect()
vm_uuid = resolve_vm(server, session, domname)
cfg['VM'] = vm_uuid
vbd_uuid = execute(server, 'VBD.create', (session, cfg), async = async)
if async:
print 'Task started: %s' % vbd_uuid
else:
print 'Done. (%s)' % vbd_uuid
def xapi_vif_create(args, async = False):
if len(args) < 2:
raise OptionError("Configuration file not specified")
domname = args[0]
filename = args[1]
cfg = _read_python_cfg(filename)
print 'Creating VIF from %s ..' % filename
server, session = connect()
vm_uuid = resolve_vm(server, session, domname)
cfg['VM'] = vm_uuid
vif_uuid = execute(server, 'VIF.create', (session, cfg), async = async)
if async:
print 'Task started: %s' % vif_uuid
else:
print 'Done. (%s)' % vif_uuid
def xapi_vbd_list(args, async = False):
server, session = connect()
domname = args[0]
dom_uuid = resolve_vm(server, session, domname)
vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
print VBD_LIST_FORMAT % {'device': 'Device',
'uuid' : 'UUID',
'VDI': 'VDI'}
for vbd in vbds:
vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
print VBD_LIST_FORMAT % vbd_struct
def xapi_vbd_stats(args, async = False):
server, session = connect()
domname = args[0]
dom_uuid = resolve_vm(server, session, domname)
vbds = execute(server, 'VM.get_VBDs', (session, dom_uuid))
for vbd_uuid in vbds:
print execute(server, 'VBD.get_io_read_kbs', (session, vbd_uuid))
def xapi_vif_list(args, async = False):
server, session = connect()
opts, args = parse_args('vdi-list', args, set_defaults = True)
is_long = opts and opts.long
domname = args[0]
dom_uuid = resolve_vm(server, session, domname)
vifs = execute(server, 'VM.get_VIFs', (session, dom_uuid))
if not is_long:
print VIF_LIST_FORMAT % {'name': 'Name',
'device': 'Device',
'uuid' : 'UUID',
'MAC': 'MAC'}
for vif in vifs:
vif_struct = execute(server, 'VIF.get_record', (session, vif))
print VIF_LIST_FORMAT % vif_struct
else:
for vif in vifs:
vif_struct = execute(server, 'VIF.get_record', (session, vif))
pprint(vif_struct)
def xapi_console_list(args, async = False):
server, session = connect()
opts, args = parse_args('vdi-list', args, set_defaults = True)
is_long = opts and opts.long
domname = args[0]
dom_uuid = resolve_vm(server, session, domname)
consoles = execute(server, 'VM.get_consoles', (session, dom_uuid))
if not is_long:
print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol',
'location': 'Location',
'uuid': 'UUID'}
for console in consoles:
console_struct = execute(server, 'console.get_record',
(session, console))
print CONSOLE_LIST_FORMAT % console_struct
else:
for console in consoles:
console_struct = execute(server, 'console.get_record',
(session, console))
pprint(console_struct)
def xapi_vdi_list(args, async = False):
opts, args = parse_args('vdi-list', args, set_defaults = True)
is_long = opts and opts.long
server, session = connect()
vdis = execute(server, 'VDI.get_all', (session,))
if not is_long:
print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
'uuid' : 'UUID',
'virtual_size': 'Bytes'}
for vdi in vdis:
vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
print VDI_LIST_FORMAT % vdi_struct
else:
for vdi in vdis:
vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
pprint(vdi_struct)
def xapi_sr_list(args, async = False):
opts, args = parse_args('sr-list', args, set_defaults = True)
is_long = opts and opts.long
server, session = connect()
srs = execute(server, 'SR.get_all', (session,))
if not is_long:
print SR_LIST_FORMAT % {'name_label': 'SR Label',
'uuid' : 'UUID',
'physical_size': 'Size (MB)',
'type': 'Type'}
for sr in srs:
sr_struct = execute(server, 'SR.get_record', (session, sr))
sr_struct['physical_size'] = int(sr_struct['physical_size'])/MB
print SR_LIST_FORMAT % sr_struct
else:
for sr in srs:
sr_struct = execute(server, 'SR.get_record', (session, sr))
pprint(sr_struct)
def xapi_sr_rename(args, async = False):
server, session = connect()
sr = execute(server, 'SR.get_by_name_label', (session, args[0]))
execute(server, 'SR.set_name_label', (session, sr[0], args[1]))
def xapi_vdi_create(args, async = False):
opts, args = parse_args('vdi-create', args)
if len(args) > 0:
cfg = _read_python_cfg(args[0])
else:
cfg = {}
for opt, val in opts:
cfg[opt] = val
server, session = connect()
srs = []
if cfg.get('SR'):
srs = execute(server, 'SR.get_by_name_label', (session, cfg['SR']))
else:
srs = execute(server, 'SR.get_all', (session,))
sr = srs[0]
cfg['SR'] = sr
size = cfg['virtual_size']/MB
print 'Creating VDI of size: %dMB ..' % size,
uuid = execute(server, 'VDI.create', (session, cfg), async = async)
if async:
print 'Task started: %s' % uuid
else:
print 'Done. (%s)' % uuid
def xapi_vdi_destroy(args, async = False):
server, session = connect()
if len(args) < 1:
raise OptionError('Not enough arguments')
vdi_uuid = args[0]
print 'Deleting VDI %s' % vdi_uuid
result = execute(server, 'VDI.destroy', (session, vdi_uuid), async = async)
if async:
print 'Task started: %s' % result
else:
print 'Done.'
def xapi_vdi_rename(args, async = False):
server, session = connect()
if len(args) < 2:
raise OptionError('Not enough arguments')
vdi_uuid = execute(server, 'VDI.get_by_name_label', session, args[0])
vdi_name = args[1]
print 'Renaming VDI %s to %s' % (vdi_uuid[0], vdi_name)
result = execute(server, 'VDI.set_name_label',
(session, vdi_uuid[0], vdi_name), async = async)
if async:
print 'Task started: %s' % result
else:
print 'Done.'
def xapi_vtpm_create(args, async = False):
server, session = connect()
domname = args[0]
cfg = _read_python_cfg(args[1])
vm_uuid = resolve_vm(server, session, domname)
cfg['VM'] = vm_uuid
print "Creating vTPM with cfg = %s" % cfg
vtpm_uuid = execute(server, 'VTPM.create', (session, cfg))
print "Done. (%s)" % vtpm_uuid
def xapi_pif_list(args, async = False):
server, session = connect()
pif_uuids = execute(server, 'PIF.get_all', (session,))
for pif_uuid in pif_uuids:
pif = execute(server, 'PIF.get_record', (session, pif_uuid))
print pif
def xapi_debug_wait(args, async = False):
secs = 10
if len(args) > 0:
secs = int(args[0])
server, session = connect()
task_uuid = execute(server, 'debug.wait', (session, secs), async=async)
print 'Task UUID: %s' % task_uuid
def xapi_vm_stat(args, async = False):
domname = args[0]
server, session = connect()
vm_uuid = resolve_vm(server, session, domname)
vif_uuids = execute(server, 'VM.get_VIFs', (session, vm_uuid))
vbd_uuids = execute(server, 'VM.get_VBDs', (session, vm_uuid))
vcpus_utils = execute(server, 'VM.get_VCPUs_utilisation',
(session, vm_uuid))
for vcpu_num in sorted(vcpus_utils.keys()):
print 'CPU %s : %5.2f%%' % (vcpu_num, vcpus_utils[vcpu_num] * 100)
for vif_uuid in vif_uuids:
vif = execute(server, 'VIF.get_record', (session, vif_uuid))
print '%(device)s: rx: %(io_read_kbs)10.2f tx: %(io_write_kbs)10.2f' \
% vif
for vbd_uuid in vbd_uuids:
vbd = execute(server, 'VBD.get_record', (session, vbd_uuid))
print '%(device)s: rd: %(io_read_kbs)10.2f wr: %(io_write_kbs)10.2f' \
% vbd
#
# Command Line Utils
#
import cmd
import shlex
class XenAPICmd(cmd.Cmd):
def __init__(self, server, session):
cmd.Cmd.__init__(self)
self.server = server
self.session = session
self.prompt = ">>> "
def default(self, line):
words = shlex.split(line)
if len(words) > 0:
cmd_name = words[0].replace('-', '_')
is_async = 'async' in cmd_name
if is_async:
cmd_name = re.sub('async_', '', cmd_name)
func_name = 'xapi_%s' % cmd_name
func = globals().get(func_name)
if func:
try:
args = tuple(words[1:])
func(args, async = is_async)
return True
except SystemExit:
return False
except OptionError, e:
print 'Error:', str(e)
return False
except Exception, e:
import traceback
traceback.print_exc()
return False
print '*** Unknown command: %s' % words[0]
return False
def do_EOF(self, line):
print
sys.exit(0)
def do_help(self, line):
usage(print_usage = False)
def emptyline(self):
pass
def postcmd(self, stop, line):
return False
def precmd(self, line):
words = shlex.split(line)
if len(words) > 0:
words0 = words[0].replace('-', '_')
return ' '.join([words0] + words[1:])
else:
return line
def shell():
server, session = connect()
x = XenAPICmd(server, session)
x.cmdloop('Xen API Prompt. Type "help" for a list of functions')
def usage(command = None, print_usage = True):
if not command:
if print_usage:
print 'Usage: xapi <subcommand> [options] [args]'
print
print 'Subcommands:'
print
for func in sorted(globals().keys()):
if func.startswith('xapi_'):
command = func[5:].replace('_', '-')
args, description = COMMANDS.get(command, ('', ''))
print '%-16s %-40s' % (command, description)
print
else:
parse_args(command, ['-h'])
def main(args):
# poor man's optparse that doesn't abort on unrecognised opts
options = {}
remaining = []
arg_n = 0
while args:
arg = args.pop(0)
if arg in ('--help', '-h'):
options['help'] = True
elif arg in ('--server', '-s') and args:
options['server'] = args.pop(0)
elif arg in ('--user', '-u') and args:
options['user'] = args.pop(0)
elif arg in ('--password', '-p') and args:
options['password'] = args.pop(0)
else:
remaining.append(arg)
# abort here if these conditions are true
if options.get('help') and not remaining:
usage()
sys.exit(1)
if options.get('help') and remaining:
usage(remaining[0])
sys.exit(1)
if not remaining:
usage()
sys.exit(1)
if options.get('server'):
# it is ugly to use a global, but it is simple
global SERVER_URI
SERVER_URI = options['server']
if options.get('user'):
global SERVER_USER
SERVER_USER = options['user']
if options.get('password'):
global SERVER_PASS
SERVER_PASS = options['password']
subcmd = remaining[0].replace('-', '_')
is_async = 'async' in subcmd
if is_async:
subcmd = re.sub('async_', '', subcmd)
subcmd_func_name = 'xapi_' + subcmd
subcmd_func = globals().get(subcmd_func_name, None)
if subcmd == 'shell':
shell()
elif not subcmd_func or not callable(subcmd_func):
print 'Error: Unable to find subcommand \'%s\'' % subcmd
usage()
sys.exit(1)
try:
subcmd_func(remaining[1:], async = is_async)
except XenAPIError, e:
print 'Error: %s' % str(e.args[0])
sys.exit(2)
except OptionError, e:
print 'Error: %s' % e
sys.exit(0)
if __name__ == "__main__":
import sys
main(sys.argv[1:])