Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3152622
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
77 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/fence/agents/amt/fence_amt.py b/fence/agents/amt/fence_amt.py
index 0eb6caf8..fdf2db30 100644
--- a/fence/agents/amt/fence_amt.py
+++ b/fence/agents/amt/fence_amt.py
@@ -1,156 +1,156 @@
#!/usr/bin/python -tt
import sys, subprocess, re
import logging
import atexit
from pipes import quote
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
-from fencing import fail_usage, is_executable, SUDO_PATH, LOG_MODE_VERBOSE
+from fencing import fail_usage, is_executable, SUDO_PATH
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="Fence agent for Intel AMT"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
def get_power_status(_, options):
cmd = create_command(options, "status")
try:
logging.debug("Running: %s" % cmd)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
except OSError:
fail_usage("Amttool not found or not accessible")
process.wait()
out = process.communicate()
process.stdout.close()
process.stderr.close()
logging.debug("%s\n" % str(out))
match = re.search('Powerstate:[\\s]*(..)', str(out))
status = match.group(1) if match else None
if (status == None):
return "fail"
elif (status == "S0"): # SO = on; S3 = sleep; S5 = off
return "on"
else:
return "off"
def set_power_status(_, options):
cmd = create_command(options, options["--action"])
try:
logging.debug("Running: %s" % cmd)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
except OSError:
fail_usage("Amttool not found or not accessible")
process.wait()
out = process.communicate()
process.stdout.close()
process.stderr.close()
logging.debug("%s\n" % str(out))
return
def reboot_cycle(_, options):
cmd = create_command(options, "cycle")
try:
logging.debug("Running: %s" % cmd)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
except OSError:
fail_usage("Amttool not found or not accessible")
status = process.wait()
out = process.communicate()
process.stdout.close()
process.stderr.close()
logging.debug("%s\n" % str(out))
return not bool(status)
def create_command(options, action):
# --password / -p
cmd = "AMT_PASSWORD=" + quote(options["--password"])
cmd += " " + options["--amttool-path"]
# --ip / -a
cmd += " " + options["--ip"]
# --action / -o
if action == "status":
cmd += " info"
elif action == "on":
cmd = "echo \"y\"|" + cmd
cmd += " powerup"
elif action == "off":
cmd = "echo \"y\"|" + cmd
cmd += " powerdown"
elif action == "cycle":
cmd = "echo \"y\"|" + cmd
cmd += " powercycle"
if action in ["on", "off", "cycle"] and options.has_key("--boot-option"):
cmd += options["--boot-option"]
# --use-sudo / -d
if options.has_key("--use-sudo"):
cmd = SUDO_PATH + " " + cmd
return cmd
def define_new_opts():
all_opt["boot_option"] = {
"getopt" : "b:",
"longopt" : "boot-option",
"help" : "-b, --boot-option=[option] "
"Change the default boot behavior of the machine. (pxe|hd|hdsafe|cd|diag)",
"required" : "0",
"shortdesc" : "Change the default boot behavior of the machine.",
"choices" : ["pxe", "hd", "hdsafe", "cd", "diag"],
"order" : 1
}
all_opt["amttool_path"] = {
"getopt" : "i:",
"longopt" : "amttool-path",
"help" : "--amttool-path=[path] Path to amttool binary",
"required" : "0",
"shortdesc" : "Path to amttool binary",
"default" : "@AMTTOOL_PATH@",
"order": 200
}
def main():
atexit.register(atexit_handler)
device_opt = [ "ipaddr", "no_login", "passwd", "boot_option", "no_port",
"sudo", "amttool_path", "method" ]
define_new_opts()
options = check_input(device_opt, process_input(device_opt))
docs = { }
docs["shortdesc"] = "Fence agent for AMT"
docs["longdesc"] = "fence_amt is an I/O Fencing agent \
which can be used with Intel AMT. This agent calls support software amttool\
(http://www.kraxel.org/cgit/amtterm/)."
docs["vendorurl"] = "http://www.intel.com/"
show_docs(options, docs)
if not is_executable(options["--amttool-path"]):
fail_usage("Amttool not found or not accessible")
result = fence_action(None, options, set_power_status, get_power_status, None, reboot_cycle)
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/cisco_ucs/fence_cisco_ucs.py b/fence/agents/cisco_ucs/fence_cisco_ucs.py
index de0f6818..2d4eaa8d 100644
--- a/fence/agents/cisco_ucs/fence_cisco_ucs.py
+++ b/fence/agents/cisco_ucs/fence_cisco_ucs.py
@@ -1,165 +1,165 @@
#!/usr/bin/python -tt
import sys, re
import pycurl, StringIO
import logging
import time
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
-from fencing import fail, EC_STATUS, EC_LOGIN_DENIED, LOG_MODE_VERBOSE
+from fencing import fail, EC_STATUS, EC_LOGIN_DENIED
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="New Cisco UCS Agent - test release on steroids"
REDHAT_COPYRIGHT=""
BUILD_DATE="March, 2008"
#END_VERSION_GENERATION
RE_COOKIE = re.compile("<aaaLogin .* outCookie=\"(.*?)\"", re.IGNORECASE)
RE_STATUS = re.compile("<lsPower .*? state=\"(.*?)\"", re.IGNORECASE)
RE_GET_DN = re.compile(" dn=\"(.*?)\"", re.IGNORECASE)
RE_GET_DESC = re.compile(" descr=\"(.*?)\"", re.IGNORECASE)
def get_power_status(conn, options):
del conn
res = send_command(options, "<configResolveDn cookie=\"" + options["cookie"] +
"\" inHierarchical=\"false\" dn=\"org-root" + options["--suborg"] + "/ls-" +
options["--plug"] + "/power\"/>", int(options["--shell-timeout"]))
result = RE_STATUS.search(res)
if (result == None):
fail(EC_STATUS)
else:
status = result.group(1)
if (status == "up"):
return "on"
else:
return "off"
def set_power_status(conn, options):
del conn
action = {
'on' : "up",
'off' : "down"
}[options["--action"]]
send_command(options, "<configConfMos cookie=\"" + options["cookie"] + "\" inHierarchical=\"no\">" +
"<inConfigs><pair key=\"org-root" + options["--suborg"] + "/ls-" + options["--plug"] +
"/power\">" + "<lsPower dn=\"org-root/ls-" + options["--plug"] + "/power\" state=\"" +
action + "\" status=\"modified\" />" + "</pair></inConfigs></configConfMos>",
int(options["--shell-timeout"]))
return
def get_list(conn, options):
del conn
outlets = { }
try:
res = send_command(options, "<configResolveClass cookie=\"" + options["cookie"] +
"\" inHierarchical=\"false\" classId=\"lsServer\"/>", int(options["--shell-timeout"]))
lines = res.split("<lsServer ")
for i in range(1, len(lines)):
node_name = RE_GET_DN.search(lines[i]).group(1)
desc = RE_GET_DESC.search(lines[i]).group(1)
outlets[node_name] = (desc, None)
except AttributeError:
return { }
except IndexError:
return { }
return outlets
def send_command(opt, command, timeout):
## setup correct URL
if opt.has_key("--ssl"):
url = "https:"
else:
url = "http:"
url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + "/nuova"
## send command through pycurl
conn = pycurl.Curl()
web_buffer = StringIO.StringIO()
conn.setopt(pycurl.URL, url)
conn.setopt(pycurl.HTTPHEADER, [ "Content-type: text/xml" ])
conn.setopt(pycurl.POSTFIELDS, command)
conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
conn.setopt(pycurl.TIMEOUT, timeout)
conn.setopt(pycurl.SSL_VERIFYPEER, 0)
conn.setopt(pycurl.SSL_VERIFYHOST, 0)
conn.perform()
result = web_buffer.getvalue()
logging.debug("%s\n" % command)
logging.debug("%s\n" % result)
return result
def define_new_opts():
all_opt["suborg"] = {
"getopt" : "s:",
"longopt" : "suborg",
"help" : "--suborg=[path] Additional path needed to access suborganization",
"required" : "0",
"shortdesc" : "Additional path needed to access suborganization",
"default" : "",
"order" : 1 }
def main():
device_opt = [ "ipaddr", "login", "passwd", "ssl", "notls", "port", "web", "suborg" ]
atexit.register(atexit_handler)
define_new_opts()
options = check_input(device_opt, process_input(device_opt))
docs = { }
docs["shortdesc"] = "Fence agent for Cisco UCS"
docs["longdesc"] = "fence_cisco_ucs is an I/O Fencing agent which can be \
used with Cisco UCS to fence machines."
docs["vendorurl"] = "http://www.cisco.com"
show_docs(options, docs)
## Do the delay of the fence device before logging in
## Delay is important for two-node clusters fencing but we do not need to delay 'status' operations
if options["--action"] in ["off", "reboot"]:
time.sleep(int(options["--delay"]))
### Login
try:
res = send_command(options, "<aaaLogin inName=\"" + options["--username"] +
"\" inPassword=\"" + options["--password"] + "\" />", int(options["--login-timeout"]))
result = RE_COOKIE.search(res)
if (result == None):
## Cookie is absenting in response
fail(EC_LOGIN_DENIED)
except:
fail(EC_LOGIN_DENIED)
options["cookie"] = result.group(1)
##
## Modify suborg to format /suborg
if options["--suborg"] != "":
options["--suborg"] = "/" + options["--suborg"].lstrip("/").rstrip("/")
##
## Fence operations
####
result = fence_action(None, options, set_power_status, get_power_status, get_list)
### Logout; we do not care about result as we will end in any case
send_command(options, "<aaaLogout inCookie=\"" + options["cookie"] + "\" />",
int(options["--shell-timeout"]))
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/eps/fence_eps.py b/fence/agents/eps/fence_eps.py
index 3a52b3c9..5efc8df7 100644
--- a/fence/agents/eps/fence_eps.py
+++ b/fence/agents/eps/fence_eps.py
@@ -1,128 +1,128 @@
#!/usr/bin/python -tt
# The Following Agent Has Been Tested On:
# ePowerSwitch 8M+ version 1.0.0.4
import sys, re
import httplib, base64, string, socket
import logging
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
-from fencing import fail, fail_usage, EC_LOGIN_DENIED, EC_TIMED_OUT, LOG_MODE_VERBOSE
+from fencing import fail, fail_usage, EC_LOGIN_DENIED, EC_TIMED_OUT
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="ePowerSwitch 8M+ (eps)"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
# Run command on EPS device.
# @param options Device options
# @param params HTTP GET parameters (without ?)
def eps_run_command(options, params):
try:
# New http connection
conn = httplib.HTTPConnection(options["--ip"])
request_str = "/"+options["--page"]
if (params!=""):
request_str += "?"+params
logging.debug("GET %s\n" % request_str)
conn.putrequest('GET', request_str)
if (options.has_key("--username")):
if (not options.has_key("--password")):
options["--password"] = "" # Default is empty password
# String for Authorization header
auth_str = 'Basic ' + string.strip(base64.encodestring(options["--username"]+':'+options["--password"]))
logging.debug("Authorization: %s\n" % auth_str)
conn.putheader('Authorization', auth_str)
conn.endheaders()
response = conn.getresponse()
logging.debug("%d %s\n"%(response.status, response.reason))
#Response != OK -> couldn't login
if (response.status!=200):
fail(EC_LOGIN_DENIED)
result = response.read()
logging.debug("%s \n" % result)
conn.close()
except socket.timeout:
fail(EC_TIMED_OUT)
except socket.error:
fail(EC_LOGIN_DENIED)
return result
def get_power_status(conn, options):
del conn
ret_val = eps_run_command(options,"")
result = {}
status = re.findall(r"p(\d{2})=(0|1)\s*\<br\>", ret_val.lower())
for out_num, out_stat in status:
result[out_num] = ("",(out_stat=="1" and "on" or "off"))
if (not (options["--action"] in ['monitor','list'])):
if (not (options["--plug"] in result)):
fail_usage("Failed: You have to enter existing physical plug!")
else:
return result[options["--plug"]][1]
else:
return result
def set_power_status(conn, options):
del conn
eps_run_command(options, "P%s=%s"%(options["--plug"], (options["--action"]=="on" and "1" or "0")))
# Define new option
def eps_define_new_opts():
all_opt["hidden_page"] = {
"getopt" : "c:",
"longopt" : "page",
"help":"-c, --page=[page] Name of hidden page (default hidden.htm)",
"required" : "0",
"shortdesc" : "Name of hidden page",
"default" : "hidden.htm",
"order": 1
}
# Starting point of fence agent
def main():
device_opt = [ "ipaddr", "login", "passwd", "no_login", "no_password", \
"port", "hidden_page" ]
atexit.register(atexit_handler)
eps_define_new_opts()
options = check_input(device_opt, process_input(device_opt))
docs = { }
docs["shortdesc"] = "Fence agent for ePowerSwitch"
docs["longdesc"] = "fence_eps is an I/O Fencing agent \
which can be used with the ePowerSwitch 8M+ power switch to fence \
connected machines. Fence agent works ONLY on 8M+ device, because \
this is only one, which has support for hidden page feature. \
\n.TP\n\
Agent basically works by connecting to hidden page and pass \
appropriate arguments to GET request. This means, that hidden \
page feature must be enabled and properly configured."
docs["vendorurl"] = "http://www.epowerswitch.com"
show_docs(options, docs)
#Run fence action. Conn is None, beacause we always need open new http connection
result = fence_action(None, options, set_power_status, get_power_status, get_power_status)
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/ipmilan/fence_ipmilan.py b/fence/agents/ipmilan/fence_ipmilan.py
index b120d6b1..a57efb73 100644
--- a/fence/agents/ipmilan/fence_ipmilan.py
+++ b/fence/agents/ipmilan/fence_ipmilan.py
@@ -1,202 +1,202 @@
#!/usr/bin/python -tt
import sys, shlex, subprocess, re, os
import logging
import atexit
from pipes import quote
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
-from fencing import SUDO_PATH, LOG_MODE_VERBOSE, fail_usage, is_executable
+from fencing import SUDO_PATH, fail_usage, is_executable
#BEGIN_VERSION_GENERATION
RELEASE_VERSION=""
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
def get_power_status(_, options):
cmd = create_command(options, "status")
try:
logging.info("Executing: %s\n" % cmd)
process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError:
fail_usage("Ipmitool not found or not accessible")
process.wait()
out = process.communicate()
process.stdout.close()
process.stderr.close()
logging.debug("%s\n" % str(out))
match = re.search('[Cc]hassis [Pp]ower is [\\s]*([a-zA-Z]{2,3})', str(out))
status = match.group(1) if match else None
return status
def set_power_status(_, options):
cmd = create_command(options, options["--action"])
try:
logging.debug("Executing: %s\n" % cmd)
process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError:
fail_usage("Ipmitool not found or not accessible")
process.wait()
out = process.communicate()
process.stdout.close()
process.stderr.close()
logging.debug("%s\n" % str(out))
return
def reboot_cycle(_, options):
cmd = create_command(options, "cycle")
try:
logging.debug("Executing: %s\n" % cmd)
process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError:
fail_usage("Ipmitool not found or not accessible")
process.wait()
out = process.communicate()
process.stdout.close()
process.stderr.close()
logging.debug("%s\n" % str(out))
return bool(re.search('chassis power control: cycle', str(out).lower()))
def create_command(options, action):
cmd = options["--ipmitool-path"]
# --lanplus / -L
if options.has_key("--lanplus") and options["--lanplus"] in ["", "1"]:
cmd += " -I lanplus"
else:
cmd += " -I lan"
# --ip / -a
cmd += " -H " + options["--ip"]
# --username / -l
if options.has_key("--username") and len(options["--username"]) != 0:
cmd += " -U " + quote(options["--username"])
# --auth / -A
if options.has_key("--auth"):
cmd += " -A " + options["--auth"]
# --password / -p
if options.has_key("--password"):
cmd += " -P " + quote(options["--password"])
# --cipher / -C
cmd += " -C " + options["--cipher"]
# --port / -n
if options.has_key("--ipport"):
cmd += " -p " + options["--ipport"]
if options.has_key("--privlvl"):
cmd += " -L " + options["--privlvl"]
# --action / -o
cmd += " chassis power " + action
# --use-sudo / -d
if options.has_key("--use-sudo"):
cmd = SUDO_PATH + " " + cmd
return cmd
def define_new_opts():
all_opt["lanplus"] = {
"getopt" : "P",
"longopt" : "lanplus",
"help" : "-P, --lanplus Use Lanplus to improve security of connection",
"required" : "0",
"default" : "0",
"shortdesc" : "Use Lanplus to improve security of connection",
"order": 1
}
all_opt["auth"] = {
"getopt" : "A:",
"longopt" : "auth",
"help" : "-A, --auth=[auth] IPMI Lan Auth type (md5|password|none)",
"required" : "0",
"shortdesc" : "IPMI Lan Auth type.",
"choices" : ["md5", "password", "none"],
"order": 1
}
all_opt["cipher"] = {
"getopt" : "C:",
"longopt" : "cipher",
"help" : "-C, --cipher=[cipher] Ciphersuite to use (same as ipmitool -C parameter)",
"required" : "0",
"shortdesc" : "Ciphersuite to use (same as ipmitool -C parameter)",
"default" : "0",
"order": 1
}
all_opt["privlvl"] = {
"getopt" : "L:",
"longopt" : "privlvl",
"help" : "-L, --privlvl=[level] "
"Privilege level on IPMI device (callback|user|operator|administrator)",
"required" : "0",
"shortdesc" : "Privilege level on IPMI device",
"default" : "administrator",
"choices" : ["callback", "user", "operator", "administrator"],
"order": 1
}
all_opt["ipmitool_path"] = {
"getopt" : "i:",
"longopt" : "ipmitool-path",
"help" : "--ipmitool-path=[path] Path to ipmitool binary",
"required" : "0",
"shortdesc" : "Path to ipmitool binary",
"default" : "@IPMITOOL_PATH@",
"order": 200
}
def main():
atexit.register(atexit_handler)
device_opt = ["ipaddr", "login", "no_login", "no_password", "passwd",
"lanplus", "auth", "cipher", "privlvl", "sudo", "ipmitool_path", "method"]
define_new_opts()
if os.path.basename(sys.argv[0]) == "fence_ilo3":
all_opt["power_wait"]["default"] = "4"
all_opt["method"]["default"] = "cycle"
all_opt["lanplus"]["default"] = "1"
elif os.path.basename(sys.argv[0]) == "fence_ilo4":
all_opt["lanplus"]["default"] = "1"
all_opt["ipport"]["default"] = "623"
options = check_input(device_opt, process_input(device_opt))
docs = { }
docs["shortdesc"] = "Fence agent for IPMI"
docs["longdesc"] = "fence_ipmilan is an I/O Fencing agent\
which can be used with machines controlled by IPMI.\
This agent calls support software ipmitool (http://ipmitool.sf.net/)."
docs["vendorurl"] = ""
docs["symlink"] = [("fence_ilo3", "Fence agent for HP iLO3"),
("fence_ilo4", "Fence agent for HP iLO4"),
("fence_imm", "Fence agent for IBM Integrated Management Module"),
("fence_idrac", "Fence agent for Dell iDRAC")]
show_docs(options, docs)
if not is_executable(options["--ipmitool-path"]):
fail_usage("Ipmitool not found or not accessible")
result = fence_action(None, options, set_power_status, get_power_status, None, reboot_cycle)
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index 73c2c4a2..f2432029 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -1,1096 +1,1093 @@
#!/usr/bin/python -tt
import sys, getopt, time, os, uuid, pycurl, stat
import pexpect, re, atexit, syslog
import logging
import __main__
## do not add code here.
#BEGIN_VERSION_GENERATION
RELEASE_VERSION = "New fence lib agent - test release on steroids"
REDHAT_COPYRIGHT = ""
BUILD_DATE = "March, 2008"
#END_VERSION_GENERATION
__all__ = [ 'atexit_handler', 'check_input', 'process_input', 'all_opt', 'show_docs',
'fence_login', 'fence_action' ]
-LOG_MODE_VERBOSE = 100
-LOG_MODE_QUIET = 0
-
EC_GENERIC_ERROR = 1
EC_BAD_ARGS = 2
EC_LOGIN_DENIED = 3
EC_CONNECTION_LOST = 4
EC_TIMED_OUT = 5
EC_WAITING_ON = 6
EC_WAITING_OFF = 7
EC_STATUS = 8
EC_STATUS_HMC = 9
EC_PASSWORD_MISSING = 10
EC_INVALID_PRIVILEGES = 11
TELNET_PATH = "/usr/bin/telnet"
SSH_PATH = "/usr/bin/ssh"
SSL_PATH = "@GNUTLSCLI_PATH@"
SUDO_PATH = "/usr/bin/sudo"
all_opt = {
"help" : {
"getopt" : "h",
"longopt" : "help",
"help" : "-h, --help Display this help and exit",
"required" : "0",
"shortdesc" : "Display help and exit",
"order" : 54 },
"version" : {
"getopt" : "V",
"longopt" : "version",
"help" : "-V, --version Output version information and exit",
"required" : "0",
"shortdesc" : "Display version information and exit",
"order" : 53 },
"verbose" : {
"getopt" : "v",
"longopt" : "verbose",
"help" : "-v, --verbose Verbose mode",
"required" : "0",
"shortdesc" : "Verbose mode",
"order" : 51 },
"debug" : {
"getopt" : "D:",
"longopt" : "debug-file",
"help" : "-D, --debug-file=[debugfile] Debugging to output file",
"required" : "0",
"shortdesc" : "Write debug information to given file",
"order" : 52 },
"delay" : {
"getopt" : "f:",
"longopt" : "delay",
"help" : "--delay=[seconds] Wait X seconds before fencing is started",
"required" : "0",
"shortdesc" : "Wait X seconds before fencing is started",
"default" : "0",
"order" : 200 },
"agent" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"web" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"action" : {
"getopt" : "o:",
"longopt" : "action",
"help" : "-o, --action=[action] Action: status, reboot (default), off or on",
"required" : "1",
"shortdesc" : "Fencing Action",
"default" : "reboot",
"order" : 1 },
"fabric_fencing" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"ipaddr" : {
"getopt" : "a:",
"longopt" : "ip",
"help" : "-a, --ip=[ip] IP address or hostname of fencing device",
"required" : "1",
"shortdesc" : "IP Address or Hostname",
"order" : 1 },
"ipport" : {
"getopt" : "u:",
"longopt" : "ipport",
"help" : "-u, --ipport=[port] TCP/UDP port to use",
"required" : "0",
"shortdesc" : "TCP/UDP port to use for connection with device",
"order" : 1 },
"login" : {
"getopt" : "l:",
"longopt" : "username",
"help" : "-l, --username=[name] Login name",
"required" : "?",
"shortdesc" : "Login Name",
"order" : 1 },
"no_login" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"no_password" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"no_port" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"passwd" : {
"getopt" : "p:",
"longopt" : "password",
"help" : "-p, --password=[password] Login password or passphrase",
"required" : "0",
"shortdesc" : "Login password or passphrase",
"order" : 1 },
"passwd_script" : {
"getopt" : "S:",
"longopt" : "password-script",
"help" : "-S, --password-script=[script] Script to run to retrieve password",
"required" : "0",
"shortdesc" : "Script to retrieve password",
"order" : 1 },
"identity_file" : {
"getopt" : "k:",
"longopt" : "identity-file",
"help" : "-k, --identity-file=[filename] Identity file (private key) for ssh ",
"required" : "0",
"shortdesc" : "Identity file for ssh",
"order" : 1 },
"cmd_prompt" : {
"getopt" : "c:",
"longopt" : "command-prompt",
"help" : "-c, --command-prompt=[prompt] Force Python regex for command prompt",
"shortdesc" : "Force Python regex for command prompt",
"required" : "0",
"order" : 1 },
"secure" : {
"getopt" : "x",
"longopt" : "ssh",
"help" : "-x, --ssh Use ssh connection",
"shortdesc" : "SSH connection",
"required" : "0",
"order" : 1 },
"ssh_options" : {
"getopt" : "X:",
"longopt" : "ssh-options",
"help" : "--ssh-options=[options] SSH options to use",
"shortdesc" : "SSH options to use",
"required" : "0",
"order" : 1 },
"ssl" : {
"getopt" : "z",
"longopt" : "ssl",
"help" : "-z, --ssl Use ssl connection",
"required" : "0",
"shortdesc" : "SSL connection",
"order" : 1 },
"notls" : {
"getopt" : "t",
"longopt" : "notls",
"help" : "-t, --notls "
"Disable TLS negotiation and force SSL3.0.\n"
" "
"This should only be used for devices that do not support TLS1.0 and up.",
"required" : "0",
"shortdesc" : "Disable TLS negotiation",
"order" : 1 },
"port" : {
"getopt" : "n:",
"longopt" : "plug",
"help" : "-n, --plug=[id] Physical plug number on device, UUID or\n" +
" identification of machine",
"required" : "1",
"shortdesc" : "Physical plug number, name of virtual machine or UUID",
"order" : 1 },
"switch" : {
"getopt" : "s:",
"longopt" : "switch",
"help" : "-s, --switch=[id] Physical switch number on device",
"required" : "0",
"shortdesc" : "Physical switch number on device",
"order" : 1 },
"exec" : {
"getopt" : "e:",
"longopt" : "exec",
"help" : "-e, --exec=[command] Command to execute",
"required" : "0",
"shortdesc" : "Command to execute",
"order" : 1 },
"vmware_type" : {
"getopt" : "d:",
"longopt" : "vmware_type",
"help" : "-d, --vmware_type=[type] Type of VMware to connect",
"required" : "0",
"shortdesc" : "Type of VMware to connect",
"order" : 1 },
"vmware_datacenter" : {
"getopt" : "s:",
"longopt" : "vmware-datacenter",
"help" : "-s, --vmware-datacenter=[dc] VMWare datacenter filter",
"required" : "0",
"shortdesc" : "Show only machines in specified datacenter",
"order" : 2 },
"snmp_version" : {
"getopt" : "d:",
"longopt" : "snmp-version",
"help" : "-d, --snmp-version=[version] Specifies SNMP version to use",
"required" : "0",
"shortdesc" : "Specifies SNMP version to use (1,2c,3)",
"choices" : [ "1", "2c", "3" ],
"order" : 1 },
"community" : {
"getopt" : "c:",
"longopt" : "community",
"help" : "-c, --community=[community] Set the community string",
"required" : "0",
"shortdesc" : "Set the community string",
"order" : 1},
"snmp_auth_prot" : {
"getopt" : "b:",
"longopt" : "snmp-auth-prot",
"help" : "-b, --snmp-auth-prot=[prot] Set authentication protocol (MD5|SHA)",
"required" : "0",
"shortdesc" : "Set authentication protocol (MD5|SHA)",
"choices" : [ "MD5" , "SHA" ],
"order" : 1},
"snmp_sec_level" : {
"getopt" : "E:",
"longopt" : "snmp-sec-level",
"help" : "-E, --snmp-sec-level=[level] Set security level\n"+
" (noAuthNoPriv|authNoPriv|authPriv)",
"required" : "0",
"shortdesc" : "Set security level (noAuthNoPriv|authNoPriv|authPriv)",
"choices" : [ "noAuthNoPriv", "authNoPriv", "authPriv" ],
"order" : 1},
"snmp_priv_prot" : {
"getopt" : "B:",
"longopt" : "snmp-priv-prot",
"help" : "-B, --snmp-priv-prot=[prot] Set privacy protocol (DES|AES)",
"required" : "0",
"shortdesc" : "Set privacy protocol (DES|AES)",
"choices" : [ "DES", "AES" ],
"order" : 1},
"snmp_priv_passwd" : {
"getopt" : "P:",
"longopt" : "snmp-priv-passwd",
"help" : "-P, --snmp-priv-passwd=[pass] Set privacy protocol password",
"required" : "0",
"shortdesc" : "Set privacy protocol password",
"order" : 1},
"snmp_priv_passwd_script" : {
"getopt" : "R:",
"longopt" : "snmp-priv-passwd-script",
"help" : "-R, --snmp-priv-passwd-script Script to run to retrieve privacy password",
"required" : "0",
"shortdesc" : "Script to run to retrieve privacy password",
"order" : 1},
"inet4_only" : {
"getopt" : "4",
"longopt" : "inet4-only",
"help" : "-4, --inet4-only Forces agent to use IPv4 addresses only",
"required" : "0",
"shortdesc" : "Forces agent to use IPv4 addresses only",
"order" : 1 },
"inet6_only" : {
"getopt" : "6",
"longopt" : "inet6-only",
"help" : "-6, --inet6-only Forces agent to use IPv6 addresses only",
"required" : "0",
"shortdesc" : "Forces agent to use IPv6 addresses only",
"order" : 1 },
"separator" : {
"getopt" : "C:",
"longopt" : "separator",
"help" : "-C, --separator=[char] Separator for CSV created by 'list' operation",
"default" : ",",
"required" : "0",
"shortdesc" : "Separator for CSV created by operation list",
"order" : 100 },
"login_timeout" : {
"getopt" : "y:",
"longopt" : "login-timeout",
"help" : "--login-timeout=[seconds] Wait X seconds for cmd prompt after login",
"default" : "5",
"required" : "0",
"shortdesc" : "Wait X seconds for cmd prompt after login",
"order" : 200 },
"shell_timeout" : {
"getopt" : "Y:",
"longopt" : "shell-timeout",
"help" : "--shell-timeout=[seconds] Wait X seconds for cmd prompt after issuing command",
"default" : "3",
"required" : "0",
"shortdesc" : "Wait X seconds for cmd prompt after issuing command",
"order" : 200 },
"power_timeout" : {
"getopt" : "g:",
"longopt" : "power-timeout",
"help" : "--power-timeout=[seconds] Test X seconds for status change after ON/OFF",
"default" : "20",
"required" : "0",
"shortdesc" : "Test X seconds for status change after ON/OFF",
"order" : 200 },
"power_wait" : {
"getopt" : "G:",
"longopt" : "power-wait",
"help" : "--power-wait=[seconds] Wait X seconds after issuing ON/OFF",
"default" : "0",
"required" : "0",
"shortdesc" : "Wait X seconds after issuing ON/OFF",
"order" : 200 },
"missing_as_off" : {
"getopt" : "M",
"longopt" : "missing-as-off",
"help" : "--missing-as-off Missing port returns OFF instead of failure",
"required" : "0",
"shortdesc" : "Missing port returns OFF instead of failure",
"order" : 200 },
"retry_on" : {
"getopt" : "F:",
"longopt" : "retry-on",
"help" : "--retry-on=[attempts] Count of attempts to retry power on",
"default" : "1",
"required" : "0",
"shortdesc" : "Count of attempts to retry power on",
"order" : 201 },
"session_url" : {
"getopt" : "s:",
"longopt" : "session-url",
"help" : "-s, --session-url URL to connect to XenServer on",
"required" : "1",
"shortdesc" : "The URL of the XenServer host.",
"order" : 1},
"sudo" : {
"getopt" : "d",
"longopt" : "use-sudo",
"help" : "--use-sudo Use sudo (without password) when calling 3rd party software",
"required" : "0",
"shortdesc" : "Use sudo (without password) when calling 3rd party sotfware.",
"order" : 205},
"method" : {
"getopt" : "m:",
"longopt" : "method",
"help" : "-m, --method=[method] Method to fence (onoff|cycle) (Default: onoff)",
"required" : "0",
"shortdesc" : "Method to fence (onoff|cycle)",
"default" : "onoff",
"choices" : [ "onoff", "cycle" ],
"order" : 1}
}
# options which are added automatically if 'key' is encountered ("default" is always added)
DEPENDENCY_OPT = {
"default" : [ "help", "debug", "verbose", "version", "action", "agent", \
"power_timeout", "shell_timeout", "login_timeout", "power_wait", "retry_on", "delay" ],
"passwd" : [ "passwd_script" ],
"secure" : [ "identity_file", "ssh_options" ],
"ipaddr" : [ "ipport", "inet4_only", "inet6_only" ],
"port" : [ "separator" ],
"community" : [ "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", \
"snmp_priv_passwd", "snmp_priv_passwd_script" ]
}
class fspawn(pexpect.spawn):
def __init__(self, options, command):
logging.info("Running command: %s" % command)
pexpect.spawn.__init__(self, command)
self.opt = options
def log_expect(self, options, pattern, timeout):
result = self.expect(pattern, timeout)
logging.debug("Received: %s" % (self.before + self.after))
return result
def send(self, message):
logging.debug("Sent: %s" % message)
pexpect.spawn.send(self,message)
# send EOL according to what was detected in login process (telnet)
def send_eol(self, message):
self.send(message + self.opt["eol"])
def atexit_handler():
try:
sys.stdout.close()
os.close(1)
except IOError:
logging.error("%s failed to close standard output\n" % (sys.argv[0]))
syslog.syslog(syslog.LOG_ERR, "Failed to close standard output")
sys.exit(EC_GENERIC_ERROR)
def add_dependency_options(options):
## Add also options which are available for every fence agent
added_opt = []
for opt in options + ["default"]:
if DEPENDENCY_OPT.has_key(opt):
added_opt.extend([y for y in DEPENDENCY_OPT[opt] if options.count(y) == 0])
return added_opt
def fail_usage(message = ""):
if len(message) > 0:
logging.error("%s\n" % message)
logging.error("Please use '-h' for usage\n")
sys.exit(EC_GENERIC_ERROR)
def fail(error_code):
message = {
EC_LOGIN_DENIED : "Unable to connect/login to fencing device",
EC_CONNECTION_LOST : "Connection lost",
EC_TIMED_OUT : "Connection timed out",
EC_WAITING_ON : "Failed: Timed out waiting to power ON",
EC_WAITING_OFF : "Failed: Timed out waiting to power OFF",
EC_STATUS : "Failed: Unable to obtain correct plug status or plug is not available",
EC_STATUS_HMC : "Failed: Either unable to obtain correct plug status, "
"partition is not available or incorrect HMC version used",
EC_PASSWORD_MISSING : "Failed: You have to set login password",
EC_INVALID_PRIVILEGES : "Failed: The user does not have the correct privileges to do the requested action."
}[error_code] + "\n"
logging.error("%s\n" % message)
syslog.syslog(syslog.LOG_ERR, message)
sys.exit(EC_GENERIC_ERROR)
def usage(avail_opt):
print "Usage:"
print "\t" + os.path.basename(sys.argv[0]) + " [options]"
print "Options:"
sorted_list = [ (key, all_opt[key]) for key in avail_opt ]
sorted_list.sort(lambda x, y: cmp(x[1]["order"], y[1]["order"]))
for key, value in sorted_list:
if len(value["help"]) != 0:
print " " + value["help"]
def metadata(avail_opt, options, docs):
# avail_opt has to be unique, if there are duplicities then they should be removed
sorted_list = [ (key, all_opt[key]) for key in list(set(avail_opt)) ]
sorted_list.sort(lambda x, y: cmp(x[1]["order"], y[1]["order"]))
print "<?xml version=\"1.0\" ?>"
print "<resource-agent name=\"" + os.path.basename(sys.argv[0]) + \
"\" shortdesc=\"" + docs["shortdesc"] + "\" >"
if "symlink" in docs:
for (symlink, desc) in docs["symlink"]:
print "<symlink name=\"" + symlink + "\" shortdesc=\"" + desc + "\"/>"
print "<longdesc>" + docs["longdesc"] + "</longdesc>"
if docs.has_key("vendorurl"):
print "<vendor-url>" + docs["vendorurl"] + "</vendor-url>"
print "<parameters>"
for option, _ in sorted_list:
if all_opt[option].has_key("shortdesc"):
print "\t<parameter name=\"" + option + "\" unique=\"0\" required=\"" + all_opt[option]["required"] + "\">"
default = ""
if all_opt[option].has_key("default"):
default = str(all_opt[option]["default"])
elif options.has_key("--" + all_opt[option]["longopt"]) and all_opt[option]["getopt"].endswith(":"):
if options["--" + all_opt[option]["longopt"]]:
try:
default = options["--" + all_opt[option]["longopt"]]
except TypeError:
## @todo/@note: Currently there is no clean way how to handle lists
## we can create a string from it but we can't set it on command line
default = str(options["--" + all_opt[option]["longopt"]])
elif options.has_key("--" + all_opt[option]["longopt"]):
default = "true"
if default:
default = default.replace("&", "&" )
default = default.replace('"', """ )
default = default.replace('<', "<" )
default = default.replace('>', ">" )
default = default.replace("'", "'" )
default = "default=\"" + default + "\" "
mixed = all_opt[option]["help"]
## split it between option and help text
res = re.compile(r"^(.*--\S+)\s+", re.IGNORECASE | re.S).search(mixed)
if (None != res):
mixed = res.group(1)
mixed = mixed.replace("<", "<").replace(">", ">")
print "\t\t<getopt mixed=\"" + mixed + "\" />"
if all_opt[option].has_key("choices"):
print "\t\t<content type=\"select\" "+default+" >"
for choice in all_opt[option]["choices"]:
print "\t\t\t<option value=\"%s\" />" % (choice)
print "\t\t</content>"
elif all_opt[option]["getopt"].count(":") > 0:
print "\t\t<content type=\"string\" "+default+" />"
else:
print "\t\t<content type=\"boolean\" "+default+" />"
print "\t\t<shortdesc lang=\"en\">" + all_opt[option]["shortdesc"] + "</shortdesc>"
print "\t</parameter>"
print "</parameters>"
print "<actions>"
if avail_opt.count("fabric_fencing") == 1:
## do 'unfence' at the start
print "\t<action name=\"on\" automatic=\"1\"/>"
else:
print "\t<action name=\"on\" automatic=\"0\"/>"
print "\t<action name=\"off\" />"
if avail_opt.count("fabric_fencing") == 0:
print "\t<action name=\"reboot\" />"
print "\t<action name=\"status\" />"
print "\t<action name=\"list\" />"
print "\t<action name=\"monitor\" />"
print "\t<action name=\"metadata\" />"
print "</actions>"
print "</resource-agent>"
def process_input(avail_opt):
avail_opt.extend(add_dependency_options(avail_opt))
##
## Set standard environment
#####
os.putenv("LANG", "C")
os.putenv("LC_ALL", "C")
##
## Prepare list of options for getopt
#####
getopt_string = ""
longopt_list = [ ]
for k in avail_opt:
if all_opt.has_key(k):
getopt_string += all_opt[k]["getopt"]
else:
fail_usage("Parse error: unknown option '"+k+"'")
if all_opt.has_key(k) and all_opt[k].has_key("longopt"):
if all_opt[k]["getopt"].endswith(":"):
longopt_list.append(all_opt[k]["longopt"] + "=")
else:
longopt_list.append(all_opt[k]["longopt"])
##
## Read options from command line or standard input
#####
if len(sys.argv) > 1:
try:
opt, _args = getopt.gnu_getopt(sys.argv[1:], getopt_string, longopt_list)
except getopt.GetoptError, error:
fail_usage("Parse error: " + error.msg)
## Transform short getopt to long one which are used in fencing agents
#####
old_opt = opt
opt = { }
for o in dict(old_opt).keys():
if o.startswith("--"):
for x in all_opt.keys():
if all_opt[x].has_key("longopt") and "--" + all_opt[x]["longopt"] == o:
opt["--" + all_opt[x]["longopt"]] = dict(old_opt)[o]
else:
for x in all_opt.keys():
if x in avail_opt and all_opt[x].has_key("getopt") and all_opt[x].has_key("longopt") and \
("-" + all_opt[x]["getopt"] == o or "-" + all_opt[x]["getopt"].rstrip(":") == o):
opt["--" + all_opt[x]["longopt"]] = dict(old_opt)[o]
opt[o] = dict(old_opt)[o]
## Compatibility Layer
#####
z = dict(opt)
if z.has_key("--plug") == 1:
z["-m"] = z["--plug"]
opt = z
##
#####
else:
opt = { }
name = ""
for line in sys.stdin.readlines():
line = line.strip()
if ((line.startswith("#")) or (len(line) == 0)):
continue
(name, value) = (line + "=").split("=", 1)
value = value[:-1]
if avail_opt.count(name) == 0:
logging.warning("Parse error: Ignoring unknown option '%s'\n" % line)
syslog.syslog(syslog.LOG_WARNING, "Parse error: Ignoring unknown option '"+line)
continue
if all_opt[name]["getopt"].endswith(":"):
opt["--"+all_opt[name]["longopt"].rstrip(":")] = value
elif value.lower() in [ "1", "yes", "on", "true" ]:
opt["--"+all_opt[name]["longopt"]] = "1"
return opt
##
## This function checks input and answers if we want to have same answers
## in each of the fencing agents. It looks for possible errors and run
## password script to set a correct password
######
def check_input(device_opt, opt):
device_opt.extend(add_dependency_options(device_opt))
options = dict(opt)
options["device_opt"] = device_opt
## Set requirements that should be included in metadata
#####
if device_opt.count("login") and device_opt.count("no_login") == 0:
all_opt["login"]["required"] = "1"
else:
all_opt["login"]["required"] = "0"
if device_opt.count("fabric_fencing"):
all_opt["action"]["default"] = "off"
all_opt["action"]["help"] = "-o, --action=[action] Action: status, off (default) or on"
## Set default values
#####
for opt in device_opt:
if all_opt[opt].has_key("default"):
getopt_long = "--" + all_opt[opt]["longopt"]
if 0 == options.has_key(getopt_long):
options[getopt_long] = all_opt[opt]["default"]
if device_opt.count("ipport"):
if options.has_key("--ipport"):
all_opt["ipport"]["help"] = "-u, --ipport=[port] " + \
"TCP/UDP port to use (default " + options["--ipport"] +")"
elif device_opt.count("snmp_version"):
all_opt["ipport"]["default"] = "161"
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 161)"
elif options.has_key("--ssh"):
all_opt["ipport"]["default"] = 22
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 22)"
elif options.has_key("--ssl"):
all_opt["ipport"]["default"] = 443
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 443)"
elif device_opt.count("web"):
all_opt["ipport"]["default"] = 80
if device_opt.count("ssl") == 0:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 80)"
else:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use\n\
(default 80, 443 if --ssl option is used)"
else:
all_opt["ipport"]["default"] = 23
if device_opt.count("secure") == 0:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 23)"
else:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use\n\
(default 23, 22 if --ssh option is used)"
## In special cases (show help, metadata or version) we don't need to check anything
#####
if options.has_key("--help") or options.has_key("--version") or \
(options.has_key("--action") and options["--action"].lower() == "metadata"):
return options
options["--action"] = options["--action"].lower()
if options.has_key("--verbose"):
logging.getLogger().setLevel(logging.DEBUG)
acceptable_actions = [ "on", "off", "status", "list", "monitor" ]
if 1 == device_opt.count("fabric_fencing"):
## Compatibility layer
#####
acceptable_actions.extend(["enable", "disable"])
else:
acceptable_actions.extend(["reboot"])
if 0 == acceptable_actions.count(options["--action"]):
fail_usage("Failed: Unrecognised action '" + options["--action"] + "'")
## Compatibility layer
#####
if options["--action"] == "enable":
options["--action"] = "on"
if options["--action"] == "disable":
options["--action"] = "off"
## automatic detection and set of valid UUID from --plug
if (0 == options.has_key("--username")) and \
device_opt.count("login") and (device_opt.count("no_login") == 0):
fail_usage("Failed: You have to set login name")
if device_opt.count("ipaddr") and 0 == options.has_key("--ip") and 0 == options.has_key("--managed"):
fail_usage("Failed: You have to enter fence address")
if (device_opt.count("no_password") == 0):
if 0 == device_opt.count("identity_file"):
if 0 == (options.has_key("--password") or options.has_key("--password-script")):
fail_usage("Failed: You have to enter password or password script")
else:
if 0 == (options.has_key("--password") or \
options.has_key("--password-script") or options.has_key("--identity-file")):
fail_usage("Failed: You have to enter password, password script or identity file")
if 0 == options.has_key("--ssh") and 1 == options.has_key("--identity-file"):
fail_usage("Failed: You have to use identity file together with ssh connection (-x)")
if 1 == options.has_key("--identity-file"):
if 0 == os.path.isfile(options["--identity-file"]):
fail_usage("Failed: Identity file " + options["--identity-file"] + " does not exist")
if (0 == ["list", "monitor"].count(options["--action"].lower())) and \
0 == options.has_key("--plug") and device_opt.count("port") and device_opt.count("no_port") == 0:
fail_usage("Failed: You have to enter plug number or machine identification")
if options.has_key("--password-script"):
options["--password"] = os.popen(options["--password-script"]).read().rstrip()
if options.has_key("--debug-file"):
try:
fh = logging.FileHandler(options["--debug-file"])
fh.setLevel(logging.DEBUG)
logging.getLogger().addHandler(fh)
except IOError:
logging.error("Unable to create file %s" % options["--debug-file"])
fail_usage("Failed: Unable to create file " + options["--debug-file"])
if options.has_key("--snmp-priv-passwd-script"):
options["--snmp-priv-passwd"] = os.popen(options["--snmp-priv-passwd-script"]).read().rstrip()
if options.has_key("--ipport") == False:
if options.has_key("--ssh"):
options["--ipport"] = 22
elif options.has_key("--ssl"):
options["--ipport"] = 443
elif device_opt.count("web"):
options["--ipport"] = 80
else:
options["--ipport"] = 23
if options.has_key("--plug") and len(options["--plug"].split(",")) > 1 and \
options.has_key("--method") and options["--method"] == "cycle":
fail_usage("Failed: Cannot use --method cycle for more than 1 plug")
for opt in device_opt:
if all_opt[opt].has_key("choices"):
longopt = "--" + all_opt[opt]["longopt"]
possible_values_upper = map (lambda y : y.upper(), all_opt[opt]["choices"])
if options.has_key(longopt):
options[longopt] = options[longopt].upper()
if not options["--" + all_opt[opt]["longopt"]] in possible_values_upper:
fail_usage("Failed: You have to enter a valid choice " + \
"for %s from the valid values: %s" % \
("--" + all_opt[opt]["longopt"] , str(all_opt[opt]["choices"])))
return options
def wait_power_status(tn, options, get_power_fn):
for dummy in xrange(int(options["--power-timeout"])):
if get_multi_power_fn(tn, options, get_power_fn) != options["--action"]:
time.sleep(1)
else:
return 1
return 0
## Obtain a power status from possibly more than one plug
## "on" is returned if at least one plug is ON
######
def get_multi_power_fn(tn, options, get_power_fn):
status = "off"
if options.has_key("--plugs"):
for plug in options["--plugs"]:
try:
options["--uuid"] = str(uuid.UUID(plug))
except ValueError:
pass
except KeyError:
pass
options["--plug"] = plug
plug_status = get_power_fn(tn, options)
if plug_status != "off":
status = plug_status
else:
status = get_power_fn(tn, options)
return status
def set_multi_power_fn(tn, options, set_power_fn):
if options.has_key("--plugs"):
for plug in options["--plugs"]:
try:
options["--uuid"] = str(uuid.UUID(plug))
except ValueError:
pass
except KeyError:
pass
options["--plug"] = plug
set_power_fn(tn, options)
else:
set_power_fn(tn, options)
def show_docs(options, docs = None):
device_opt = options["device_opt"]
if docs == None:
docs = { }
docs["shortdesc"] = "Fence agent"
docs["longdesc"] = ""
## Process special options (and exit)
#####
if options.has_key("--help"):
usage(device_opt)
sys.exit(0)
if options.has_key("--action") and options["--action"].lower() == "metadata":
metadata(device_opt, options, docs)
sys.exit(0)
if options.has_key("--version"):
print __main__.RELEASE_VERSION, __main__.BUILD_DATE
print __main__.REDHAT_COPYRIGHT
sys.exit(0)
def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = None, reboot_cycle_fn = None):
result = 0
try:
if options.has_key("--plug"):
options["--plugs"] = options["--plug"].split(",")
## Process options that manipulate fencing device
#####
if (options["--action"] == "list") and 0 == options["device_opt"].count("port"):
print "N/A"
return
elif (options["--action"] == "list" and get_outlet_list == None):
## @todo: exception?
## This is just temporal solution, we will remove default value
## None as soon as all existing agent will support this operation
print "NOTICE: List option is not working on this device yet"
return
elif (options["--action"] == "list") or \
((options["--action"] == "monitor") and 1 == options["device_opt"].count("port")):
outlets = get_outlet_list(tn, options)
## keys can be numbers (port numbers) or strings (names of VM)
for outlet_id in outlets.keys():
(alias, status) = outlets[outlet_id]
if options["--action"] != "monitor":
print outlet_id + options["--separator"] + alias
return
status = get_multi_power_fn(tn, options, get_power_fn)
if status != "on" and status != "off":
fail(EC_STATUS)
if options["--action"] == "on":
if status == "on":
print "Success: Already ON"
else:
power_on = False
for _ in range(1, 1 + int(options["--retry-on"])):
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn):
power_on = True
break
if power_on:
print "Success: Powered ON"
else:
fail(EC_WAITING_ON)
elif options["--action"] == "off":
if status == "off":
print "Success: Already OFF"
else:
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn):
print "Success: Powered OFF"
else:
fail(EC_WAITING_OFF)
elif options["--action"] == "reboot":
power_on = False
if options.has_key("--method") and options["--method"].lower() == "cycle" and reboot_cycle_fn is not None:
for _ in range(1, 1 + int(options["--retry-on"])):
if reboot_cycle_fn(tn, options):
power_on = True
break
if not power_on:
fail(EC_TIMED_OUT)
else:
if status != "off":
options["--action"] = "off"
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn) == 0:
fail(EC_WAITING_OFF)
options["--action"] = "on"
try:
for _ in range(1, 1 + int(options["--retry-on"])):
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn) == 1:
power_on = True
break
except Exception, ex:
# an error occured during power ON phase in reboot
# fence action was completed succesfully even in that case
logging.error("%s\n", str(ex))
syslog.syslog(syslog.LOG_NOTICE, str(ex))
if power_on == False:
# this should not fail as node was fenced succesfully
logging.error('Timed out waiting to power ON\n')
syslog.syslog(syslog.LOG_NOTICE, "Timed out waiting to power ON")
print "Success: Rebooted"
elif options["--action"] == "status":
print "Status: " + status.upper()
if status.upper() == "OFF":
result = 2
elif options["--action"] == "monitor":
pass
except pexpect.EOF:
fail(EC_CONNECTION_LOST)
except pexpect.TIMEOUT:
fail(EC_TIMED_OUT)
except pycurl.error, ex:
logging.error("%s\n" % str(ex))
syslog.syslog(syslog.LOG_ERR, ex[1])
fail(EC_TIMED_OUT)
return result
def fence_login(options, re_login_string = r"(login\s*: )|(Login Name: )|(username: )|(User Name :)"):
force_ipvx = ""
if (options.has_key("--inet6-only")):
force_ipvx = "-6 "
if (options.has_key("--inet4-only")):
force_ipvx = "-4 "
if (options.has_key("eol") == False):
options["eol"] = "\r\n"
if options.has_key("--command-prompt") and type(options["--command-prompt"]) is not list:
options["--command-prompt"] = [ options["--command-prompt"] ]
## Do the delay of the fence device before logging in
## Delay is important for two-node clusters fencing but we do not need to delay 'status' operations
if options["--action"] in ["off", "reboot"]:
logging.info("Delay %s second(s) before logging in to the fence device" % options["--delay"])
time.sleep(int(options["--delay"]))
try:
re_login = re.compile(re_login_string, re.IGNORECASE)
re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
if options.has_key("--ssl"):
gnutls_opts = ""
if options.has_key("--notls"):
gnutls_opts = "--priority \"NORMAL:-VERS-TLS1.2:-VERS-TLS1.1:-VERS-TLS1.0:+VERS-SSL3.0\""
command = '%s %s --insecure --crlf -p %s %s' % \
(SSL_PATH, gnutls_opts, options["--ipport"], options["--ip"])
try:
conn = fspawn(options, command)
except pexpect.ExceptionPexpect, ex:
logging.error("%s\n" % str(ex))
syslog.syslog(syslog.LOG_ERR, str(ex))
sys.exit(EC_GENERIC_ERROR)
elif options.has_key("--ssh") and 0 == options.has_key("--identity-file"):
command = '%s %s %s@%s -p %s -o PubkeyAuthentication=no' % \
(SSH_PATH, force_ipvx, options["--username"], options["--ip"], options["--ipport"])
if options.has_key("--ssh-options"):
command += ' ' + options["--ssh-options"]
conn = fspawn(options, command)
if options.has_key("telnet_over_ssh"):
# This is for stupid ssh servers (like ALOM) which behave more like telnet
# (ignore name and display login prompt)
result = conn.log_expect(options, \
[ re_login, "Are you sure you want to continue connecting (yes/no)?" ],
int(options["--login-timeout"]))
if result == 1:
conn.sendline("yes") # Host identity confirm
conn.log_expect(options, re_login, int(options["--login-timeout"]))
conn.sendline(options["--username"])
conn.log_expect(options, re_pass, int(options["--login-timeout"]))
else:
result = conn.log_expect(options, \
[ "ssword:", "Are you sure you want to continue connecting (yes/no)?" ],
int(options["--login-timeout"]))
if result == 1:
conn.sendline("yes")
conn.log_expect(options, "ssword:", int(options["--login-timeout"]))
conn.sendline(options["--password"])
conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
elif options.has_key("--ssh") and options.has_key("--identity-file"):
command = '%s %s %s@%s -i %s -p %s' % \
(SSH_PATH, force_ipvx, options["--username"], options["--ip"], \
options["--identity-file"], options["--ipport"])
if options.has_key("--ssh-options"):
command += ' ' + options["--ssh-options"]
conn = fspawn(options, command)
result = conn.log_expect(options, [ "Enter passphrase for key '" + options["--identity-file"] + "':", \
"Are you sure you want to continue connecting (yes/no)?" ] + \
options["--command-prompt"], int(options["--login-timeout"]))
if result == 1:
conn.sendline("yes")
result = conn.log_expect(options,
[ "Enter passphrase for key '" + options["--identity-file"]+"':"] + \
options["--command-prompt"], int(options["--login-timeout"]))
if result == 0:
if options.has_key("--password"):
conn.sendline(options["--password"])
conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
else:
fail_usage("Failed: You have to enter passphrase (-p) for identity file")
else:
conn = fspawn(options, TELNET_PATH)
conn.send("set binary\n")
conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
result = conn.log_expect(options, re_login, int(options["--login-timeout"]))
conn.send_eol(options["--username"])
## automatically change end of line separator
screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
if (re_login.search(screen) != None):
options["eol"] = "\n"
conn.send_eol(options["--username"])
result = conn.log_expect(options, re_pass, int(options["--login-timeout"]))
elif (re_pass.search(screen) == None):
conn.log_expect(options, re_pass, int(options["--shell-timeout"]))
try:
conn.send_eol(options["--password"])
valid_password = conn.log_expect(options, [ re_login ] + \
options["--command-prompt"], int(options["--shell-timeout"]))
if valid_password == 0:
## password is invalid or we have to change EOL separator
options["eol"] = "\r"
conn.send_eol("")
screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
## after sending EOL the fence device can either show 'Login' or 'Password'
if (re_login.search(screen) != None):
conn.send_eol("")
conn.send_eol(options["--username"])
conn.log_expect(options, re_pass, int(options["--login-timeout"]))
conn.send_eol(options["--password"])
conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
except KeyError:
fail(EC_PASSWORD_MISSING)
except pexpect.EOF:
fail(EC_LOGIN_DENIED)
except pexpect.TIMEOUT:
fail(EC_LOGIN_DENIED)
return conn
def is_executable(path):
if os.path.exists(path):
stats = os.stat(path)
if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
return True
return False
diff --git a/fence/agents/lib/fencing_snmp.py.py b/fence/agents/lib/fencing_snmp.py.py
index d8dd7464..9ebdcbc1 100644
--- a/fence/agents/lib/fencing_snmp.py.py
+++ b/fence/agents/lib/fencing_snmp.py.py
@@ -1,137 +1,137 @@
#!/usr/bin/python -tt
# For example of use please see fence_cisco_mds
import re, pexpect
import logging
from fencing import *
-from fencing import fail, fail_usage, EC_TIMED_OUT, LOG_MODE_VERBOSE
+from fencing import fail, fail_usage, EC_TIMED_OUT
__all__ = [ 'FencingSnmp' ]
## do not add code here.
#BEGIN_VERSION_GENERATION
RELEASE_VERSION = ""
REDHAT_COPYRIGHT = ""
BUILD_DATE = ""
#END_VERSION_GENERATION
class FencingSnmp:
def __init__(self, options):
self.options = options
# Log message if user set verbose option
def log_command(self, message):
logging.debug("%s\n" % message)
def quote_for_run(self, string):
return ''.join(map(lambda x:x==r"'" and "'\\''" or x, string))
def complete_missed_params(self):
mapping = [[
['snmp-priv-passwd','password','!snmp-sec-level'],
'self.options["--snmp-sec-level"]="authPriv"'
],[
['!snmp-version','community','!username','!snmp-priv-passwd','!password'],
'self.options["--snmp-version"]="2c"'
]]
for val in mapping:
e = val[0]
res = True
for item in e:
if ((item[0]=='!') and (self.options.has_key("--"+item[1:]))):
res = False
break
if ((item[0]!='!') and (not self.options.has_key("--"+item[0:]))):
res = False
break
if res:
exec(val[1])
def prepare_cmd(self, command):
cmd = "@SNMPBIN@/%s -m '' -Oeqn "% (command)
self.complete_missed_params()
#mapping from our option to snmpcmd option
mapping = (('snmp-version', 'v'),('community', 'c'))
for item in mapping:
if (self.options.has_key("--" + item[0])):
cmd += " -%s '%s'"% (item[1], self.quote_for_run(self.options["--" + item[0]]))
# Some options make sense only for v3 (and for v1/2c can cause "problems")
if (self.options.has_key("--snmp-version")) and (self.options["--snmp-version"] == "3"):
# Mapping from our options to snmpcmd options for v3
mapping_v3 = (('snmp-auth-prot','a'), ('snmp-sec-level','l'), ('snmp-priv-prot','x'), \
('snmp-priv-passwd','X'),('password','A'),('username','u'))
for item in mapping_v3:
if (self.options.has_key("--"+item[0])):
cmd += " -%s '%s'"% (item[1], self.quote_for_run(self.options["--" + item[0]]))
force_ipvx = ""
if (self.options.has_key("--inet6-only")):
force_ipvx = "udp6:"
if (self.options.has_key("--inet4-only")):
force_ipvx = "udp:"
cmd += " '%s%s%s'"% (force_ipvx, self.quote_for_run(self.options["--ip"]),
self.options.has_key("--ipport") and self.quote_for_run(":" + str (self.options["--ipport"])) or "")
return cmd
def run_command(self, command, additional_timemout=0):
try:
self.log_command(command)
(res_output, res_code) = pexpect.run(command,
int(self.options["--shell-timeout"]) +
int(self.options["--login-timeout"]) +
additional_timemout, True)
if (res_code==None):
fail(EC_TIMED_OUT)
self.log_command(res_output)
if (res_code!=0) or (re.search("^Error ", res_output, re.MULTILINE) != None):
fail_usage("Returned %d: %s"% (res_code, res_output))
except pexpect.ExceptionPexpect:
fail_usage("Cannot run command %s"%(command))
return res_output
def get(self, oid, additional_timemout=0):
cmd = "%s '%s'"% (self.prepare_cmd("snmpget"), self.quote_for_run(oid))
output = self.run_command(cmd, additional_timemout).splitlines()
return output[len(output)-1].split(None, 1)
def set(self, oid, value, additional_timemout=0):
mapping = ((int, 'i'), (str, 's'))
type_of_value = ''
for item in mapping:
if (isinstance(value, item[0])):
type_of_value = item[1]
break
cmd = "%s '%s' %s '%s'" % (self.prepare_cmd("snmpset"),
self.quote_for_run(oid), type_of_value, self.quote_for_run(str(value)))
self.run_command(cmd, additional_timemout)
def walk(self, oid, additional_timemout=0):
cmd = "%s '%s'"% (self.prepare_cmd("snmpwalk"), self.quote_for_run(oid))
output = self.run_command(cmd, additional_timemout).splitlines()
return map(lambda x:x.split(None, 1), filter(lambda y:len(y)>0 and y[0]=='.', output))
diff --git a/fence/agents/rhevm/fence_rhevm.py b/fence/agents/rhevm/fence_rhevm.py
index 767c0985..54af81b2 100644
--- a/fence/agents/rhevm/fence_rhevm.py
+++ b/fence/agents/rhevm/fence_rhevm.py
@@ -1,133 +1,133 @@
#!/usr/bin/python -tt
import sys, re
import pycurl, StringIO
import logging
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
-from fencing import fail, EC_STATUS, LOG_MODE_VERBOSE
+from fencing import fail, EC_STATUS
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="New RHEV-M Agent - test release on steroids"
REDHAT_COPYRIGHT=""
BUILD_DATE="March, 2008"
#END_VERSION_GENERATION
RE_GET_ID = re.compile("<vm( .*)? id=\"(.*?)\"", re.IGNORECASE)
RE_STATUS = re.compile("<state>(.*?)</state>", re.IGNORECASE)
RE_GET_NAME = re.compile("<name>(.*?)</name>", re.IGNORECASE)
def get_power_status(conn, options):
del conn
### Obtain real ID from name
res = send_command(options, "vms/?search=name%3D" + options["--plug"])
result = RE_GET_ID.search(res)
if (result == None):
# Unable to obtain ID needed to access virtual machine
fail(EC_STATUS)
options["id"] = result.group(2)
result = RE_STATUS.search(res)
if (result == None):
# We were able to parse ID so output is correct
# in some cases it is possible that RHEV-M output does not
# contain <status> line. We can assume machine is OFF then
return "off"
else:
status = result.group(1)
if (status.lower() == "down"):
return "off"
else:
return "on"
def set_power_status(conn, options):
del conn
action = {
'on' : "start",
'off' : "stop"
}[options["--action"]]
url = "vms/" + options["id"] + "/" + action
send_command(options, url, "POST")
def get_list(conn, options):
del conn
outlets = { }
try:
res = send_command(options, "vms")
lines = res.split("<vm ")
for i in range(1, len(lines)):
name = RE_GET_NAME.search(lines[i]).group(1)
outlets[name] = ("", None)
except AttributeError:
return { }
except IndexError:
return { }
return outlets
def send_command(opt, command, method = "GET"):
## setup correct URL
if opt.has_key("--ssl"):
url = "https:"
else:
url = "http:"
url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + "/api/" + command
## send command through pycurl
conn = pycurl.Curl()
web_buffer = StringIO.StringIO()
conn.setopt(pycurl.URL, url)
conn.setopt(pycurl.HTTPHEADER, [ "Content-type: application/xml", "Accept: application/xml" ])
conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"])
conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
conn.setopt(pycurl.SSL_VERIFYPEER, 0)
conn.setopt(pycurl.SSL_VERIFYHOST, 0)
if (method == "POST"):
conn.setopt(pycurl.POSTFIELDS, "<action />")
conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
conn.perform()
result = web_buffer.getvalue()
logging.debug("%s\n" % command)
logging.debug("%s\n" % result)
return result
def main():
device_opt = [ "ipaddr", "login", "passwd", "ssl", "notls", "web", "port" ]
atexit.register(atexit_handler)
all_opt["power_wait"]["default"] = "1"
options = check_input(device_opt, process_input(device_opt))
docs = { }
docs["shortdesc"] = "Fence agent for RHEV-M REST API"
docs["longdesc"] = "fence_rhevm is an I/O Fencing agent which can be \
used with RHEV-M REST API to fence virtual machines."
docs["vendorurl"] = "http://www.redhat.com"
show_docs(options, docs)
##
## Fence operations
####
result = fence_action(None, options, set_power_status, get_power_status, get_list)
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/vmware/fence_vmware.py b/fence/agents/vmware/fence_vmware.py
index c9310fb1..b5cca485 100644
--- a/fence/agents/vmware/fence_vmware.py
+++ b/fence/agents/vmware/fence_vmware.py
@@ -1,344 +1,344 @@
#!/usr/bin/python -tt
#
# 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
import logging
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
-from fencing import fail, fail_usage, EC_TIMED_OUT, LOG_MODE_VERBOSE
+from fencing import fail, fail_usage, EC_TIMED_OUT
#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(text):
dstr = ''
for c in text:
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["--exec"]
if (add_login_params):
if (vmware_internal_type==VMWARE_TYPE_ESX):
res += " --server '%s' --username '%s' --password '%s' "% (quote_for_run(options["--ip"]),
quote_for_run(options["--username"]),
quote_for_run(options["--password"]))
elif (vmware_internal_type==VMWARE_TYPE_SERVER2):
res += " -h 'https://%s/sdk' -u '%s' -p '%s' -T server "% (quote_for_run(options["--ip"]),
quote_for_run(options["--username"]),
quote_for_run(options["--password"]))
elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
host_name_array = options["--ip"].split(':')
res += " -h '%s' -u '%s' -p '%s' -T server1 "% (quote_for_run(host_name_array[0]),
quote_for_run(options["--username"]),
quote_for_run(options["--password"]))
if (len(host_name_array)>1):
res += "-P '%s' "% (quote_for_run(host_name_array[1]))
if ((options.has_key("--vmware-datacenter")) and (vmware_internal_type==VMWARE_TYPE_ESX)):
res += "--datacenter '%s' "% (quote_for_run(options["--vmware-datacenter"]))
if (additional_params != ""):
res += additional_params
return res
# Log message if user set verbose option
def vmware_log(options, message):
logging.debug("%s\n" % message)
# 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["--shell-timeout"]) + int(options["--login-timeout"]) + 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["--exec"], res_output))
else:
vmware_log(options, res_output)
except pexpect.ExceptionPexpect:
fail_usage("Cannot run command %s"% (options["--exec"]))
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(options, add_vm_name):
outlets = {}
if (add_vm_name):
all_machines = vmware_run_command(options, True,
("--operation status --vmname '%s'"% (quote_for_run(options["--plug"]))), 0)
else:
all_machines = vmware_run_command(options, True, "--operation list", int(options["--power-timeout"]))
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(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):
del conn
if (vmware_internal_type==VMWARE_TYPE_ESX):
return vmware_get_outlets_vi(options, False)
if ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
return vmware_get_outlets_vix(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["--plug"] in outlets)):
fail_usage("Failed: You have to enter existing name of virtual machine!")
else:
return outlets[options["--plug"]][1]
elif (vmware_internal_type==VMWARE_TYPE_SERVER1):
return ((options["--plug"] in outlets) and "on" or "off")
def set_power_status(conn, options):
del conn
if (vmware_internal_type==VMWARE_TYPE_ESX):
additional_params = "--operation %s --vmname '%s'" % \
((options["--action"]=="on" and "on" or "off"), quote_for_run(options["--plug"]))
elif ((vmware_internal_type==VMWARE_TYPE_SERVER1) or (vmware_internal_type==VMWARE_TYPE_SERVER2)):
additional_params = "%s '%s'" % \
((options["--action"]=="on" and "start" or "stop"), quote_for_run(options["--plug"]))
if (options["--action"]=="off"):
additional_params += " hard"
vmware_run_command(options, True, additional_params, int(options["--power-timeout"]))
# 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(r"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
# Check vmware type, set vmware_internal_type to one of VMWARE_TYPE_ value and
# options["--exec"] to path (if not specified)
def vmware_check_vmware_type(options):
global vmware_internal_type
options["--vmware_type"] = options["--vmware_type"].lower()
if (options["--vmware_type"]=="esx"):
vmware_internal_type = VMWARE_TYPE_ESX
if (not options.has_key("--exec")):
options["--exec"] = VMHELPER_COMMAND
elif (options["--vmware_type"]=="server2"):
vmware_internal_type = VMWARE_TYPE_SERVER2
if (not options.has_key("--exec")):
options["--exec"] = VMRUN_COMMAND
elif (options["--vmware_type"]=="server1"):
vmware_internal_type = VMWARE_TYPE_SERVER1
if (not options.has_key("--exec")):
options["--exec"] = VMRUN_COMMAND
else:
fail_usage("vmware_type can be esx,server2 or server1!")
# Main agent method
def main():
device_opt = [ "ipaddr", "login", "passwd", "secure",
"exec", "vmware_type", "vmware_datacenter"]
atexit.register(atexit_handler)
all_opt["secure"]["default"] = "1"
all_opt["vmware_type"]["default"] = VMWARE_DEFAULT_TYPE
options = check_input(device_opt, process_input(device_opt))
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
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Feb 25, 1:00 AM (19 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464578
Default Alt Text
(77 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment