Turns out that using the “free” version of ESXi 5.1 does not work with RHCS fencing due to SOAP limitations.
Place the following file in /usr/sbin/fence_esxi and chmod a+x /usr/sbin/fence_esxi
Make sure to install paramiko (yum install python-paramiko)
#!/usr/bin/python import paramiko import sys import time import datetime import re sys.path.append("/usr/share/fence") from fencing import * device_opt = [ "help", "version", "agent", "quiet", "verbose", "debug", "action", "ipaddr", "login", "passwd", "passwd_script", "ssl", "port", "uuid", "separator", "ipport", "power_timeout", "shell_timeout", "login_timeout", "power_wait" ] options = check_input(device_opt, process_input(device_opt)) f = open("/var/log/cluster/fence_esxi.log","w+") ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') f.write(st + " starting fencing.\n") f.write("-n " + options["-n"] + "\n") f.write("-a " + options["-a"] + "\n") f.write("-l " + options["-l"] + "\n") f.write("-p " + options["-p"] + "\n") client = paramiko.SSHClient() client.load_system_host_keys() client.connect(options["-a"],username=options["-l"],password=options["-p"]) command="esxcli vm process list | grep ^" + options["-n"] + " -A 1 | tail -n 1 | sed \'s/ */ /g\' | cut -d \" \" -f 4" f.write("Cmd: " + command + "\n") stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): f.write("Waiting for command to finish... \n") time.sleep(2) wwid = stdout.read() f.write("wwid: " + wwid + "\n") if len(wwid) < 2: f.write("VM not found or alread offline \n") client.close() sys.exit(1) f.write("VM found \n") command="esxcli vm process kill --type=soft --world-id=" + wwid f.write("Cmd: " + command + "\n") stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): f.write("Waiting for command to finish... \n") time.sleep(2) #Give the VM some time to shut down gracefully time.sleep(30) f.write("Waited 30 seconds \n") command="vm-support -V | grep centos | cut -d \"(\" -f 2 | cut -d \")\" -f 1" f.write("Cmd: " + command + "\n") stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): f.write("Waiting for command to finish... \n") time.sleep(2) status = stdout.read() f.write("VM Status: " + status + "\n") sregex = re.compile('Running') if sregex.search(status): f.write("VM still running, hard kill required \n") command="esxcli vm process kill --type=hard --world-id=" + wwid f.write("Cmd: " + command + "\n") stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): f.write("Waiting for command to finish... \n") time.sleep(2) time.sleep(30) else: f.write("VM successfully soft killed \n") #Get VM info while powered off command="vim-cmd vmsvc/getallvms | grep " + options["-n"] + " | sed 's/ */ /g' | cut -d \" \" -f 1" f.write("Cmd: " + command + "\n") stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): f.write("Waiting for command to finish... \n") time.sleep(2) vmid = stdout.read() #Start VM back up command="vim-cmd vmsvc/power.on " + vmid f.write("Cmd: " + command + "\n") stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): f.write("Waiting for command to finish... \n") time.sleep(2) f.write("fence_esxi exiting...") f.close() client.close() sys.exit(0)
In your cluster.conf you would then have something like the following. Make sure to enable SSH on your ESXi hosts
<fence>
<method name="fence-cluster1">
<device name="esx1" port="centos-cluster1" ssl="on" />
</method>
</fence>
<fencedevices>
<fencedevice agent=”fence_esxi” ipaddr=”esx2.FQDN.com” login=”root” name=”esx2″ passwd=”YOURPASSWORDHERE” delay=”60″ />
</fencedevices>