blob: 2fd33dc1814d9d96817994520666b1c5f1de4847 [file] [log] [blame]
Michael Walsh0bbd8602016-11-22 11:31:49 -06001#!/usr/bin/env python
2
3r"""
4This module is the python counterpart to obmc_boot_test.
5"""
6
Michael Walsh0b93fbf2017-03-02 14:42:41 -06007import os
8import imp
9import time
10import glob
11import random
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050012import re
George Keishingd54bbc22018-08-03 08:24:58 -050013try:
14 import cPickle as pickle
15except ImportError:
16 import pickle
Michael Walshdc80d672017-05-09 12:58:32 -050017import socket
Michael Walsh0b93fbf2017-03-02 14:42:41 -060018
19from robot.utils import DotDict
20from robot.libraries.BuiltIn import BuiltIn
21
Michael Walsh6741f742017-02-20 16:16:38 -060022from boot_data import *
Michael Walshc9116812017-03-10 14:23:06 -060023import gen_print as gp
Michael Walsh0bbd8602016-11-22 11:31:49 -060024import gen_robot_print as grp
Michael Walsh55302292017-01-10 11:43:02 -060025import gen_robot_plug_in as grpi
Michael Walsh6741f742017-02-20 16:16:38 -060026import gen_robot_valid as grv
27import gen_misc as gm
28import gen_cmd as gc
Michael Walshb5839d02017-04-12 16:11:20 -050029import gen_robot_keyword as grk
Michael Walsh55302292017-01-10 11:43:02 -060030import state as st
Michael Walshff340002017-08-29 11:18:27 -050031import var_stack as vs
Michael Walsh0bbd8602016-11-22 11:31:49 -060032
Michael Walsh0b93fbf2017-03-02 14:42:41 -060033base_path = os.path.dirname(os.path.dirname(
34 imp.find_module("gen_robot_print")[1])) +\
Michael Walshc9116812017-03-10 14:23:06 -060035 os.sep
Michael Walsh0b93fbf2017-03-02 14:42:41 -060036sys.path.append(base_path + "extended/")
37import run_keyword as rk
Michael Walsh0bbd8602016-11-22 11:31:49 -060038
Michael Walshe1e26442017-03-06 17:50:07 -060039# Setting master_pid correctly influences the behavior of plug-ins like
40# DB_Logging
41program_pid = os.getpid()
42master_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050043pgm_name = re.sub('\\.py$', '', os.path.basename(__file__))
Michael Walshe1e26442017-03-06 17:50:07 -060044
Michael Walshb5839d02017-04-12 16:11:20 -050045# Set up boot data structures.
46boot_table = create_boot_table()
47valid_boot_types = create_valid_boot_list(boot_table)
Michael Walsh0b93fbf2017-03-02 14:42:41 -060048
Michael Walsh6741f742017-02-20 16:16:38 -060049boot_lists = read_boot_lists()
50last_ten = []
Michael Walsh6741f742017-02-20 16:16:38 -060051
Michael Walsh7dc885b2018-03-14 17:51:59 -050052state = st.return_state_constant('default_state')
Michael Walsh6741f742017-02-20 16:16:38 -060053cp_setup_called = 0
54next_boot = ""
55base_tool_dir_path = os.path.normpath(os.environ.get(
56 'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
Michael Walshb5839d02017-04-12 16:11:20 -050057
Michael Walsh6741f742017-02-20 16:16:38 -060058ffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
Michael Walsh6741f742017-02-20 16:16:38 -060059boot_success = 0
Michael Walsh6741f742017-02-20 16:16:38 -060060status_dir_path = os.environ.get('STATUS_DIR_PATH', "")
61if status_dir_path != "":
62 status_dir_path = os.path.normpath(status_dir_path) + os.sep
Michael Walsh0b93fbf2017-03-02 14:42:41 -060063default_power_on = "REST Power On"
64default_power_off = "REST Power Off"
Michael Walsh6741f742017-02-20 16:16:38 -060065boot_count = 0
Michael Walsh0bbd8602016-11-22 11:31:49 -060066
Michael Walsh85678942017-03-27 14:34:22 -050067LOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
Michael Walshe1974b92017-08-03 13:39:51 -050068ffdc_prefix = ""
Sunil M325eb542017-08-10 07:09:43 -050069boot_start_time = ""
70boot_end_time = ""
Michael Walshff340002017-08-29 11:18:27 -050071save_stack = vs.var_stack('save_stack')
72main_func_parm_list = ['boot_stack', 'stack_mode', 'quiet']
Michael Walsh85678942017-03-27 14:34:22 -050073
74
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050075def process_host(host,
76 host_var_name=""):
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050077 r"""
78 Process a host by getting the associated host name and IP address and
79 setting them in global variables.
80
81 If the caller does not pass the host_var_name, this function will try to
82 figure out the name of the variable used by the caller for the host parm.
83 Callers are advised to explicitly specify the host_var_name when calling
84 with an exec command. In such cases, the get_arg_name cannot figure out
85 the host variable name.
86
87 This function will then create similar global variable names by
88 removing "_host" and appending "_host_name" or "_ip" to the host variable
89 name.
90
91 Example:
92
93 If a call is made like this:
94 process_host(openbmc_host)
95
96 Global variables openbmc_host_name and openbmc_ip will be set.
97
98 Description of argument(s):
99 host A host name or IP. The name of the variable used should
100 have a suffix of "_host".
101 host_var_name The name of the variable being used as the host parm.
102 """
103
104 if host_var_name == "":
105 host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
106
107 host_name_var_name = re.sub("host", "host_name", host_var_name)
108 ip_var_name = re.sub("host", "ip", host_var_name)
109 cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\
110 host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\
111 host + "')"
112 exec(cmd_buf)
113
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500114
Michael Walshb5839d02017-04-12 16:11:20 -0500115def process_pgm_parms():
Michael Walshb5839d02017-04-12 16:11:20 -0500116 r"""
117 Process the program parameters by assigning them all to corresponding
118 globals. Also, set some global values that depend on program parameters.
119 """
120
121 # Program parameter processing.
122 # Assign all program parms to python variables which are global to this
123 # module.
124
125 global parm_list
126 parm_list = BuiltIn().get_variable_value("${parm_list}")
127 # The following subset of parms should be processed as integers.
128 int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only',
Michael Walshaabef1e2017-09-20 15:16:17 -0500129 'boot_fail_threshold', 'delete_errlogs', 'quiet', 'test_mode',
130 'debug']
Michael Walshb5839d02017-04-12 16:11:20 -0500131 for parm in parm_list:
132 if parm in int_list:
133 sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
134 "}\", \"0\"))"
135 else:
136 sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
137 cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
Michael Walshff340002017-08-29 11:18:27 -0500138 gp.dpissuing(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500139 exec(cmd_buf)
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500140 if re.match(r".*_host$", parm):
141 cmd_buf = "process_host(" + parm + ", '" + parm + "')"
142 exec(cmd_buf)
143 if re.match(r".*_password$", parm):
144 # Register the value of any parm whose name ends in _password.
145 # This will cause the print functions to replace passwords with
146 # asterisks in the output.
147 cmd_buf = "gp.register_passwords(" + parm + ")"
148 exec(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500149
150 global ffdc_dir_path_style
151 global boot_list
152 global boot_stack
153 global boot_results_file_path
154 global boot_results
Michael Walsh6c645742018-08-17 15:02:17 -0500155 global last_ten
Michael Walshb5839d02017-04-12 16:11:20 -0500156 global ffdc_list_file_path
Michael Walshe0cf8d72017-05-17 13:20:46 -0500157 global ffdc_report_list_path
Michael Walsh600876d2017-05-30 17:58:58 -0500158 global ffdc_summary_list_path
Michael Walshb5839d02017-04-12 16:11:20 -0500159
160 if ffdc_dir_path_style == "":
161 ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
162
163 # Convert these program parms to lists for easier processing..
164 boot_list = filter(None, boot_list.split(":"))
165 boot_stack = filter(None, boot_stack.split(":"))
166
Michael Walsh903e0b22017-09-19 17:00:33 -0500167 cleanup_boot_results_file()
168 boot_results_file_path = create_boot_results_file_path(pgm_name,
169 openbmc_nickname,
170 master_pid)
Michael Walshb5839d02017-04-12 16:11:20 -0500171
172 if os.path.isfile(boot_results_file_path):
173 # We've been called before in this run so we'll load the saved
Michael Walsh6c645742018-08-17 15:02:17 -0500174 # boot_results and last_ten objects.
175 boot_results, last_ten =\
176 pickle.load(open(boot_results_file_path, 'rb'))
Michael Walshb5839d02017-04-12 16:11:20 -0500177 else:
178 boot_results = boot_results(boot_table, boot_pass, boot_fail)
179
180 ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\
181 "/FFDC_FILE_LIST"
Michael Walshe0cf8d72017-05-17 13:20:46 -0500182 ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\
183 "/FFDC_REPORT_FILE_LIST"
Michael Walshb5839d02017-04-12 16:11:20 -0500184
Michael Walsh600876d2017-05-30 17:58:58 -0500185 ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\
186 "/FFDC_SUMMARY_FILE_LIST"
187
Michael Walshb5839d02017-04-12 16:11:20 -0500188
Michael Walsh85678942017-03-27 14:34:22 -0500189def initial_plug_in_setup():
Michael Walsh85678942017-03-27 14:34:22 -0500190 r"""
191 Initialize all plug-in environment variables which do not change for the
192 duration of the program.
193
194 """
195
196 global LOG_LEVEL
197 BuiltIn().set_log_level("NONE")
198
199 BuiltIn().set_global_variable("${master_pid}", master_pid)
200 BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
201 BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
202 BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
203 BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
204 ffdc_list_file_path)
Michael Walshe0cf8d72017-05-17 13:20:46 -0500205 BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}",
206 ffdc_report_list_path)
Michael Walsh600876d2017-05-30 17:58:58 -0500207 BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}",
208 ffdc_summary_list_path)
Michael Walsh85678942017-03-27 14:34:22 -0500209
210 BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
211 ffdc_dir_path_style)
212 BuiltIn().set_global_variable("${FFDC_CHECK}",
213 ffdc_check)
214
215 # For each program parameter, set the corresponding AUTOBOOT_ environment
216 # variable value. Also, set an AUTOBOOT_ environment variable for every
217 # element in additional_values.
218 additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
219 "status_dir_path", "base_tool_dir_path",
Michael Walsh600876d2017-05-30 17:58:58 -0500220 "ffdc_list_file_path", "ffdc_report_list_path",
221 "ffdc_summary_list_path"]
Michael Walsh85678942017-03-27 14:34:22 -0500222
223 plug_in_vars = parm_list + additional_values
224
225 for var_name in plug_in_vars:
226 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
227 var_name = var_name.upper()
228 if var_value is None:
229 var_value = ""
230 os.environ["AUTOBOOT_" + var_name] = str(var_value)
231
232 BuiltIn().set_log_level(LOG_LEVEL)
233
Michael Walsh68a61162017-04-25 11:54:06 -0500234 # Make sure the ffdc list directory exists.
235 ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
236 if not os.path.exists(ffdc_list_dir_path):
237 os.makedirs(ffdc_list_dir_path)
Michael Walsh85678942017-03-27 14:34:22 -0500238
Michael Walsh85678942017-03-27 14:34:22 -0500239
Michael Walsh0bbd8602016-11-22 11:31:49 -0600240def plug_in_setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600241 r"""
Michael Walsh85678942017-03-27 14:34:22 -0500242 Initialize all changing plug-in environment variables for use by the
243 plug-in programs.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600244 """
245
Michael Walsh85678942017-03-27 14:34:22 -0500246 global LOG_LEVEL
247 global test_really_running
248
249 BuiltIn().set_log_level("NONE")
250
Michael Walsh6741f742017-02-20 16:16:38 -0600251 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600252 if boot_pass > 1:
253 test_really_running = 1
254 else:
255 test_really_running = 0
256
Michael Walsh6741f742017-02-20 16:16:38 -0600257 BuiltIn().set_global_variable("${test_really_running}",
258 test_really_running)
259 BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
Michael Walsh6741f742017-02-20 16:16:38 -0600260 BuiltIn().set_global_variable("${boot_pass}", boot_pass)
261 BuiltIn().set_global_variable("${boot_fail}", boot_fail)
262 BuiltIn().set_global_variable("${boot_success}", boot_success)
263 BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
Sunil M325eb542017-08-10 07:09:43 -0500264 BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
265 BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
Michael Walsh4c9a6452016-12-13 16:03:11 -0600266
Michael Walsh0bbd8602016-11-22 11:31:49 -0600267 # For each program parameter, set the corresponding AUTOBOOT_ environment
268 # variable value. Also, set an AUTOBOOT_ environment variable for every
269 # element in additional_values.
270 additional_values = ["boot_type_desc", "boot_success", "boot_pass",
Sunil M325eb542017-08-10 07:09:43 -0500271 "boot_fail", "test_really_running", "ffdc_prefix",
272 "boot_start_time", "boot_end_time"]
Michael Walsh0bbd8602016-11-22 11:31:49 -0600273
Michael Walsh85678942017-03-27 14:34:22 -0500274 plug_in_vars = additional_values
Michael Walsh0bbd8602016-11-22 11:31:49 -0600275
276 for var_name in plug_in_vars:
277 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
278 var_name = var_name.upper()
279 if var_value is None:
280 var_value = ""
Michael Walsh6741f742017-02-20 16:16:38 -0600281 os.environ["AUTOBOOT_" + var_name] = str(var_value)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600282
Michael Walsh0bbd8602016-11-22 11:31:49 -0600283 if debug:
Michael Walsh6741f742017-02-20 16:16:38 -0600284 shell_rc, out_buf = \
285 gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
Michael Walsh0bbd8602016-11-22 11:31:49 -0600286
Michael Walsh85678942017-03-27 14:34:22 -0500287 BuiltIn().set_log_level(LOG_LEVEL)
288
Michael Walsh0bbd8602016-11-22 11:31:49 -0600289
Michael Walshe0cf8d72017-05-17 13:20:46 -0500290def pre_boot_plug_in_setup():
291
292 # Clear the ffdc_list_file_path file. Plug-ins may now write to it.
293 try:
294 os.remove(ffdc_list_file_path)
295 except OSError:
296 pass
297
298 # Clear the ffdc_report_list_path file. Plug-ins may now write to it.
299 try:
300 os.remove(ffdc_report_list_path)
301 except OSError:
302 pass
303
Michael Walsh600876d2017-05-30 17:58:58 -0500304 # Clear the ffdc_summary_list_path file. Plug-ins may now write to it.
305 try:
306 os.remove(ffdc_summary_list_path)
307 except OSError:
308 pass
309
Michael Walshe1974b92017-08-03 13:39:51 -0500310 global ffdc_prefix
311
312 seconds = time.time()
313 loc_time = time.localtime(seconds)
314 time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
315
316 ffdc_prefix = openbmc_nickname + "." + time_string
317
Michael Walshe0cf8d72017-05-17 13:20:46 -0500318
Michael Walsh6741f742017-02-20 16:16:38 -0600319def setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600320 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600321 Do general program setup tasks.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600322 """
323
Michael Walsh6741f742017-02-20 16:16:38 -0600324 global cp_setup_called
Michael Walsh81816742017-09-27 11:02:29 -0500325 global transitional_boot_selected
Michael Walsh0bbd8602016-11-22 11:31:49 -0600326
Michael Walshb5839d02017-04-12 16:11:20 -0500327 gp.qprintn()
328
Michael Walsh81816742017-09-27 11:02:29 -0500329 transitional_boot_selected = False
330
Michael Walsh83f4bc72017-04-20 16:49:43 -0500331 robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
332 repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
Michael Walshd061c042017-05-23 14:46:57 -0500333 # If we can't find process_plug_in_packages.py, ssh_pw or
334 # validate_plug_ins.py, then we don't have our repo bin in PATH.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500335 shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py"
336 + " ssh_pw validate_plug_ins.py", quiet=1,
Michael Walshd061c042017-05-23 14:46:57 -0500337 print_output=0, show_err=0)
Michael Walshb5839d02017-04-12 16:11:20 -0500338 if shell_rc != 0:
Michael Walsh83f4bc72017-04-20 16:49:43 -0500339 os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "")
340 # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
341 if robot_pgm_dir_path not in sys.path:
342 sys.path.append(robot_pgm_dir_path)
343 PYTHONPATH = os.environ.get("PYTHONPATH", "")
344 if PYTHONPATH == "":
345 os.environ['PYTHONPATH'] = robot_pgm_dir_path
346 else:
347 os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH
Michael Walsh6741f742017-02-20 16:16:38 -0600348
349 validate_parms()
350
351 grp.rqprint_pgm_header()
352
George Keishingefc3ff22017-12-12 11:49:25 -0600353 grk.run_key("Set BMC Power Policy ALWAYS_POWER_OFF")
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500354
Michael Walsh85678942017-03-27 14:34:22 -0500355 initial_plug_in_setup()
356
Michael Walsh6741f742017-02-20 16:16:38 -0600357 plug_in_setup()
358 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
359 call_point='setup')
360 if rc != 0:
361 error_message = "Plug-in setup failed.\n"
362 grp.rprint_error_report(error_message)
363 BuiltIn().fail(error_message)
364 # Setting cp_setup_called lets our Teardown know that it needs to call
365 # the cleanup plug-in call point.
366 cp_setup_called = 1
367
368 # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
369 BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
Michael Walsh85678942017-03-27 14:34:22 -0500370 # FFDC_LOG_PATH is used by "FFDC" keyword.
371 BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
Michael Walsh6741f742017-02-20 16:16:38 -0600372
Michael Walshdc80d672017-05-09 12:58:32 -0500373 # Also printed by FFDC.
374 global host_name
375 global host_ip
376 host = socket.gethostname()
377 host_name, host_ip = gm.get_host_name_ip(host)
378
Michael Walshb5839d02017-04-12 16:11:20 -0500379 gp.dprint_var(boot_table, 1)
380 gp.dprint_var(boot_lists)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600381
Michael Walsh0bbd8602016-11-22 11:31:49 -0600382
Michael Walsh6741f742017-02-20 16:16:38 -0600383def validate_parms():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600384 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600385 Validate all program parameters.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600386 """
387
Michael Walshb5839d02017-04-12 16:11:20 -0500388 process_pgm_parms()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600389
Michael Walshb5839d02017-04-12 16:11:20 -0500390 gp.qprintn()
391
392 global openbmc_model
Michael Walsh6741f742017-02-20 16:16:38 -0600393 grv.rvalid_value("openbmc_host")
394 grv.rvalid_value("openbmc_username")
395 grv.rvalid_value("openbmc_password")
396 if os_host != "":
397 grv.rvalid_value("os_username")
398 grv.rvalid_value("os_password")
Michael Walsh0bbd8602016-11-22 11:31:49 -0600399
Michael Walsh6741f742017-02-20 16:16:38 -0600400 if pdu_host != "":
401 grv.rvalid_value("pdu_username")
402 grv.rvalid_value("pdu_password")
Michael Walsh85678942017-03-27 14:34:22 -0500403 grv.rvalid_integer("pdu_slot_no")
Michael Walsh6741f742017-02-20 16:16:38 -0600404 if openbmc_serial_host != "":
405 grv.rvalid_integer("openbmc_serial_port")
Michael Walshb5839d02017-04-12 16:11:20 -0500406 if openbmc_model == "":
407 status, ret_values =\
408 grk.run_key_u("Get BMC System Model")
409 openbmc_model = ret_values
410 BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
Michael Walsh6741f742017-02-20 16:16:38 -0600411 grv.rvalid_value("openbmc_model")
Michael Walshb5839d02017-04-12 16:11:20 -0500412 grv.rvalid_integer("max_num_tests")
Michael Walsh6741f742017-02-20 16:16:38 -0600413 grv.rvalid_integer("boot_pass")
414 grv.rvalid_integer("boot_fail")
415
416 plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
417 BuiltIn().set_global_variable("${plug_in_packages_list}",
418 plug_in_packages_list)
419
Michael Walshb5839d02017-04-12 16:11:20 -0500420 grv.rvalid_value("stack_mode", valid_values=['normal', 'skip'])
Michael Walsha20da402017-03-31 16:27:45 -0500421 if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
Michael Walsh6741f742017-02-20 16:16:38 -0600422 error_message = "You must provide either a value for either the" +\
423 " boot_list or the boot_stack parm.\n"
424 BuiltIn().fail(gp.sprint_error(error_message))
425
426 valid_boot_list(boot_list, valid_boot_types)
427 valid_boot_list(boot_stack, valid_boot_types)
428
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500429 selected_PDU_boots = list(set(boot_list + boot_stack)
430 & set(boot_lists['PDU_reboot']))
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500431
432 if len(selected_PDU_boots) > 0 and pdu_host == "":
433 error_message = "You have selected the following boots which" +\
434 " require a PDU host but no value for pdu_host:\n"
435 error_message += gp.sprint_var(selected_PDU_boots)
436 error_message += gp.sprint_var(pdu_host, 2)
437 BuiltIn().fail(gp.sprint_error(error_message))
438
Michael Walsh6741f742017-02-20 16:16:38 -0600439 return
Michael Walsh0bbd8602016-11-22 11:31:49 -0600440
Michael Walsh0bbd8602016-11-22 11:31:49 -0600441
Michael Walsh6741f742017-02-20 16:16:38 -0600442def my_get_state():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600443 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600444 Get the system state plus a little bit of wrapping.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600445 """
446
Michael Walsh6741f742017-02-20 16:16:38 -0600447 global state
448
449 req_states = ['epoch_seconds'] + st.default_req_states
450
Michael Walshb5839d02017-04-12 16:11:20 -0500451 gp.qprint_timen("Getting system state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600452 if test_mode:
453 state['epoch_seconds'] = int(time.time())
454 else:
Michael Walshb5839d02017-04-12 16:11:20 -0500455 state = st.get_state(req_states=req_states, quiet=quiet)
456 gp.qprint_var(state)
Michael Walsh341c21e2017-01-17 16:25:20 -0600457
Michael Walsh341c21e2017-01-17 16:25:20 -0600458
Michael Walsh45ca6e42017-09-14 17:29:12 -0500459def valid_state():
Michael Walsh45ca6e42017-09-14 17:29:12 -0500460 r"""
461 Verify that our state dictionary contains no blank values. If we don't get
462 valid state data, we cannot continue to work.
463 """
464
465 if st.compare_states(state, st.invalid_state_match, 'or'):
466 error_message = "The state dictionary contains blank fields which" +\
467 " is illegal.\n" + gp.sprint_var(state)
468 BuiltIn().fail(gp.sprint_error(error_message))
469
Michael Walsh45ca6e42017-09-14 17:29:12 -0500470
Michael Walsh6741f742017-02-20 16:16:38 -0600471def select_boot():
Michael Walsh341c21e2017-01-17 16:25:20 -0600472 r"""
473 Select a boot test to be run based on our current state and return the
474 chosen boot type.
475
476 Description of arguments:
Michael Walsh6741f742017-02-20 16:16:38 -0600477 state The state of the machine.
Michael Walsh341c21e2017-01-17 16:25:20 -0600478 """
479
Michael Walsh81816742017-09-27 11:02:29 -0500480 global transitional_boot_selected
Michael Walsh30dadae2017-02-27 14:25:52 -0600481 global boot_stack
482
Michael Walshb5839d02017-04-12 16:11:20 -0500483 gp.qprint_timen("Selecting a boot test.")
Michael Walsh6741f742017-02-20 16:16:38 -0600484
Michael Walsh81816742017-09-27 11:02:29 -0500485 if transitional_boot_selected and not boot_success:
486 prior_boot = next_boot
487 boot_candidate = boot_stack.pop()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500488 gp.qprint_timen("The prior '" + next_boot + "' was chosen to"
489 + " transition to a valid state for '" + boot_candidate
490 + "' which was at the top of the boot_stack. Since"
491 + " the '" + next_boot + "' failed, the '"
492 + boot_candidate + "' has been removed from the stack"
493 + " to avoid and endless failure loop.")
Michael Walsh81816742017-09-27 11:02:29 -0500494 if len(boot_stack) == 0:
495 return ""
496
Michael Walsh6741f742017-02-20 16:16:38 -0600497 my_get_state()
Michael Walsh45ca6e42017-09-14 17:29:12 -0500498 valid_state()
Michael Walsh6741f742017-02-20 16:16:38 -0600499
Michael Walsh81816742017-09-27 11:02:29 -0500500 transitional_boot_selected = False
Michael Walsh6741f742017-02-20 16:16:38 -0600501 stack_popped = 0
502 if len(boot_stack) > 0:
503 stack_popped = 1
Michael Walshb5839d02017-04-12 16:11:20 -0500504 gp.qprint_dashes()
505 gp.qprint_var(boot_stack)
506 gp.qprint_dashes()
507 skip_boot_printed = 0
508 while len(boot_stack) > 0:
509 boot_candidate = boot_stack.pop()
510 if stack_mode == 'normal':
511 break
512 else:
513 if st.compare_states(state, boot_table[boot_candidate]['end']):
514 if not skip_boot_printed:
Michael Walshff340002017-08-29 11:18:27 -0500515 gp.qprint_var(stack_mode)
516 gp.qprintn()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500517 gp.qprint_timen("Skipping the following boot tests"
518 + " which are unnecessary since their"
519 + " required end states match the"
520 + " current machine state:")
Michael Walshb5839d02017-04-12 16:11:20 -0500521 skip_boot_printed = 1
Michael Walshff340002017-08-29 11:18:27 -0500522 gp.qprint_var(boot_candidate)
Michael Walshb5839d02017-04-12 16:11:20 -0500523 boot_candidate = ""
524 if boot_candidate == "":
525 gp.qprint_dashes()
526 gp.qprint_var(boot_stack)
527 gp.qprint_dashes()
528 return boot_candidate
Michael Walsh6741f742017-02-20 16:16:38 -0600529 if st.compare_states(state, boot_table[boot_candidate]['start']):
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500530 gp.qprint_timen("The machine state is valid for a '"
531 + boot_candidate + "' boot test.")
Michael Walshb5839d02017-04-12 16:11:20 -0500532 gp.qprint_dashes()
533 gp.qprint_var(boot_stack)
534 gp.qprint_dashes()
Michael Walsh6741f742017-02-20 16:16:38 -0600535 return boot_candidate
Michael Walsh341c21e2017-01-17 16:25:20 -0600536 else:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500537 gp.qprint_timen("The machine state does not match the required"
538 + " starting state for a '" + boot_candidate
539 + "' boot test:")
Michael Walshff340002017-08-29 11:18:27 -0500540 gp.qprint_varx("boot_table[" + boot_candidate + "][start]",
541 boot_table[boot_candidate]['start'], 1)
Michael Walsh6741f742017-02-20 16:16:38 -0600542 boot_stack.append(boot_candidate)
Michael Walsh81816742017-09-27 11:02:29 -0500543 transitional_boot_selected = True
Michael Walsh6741f742017-02-20 16:16:38 -0600544 popped_boot = boot_candidate
545
546 # Loop through your list selecting a boot_candidates
547 boot_candidates = []
548 for boot_candidate in boot_list:
549 if st.compare_states(state, boot_table[boot_candidate]['start']):
550 if stack_popped:
551 if st.compare_states(boot_table[boot_candidate]['end'],
Gunnar Mills096cd562018-03-26 10:19:12 -0500552 boot_table[popped_boot]['start']):
Michael Walsh6741f742017-02-20 16:16:38 -0600553 boot_candidates.append(boot_candidate)
554 else:
555 boot_candidates.append(boot_candidate)
556
557 if len(boot_candidates) == 0:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500558 gp.qprint_timen("The user's boot list contained no boot tests"
559 + " which are valid for the current machine state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600560 boot_candidate = default_power_on
561 if not st.compare_states(state, boot_table[default_power_on]['start']):
562 boot_candidate = default_power_off
563 boot_candidates.append(boot_candidate)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500564 gp.qprint_timen("Using default '" + boot_candidate
565 + "' boot type to transition to valid state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600566
Michael Walshb5839d02017-04-12 16:11:20 -0500567 gp.dprint_var(boot_candidates)
Michael Walsh6741f742017-02-20 16:16:38 -0600568
569 # Randomly select a boot from the candidate list.
570 boot = random.choice(boot_candidates)
Michael Walsh341c21e2017-01-17 16:25:20 -0600571
572 return boot
Michael Walsh0bbd8602016-11-22 11:31:49 -0600573
Michael Walsh55302292017-01-10 11:43:02 -0600574
Michael Walsh341c21e2017-01-17 16:25:20 -0600575def print_last_boots():
Michael Walsh341c21e2017-01-17 16:25:20 -0600576 r"""
577 Print the last ten boots done with their time stamps.
578 """
579
580 # indent 0, 90 chars wide, linefeed, char is "="
Michael Walshb5839d02017-04-12 16:11:20 -0500581 gp.qprint_dashes(0, 90)
582 gp.qprintn("Last 10 boots:\n")
Michael Walsh341c21e2017-01-17 16:25:20 -0600583
584 for boot_entry in last_ten:
585 grp.rqprint(boot_entry)
Michael Walshb5839d02017-04-12 16:11:20 -0500586 gp.qprint_dashes(0, 90)
Michael Walsh341c21e2017-01-17 16:25:20 -0600587
Michael Walsh341c21e2017-01-17 16:25:20 -0600588
Michael Walshb2e53ec2017-10-30 15:04:36 -0500589def print_defect_report(ffdc_file_list):
Michael Walsh341c21e2017-01-17 16:25:20 -0600590 r"""
591 Print a defect report.
Michael Walshb2e53ec2017-10-30 15:04:36 -0500592
593 Description of argument(s):
594 ffdc_file_list A list of files which were collected by our ffdc functions.
Michael Walsh341c21e2017-01-17 16:25:20 -0600595 """
596
Michael Walsh600876d2017-05-30 17:58:58 -0500597 # Making deliberate choice to NOT run plug_in_setup(). We don't want
598 # ffdc_prefix updated.
599 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
600 call_point='ffdc_report', stop_on_plug_in_failure=0)
601
Michael Walshe0cf8d72017-05-17 13:20:46 -0500602 # Get additional header data which may have been created by ffdc plug-ins.
603 # Also, delete the individual header files to cleanup.
604 cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\
605 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
606 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
607 shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
608 show_err=0)
609
Michael Walshb2e53ec2017-10-30 15:04:36 -0500610 # Get additional summary data which may have been created by ffdc plug-ins.
Michael Walsh600876d2017-05-30 17:58:58 -0500611 # Also, delete the individual header files to cleanup.
612 cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\
613 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
614 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
615 shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
616 show_err=0)
617
Michael Walshb2e53ec2017-10-30 15:04:36 -0500618 # ffdc_list_file_path contains a list of any ffdc files created by plug-
619 # ins, etc. Read that data into a list.
Michael Walsh341c21e2017-01-17 16:25:20 -0600620 try:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500621 plug_in_ffdc_list = \
622 open(ffdc_list_file_path, 'r').read().rstrip("\n").split("\n")
623 plug_in_ffdc_list = filter(None, plug_in_ffdc_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600624 except IOError:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500625 plug_in_ffdc_list = []
626
627 # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
628 # in. Eliminate duplicates and sort the list.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500629 ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
Michael Walshb2e53ec2017-10-30 15:04:36 -0500630
631 if status_file_path != "":
632 ffdc_file_list.insert(0, status_file_path)
633
634 # Convert the list to a printable list.
635 printable_ffdc_file_list = "\n".join(ffdc_file_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600636
Michael Walsh68a61162017-04-25 11:54:06 -0500637 # Open ffdc_file_list for writing. We will write a complete list of
638 # FFDC files to it for possible use by plug-ins like cp_stop_check.
639 ffdc_list_file = open(ffdc_list_file_path, 'w')
Michael Walshb2e53ec2017-10-30 15:04:36 -0500640 ffdc_list_file.write(printable_ffdc_file_list + "\n")
641 ffdc_list_file.close()
642
643 indent = 0
644 width = 90
645 linefeed = 1
646 char = "="
Michael Walsh68a61162017-04-25 11:54:06 -0500647
648 gp.qprintn()
Michael Walshb2e53ec2017-10-30 15:04:36 -0500649 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500650 gp.qprintn("Copy this data to the defect:\n")
651
Michael Walshe0cf8d72017-05-17 13:20:46 -0500652 if len(more_header_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500653 gp.qprintn(more_header_info)
Michael Walshdc80d672017-05-09 12:58:32 -0500654 gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
655 openbmc_host_name, openbmc_ip, openbmc_username,
656 openbmc_password, os_host, os_host_name, os_ip, os_username,
657 os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
658 pdu_password, pdu_slot_no, openbmc_serial_host,
659 openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
Michael Walsh68a61162017-04-25 11:54:06 -0500660
661 gp.qprintn()
Michael Walsh68a61162017-04-25 11:54:06 -0500662 print_last_boots()
663 gp.qprintn()
664 gp.qprint_var(state)
Michael Walshb5839d02017-04-12 16:11:20 -0500665 gp.qprintn()
666 gp.qprintn("FFDC data files:")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500667 gp.qprintn(printable_ffdc_file_list)
Michael Walshb5839d02017-04-12 16:11:20 -0500668 gp.qprintn()
Michael Walsh341c21e2017-01-17 16:25:20 -0600669
Michael Walsh600876d2017-05-30 17:58:58 -0500670 if len(ffdc_summary_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500671 gp.qprintn(ffdc_summary_info)
Michael Walsh600876d2017-05-30 17:58:58 -0500672
Michael Walshb2e53ec2017-10-30 15:04:36 -0500673 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500674
Michael Walsh6741f742017-02-20 16:16:38 -0600675
Michael Walsh6741f742017-02-20 16:16:38 -0600676def my_ffdc():
Michael Walsh6741f742017-02-20 16:16:38 -0600677 r"""
678 Collect FFDC data.
679 """
680
681 global state
682
683 plug_in_setup()
684 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500685 call_point='ffdc', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600686
687 AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500688 status, ffdc_file_list = grk.run_key_u("FFDC ffdc_prefix="
689 + AUTOBOOT_FFDC_PREFIX
690 + " ffdc_function_list="
691 + ffdc_function_list, ignore=1)
Michael Walsh83f4bc72017-04-20 16:49:43 -0500692 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500693 gp.qprint_error("Call to ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600694
695 my_get_state()
696
Michael Walshb2e53ec2017-10-30 15:04:36 -0500697 print_defect_report(ffdc_file_list)
Michael Walsh6741f742017-02-20 16:16:38 -0600698
Michael Walsh6741f742017-02-20 16:16:38 -0600699
Michael Walsh6741f742017-02-20 16:16:38 -0600700def print_test_start_message(boot_keyword):
Michael Walsh6741f742017-02-20 16:16:38 -0600701 r"""
702 Print a message indicating what boot test is about to run.
703
704 Description of arguments:
705 boot_keyword The name of the boot which is to be run
706 (e.g. "BMC Power On").
707 """
708
709 global last_ten
Sunil M325eb542017-08-10 07:09:43 -0500710 global boot_start_time
Michael Walsh6741f742017-02-20 16:16:38 -0600711
712 doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
Sunil M325eb542017-08-10 07:09:43 -0500713
714 # Set boot_start_time for use by plug-ins.
715 boot_start_time = doing_msg[1:33]
716 gp.qprint_var(boot_start_time)
717
Michael Walshb5839d02017-04-12 16:11:20 -0500718 gp.qprint(doing_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600719
720 last_ten.append(doing_msg)
721
722 if len(last_ten) > 10:
723 del last_ten[0]
724
Michael Walsh6741f742017-02-20 16:16:38 -0600725
Michael Walsh6741f742017-02-20 16:16:38 -0600726def run_boot(boot):
Michael Walsh6741f742017-02-20 16:16:38 -0600727 r"""
728 Run the specified boot.
729
730 Description of arguments:
731 boot The name of the boot test to be performed.
732 """
733
734 global state
735
736 print_test_start_message(boot)
737
738 plug_in_setup()
739 rc, shell_rc, failed_plug_in_name = \
740 grpi.rprocess_plug_in_packages(call_point="pre_boot")
741 if rc != 0:
742 error_message = "Plug-in failed with non-zero return code.\n" +\
743 gp.sprint_var(rc, 1)
744 BuiltIn().fail(gp.sprint_error(error_message))
745
746 if test_mode:
747 # In test mode, we'll pretend the boot worked by assigning its
748 # required end state to the default state value.
Michael Walsh30dadae2017-02-27 14:25:52 -0600749 state = st.strip_anchor_state(boot_table[boot]['end'])
Michael Walsh6741f742017-02-20 16:16:38 -0600750 else:
751 # Assertion: We trust that the state data was made fresh by the
752 # caller.
753
Michael Walshb5839d02017-04-12 16:11:20 -0500754 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600755
756 if boot_table[boot]['method_type'] == "keyword":
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600757 rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
Michael Walshb5839d02017-04-12 16:11:20 -0500758 boot_table[boot]['method'],
759 quiet=quiet)
Michael Walsh6741f742017-02-20 16:16:38 -0600760
761 if boot_table[boot]['bmc_reboot']:
762 st.wait_for_comm_cycle(int(state['epoch_seconds']))
Michael Walsh30dadae2017-02-27 14:25:52 -0600763 plug_in_setup()
764 rc, shell_rc, failed_plug_in_name = \
765 grpi.rprocess_plug_in_packages(call_point="post_reboot")
766 if rc != 0:
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600767 error_message = "Plug-in failed with non-zero return code.\n"
768 error_message += gp.sprint_var(rc, 1)
Michael Walsh30dadae2017-02-27 14:25:52 -0600769 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -0600770 else:
771 match_state = st.anchor_state(state)
772 del match_state['epoch_seconds']
773 # Wait for the state to change in any way.
774 st.wait_state(match_state, wait_time=state_change_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500775 interval="10 seconds", invert=1)
Michael Walsh6741f742017-02-20 16:16:38 -0600776
Michael Walshb5839d02017-04-12 16:11:20 -0500777 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600778 if boot_table[boot]['end']['chassis'] == "Off":
779 boot_timeout = power_off_timeout
780 else:
781 boot_timeout = power_on_timeout
782 st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500783 interval="10 seconds")
Michael Walsh6741f742017-02-20 16:16:38 -0600784
785 plug_in_setup()
786 rc, shell_rc, failed_plug_in_name = \
787 grpi.rprocess_plug_in_packages(call_point="post_boot")
788 if rc != 0:
789 error_message = "Plug-in failed with non-zero return code.\n" +\
790 gp.sprint_var(rc, 1)
791 BuiltIn().fail(gp.sprint_error(error_message))
792
Michael Walsh6741f742017-02-20 16:16:38 -0600793
Michael Walsh6741f742017-02-20 16:16:38 -0600794def test_loop_body():
Michael Walsh6741f742017-02-20 16:16:38 -0600795 r"""
796 The main loop body for the loop in main_py.
797
798 Description of arguments:
799 boot_count The iteration number (starts at 1).
800 """
801
802 global boot_count
803 global state
804 global next_boot
805 global boot_success
Sunil M325eb542017-08-10 07:09:43 -0500806 global boot_end_time
Michael Walsh6741f742017-02-20 16:16:38 -0600807
Michael Walshb5839d02017-04-12 16:11:20 -0500808 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600809
810 next_boot = select_boot()
Michael Walshb5839d02017-04-12 16:11:20 -0500811 if next_boot == "":
812 return True
Michael Walsh6741f742017-02-20 16:16:38 -0600813
Michael Walshb5839d02017-04-12 16:11:20 -0500814 boot_count += 1
815 gp.qprint_timen("Starting boot " + str(boot_count) + ".")
Michael Walsh6741f742017-02-20 16:16:38 -0600816
Michael Walshe0cf8d72017-05-17 13:20:46 -0500817 pre_boot_plug_in_setup()
Michael Walsh6741f742017-02-20 16:16:38 -0600818
819 cmd_buf = ["run_boot", next_boot]
820 boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
821 if boot_status == "FAIL":
Michael Walshb5839d02017-04-12 16:11:20 -0500822 gp.qprint(msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600823
Michael Walshb5839d02017-04-12 16:11:20 -0500824 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600825 if boot_status == "PASS":
826 boot_success = 1
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500827 completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot
828 + "\" succeeded.")
Michael Walsh6741f742017-02-20 16:16:38 -0600829 else:
830 boot_success = 0
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500831 completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot
832 + "\" failed.")
Sunil M325eb542017-08-10 07:09:43 -0500833
834 # Set boot_end_time for use by plug-ins.
835 boot_end_time = completion_msg[1:33]
836 gp.qprint_var(boot_end_time)
837
838 gp.qprint(completion_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600839
840 boot_results.update(next_boot, boot_status)
841
842 plug_in_setup()
843 # NOTE: A post_test_case call point failure is NOT counted as a boot
844 # failure.
845 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500846 call_point='post_test_case', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600847
848 plug_in_setup()
849 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
850 call_point='ffdc_check', shell_rc=0x00000200,
851 stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
852 if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200:
Michael Walsh83f4bc72017-04-20 16:49:43 -0500853 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
854 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500855 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600856
Michael Walshaabef1e2017-09-20 15:16:17 -0500857 if delete_errlogs:
858 # We need to purge error logs between boots or they build up.
859 grk.run_key("Delete Error logs", ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -0500860
Michael Walsh952f9b02017-03-09 13:11:14 -0600861 boot_results.print_report()
Michael Walshb5839d02017-04-12 16:11:20 -0500862 gp.qprint_timen("Finished boot " + str(boot_count) + ".")
Michael Walsh952f9b02017-03-09 13:11:14 -0600863
Michael Walsh6741f742017-02-20 16:16:38 -0600864 plug_in_setup()
865 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500866 call_point='stop_check', shell_rc=0x00000200, stop_on_non_zero_rc=1)
867 if shell_rc == 0x00000200:
868 message = "Stopping as requested by user.\n"
869 gp.print_time(message)
870 BuiltIn().fail(message)
Michael Walsh6741f742017-02-20 16:16:38 -0600871
Michael Walshd139f282017-04-04 18:00:23 -0500872 # This should help prevent ConnectionErrors.
Michael Walsh0960b382017-06-22 16:23:37 -0500873 grk.run_key_u("Close All Connections")
Michael Walshd139f282017-04-04 18:00:23 -0500874
Michael Walsh6741f742017-02-20 16:16:38 -0600875 return True
876
Michael Walsh6741f742017-02-20 16:16:38 -0600877
Michael Walsh83f4bc72017-04-20 16:49:43 -0500878def obmc_boot_test_teardown():
Michael Walsh6741f742017-02-20 16:16:38 -0600879 r"""
Michael Walshc9116812017-03-10 14:23:06 -0600880 Clean up after the Main keyword.
Michael Walsh6741f742017-02-20 16:16:38 -0600881 """
882
883 if cp_setup_called:
884 plug_in_setup()
885 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500886 call_point='cleanup', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600887
Michael Walsh600876d2017-05-30 17:58:58 -0500888 if 'boot_results_file_path' in globals():
Michael Walsh6c645742018-08-17 15:02:17 -0500889 # Save boot_results and last_ten objects to a file in case they are
890 # needed again.
Michael Walsh600876d2017-05-30 17:58:58 -0500891 gp.qprint_timen("Saving boot_results to the following path.")
892 gp.qprint_var(boot_results_file_path)
Michael Walsh6c645742018-08-17 15:02:17 -0500893 pickle.dump((boot_results, last_ten),
894 open(boot_results_file_path, 'wb'),
Michael Walsh600876d2017-05-30 17:58:58 -0500895 pickle.HIGHEST_PROTOCOL)
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600896
Michael Walshff340002017-08-29 11:18:27 -0500897 global save_stack
898 # Restore any global values saved on the save_stack.
899 for parm_name in main_func_parm_list:
900 # Get the parm_value if it was saved on the stack.
901 try:
902 parm_value = save_stack.pop(parm_name)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500903 except BaseException:
Michael Walshff340002017-08-29 11:18:27 -0500904 # If it was not saved, no further action is required.
905 continue
906
907 # Restore the saved value.
908 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
909 "}\", parm_value)"
910 gp.dpissuing(cmd_buf)
911 exec(cmd_buf)
912
913 gp.dprintn(save_stack.sprint_obj())
914
Michael Walsh6741f742017-02-20 16:16:38 -0600915
Michael Walshc9116812017-03-10 14:23:06 -0600916def test_teardown():
Michael Walshc9116812017-03-10 14:23:06 -0600917 r"""
918 Clean up after this test case.
919 """
920
921 gp.qprintn()
922 cmd_buf = ["Print Error",
923 "A keyword timeout occurred ending this program.\n"]
924 BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
925
Michael Walshb5839d02017-04-12 16:11:20 -0500926 grp.rqprint_pgm_footer()
927
Michael Walshc9116812017-03-10 14:23:06 -0600928
Michael Walshff340002017-08-29 11:18:27 -0500929def obmc_boot_test_py(loc_boot_stack=None,
930 loc_stack_mode=None,
931 loc_quiet=None):
Michael Walsh6741f742017-02-20 16:16:38 -0600932 r"""
933 Do main program processing.
934 """
935
Michael Walshff340002017-08-29 11:18:27 -0500936 global save_stack
937
938 # Process function parms.
939 for parm_name in main_func_parm_list:
940 # Get parm's value.
941 cmd_buf = "parm_value = loc_" + parm_name
942 exec(cmd_buf)
943 gp.dpvar(parm_name)
944 gp.dpvar(parm_value)
945
946 if parm_value is None:
947 # Parm was not specified by the calling function so set it to its
948 # corresponding global value.
949 cmd_buf = "loc_" + parm_name + " = BuiltIn().get_variable_value" +\
950 "(\"${" + parm_name + "}\")"
951 gp.dpissuing(cmd_buf)
952 exec(cmd_buf)
953 else:
954 # Save the global value on a stack.
955 cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\
956 parm_name + "}\"), \"" + parm_name + "\")"
957 gp.dpissuing(cmd_buf)
958 exec(cmd_buf)
959
960 # Set the global value to the passed value.
961 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
962 "}\", loc_" + parm_name + ")"
963 gp.dpissuing(cmd_buf)
964 exec(cmd_buf)
965
966 gp.dprintn(save_stack.sprint_obj())
Michael Walshb5839d02017-04-12 16:11:20 -0500967
Michael Walsh6741f742017-02-20 16:16:38 -0600968 setup()
969
Michael Walshcd9fbfd2017-09-19 12:00:08 -0500970 init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
971
Michael Walsha20da402017-03-31 16:27:45 -0500972 if ffdc_only:
973 gp.qprint_timen("Caller requested ffdc_only.")
Michael Walshe0cf8d72017-05-17 13:20:46 -0500974 pre_boot_plug_in_setup()
Michael Walsh83f4bc72017-04-20 16:49:43 -0500975 grk.run_key_u("my_ffdc")
Michael Walsh764d2f82017-04-27 16:01:08 -0500976 return
Michael Walsha20da402017-03-31 16:27:45 -0500977
Michael Walsh6741f742017-02-20 16:16:38 -0600978 # Process caller's boot_stack.
979 while (len(boot_stack) > 0):
980 test_loop_body()
981
Michael Walshb5839d02017-04-12 16:11:20 -0500982 gp.qprint_timen("Finished processing stack.")
Michael Walsh30dadae2017-02-27 14:25:52 -0600983
Michael Walsh6741f742017-02-20 16:16:38 -0600984 # Process caller's boot_list.
985 if len(boot_list) > 0:
986 for ix in range(1, max_num_tests + 1):
987 test_loop_body()
988
Michael Walshb5839d02017-04-12 16:11:20 -0500989 gp.qprint_timen("Completed all requested boot tests.")
990
991 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walshcd9fbfd2017-09-19 12:00:08 -0500992 new_fail = boot_fail - init_boot_fail
993 if new_fail > boot_fail_threshold:
Michael Walshb5839d02017-04-12 16:11:20 -0500994 error_message = "Boot failures exceed the boot failure" +\
995 " threshold:\n" +\
Michael Walshcd9fbfd2017-09-19 12:00:08 -0500996 gp.sprint_var(new_fail) +\
Michael Walshb5839d02017-04-12 16:11:20 -0500997 gp.sprint_var(boot_fail_threshold)
998 BuiltIn().fail(gp.sprint_error(error_message))