Page MenuHomeClusterLabs Projects

fence_vmware.py
No OneTemporary

fence_vmware.py

#!/usr/bin/python
#
# The Following agent has been tested on:
# vmrun 2.0.0 build-116503 (from VMware Server 2.0) against:
# VMware ESX 4.0.0
# VMware vCenter 4.0.0
# VMware ESX 3.5
# VMware Server 2.0.0
# VMware ESXi 3.5 update 2
# VMware Server 1.0.7 (works but list/status show only running VMs)
#
# VI Perl API 1.6 against:
# VMware ESX 4.0.0
# VMware vCenter 4.0.0
# VMware ESX 3.5
# VMware ESXi 3.5 update 2
# VMware Virtual Center 2.5
#
# VMware vSphere SDK for Perl 4.0.0 against:
# VMware ESX 4.0.0
# VMware vCenter 4.0.0
#
import sys, re, pexpect, exceptions
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="VMware Agent using VI Perl API and/or VIX vmrun command"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
### CONSTANTS ####
# VMware type is ESX/ESXi/VC
VMWARE_TYPE_ESX=0
# VMware type is Server 1.x
VMWARE_TYPE_SERVER1=1
# VMware type is Server 2.x and/or ESX 3.5 up2, ESXi 3.5 up2, VC 2.5 up2
VMWARE_TYPE_SERVER2=2
# Minimum required version of vmrun command
VMRUN_MINIMUM_REQUIRED_VERSION=2
# Default path to vmhelper command
VMHELPER_COMMAND="fence_vmware_helper"
# Default path to vmrun command
VMRUN_COMMAND="/usr/bin/vmrun"
# Default type of vmware
VMWARE_DEFAULT_TYPE="esx"
#### GLOBAL VARIABLES ####
# Internal type. One of VMWARE_TYPE_, set by #vmware_check_vmware_type
vmware_internal_type=VMWARE_TYPE_ESX
# If ESX is disconnected, say, that VM is off (don't return previous state)
vmware_disconnected_hack=False
### FUNCTIONS ####
#Split string in simplified DSV format to array of items
def dsv_split(dsv_str):
delimiter_c=':'
escape_c='\\'
res=[]
status=0
tmp_str=""
for x in dsv_str:
if (status==0):
if (x==delimiter_c):
res.append(tmp_str)
tmp_str=""
elif (x==escape_c):
status=1
else:
tmp_str+=x
elif (status==1):
if (x==delimiter_c):
tmp_str+=delimiter_c
elif (x==escape_c):
tmp_str+=escape_c
else:
tmp_str+=escape_c+x
status=0
if (tmp_str!=""):
res.append(tmp_str)
return res
# Quote string for proper existence in quoted string used for pexpect.run function
# Ex. test'this will return test'\''this. So pexpect run will really pass ' to argument
def quote_for_run(str):
dstr=''
for c in str:
if c==r"'":
dstr+="'\\''"
else:
dstr+=c
return dstr
# Return string with command and additional parameters (something like vmrun -h 'host'
def vmware_prepare_command(options,add_login_params,additional_params):
res=options["-e"]
if (add_login_params):
if (vmware_internal_type==VMWARE_TYPE_ESX):
res+=" --server '%s' --username '%s' --password '%s' "%(quote_for_run(options["-a"]),
quote_for_run(options["-l"]),
quote_for_run(options["-p"]))
elif (vmware_internal_type==VMWARE_TYPE_SERVER2):
res+=" -h 'https://%s/sdk' -u '%s' -p '%s' -T server "%(quote_for_run(options["-a"]),
quote_for_run(options["-l"]),
quote_for_run(options["-p"]))
elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
host_name_array=options["-a"].split(':')
res+=" -h '%s' -u '%s' -p '%s' -T server1 "%(quote_for_run(host_name_array[0]),
quote_for_run(options["-l"]),
quote_for_run(options["-p"]))
if (len(host_name_array)>1):
res+="-P '%s' "%(quote_for_run(host_name_array[1]))
if ((options.has_key("-s")) and (vmware_internal_type==VMWARE_TYPE_ESX)):
res+="--datacenter '%s' "%(quote_for_run(options["-s"]))
if (additional_params!=""):
res+=additional_params
return res
# Log message if user set verbose option
def vmware_log(options, message):
if options["log"] >= LOG_MODE_VERBOSE:
options["debug_fh"].write(message+"\n")
# Run command with timeout and parameters. Internaly uses vmware_prepare_command. Returns string
# with output from vmrun command. If something fails (command not found, exit code is not 0), fail_usage
# function is called (and never return).
def vmware_run_command(options,add_login_params,additional_params,additional_timeout):
command=vmware_prepare_command(options,add_login_params,additional_params)
try:
vmware_log(options,command)
(res_output,res_code)=pexpect.run(command,int(options["-Y"])+int(options["-y"])+additional_timeout,True)
if (res_code==None):
fail(EC_TIMED_OUT)
if ((res_code!=0) and (add_login_params)):
vmware_log(options,res_output)
fail_usage("%s returned %s"%(options["-e"],res_output))
else:
vmware_log(options,res_output)
except pexpect.ExceptionPexpect:
fail_usage("Cannot run command %s"%(options["-e"]))
return res_output
# Get outlet list with status as hash table. If you will use add_vm_name, only VM with vmname is
# returned. This is used in get_status function
def vmware_get_outlets_vi(conn, options, add_vm_name):
outlets={}
if (add_vm_name):
all_machines=vmware_run_command(options,True,("--operation status --vmname '%s'"%(quote_for_run(options["-n"]))),0)
else:
all_machines=vmware_run_command(options,True,"--operation list",int(options["-g"]))
all_machines_array=all_machines.splitlines()
for machine in all_machines_array:
machine_array=dsv_split(machine)
if (len(machine_array)==4):
if (machine_array[0] in outlets):
fail_usage("Failed. More machines with same name %s found!"%(machine_array[0]))
if (vmware_disconnected_hack):
outlets[machine_array[0]]=("",(
((machine_array[2].lower() in ["poweredon"]) and
(machine_array[3].lower()=="connected"))
and "on" or "off"))
else:
outlets[machine_array[0]]=("",((machine_array[2].lower() in ["poweredon"]) and "on" or "off"))
return outlets
# Get outlet list with status as hash table.
def vmware_get_outlets_vix(conn,options):
outlets={}
running_machines=vmware_run_command(options,True,"list",0)
running_machines_array=running_machines.splitlines()[1:]
if (vmware_internal_type==VMWARE_TYPE_SERVER2):
all_machines=vmware_run_command(options,True,"listRegisteredVM",0)
all_machines_array=all_machines.splitlines()[1:]
elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
all_machines_array=running_machines_array
for machine in all_machines_array:
if (machine!=""):
outlets[machine]=("",((machine in running_machines_array) and "on" or "off"))
return outlets
def get_outlets_status(conn, options):
if (vmware_internal_type==VMWARE_TYPE_ESX):
return vmware_get_outlets_vi(conn,options,False)
if ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
return vmware_get_outlets_vix(conn,options)
def get_power_status(conn,options):
if (vmware_internal_type==VMWARE_TYPE_ESX):
outlets=vmware_get_outlets_vi(conn,options,True)
else:
outlets=get_outlets_status(conn,options)
if ((vmware_internal_type==VMWARE_TYPE_SERVER2) or (vmware_internal_type==VMWARE_TYPE_ESX)):
if (not (options["-n"] in outlets)):
fail_usage("Failed: You have to enter existing name of virtual machine!")
else:
return outlets[options["-n"]][1]
elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
return ((options["-n"] in outlets) and "on" or "off")
def set_power_status(conn, options):
if (vmware_internal_type==VMWARE_TYPE_ESX):
additional_params="--operation %s --vmname '%s'"%((options["-o"]=="on" and "on" or "off"),quote_for_run(options["-n"]))
elif ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
additional_params="%s '%s'"%((options["-o"]=="on" and "start" or "stop"),quote_for_run(options["-n"]))
if (options["-o"]=="off"):
additional_params+=" hard"
vmware_run_command(options,True,additional_params,int(options["-g"]))
# Returns True, if user uses supported vmrun version (currently >=2.0.0) otherwise False.
def vmware_is_supported_vmrun_version(options):
vmware_help_str=vmware_run_command(options,False,"",0)
version_re=re.search("vmrun version (\d\.(\d[\.]*)*)",vmware_help_str.lower())
if (version_re==None):
return False # Looks like this "vmrun" is not real vmrun
version_array=version_re.group(1).split(".")
try:
if (int(version_array[0])<VMRUN_MINIMUM_REQUIRED_VERSION):
return False
except Exception:
return False
return True
# Define new options
def vmware_define_defaults():
all_opt["vmware_type"]["default"]=VMWARE_DEFAULT_TYPE
# Check vmware type, set vmware_internal_type to one of VMWARE_TYPE_ value and
# options["-e"] to path (if not specified)
def vmware_check_vmware_type(options):
global vmware_internal_type
options["-d"]=options["-d"].lower()
if (options["-d"]=="esx"):
vmware_internal_type=VMWARE_TYPE_ESX
if (not options.has_key("-e")):
options["-e"]=VMHELPER_COMMAND
elif (options["-d"]=="server2"):
vmware_internal_type=VMWARE_TYPE_SERVER2
if (not options.has_key("-e")):
options["-e"]=VMRUN_COMMAND
elif (options["-d"]=="server1"):
vmware_internal_type=VMWARE_TYPE_SERVER1
if (not options.has_key("-e")):
options["-e"]=VMRUN_COMMAND
else:
fail_usage("vmware_type can be esx,server2 or server1!")
# Main agent method
def main():
device_opt = [ "help", "version", "agent", "quiet", "verbose", "debug",
"action", "ipaddr", "login", "passwd", "passwd_script",
"test", "port", "separator", "exec", "vmware_type",
"vmware_datacenter", "secure", "identity_file",
"power_timeout", "shell_timeout", "login_timeout", "power_wait" ]
atexit.register(atexit_handler)
vmware_define_defaults()
options = check_input(device_opt, process_input(device_opt))
# Default is secure connection
options["-x"] = 1
docs = { }
docs["shortdesc"] = "Fence agent for VMWare"
docs["longdesc"] = "fence_vmware is an I/O Fencing agent \
which can be used with the VMware ESX, VMware ESXi or VMware Server \
to fence virtual machines.\
\n.P\n\
Before you can use this agent, it must be installed VI Perl Toolkit or \
vmrun command on every node you want to make fencing.\
\n.P\n\
VI Perl Toolkit is preferred for VMware ESX/ESXi and Virtual Center. Vmrun \
command is only solution for VMware Server 1/2 (this command will works against \
ESX/ESXi 3.5 up2 and VC up2 too, but not cluster aware!) and is available as part \
of VMware VIX API SDK package. VI Perl and VIX API SDK are both available from \
VMware web pages (not int RHEL repository!). \
\n.P\n\
You can specify type of VMware you are connecting to with \\fB-d\\fP switch \
(or \\fIvmware_type\\fR for stdin). Possible values are esx, server2 and server1.\
Default value is esx, which will use VI Perl. With server1 and server2, vmrun \
command is used.\
\n.P\n\
After you have successfully installed VI Perl Toolkit or VIX API, you should \
be able to run fence_vmware_helper (part of this agent) or vmrun command. \
This agent supports only vmrun from version 2.0.0 (VIX API 1.6.0)."
docs["vendorurl"] = "http://www.vmware.com"
show_docs(options, docs)
# Check vmware type and set path
vmware_check_vmware_type(options)
# Test user vmrun command version
if ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
if (not (vmware_is_supported_vmrun_version(options))):
fail_usage("Unsupported version of vmrun command! You must use at least version %d!"%(VMRUN_MINIMUM_REQUIRED_VERSION))
# Operate the fencing device
result = fence_action(None, options, set_power_status, get_power_status, get_outlets_status)
sys.exit(result)
if __name__ == "__main__":
main()

File Metadata

Mime Type
text/x-script.python
Expires
Mon, Feb 24, 8:44 PM (12 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464446
Default Alt Text
fence_vmware.py (11 KB)

Event Timeline