From 39fd1b540bb06be1607d4fcd044b5e37abb2daba Mon Sep 17 00:00:00 2001 From: Marek 'marx' Grac <mgrac@redhat.com> Date: Mon, 12 Oct 2009 14:04:20 +0200 Subject: [PATCH] fencing: Support for 'metadata' option for fencing agents / show_docs New function for showing documentation that accepts default values. Better XML output for metadata and man-page creation. Part of solution for bz#488959 --- fence/agents/apc/fence_apc.py | 2 + fence/agents/bladecenter/fence_bladecenter.py | 2 + fence/agents/cisco_mds/fence_cisco_mds.py | 2 + fence/agents/drac/fence_drac5.py | 2 + fence/agents/eps/fence_eps.py | 2 + fence/agents/ilo/fence_ilo.py | 2 + fence/agents/lib/fencing.py.py | 146 +++++++++++++++++++------ fence/agents/lpar/fence_lpar.py | 2 + fence/agents/rsa/fence_rsa.py | 2 + fence/agents/sanbox2/fence_sanbox2.py | 2 + fence/agents/virsh/fence_virsh.py | 2 + fence/agents/vmware/fence_vmware.py | 2 + fence/agents/wti/fence_wti.py | 2 + 13 files changed, 138 insertions(+), 32 deletions(-) diff --git a/fence/agents/apc/fence_apc.py b/fence/agents/apc/fence_apc.py index 20efb49..ced7d39 100755 --- a/fence/agents/apc/fence_apc.py +++ b/fence/agents/apc/fence_apc.py @@ -201,6 +201,8 @@ def main(): if 0 == options.has_key("-c"): options["-c"] = "\n>" + show_docs(options) + ## Support for -n [switch]:[plug] notation that was used before if (options.has_key("-n") == 1) and (-1 != options["-n"].find(":")): (switch, plug) = options["-n"].split(":", 1) diff --git a/fence/agents/bladecenter/fence_bladecenter.py b/fence/agents/bladecenter/fence_bladecenter.py index 83f255c..ef7ed53 100755 --- a/fence/agents/bladecenter/fence_bladecenter.py +++ b/fence/agents/bladecenter/fence_bladecenter.py @@ -102,6 +102,8 @@ def main(): options = check_input(device_opt, process_input(device_opt)) + show_docs(options) + ## ## Operate the fencing device ###### diff --git a/fence/agents/cisco_mds/fence_cisco_mds.py b/fence/agents/cisco_mds/fence_cisco_mds.py index 989ec5c..1237ec8 100644 --- a/fence/agents/cisco_mds/fence_cisco_mds.py +++ b/fence/agents/cisco_mds/fence_cisco_mds.py @@ -106,6 +106,8 @@ def main(): options = check_input(device_opt, options) + show_docs(options) + if (not (options["-o"] in ["list","monitor"])): port_oid=cisco_port2oid(options["-n"]) diff --git a/fence/agents/drac/fence_drac5.py b/fence/agents/drac/fence_drac5.py index c3e1045..d93501a 100755 --- a/fence/agents/drac/fence_drac5.py +++ b/fence/agents/drac/fence_drac5.py @@ -97,6 +97,8 @@ def main(): if 0 == options.has_key("-c"): options["-c"] = "\$" + show_docs(options) + ## ## Operate the fencing device ###### diff --git a/fence/agents/eps/fence_eps.py b/fence/agents/eps/fence_eps.py index 0d2a63a..1660931 100644 --- a/fence/agents/eps/fence_eps.py +++ b/fence/agents/eps/fence_eps.py @@ -107,6 +107,8 @@ def main(): if (not options.has_key("-c")): options["-c"]="hidden.htm" + show_docs(options) + #Run fence action. Conn is None, beacause we always need open new http connection fence_action(None, options, set_power_status, get_power_status,get_power_status) diff --git a/fence/agents/ilo/fence_ilo.py b/fence/agents/ilo/fence_ilo.py index e67f645..ae94017 100755 --- a/fence/agents/ilo/fence_ilo.py +++ b/fence/agents/ilo/fence_ilo.py @@ -70,6 +70,8 @@ def main(): LOGIN_TIMEOUT = 10 + show_docs(options) + ## ## Login and get version number #### diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py index 3cd1818..19644c2 100644 --- a/fence/agents/lib/fencing.py.py +++ b/fence/agents/lib/fencing.py.py @@ -19,6 +19,7 @@ BUILD_DATE="" LOG_MODE_VERBOSE = 100 LOG_MODE_QUIET = 0 +EC_GENERIC_ERROR = 1 EC_BAD_ARGS = 2 EC_LOGIN_DENIED = 3 EC_CONNECTION_LOST = 4 @@ -37,11 +38,15 @@ all_opt = { "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", @@ -58,6 +63,8 @@ all_opt = { "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 }, "agent" : { "getopt" : "", @@ -133,21 +140,30 @@ all_opt = { "getopt" : "m:", "longopt" : "module-name", "help" : "-m, --module-name=<module> DRAC/MC module name", + "required" : "0", + "shortdesc" : "DRAC/MC module name", "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 }, "hmc_version" : { "getopt" : "H:", "longopt" : "hmc-version", - "help" : "-H, --hmc-version=<version> Force HMC version to use: 3, 4 (default)", + "help" : "-H, --hmc-version=<version> Force HMC version to use: 3, 4 (default)", + "required" : "0", + "shortdesc" : "Force HMC version to use (3 or 4)", + "default" : "4", "order" : 1 }, "ribcl" : { "getopt" : "r:", "longopt" : "ribcl-version", "help" : "-r, --ribcl-version=<version> Force ribcl version to use", + "required" : "0", + "shortdesc" : "Force ribcl version to use", "order" : 1 }, "login_eol_lf" : { "getopt" : "", @@ -158,13 +174,15 @@ all_opt = { "getopt" : "c:", "longopt" : "command-prompt", "help" : "-c, --command-prompt=<prompt> Force command prompt", + "shortdesc" : "Force command prompt", + "required" : "0", "order" : 1 }, "secure" : { "getopt" : "x", "longopt" : "ssh", "help" : "-x, --ssh Use ssh connection", - "required" : "0", "shortdesc" : "SSH connection", + "required" : "0", "order" : 1 }, "ssl" : { "getopt" : "z", @@ -223,31 +241,53 @@ all_opt = { "order" : 2 }, "snmp_version" : { "getopt" : "d:", - "help" : "-d <ver> Specifies SNMP version to use", + "longopt" : "snmp-version", + "help" : "-d, --snmp-version=<ver> Specifies SNMP version to use", + "required" : "0", + "shortdesc" : "Specifies SNMP version to use (1,2c,3)", "order" : 1 }, "community" : { "getopt" : "c:", - "help" : "-c <community> Set the community string", + "longopt" : "community", + "help" : "-c, --community=<community> Set the community string", + "required" : "0", + "shortdesc" : "Set the community string", "order" : 1}, "snmp_auth_prot" : { "getopt" : "b:", - "help" : "-b <prot> Set authentication protocol (MD5|SHA)", + "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:", - "help" : "-E <level> Set security level (noAuthNoPriv|authNoPriv|authPriv)", + "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:", - "help" : "-B <prot> Set privacy protocol (DES|AES)", + "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:", - "help" : "-P <pass> Set privacy protocol password", + "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:", - "help" : "-R <script> Script to run to retrieve privacy password", + "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", @@ -265,7 +305,10 @@ all_opt = { "order" : 1 }, "udpport" : { "getopt" : "u:", - "help" : "-u <port> UDP/TCP port to use", + "longopt" : "udpport", + "help" : "-u, --udpport UDP/TCP port to use", + "required" : "0", + "shortdesc" : "UDP/TCP port to use for connection with device", "order" : 1}, "separator" : { "getopt" : "C:", @@ -354,12 +397,15 @@ def usage(avail_opt): if len(value["help"]) != 0: print " " + value["help"] -def metadata(avail_opt): +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 "<?xml version=\"1.0\" ?>" + print "<resource-agent name=\"" + os.path.basename(sys.argv[0])[:-3] + "\" shortdesc=\"" + docs["shortdesc"] + "\" >" + print "<longdesc>" + docs["longdesc"] + "</longdesc>" print "<parameters>" for option, value in sorted_list: if all_opt[option].has_key("shortdesc"): @@ -368,14 +414,43 @@ def metadata(avail_opt): default = "" if all_opt[option].has_key("default"): default = "default=\""+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=\"list of values\"" + 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<getopt mixed=\"" + mixed + "\" />" if all_opt[option]["getopt"].count(":") > 0: print "\t\t<content type=\"string\" "+default+" />" else: print "\t\t<content type=\"boolean\" "+default+" />" + print "\t\t<shortdesc lang=\"en\">" + all_opt[option]["shortdesc"] + "</shortdesc>" print "\t</parameter>" print "</parameters>" + print "<actions>" + print "\t<action name=\"on\" />" + print "\t<action name=\"off\" />" + print "\t<action name=\"reboot\" />" + print "\t<action name=\"status\" />" + print "\t<action name=\"list\" />" + print "\t<action name=\"monitor\" />" + print "\t<action name=\"meta-data\" />" + print "</actions>" + print "</resource-agent>" def process_input(avail_opt): global all_opt @@ -488,20 +563,10 @@ def check_input(device_opt, opt): else: all_opt["login"]["required"] = "0" - ## Process special options (and exit) + ## In special cases (show help, metadata or version) we don't need to check anything ##### - if options.has_key("-h"): - usage(device_opt) - sys.exit(0) - - if options.has_key("-o") and options["-o"].lower() == "metadata": - metadata(device_opt) - sys.exit(0) - - if options.has_key("-V"): - print FENCE_RELEASE_NAME, BUILD_DATE - print REDHAT_COPYRIGHT - sys.exit(0) + if options.has_key("-h") or options.has_key("-V") or (options.has_key("-o") and options["-o"].lower() == "metadata"): + return options; ## Set default values ##### @@ -518,17 +583,10 @@ def check_input(device_opt, opt): else: options["log"] = LOG_MODE_QUIET - # Convert action to lowercase - options["-o"]=options["-o"].lower() - if 0 == device_opt.count("io_fencing"): - if 0 == options.has_key("-o"): - options["-o"] = "reboot" if 0 == ["on", "off", "reboot", "status", "list", "monitor"].count(options["-o"].lower()): fail_usage("Failed: Unrecognised action '" + options["-o"] + "'") else: - if 0 == options.has_key("-o"): - options["-o"] = "disable" if 0 == ["enable", "disable", "status", "list", "monitor"].count(options["-o"].lower()): fail_usage("Failed: Unrecognised action '" + options["-o"] + "'") @@ -603,7 +661,32 @@ def wait_power_status(tn, options, get_power_fn): return 1 return 0 +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": + metadata(device_opt, options, docs) + sys.exit(0) + + if options.has_key("-V"): + print RELEASE_VERSION, BUILD_DATE + print REDHAT_COPYRIGHT + sys.exit(0) + def fence_action(tn, options, set_power_fn, get_power_fn, get_outlet_list = None): + ## Process options that manipulate fencing device + ##### if (options["-o"] == "list") and (0 == options["device_opt"].count("port")) and (0 == options["device_opt"].count("partition")): print "N/A" return diff --git a/fence/agents/lpar/fence_lpar.py b/fence/agents/lpar/fence_lpar.py index 97241d3..cfb78b0 100755 --- a/fence/agents/lpar/fence_lpar.py +++ b/fence/agents/lpar/fence_lpar.py @@ -155,6 +155,8 @@ def main(): if 0 == options.has_key("-x"): fail_usage("Failed: You have to use ssh connection (-x) to fence device") + show_docs(options) + if 0 == options.has_key("-s"): fail_usage("Failed: You have to enter name of managed system") diff --git a/fence/agents/rsa/fence_rsa.py b/fence/agents/rsa/fence_rsa.py index 0a614a6..9237f67 100755 --- a/fence/agents/rsa/fence_rsa.py +++ b/fence/agents/rsa/fence_rsa.py @@ -56,6 +56,8 @@ def main(): # This device will not allow us to login even with LANG=C options["ssh_options"] = "-F /dev/null" + + show_docs(options) ## ## Operate the fencing device diff --git a/fence/agents/sanbox2/fence_sanbox2.py b/fence/agents/sanbox2/fence_sanbox2.py index c792fc5..d1e65cf 100644 --- a/fence/agents/sanbox2/fence_sanbox2.py +++ b/fence/agents/sanbox2/fence_sanbox2.py @@ -123,6 +123,8 @@ def main(): if 0 == options.has_key("-c"): options["-c"] = [ " #> " ] + show_docs(options) + ## ## Operate the fencing device ## diff --git a/fence/agents/virsh/fence_virsh.py b/fence/agents/virsh/fence_virsh.py index ea2e06b..9174ac6 100644 --- a/fence/agents/virsh/fence_virsh.py +++ b/fence/agents/virsh/fence_virsh.py @@ -79,6 +79,8 @@ def main(): options["ssh_options"]="-t '/bin/bash -c \"PS1=\[EXPECT\]#\ /bin/bash --noprofile --norc\"'" + show_docs(options) + ## Operate the fencing device conn = fence_login(options) fence_action(conn, options, set_power_status, get_power_status, get_outlets_status) diff --git a/fence/agents/vmware/fence_vmware.py b/fence/agents/vmware/fence_vmware.py index 1ae7398..a6ce9ef 100755 --- a/fence/agents/vmware/fence_vmware.py +++ b/fence/agents/vmware/fence_vmware.py @@ -130,6 +130,8 @@ def main(): options["-A"] = "localhost" options["-x"] = 1 + + show_docs(options) ## ## Operate the fencing device #### diff --git a/fence/agents/wti/fence_wti.py b/fence/agents/wti/fence_wti.py index 181a4b5..f0f02b3 100755 --- a/fence/agents/wti/fence_wti.py +++ b/fence/agents/wti/fence_wti.py @@ -90,6 +90,8 @@ def main(): if 0 == options.has_key("-c"): options["-c"] = [ "RSM>", "MPC>", "IPS>", "TPS>", "NBB>", "NPS>" ] + show_docs(options) + ## ## Operate the fencing device ## -- 1.6.0.6