Blob Blame History Raw
commit 1db6440eb38789bcb59451cb8adb39f2084f9443
Author: Marek 'marx' Grac <mgrac@redhat.com>
Date:   Mon Oct 21 12:44:39 2013 +0200

    testing: Check if fence agent uses only valid keys in options["--???"]
    
    Valid keys are defined in fencing library or fence agent itself. This check
    will be run at every build, so we should be protected against case when
    developer unintentionally use new key (e.g. typo). These type of bugs are
    usually not detected by static analyzers.

diff --git a/fence/agents/lib/check_used_options.py b/fence/agents/lib/check_used_options.py
new file mode 100755
index 0000000..2d75756
--- /dev/null
+++ b/fence/agents/lib/check_used_options.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+## Check if fence agent uses only options["--??"] which are defined in fencing library or 
+## fence agent itself
+##
+## Usage: ./check_used_options.py fence-agent (e.g. lpar/fence_lpar.py)
+##
+
+import sys, re
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import all_opt
+
+def main():
+	agent = sys.argv[1]
+
+	available = { }
+
+	## all_opt from fencing library are imported
+	for k in all_opt.keys():
+		if all_opt[k].has_key("longopt"):
+			available["--" + all_opt[k]["longopt"]] = True
+
+	## add UUID which is derived automatically from --plug if possible
+	available["--uuid"] = True
+
+	## all_opt defined in fence agent are found
+	agent_file = open(agent)
+	opt_re = re.compile("\s*all_opt\[\"([^\"]*)\"\] = {")
+	opt_longopt_re = re.compile("\s*\"longopt\" : \"([^\"]*)\"")
+
+	in_opt = False
+	for line in agent_file:
+		if opt_re.search(line) != None:
+			in_opt = True
+		if in_opt and opt_longopt_re.search(line) != None:
+			available["--" + opt_longopt_re.search(line).group(1)] = True
+			in_opt = False
+
+	## check if all options are defined
+	agent_file = open(agent)
+	option_use_re = re.compile("options\[\"(--[^\"]*)\"\]")
+	option_has_re = re.compile("options.has_key\(\"(--[^\"]*)\"\)")
+
+	counter = 0
+	without_errors = True
+	for line in agent_file:
+		counter += 1
+
+		for x in option_use_re.findall(line):
+			if not available.has_key(x):
+				print "ERROR on line %d in %s: option %s is not defined" % (counter, agent, option_use_re.search(line).group(1))
+				without_errors = False
+
+		for x in option_has_re.findall(line):
+			if not available.has_key(x):
+				print "ERROR on line %d in %s: option %s is not defined" % (counter, agent, option_has_re.search(line).group(1))
+				without_errors = False
+
+	if without_errors:
+		sys.exit(0)
+	else:
+		sys.exit(1)
+
+if __name__ == "__main__":
+	main()
diff --git a/make/fencebuild.mk b/make/fencebuild.mk
index e86d03c..d775e92 100644
--- a/make/fencebuild.mk
+++ b/make/fencebuild.mk
@@ -1,4 +1,8 @@
 $(TARGET): $(SRC)
+	if [ 0 -eq `echo "$(SRC)" | grep fence_ &> /dev/null; echo $$?` ]; then \
+		PYTHONPATH=$(abs_srcdir)/../lib:$(abs_builddir)/../lib $(top_srcdir)/fence/agents/lib/check_used_options.py $(SRC); \
+	else true ; fi
+
 	bash $(top_srcdir)/scripts/fenceparse \
 		$(top_srcdir)/make/copyright.cf REDHAT_COPYRIGHT \
 		$(VERSION) \