diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
index bb144bb6..d6b02d39 100644
--- a/fence/agents/lib/fencing.py.py
+++ b/fence/agents/lib/fencing.py.py
@@ -1,1025 +1,1029 @@
#!/usr/bin/python
import sys, getopt, time, os, uuid, pycurl
import pexpect, re, atexit, syslog
import __main__
## do not add code here.
#BEGIN_VERSION_GENERATION
RELEASE_VERSION = "New fence lib agent - test release on steroids"
REDHAT_COPYRIGHT = ""
BUILD_DATE = "March, 2008"
#END_VERSION_GENERATION
LOG_MODE_VERBOSE = 100
LOG_MODE_QUIET = 0
EC_GENERIC_ERROR = 1
EC_BAD_ARGS = 2
EC_LOGIN_DENIED = 3
EC_CONNECTION_LOST = 4
EC_TIMED_OUT = 5
EC_WAITING_ON = 6
EC_WAITING_OFF = 7
EC_STATUS = 8
EC_STATUS_HMC = 9
EC_PASSWORD_MISSING = 10
TELNET_PATH = "/usr/bin/telnet"
SSH_PATH = "/usr/bin/ssh"
SSL_PATH = "@LIBEXECDIR@/fence_nss_wrapper"
SUDO_PATH = "/usr/bin/sudo"
all_opt = {
"help" : {
"getopt" : "h",
"longopt" : "help",
"help" : "-h, --help Display this help and exit",
"required" : "0",
"shortdesc" : "Display help and exit",
"order" : 54 },
"version" : {
"getopt" : "V",
"longopt" : "version",
"help" : "-V, --version Output version information and exit",
"required" : "0",
"shortdesc" : "Display version information and exit",
"order" : 53 },
"verbose" : {
"getopt" : "v",
"longopt" : "verbose",
"help" : "-v, --verbose Verbose mode",
"required" : "0",
"shortdesc" : "Verbose mode",
"order" : 51 },
"debug" : {
"getopt" : "D:",
"longopt" : "debug-file",
"help" : "-D, --debug-file=[debugfile] Debugging to output file",
"required" : "0",
"shortdesc" : "Write debug information to given file",
"order" : 52 },
"delay" : {
"getopt" : "f:",
"longopt" : "delay",
"help" : "--delay=[seconds] Wait X seconds before fencing is started",
"required" : "0",
"shortdesc" : "Wait X seconds before fencing is started",
"default" : "0",
"order" : 200 },
"agent" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"web" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"action" : {
"getopt" : "o:",
"longopt" : "action",
"help" : "-o, --action=[action] Action: status, reboot (default), off or on",
"required" : "1",
"shortdesc" : "Fencing Action",
"default" : "reboot",
"order" : 1 },
"fabric_fencing" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"ipaddr" : {
"getopt" : "a:",
"longopt" : "ip",
"help" : "-a, --ip=[ip] IP address or hostname of fencing device",
"required" : "1",
"shortdesc" : "IP Address or Hostname",
"order" : 1 },
"ipport" : {
"getopt" : "u:",
"longopt" : "ipport",
"help" : "-u, --ipport=[port] TCP/UDP port to use",
"required" : "0",
"shortdesc" : "TCP/UDP port to use for connection with device",
"order" : 1 },
"login" : {
"getopt" : "l:",
"longopt" : "username",
"help" : "-l, --username=[name] Login name",
"required" : "?",
"shortdesc" : "Login Name",
"order" : 1 },
"no_login" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"no_password" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"no_port" : {
"getopt" : "",
"help" : "",
"order" : 1 },
"passwd" : {
"getopt" : "p:",
"longopt" : "password",
"help" : "-p, --password=[password] Login password or passphrase",
"required" : "0",
"shortdesc" : "Login password or passphrase",
"order" : 1 },
"passwd_script" : {
"getopt" : "S:",
"longopt" : "password-script",
"help" : "-S, --password-script=[script] Script to run to retrieve password",
"required" : "0",
"shortdesc" : "Script to retrieve password",
"order" : 1 },
"identity_file" : {
"getopt" : "k:",
"longopt" : "identity-file",
"help" : "-k, --identity-file=[filename] Identity file (private key) for ssh ",
"required" : "0",
"shortdesc" : "Identity file for ssh",
"order" : 1 },
"drac_version" : {
"getopt" : "d:",
"longopt" : "drac-version",
"help" : "-d, --drac-version=[version] Force DRAC version to use",
"required" : "0",
"shortdesc" : "Force DRAC version to use",
"order" : 1 },
"cmd_prompt" : {
"getopt" : "c:",
"longopt" : "command-prompt",
"help" : "-c, --command-prompt=[prompt] Force Python regex for command prompt",
"shortdesc" : "Force Python regex for command prompt",
"required" : "0",
"order" : 1 },
"secure" : {
"getopt" : "x",
"longopt" : "ssh",
"help" : "-x, --ssh Use ssh connection",
"shortdesc" : "SSH connection",
"required" : "0",
"order" : 1 },
"ssh_options" : {
"getopt" : "X:",
"longopt" : "ssh-options",
"help" : "--ssh-options=[options] SSH options to use",
"shortdesc" : "SSH options to use",
"required" : "0",
"order" : 1 },
"ssl" : {
"getopt" : "z",
"longopt" : "ssl",
"help" : "-z, --ssl Use ssl connection",
"required" : "0",
"shortdesc" : "SSL connection",
"order" : 1 },
"port" : {
"getopt" : "n:",
"longopt" : "plug",
"help" : "-n, --plug=[id] Physical plug number on device, UUID or\n" +
" identification of machine",
"required" : "1",
"shortdesc" : "Physical plug number, name of virtual machine or UUID",
"order" : 1 },
"switch" : {
"getopt" : "s:",
"longopt" : "switch",
"help" : "-s, --switch=[id] Physical switch number on device",
"required" : "0",
"shortdesc" : "Physical switch number on device",
"order" : 1 },
"exec" : {
"getopt" : "e:",
"longopt" : "exec",
"help" : "-e, --exec=[command] Command to execute",
"required" : "0",
"shortdesc" : "Command to execute",
"order" : 1 },
"vmware_type" : {
"getopt" : "d:",
"longopt" : "vmware_type",
"help" : "-d, --vmware_type=[type] Type of VMware to connect",
"required" : "0",
"shortdesc" : "Type of VMware to connect",
"order" : 1 },
"vmware_datacenter" : {
"getopt" : "s:",
"longopt" : "vmware-datacenter",
"help" : "-s, --vmware-datacenter=[dc] VMWare datacenter filter",
"required" : "0",
"shortdesc" : "Show only machines in specified datacenter",
"order" : 2 },
"snmp_version" : {
"getopt" : "d:",
"longopt" : "snmp-version",
"help" : "-d, --snmp-version=[version] Specifies SNMP version to use",
"required" : "0",
"shortdesc" : "Specifies SNMP version to use (1,2c,3)",
"order" : 1 },
"community" : {
"getopt" : "c:",
"longopt" : "community",
"help" : "-c, --community=[community] Set the community string",
"required" : "0",
"shortdesc" : "Set the community string",
"order" : 1},
"snmp_auth_prot" : {
"getopt" : "b:",
"longopt" : "snmp-auth-prot",
"help" : "-b, --snmp-auth-prot=[prot] Set authentication protocol (MD5|SHA)",
"required" : "0",
"shortdesc" : "Set authentication protocol (MD5|SHA)",
"order" : 1},
"snmp_sec_level" : {
"getopt" : "E:",
"longopt" : "snmp-sec-level",
"help" : "-E, --snmp-sec-level=[level] Set security level\n"+
" (noAuthNoPriv|authNoPriv|authPriv)",
"required" : "0",
"shortdesc" : "Set security level (noAuthNoPriv|authNoPriv|authPriv)",
"order" : 1},
"snmp_priv_prot" : {
"getopt" : "B:",
"longopt" : "snmp-priv-prot",
"help" : "-B, --snmp-priv-prot=[prot] Set privacy protocol (DES|AES)",
"required" : "0",
"shortdesc" : "Set privacy protocol (DES|AES)",
"order" : 1},
"snmp_priv_passwd" : {
"getopt" : "P:",
"longopt" : "snmp-priv-passwd",
"help" : "-P, --snmp-priv-passwd=[pass] Set privacy protocol password",
"required" : "0",
"shortdesc" : "Set privacy protocol password",
"order" : 1},
"snmp_priv_passwd_script" : {
"getopt" : "R:",
"longopt" : "snmp-priv-passwd-script",
"help" : "-R, --snmp-priv-passwd-script Script to run to retrieve privacy password",
"required" : "0",
"shortdesc" : "Script to run to retrieve privacy password",
"order" : 1},
"inet4_only" : {
"getopt" : "4",
"longopt" : "inet4-only",
"help" : "-4, --inet4-only Forces agent to use IPv4 addresses only",
"required" : "0",
"shortdesc" : "Forces agent to use IPv4 addresses only",
"order" : 1 },
"inet6_only" : {
"getopt" : "6",
"longopt" : "inet6-only",
"help" : "-6, --inet6-only Forces agent to use IPv6 addresses only",
"required" : "0",
"shortdesc" : "Forces agent to use IPv6 addresses only",
"order" : 1 },
"separator" : {
"getopt" : "C:",
"longopt" : "separator",
"help" : "-C, --separator=[char] Separator for CSV created by 'list' operation",
"default" : ",",
"required" : "0",
"shortdesc" : "Separator for CSV created by operation list",
"order" : 100 },
"login_timeout" : {
"getopt" : "y:",
"longopt" : "login-timeout",
"help" : "--login-timeout=[seconds] Wait X seconds for cmd prompt after login",
"default" : "5",
"required" : "0",
"shortdesc" : "Wait X seconds for cmd prompt after login",
"order" : 200 },
"shell_timeout" : {
"getopt" : "Y:",
"longopt" : "shell-timeout",
"help" : "--shell-timeout=[seconds] Wait X seconds for cmd prompt after issuing command",
"default" : "3",
"required" : "0",
"shortdesc" : "Wait X seconds for cmd prompt after issuing command",
"order" : 200 },
"power_timeout" : {
"getopt" : "g:",
"longopt" : "power-timeout",
"help" : "--power-timeout=[seconds] Test X seconds for status change after ON/OFF",
"default" : "20",
"required" : "0",
"shortdesc" : "Test X seconds for status change after ON/OFF",
"order" : 200 },
"power_wait" : {
"getopt" : "G:",
"longopt" : "power-wait",
"help" : "--power-wait=[seconds] Wait X seconds after issuing ON/OFF",
"default" : "0",
"required" : "0",
"shortdesc" : "Wait X seconds after issuing ON/OFF",
"order" : 200 },
"missing_as_off" : {
"getopt" : "M",
"longopt" : "missing-as-off",
"help" : "--missing-as-off Missing port returns OFF instead of failure",
"required" : "0",
"shortdesc" : "Missing port returns OFF instead of failure",
"order" : 200 },
"retry_on" : {
"getopt" : "F:",
"longopt" : "retry-on",
"help" : "--retry-on=[attempts] Count of attempts to retry power on",
"default" : "1",
"required" : "0",
"shortdesc" : "Count of attempts to retry power on",
"order" : 201 },
"session_url" : {
"getopt" : "s:",
"longopt" : "session-url",
"help" : "-s, --session-url URL to connect to XenServer on",
"required" : "1",
"shortdesc" : "The URL of the XenServer host.",
"order" : 1},
"sudo" : {
"getopt" : "d",
"longopt" : "use-sudo",
"help" : "--use-sudo Use sudo (without password) when calling 3rd party software",
"required" : "0",
"shortdesc" : "Use sudo (without password) when calling 3rd party sotfware.",
"order" : 205}
}
# options which are added automatically if 'key' is encountered ("default" is always added)
DEPENDENCY_OPT = {
"default" : [ "help", "debug", "verbose", "version", "action", "agent", \
"power_timeout", "shell_timeout", "login_timeout", "power_wait", "retry_on", "delay" ],
"passwd" : [ "passwd_script" ],
"secure" : [ "identity_file", "ssh_options" ],
"ipaddr" : [ "ipport", "inet4_only", "inet6_only" ],
"port" : [ "separator" ],
"community" : [ "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", \
"snmp_priv_passwd", "snmp_priv_passwd_script" ]
}
class fspawn(pexpect.spawn):
def __init__(self, options, command):
pexpect.spawn.__init__(self, command)
self.opt = options
def log_expect(self, options, pattern, timeout):
result = self.expect(pattern, timeout)
if options["log"] >= LOG_MODE_VERBOSE:
options["debug_fh"].write(self.before + self.after)
return result
# send EOL according to what was detected in login process (telnet)
def send_eol(self, message):
self.send(message + self.opt["eol"])
def atexit_handler():
try:
sys.stdout.close()
os.close(1)
except IOError:
sys.stderr.write("%s failed to close standard output\n"%(sys.argv[0]))
syslog.syslog(syslog.LOG_ERR, "Failed to close standard output")
sys.exit(EC_GENERIC_ERROR)
def add_dependency_options(options):
## Add options which are available for every fence agent
added_opt = []
for x in options + ["default"]:
if DEPENDENCY_OPT.has_key(x):
added_opt.extend([y for y in DEPENDENCY_OPT[x] if options.count(y) == 0])
return added_opt
def version(command, release, build_date, copyright_notice):
print command, " ", release, " ", build_date
if len(copyright_notice) > 0:
print copyright_notice
def fail_usage(message = ""):
if len(message) > 0:
sys.stderr.write(message+"\n")
sys.stderr.write("Please use '-h' for usage\n")
sys.exit(EC_GENERIC_ERROR)
def fail(error_code):
message = {
EC_LOGIN_DENIED : "Unable to connect/login to fencing device",
EC_CONNECTION_LOST : "Connection lost",
EC_TIMED_OUT : "Connection timed out",
EC_WAITING_ON : "Failed: Timed out waiting to power ON",
EC_WAITING_OFF : "Failed: Timed out waiting to power OFF",
EC_STATUS : "Failed: Unable to obtain correct plug status or plug is not available",
EC_STATUS_HMC :
"Failed: Either unable to obtain correct plug status, partition is not available or incorrect HMC version used",
EC_PASSWORD_MISSING : "Failed: You have to set login password"
}[error_code] + "\n"
sys.stderr.write(message)
syslog.syslog(syslog.LOG_ERR, message)
sys.exit(EC_GENERIC_ERROR)
def usage(avail_opt):
print "Usage:"
print "\t" + os.path.basename(sys.argv[0]) + " [options]"
print "Options:"
sorted_list = [ (key, all_opt[key]) for key in avail_opt ]
sorted_list.sort(lambda x, y: cmp(x[1]["order"], y[1]["order"]))
for key, value in sorted_list:
if len(value["help"]) != 0:
print " " + value["help"]
def metadata(avail_opt, options, docs):
sorted_list = [ (key, all_opt[key]) for key in avail_opt ]
sorted_list.sort(lambda x, y: cmp(x[1]["order"], y[1]["order"]))
print ""
print ""
if "symlink" in docs:
for (symlink, desc) in docs["symlink"]:
print ""
print "" + docs["longdesc"] + ""
if docs.has_key("vendorurl"):
print "" + docs["vendorurl"] + ""
print ""
for option, _value in sorted_list:
if all_opt[option].has_key("shortdesc"):
print "\t"
default = ""
if all_opt[option].has_key("default"):
default = str(all_opt[option]["default"])
elif options.has_key("--" + all_opt[option]["longopt"]) and all_opt[option]["getopt"].endswith(":"):
if options["--" + all_opt[option]["longopt"]]:
try:
default = options["--" + all_opt[option]["longopt"]]
except TypeError:
## @todo/@note: Currently there is no clean way how to handle lists
## we can create a string from it but we can't set it on command line
default = str(options["--" + all_opt[option]["longopt"]])
elif options.has_key("--" + all_opt[option]["longopt"]):
default = "true"
if default:
default = default.replace("&", "&" )
default = default.replace('"', """ )
default = default.replace('<', "<" )
default = default.replace('>', ">" )
default = default.replace("'", "'" )
default = "default=\"" + default + "\" "
mixed = all_opt[option]["help"]
## split it between option and help text
res = re.compile("^(.*--\S+)\s+", re.IGNORECASE | re.S).search(mixed)
if (None != res):
mixed = res.group(1)
mixed = mixed.replace("<", "<").replace(">", ">")
print "\t\t"
if all_opt[option]["getopt"].count(":") > 0:
print "\t\t"
else:
print "\t\t"
print "\t\t" + all_opt[option]["shortdesc"] + ""
print "\t"
print ""
print ""
- print "\t"
+ if avail_opt.count("fabric_fencing") == 1:
+ ## do 'unfence' at the start
+ print "\t"
+ else:
+ print "\t"
print "\t"
if avail_opt.count("fabric_fencing") == 0:
print "\t"
print "\t"
print "\t"
print "\t"
print "\t"
print ""
print ""
def process_input(avail_opt):
avail_opt.extend(add_dependency_options(avail_opt))
##
## Set standard environment
#####
os.putenv("LANG", "C")
os.putenv("LC_ALL", "C")
##
## Prepare list of options for getopt
#####
getopt_string = ""
longopt_list = [ ]
for k in avail_opt:
if all_opt.has_key(k):
getopt_string += all_opt[k]["getopt"]
else:
fail_usage("Parse error: unknown option '"+k+"'")
if all_opt.has_key(k) and all_opt[k].has_key("longopt"):
if all_opt[k]["getopt"].endswith(":"):
longopt_list.append(all_opt[k]["longopt"] + "=")
else:
longopt_list.append(all_opt[k]["longopt"])
##
## Read options from command line or standard input
#####
if len(sys.argv) > 1:
try:
opt, _args = getopt.gnu_getopt(sys.argv[1:], getopt_string, longopt_list)
except getopt.GetoptError, error:
fail_usage("Parse error: " + error.msg)
## Transform short getopt to long one which are used in fencing agents
#####
old_opt = opt
opt = { }
for o in dict(old_opt).keys():
if o.startswith("--"):
for x in all_opt.keys():
if all_opt[x].has_key("longopt") and "--" + all_opt[x]["longopt"] == o:
opt["--" + all_opt[x]["longopt"]] = dict(old_opt)[o]
else:
for x in all_opt.keys():
if all_opt[x].has_key("getopt") and all_opt[x].has_key("longopt") and \
("-" + all_opt[x]["getopt"] == o or "-" + all_opt[x]["getopt"].rstrip(":") == o):
opt["--" + all_opt[x]["longopt"]] = dict(old_opt)[o]
opt[o] = dict(old_opt)[o]
## Compatibility Layer
#####
z = dict(opt)
if z.has_key("--plug") == 1:
z["-m"] = z["--plug"]
opt = z
##
#####
else:
opt = { }
name = ""
for line in sys.stdin.readlines():
line = line.strip()
if ((line.startswith("#")) or (len(line) == 0)):
continue
(name, value) = (line + "=").split("=", 1)
value = value[:-1]
if avail_opt.count(name) == 0:
sys.stderr.write("Parse error: Ignoring unknown option '"+line+"'\n")
syslog.syslog(syslog.LOG_WARNING, "Parse error: Ignoring unknown option '"+line)
continue
if all_opt[name]["getopt"].endswith(":"):
opt["--"+all_opt[name]["longopt"].rstrip(":")] = value
elif value.lower() in [ "1", "yes", "on", "true" ]:
opt["--"+all_opt[name]["longopt"]] = "1"
return opt
##
## This function checks input and answers if we want to have same answers
## in each of the fencing agents. It looks for possible errors and run
## password script to set a correct password
######
def check_input(device_opt, opt):
device_opt.extend(add_dependency_options(device_opt))
options = dict(opt)
options["device_opt"] = device_opt
## Set requirements that should be included in metadata
#####
if device_opt.count("login") and device_opt.count("no_login") == 0:
all_opt["login"]["required"] = "1"
else:
all_opt["login"]["required"] = "0"
## Set default values
#####
for opt in device_opt:
if all_opt[opt].has_key("default"):
getopt_long = "--" + all_opt[opt]["longopt"]
if 0 == options.has_key(getopt_long):
options[getopt_long] = all_opt[opt]["default"]
if device_opt.count("ipport"):
if options.has_key("--ipport"):
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default "+ options["--ipport"] +")"
elif options.has_key("--ssh"):
all_opt["ipport"]["default"] = 22
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 22)"
elif options.has_key("--ssl"):
all_opt["ipport"]["default"] = 443
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 443)"
elif device_opt.count("web"):
all_opt["ipport"]["default"] = 80
if device_opt.count("ssl") == 0:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 80)"
else:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use\n\
(default 80, 443 if --ssl option is used)"
else:
all_opt["ipport"]["default"] = 23
if device_opt.count("secure") == 0:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default 23)"
else:
all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use\n\
(default 23, 22 if --ssh option is used)"
## In special cases (show help, metadata or version) we don't need to check anything
#####
if options.has_key("--help") or options.has_key("--version") or (options.has_key("--action") and options["--action"].lower() == "metadata"):
return options
options["--action"] = options["--action"].lower()
if options.has_key("--verbose"):
options["log"] = LOG_MODE_VERBOSE
else:
options["log"] = LOG_MODE_QUIET
acceptable_actions = [ "on", "off", "status", "list", "monitor" ]
if 1 == device_opt.count("fabric_fencing"):
## Compatibility layer
#####
acceptable_actions.extend(["enable", "disable"])
else:
acceptable_actions.extend(["reboot"])
if 0 == acceptable_actions.count(options["--action"]):
fail_usage("Failed: Unrecognised action '" + options["--action"] + "'")
## Compatibility layer
#####
if options["--action"] == "enable":
options["--action"] = "on"
if options["--action"] == "disable":
options["--action"] = "off"
## automatic detection and set of valid UUID from --plug
if (0 == options.has_key("--username")) and device_opt.count("login") and (device_opt.count("no_login") == 0):
fail_usage("Failed: You have to set login name")
if device_opt.count("ipaddr") and 0 == options.has_key("--ip") and 0 == options.has_key("--managed"):
fail_usage("Failed: You have to enter fence address")
if (device_opt.count("no_password") == 0):
if 0 == device_opt.count("identity_file"):
if 0 == (options.has_key("--password") or options.has_key("--password-script")):
fail_usage("Failed: You have to enter password or password script")
else:
if 0 == (options.has_key("--password") or options.has_key("--password-script") or options.has_key("--identity-file")):
fail_usage("Failed: You have to enter password, password script or identity file")
if 0 == options.has_key("--ssh") and 1 == options.has_key("--identity-file"):
fail_usage("Failed: You have to use identity file together with ssh connection (-x)")
if 1 == options.has_key("--identity-file"):
if 0 == os.path.isfile(options["--identity-file"]):
fail_usage("Failed: Identity file " + options["--identity-file"] + " does not exist")
if (0 == ["list", "monitor"].count(options["--action"].lower())) and \
0 == options.has_key("--plug") and device_opt.count("port") and device_opt.count("no_port") == 0:
fail_usage("Failed: You have to enter plug number or machine identification")
if options.has_key("--password-script"):
options["--password"] = os.popen(options["--password-script"]).read().rstrip()
if options.has_key("--debug-file"):
try:
options["debug_fh"] = file (options["--debug-file"], "w")
except IOError:
fail_usage("Failed: Unable to create file " + options["--debug-file"])
if options.has_key("--verbose") and options.has_key("debug_fh") == 0:
options["debug_fh"] = sys.stderr
if options.has_key("--snmp-priv-passwd-script"):
options["--snmp-priv-passwd"] = os.popen(options["--snmp-priv-passwd-script"]).read().rstrip()
if options.has_key("--ipport") == False:
if options.has_key("--ssh"):
options["--ipport"] = 22
elif options.has_key("--ssl"):
options["--ipport"] = 443
elif device_opt.count("web"):
options["--ipport"] = 80
else:
options["--ipport"] = 23
return options
def wait_power_status(tn, options, get_power_fn):
for dummy in xrange(int(options["--power-timeout"])):
if get_multi_power_fn(tn, options, get_power_fn) != options["--action"]:
time.sleep(1)
else:
return 1
return 0
## Obtain a power status from possibly more than one plug
## "on" is returned if at least one plug is ON
######
def get_multi_power_fn(tn, options, get_power_fn):
status = "off"
if options.has_key("--plugs"):
for plug in options["--plugs"]:
try:
options["--uuid"] = str(uuid.UUID(plug))
except ValueError:
pass
except KeyError:
pass
options["--plug"] = plug
plug_status = get_power_fn(tn, options)
if plug_status != "off":
status = plug_status
else:
status = get_power_fn(tn, options)
return status
def set_multi_power_fn(tn, options, set_power_fn):
if options.has_key("--plugs"):
for plug in options["--plugs"]:
try:
options["--uuid"] = str(uuid.UUID(plug))
except ValueError:
pass
except KeyError:
pass
options["--plug"] = plug
set_power_fn(tn, options)
else:
set_power_fn(tn, options)
def show_docs(options, docs = None):
device_opt = options["device_opt"]
if docs == None:
docs = { }
docs["shortdesc"] = "Fence agent"
docs["longdesc"] = ""
## Process special options (and exit)
#####
if options.has_key("--help"):
usage(device_opt)
sys.exit(0)
if options.has_key("--action") and options["--action"].lower() == "metadata":
metadata(device_opt, options, docs)
sys.exit(0)
if options.has_key("--version"):
print __main__.RELEASE_VERSION, __main__.BUILD_DATE
print __main__.REDHAT_COPYRIGHT
sys.exit(0)
def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = None):
result = 0
try:
if options.has_key("--plug"):
options["--plugs"] = options["--plug"].split(",")
## Process options that manipulate fencing device
#####
if (options["--action"] == "list") and 0 == options["device_opt"].count("port"):
print "N/A"
return
elif (options["--action"] == "list" and get_outlet_list == None):
## @todo: exception?
## This is just temporal solution, we will remove default value
## None as soon as all existing agent will support this operation
print "NOTICE: List option is not working on this device yet"
return
elif (options["--action"] == "list") or ((options["--action"] == "monitor") and 1 == options["device_opt"].count("port")):
outlets = get_outlet_list(tn, options)
## keys can be numbers (port numbers) or strings (names of VM)
for o in outlets.keys():
(alias, status) = outlets[o]
if options["--action"] != "monitor":
print o + options["--separator"] + alias
return
status = get_multi_power_fn(tn, options, get_power_fn)
if status != "on" and status != "off":
fail(EC_STATUS)
if options["--action"] == "on":
if status == "on":
print "Success: Already ON"
else:
power_on = False
for _ in range(1, 1 + int(options["--retry-on"])):
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn):
power_on = True
break
if power_on:
print "Success: Powered ON"
else:
fail(EC_WAITING_ON)
elif options["--action"] == "off":
if status == "off":
print "Success: Already OFF"
else:
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn):
print "Success: Powered OFF"
else:
fail(EC_WAITING_OFF)
elif options["--action"] == "reboot":
if status != "off":
options["--action"] = "off"
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn) == 0:
fail(EC_WAITING_OFF)
options["--action"] = "on"
power_on = False
try:
for _ in range(1, 1 + int(options["--retry-on"])):
set_multi_power_fn(tn, options, set_power_fn)
time.sleep(int(options["--power-wait"]))
if wait_power_status(tn, options, get_power_fn) == 1:
power_on = True
break
except Exception, ex:
# an error occured during power ON phase in reboot
# fence action was completed succesfully even in that case
sys.stderr.write(str(ex))
syslog.syslog(syslog.LOG_NOTICE, str(ex))
pass
if power_on == False:
# this should not fail as node was fenced succesfully
sys.stderr.write('Timed out waiting to power ON\n')
syslog.syslog(syslog.LOG_NOTICE, "Timed out waiting to power ON")
print "Success: Rebooted"
elif options["--action"] == "status":
print "Status: " + status.upper()
if status.upper() == "OFF":
result = 2
elif options["--action"] == "monitor":
pass
except pexpect.EOF:
fail(EC_CONNECTION_LOST)
except pexpect.TIMEOUT:
fail(EC_TIMED_OUT)
except pycurl.error, ex:
sys.stderr.write(ex[1] + "\n")
syslog.syslog(syslog.LOG_ERR, ex[1])
fail(EC_TIMED_OUT)
return result
def fence_login(options, re_login_string = "(login\s*: )|(Login Name: )|(username: )|(User Name :)"):
force_ipvx=""
if (options.has_key("--inet6-only")):
force_ipvx = "-6 "
if (options.has_key("--inet4-only")):
force_ipvx = "-4 "
if (options.has_key("eol") == False):
options["eol"] = "\r\n"
if options.has_key("--command-prompt") and type(options["--command-prompt"]) is not list:
options["--command-prompt"] = [ options["--command-prompt"] ]
## Do the delay of the fence device before logging in
## Delay is important for two-node clusters fencing but we do not need to delay 'status' operations
if options["--action"] in ["off", "reboot"]:
time.sleep(int(options["--delay"]))
try:
re_login = re.compile(re_login_string, re.IGNORECASE)
re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
if options.has_key("--ssl"):
command = '%s %s %s %s' % (SSL_PATH, force_ipvx, options["--ip"], options["--ipport"])
try:
conn = fspawn(options, command)
except pexpect.ExceptionPexpect, ex:
## SSL telnet is part of the fencing package
sys.stderr.write(str(ex) + "\n")
syslog.syslog(syslog.LOG_ERR, str(ex))
sys.exit(EC_GENERIC_ERROR)
elif options.has_key("--ssh") and 0 == options.has_key("--identity-file"):
command = '%s %s %s@%s -p %s' % (SSH_PATH, force_ipvx, options["--username"], options["--ip"], options["--ipport"])
if options.has_key("--ssh-options"):
command += ' ' + options["--ssh-options"]
try:
conn = fspawn(options, command)
except pexpect.ExceptionPexpect, ex:
sys.stderr.write(str(ex) + "\n")
syslog.syslog(syslog.LOG_ERR, str(ex))
sys.stderr.write("Due to limitations, binary dependencies on fence agents "
"are not in the spec file and must be installed separately." + "\n")
sys.exit(EC_GENERIC_ERROR)
if options.has_key("telnet_over_ssh"):
#This is for stupid ssh servers (like ALOM) which behave more like telnet (ignore name and display login prompt)
result = conn.log_expect(options, [ re_login, "Are you sure you want to continue connecting (yes/no)?" ], int(options["--login-timeout"]))
if result == 1:
conn.sendline("yes") # Host identity confirm
conn.log_expect(options, re_login, int(options["--login-timeout"]))
conn.sendline(options["--username"])
conn.log_expect(options, re_pass, int(options["--login-timeout"]))
else:
result = conn.log_expect(options, [ "ssword:", "Are you sure you want to continue connecting (yes/no)?" ], int(options["--login-timeout"]))
if result == 1:
conn.sendline("yes")
conn.log_expect(options, "ssword:", int(options["--login-timeout"]))
conn.sendline(options["--password"])
conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
elif options.has_key("--ssh") and options.has_key("--identity-file"):
command = '%s %s %s@%s -i %s -p %s' % (SSH_PATH, force_ipvx, options["--username"], options["--ip"], options["--identity-file"], options["--ipport"])
if options.has_key("--ssh-options"):
command += ' ' + options["--ssh-options"]
try:
conn = fspawn(options, command)
except pexpect.ExceptionPexpect, ex:
sys.stderr.write(str(ex) + "\n")
syslog.syslog(syslog.LOG_ERR, str(ex))
sys.stderr.write("Due to limitations, binary dependencies on fence agents "
"are not in the spec file and must be installed separately." + "\n")
sys.exit(EC_GENERIC_ERROR)
result = conn.log_expect(options, [ options["--command-prompt"], \
"Are you sure you want to continue connecting (yes/no)?", \
"Enter passphrase for key '" + options["--identity-file"] + "':" ], int(options["--login-timeout"]))
if result == 1:
conn.sendline("yes")
conn.log_expect(options, [ options["--command-prompt"], "Enter passphrase for key '"+options["--identity-file"]+"':"] , int(options["--login-timeout"]))
if result != 0:
if options.has_key("--password"):
conn.sendline(options["--password"])
conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
else:
fail_usage("Failed: You have to enter passphrase (-p) for identity file")
else:
try:
conn = fspawn(options, TELNET_PATH)
conn.send("set binary\n")
conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
except pexpect.ExceptionPexpect, ex:
sys.stderr.write(str(ex) + "\n")
syslog.syslog(syslog.LOG_ERR, str(ex))
sys.stderr.write("Due to limitations, binary dependencies on fence agents "
"are not in the spec file and must be installed separately." + "\n")
sys.exit(EC_GENERIC_ERROR)
result = conn.log_expect(options, re_login, int(options["--login-timeout"]))
conn.send_eol(options["--username"])
## automatically change end of line separator
screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
if (re_login.search(screen) != None):
options["eol"] = "\n"
conn.send_eol(options["--username"])
result = conn.log_expect(options, re_pass, int(options["--login-timeout"]))
elif (re_pass.search(screen) == None):
conn.log_expect(options, re_pass, int(options["--shell-timeout"]))
try:
conn.send_eol(options["--password"])
valid_password = conn.log_expect(options, [ re_login_string ] + options["--command-prompt"], int(options["--shell-timeout"]))
if valid_password == 0:
## password is invalid or we have to change EOL separator
options["eol"] = "\r"
conn.send_eol("")
conn.send_eol("")
conn.send_eol(options["--username"])
conn.log_expect(options, re_pass, int(options["--login-timeout"]))
conn.send_eol(options["--password"])
conn.log_expect(options, options["--command-prompt"], int(options["--login-timeout"]))
except KeyError:
fail(EC_PASSWORD_MISSING)
except pexpect.EOF:
fail(EC_LOGIN_DENIED)
except pexpect.TIMEOUT:
fail(EC_LOGIN_DENIED)
return conn
diff --git a/fence/agents/scsi/fence_scsi.pl b/fence/agents/scsi/fence_scsi.pl
index 4e5cc964..2585f9e9 100644
--- a/fence/agents/scsi/fence_scsi.pl
+++ b/fence/agents/scsi/fence_scsi.pl
@@ -1,868 +1,868 @@
#!/usr/bin/perl
use Cwd 'realpath';
use File::Basename;
use File::Path;
use Getopt::Std;
use POSIX;
#BEGIN_VERSION_GENERATION
$RELEASE_VERSION="";
$REDHAT_COPYRIGHT="";
$BUILD_DATE="";
#END_VERSION_GENERATION
my $ME = fileparse ($0, ".pl");
################################################################################
sub log_debug ($)
{
my $time = strftime "%b %e %T", localtime;
my ($msg) = @_;
print STDOUT "$time $ME: [debug] $msg\n" unless defined ($opt_q);
return;
}
sub log_error ($)
{
my $time = strftime "%b %e %T", localtime;
my ($msg) = @_;
print STDERR "$time $ME: [error] $msg\n" unless defined ($opt_q);
exit (1);
}
sub do_action_on ($@)
{
my $self = (caller(0))[3];
my ($node_key, @devices) = @_;
key_write ($node_key);
foreach $dev (@devices) {
log_error ("device $dev does not exist") if (! -e $dev);
log_error ("device $dev is not a block device") if (! -b $dev);
if (do_register_ignore ($node_key, $dev) != 0) {
log_error ("failed to create registration (key=$node_key, device=$dev)");
}
if (!get_reservation_key ($dev)) {
if (do_reserve ($node_key, $dev) != 0) {
if (!get_reservation_key ($dev)) {
log_error ("failed to create reservation (key=$node_key, device=$dev)");
}
}
}
}
return;
}
sub do_action_off ($@)
{
my $self = (caller(0))[3];
my ($node_key, @devices) = @_;
my $host_key = key_read ();
if ($host_key eq $node_key) {
log_error ($self);
}
foreach $dev (@devices) {
log_error ("device $dev does not exist") if (! -e $dev);
log_error ("device $dev is not a block device") if (! -b $dev);
my @keys = grep { /^$node_key$/i } get_registration_keys ($dev);
if (scalar (@keys) != 0) {
do_preempt_abort ($host_key, $node_key, $dev);
}
}
return;
}
sub do_action_status ($@)
{
my $self = (caller(0))[3];
my ($node_key, @devices) = @_;
my $dev_count = 0;
my $key_count = 0;
foreach $dev (@devices) {
log_error ("device $dev does not exist") if (! -e $dev);
log_error ("device $dev is not a block device") if (! -b $dev);
do_reset ($dev);
my @keys = grep { /^$node_key$/i } get_registration_keys ($dev);
if (scalar (@keys) != 0) {
$dev_count++;
}
}
if ($dev_count != 0) {
exit (0);
} else {
exit (2);
}
}
sub do_verify_on ($@)
{
my $self = (caller(0))[3];
my ($node_key, @devices) = @_;
my $count = 0;
for $dev (@devices) {
my @keys = grep { /^$node_key$/i } get_registration_keys ($dev);
## check that our key is registered
if (scalar (@keys) == 0) {
log_debug ("failed to register key $node_key on device $dev");
$count++;
next;
}
## write dev to device file once registration is verified
dev_write ($dev);
## check that a reservation exists
if (!get_reservation_key ($dev)) {
log_debug ("no reservation exists on device $dev");
$count++;
}
}
if ($count != 0) {
log_error ("$self: failed to verify $count devices");
}
}
sub do_verify_off ($@)
{
my $self = (caller(0))[3];
my ($node_key, @devices) = @_;
my $count = 0;
for $dev (@devices) {
my @keys = grep { /^$node_key$/i } get_registration_keys ($dev);
## check that our key is not registered
if (scalar (@keys) != 0) {
log_debug ("failed to remove key $node_key from device $dev");
$count++;
next;
}
## check that a reservation exists
if (!get_reservation_key ($dev)) {
log_debug ("no reservation exists on device $dev");
$count++;
}
}
if ($count != 0) {
log_error ("$self: failed to verify $count devices");
}
}
sub do_register ($$$)
{
my $self = (caller(0))[3];
my ($host_key, $node_key, $dev) = @_;
$dev = realpath ($dev);
if (substr ($dev, 5) =~ /^dm/) {
my @slaves = get_mpath_slaves ($dev);
foreach (@slaves) {
do_register ($node_key, $_);
}
return;
}
log_debug ("$self (host_key=$host_key, node_key=$node_key, dev=$dev)");
my $cmd;
my $out;
my $err;
do_reset ($dev);
$cmd = "sg_persist -n -o -G -K $host_key -S $node_key -d $dev";
$cmd .= " -Z" if (defined $opt_a);
$out = qx { $cmd 2> /dev/null };
$err = ($?>>8);
# if ($err != 0) {
# log_error ("$self (err=$err)");
# }
log_debug ("$self (err=$err)");
return ($err);
}
sub do_register_ignore ($$)
{
my $self = (caller(0))[3];
my ($node_key, $dev) = @_;
$dev = realpath ($dev);
if (substr ($dev, 5) =~ /^dm/) {
my @slaves = get_mpath_slaves ($dev);
foreach (@slaves) {
do_register_ignore ($node_key, $_);
}
return;
}
log_debug ("$self (node_key=$node_key, dev=$dev)");
my $cmd;
my $out;
my $err;
do_reset ($dev);
$cmd = "sg_persist -n -o -I -S $node_key -d $dev";
$cmd .= " -Z" if (defined $opt_a);
$out = qx { $cmd 2> /dev/null };
$err = ($?>>8);
# if ($err != 0) {
# log_error ("$self (err=$err)");
# }
log_debug ("$self (err=$err)");
return ($err);
}
sub do_reserve ($$)
{
my $self = (caller(0))[3];
my ($host_key, $dev) = @_;
log_debug ("$self (host_key=$host_key, dev=$dev)");
my $cmd = "sg_persist -n -o -R -T 5 -K $host_key -d $dev";
my $out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
# if ($err != 0) {
# log_error ("$self (err=$err)");
# }
log_debug ("$self (err=$err)");
return ($err);
}
sub do_release ($$)
{
my $self = (caller(0))[3];
my ($host_key, $dev) = @_;
log_debug ("$self (host_key=$host_key, dev=$dev)");
my $cmd = "sg_persist -n -o -L -T 5 -K $host_key -d $dev";
my $out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
# if ($err != 0) {
# log_error ("$self (err=$err)");
# }
log_debug ("$self (err=$err)");
return ($err);
}
sub do_preempt ($$$)
{
my $self = (caller(0))[3];
my ($host_key, $node_key, $dev) = @_;
log_debug ("$self (host_key=$host_key, node_key=$node_key, dev=$dev)");
my $cmd = "sg_persist -n -o -P -T 5 -K $host_key -S $node_key -d $dev";
my $out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
# if ($err != 0) {
# log_error ("$self (err=$err)");
# }
log_debug ("$self (err=$err)");
return ($err);
}
sub do_preempt_abort ($$$)
{
my $self = (caller(0))[3];
my ($host_key, $node_key, $dev) = @_;
log_debug ("$self (host_key=$host_key, node_key=$node_key, dev=$dev)");
my $cmd = "sg_persist -n -o -A -T 5 -K $host_key -S $node_key -d $dev";
my $out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
# if ($err != 0) {
# log_error ("$self (err=$err)");
# }
log_debug ("$self (err=$err)");
return ($err);
}
sub do_reset (S)
{
my $self = (caller(0))[3];
my ($dev) = @_;
my $cmd = "sg_turs $dev";
my @out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
## note that it is not necessarily an error is $err is non-zero,
## so just log the device and status and continue.
log_debug ("$self (dev=$dev, status=$err)");
return ($err);
}
sub dev_unlink ()
{
my $self = (caller(0))[3];
my $file = "/var/run/cluster/fence_scsi.dev";
if (-e $file) {
unlink ($file) or die "$!\n";
}
return;
}
sub dev_write ($)
{
my $self = (caller(0))[3];
my $file = "/var/run/cluster/fence_scsi.dev";
my $dev = shift;
if (! -d "/var/run/cluster") {
mkpath ("/var/run/cluster");
}
open (\*FILE, "+>>$file") or die "$!\n";
## since the file is opened for read, write and append,
## we need to seek to the beginning of the file before grep.
seek (FILE, 0, 0);
if (! grep { /^$dev$/ } ) {
print FILE "$dev\n";
}
close (FILE);
return;
}
sub key_read ()
{
my $self = (caller(0))[3];
my $file = "/var/run/cluster/fence_scsi.key";
my $key;
open (\*FILE, "<$file") or die "$!\n";
chomp ($key = );
close (FILE);
return ($key);
}
sub key_write ($)
{
my $self = (caller(0))[3];
my $file = "/var/run/cluster/fence_scsi.key";
my $key = shift;
if (! -d "/var/run/cluster") {
mkpath ("/var/run/cluster");
}
open (\*FILE, ">$file") or die "$!\n";
print FILE "$key\n";
close (FILE);
return;
}
sub get_key ($)
{
my $self = (caller(0))[3];
my $key = sprintf ("%.4x%.4x", get_cluster_id (), get_node_id ($_[0]));
return ($key);
}
sub get_node_id ($)
{
my $self = (caller(0))[3];
my $node_id;
my $cmd = "cman_tool nodes -n $_[0] -F id";
my $out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
if ($err != 0) {
log_error ("$self (err=$err)");
}
# die "[error]: $self\n" if ($?>>8);
chomp ($out);
$node_id = $out;
return ($node_id);
}
sub get_cluster_id ()
{
my $self = (caller(0))[3];
my $cluster_id;
my $cmd = "cman_tool status";
my @out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
if ($err != 0) {
log_error ("$self (err=$err)");
}
# die "[error]: $self\n" if ($?>>8);
foreach (@out) {
chomp;
my ($param, $value) = split (/\s*:\s*/, $_);
if ($param =~ /^cluster\s+id/i) {
$cluster_id = $value;
}
}
return ($cluster_id);
}
sub get_devices_clvm ()
{
my $self = (caller(0))[3];
my @devices;
my $cmd = "vgs --noheadings " .
" --separator : " .
" --sort pv_uuid " .
" --options vg_attr,pv_name " .
" --config 'global { locking_type = 0 } " .
" devices { preferred_names = [ \"^/dev/dm\" ] }'";
my @out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
if ($err != 0) {
log_error ("$self (err=$err)");
}
# die "[error]: $self\n" if ($?>>8);
foreach (@out) {
chomp;
my ($vg_attr, $pv_name) = split (/:/, $_);
if ($vg_attr =~ /c$/) {
push (@devices, $pv_name);
}
}
return (@devices);
}
sub get_devices_scsi ()
{
my $self = (caller(0))[3];
my @devices;
opendir (\*DIR, "/sys/block/") or die "$!\n";
@devices = grep { /^sd/ } readdir (DIR);
closedir (DIR);
return (@devices);
}
sub get_mpath_name ($)
{
my $self = (caller(0))[3];
my ($dev) = @_;
my $name;
if ($dev =~ /^\/dev\//) {
$dev = substr ($dev, 5);
}
open (\*FILE, "/sys/block/$dev/dm/name") or die "$!\n";
chomp ($name = );
close (FILE);
return ($name);
}
sub get_mpath_uuid ($)
{
my $self = (caller(0))[3];
my ($dev) = @_;
my $uuid;
if ($dev =~ /^\/dev\//) {
$dev = substr ($dev, 5);
}
open (\*FILE, "/sys/block/$dev/dm/uuid") or die "$!\n";
chomp ($uuid = );
close (FILE);
return ($name);
}
sub get_mpath_slaves ($)
{
my $self = (caller(0))[3];
my ($dev) = @_;
my @slaves;
if ($dev =~ /^\/dev\//) {
$dev = substr ($dev, 5);
}
opendir (\*DIR, "/sys/block/$dev/slaves/") or die "$!\n";
@slaves = grep { !/^\./ } readdir (DIR);
if ($slaves[0] =~ /^dm/) {
@slaves = get_mpath_slaves ($slaves[0]);
} else {
@slaves = map { "/dev/$_" } @slaves;
}
closedir (DIR);
return (@slaves);
}
sub get_registration_keys ($)
{
my $self = (caller(0))[3];
my ($dev) = @_;
my @keys;
my $cmd = "sg_persist -n -i -k -d $dev";
my @out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
if ($err != 0) {
log_error ("$self (err=$err)");
}
# die "[error]: $self\n" if ($?>>8);
foreach (@out) {
chomp;
if ($_ =~ s/^\s+0x//i) {
push (@keys, $_);
}
}
return (@keys);
}
sub get_reservation_key ($)
{
my $self = (caller(0))[3];
my ($dev) = @_;
my $key;
my $cmd = "sg_persist -n -i -r -d $dev";
my @out = qx { $cmd 2> /dev/null };
my $err = ($?>>8);
if ($err != 0) {
log_error ("$self (err=$err)");
}
# die "[error]: $self\n" if ($?>>8);
foreach (@out) {
chomp;
if ($_ =~ s/^\s+key=0x//i) {
$key = $_;
last;
}
}
return ($key)
}
sub get_options_stdin ()
{
my $num = 0;
while () {
chomp;
s/^\s*//;
s/\s*$//;
next if (/^#/);
$num++;
next unless ($_);
my ($opt, $arg) = split (/\s*=\s*/, $_);
if ($opt eq "") {
exit (1);
}
elsif ($opt eq "aptpl") {
$opt_a = $arg;
}
elsif ($opt eq "devices") {
$opt_d = $arg;
}
elsif ($opt eq "logfile") {
$opt_f = $arg;
}
elsif ($opt eq "key") {
$opt_k = $arg;
}
elsif ($opt eq "nodename") {
$opt_n = $arg;
}
elsif ($opt eq "action") {
$opt_o = $arg;
}
elsif ($opt eq "delay") {
$opt_H = $arg;
}
}
}
sub print_usage ()
{
print "Usage:\n";
print "\n";
print "$ME [options]\n";
print "\n";
print "Options:\n";
print " -a Use APTPL flag\n";
print " -d Devices to be used for action\n";
print " -f File to write debug/error output\n";
print " -H Wait X seconds before fencing is started\n";
print " -h Usage\n";
print " -k Key to be used for current action\n";
print " -n Name of node to operate on\n";
print " -o Action: off (default), on, or status\n";
print " -q Quiet mode\n";
print " -V Version\n";
exit (0);
}
sub print_version ()
{
print "$ME $RELEASE_VERSION $BUILD_DATE\n";
print "$REDHAT_COPYRIGHT\n" if ( $REDHAT_COPYRIGHT );
exit (0);
}
sub print_metadata ()
{
print "\n";
print "\n";
print "fence_scsi\n";
print "\n";
print "\t\n";
print "\t\t\n";
print "\t\t\n";
print "\t\t" .
"Use APTPL flag for registrations" .
"\n";
print "\t\n";
print "\t\n";
print "\t\t\n";
print "\t\t\n";
print "\t\t" .
"List of devices to be used for fencing action" .
"\n";
print "\t\n";
print "\t\n";
print "\t\t\n";
print "\t\t\n";
print "\t\t" .
"File to write error/debug messages" .
"\n";
print "\t\n";
print "\t\n";
print "\t\t\n";
print "\t\t\n";
print "\t\t" .
"Wait X seconds before fencing is started" .
"\n";
print "\t\n";
print "\t\n";
print "\t\t\n";
print "\t\t\n";
print "\t\t" .
"Key value to be used for fencing action" .
"\n";
print "\t\n";
print "\t\n";
print "\t\t\n";
print "\t\t\n";
print "\t\t" .
"Fencing action" .
"\n";
print "\t\n";
print "\t\n";
print "\t\t\n";
print "\t\t\n";
print "\t\t" .
"Name of node" .
"\n";
print "\t\n";
print "\n";
print "\n";
- print "\t\n";
+ print "\t\n";
print "\t\n";
print "\t\n";
print "\t\n";
print "\n";
print "\n";
exit (0);
}
################################################################################
if (@ARGV > 0) {
getopts ("ad:f:H:hk:n:o:qV") or print_usage;
print_usage if (defined $opt_h);
print_version if (defined $opt_V);
} else {
get_options_stdin ();
}
## handle the metadata action here to avoid other parameter checks
##
if ($opt_o =~ /^metadata$/i) {
print_metadata;
}
## if the logfile (-f) parameter was specified, open the logfile
## and redirect STDOUT and STDERR to the logfile.
##
if (defined $opt_f) {
open (LOG, ">>$opt_f") or die "$!\n";
open (STDOUT, ">&LOG");
open (STDERR, ">&LOG");
}
## verify that either key or nodename have been specified
##
if ((!defined $opt_n) && (!defined $opt_k)) {
print_usage ();
}
## determine key value
##
if (defined $opt_k) {
$key = $opt_k;
} else {
$key = get_key ($opt_n);
}
## verify that key is not zero
##
if (hex($key) == 0) {
log_error ("key cannot be zero");
}
## remove any leading zeros from key
##
if ($key =~ /^0/) {
$key =~ s/^0+//;
}
## get devices
##
if (defined $opt_d) {
@devices = split (/\s*,\s*/, $opt_d);
} else {
@devices = get_devices_clvm ();
}
## verify that device list is not empty
##
if (scalar (@devices) == 0) {
log_error ("no devices found");
}
## default action is "off"
##
if (!defined $opt_o) {
$opt_o = "off";
}
## Wait for defined period (-H / delay= )
##
if ((defined $opt_H) && ($opt_H =~ /^[0-9]+/)) {
sleep($opt_H);
}
## determine the action to perform
##
if ($opt_o =~ /^on$/i) {
do_action_on ($key, @devices);
do_verify_on ($key, @devices);
}
elsif ($opt_o =~ /^off$/i) {
do_action_off ($key, @devices);
do_verify_off ($key, @devices);
}
elsif ($opt_o =~ /^status/i) {
do_action_status ($key, @devices);
} else {
log_error ("unknown action '$opt_o'");
exit (1);
}
## close the logfile
##
if (defined $opt_f) {
close (LOG);
}