diff --git a/fence/agents/apc_snmp/fence_apc_snmp.py b/fence/agents/apc_snmp/fence_apc_snmp.py
index 29aafe62..d91e9e95 100644
--- a/fence/agents/apc_snmp/fence_apc_snmp.py
+++ b/fence/agents/apc_snmp/fence_apc_snmp.py
@@ -1,208 +1,208 @@
#!/usr/bin/python -tt
# The Following agent has been tested on:
# - APC Switched Rack PDU - SNMP v1
# (MB:v3.7.0 PF:v2.7.0 PN:apc_hw02_aos_270.bin AF1:v2.7.3
# AN1:apc_hw02_aos_270.bin AF1:v2.7.3 AN1:apc_hw02_rpdu_273.bin MN:AP7930 HR:B2)
# - APC Web/SNMP Management Card - SNMP v1 and v3 (noAuthNoPrivacy,authNoPrivacy, authPrivacy)
# (MB:v3.8.6 PF:v3.5.8 PN:apc_hw02_aos_358.bin AF1:v3.5.7
# AN1:apc_hw02_aos_358.bin AF1:v3.5.7 AN1:apc_hw02_rpdu_357.bin MN:AP7900 HR:B2)
# - APC Switched Rack PDU - SNMP v1
# (MB:v3.7.0 PF:v2.7.0 PN:apc_hw02_aos_270.bin AF1:v2.7.3
# AN1:apc_hw02_rpdu_273.bin MN:AP7951 HR:B2)
# - Tripplite PDUMH20HVNET 12.04.0055 - SNMP v1, v2c, v3
import sys
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing_snmp import FencingSnmp
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="APC SNMP fence agent"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
### CONSTANTS ###
# oid defining fence device
OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0'
### GLOBAL VARIABLES ###
# Device - see ApcRPDU, ApcMSP, ApcMS, TripplitePDU
device = None
# Port ID
port_id = None
# Switch ID
switch_id = None
# Classes describing Device params
class TripplitePDU:
# Rack PDU
status_oid = '.1.3.6.1.4.1.850.10.2.3.5.1.2.1.%d'
control_oid = '.1.3.6.1.4.1.850.10.2.3.5.1.4.1.%d'
outlet_table_oid = '.1.3.6.1.4.1.850.10.2.3.5.1.5'
ident_str = "Tripplite"
state_on = 2
state_off = 1
turn_on = 2
turn_off = 1
has_switches = False
class ApcRPDU:
# Rack PDU
status_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.%d'
control_oid = '.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%d'
outlet_table_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.2'
ident_str = "APC rPDU"
state_on = 1
state_off = 2
turn_on = 1
turn_off = 2
has_switches = False
class ApcMSP:
# Master Switch+
status_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.5.%d.1.%d'
control_oid = '.1.3.6.1.4.1.318.1.1.6.5.1.1.5.%d.1.%d'
outlet_table_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.4'
ident_str = "APC Master Switch+"
state_on = 1
state_off = 2
turn_on = 1
turn_off = 3
has_switches = True
class ApcMS:
# Master Switch - seems oldest, but supported on every APC PDU
status_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.3.%d'
control_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.3.%d'
outlet_table_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.4'
ident_str = "APC Master Switch (fallback)"
state_on = 1
state_off = 2
turn_on = 1
turn_off = 2
has_switches = False
### FUNCTIONS ###
-def apc_set_device(conn, options):
+def apc_set_device(conn):
global device
agents_dir = {'.1.3.6.1.4.1.318.1.3.4.5':ApcRPDU,
'.1.3.6.1.4.1.318.1.3.4.4':ApcMSP,
'.1.3.6.1.4.1.850.1':TripplitePDU,
None:ApcMS}
# First resolve type of APC
apc_type = conn.walk(OID_SYS_OBJECT_ID)
if (not ((len(apc_type)==1) and (agents_dir.has_key(apc_type[0][1])))):
apc_type = [[None, None]]
device = agents_dir[apc_type[0][1]]
conn.log_command("Trying %s"%(device.ident_str))
def apc_resolv_port_id(conn, options):
global port_id, switch_id
if (device == None):
- apc_set_device(conn, options)
+ apc_set_device(conn)
# Now we resolv port_id/switch_id
if ((options["--plug"].isdigit()) and ((not device.has_switches) or (options["--switch"].isdigit()))):
port_id = int(options["--plug"])
if (device.has_switches):
switch_id = int(options["--switch"])
else:
table = conn.walk(device.outlet_table_oid, 30)
for x in table:
if (x[1].strip('"') == options["--plug"]):
t = x[0].split('.')
if (device.has_switches):
port_id = int(t[len(t)-1])
switch_id = int(t[len(t)-3])
else:
port_id = int(t[len(t)-1])
if (port_id == None):
fail_usage("Can't find port with name %s!"%(options["--plug"]))
def get_power_status(conn, options):
if (port_id == None):
apc_resolv_port_id(conn, options)
oid = ((device.has_switches) and device.status_oid%(switch_id, port_id) or device.status_oid%(port_id))
(oid, status) = conn.get(oid)
return (status==str(device.state_on) and "on" or "off")
def set_power_status(conn, options):
if (port_id == None):
apc_resolv_port_id(conn, options)
oid = ((device.has_switches) and device.control_oid%(switch_id, port_id) or device.control_oid%(port_id))
conn.set(oid, (options["--action"]=="on" and device.turn_on or device.turn_off))
def get_outlets_status(conn, options):
result = {}
if (device == None):
- apc_set_device(conn, options)
+ apc_set_device(conn)
res_ports = conn.walk(device.outlet_table_oid, 30)
for x in res_ports:
t = x[0].split('.')
port_num = ((device.has_switches) and "%s:%s"%(t[len(t)-3], t[len(t)-1]) or "%s"%(t[len(t)-1]))
port_name = x[1].strip('"')
port_status = ""
result[port_num] = (port_name, port_status)
return result
# Main agent method
def main():
device_opt = [ "ipaddr", "login", "passwd", "no_login", "no_password", \
"port", "snmp_version", "community" ]
atexit.register(atexit_handler)
all_opt["snmp_version"]["default"] = "1"
all_opt["community"]["default"] = "private"
options = check_input(device_opt, process_input(device_opt))
## Support for -n [switch]:[plug] notation that was used before
if ((options.has_key("--plug")) and (-1 != options["--plug"].find(":"))):
(switch, plug) = options["--plug"].split(":", 1)
if ((switch.isdigit()) and (plug.isdigit())):
options["--switch"] = switch
options["--plug"] = plug
if (not (options.has_key("--switch"))):
options["--switch"] = "1"
docs = { }
docs["shortdesc"] = "Fence agent for APC, Tripplite PDU over SNMP"
docs["longdesc"] = "fence_apc_snmp is an I/O Fencing agent \
which can be used with the APC network power switch or Tripplite PDU devices.\
It logs into a device via SNMP and reboots a specified outlet. It supports \
SNMP v1, v2c, v3 with all combinations of authenticity/privacy settings."
docs["vendorurl"] = "http://www.apc.com"
show_docs(options, docs)
# Operate the fencing device
result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
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 d2777def..a9ca8fe6 100644
--- a/fence/agents/cisco_ucs/fence_cisco_ucs.py
+++ b/fence/agents/cisco_ucs/fence_cisco_ucs.py
@@ -1,160 +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
#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("", 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, "" +
"" + "" + "",
int(options["--shell-timeout"]))
return
def get_list(conn, options):
+ del conn
outlets = { }
try:
res = send_command(options, "", int(options["--shell-timeout"]))
lines = res.split("", 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, "",
int(options["--shell-timeout"]))
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/dummy/fence_dummy.py b/fence/agents/dummy/fence_dummy.py
index ff67e7b1..aa1e5c23 100644
--- a/fence/agents/dummy/fence_dummy.py
+++ b/fence/agents/dummy/fence_dummy.py
@@ -1,135 +1,142 @@
#!/usr/bin/python -tt
import sys, random
import logging
import time
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing import fail_usage
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="New Dummy Agent - test release on steroids"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
plug_status = "on"
def get_power_status_file(conn, options):
+ del conn
+
try:
status_file = open(options["--status-file"], 'r')
except:
return "off"
status = status_file.read()
status_file.close()
return status.lower()
def set_power_status_file(conn, options):
+ del conn
+
if not (options["--action"] in [ "on", "off" ]):
return
status_file = open(options["--status-file"], 'w')
status_file.write(options["--action"])
status_file.close()
def get_power_status_fail(conn, options):
outlets = get_outlets_fail(conn, options)
if len(outlets) == 0 or options.has_key("--plug") == 0:
fail_usage("Failed: You have to enter existing machine!")
else:
return outlets[options["--plug"]][0]
def set_power_status_fail(conn, options):
global plug_status
+ del conn
plug_status = "unknown"
if options["--action"] == "on":
plug_status = "off"
def get_outlets_fail(conn, options):
+ del conn
+
result = {}
global plug_status
if options["--action"] == "on":
plug_status = "off"
# This fake agent has no port data to list, so we have to make
# something up for the list action.
if options.has_key("--action") and options["--action"] == "list":
result["fake_port_1"] = [plug_status, "fake"]
result["fake_port_2"] = [plug_status, "fake"]
elif (options.has_key("--plug") == 0):
fail_usage("Failed: You have to enter existing machine!")
else:
port = options["--plug"]
result[port] = [plug_status, "fake"]
return result
def main():
device_opt = [ "no_password", "status_file", "random_sleep_range", "type", "port" ]
atexit.register(atexit_handler)
all_opt["status_file"] = {
"getopt" : "s:",
"longopt" : "status-file",
"help":"--status-file=[file] Name of file that holds current status",
"required" : "0",
"shortdesc" : "File with status",
"default" : "/tmp/fence_dummy.status",
"order": 1
}
all_opt["random_sleep_range"] = {
"getopt" : "r:",
"longopt" : "random_sleep_range",
"help":"--random_sleep_range=[seconds] Issue a sleep between 1 and [seconds]",
"required" : "0",
"shortdesc" : "Issue a sleep between 1 and X seconds. Used for testing.",
"order": 1
}
all_opt["type"] = {
"getopt" : "t:",
"longopt" : "type",
"help":"--type=[type] Possible types are: file and fail",
"required" : "0",
"shortdesc" : "Type of the dummy fence agent",
"default" : "file",
"order": 1
}
pinput = process_input(device_opt)
if (pinput.has_key("--type") and pinput["--type"] == "file") or (pinput.has_key("--type") == False):
# hack to have fence agents that require ports 'fail' and one that do not 'file'
device_opt.remove("port")
options = check_input(device_opt, process_input(device_opt))
docs = { }
docs["shortdesc"] = "Dummy fence agent"
docs["longdesc"] = "fence_dummy"
docs["vendorurl"] = "http://www.example.com"
show_docs(options, docs)
# random sleep for testing
if options.has_key("--random_sleep_range"):
val = int(options["--random_sleep_range"])
ran = random.randint(1, val)
logging.info("Random sleep for %d seconds\n" % ran)
time.sleep(ran)
if options["--type"] == "fail":
result = fence_action(None, options, set_power_status_fail, get_power_status_fail, get_outlets_fail)
else:
result = fence_action(None, options, set_power_status_file, get_power_status_file, None)
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/eaton_snmp/fence_eaton_snmp.py b/fence/agents/eaton_snmp/fence_eaton_snmp.py
index 970fd690..9688516d 100644
--- a/fence/agents/eaton_snmp/fence_eaton_snmp.py
+++ b/fence/agents/eaton_snmp/fence_eaton_snmp.py
@@ -1,233 +1,233 @@
#!/usr/bin/python -tt
# The Following agent has been tested on:
# - Eaton ePDU Managed - SNMP v1
# EATON | Powerware ePDU model: Managed ePDU (PW104MA0UB99), firmware: 01.01.01
# - Eaton ePDU Switched - SNMP v1
# EATON | Powerware ePDU model: Switched ePDU (IPV3600), firmware: 2.0.K
import sys
import atexit
sys.path.append("@FENCEAGENTSLIBDIR@")
from fencing import *
from fencing_snmp import FencingSnmp
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="Eaton SNMP fence agent"
REDHAT_COPYRIGHT=""
BUILD_DATE=""
#END_VERSION_GENERATION
### CONSTANTS ###
# oid defining fence device
OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0'
### GLOBAL VARIABLES ###
# Device - see EatonManagedePDU, EatonSwitchedePDU
device = None
# Port ID
port_id = None
# Switch ID
switch_id = None
# Did we issue a set before get (to adjust OID with Switched ePDU)
after_set = False
# Classes describing Device params
# Managed ePDU
class EatonManagedePDU:
status_oid = '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.3.%d'
control_oid = '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.3.%d'
outlet_table_oid = '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.1'
ident_str = "Eaton Managed ePDU"
state_off = 0
state_on = 1
state_cycling = 2 # FIXME: not usable with fence-agents
turn_off = 0
turn_on = 1
turn_cycle = 2 # FIXME: not usable with fence-agents
has_switches = False
# Switched ePDU (Pulizzi 2)
# NOTE: sysOID reports "20677.1", while data are actually at "20677.2"
class EatonSwitchedePDU:
status_oid = '.1.3.6.1.4.1.20677.2.6.3.%d.0'
control_oid = '.1.3.6.1.4.1.20677.2.6.2.%d.0'
outlet_table_oid = '.1.3.6.1.4.1.20677.2.6.3'
ident_str = "Eaton Switched ePDU"
state_off = 2
state_on = 1
state_cycling = 0 # Note: this status doesn't exist on this device
turn_off = 2
turn_on = 1
turn_cycle = 3 # FIXME: not usable with fence-agents
has_switches = False
### FUNCTIONS ###
-def eaton_set_device(conn, options):
+def eaton_set_device(conn):
global device
agents_dir = {'.1.3.6.1.4.1.534.6.6.6':EatonManagedePDU,
'.1.3.6.1.4.1.20677.1':EatonSwitchedePDU,
'.1.3.6.1.4.1.20677.2':EatonSwitchedePDU }
# First resolve type of Eaton
eaton_type = conn.walk(OID_SYS_OBJECT_ID)
if (not ((len(eaton_type)==1) and (agents_dir.has_key(eaton_type[0][1])))):
eaton_type = [[None, None]]
device = agents_dir[eaton_type[0][1]]
conn.log_command("Trying %s"%(device.ident_str))
def eaton_resolv_port_id(conn, options):
global port_id, switch_id
if (device==None):
- eaton_set_device(conn, options)
+ eaton_set_device(conn)
# Restore the increment, that was removed in main for ePDU Managed
if (device.ident_str == "Eaton Switched ePDU"):
options["--plug"] = str(int(options["--plug"]) + 1)
# Now we resolv port_id/switch_id
if ((options["--plug"].isdigit()) and ((not device.has_switches) or (options["--switch"].isdigit()))):
port_id = int(options["--plug"])
if (device.has_switches):
switch_id = int(options["--switch"])
else:
table = conn.walk(device.outlet_table_oid, 30)
for x in table:
if (x[1].strip('"')==options["--plug"]):
t = x[0].split('.')
if (device.has_switches):
port_id = int(t[len(t)-1])
switch_id = int(t[len(t)-3])
else:
if (device.ident_str == "Eaton Switched ePDU"):
port_id = int(t[len(t)-3])
else:
port_id = int(t[len(t)-1])
if (port_id==None):
# Restore index offset, to provide a valid error output on Managed ePDU
if (device.ident_str != "Eaton Switched ePDU"):
options["--plug"] = str(int(options["--plug"]) + 1)
fail_usage("Can't find port with name %s!"%(options["--plug"]))
def get_power_status(conn, options):
global port_id, after_set
if (port_id==None):
eaton_resolv_port_id(conn, options)
# Ajust OID for Switched ePDU when the get is after a set
if ((after_set == True) and (device.ident_str == "Eaton Switched ePDU")):
port_id -= 1
after_set = False
oid = ((device.has_switches) and device.status_oid%(switch_id, port_id) or device.status_oid%(port_id))
try:
(oid, status)=conn.get(oid)
if (status==str(device.state_on)):
return "on"
elif (status==str(device.state_off)):
return "off"
else:
return None
except:
return None
def set_power_status(conn, options):
global port_id, after_set
after_set = True
if (port_id==None):
eaton_resolv_port_id(conn, options)
# Controls start at #2 on Switched ePDU, since #1 is the global command
if (device.ident_str == "Eaton Switched ePDU"):
port_id = int(port_id)+1
oid = ((device.has_switches) and device.control_oid%(switch_id, port_id) or device.control_oid%(port_id))
conn.set(oid,(options["--action"]=="on" and device.turn_on or device.turn_off))
def get_outlets_status(conn, options):
outletCount = 0
result = {}
if (device==None):
- eaton_set_device(conn, options)
+ eaton_set_device(conn)
res_ports = conn.walk(device.outlet_table_oid, 30)
for x in res_ports:
outletCount += 1
status = x[1]
t = x[0].split('.')
# Plug indexing start from zero, so we substract '1' from the
# user's given plug number
if (device.ident_str == "Eaton Managed ePDU"):
port_num = str(int(((device.has_switches) and
"%s:%s"%(t[len(t)-3], t[len(t)-1]) or "%s"%(t[len(t)-1]))) + 1)
# Plug indexing start from zero, so we add '1'
# for the user's exposed plug number
port_name = str(int(x[1].strip('"')) + 1)
port_status = ""
result[port_num] = (port_name, port_status)
else:
# Switched ePDU do not propose an outletCount OID!
# Invalid status (ie value == '0'), retrieved via the walk,
# means the outlet is absent
port_num = str(outletCount)
port_name = str(outletCount)
port_status = ""
if (status != '0'):
result[port_num] = (port_name, port_status)
return result
# Main agent method
def main():
device_opt = [ "ipaddr", "login", "passwd", "no_login", "no_password", \
"port", "snmp_version", "community" ]
atexit.register(atexit_handler)
all_opt["switch"]["default"] = 1
all_opt["power_wait"]["default"] = 2
all_opt["snmp_version"]["default"] = "1"
all_opt["community"]["default"] = "private"
options = check_input(device_opt, process_input(device_opt))
# Plug indexing start from zero on ePDU Managed, so we substract '1' from
# the user's given plug number.
# For Switched ePDU, we will add this back again later.
if ((options.has_key("--plug")) and (options["--plug"].isdigit())):
options["--plug"] = str(int(options["--plug"]) - 1)
docs = { }
docs["shortdesc"] = "Fence agent for Eaton over SNMP"
docs["longdesc"] = "fence_eaton_snmp is an I/O Fencing agent \
which can be used with the Eaton network power switch. It logs \
into a device via SNMP and reboots a specified outlet. It supports \
SNMP v1 and v3 with all combinations of authenticity/privacy settings."
docs["vendorurl"] = "http://powerquality.eaton.com"
show_docs(options, docs)
# Operate the fencing device
result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fence/agents/eps/fence_eps.py b/fence/agents/eps/fence_eps.py
index 0d9e573f..3a52b3c9 100644
--- a/fence/agents/eps/fence_eps.py
+++ b/fence/agents/eps/fence_eps.py
@@ -1,126 +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
#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*\
", 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/rhevm/fence_rhevm.py b/fence/agents/rhevm/fence_rhevm.py
index c8760d97..8efdc456 100644
--- a/fence/agents/rhevm/fence_rhevm.py
+++ b/fence/agents/rhevm/fence_rhevm.py
@@ -1,129 +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
#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("(.*?)", re.IGNORECASE)
RE_GET_NAME = re.compile("(.*?)", 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 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("")
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.perform()
result = b.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 f645650c..c9310fb1 100644
--- a/fence/agents/vmware/fence_vmware.py
+++ b/fence/agents/vmware/fence_vmware.py
@@ -1,340 +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
#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(conn, options, add_vm_name):
+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(conn, options):
+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(conn, options, False)
+ 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(conn, options)
+ 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()