diff --git a/fencing/fence_dummy b/fencing/fence_dummy
index c3c4604131..8d8639def0 100755
--- a/fencing/fence_dummy
+++ b/fencing/fence_dummy
@@ -1,362 +1,380 @@
#!/usr/bin/python
+"""Dummy fence agent for testing
+"""
+
+# Pacemaker targets compatibility with python 2.6+ and 3.2+
+from __future__ import print_function, unicode_literals, absolute_import, division
+
+import io
+import os
+import re
+import sys
+import time
+import random
+import atexit
+import getopt
+
+AGENT_VERSION = "4.0.0"
+OCF_VERSION = "1.0"
+SHORT_DESC = "Dummy fence agent"
+LONG_DESC = """fence_dummy is a fake fencing agent which reports success
+based on its mode (pass|fail|random) without doing anything."""
-# The Following Agent Has Been Tested On:
-#
-# Virsh 0.3.3 on RHEL 5.2 with xen-3.0.3-51
-#
+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 Display version information and exit",
+ "required" : "0",
+ "shortdesc" : "Display version information and exit",
+ "order" : 53 },
+ "quiet" : {
+ "getopt" : "q",
+ "help" : "",
+ "order" : 50 },
+ "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 },
+ "random_sleep_range": {
+ "getopt" : "R:",
+ "required" : "0",
+ "longopt" : "random_sleep_range",
+ "help" : "--random_sleep_range=[seconds] Sleep between 1 and [seconds] before returning",
+ "shortdesc" : "Issue a sleep between 1 and [seconds]",
+ "order" : 1 },
+ "mode": {
+ "getopt" : "M:",
+ "longopt" : "mode",
+ "required" : "0",
+ "help" : "--mode=(pass|fail|random) What exit status should be returned for this operation",
+ "shortdesc" : "Should operations always pass, always fail or fail at random",
+ "order" : 1 },
+ "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 },
+ "action" : {
+ "getopt" : "o:",
+ "longopt" : "action",
+ "help" : "-o, --action=[action] Action: status, list, reboot (default), off or on",
+ "required" : "1",
+ "shortdesc" : "Fencing Action",
+ "default" : "reboot",
+ "order" : 1 },
+ "port" : {
+ "getopt" : "n:",
+ "longopt" : "plug",
+ "help" : "-n, --plug=[id] Physical plug number on device",
+ "required" : "1",
+ "shortdesc" : "Physical plug number or name of virtual machine",
+ "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 },
+ "nodename" : {
+ "getopt" : "N:",
+ "longopt" : "nodename",
+ "help" : "-N, --nodename Node name of fence victim",
+ "required" : "0",
+ "shortdesc" : "The node name of fence victim",
+ "order" : 1},
+ "nodeid" : {
+ "getopt" : "i:",
+ "longopt" : "nodeid",
+ "help" : "-i, --nodeid Corosync id of fence victim",
+ "required" : "0",
+ "shortdesc" : "The corosync id of fence victim",
+ "order" : 1},
+ "uuid" : {
+ "getopt" : "U:",
+ "longopt" : "uuid",
+ "help" : "-U, --uuid UUID of the VM to fence",
+ "required" : "0",
+ "shortdesc" : "The UUID of the virtual machine to fence",
+ "order" : 1},
+ "mock_dynamic_hosts" : {
+ "getopt" : "H:",
+ "longopt" : "mock_dynamic_hosts",
+ "help" : "-H, --mock_dynamic_hosts=[list] What to return when dynamically queried for possible targets",
+ "required" : "0",
+ "shortdesc" : "A list of hosts we can fence.",
+ "order" : 1}
+}
-import sys, time, random, os, atexit, getopt, re
-#BEGIN_VERSION_GENERATION
-RELEASE_VERSION="3.1.6"
-BUILD_DATE="(built Mon Oct 24 12:14:08 UTC 2011)"
-REDHAT_COPYRIGHT="Copyright (C) Red Hat, Inc. 2004-2010 All rights reserved."
-#END_VERSION_GENERATION
+def fail_usage(message):
+ sys.stderr.write("%s\nPlease use '-h' for usage\n" % message)
+ sys.exit(1)
-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 },
- "quiet" : {
- "getopt" : "q",
- "help" : "",
- "order" : 50 },
- "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 },
- "random_sleep_range": {
- "getopt" : "R:",
- "required" : "0",
- "longopt" : "random_sleep_range",
- "help" : "--random_sleep-range=[seconds] Issue a sleep between 1 and [seconds]. Used for testing.",
- "shortdesc" : "Issue a sleep between 1 and [seconds]",
- "order" : 1 },
- "mode": {
- "getopt" : "M:",
- "longopt" : "mode",
- "required" : "0",
- "help" : "--mode=(pass|fail|random). Used for testing.",
- "shortdesc" : "Should operations always pass, always fail or fail at random",
- "order" : 1 },
- "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 },
- "action" : {
- "getopt" : "o:",
- "longopt" : "action",
- "help" : "-o, --action=[action] Action: status, list, reboot (default), off or on",
- "required" : "1",
- "shortdesc" : "Fencing Action",
- "default" : "reboot",
- "order" : 1 },
- "port" : {
- "getopt" : "n:",
- "longopt" : "plug",
- "help" : "-n, --plug=[id] Physical plug number on device or\n" +
- " name of virtual machine",
- "required" : "1",
- "shortdesc" : "Physical plug number or name of virtual machine",
- "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 },
- "nodeid" : {
- "getopt" : "i:",
- "longopt" : "nodeid",
- "help" : "-i, --nodeid corosync id of fence victim",
- "required" : "0",
- "shortdesc" : "The corosync id of fence victim",
- "order" : 1},
- "uuid" : {
- "getopt" : "U:",
- "longopt" : "uuid",
- "help" : "-U, --uuid UUID of the VM to fence.",
- "required" : "0",
- "shortdesc" : "The UUID of the virtual machine to fence.",
- "order" : 1},
- "mock_dynamic_hosts" : {
- "getopt" : "H:",
- "longopt" : "mock_dynamic_hosts",
- "help" : "-H, --mock_dynamic_hosts=[hostlist] List of hosts we can fence.",
- "required" : "0",
- "shortdesc" : "A list of hosts we can fence.",
- "order" : 1}
-}
-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("-h"):
- usage(device_opt)
- sys.exit(0)
-
- if options.has_key("-o") and options["-o"].lower() == "metadata":
- sys.stderr.write("asked for fence_dummy metadata\n")
- metadata(device_opt, options, docs)
- sys.exit(0)
-
- if options.has_key("-V"):
- print __main__.RELEASE_VERSION, __main__.BUILD_DATE
- print __main__.REDHAT_COPYRIGHT
- sys.exit(0)
+def show_docs(options):
+ """ Handle informational options (display info and exit). """
+
+ device_opt = options["device_opt"]
+
+ if "-h" in options:
+ usage(device_opt)
+ sys.exit(0)
+
+ if "-o" in options and options["-o"].lower() == "metadata":
+ metadata(device_opt, options)
+ sys.exit(0)
+
+ if "-V" in options:
+ print(AGENT_VERSION)
+ sys.exit(0)
+
def usage(avail_opt):
- global all_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):
- global all_opt
-
- 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 ""
- 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 = "default=\""+str(all_opt[option]["default"])+"\""
- elif options.has_key("-" + all_opt[option]["getopt"][:-1]):
- if options["-" + all_opt[option]["getopt"][:-1]]:
- try:
- default = "default=\"" + options["-" + all_opt[option]["getopt"][:-1]] + "\""
- 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 = "default=\"" + str(options["-" + all_opt[option]["getopt"][:-1]]) +"\""
- elif options.has_key("-" + all_opt[option]["getopt"]):
- default = "default=\"true\" "
-
- 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 ""
- if avail_opt.count("io_fencing") == 0:
- print "\t"
- print "\t"
- print "\t"
- else:
- print "\t"
- print "\t"
-
- print "\t"
- print "\t"
- print "\t"
- print "\t"
- print ""
- print ""
+ global all_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(key=lambda x: x[1]["order"])
+
+ for key, value in sorted_list:
+ if len(value["help"]) != 0:
+ print(" " + value["help"])
+
+
+def metadata(avail_opt, options):
+ global all_opt
+
+ # This log is just for testing handling of stderr output
+ sys.stderr.write("asked for fence_dummy metadata\n")
+
+ sorted_list = [ (key, all_opt[key]) for key in avail_opt ]
+ sorted_list.sort(key=lambda x: x[1]["order"])
+
+ print("""
+
+%s
+%s
+""" % (os.path.basename(sys.argv[0]), SHORT_DESC,
+ AGENT_VERSION, OCF_VERSION, LONG_DESC))
+
+ for option, value in sorted_list:
+ if "shortdesc" in all_opt[option]:
+ print("\t")
+
+ default = ""
+ if "default" in all_opt[option]:
+ default = "default=\""+str(all_opt[option]["default"])+"\""
+ elif ("-" + all_opt[option]["getopt"][:-1]) in options:
+ if options["-" + all_opt[option]["getopt"][:-1]]:
+ try:
+ default = "default=\"" + options["-" + all_opt[option]["getopt"][:-1]] + "\""
+ 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 = "default=\"" + str(options["-" + all_opt[option]["getopt"][:-1]]) +"\""
+ elif ("-" + all_opt[option]["getopt"]) in options:
+ default = "default=\"true\" "
+
+ 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("""
+
+\t
+\t
+\t
+\t
+\t
+\t
+\t
+
+""")
def process_input(avail_opt):
- global all_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"])
-
- ## Compatibility layer
- if avail_opt.count("module_name") == 1:
- getopt_string += "n:"
- longopt_list.append("plug=")
-
- ##
- ## 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 longopt to short 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]["getopt"].rstrip(":")] = dict(old_opt)[o]
- else:
- opt[o] = dict(old_opt)[o]
-
- ## Compatibility Layer
- #####
- z = dict(opt)
- if z.has_key("-T") == 1:
- z["-o"] = "status"
- if z.has_key("-n") == 1:
- z["-m"] = z["-n"]
-
- 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]
-
- ## Compatibility Layer
- ######
- if name == "option":
- name = "action"
-
- ##
- ######
- if avail_opt.count(name) == 0:
- sys.stderr.write("Parse error: Ignoring unknown option '"+line+"'\n")
- continue
-
- if all_opt[name]["getopt"].endswith(":"):
- opt["-"+all_opt[name]["getopt"].rstrip(":")] = value
- elif ((value == "1") or (value.lower() == "yes") or (value.lower() == "on") or (value.lower() == "true")):
- opt["-"+all_opt[name]["getopt"]] = "1"
- return opt
+ global all_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 k in all_opt:
+ getopt_string += all_opt[k]["getopt"]
+ else:
+ fail_usage("Parse error: unknown option '"+k+"'")
+
+ if k in all_opt and "longopt" in all_opt[k]:
+ 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 as error:
+ fail_usage("Parse error: " + error.msg)
+
+ ## Transform longopt to short 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 "longopt" in all_opt[x] and "--" + all_opt[x]["longopt"] == o:
+ opt["-" + all_opt[x]["getopt"].rstrip(":")] = dict(old_opt)[o]
+ else:
+ opt[o] = dict(old_opt)[o]
+
+ ## Compatibility Layer
+ #####
+ z = dict(opt)
+ if "-T" in z:
+ z["-o"] = "status"
+ if "-n" in z:
+ z["-m"] = z["-n"]
+
+ 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]
+
+ ## Compatibility Layer
+ ######
+ if name == "option":
+ name = "action"
+
+ ##
+ ######
+ if avail_opt.count(name) == 0:
+ sys.stderr.write("Parse error: Ignoring unknown option '"+line+"'\n")
+ continue
+
+ if all_opt[name]["getopt"].endswith(":"):
+ opt["-"+all_opt[name]["getopt"].rstrip(":")] = value
+ elif ((value == "1") or (value.lower() == "yes") or (value.lower() == "on") or (value.lower() == "true")):
+ opt["-"+all_opt[name]["getopt"]] = "1"
+ return opt
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]))
- sys.exit(1)
+ try:
+ sys.stdout.close()
+ os.close(1)
+ except IOError:
+ sys.stderr.write("%s failed to close standard output\n"%(sys.argv[0]))
+ sys.exit(1)
def main():
global all_opt
device_opt = all_opt.keys()
## Defaults for fence agent
- docs = { }
- docs["shortdesc"] = "Dummy fence agent"
- docs["longdesc"] = "fence_dummy is a fake fencing agent which reports success based on its mode (pass|fail|random) without doing anything."
-
atexit.register(atexit_handler)
options = process_input(device_opt)
options["device_opt"] = device_opt
- show_docs(options, docs)
+ show_docs(options)
+
+
+ # dump input to file
+ if "-D" in options:
+ try:
+ f = io.open(options["-D"], 'at')
+ f.write("### %s ###\n" % (time.strftime("%Y-%m-%d %H:%M:%S")))
+ for v in sorted(options):
+ f.write("%s=%s\n" % (v, options[v]))
+ f.write("###\n")
+ f.close()
+ except IOError:
+ pass
# random sleep for testing
- if options.has_key("-f"):
+ if "-f" in options:
val = int(options["-f"])
sys.stderr.write("delay sleep for %d seconds\n" % val)
time.sleep(val)
- if options.has_key("-R"):
+ if "-R" in options:
val = int(options["-R"])
ran = random.randint(1, val)
sys.stderr.write("random sleep for %d seconds\n" % ran)
time.sleep(ran)
- if options.has_key("-o") and (options["-o"] == "monitor"):
+ if "-o" in options and (options["-o"] == "monitor"):
sys.stderr.write("fence_dummy monitor called\n")
sys.exit(0)
- if options.has_key("-o") and (options["-o"] == "list"):
+ if "-o" in options and (options["-o"] == "list"):
sys.stderr.write("fence_dummy action (list) called\n")
- if options.has_key("-H"):
- print options["-H"]
+ if "-H" in options:
+ print(options["-H"])
else:
sys.stderr.write("were asked for hostlist but attribute mock_dynamic_hosts wasn't set\n")
- if options.has_key("-M"):
+ if "-M" in options:
if options["-M"] == "pass":
sys.exit(0)
elif options["-M"] == "fail":
sys.exit(1)
sys.exit(random.randint(0, 1))
if __name__ == "__main__":
main()