This section describes two complete examples of real programs using the API. The application source code is
contained within the SDK.
4.2.1. Simultaneously migrating VMs using XenMotion
This python example (contained in /SDK/client-examples/python/permute.py)
demonstrates
how to use XenMotion to move VMs simultaneously between hosts in a Resource Pool.
The example makes use of asynchronous API calls and shows how to wait for a set of tasks to complete.
The program begins with some standard boilerplate and imports the API bindings module
import sys, time
import XenAPI
Next the commandline arguments containing a server URL, username, password and a number
of iterations are parsed. The username and password are used to establish a session which is
passed to the function main, which is called multiple times in a loop.
Note the use of try: finally:
to make sure the program logs out of its session at the end.
if __name__ == "__main__":
if len(sys.argv) <> 5:
print "Usage:"
print sys.argv[0], " <url> <username> <password> <iterations>"
sys.exit(1)
url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
iterations = int(sys.argv[4])
# First acquire a valid session by logging in:
session = XenAPI.Session(url)
session.xenapi.login_with_password(username, password)
try:
for i in range(iterations):
main(session, i)
finally:
session.xenapi.session.logout()
The main function examines each running VM in the system, taking
care to filter out control domains (which are part of the system and not controllable
by the user). A list of running VMs and their current hosts is constructed.
def main(session, iteration):
# Find a non-template VM object
all = session.xenapi.VM.get_all()
vms = []
hosts = []
for vm in all:
record = session.xenapi.VM.get_record(vm)
if not(record["is_a_template"]) and \
not(record["is_control_domain"]) and \
record["power_state"] == "Running":
vms.append(vm)
hosts.append(record["resident_on"])
print "%d: Found %d suitable running VMs" % (iteration, len(vms))
Next the list of hosts is rotated:
# use a rotation as a permutation
hosts = [hosts[-1]] + hosts[:(len(hosts)-1)]
Each VM is then moved via XenMotion to the new host under this rotation (i.e.
a VM running on host at position 2 in the list will be moved to the host at position 1
in the list etc.)
In order to execute each of the movements in parallel, the asynchronous version
of the VM.pool_migrate is used and a list of task references constructed.
Note the live flag passed to the VM.pool_migrate; this
causes the VMs to be moved while they are still running.
tasks = []
for i in range(0, len(vms)):
vm = vms[i]
host = hosts[i]
task = session.xenapi.Async.VM.pool_migrate(vm, host, { "live": "true" })
tasks.append(task)
The list of tasks is then polled for completion:
finished = False
records = {}
while not(finished):
finished = True
for task in tasks:
record = session.xenapi.task.get_record(task)
records[task] = record
if record["status"] == "pending":
finished = False
time.sleep(1)
Once all tasks have left the pending state (i.e. they have successfully completed,
failed or been cancelled) the tasks are polled once more to see if they all succeeded:
allok = True
for task in tasks:
record = records[task]
if record["status"] <> "success":
allok = False
If any one of the tasks failed then details are printed, an exception is raised and the task objects
left around for further inspection. If all tasks succeeded then the task objects are destroyed and the
function returns.
if not(allok):
print "One of the tasks didn't succeed at", \
time.strftime("%F:%HT%M:%SZ", time.gmtime())
idx = 0
for task in tasks:
record = records[task]
vm_name = session.xenapi.VM.get_name_label(vms[idx])
host_name = session.xenapi.host.get_name_label(hosts[idx])
print "%s : %12s %s -> %s [ status: %s; result = %s; error = %s ]" % \
(record["uuid"], record["name_label"], vm_name, host_name, \
record["status"], record["result"], repr(record["error_info"]))
idx = idx + 1
raise "Task failed"
else:
for task in tasks:
session.xenapi.task.destroy(task)
4.2.2. Cloning a VM via the XE CLI
This example (contained in /SDK/client-examples/bash-cli/clone-vms)
is a bash script which uses the XE CLI to clone a VM
taking care to shut it down first if it is powered on.
The example begins with some boilerplate which first checks if the environment variable
XE has been set: if it has it assumes that it points to the full path
of the CLI, else it is assumed that the XE CLI is on the
current path. Next the script prompts the user for a server name, username and password:
# Allow the path to the 'xe' binary to be overridden by the XE environment varia
ble
if [ -z "${XE}" ]; then
XE=xe
fi
if [ ! -e "${HOME}/.xe" ]; then
read -p "Server name: " SERVER
read -p "Username: " USERNAME
read -p "Password: " PASSWORD
XE="${XE} -s ${SERVER} -u ${USERNAME} -pw ${PASSWORD}"
fi
Next the script checks its commandline arguments. It requires exactly one: the UUID of
the VM which is to be cloned:
# Check if there's a VM by the uuid specified
${XE} vm-list params=uuid | grep -q " ${vmuuid}$"
if [ $? -ne 0 ]; then
echo "error: no vm uuid \"${vmuuid}\" found"
exit 2
fi
The script then checks the power state of the VM and if it is running, it attempts a clean
shutdown. The event system is used to wait for the VM to enter state "Halted".
Note
The XE CLI supports a command-line argument --minimal which causes it to print its
output without excess whitespace or formatting, ideal for use from scripts. If multiple values are returned
they are comma-separated.
# Check the power state of the vm
name=$(${XE} vm-list uuid=${vmuuid} params=name-label --minimal)
state=$(${XE} vm-list uuid=${vmuuid} params=power-state --minimal)
wasrunning=0
# If the VM state is running, we shutdown the vm first
if [ "${state}" = "running" ]; then
${XE} vm-shutdown uuid=${vmuuid}
${XE} event-wait class=vm power-state=halted uuid=${vmuuid}
wasrunning=1
fi
The VM is then cloned and the new VM has its name_label
set to cloned_vm.
# Clone the VM
newuuid=$(${XE} vm-clone uuid=${vmuuid} new-name-label=cloned_vm)
Finally, if the original VM had been running and was shutdown, both it and the new
VM are started.
# If the VM state was running before cloning, we start it again
# along with the new VM.
if [ "$wasrunning" -eq 1 ]; then
${XE} vm-start uuid=${vmuuid}
${XE} vm-start uuid=${newuuid}
fi