1    	#!@PYTHON@ -tt
2    	
3    	#####
4    	##
5    	## The Following Agent Has Been Tested On:
6    	##
7    	##  Version
8    	## +---------------------------------------------+
9    	##  Tested on HMC
10   	##
11   	#####
12   	
13   	import sys, re
14   	import atexit
15   	import logging
16   	sys.path.append("@FENCEAGENTSLIBDIR@")
17   	from fencing import *
18   	from fencing import fail, fail_usage, EC_STATUS_HMC
19   	
20   	##
21   	## Transformation to standard ON/OFF status if possible
22   	def _normalize_status(status):
23   		if status in ["Running", "Open Firmware", "Shutting Down", "Starting"]:
24   			status = "on"
25   		else:
26   			status = "off"
27   	
28   		return status
29   	
30   	def get_power_status(conn, options):
31   		if options["--hmc-version"] == "3":
32   			command = "lssyscfg -r lpar -m " + options["--managed"] + " -n " + options["--plug"] + " -F name,state\n"
33   		elif options["--hmc-version"] in ["4", "IVM"]:
34   			command = "lssyscfg -r lpar -m "+ options["--managed"] + \
35   				" --filter 'lpar_names=" + options["--plug"] + "'\n"
36   		else:
37   			# Bad HMC Version cannot be reached
38   			fail(EC_STATUS_HMC)
39   	
40   		conn.send(command)
41   		# First line (command) may cause parsing issues if long
42   		conn.readline()
43   		conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
44   	
45   		try:
46   			if options["--hmc-version"] == "3":
47   				status = re.compile(r"^" + options["--plug"] + r",(.*?),.*$",
48   						    re.IGNORECASE | re.MULTILINE).search(conn.before).group(1)
49   			elif options["--hmc-version"] in ["4", "IVM"]:
50   				status = re.compile(r",state=(.*?),", re.IGNORECASE).search(conn.before).group(1)
51   		except AttributeError as e:
52   			logging.debug("Command on HMC failed: {}\n{}".format(command, str(e)))
53   			fail(EC_STATUS_HMC)
54   	
55   		return _normalize_status(status)
56   	
57   	def is_comanaged(conn, options):
58   		conn.send("lscomgmt -m " + options["--managed"] + "\n" )
59   		conn.readline()
60   		conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
61   	
62   		try:
63   			cm = re.compile(r",curr_master_mtms=(.*?),", re.IGNORECASE).search(conn.before).group(1)
64   		except AttributeError as e:
65   			cm = False
66   	
67   		return cm
68   	
69   	def set_power_status(conn, options):
70   		if options["--hmc-version"] == "3":
71   			conn.send("chsysstate -o " + options["--action"] + " -r lpar -m " + options["--managed"]
72   				+ " -n " + options["--plug"] + "\n")
73   	
74   			# First line (command) may cause parsing issues if long
75   			conn.readline()
76   			conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
77   		elif options["--hmc-version"] in ["4", "IVM"]:
78   			if options["--action"] == "on":
79   				if is_comanaged(conn, options):
80   					profile = ""
81   				else:
82   					profile = " -f `lssyscfg -r lpar -F curr_profile " + \
83   					    " -m " + options["--managed"] + \
84   					    " --filter \"lpar_names=" + options["--plug"] + "\"`"
85   				conn.send("chsysstate -o on -r lpar" +
86   					" -m " + options["--managed"] +
87   					" -n " + options["--plug"] +
88   					profile +
89   					"\n")
90   			else:
91   				conn.send("chsysstate -o shutdown -r lpar --immed" +
92   					" -m " + options["--managed"] + " -n " + options["--plug"] + "\n")
93   	
94   			# First line (command) may cause parsing issues if long
95   			conn.readline()
96   			conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
97   	
98   	def get_lpar_list(conn, options):
99   		outlets = {}
(1) Event cond_true: Condition "options["--hmc-version"] == "3"", taking true branch.
100  		if options["--hmc-version"] == "3":
101  			conn.send("query_partition_names -m " + options["--managed"] + "\n")
102  	
103  			## We have to remove first line (command)
104  			conn.readline()
105  			conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
106  	
107  			## We have to remove next 2 lines (header) and last line (part of new prompt)
108  			####
109  			res = re.search(r"^(.+?\n){2}(.*)\n.*$", conn.before, re.S)
110  	
(2) Event cond_true: Condition "res == None", taking true branch.
(3) Event null_check: Comparing "res" to a null-like value implies that "res" might be null-like.
Also see events: [property_access]
111  			if res == None:
112  				fail_usage("Unable to parse output of list command")
113  	
(4) Event property_access: Accessing a property of null-like value "res".
Also see events: [null_check]
114  			lines = res.group(2).split("\n")
115  			for outlet_line in lines:
116  				outlets[outlet_line.rstrip()] = ("", "")
117  		elif options["--hmc-version"] in ["4", "IVM"]:
118  			sep = ":" if options["--hmc-version"] == "4" else ","
119  	
120  			conn.send("lssyscfg -r lpar -m " + options["--managed"] +
121  				" -F name" + sep + "state\n")
122  	
123  			## We have to remove first line (command)
124  			conn.readline()
125  			conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
126  	
127  			## We have to remove last line (part of new prompt)
128  			####
129  			res = re.search(r"^(.*)\n.*$", conn.before, re.S)
130  	
131  			if res == None:
132  				fail_usage("Unable to parse output of list command")
133  	
134  			lines = res.group(1).split("\n")
135  			for outlet_line in lines:
136  				try:
137  					(port, status) = outlet_line.rstrip().split(sep)
138  				except ValueError:
139  					fail_usage('Output does not match expected HMC version, try different one');
140  				outlets[port] = ("", _normalize_status(status))
141  	
142  		return outlets
143  	
144  	def define_new_opts():
145  		all_opt["managed"] = {
146  			"getopt" : "s:",
147  			"longopt" : "managed",
148  			"help" : "-s, --managed=[id]             Name of the managed system",
149  			"required" : "1",
150  			"shortdesc" : "Managed system name",
151  			"order" : 1}
152  		all_opt["hmc_version"] = {
153  			"getopt" : "H:",
154  			"longopt" : "hmc-version",
155  			"help" : "-H, --hmc-version=[version]    Force HMC version to use: (3|4|ivm) (default: 4)",
156  			"required" : "0",
157  			"shortdesc" : "Force HMC version to use",
158  			"default" : "4",
159  			"choices" : ["3", "4", "ivm"],
160  			"order" : 1}
161  	
162  	def main():
163  		device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", \
164  		                "port", "managed", "hmc_version"]
165  	
166  		atexit.register(atexit_handler)
167  	
168  		define_new_opts()
169  	
170  		all_opt["login_timeout"]["default"] = "15"
171  		all_opt["secure"]["default"] = "1"
172  		all_opt["cmd_prompt"]["default"] = [r":~>", r"]\$", r"\$ "]
173  	
174  		options = check_input(device_opt, process_input(device_opt), other_conditions = True)
175  	
176  		docs = {}
177  		docs["shortdesc"] = "Fence agent for IBM LPAR"
178  		docs["longdesc"] = "fence_lpar is a Power Fencing agent for IBM LPAR."
179  		docs["vendorurl"] = "http://www.ibm.com"
180  		show_docs(options, docs)
181  	
182  		if "--managed" not in options:
183  			fail_usage("Failed: You have to enter name of managed system")
184  	
185  		if options["--action"] == "validate-all":
186  			sys.exit(0)
187  	
188  		##
189  		## Operate the fencing device
190  		####
191  		conn = fence_login(options)
192  		result = fence_action(conn, options, set_power_status, get_power_status, get_lpar_list)
193  		fence_logout(conn, "quit\r\n")
194  		sys.exit(result)
195  	
196  	if __name__ == "__main__":
197  		main()
198