diff --git a/fencing/fence_dummy b/fencing/fence_dummy index 00f812333b..55baa383e3 100755 --- a/fencing/fence_dummy +++ b/fencing/fence_dummy @@ -1,362 +1,369 @@ #!/usr/bin/python - -# The Following Agent Has Been Tested On: -# -# Virsh 0.3.3 on RHEL 5.2 with xen-3.0.3-51 -# - -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 +"""Dummy fence agent for testing +""" + +import os +import re +import sys +import time +import random +import atexit +import getopt + +AGENT_VERSION = "3.2.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.""" 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", + "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] Issue a sleep between 1 and [seconds]. Used for testing.", + "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). Used for testing.", + "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 or\n" + - " name of virtual machine", + "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 }, "nodeid" : { "getopt" : "i:", "longopt" : "nodeid", - "help" : "-i, --nodeid corosync id of fence victim", + "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.", + "help" : "-U, --uuid UUID of the VM to fence", "required" : "0", - "shortdesc" : "The UUID of the virtual machine to fence.", + "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.", + "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} } -def show_docs(options, docs = None): + +def show_docs(options): + """ Handle informational options (display info and exit). """ + 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) + metadata(device_opt, options) sys.exit(0) if options.has_key("-V"): - print __main__.RELEASE_VERSION, __main__.BUILD_DATE - print __main__.REDHAT_COPYRIGHT + 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): + +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(lambda x, y: cmp(x[1]["order"], y[1]["order"])) - print "" - print "" - print "" + docs["longdesc"] + "" - if docs.has_key("vendorurl"): - print "" + docs["vendorurl"] + "" - print "" + print """ + +%s +%s +""" % (os.path.basename(sys.argv[0]), SHORT_DESC, + AGENT_VERSION, OCF_VERSION, LONG_DESC) + 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 "" + 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 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) 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 options.has_key("-D"): + try: + f = open(options["-D"], 'a') + 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"): val = int(options["-f"]) sys.stderr.write("delay sleep for %d seconds\n" % val) time.sleep(val) if options.has_key("-R"): 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"): sys.stderr.write("fence_dummy monitor called\n") sys.exit(0) if options.has_key("-o") and (options["-o"] == "list"): sys.stderr.write("fence_dummy action (list) called\n") if options.has_key("-H"): 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 options["-M"] == "pass": sys.exit(0) elif options["-M"] == "fail": sys.exit(1) sys.exit(random.randint(0, 1)) if __name__ == "__main__": main()