Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624703
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
44 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/agents/apc/fence_apc.py b/agents/apc/fence_apc.py
index 24a5a423..dd0287f8 100644
--- a/agents/apc/fence_apc.py
+++ b/agents/apc/fence_apc.py
@@ -1,260 +1,262 @@
#!@PYTHON@ -tt
#####
##
## The Following Agent Has Been Tested On:
##
## Model Firmware
## +---------------------------------------------+
## AP7951 AOS v2.7.0, PDU APP v2.7.3
## AP7941 AOS v3.5.7, PDU APP v3.5.6
## AP9606 AOS v2.5.4, PDU APP v2.7.3
##
## @note: ssh is very slow on AP79XX devices protocol (1) and
## cipher (des/blowfish) have to be defined
#####
import sys, re, time
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing import fail, fail_usage, EC_STATUS
# Fix for connection timed out issue in:
# https://bugzilla.redhat.com/show_bug.cgi?id=1342584
TIMEDOUT_DELAY = 0.5
def get_power_status(conn, options):
exp_result = 0
outlets = {}
conn.send_eol("1")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
version = 0
admin = 0
switch = 0
if None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before):
switch = 1
if None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before):
if "--switch" not in options:
fail_usage("Failed: You have to enter physical switch number")
else:
if "--switch" not in options:
options["--switch"] = "1"
if None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before):
version = 2
else:
version = 3
if None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before):
admin = 0
else:
admin = 1
if switch == 0:
if version == 2:
if admin == 0:
conn.send_eol("2")
else:
conn.send_eol("3")
else:
conn.send_eol("2")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
conn.send_eol("1")
else:
conn.send_eol(options["--switch"])
while True:
exp_result = conn.log_expect(
["Press <ENTER>"] + options["--command-prompt"], int(options["--shell-timeout"]))
lines = conn.before.split("\n")
show_re = re.compile(r'(^|\x0D)\s*(\d+)- (.*?)\s+(ON|OFF)\s*')
for line in lines:
res = show_re.search(line)
if res != None:
outlets[res.group(2)] = (res.group(3), res.group(4))
time.sleep(TIMEDOUT_DELAY)
conn.send_eol("")
if exp_result != 0:
break
conn.send(chr(0o3))
conn.log_expect("- Logout", int(options["--shell-timeout"]))
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
if ["list", "monitor"].count(options["--action"]) == 1:
return outlets
else:
try:
(_, status) = outlets[options["--plug"]]
return status.lower().strip()
- except KeyError:
+ except KeyError as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_STATUS)
def set_power_status(conn, options):
action = {
'on' : "1",
'off': "2"
}[options["--action"]]
conn.send_eol("1")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
version = 0
admin2 = 0
admin3 = 0
switch = 0
if None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before):
switch = 1
## MasterSwitch has different schema for on/off actions
action = {
'on' : "1",
'off': "3"
}[options["--action"]]
if None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before):
if "--switch" not in options:
fail_usage("Failed: You have to enter physical switch number")
else:
if "--switch" not in options:
options["--switch"] = 1
if None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before):
version = 2
else:
version = 3
if None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before):
admin2 = 0
else:
admin2 = 1
if switch == 0:
if version == 2:
if admin2 == 0:
conn.send_eol("2")
else:
conn.send_eol("3")
else:
conn.send_eol("2")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
if None == re.compile('.*2- Outlet Restriction.*', re.IGNORECASE | re.S).match(conn.before):
admin3 = 0
else:
admin3 = 1
conn.send_eol("1")
else:
conn.send_eol(options["--switch"])
while 0 == conn.log_expect(
["Press <ENTER>"] + options["--command-prompt"], int(options["--shell-timeout"])):
time.sleep(TIMEDOUT_DELAY)
conn.send_eol("")
conn.send_eol(options["--plug"]+"")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
if switch == 0:
if admin2 == 1:
conn.send_eol("1")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
if admin3 == 1:
conn.send_eol("1")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
else:
conn.send_eol("1")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
conn.send_eol(action)
conn.log_expect("Enter 'YES' to continue or <ENTER> to cancel :", int(options["--shell-timeout"]))
conn.send_eol("YES")
conn.log_expect("Press <ENTER> to continue...", int(options["--power-timeout"]))
time.sleep(TIMEDOUT_DELAY)
conn.send_eol("")
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
conn.send(chr(0o3))
conn.log_expect("- Logout", int(options["--shell-timeout"]))
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
def get_power_status5(conn, options):
outlets = {}
conn.send_eol("olStatus all")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
lines = conn.before.split("\n")
show_re = re.compile(r'^\s*(\d+): (.*): (On|Off)\s*$', re.IGNORECASE)
for line in lines:
res = show_re.search(line)
if res != None:
outlets[res.group(1)] = (res.group(2), res.group(3))
if ["list", "monitor"].count(options["--action"]) == 1:
return outlets
else:
try:
(_, status) = outlets[options["--plug"]]
return status.lower().strip()
- except KeyError:
+ except KeyError as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_STATUS)
def set_power_status5(conn, options):
action = {
'on' : "olOn",
'off': "olOff"
}[options["--action"]]
conn.send_eol(action + " " + options["--plug"])
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
def main():
device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
"port", "switch", "telnet"]
atexit.register(atexit_handler)
all_opt["cmd_prompt"]["default"] = ["\n>", "\napc>"]
all_opt["ssh_options"]["default"] = "-1 -c blowfish"
options = check_input(device_opt, process_input(device_opt))
docs = {}
docs["shortdesc"] = "Fence agent for APC over telnet/ssh"
docs["longdesc"] = "fence_apc is an I/O Fencing agent \
which can be used with the APC network power switch. It logs into device \
via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections \
should be avoided while a GFS cluster is running because the connection \
will block any necessary fencing actions."
docs["vendorurl"] = "http://www.apc.com"
show_docs(options, docs)
## Support for --plug [switch]:[plug] notation that was used before
if (("--plug" in options) == 1) and (-1 != options["--plug"].find(":")):
(switch, plug) = options["--plug"].split(":", 1)
options["--switch"] = switch
options["--plug"] = plug
##
## Operate the fencing device
####
conn = fence_login(options)
## Detect firmware version (ASCII menu vs command-line interface)
## and continue with proper action
####
result = -1
firmware_version = re.compile(r'\s*v(\d)*\.').search(conn.before)
if (firmware_version != None) and (firmware_version.group(1) in [ "5", "6" ]):
result = fence_action(conn, options, set_power_status5, get_power_status5, get_power_status5)
else:
result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
fence_logout(conn, "4")
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/agents/cisco_ucs/fence_cisco_ucs.py b/agents/cisco_ucs/fence_cisco_ucs.py
index ec311754..2280dbbc 100644
--- a/agents/cisco_ucs/fence_cisco_ucs.py
+++ b/agents/cisco_ucs/fence_cisco_ucs.py
@@ -1,196 +1,197 @@
#!@PYTHON@ -tt
import sys, re
import pycurl, io
import logging
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing import fail, EC_STATUS, EC_LOGIN_DENIED, run_delay
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_PNDN = re.compile(" pndn=\"(.*?)\"", re.IGNORECASE)
RE_GET_DESC = re.compile(" descr=\"(.*?)\"", re.IGNORECASE)
RE_GET_OPERPOWER = re.compile(" operPower=\"(.*?)\"", re.IGNORECASE)
RE_GET_PRESENCE = re.compile(" presence=\"(.*?)\"", re.IGNORECASE)
options_global = None
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"] + "\"/>", int(options["--shell-timeout"]))
result = RE_GET_PNDN.search(res)
if result == None:
pndn = ""
else:
pndn = result.group(1)
if pndn.strip() == "":
if "--missing-as-off" in options:
return "off"
else:
fail(EC_STATUS)
res = send_command(options, "<configResolveDn cookie=\"" + options["cookie"] +
"\" inHierarchical=\"false\" dn=\"" + pndn +
"\"/>", int(options["--shell-timeout"]))
result = RE_GET_PRESENCE.search(res)
if result == None:
fail(EC_STATUS)
else:
presence_status = result.group(1)
if presence_status in ["missing", "mismatch"]:
return "off"
else:
result = RE_GET_OPERPOWER.search(res)
if result == None:
fail(EC_STATUS)
else:
power_status = result.group(1)
if power_status == "on":
return "on"
else:
return "off"
def set_power_status(conn, options):
del conn
action = {
'on' : "admin-up",
'off' : "admin-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 "--ssl" in opt or "--ssl-secure" in opt or "--ssl-insecure" in opt:
url = "https:"
else:
url = "http:"
url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + "/nuova"
## send command through pycurl
conn = pycurl.Curl()
web_buffer = io.BytesIO()
conn.setopt(pycurl.URL, url.encode("ascii"))
conn.setopt(pycurl.HTTPHEADER, ["Content-type: text/xml"])
conn.setopt(pycurl.POSTFIELDS, command.encode("ascii"))
conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
conn.setopt(pycurl.TIMEOUT, timeout)
if "--ssl" in opt or "--ssl-secure" in opt:
conn.setopt(pycurl.SSL_VERIFYPEER, 1)
conn.setopt(pycurl.SSL_VERIFYHOST, 2)
if "--ssl-insecure" in opt:
conn.setopt(pycurl.SSL_VERIFYPEER, 0)
conn.setopt(pycurl.SSL_VERIFYHOST, 0)
conn.perform()
result = web_buffer.getvalue().decode()
logging.debug("%s\n", command)
logging.debug("%s\n", result)
return result
def define_new_opts():
all_opt["suborg"] = {
"getopt" : ":",
"longopt" : "suborg",
"help" : "--suborg=[path] Additional path needed to access suborganization",
"required" : "0",
"shortdesc" : "Additional path needed to access suborganization",
"default" : "",
"order" : 1}
def logout():
### Logout; we do not care about result as we will end in any case
try:
send_command(options_global, "<aaaLogout inCookie=\"" + options_global["cookie"] + "\" />",
int(options_global["--shell-timeout"]))
except Exception:
pass
def main():
global options_global
device_opt = ["ipaddr", "login", "passwd", "ssl", "notls", "port", "web", "suborg", "missing_as_off"]
atexit.register(atexit_handler)
atexit.register(logout)
define_new_opts()
options_global = 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_global, docs)
run_delay(options_global)
### Login
try:
res = send_command(options_global, "<aaaLogin inName=\"" + options_global["--username"] +
"\" inPassword=\"" + options_global["--password"] + "\" />", int(options_global["--login-timeout"]))
result = RE_COOKIE.search(res)
if result == None:
## Cookie is absenting in response
fail(EC_LOGIN_DENIED)
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_LOGIN_DENIED)
options_global["cookie"] = result.group(1)
##
## Modify suborg to format /suborg
if options_global["--suborg"] != "":
options_global["--suborg"] = "/" + options_global["--suborg"].lstrip("/").rstrip("/")
##
## Fence operations
####
result = fence_action(None, options_global, set_power_status, get_power_status, get_list)
## Logout is done every time at atexit phase
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/agents/eps/fence_eps.py b/agents/eps/fence_eps.py
index 74c89b95..f0df8623 100644
--- a/agents/eps/fence_eps.py
+++ b/agents/eps/fence_eps.py
@@ -1,128 +1,129 @@
#!@PYTHON@ -tt
# The Following Agent Has Been Tested On:
# ePowerSwitch 8M+ version 1.0.0.4
import sys, re
import 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, run_delay
if sys.version_info[0] > 2:
import http.client as httplib
else:
import httplib
# 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 "--username" in options:
if "--password" not in options:
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:
+ except socket.error as e:
+ logging.error("Failed: {}".format(str(e)))
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", "web"]
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_delay(options)
#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/agents/ilo_moonshot/fence_ilo_moonshot.py b/agents/ilo_moonshot/fence_ilo_moonshot.py
index a066a9c9..6f5cca32 100644
--- a/agents/ilo_moonshot/fence_ilo_moonshot.py
+++ b/agents/ilo_moonshot/fence_ilo_moonshot.py
@@ -1,63 +1,64 @@
#!@PYTHON@ -tt
import sys
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing import fail, EC_STATUS
def get_power_status(conn, options):
conn.send_eol("show node list")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
nodes = {}
for line in conn.before.splitlines():
if len(line.split()) == 10:
nodes[line.split()[1]] = ("", line.split()[8].lower().strip())
if ["list", "monitor"].count(options["--action"]) == 1:
return nodes
else:
try:
(_, status) = nodes[options["--plug"]]
return status.lower()
- except KeyError:
+ except KeyError as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_STATUS)
def set_power_status(conn, options):
if options["--action"] == "on":
conn.send_eol("set node power on %s" % (options["--plug"]))
else:
conn.send_eol("set node power off force %s" % (options["--plug"]))
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
return
def main():
device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", "port"]
atexit.register(atexit_handler)
all_opt["secure"]["default"] = "1"
all_opt["cmd_prompt"]["default"] = ["MP>", "hpiLO->"]
options = check_input(device_opt, process_input(device_opt))
docs = {}
docs["shortdesc"] = "Fence agent for HP Moonshot iLO"
docs["longdesc"] = ""
docs["vendorurl"] = "http://www.hp.com"
show_docs(options, docs)
conn = fence_login(options)
##
## Fence operations
####
result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
fence_logout(conn, "exit")
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/agents/lpar/fence_lpar.py b/agents/lpar/fence_lpar.py
index a1610373..66cb65e4 100644
--- a/agents/lpar/fence_lpar.py
+++ b/agents/lpar/fence_lpar.py
@@ -1,179 +1,181 @@
#!@PYTHON@ -tt
#####
##
## The Following Agent Has Been Tested On:
##
## Version
## +---------------------------------------------+
## Tested on HMC
##
#####
import sys, re
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing import fail, fail_usage, EC_STATUS_HMC
##
## Transformation to standard ON/OFF status if possible
def _normalize_status(status):
if status in ["Running", "Open Firmware", "Shutting Down", "Starting"]:
status = "on"
else:
status = "off"
return status
def get_power_status(conn, options):
if options["--hmc-version"] == "3":
conn.send("lssyscfg -r lpar -m " + options["--managed"] + " -n " + options["--plug"] + " -F name,state\n")
# First line (command) may cause parsing issues if long
conn.readline()
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
try:
status = re.compile("^" + options["--plug"] + ",(.*?),.*$",
re.IGNORECASE | re.MULTILINE).search(conn.before).group(1)
- except AttributeError:
+ except AttributeError as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_STATUS_HMC)
elif options["--hmc-version"] in ["4", "IVM"]:
conn.send("lssyscfg -r lpar -m "+ options["--managed"] +
" --filter 'lpar_names=" + options["--plug"] + "'\n")
# First line (command) may cause parsing issues if long
conn.readline()
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
try:
status = re.compile(",state=(.*?),", re.IGNORECASE).search(conn.before).group(1)
- except AttributeError:
+ except AttributeError as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_STATUS_HMC)
return _normalize_status(status)
def set_power_status(conn, options):
if options["--hmc-version"] == "3":
conn.send("chsysstate -o " + options["--action"] + " -r lpar -m " + options["--managed"]
+ " -n " + options["--plug"] + "\n")
# First line (command) may cause parsing issues if long
conn.readline()
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
elif options["--hmc-version"] in ["4", "IVM"]:
if options["--action"] == "on":
conn.send("chsysstate -o on -r lpar -m " + options["--managed"] +
" -n " + options["--plug"] +
" -f `lssyscfg -r lpar -F curr_profile " +
" -m " + options["--managed"] +
" --filter \"lpar_names=" + options["--plug"] + "\"`\n")
else:
conn.send("chsysstate -o shutdown -r lpar --immed" +
" -m " + options["--managed"] + " -n " + options["--plug"] + "\n")
# First line (command) may cause parsing issues if long
conn.readline()
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
def get_lpar_list(conn, options):
outlets = {}
if options["--hmc-version"] == "3":
conn.send("query_partition_names -m " + options["--managed"] + "\n")
## We have to remove first line (command)
conn.readline()
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
## We have to remove next 2 lines (header) and last line (part of new prompt)
####
res = re.search("^(.+?\n){2}(.*)\n.*$", conn.before, re.S)
if res == None:
fail_usage("Unable to parse output of list command")
lines = res.group(2).split("\n")
for outlet_line in lines:
outlets[outlet_line.rstrip()] = ("", "")
elif options["--hmc-version"] in ["4", "IVM"]:
sep = ":" if options["--hmc-version"] == "4" else ","
conn.send("lssyscfg -r lpar -m " + options["--managed"] +
" -F name" + sep + "state\n")
## We have to remove first line (command)
conn.readline()
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
## We have to remove last line (part of new prompt)
####
res = re.search("^(.*)\n.*$", conn.before, re.S)
if res == None:
fail_usage("Unable to parse output of list command")
lines = res.group(1).split("\n")
for outlet_line in lines:
try:
(port, status) = outlet_line.rstrip().split(sep)
except ValueError:
fail_usage('Output does not match expected HMC version, try different one');
outlets[port] = ("", _normalize_status(status))
return outlets
def define_new_opts():
all_opt["managed"] = {
"getopt" : "s:",
"longopt" : "managed",
"help" : "-s, --managed=[id] Name of the managed system",
"required" : "1",
"shortdesc" : "Managed system name",
"order" : 1}
all_opt["hmc_version"] = {
"getopt" : "H:",
"longopt" : "hmc-version",
"help" : "-H, --hmc-version=[version] Force HMC version to use: (3|4|ivm) (default: 4)",
"required" : "0",
"shortdesc" : "Force HMC version to use",
"default" : "4",
"choices" : ["3", "4", "ivm"],
"order" : 1}
def main():
device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", \
"port", "managed", "hmc_version"]
atexit.register(atexit_handler)
define_new_opts()
all_opt["login_timeout"]["default"] = "15"
all_opt["secure"]["default"] = "1"
all_opt["cmd_prompt"]["default"] = [r":~>", r"]\$", r"\$ "]
options = check_input(device_opt, process_input(device_opt), other_conditions = True)
docs = {}
docs["shortdesc"] = "Fence agent for IBM LPAR"
docs["longdesc"] = ""
docs["vendorurl"] = "http://www.ibm.com"
show_docs(options, docs)
if "--managed" not in options:
fail_usage("Failed: You have to enter name of managed system")
if options["--action"] == "validate-all":
sys.exit(0)
##
## Operate the fencing device
####
conn = fence_login(options)
result = fence_action(conn, options, set_power_status, get_power_status, get_lpar_list)
fence_logout(conn, "quit\r\n")
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/agents/ovh/fence_ovh.py b/agents/ovh/fence_ovh.py
index f5403c54..2b7eb864 100644
--- a/agents/ovh/fence_ovh.py
+++ b/agents/ovh/fence_ovh.py
@@ -1,163 +1,164 @@
#!@PYTHON@ -tt
# Copyright 2013 Adrian Gibanel Lopez (bTactic)
# Adrian Gibanel improved this script at 2013 to add verification of success and to output metadata
# Based on:
# This is a fence agent for use at OVH
# As there are no other fence devices available, we must use OVH's SOAP API #Quick-and-dirty
# assemled by Dennis Busch, secofor GmbH, Germany
# This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
import sys, time
import shutil, tempfile
import logging
import atexit
from datetime import datetime
from suds.client import Client
from suds.xsd.doctor import ImportDoctor, Import
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing import fail, fail_usage, EC_LOGIN_DENIED, run_delay
OVH_RESCUE_PRO_NETBOOT_ID = '28'
OVH_HARD_DISK_NETBOOT_ID = '1'
STATUS_HARD_DISK_SLEEP = 240 # Wait 4 minutes to SO to boot
STATUS_RESCUE_PRO_SLEEP = 150 # Wait 2 minutes 30 seconds to Rescue-Pro to run
def define_new_opts():
all_opt["email"] = {
"getopt" : "Z:",
"longopt" : "email",
"help" : "-Z, --email=[email] email for reboot message: admin@domain.com",
"required" : "1",
"shortdesc" : "Reboot email",
"order" : 1}
def netboot_reboot(conn, options, mode):
# dedicatedNetbootModifyById changes the mode of the next reboot
conn.service.dedicatedNetbootModifyById(options["session"], options["--plug"], mode, '', options["--email"])
# dedicatedHardRebootDo initiates a hard reboot on the given node
conn.service.dedicatedHardRebootDo(options["session"],
options["--plug"], 'Fencing initiated by cluster', '', 'en')
conn.logout(options["session"])
def reboot_time(conn, options):
result = conn.service.dedicatedHardRebootStatus(options["session"], options["--plug"])
tmpstart = datetime.strptime(result.start, '%Y-%m-%d %H:%M:%S')
tmpend = datetime.strptime(result.end, '%Y-%m-%d %H:%M:%S')
result.start = tmpstart
result.end = tmpend
return result
def soap_login(options):
imp = Import('http://schemas.xmlsoap.org/soap/encoding/')
url = 'https://www.ovh.com/soapi/soapi-re-1.59.wsdl'
imp.filter.add('http://soapi.ovh.com/manager')
d = ImportDoctor(imp)
tmp_dir = tempfile.mkdtemp()
tempfile.tempdir = tmp_dir
atexit.register(remove_tmp_dir, tmp_dir)
try:
soap = Client(url, doctor=d)
session = soap.service.login(options["--username"], options["--password"], 'en', 0)
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_LOGIN_DENIED)
options["session"] = session
return soap
def remove_tmp_dir(tmp_dir):
shutil.rmtree(tmp_dir)
def main():
device_opt = ["login", "passwd", "port", "email", "no_status", "web"]
atexit.register(atexit_handler)
define_new_opts()
options = check_input(device_opt, process_input(device_opt), other_conditions=True)
docs = {}
docs["shortdesc"] = "Fence agent for OVH"
docs["longdesc"] = "fence_ovh is an Power Fencing agent \
which can be used within OVH datecentre. \
Poweroff is simulated with a reboot into rescue-pro mode."
docs["vendorurl"] = "http://www.ovh.net"
show_docs(options, docs)
if options["--action"] == "list":
fail_usage("Action 'list' is not supported in this fence agent")
if options["--action"] == "list-status":
fail_usage("Action 'list-status' is not supported in this fence agent")
if "--email" not in options:
fail_usage("You have to enter e-mail address which is notified by fence agent")
if options["--action"] == "validate-all":
sys.exit(0)
if options["--action"] != "monitor" and not options["--plug"].endswith(".ovh.net"):
options["--plug"] += ".ovh.net"
run_delay(options)
conn = soap_login(options)
if options["--action"] == 'monitor':
try:
conn.service.logout(options["session"])
except Exception:
pass
sys.exit(0)
# Save datetime just before changing netboot
before_netboot_reboot = datetime.now()
if options["--action"] == 'off':
# Reboot in Rescue-pro
netboot_reboot(conn, options, OVH_RESCUE_PRO_NETBOOT_ID)
time.sleep(STATUS_RESCUE_PRO_SLEEP)
elif options["--action"] in ['on', 'reboot']:
# Reboot from HD
netboot_reboot(conn, options, OVH_HARD_DISK_NETBOOT_ID)
time.sleep(STATUS_HARD_DISK_SLEEP)
# Save datetime just after reboot
after_netboot_reboot = datetime.now()
# Verify that action was completed sucesfully
reboot_t = reboot_time(conn, options)
logging.debug("reboot_start_end.start: %s\n",
reboot_t.start.strftime('%Y-%m-%d %H:%M:%S'))
logging.debug("before_netboot_reboot: %s\n",
before_netboot_reboot.strftime('%Y-%m-%d %H:%M:%S'))
logging.debug("reboot_start_end.end: %s\n",
reboot_t.end.strftime('%Y-%m-%d %H:%M:%S'))
logging.debug("after_netboot_reboot: %s\n",
after_netboot_reboot.strftime('%Y-%m-%d %H:%M:%S'))
if reboot_t.start < after_netboot_reboot < reboot_t.end:
result = 0
logging.debug("Netboot reboot went OK.\n")
else:
result = 1
logging.debug("ERROR: Netboot reboot wasn't OK.\n")
try:
conn.service.logout(options["session"])
except Exception:
pass
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/agents/sanbox2/fence_sanbox2.py b/agents/sanbox2/fence_sanbox2.py
index 679d1d98..179fe0e8 100644
--- a/agents/sanbox2/fence_sanbox2.py
+++ b/agents/sanbox2/fence_sanbox2.py
@@ -1,151 +1,155 @@
#!@PYTHON@ -tt
#####
##
## The Following Agent Has Been Tested On:
##
## Version Firmware
## +-----------------+---------------------------+
#####
import sys, re, pexpect
import logging
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing import fail, EC_TIMED_OUT, EC_GENERIC_ERROR
def get_power_status(conn, options):
status_trans = {
'online' : "on",
'offline' : "off"
}
try:
conn.send_eol("show port " + options["--plug"])
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
except pexpect.TIMEOUT:
try:
conn.send_eol("admin end")
conn.send_eol("exit")
conn.close()
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
pass
fail(EC_TIMED_OUT)
status = re.compile(r".*AdminState\s+(online|offline)\s+",
re.IGNORECASE | re.MULTILINE).search(conn.before).group(1)
try:
return status_trans[status.lower().strip()]
except KeyError:
return "PROBLEM"
def set_power_status(conn, options):
action = {
'on' : "online",
'off' : "offline"
}[options["--action"]]
try:
conn.send_eol("set port " + options["--plug"] + " state " + action)
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
except pexpect.TIMEOUT:
try:
conn.send_eol("admin end")
conn.send_eol("exit")
conn.close()
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
pass
fail(EC_TIMED_OUT)
try:
conn.send_eol("set port " + options["--plug"] + " state " + action)
conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
except pexpect.TIMEOUT:
try:
conn.send_eol("admin end")
conn.send_eol("exit")
conn.close()
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
pass
fail(EC_TIMED_OUT)
def get_list_devices(conn, options):
outlets = {}
try:
conn.send_eol("show port")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
list_re = re.compile(r"^\s+(\d+?)\s+(Online|Offline)\s+", re.IGNORECASE)
for line in conn.before.splitlines():
if list_re.search(line):
status = {
'online' : "ON",
'offline' : "OFF"
}[list_re.search(line).group(2).lower()]
outlets[list_re.search(line).group(1)] = ("", status)
except pexpect.TIMEOUT:
try:
conn.send_eol("admin end")
conn.send_eol("exit")
conn.close()
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
pass
fail(EC_TIMED_OUT)
return outlets
def main():
device_opt = ["fabric_fencing", "ipaddr", "login", "passwd", "cmd_prompt", \
"port", "telnet"]
atexit.register(atexit_handler)
all_opt["cmd_prompt"]["default"] = [" #> "]
options = check_input(device_opt, process_input(device_opt))
docs = {}
docs["shortdesc"] = "Fence agent for QLogic SANBox2 FC switches"
docs["longdesc"] = "fence_sanbox2 is an I/O Fencing agent which can be used with \
QLogic SANBox2 FC switches. It logs into a SANBox2 switch via telnet and disables a specified \
port. Disabling the port which a machine is connected to effectively fences that machine. \
Lengthy telnet connections to the switch should be avoided while a GFS cluster is running \
because the connection will block any necessary fencing actions."
docs["vendorurl"] = "http://www.qlogic.com"
show_docs(options, docs)
##
## Operate the fencing device
##
conn = fence_login(options)
conn.send_eol("admin start")
conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
if re.search(r"\(admin\)", conn.before, re.MULTILINE) == None:
## Someone else is in admin section, we can't enable/disable
## ports so we will rather exit
logging.error("Failed: Unable to switch to admin section\n")
sys.exit(EC_GENERIC_ERROR)
result = fence_action(conn, options, set_power_status, get_power_status, get_list_devices)
##
## Logout from system
######
try:
conn.send_eol("admin end")
conn.send_eol("exit\n")
conn.close()
except OSError:
pass
except pexpect.ExceptionPexpect:
pass
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/agents/vmware_soap/fence_vmware_soap.py b/agents/vmware_soap/fence_vmware_soap.py
index f2ab68b0..a7f08b3d 100644
--- a/agents/vmware_soap/fence_vmware_soap.py
+++ b/agents/vmware_soap/fence_vmware_soap.py
@@ -1,261 +1,264 @@
#!@PYTHON@ -tt
import sys
import shutil, tempfile, suds
import logging, requests
import atexit, signal
sys.path.append("@FENCEAGENTSLIBDIR@")
from suds.client import Client
from suds.sudsobject import Property
from suds.transport.http import HttpAuthenticated
from suds.transport import Reply, TransportError
from fencing import *
from fencing import fail, fail_usage, EC_STATUS, EC_LOGIN_DENIED, EC_INVALID_PRIVILEGES, EC_WAITING_ON, EC_WAITING_OFF
from fencing import run_delay
options_global = None
conn_global = None
class RequestsTransport(HttpAuthenticated):
def __init__(self, **kwargs):
self.cert = kwargs.pop('cert', None)
self.verify = kwargs.pop('verify', True)
self.session = requests.Session()
# super won't work because not using new style class
HttpAuthenticated.__init__(self, **kwargs)
def send(self, request):
self.addcredentials(request)
resp = self.session.post(request.url, data=request.message, headers=request.headers, cert=self.cert, verify=self.verify)
result = Reply(resp.status_code, resp.headers, resp.content)
return result
def soap_login(options):
run_delay(options)
if "--ssl" in options or "--ssl-secure" in options or "--ssl-insecure" in options:
if "--ssl-insecure" in options:
import ssl
import urllib3
if hasattr(ssl, '_create_unverified_context'):
ssl._create_default_https_context = ssl._create_unverified_context
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
verify = False
else:
verify = True
url = "https://"
else:
verify = False
url = "http://"
url += options["--ip"] + ":" + str(options["--ipport"]) + "/sdk"
tmp_dir = tempfile.mkdtemp()
tempfile.tempdir = tmp_dir
atexit.register(remove_tmp_dir, tmp_dir)
try:
headers = {"Content-Type" : "text/xml;charset=UTF-8", "SOAPAction" : "vim25"}
conn = Client(url + "/vimService.wsdl", location=url, transport=RequestsTransport(verify=verify), headers=headers)
mo_ServiceInstance = Property('ServiceInstance')
mo_ServiceInstance._type = 'ServiceInstance'
ServiceContent = conn.service.RetrieveServiceContent(mo_ServiceInstance)
mo_SessionManager = Property(ServiceContent.sessionManager.value)
mo_SessionManager._type = 'SessionManager'
conn.service.Login(mo_SessionManager, options["--username"], options["--password"])
except requests.exceptions.SSLError as ex:
fail_usage("Server side certificate verification failed: %s" % ex)
- except Exception:
+ except Exception as e:
+ logging.error("Server side certificate verification failed: {}".format(str(e)))
fail(EC_LOGIN_DENIED)
options["ServiceContent"] = ServiceContent
options["mo_SessionManager"] = mo_SessionManager
return conn
def process_results(results, machines, uuid, mappingToUUID):
for m in results.objects:
info = {}
for i in m.propSet:
info[i.name] = i.val
# Prevent error KeyError: 'config.uuid' when reaching systems which P2V failed,
# since these systems don't have a valid UUID
if "config.uuid" in info:
machines[info["name"]] = (info["config.uuid"], info["summary.runtime.powerState"])
uuid[info["config.uuid"]] = info["summary.runtime.powerState"]
mappingToUUID[m.obj.value] = info["config.uuid"]
return (machines, uuid, mappingToUUID)
def get_power_status(conn, options):
mo_ViewManager = Property(options["ServiceContent"].viewManager.value)
mo_ViewManager._type = "ViewManager"
mo_RootFolder = Property(options["ServiceContent"].rootFolder.value)
mo_RootFolder._type = "Folder"
mo_PropertyCollector = Property(options["ServiceContent"].propertyCollector.value)
mo_PropertyCollector._type = 'PropertyCollector'
ContainerView = conn.service.CreateContainerView(mo_ViewManager, recursive=1,
container=mo_RootFolder, type=['VirtualMachine'])
mo_ContainerView = Property(ContainerView.value)
mo_ContainerView._type = "ContainerView"
FolderTraversalSpec = conn.factory.create('ns0:TraversalSpec')
FolderTraversalSpec.name = "traverseEntities"
FolderTraversalSpec.path = "view"
FolderTraversalSpec.skip = False
FolderTraversalSpec.type = "ContainerView"
objSpec = conn.factory.create('ns0:ObjectSpec')
objSpec.obj = mo_ContainerView
objSpec.selectSet = [FolderTraversalSpec]
objSpec.skip = True
propSpec = conn.factory.create('ns0:PropertySpec')
propSpec.all = False
propSpec.pathSet = ["name", "summary.runtime.powerState", "config.uuid"]
propSpec.type = "VirtualMachine"
propFilterSpec = conn.factory.create('ns0:PropertyFilterSpec')
propFilterSpec.propSet = [propSpec]
propFilterSpec.objectSet = [objSpec]
try:
raw_machines = conn.service.RetrievePropertiesEx(mo_PropertyCollector, propFilterSpec)
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_STATUS)
(machines, uuid, mappingToUUID) = process_results(raw_machines, {}, {}, {})
# Probably need to loop over the ContinueRetreive if there are more results after 1 iteration.
while hasattr(raw_machines, 'token'):
try:
raw_machines = conn.service.ContinueRetrievePropertiesEx(mo_PropertyCollector, raw_machines.token)
- except Exception:
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
fail(EC_STATUS)
(more_machines, more_uuid, more_mappingToUUID) = process_results(raw_machines, {}, {}, {})
machines.update(more_machines)
uuid.update(more_uuid)
mappingToUUID.update(more_mappingToUUID)
# Do not run unnecessary SOAP requests
if "--uuid" in options and options["--uuid"] in uuid:
break
if ["list", "monitor"].count(options["--action"]) == 1:
return machines
else:
if "--uuid" not in options:
if options["--plug"].startswith('/'):
## Transform InventoryPath to UUID
mo_SearchIndex = Property(options["ServiceContent"].searchIndex.value)
mo_SearchIndex._type = "SearchIndex"
vm = conn.service.FindByInventoryPath(mo_SearchIndex, options["--plug"])
try:
options["--uuid"] = mappingToUUID[vm.value]
except KeyError:
fail(EC_STATUS)
except AttributeError:
fail(EC_STATUS)
else:
## Name of virtual machine instead of path
## warning: if you have same names of machines this won't work correctly
try:
(options["--uuid"], _) = machines[options["--plug"]]
except KeyError:
fail(EC_STATUS)
except AttributeError:
fail(EC_STATUS)
try:
if uuid[options["--uuid"]] == "poweredOn":
return "on"
else:
return "off"
except KeyError:
fail(EC_STATUS)
def set_power_status(conn, options):
mo_SearchIndex = Property(options["ServiceContent"].searchIndex.value)
mo_SearchIndex._type = "SearchIndex"
vm = conn.service.FindByUuid(mo_SearchIndex, vmSearch=1, uuid=options["--uuid"])
mo_machine = Property(vm.value)
mo_machine._type = "VirtualMachine"
try:
if options["--action"] == "on":
conn.service.PowerOnVM_Task(mo_machine)
else:
conn.service.PowerOffVM_Task(mo_machine)
except suds.WebFault as ex:
if (str(ex).find("Permission to perform this operation was denied")) >= 0:
fail(EC_INVALID_PRIVILEGES)
else:
if options["--action"] == "on":
fail(EC_WAITING_ON)
else:
fail(EC_WAITING_OFF)
def remove_tmp_dir(tmp_dir):
shutil.rmtree(tmp_dir)
def logout():
try:
conn_global.service.Logout(options_global["mo_SessionManager"])
except Exception:
pass
def signal_handler(signum, frame):
raise Exception("Signal \"%d\" received which has triggered an exit of the process." % signum)
def main():
global options_global
global conn_global
device_opt = ["ipaddr", "login", "passwd", "web", "ssl", "notls", "port"]
atexit.register(atexit_handler)
atexit.register(logout)
signal.signal(signal.SIGTERM, signal_handler)
options_global = check_input(device_opt, process_input(device_opt))
##
## Fence agent specific defaults
#####
docs = {}
docs["shortdesc"] = "Fence agent for VMWare over SOAP API"
docs["longdesc"] = "fence_vmware_soap is an I/O Fencing agent \
which can be used with the virtual machines managed by VMWare products \
that have SOAP API v4.1+. \
\n.P\n\
Name of virtual machine (-n / port) has to be used in inventory path \
format (e.g. /datacenter/vm/Discovered virtual machine/myMachine). \
In the cases when name of yours VM is unique you can use it instead. \
Alternatively you can always use UUID to access virtual machine."
docs["vendorurl"] = "http://www.vmware.com"
show_docs(options_global, docs)
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.CRITICAL)
logging.getLogger("requests").setLevel(logging.CRITICAL)
logging.getLogger("urllib3").setLevel(logging.CRITICAL)
##
## Operate the fencing device
####
conn_global = soap_login(options_global)
result = fence_action(conn_global, options_global, set_power_status, get_power_status, get_power_status)
## Logout from system is done automatically via atexit()
sys.exit(result)
if __name__ == "__main__":
main()
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:42 PM (1 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1985707
Default Alt Text
(44 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment