mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
tools/python: Remove some legacy scripts
Nothing in scripts/ is referenced by the current Xen build system. It is a legacy version of the XenAPI bindings, other parts of which have already been removed from the tree. Additionally, prevent the install target from creating an $(SBINDIR) directory but putting nothing in it. This appears to be something missed when removing Xend. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> CC: Ian Campbell <Ian.Campbell@citrix.com> CC: Ian Jackson <Ian.Jackson@eu.citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
6b70cb9ff8
commit
1747fc59d6
13 files changed
-1772
No files matched your search
@@ -1,49 +0,0 @@
|
||||
Xen API Test
|
||||
============
|
||||
|
||||
xapi.py is a simple command line tool to test the functionality of a
|
||||
domain lifecycle supporting, Xen API talking version of Xend.
|
||||
|
||||
Creating a VM is slightly more work under the Xen API. The differences
|
||||
with this and xm is:
|
||||
|
||||
1. None of the devices are created during vm-create. You must use
|
||||
vbd-create and vif-create to attach a new device to the VM.
|
||||
|
||||
2. VM's that are created using vm-create will not start by
|
||||
default. You must use vm-start to "start" the domain.
|
||||
|
||||
3. VM's that are created using vm-create will not be removed on
|
||||
shutdown. You must remove it using vm-delete.
|
||||
|
||||
Example Configuration Files
|
||||
---------------------------
|
||||
|
||||
xapi.py uses a simple python configuration file similar to xm in the
|
||||
face of the lack of any other reasonable format.
|
||||
|
||||
All the fields are directly mapped to the arguments that are in the
|
||||
Xen API constructore for the respective classes.
|
||||
|
||||
xapi.domcfg.py: example configuration for a paravirtualised domain.
|
||||
xapi.vbdcfg.py: example configuration for a file based block device.
|
||||
xapi.vifcfg.py: example configuration for a simple bridged network
|
||||
device.
|
||||
|
||||
Example Session
|
||||
---------------
|
||||
|
||||
xapi.py vm-list
|
||||
xapi.py vm-create xapi.domcfg.py
|
||||
xapi.py vbd-create <DomainName> xapi.vbdcfg.py
|
||||
xapi.py vif-create <DomainName> xapi.vifcfg.py
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
Currently lacking:
|
||||
|
||||
1. Any real authentication. XendAuthSessions need to be filled in with
|
||||
a proper authentication implementation either using PAM or other
|
||||
means.
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
Xend Lifecycle/XenAPI Implementation Changes
|
||||
============================================
|
||||
|
||||
Summary of what has changed in this branch of Xend:
|
||||
|
||||
Managed Domains
|
||||
---------------
|
||||
|
||||
The concept of managed domains is that Xend now has the ability to
|
||||
manage the lifecycle of a domain from when it is created to being
|
||||
shutdown.
|
||||
|
||||
XendDomain
|
||||
~~~~~~~~~~
|
||||
|
||||
In order to support managed domains, XendDomain has been modified to
|
||||
keep the configuration in /var/lib/xend/domains/.
|
||||
|
||||
The configuration is stored in SXP format so that it can be easily
|
||||
loaded by the current Xend. In the future, we may switch to an XML
|
||||
format similar to how XenAPI defines a VM configuration.
|
||||
|
||||
TODO: There are still places where the device configuration or VM
|
||||
configuration can be altered but the managed domain does not save it.
|
||||
|
||||
XendDomainInfo
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
XendDomainInfo has changed to support this mode of operation,
|
||||
especially with domain construction and assumptions about the domain
|
||||
when it shuts down.
|
||||
|
||||
All configuration option parsing and validation has been moved from
|
||||
XendDomainInfo to XendConfig. The purpose is so that we can abstract
|
||||
away the knowledge of SXP in XendDomainInfo. The goal is to do away
|
||||
with the bulky way of accessing SXP in Xend and moving that all to a
|
||||
more pythonic interface.
|
||||
|
||||
The DevController stuff at the end of XendDomainInfo has also been
|
||||
moved to XendDevices because now it is needed in both XendConfig and
|
||||
XendDomainInfo.
|
||||
|
||||
Many of the constants are moved to XendConstants which reduces the
|
||||
amount of recursive or scoped imports that occur in the code.
|
||||
|
||||
XendConfig
|
||||
~~~~~~~~~~
|
||||
|
||||
XendConfig is the beginnings of an interface for configuration options
|
||||
so that other parts of Xend do not need to know what format the
|
||||
configuration in. It can accept configuration passed in as parsed SXP
|
||||
format, python filename or a Xen API struct.
|
||||
|
||||
It is a subclass of a python dictionary, and hence access to its
|
||||
functions are via the __getitem__ accessor.
|
||||
|
||||
TODO: Define a proper interface to the XendConfig which is based on
|
||||
either the Xen API or some other flexible format.
|
||||
|
||||
XMLRPCServer
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Changes to the busy loop in here and SrvServer so that the daemon
|
||||
shuts down cleanly. This also allows us to catch the shutdown and
|
||||
perform maintanence tasks on the domains.
|
||||
|
||||
Replacing xendomains init.d script
|
||||
==================================
|
||||
|
||||
Some work has gone into catching Xend's shutdown so that we can do the
|
||||
same tasks that xendomains init.d script does but natively in Xend.
|
||||
|
||||
For instance, a new configuration option, 'on_xend_start' and
|
||||
'on_xend_stop' will allow domains that are managed by Xend to start up
|
||||
when Xend starts, and correspondingly stop when Xend stops.
|
||||
|
||||
Xen API
|
||||
=======
|
||||
|
||||
The new Xen API gives a standard interface to creating, configuring,
|
||||
controlling and destroying VMs and the virtual devices that belong to
|
||||
it.
|
||||
|
||||
It also introduces the concept of Storage Repositories (SR) which are
|
||||
factories for creating disk images.
|
||||
|
||||
XendDomain
|
||||
~~~~~~~~~~
|
||||
|
||||
XendDomain has now separated the section for the Legacy XM XMLRPC API
|
||||
and the new Xen API.
|
||||
|
||||
Since many things have a UUID, these are stored and represented as
|
||||
close to the existing configuration.
|
||||
|
||||
XendDomainInfo
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
XendDomainInfo now supports UUIDs being assigned to devices and the
|
||||
domain itself. It will preserve the UUID for managed domains.
|
||||
|
||||
A number of new functions are now in XendDomainInfo to provide an
|
||||
interface to devices.
|
||||
|
||||
XendNode
|
||||
~~~~~~~~
|
||||
|
||||
Represents the Host class in the Xen API and also contains an
|
||||
incomplete representation of the physical CPUs availabel for the host.
|
||||
|
||||
XendAuthSessions
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
An abstract authenticator for the Xen API. Currently it is an empty
|
||||
implementation with rudimentary support for users. The plan is the add
|
||||
PAM based authentication.
|
||||
|
||||
XendAPI
|
||||
~~~~~~~
|
||||
|
||||
The guts of the Xen API implementation. Implements all the supported
|
||||
functionality of the Xen API by placing calls to the relevent objects
|
||||
like XendDomain and XendDomanInfo.
|
||||
|
||||
The initialisation of the XendAPI object will actually install a
|
||||
number of validation decorators in order to ensure the input is
|
||||
correct. It is using some features of introspection and
|
||||
metaprogramming in Python to reduce the amount of replication in the
|
||||
code.
|
||||
|
||||
XMLRPCServer
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The XMLRPC Server will support both the new Xen API and the old XM
|
||||
XMLRPC API. The support is clearly marked in the code.
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
vm_cfg = {
|
||||
'name_label': 'API_HVM',
|
||||
'user_version': 1,
|
||||
'is_a_template': False,
|
||||
'auto_power_on': False, # TODO
|
||||
|
||||
'memory_static_min': 64,
|
||||
'memory_static_max': 128,
|
||||
#'memory_dynamic_min': 64,
|
||||
#'memory_dynamic_max': 128,
|
||||
|
||||
|
||||
'VCPUs_policy': 'credit',
|
||||
'VCPUs_params': {},
|
||||
'VCPUs_number': 2,
|
||||
|
||||
'actions_after_shutdown': 'destroy',
|
||||
'actions_after_reboot': 'restart',
|
||||
'actions_after_crash': 'destroy',
|
||||
|
||||
'PV_bootloader': '',
|
||||
'PV_bootloader_args': '',
|
||||
|
||||
'PV_kernel': '',
|
||||
'PV_ramdisk': '',
|
||||
'PV_args': '',
|
||||
|
||||
'HVM_boot': 'cda',
|
||||
'platform_std_VGA': False,
|
||||
'platform_serial': '',
|
||||
'platform_localtime': False,
|
||||
'platform_clock_offset': False,
|
||||
'platform_enable_audio': False,
|
||||
'PCI_bus': ''
|
||||
}
|
||||
|
||||
local_vdi_cfg = {
|
||||
'name_label': 'gentoo.hvm',
|
||||
'name_description': '',
|
||||
'virtual_size': 0,
|
||||
'type': 'system',
|
||||
'parent': '',
|
||||
'SR_name': 'Local',
|
||||
'sharable': False,
|
||||
'read_only': False,
|
||||
'other_config': {'location': 'file:/root/gentoo.amd64.hvm.img'},
|
||||
}
|
||||
|
||||
local_vbd_cfg = {
|
||||
'VDI': '',
|
||||
'VM': '',
|
||||
'device': 'hda',
|
||||
'mode': 'RW',
|
||||
'type': 'disk',
|
||||
'driver': 'ioemu',
|
||||
}
|
||||
|
||||
vif_cfg = {
|
||||
'name': 'API_VIF',
|
||||
'type': 'ioemu',
|
||||
'device': '',
|
||||
'network': '',
|
||||
'MAC': '',
|
||||
'MTU': 1500,
|
||||
}
|
||||
|
||||
console_cfg = {
|
||||
'protocol': 'rfb',
|
||||
'other_config': {'vncunused': 1, 'vncpasswd': 'testing'},
|
||||
}
|
||||
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
from xapi import connect, execute
|
||||
|
||||
def test_vm_create():
|
||||
server, session = connect()
|
||||
vm_uuid = None
|
||||
local_vdi_uuid = None
|
||||
local_vbd_uuid = None
|
||||
vif_uuid = None
|
||||
|
||||
# List all VMs
|
||||
vm_list = execute(server, 'VM.get_all', (session,))
|
||||
vm_names = []
|
||||
for vm_uuid in vm_list:
|
||||
vm_record = execute(server, 'VM.get_record', (session, vm_uuid))
|
||||
vm_names.append(vm_record['name_label'])
|
||||
|
||||
# Get default SR
|
||||
local_sr_list = execute(server, 'SR.get_by_name_label',
|
||||
(session, local_vdi_cfg['SR_name']))
|
||||
local_sr_uuid = local_sr_list[0]
|
||||
|
||||
# Get default network
|
||||
net_list = execute(server, 'network.get_all', (session,))
|
||||
net_uuid = net_list[0]
|
||||
|
||||
try:
|
||||
# Create a new VM
|
||||
print 'Create VM'
|
||||
vm_uuid = execute(server, 'VM.create', (session, vm_cfg))
|
||||
|
||||
print 'Create VDI'
|
||||
# Create a new VDI (Local)
|
||||
local_vdi_cfg['SR'] = local_sr_uuid
|
||||
local_vdi_uuid = execute(server, 'VDI.create',
|
||||
(session, local_vdi_cfg))
|
||||
|
||||
print 'Create VBD'
|
||||
# Create a new VBD (Local)
|
||||
local_vbd_cfg['VM'] = vm_uuid
|
||||
local_vbd_cfg['VDI'] = local_vdi_uuid
|
||||
local_vbd_uuid = execute(server, 'VBD.create',
|
||||
(session, local_vbd_cfg))
|
||||
|
||||
print 'Craete VIF'
|
||||
# Create a new VIF
|
||||
vif_cfg['network'] = net_uuid
|
||||
vif_cfg['VM'] = vm_uuid
|
||||
vif_uuid = execute(server, 'VIF.create', (session, vif_cfg))
|
||||
|
||||
# Create a console
|
||||
console_cfg['VM'] = vm_uuid
|
||||
console_uuid = execute(server, 'console.create',
|
||||
(session, console_cfg))
|
||||
print console_uuid
|
||||
|
||||
# Start the VM
|
||||
execute(server, 'VM.start', (session, vm_uuid, False))
|
||||
|
||||
time.sleep(30)
|
||||
|
||||
test_suspend = False
|
||||
if test_suspend:
|
||||
print 'Suspending VM..'
|
||||
execute(server, 'VM.suspend', (session, vm_uuid))
|
||||
print 'Suspended VM.'
|
||||
time.sleep(5)
|
||||
print 'Resuming VM ...'
|
||||
execute(server, 'VM.resume', (session, vm_uuid, False))
|
||||
print 'Resumed VM.'
|
||||
|
||||
# Wait for user to say we're good to shut it down
|
||||
while True:
|
||||
destroy = raw_input('destroy VM? ')
|
||||
if destroy[0] in ('y', 'Y'):
|
||||
break
|
||||
|
||||
finally:
|
||||
# Clean up
|
||||
if vif_uuid:
|
||||
execute(server, 'VIF.destroy', (session, vif_uuid))
|
||||
|
||||
if local_vbd_uuid:
|
||||
execute(server, 'VBD.destroy', (session, local_vbd_uuid))
|
||||
if local_vdi_uuid:
|
||||
execute(server, 'VDI.destroy', (session, local_vdi_uuid))
|
||||
|
||||
if vm_uuid:
|
||||
try:
|
||||
execute(server, 'VM.hard_shutdown', (session, vm_uuid))
|
||||
time.sleep(2)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
execute(server, 'VM.destroy', (session, vm_uuid))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_vm_create()
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
vm_cfg = {
|
||||
'name_label': 'APIVM',
|
||||
'user_version': 1,
|
||||
'is_a_template': False,
|
||||
'auto_power_on': False, # TODO
|
||||
|
||||
'memory_static_min': 64,
|
||||
'memory_static_max': 128,
|
||||
#'memory_dynamic_min': 64,
|
||||
#'memory_dynamic_max': 128,
|
||||
|
||||
|
||||
'VCPUs_policy': 'credit',
|
||||
'VCPUs_params': '',
|
||||
'VCPUs_number': 2,
|
||||
|
||||
'actions_after_shutdown': 'destroy',
|
||||
'actions_after_reboot': 'restart',
|
||||
'actions_after_crash': 'destroy',
|
||||
|
||||
'PV_bootloader': '',
|
||||
'PV_bootloader_args': '',
|
||||
|
||||
'PV_kernel': '/boot/vmlinuz-2.6.18-xenU',
|
||||
'PV_ramdisk': '',
|
||||
'PV_args': 'root=/dev/sda1 ro',
|
||||
|
||||
#'HVM_boot': '',
|
||||
'platform_std_VGA': False,
|
||||
'platform_serial': '',
|
||||
'platform_localtime': False,
|
||||
'platform_clock_offset': False,
|
||||
'platform_enable_audio': False,
|
||||
'PCI_bus': ''
|
||||
}
|
||||
|
||||
vdi_cfg = {
|
||||
'name_label': 'API_VDI',
|
||||
'name_description': '',
|
||||
'virtual_size': 100 * 1024 * 1024 * 1024,
|
||||
'type': 'system',
|
||||
'parent': '',
|
||||
'SR_name': 'QCoW',
|
||||
'sharable': False,
|
||||
'read_only': False,
|
||||
}
|
||||
|
||||
vbd_cfg = {
|
||||
'VDI': '',
|
||||
'VM': '',
|
||||
'device': 'sda2',
|
||||
'mode': 'RW',
|
||||
'type': 'disk',
|
||||
'driver': 'paravirtualised',
|
||||
}
|
||||
|
||||
local_vdi_cfg = {
|
||||
'name_label': 'gentoo.amd64.img',
|
||||
'name_description': '',
|
||||
'virtual_size': 0,
|
||||
'type': 'system',
|
||||
'parent': '',
|
||||
'SR_name': 'Local',
|
||||
'sharable': False,
|
||||
'read_only': False,
|
||||
'other_config': {'location': 'file:/root/gentoo.amd64.img'},
|
||||
}
|
||||
|
||||
local_vbd_cfg = {
|
||||
'VDI': '',
|
||||
'VM': '',
|
||||
'device': 'sda1',
|
||||
'mode': 'RW',
|
||||
'type': 'disk',
|
||||
'driver': 'paravirtualised',
|
||||
}
|
||||
|
||||
vif_cfg = {
|
||||
'name': 'API_VIF',
|
||||
'type': 'paravirtualised',
|
||||
'device': '',
|
||||
'network': '',
|
||||
'MAC': '',
|
||||
'MTU': 1500,
|
||||
}
|
||||
|
||||
console_cfg = {
|
||||
'protocol': 'rfb',
|
||||
'other_config': {'vncunused': 1, 'vncpasswd': 'testing'},
|
||||
}
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
from xapi import connect, execute
|
||||
|
||||
def test_vm_create():
|
||||
server, session = connect()
|
||||
vm_uuid = None
|
||||
vdi_uuid = None
|
||||
local_vdi_uuid = None
|
||||
local_vbd_uuid = None
|
||||
vbd_uuid = None
|
||||
vif_uuid = None
|
||||
|
||||
# List all VMs
|
||||
vm_list = execute(server, 'VM.get_all', (session,))
|
||||
vm_names = []
|
||||
for vm_uuid in vm_list:
|
||||
vm_record = execute(server, 'VM.get_record', (session, vm_uuid))
|
||||
vm_names.append(vm_record['name_label'])
|
||||
|
||||
# Get default SR
|
||||
sr_list = execute(server, 'SR.get_by_name_label', (session,
|
||||
vdi_cfg['SR_name']))
|
||||
sr_uuid = sr_list[0]
|
||||
|
||||
local_sr_list = execute(server, 'SR.get_by_name_label',
|
||||
(session, local_vdi_cfg['SR_name']))
|
||||
local_sr_uuid = local_sr_list[0]
|
||||
|
||||
# Get default network
|
||||
net_list = execute(server, 'network.get_all', (session,))
|
||||
net_uuid = net_list[0]
|
||||
|
||||
try:
|
||||
# Create a new VM
|
||||
vm_uuid = execute(server, 'VM.create', (session, vm_cfg))
|
||||
|
||||
# Create a new VDI
|
||||
vdi_cfg['SR'] = sr_uuid
|
||||
vdi_uuid = execute(server, 'VDI.create', (session, vdi_cfg))
|
||||
|
||||
# Create a VDI backed VBD
|
||||
vbd_cfg['VM'] = vm_uuid
|
||||
vbd_cfg['VDI'] = vdi_uuid
|
||||
vbd_uuid = execute(server, 'VBD.create', (session, vbd_cfg))
|
||||
|
||||
# Create a new VDI (Local)
|
||||
local_vdi_cfg['SR'] = local_sr_uuid
|
||||
local_vdi_uuid = execute(server, 'VDI.create',
|
||||
(session, local_vdi_cfg))
|
||||
|
||||
# Create a new VBD (Local)
|
||||
local_vbd_cfg['VM'] = vm_uuid
|
||||
local_vbd_cfg['VDI'] = local_vdi_uuid
|
||||
local_vbd_uuid = execute(server, 'VBD.create',
|
||||
(session, local_vbd_cfg))
|
||||
|
||||
# Create a new VIF
|
||||
vif_cfg['network'] = net_uuid
|
||||
vif_cfg['VM'] = vm_uuid
|
||||
vif_uuid = execute(server, 'VIF.create', (session, vif_cfg))
|
||||
|
||||
# Create a console
|
||||
console_cfg['VM'] = vm_uuid
|
||||
console_uuid = execute(server, 'console.create',
|
||||
(session, console_cfg))
|
||||
print console_uuid
|
||||
|
||||
# Start the VM
|
||||
execute(server, 'VM.start', (session, vm_uuid, False))
|
||||
|
||||
time.sleep(30)
|
||||
|
||||
test_suspend = False
|
||||
if test_suspend:
|
||||
print 'Suspending VM..'
|
||||
execute(server, 'VM.suspend', (session, vm_uuid))
|
||||
print 'Suspended VM.'
|
||||
time.sleep(5)
|
||||
print 'Resuming VM ...'
|
||||
execute(server, 'VM.resume', (session, vm_uuid, False))
|
||||
print 'Resumed VM.'
|
||||
|
||||
finally:
|
||||
# Wait for user to say we're good to shut it down
|
||||
while True:
|
||||
destroy = raw_input('destroy VM? ')
|
||||
if destroy[0] in ('y', 'Y'):
|
||||
break
|
||||
|
||||
# Clean up
|
||||
if vif_uuid:
|
||||
execute(server, 'VIF.destroy', (session, vif_uuid))
|
||||
|
||||
if local_vbd_uuid:
|
||||
execute(server, 'VBD.destroy', (session, local_vbd_uuid))
|
||||
if local_vdi_uuid:
|
||||
execute(server, 'VDI.destroy', (session, local_vdi_uuid))
|
||||
|
||||
if vbd_uuid:
|
||||
execute(server, 'VBD.destroy', (session, vbd_uuid))
|
||||
if vdi_uuid:
|
||||
execute(server, 'VDI.destroy', (session, vdi_uuid))
|
||||
|
||||
if vm_uuid:
|
||||
try:
|
||||
execute(server, 'VM.hard_shutdown', (session, vm_uuid))
|
||||
time.sleep(2)
|
||||
except:
|
||||
pass
|
||||
|
||||
execute(server, 'VM.destroy', (session, vm_uuid))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_vm_create()
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#
|
||||
# VM Configuration for Xen API
|
||||
#
|
||||
|
||||
name_label = 'GentooAPI'
|
||||
name_description = 'Gentoo VM via API'
|
||||
user_version = 1
|
||||
is_a_template = False
|
||||
memory_static_max = 32
|
||||
memory_dynamic_max = 32
|
||||
memory_dynamic_min = 32
|
||||
memory_static_min = 32
|
||||
VCPUs_policy = ''
|
||||
VCPUs_params = ''
|
||||
VCPUS_features_required = ''
|
||||
VCPUs_features_can_use = ''
|
||||
VCPUs_features_force_on = ''
|
||||
VCPUs_features_force_off = ''
|
||||
actions_after_shutdown = 'destroy'
|
||||
actions_after_reboot = 'restart'
|
||||
actions_after_suspend = 'destroy'
|
||||
actions_after_crash = 'restart'
|
||||
bios_boot = ''
|
||||
platform_std_VGA = False
|
||||
platform_serial = ''
|
||||
platform_localtime = False
|
||||
platform_clock_offset = False
|
||||
platform_enable_audio = False
|
||||
builder = 'linux'
|
||||
boot_method = '' # this will remove the kernel/initrd ??
|
||||
kernel_kernel = '/boot/vmlinuz-2.6.16.29-xen'
|
||||
kernel_initrd = '/root/initrd-2.6.16.29-xen.img'
|
||||
kernel_args = 'root=/dev/sda1 ro'
|
||||
grub_cmdline = ''
|
||||
PCI_bus = ''
|
||||
other_config = ''
|
||||
|
||||
@@ -1,854 +0,0 @@
|
||||
#!/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'),
|
||||
|
||||
'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']
|
||||
vif_infos = []
|
||||
vbd_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)
|
||||
vm_info['VBDs'] = vbd_infos
|
||||
vm_info['VIFs'] = vif_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_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:])
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# Virtual Block Device (VBD) Xen API Configuration
|
||||
#
|
||||
# Note: There is a non-API field here called "image" which is a backwards
|
||||
# compat addition so you can mount to old images.
|
||||
#
|
||||
|
||||
VDI = ''
|
||||
device = 'sda1'
|
||||
mode = 'RW'
|
||||
driver = 'paravirtualised'
|
||||
image = 'file:/root/gentoo.amd64.img'
|
||||
@@ -1,6 +0,0 @@
|
||||
name_label = 'VDI 1'
|
||||
name_description = ''
|
||||
virtual_size = 10 * 1024 * 1024 * 1024
|
||||
type = 'system'
|
||||
sharable = False
|
||||
read_only = False
|
||||
@@ -1,10 +0,0 @@
|
||||
#
|
||||
# Virtual Network Interface Configuration for the Xen API
|
||||
#
|
||||
|
||||
name = ''
|
||||
type = 'paravirtualised'
|
||||
#device = 'eth0' # this is the dom0 device, not domU!
|
||||
network = '' # ignored
|
||||
MAC = ''
|
||||
MTU = '1500'
|
||||
@@ -1,3 +0,0 @@
|
||||
type = 'paravirtualised'
|
||||
backend = 'Domain-0'
|
||||
instance = 1
|
||||