Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Fetching contributors…
Cannot retrieve contributors at this time
147 lines (112 sloc) 4.12 KB
#!/usr/bin/env python
# Multipath test support plugin
import subprocess, sys, socket, struct, time, syslog
import os
import re
import signal
from threading import Timer
import XenAPI, inventory
import XenAPIPlugin
dmsetup = "/sbin/dmsetup"
iptables = "/sbin/iptables"
dd = "/bin/dd"
scli = "/usr/local/bin/scli"
list_domains = "@OPTDIR@/bin/list_domains"
xs = "@OPTDIR@/debug/xs"
def doexec(args, inputtext=None):
"""Execute a subprocess, then return its return code, stdout and stderr"""
proc = subprocess.Popen(args,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,close_fds=True)
(stdout,stderr) = proc.communicate(inputtext)
rc = proc.returncode
return (rc,stdout,stderr)
def get_devmapper_status(session, args):
(rc,stdout,stderr) = doexec([dmsetup, "status", "--target", "multipath"])
return stdout
def modify_paths(session, args):
if args['remove'] == 'true':
remove = '-A'
remove = '-D'
num_paths = int(args['num_paths'])
# Get the IP addresses of the paths to remove
rcs = []
for i in range(num_paths):
ip = args['ip%d' % i]
(rc,stdout,stderr) = doexec([iptables, remove, "OUTPUT", "-d", ip, "-j", "DROP"])
# Return the iptables exit codes
return ','.join(rcs)
def time_data_transfer(session, args):
dev = "/dev/%s" % args['device']
# Time the dd
start_time = time.time()
(rc,stdout,stderr) = doexec([dd, "if=/dev/zero", "of=%s" % dev, "bs=1K", "count=1024"])
finish_time = time.time()
return str(finish_time - start_time)
def get_hba_status(session, args):
(rc,stdout,stderr) = doexec([scli, "-t"])
# Extract the WWPNs and online/offline status
wwpn = None
wwpns = []
lines = stdout.splitlines()
for line in lines:
if line.find('HBA Instance') == 0:
fields = line.split(' ')
wwpn = fields[7]
if line.find('Status') == 0:
fields = re.split('\s+', line)
status = fields[2]
wwpns.append("%s:%s" % (wwpn, status))
return ','.join(wwpns)
def check_xenstore_key_exists(key):
# See if there's a value in XenStore against the given key
(rc,stdout,stderr) = doexec([xs, "read", key])
if rc == 0:
return True
return False
def get_domid_for_vm(vm_uuid):
(rc,stdout,stderr) = doexec([list_domains])
lines = stdout.split("\n")
lines.pop() # remove last element (blank line)
lines.pop(0) # remove first element (column headers)
for line in lines:
cols = line.split(" | ")
if cols[1] == vm_uuid:
return cols[0].strip() # remove start and end whitespace
return None
def wait_for_iscsi_vm_boot(session, args):
vm_uuid = args['vm_uuid']
delay = float(args['delay'])
# Find the domain ID for the VM with the given UUID
domid = get_domid_for_vm(vm_uuid)
if domid == None:
return 'ERROR: could not find domain with uuid %s' % vm_uuid
# Now wait for the key to appear in XenStore
key = "/local/domain/%s/data/updated" % domid
finished = False
if check_xenstore_key_exists(key):
finished = True
proc = subprocess.Popen([xs,'watch',key],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,close_fds=True)
def kill():
os.kill(, signal.SIGKILL)
# Kill the watch if it takes too long
timer = Timer(delay, kill)
while not finished:
# Wait for the watch to fire
line = proc.stdout.readline()
if line == '':
# Then EOF was reached
return 'ERROR: waiting for xenstore key %s timed out after %.1f secs' % (key,delay)
if check_xenstore_key_exists(key):
finished = True
return 'OK'
if __name__ == "__main__":
XenAPIPlugin.dispatch({"get_devmapper_status": get_devmapper_status,
"modify_paths": modify_paths,
"time_data_transfer": time_data_transfer,
"get_hba_status": get_hba_status,
"wait_for_iscsi_vm_boot": wait_for_iscsi_vm_boot})
Jump to Line
Something went wrong with that request. Please try again.