Page MenuHomeClusterLabs Projects

No OneTemporary

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

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)

Event Timeline