blob: 24416df7829c7a68f7de48a2345a4a6741f18229 [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 Walsh89de14a2018-10-01 16:51:37 -050075def dump_ffdc_rc():
76 r"""
77 Return the constant dump ffdc test return code value.
78
79 When a plug-in call point program returns this value, it indicates that
80 this program should collect FFDC.
81 """
82
83 return 0x00000200
84
85
86def stop_test_rc():
87 r"""
88 Return the constant stop test return code value.
89
90 When a plug-in call point program returns this value, it indicates that
91 this program should stop running.
92 """
93
94 return 0x00000200
95
96
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050097def process_host(host,
98 host_var_name=""):
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050099 r"""
100 Process a host by getting the associated host name and IP address and
101 setting them in global variables.
102
103 If the caller does not pass the host_var_name, this function will try to
104 figure out the name of the variable used by the caller for the host parm.
105 Callers are advised to explicitly specify the host_var_name when calling
106 with an exec command. In such cases, the get_arg_name cannot figure out
107 the host variable name.
108
109 This function will then create similar global variable names by
110 removing "_host" and appending "_host_name" or "_ip" to the host variable
111 name.
112
113 Example:
114
115 If a call is made like this:
116 process_host(openbmc_host)
117
118 Global variables openbmc_host_name and openbmc_ip will be set.
119
120 Description of argument(s):
121 host A host name or IP. The name of the variable used should
122 have a suffix of "_host".
123 host_var_name The name of the variable being used as the host parm.
124 """
125
126 if host_var_name == "":
127 host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
128
129 host_name_var_name = re.sub("host", "host_name", host_var_name)
130 ip_var_name = re.sub("host", "ip", host_var_name)
131 cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\
132 host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\
133 host + "')"
134 exec(cmd_buf)
135
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500136
Michael Walshb5839d02017-04-12 16:11:20 -0500137def process_pgm_parms():
Michael Walshb5839d02017-04-12 16:11:20 -0500138 r"""
139 Process the program parameters by assigning them all to corresponding
140 globals. Also, set some global values that depend on program parameters.
141 """
142
143 # Program parameter processing.
144 # Assign all program parms to python variables which are global to this
145 # module.
146
147 global parm_list
148 parm_list = BuiltIn().get_variable_value("${parm_list}")
149 # The following subset of parms should be processed as integers.
150 int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only',
Michael Walsh89de14a2018-10-01 16:51:37 -0500151 'boot_fail_threshold', 'delete_errlogs',
152 'call_post_stack_plug', 'quiet', 'test_mode', 'debug']
Michael Walshb5839d02017-04-12 16:11:20 -0500153 for parm in parm_list:
154 if parm in int_list:
155 sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
156 "}\", \"0\"))"
157 else:
158 sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
159 cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
Michael Walshff340002017-08-29 11:18:27 -0500160 gp.dpissuing(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500161 exec(cmd_buf)
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500162 if re.match(r".*_host$", parm):
163 cmd_buf = "process_host(" + parm + ", '" + parm + "')"
164 exec(cmd_buf)
165 if re.match(r".*_password$", parm):
166 # Register the value of any parm whose name ends in _password.
167 # This will cause the print functions to replace passwords with
168 # asterisks in the output.
169 cmd_buf = "gp.register_passwords(" + parm + ")"
170 exec(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500171
172 global ffdc_dir_path_style
173 global boot_list
174 global boot_stack
175 global boot_results_file_path
176 global boot_results
Michael Walsh6c645742018-08-17 15:02:17 -0500177 global last_ten
Michael Walshb5839d02017-04-12 16:11:20 -0500178 global ffdc_list_file_path
Michael Walshe0cf8d72017-05-17 13:20:46 -0500179 global ffdc_report_list_path
Michael Walsh600876d2017-05-30 17:58:58 -0500180 global ffdc_summary_list_path
Michael Walshb5839d02017-04-12 16:11:20 -0500181
182 if ffdc_dir_path_style == "":
183 ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
184
185 # Convert these program parms to lists for easier processing..
186 boot_list = filter(None, boot_list.split(":"))
187 boot_stack = filter(None, boot_stack.split(":"))
188
Michael Walsh903e0b22017-09-19 17:00:33 -0500189 cleanup_boot_results_file()
190 boot_results_file_path = create_boot_results_file_path(pgm_name,
191 openbmc_nickname,
192 master_pid)
Michael Walshb5839d02017-04-12 16:11:20 -0500193
194 if os.path.isfile(boot_results_file_path):
195 # We've been called before in this run so we'll load the saved
Michael Walsh6c645742018-08-17 15:02:17 -0500196 # boot_results and last_ten objects.
197 boot_results, last_ten =\
198 pickle.load(open(boot_results_file_path, 'rb'))
Michael Walshb5839d02017-04-12 16:11:20 -0500199 else:
200 boot_results = boot_results(boot_table, boot_pass, boot_fail)
201
202 ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\
203 "/FFDC_FILE_LIST"
Michael Walshe0cf8d72017-05-17 13:20:46 -0500204 ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\
205 "/FFDC_REPORT_FILE_LIST"
Michael Walshb5839d02017-04-12 16:11:20 -0500206
Michael Walsh600876d2017-05-30 17:58:58 -0500207 ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\
208 "/FFDC_SUMMARY_FILE_LIST"
209
Michael Walshb5839d02017-04-12 16:11:20 -0500210
Michael Walsh85678942017-03-27 14:34:22 -0500211def initial_plug_in_setup():
Michael Walsh85678942017-03-27 14:34:22 -0500212 r"""
213 Initialize all plug-in environment variables which do not change for the
214 duration of the program.
215
216 """
217
218 global LOG_LEVEL
219 BuiltIn().set_log_level("NONE")
220
221 BuiltIn().set_global_variable("${master_pid}", master_pid)
222 BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
223 BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
224 BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
225 BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
226 ffdc_list_file_path)
Michael Walshe0cf8d72017-05-17 13:20:46 -0500227 BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}",
228 ffdc_report_list_path)
Michael Walsh600876d2017-05-30 17:58:58 -0500229 BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}",
230 ffdc_summary_list_path)
Michael Walsh85678942017-03-27 14:34:22 -0500231
232 BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
233 ffdc_dir_path_style)
234 BuiltIn().set_global_variable("${FFDC_CHECK}",
235 ffdc_check)
236
237 # For each program parameter, set the corresponding AUTOBOOT_ environment
238 # variable value. Also, set an AUTOBOOT_ environment variable for every
239 # element in additional_values.
240 additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
241 "status_dir_path", "base_tool_dir_path",
Michael Walsh600876d2017-05-30 17:58:58 -0500242 "ffdc_list_file_path", "ffdc_report_list_path",
243 "ffdc_summary_list_path"]
Michael Walsh85678942017-03-27 14:34:22 -0500244
245 plug_in_vars = parm_list + additional_values
246
247 for var_name in plug_in_vars:
248 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
249 var_name = var_name.upper()
250 if var_value is None:
251 var_value = ""
252 os.environ["AUTOBOOT_" + var_name] = str(var_value)
253
254 BuiltIn().set_log_level(LOG_LEVEL)
255
Michael Walsh68a61162017-04-25 11:54:06 -0500256 # Make sure the ffdc list directory exists.
257 ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
258 if not os.path.exists(ffdc_list_dir_path):
259 os.makedirs(ffdc_list_dir_path)
Michael Walsh85678942017-03-27 14:34:22 -0500260
Michael Walsh85678942017-03-27 14:34:22 -0500261
Michael Walsh0bbd8602016-11-22 11:31:49 -0600262def plug_in_setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600263 r"""
Michael Walsh85678942017-03-27 14:34:22 -0500264 Initialize all changing plug-in environment variables for use by the
265 plug-in programs.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600266 """
267
Michael Walsh85678942017-03-27 14:34:22 -0500268 global LOG_LEVEL
269 global test_really_running
270
271 BuiltIn().set_log_level("NONE")
272
Michael Walsh6741f742017-02-20 16:16:38 -0600273 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600274 if boot_pass > 1:
275 test_really_running = 1
276 else:
277 test_really_running = 0
278
Michael Walsh6741f742017-02-20 16:16:38 -0600279 BuiltIn().set_global_variable("${test_really_running}",
280 test_really_running)
281 BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
Michael Walsh6741f742017-02-20 16:16:38 -0600282 BuiltIn().set_global_variable("${boot_pass}", boot_pass)
283 BuiltIn().set_global_variable("${boot_fail}", boot_fail)
284 BuiltIn().set_global_variable("${boot_success}", boot_success)
285 BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
Sunil M325eb542017-08-10 07:09:43 -0500286 BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
287 BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
Michael Walsh4c9a6452016-12-13 16:03:11 -0600288
Michael Walsh0bbd8602016-11-22 11:31:49 -0600289 # For each program parameter, set the corresponding AUTOBOOT_ environment
290 # variable value. Also, set an AUTOBOOT_ environment variable for every
291 # element in additional_values.
292 additional_values = ["boot_type_desc", "boot_success", "boot_pass",
Sunil M325eb542017-08-10 07:09:43 -0500293 "boot_fail", "test_really_running", "ffdc_prefix",
294 "boot_start_time", "boot_end_time"]
Michael Walsh0bbd8602016-11-22 11:31:49 -0600295
Michael Walsh85678942017-03-27 14:34:22 -0500296 plug_in_vars = additional_values
Michael Walsh0bbd8602016-11-22 11:31:49 -0600297
298 for var_name in plug_in_vars:
299 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
300 var_name = var_name.upper()
301 if var_value is None:
302 var_value = ""
Michael Walsh6741f742017-02-20 16:16:38 -0600303 os.environ["AUTOBOOT_" + var_name] = str(var_value)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600304
Michael Walsh0bbd8602016-11-22 11:31:49 -0600305 if debug:
Michael Walsh6741f742017-02-20 16:16:38 -0600306 shell_rc, out_buf = \
307 gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
Michael Walsh0bbd8602016-11-22 11:31:49 -0600308
Michael Walsh85678942017-03-27 14:34:22 -0500309 BuiltIn().set_log_level(LOG_LEVEL)
310
Michael Walsh0bbd8602016-11-22 11:31:49 -0600311
Michael Walshe0cf8d72017-05-17 13:20:46 -0500312def pre_boot_plug_in_setup():
313
314 # Clear the ffdc_list_file_path file. Plug-ins may now write to it.
315 try:
316 os.remove(ffdc_list_file_path)
317 except OSError:
318 pass
319
320 # Clear the ffdc_report_list_path file. Plug-ins may now write to it.
321 try:
322 os.remove(ffdc_report_list_path)
323 except OSError:
324 pass
325
Michael Walsh600876d2017-05-30 17:58:58 -0500326 # Clear the ffdc_summary_list_path file. Plug-ins may now write to it.
327 try:
328 os.remove(ffdc_summary_list_path)
329 except OSError:
330 pass
331
Michael Walshe1974b92017-08-03 13:39:51 -0500332 global ffdc_prefix
333
334 seconds = time.time()
335 loc_time = time.localtime(seconds)
336 time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
337
338 ffdc_prefix = openbmc_nickname + "." + time_string
339
Michael Walshe0cf8d72017-05-17 13:20:46 -0500340
Michael Walsh6741f742017-02-20 16:16:38 -0600341def setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600342 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600343 Do general program setup tasks.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600344 """
345
Michael Walsh6741f742017-02-20 16:16:38 -0600346 global cp_setup_called
Michael Walsh81816742017-09-27 11:02:29 -0500347 global transitional_boot_selected
Michael Walsh0bbd8602016-11-22 11:31:49 -0600348
Michael Walshb5839d02017-04-12 16:11:20 -0500349 gp.qprintn()
350
Michael Walsh81816742017-09-27 11:02:29 -0500351 transitional_boot_selected = False
352
Michael Walsh83f4bc72017-04-20 16:49:43 -0500353 robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
354 repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
Michael Walshd061c042017-05-23 14:46:57 -0500355 # If we can't find process_plug_in_packages.py, ssh_pw or
356 # validate_plug_ins.py, then we don't have our repo bin in PATH.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500357 shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py"
358 + " ssh_pw validate_plug_ins.py", quiet=1,
Michael Walshd061c042017-05-23 14:46:57 -0500359 print_output=0, show_err=0)
Michael Walshb5839d02017-04-12 16:11:20 -0500360 if shell_rc != 0:
Michael Walsh83f4bc72017-04-20 16:49:43 -0500361 os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "")
362 # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
363 if robot_pgm_dir_path not in sys.path:
364 sys.path.append(robot_pgm_dir_path)
365 PYTHONPATH = os.environ.get("PYTHONPATH", "")
366 if PYTHONPATH == "":
367 os.environ['PYTHONPATH'] = robot_pgm_dir_path
368 else:
369 os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH
Michael Walsh6741f742017-02-20 16:16:38 -0600370
371 validate_parms()
372
373 grp.rqprint_pgm_header()
374
George Keishingefc3ff22017-12-12 11:49:25 -0600375 grk.run_key("Set BMC Power Policy ALWAYS_POWER_OFF")
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500376
Michael Walsh85678942017-03-27 14:34:22 -0500377 initial_plug_in_setup()
378
Michael Walsh6741f742017-02-20 16:16:38 -0600379 plug_in_setup()
380 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
381 call_point='setup')
382 if rc != 0:
383 error_message = "Plug-in setup failed.\n"
384 grp.rprint_error_report(error_message)
385 BuiltIn().fail(error_message)
386 # Setting cp_setup_called lets our Teardown know that it needs to call
387 # the cleanup plug-in call point.
388 cp_setup_called = 1
389
390 # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
391 BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
Michael Walsh85678942017-03-27 14:34:22 -0500392 # FFDC_LOG_PATH is used by "FFDC" keyword.
393 BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
Michael Walsh6741f742017-02-20 16:16:38 -0600394
Michael Walshdc80d672017-05-09 12:58:32 -0500395 # Also printed by FFDC.
396 global host_name
397 global host_ip
398 host = socket.gethostname()
399 host_name, host_ip = gm.get_host_name_ip(host)
400
Michael Walshb5839d02017-04-12 16:11:20 -0500401 gp.dprint_var(boot_table, 1)
402 gp.dprint_var(boot_lists)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600403
Michael Walsh0bbd8602016-11-22 11:31:49 -0600404
Michael Walsh6741f742017-02-20 16:16:38 -0600405def validate_parms():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600406 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600407 Validate all program parameters.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600408 """
409
Michael Walshb5839d02017-04-12 16:11:20 -0500410 process_pgm_parms()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600411
Michael Walshb5839d02017-04-12 16:11:20 -0500412 gp.qprintn()
413
414 global openbmc_model
Michael Walsh6741f742017-02-20 16:16:38 -0600415 grv.rvalid_value("openbmc_host")
416 grv.rvalid_value("openbmc_username")
417 grv.rvalid_value("openbmc_password")
418 if os_host != "":
419 grv.rvalid_value("os_username")
420 grv.rvalid_value("os_password")
Michael Walsh0bbd8602016-11-22 11:31:49 -0600421
Michael Walsh6741f742017-02-20 16:16:38 -0600422 if pdu_host != "":
423 grv.rvalid_value("pdu_username")
424 grv.rvalid_value("pdu_password")
Michael Walsh85678942017-03-27 14:34:22 -0500425 grv.rvalid_integer("pdu_slot_no")
Michael Walsh6741f742017-02-20 16:16:38 -0600426 if openbmc_serial_host != "":
427 grv.rvalid_integer("openbmc_serial_port")
Michael Walshb5839d02017-04-12 16:11:20 -0500428 if openbmc_model == "":
429 status, ret_values =\
430 grk.run_key_u("Get BMC System Model")
431 openbmc_model = ret_values
432 BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
Michael Walsh6741f742017-02-20 16:16:38 -0600433 grv.rvalid_value("openbmc_model")
Michael Walshb5839d02017-04-12 16:11:20 -0500434 grv.rvalid_integer("max_num_tests")
Michael Walsh6741f742017-02-20 16:16:38 -0600435 grv.rvalid_integer("boot_pass")
436 grv.rvalid_integer("boot_fail")
437
438 plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
439 BuiltIn().set_global_variable("${plug_in_packages_list}",
440 plug_in_packages_list)
441
Michael Walshb5839d02017-04-12 16:11:20 -0500442 grv.rvalid_value("stack_mode", valid_values=['normal', 'skip'])
Michael Walsha20da402017-03-31 16:27:45 -0500443 if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
Michael Walsh6741f742017-02-20 16:16:38 -0600444 error_message = "You must provide either a value for either the" +\
445 " boot_list or the boot_stack parm.\n"
446 BuiltIn().fail(gp.sprint_error(error_message))
447
448 valid_boot_list(boot_list, valid_boot_types)
449 valid_boot_list(boot_stack, valid_boot_types)
450
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500451 selected_PDU_boots = list(set(boot_list + boot_stack)
452 & set(boot_lists['PDU_reboot']))
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500453
454 if len(selected_PDU_boots) > 0 and pdu_host == "":
455 error_message = "You have selected the following boots which" +\
456 " require a PDU host but no value for pdu_host:\n"
457 error_message += gp.sprint_var(selected_PDU_boots)
458 error_message += gp.sprint_var(pdu_host, 2)
459 BuiltIn().fail(gp.sprint_error(error_message))
460
Michael Walsh6741f742017-02-20 16:16:38 -0600461 return
Michael Walsh0bbd8602016-11-22 11:31:49 -0600462
Michael Walsh0bbd8602016-11-22 11:31:49 -0600463
Michael Walsh6741f742017-02-20 16:16:38 -0600464def my_get_state():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600465 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600466 Get the system state plus a little bit of wrapping.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600467 """
468
Michael Walsh6741f742017-02-20 16:16:38 -0600469 global state
470
471 req_states = ['epoch_seconds'] + st.default_req_states
472
Michael Walshb5839d02017-04-12 16:11:20 -0500473 gp.qprint_timen("Getting system state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600474 if test_mode:
475 state['epoch_seconds'] = int(time.time())
476 else:
Michael Walshb5839d02017-04-12 16:11:20 -0500477 state = st.get_state(req_states=req_states, quiet=quiet)
478 gp.qprint_var(state)
Michael Walsh341c21e2017-01-17 16:25:20 -0600479
Michael Walsh341c21e2017-01-17 16:25:20 -0600480
Michael Walsh45ca6e42017-09-14 17:29:12 -0500481def valid_state():
Michael Walsh45ca6e42017-09-14 17:29:12 -0500482 r"""
483 Verify that our state dictionary contains no blank values. If we don't get
484 valid state data, we cannot continue to work.
485 """
486
487 if st.compare_states(state, st.invalid_state_match, 'or'):
488 error_message = "The state dictionary contains blank fields which" +\
489 " is illegal.\n" + gp.sprint_var(state)
490 BuiltIn().fail(gp.sprint_error(error_message))
491
Michael Walsh45ca6e42017-09-14 17:29:12 -0500492
Michael Walsh6741f742017-02-20 16:16:38 -0600493def select_boot():
Michael Walsh341c21e2017-01-17 16:25:20 -0600494 r"""
495 Select a boot test to be run based on our current state and return the
496 chosen boot type.
497
498 Description of arguments:
Michael Walsh6741f742017-02-20 16:16:38 -0600499 state The state of the machine.
Michael Walsh341c21e2017-01-17 16:25:20 -0600500 """
501
Michael Walsh81816742017-09-27 11:02:29 -0500502 global transitional_boot_selected
Michael Walsh30dadae2017-02-27 14:25:52 -0600503 global boot_stack
504
Michael Walshb5839d02017-04-12 16:11:20 -0500505 gp.qprint_timen("Selecting a boot test.")
Michael Walsh6741f742017-02-20 16:16:38 -0600506
Michael Walsh81816742017-09-27 11:02:29 -0500507 if transitional_boot_selected and not boot_success:
508 prior_boot = next_boot
509 boot_candidate = boot_stack.pop()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500510 gp.qprint_timen("The prior '" + next_boot + "' was chosen to"
511 + " transition to a valid state for '" + boot_candidate
512 + "' which was at the top of the boot_stack. Since"
513 + " the '" + next_boot + "' failed, the '"
514 + boot_candidate + "' has been removed from the stack"
515 + " to avoid and endless failure loop.")
Michael Walsh81816742017-09-27 11:02:29 -0500516 if len(boot_stack) == 0:
517 return ""
518
Michael Walsh6741f742017-02-20 16:16:38 -0600519 my_get_state()
Michael Walsh45ca6e42017-09-14 17:29:12 -0500520 valid_state()
Michael Walsh6741f742017-02-20 16:16:38 -0600521
Michael Walsh81816742017-09-27 11:02:29 -0500522 transitional_boot_selected = False
Michael Walsh6741f742017-02-20 16:16:38 -0600523 stack_popped = 0
524 if len(boot_stack) > 0:
525 stack_popped = 1
Michael Walshb5839d02017-04-12 16:11:20 -0500526 gp.qprint_dashes()
527 gp.qprint_var(boot_stack)
528 gp.qprint_dashes()
529 skip_boot_printed = 0
530 while len(boot_stack) > 0:
531 boot_candidate = boot_stack.pop()
532 if stack_mode == 'normal':
533 break
534 else:
535 if st.compare_states(state, boot_table[boot_candidate]['end']):
536 if not skip_boot_printed:
Michael Walshff340002017-08-29 11:18:27 -0500537 gp.qprint_var(stack_mode)
538 gp.qprintn()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500539 gp.qprint_timen("Skipping the following boot tests"
540 + " which are unnecessary since their"
541 + " required end states match the"
542 + " current machine state:")
Michael Walshb5839d02017-04-12 16:11:20 -0500543 skip_boot_printed = 1
Michael Walshff340002017-08-29 11:18:27 -0500544 gp.qprint_var(boot_candidate)
Michael Walshb5839d02017-04-12 16:11:20 -0500545 boot_candidate = ""
546 if boot_candidate == "":
547 gp.qprint_dashes()
548 gp.qprint_var(boot_stack)
549 gp.qprint_dashes()
550 return boot_candidate
Michael Walsh6741f742017-02-20 16:16:38 -0600551 if st.compare_states(state, boot_table[boot_candidate]['start']):
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500552 gp.qprint_timen("The machine state is valid for a '"
553 + boot_candidate + "' boot test.")
Michael Walshb5839d02017-04-12 16:11:20 -0500554 gp.qprint_dashes()
555 gp.qprint_var(boot_stack)
556 gp.qprint_dashes()
Michael Walsh6741f742017-02-20 16:16:38 -0600557 return boot_candidate
Michael Walsh341c21e2017-01-17 16:25:20 -0600558 else:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500559 gp.qprint_timen("The machine state does not match the required"
560 + " starting state for a '" + boot_candidate
561 + "' boot test:")
Michael Walshff340002017-08-29 11:18:27 -0500562 gp.qprint_varx("boot_table[" + boot_candidate + "][start]",
563 boot_table[boot_candidate]['start'], 1)
Michael Walsh6741f742017-02-20 16:16:38 -0600564 boot_stack.append(boot_candidate)
Michael Walsh81816742017-09-27 11:02:29 -0500565 transitional_boot_selected = True
Michael Walsh6741f742017-02-20 16:16:38 -0600566 popped_boot = boot_candidate
567
568 # Loop through your list selecting a boot_candidates
569 boot_candidates = []
570 for boot_candidate in boot_list:
571 if st.compare_states(state, boot_table[boot_candidate]['start']):
572 if stack_popped:
573 if st.compare_states(boot_table[boot_candidate]['end'],
Gunnar Mills096cd562018-03-26 10:19:12 -0500574 boot_table[popped_boot]['start']):
Michael Walsh6741f742017-02-20 16:16:38 -0600575 boot_candidates.append(boot_candidate)
576 else:
577 boot_candidates.append(boot_candidate)
578
579 if len(boot_candidates) == 0:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500580 gp.qprint_timen("The user's boot list contained no boot tests"
581 + " which are valid for the current machine state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600582 boot_candidate = default_power_on
583 if not st.compare_states(state, boot_table[default_power_on]['start']):
584 boot_candidate = default_power_off
585 boot_candidates.append(boot_candidate)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500586 gp.qprint_timen("Using default '" + boot_candidate
587 + "' boot type to transition to valid state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600588
Michael Walshb5839d02017-04-12 16:11:20 -0500589 gp.dprint_var(boot_candidates)
Michael Walsh6741f742017-02-20 16:16:38 -0600590
591 # Randomly select a boot from the candidate list.
592 boot = random.choice(boot_candidates)
Michael Walsh341c21e2017-01-17 16:25:20 -0600593
594 return boot
Michael Walsh0bbd8602016-11-22 11:31:49 -0600595
Michael Walsh55302292017-01-10 11:43:02 -0600596
Michael Walsh341c21e2017-01-17 16:25:20 -0600597def print_last_boots():
Michael Walsh341c21e2017-01-17 16:25:20 -0600598 r"""
599 Print the last ten boots done with their time stamps.
600 """
601
602 # indent 0, 90 chars wide, linefeed, char is "="
Michael Walshb5839d02017-04-12 16:11:20 -0500603 gp.qprint_dashes(0, 90)
604 gp.qprintn("Last 10 boots:\n")
Michael Walsh341c21e2017-01-17 16:25:20 -0600605
606 for boot_entry in last_ten:
607 grp.rqprint(boot_entry)
Michael Walshb5839d02017-04-12 16:11:20 -0500608 gp.qprint_dashes(0, 90)
Michael Walsh341c21e2017-01-17 16:25:20 -0600609
Michael Walsh341c21e2017-01-17 16:25:20 -0600610
Michael Walshb2e53ec2017-10-30 15:04:36 -0500611def print_defect_report(ffdc_file_list):
Michael Walsh341c21e2017-01-17 16:25:20 -0600612 r"""
613 Print a defect report.
Michael Walshb2e53ec2017-10-30 15:04:36 -0500614
615 Description of argument(s):
616 ffdc_file_list A list of files which were collected by our ffdc functions.
Michael Walsh341c21e2017-01-17 16:25:20 -0600617 """
618
Michael Walsh600876d2017-05-30 17:58:58 -0500619 # Making deliberate choice to NOT run plug_in_setup(). We don't want
620 # ffdc_prefix updated.
621 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
622 call_point='ffdc_report', stop_on_plug_in_failure=0)
623
Michael Walshe0cf8d72017-05-17 13:20:46 -0500624 # Get additional header data which may have been created by ffdc plug-ins.
625 # Also, delete the individual header files to cleanup.
626 cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\
627 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
628 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
629 shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
630 show_err=0)
631
Michael Walshb2e53ec2017-10-30 15:04:36 -0500632 # Get additional summary data which may have been created by ffdc plug-ins.
Michael Walsh600876d2017-05-30 17:58:58 -0500633 # Also, delete the individual header files to cleanup.
634 cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\
635 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
636 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
637 shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
638 show_err=0)
639
Michael Walshb2e53ec2017-10-30 15:04:36 -0500640 # ffdc_list_file_path contains a list of any ffdc files created by plug-
641 # ins, etc. Read that data into a list.
Michael Walsh341c21e2017-01-17 16:25:20 -0600642 try:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500643 plug_in_ffdc_list = \
644 open(ffdc_list_file_path, 'r').read().rstrip("\n").split("\n")
645 plug_in_ffdc_list = filter(None, plug_in_ffdc_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600646 except IOError:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500647 plug_in_ffdc_list = []
648
649 # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
650 # in. Eliminate duplicates and sort the list.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500651 ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
Michael Walshb2e53ec2017-10-30 15:04:36 -0500652
653 if status_file_path != "":
654 ffdc_file_list.insert(0, status_file_path)
655
656 # Convert the list to a printable list.
657 printable_ffdc_file_list = "\n".join(ffdc_file_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600658
Michael Walsh68a61162017-04-25 11:54:06 -0500659 # Open ffdc_file_list for writing. We will write a complete list of
660 # FFDC files to it for possible use by plug-ins like cp_stop_check.
661 ffdc_list_file = open(ffdc_list_file_path, 'w')
Michael Walshb2e53ec2017-10-30 15:04:36 -0500662 ffdc_list_file.write(printable_ffdc_file_list + "\n")
663 ffdc_list_file.close()
664
665 indent = 0
666 width = 90
667 linefeed = 1
668 char = "="
Michael Walsh68a61162017-04-25 11:54:06 -0500669
670 gp.qprintn()
Michael Walshb2e53ec2017-10-30 15:04:36 -0500671 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500672 gp.qprintn("Copy this data to the defect:\n")
673
Michael Walshe0cf8d72017-05-17 13:20:46 -0500674 if len(more_header_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500675 gp.qprintn(more_header_info)
Michael Walshdc80d672017-05-09 12:58:32 -0500676 gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
677 openbmc_host_name, openbmc_ip, openbmc_username,
678 openbmc_password, os_host, os_host_name, os_ip, os_username,
679 os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
680 pdu_password, pdu_slot_no, openbmc_serial_host,
681 openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
Michael Walsh68a61162017-04-25 11:54:06 -0500682
683 gp.qprintn()
Michael Walsh68a61162017-04-25 11:54:06 -0500684 print_last_boots()
685 gp.qprintn()
686 gp.qprint_var(state)
Michael Walshb5839d02017-04-12 16:11:20 -0500687 gp.qprintn()
688 gp.qprintn("FFDC data files:")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500689 gp.qprintn(printable_ffdc_file_list)
Michael Walshb5839d02017-04-12 16:11:20 -0500690 gp.qprintn()
Michael Walsh341c21e2017-01-17 16:25:20 -0600691
Michael Walsh600876d2017-05-30 17:58:58 -0500692 if len(ffdc_summary_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500693 gp.qprintn(ffdc_summary_info)
Michael Walsh600876d2017-05-30 17:58:58 -0500694
Michael Walshb2e53ec2017-10-30 15:04:36 -0500695 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500696
Michael Walsh6741f742017-02-20 16:16:38 -0600697
Michael Walsh6741f742017-02-20 16:16:38 -0600698def my_ffdc():
Michael Walsh6741f742017-02-20 16:16:38 -0600699 r"""
700 Collect FFDC data.
701 """
702
703 global state
704
705 plug_in_setup()
706 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500707 call_point='ffdc', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600708
709 AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500710 status, ffdc_file_list = grk.run_key_u("FFDC ffdc_prefix="
711 + AUTOBOOT_FFDC_PREFIX
712 + " ffdc_function_list="
713 + ffdc_function_list, ignore=1)
Michael Walsh83f4bc72017-04-20 16:49:43 -0500714 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500715 gp.qprint_error("Call to ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600716
717 my_get_state()
718
Michael Walshb2e53ec2017-10-30 15:04:36 -0500719 print_defect_report(ffdc_file_list)
Michael Walsh6741f742017-02-20 16:16:38 -0600720
Michael Walsh6741f742017-02-20 16:16:38 -0600721
Michael Walsh6741f742017-02-20 16:16:38 -0600722def print_test_start_message(boot_keyword):
Michael Walsh6741f742017-02-20 16:16:38 -0600723 r"""
724 Print a message indicating what boot test is about to run.
725
726 Description of arguments:
727 boot_keyword The name of the boot which is to be run
728 (e.g. "BMC Power On").
729 """
730
731 global last_ten
Sunil M325eb542017-08-10 07:09:43 -0500732 global boot_start_time
Michael Walsh6741f742017-02-20 16:16:38 -0600733
734 doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
Sunil M325eb542017-08-10 07:09:43 -0500735
736 # Set boot_start_time for use by plug-ins.
737 boot_start_time = doing_msg[1:33]
738 gp.qprint_var(boot_start_time)
739
Michael Walshb5839d02017-04-12 16:11:20 -0500740 gp.qprint(doing_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600741
742 last_ten.append(doing_msg)
743
744 if len(last_ten) > 10:
745 del last_ten[0]
746
Michael Walsh6741f742017-02-20 16:16:38 -0600747
Michael Walsh6741f742017-02-20 16:16:38 -0600748def run_boot(boot):
Michael Walsh6741f742017-02-20 16:16:38 -0600749 r"""
750 Run the specified boot.
751
752 Description of arguments:
753 boot The name of the boot test to be performed.
754 """
755
756 global state
757
758 print_test_start_message(boot)
759
760 plug_in_setup()
761 rc, shell_rc, failed_plug_in_name = \
762 grpi.rprocess_plug_in_packages(call_point="pre_boot")
763 if rc != 0:
764 error_message = "Plug-in failed with non-zero return code.\n" +\
765 gp.sprint_var(rc, 1)
766 BuiltIn().fail(gp.sprint_error(error_message))
767
768 if test_mode:
769 # In test mode, we'll pretend the boot worked by assigning its
770 # required end state to the default state value.
Michael Walsh30dadae2017-02-27 14:25:52 -0600771 state = st.strip_anchor_state(boot_table[boot]['end'])
Michael Walsh6741f742017-02-20 16:16:38 -0600772 else:
773 # Assertion: We trust that the state data was made fresh by the
774 # caller.
775
Michael Walshb5839d02017-04-12 16:11:20 -0500776 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600777
778 if boot_table[boot]['method_type'] == "keyword":
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600779 rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
Michael Walshb5839d02017-04-12 16:11:20 -0500780 boot_table[boot]['method'],
781 quiet=quiet)
Michael Walsh6741f742017-02-20 16:16:38 -0600782
783 if boot_table[boot]['bmc_reboot']:
784 st.wait_for_comm_cycle(int(state['epoch_seconds']))
Michael Walsh30dadae2017-02-27 14:25:52 -0600785 plug_in_setup()
786 rc, shell_rc, failed_plug_in_name = \
787 grpi.rprocess_plug_in_packages(call_point="post_reboot")
788 if rc != 0:
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600789 error_message = "Plug-in failed with non-zero return code.\n"
790 error_message += gp.sprint_var(rc, 1)
Michael Walsh30dadae2017-02-27 14:25:52 -0600791 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -0600792 else:
793 match_state = st.anchor_state(state)
794 del match_state['epoch_seconds']
795 # Wait for the state to change in any way.
796 st.wait_state(match_state, wait_time=state_change_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500797 interval="10 seconds", invert=1)
Michael Walsh6741f742017-02-20 16:16:38 -0600798
Michael Walshb5839d02017-04-12 16:11:20 -0500799 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600800 if boot_table[boot]['end']['chassis'] == "Off":
801 boot_timeout = power_off_timeout
802 else:
803 boot_timeout = power_on_timeout
804 st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500805 interval="10 seconds")
Michael Walsh6741f742017-02-20 16:16:38 -0600806
807 plug_in_setup()
808 rc, shell_rc, failed_plug_in_name = \
809 grpi.rprocess_plug_in_packages(call_point="post_boot")
810 if rc != 0:
811 error_message = "Plug-in failed with non-zero return code.\n" +\
812 gp.sprint_var(rc, 1)
813 BuiltIn().fail(gp.sprint_error(error_message))
814
Michael Walsh6741f742017-02-20 16:16:38 -0600815
Michael Walsh6741f742017-02-20 16:16:38 -0600816def test_loop_body():
Michael Walsh6741f742017-02-20 16:16:38 -0600817 r"""
818 The main loop body for the loop in main_py.
819
820 Description of arguments:
821 boot_count The iteration number (starts at 1).
822 """
823
824 global boot_count
825 global state
826 global next_boot
827 global boot_success
Sunil M325eb542017-08-10 07:09:43 -0500828 global boot_end_time
Michael Walsh6741f742017-02-20 16:16:38 -0600829
Michael Walshb5839d02017-04-12 16:11:20 -0500830 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600831
832 next_boot = select_boot()
Michael Walshb5839d02017-04-12 16:11:20 -0500833 if next_boot == "":
834 return True
Michael Walsh6741f742017-02-20 16:16:38 -0600835
Michael Walshb5839d02017-04-12 16:11:20 -0500836 boot_count += 1
837 gp.qprint_timen("Starting boot " + str(boot_count) + ".")
Michael Walsh6741f742017-02-20 16:16:38 -0600838
Michael Walshe0cf8d72017-05-17 13:20:46 -0500839 pre_boot_plug_in_setup()
Michael Walsh6741f742017-02-20 16:16:38 -0600840
841 cmd_buf = ["run_boot", next_boot]
842 boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
843 if boot_status == "FAIL":
Michael Walshb5839d02017-04-12 16:11:20 -0500844 gp.qprint(msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600845
Michael Walshb5839d02017-04-12 16:11:20 -0500846 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600847 if boot_status == "PASS":
848 boot_success = 1
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500849 completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot
850 + "\" succeeded.")
Michael Walsh6741f742017-02-20 16:16:38 -0600851 else:
852 boot_success = 0
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500853 completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot
854 + "\" failed.")
Sunil M325eb542017-08-10 07:09:43 -0500855
856 # Set boot_end_time for use by plug-ins.
857 boot_end_time = completion_msg[1:33]
858 gp.qprint_var(boot_end_time)
859
860 gp.qprint(completion_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600861
862 boot_results.update(next_boot, boot_status)
863
864 plug_in_setup()
865 # NOTE: A post_test_case call point failure is NOT counted as a boot
866 # failure.
867 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500868 call_point='post_test_case', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600869
870 plug_in_setup()
871 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh89de14a2018-10-01 16:51:37 -0500872 call_point='ffdc_check', shell_rc=dump_ffdc_rc(),
Michael Walsh6741f742017-02-20 16:16:38 -0600873 stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
Michael Walsh89de14a2018-10-01 16:51:37 -0500874 if boot_status != "PASS" or ffdc_check == "All" or\
875 shell_rc == dump_ffdc_rc():
Michael Walsh83f4bc72017-04-20 16:49:43 -0500876 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
877 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500878 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600879
Michael Walshaabef1e2017-09-20 15:16:17 -0500880 if delete_errlogs:
881 # We need to purge error logs between boots or they build up.
882 grk.run_key("Delete Error logs", ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -0500883
Michael Walsh952f9b02017-03-09 13:11:14 -0600884 boot_results.print_report()
Michael Walshb5839d02017-04-12 16:11:20 -0500885 gp.qprint_timen("Finished boot " + str(boot_count) + ".")
Michael Walsh952f9b02017-03-09 13:11:14 -0600886
Michael Walsh6741f742017-02-20 16:16:38 -0600887 plug_in_setup()
888 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh89de14a2018-10-01 16:51:37 -0500889 call_point='stop_check', shell_rc=stop_test_rc(),
890 stop_on_non_zero_rc=1)
891 if shell_rc == stop_test_rc():
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500892 message = "Stopping as requested by user.\n"
893 gp.print_time(message)
894 BuiltIn().fail(message)
Michael Walsh6741f742017-02-20 16:16:38 -0600895
Michael Walshd139f282017-04-04 18:00:23 -0500896 # This should help prevent ConnectionErrors.
Michael Walsh0960b382017-06-22 16:23:37 -0500897 grk.run_key_u("Close All Connections")
Michael Walshd139f282017-04-04 18:00:23 -0500898
Michael Walsh6741f742017-02-20 16:16:38 -0600899 return True
900
Michael Walsh6741f742017-02-20 16:16:38 -0600901
Michael Walsh83f4bc72017-04-20 16:49:43 -0500902def obmc_boot_test_teardown():
Michael Walsh6741f742017-02-20 16:16:38 -0600903 r"""
Michael Walshc9116812017-03-10 14:23:06 -0600904 Clean up after the Main keyword.
Michael Walsh6741f742017-02-20 16:16:38 -0600905 """
906
907 if cp_setup_called:
908 plug_in_setup()
909 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500910 call_point='cleanup', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600911
Michael Walsh600876d2017-05-30 17:58:58 -0500912 if 'boot_results_file_path' in globals():
Michael Walsh6c645742018-08-17 15:02:17 -0500913 # Save boot_results and last_ten objects to a file in case they are
914 # needed again.
Michael Walsh600876d2017-05-30 17:58:58 -0500915 gp.qprint_timen("Saving boot_results to the following path.")
916 gp.qprint_var(boot_results_file_path)
Michael Walsh6c645742018-08-17 15:02:17 -0500917 pickle.dump((boot_results, last_ten),
918 open(boot_results_file_path, 'wb'),
Michael Walsh600876d2017-05-30 17:58:58 -0500919 pickle.HIGHEST_PROTOCOL)
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600920
Michael Walshff340002017-08-29 11:18:27 -0500921 global save_stack
922 # Restore any global values saved on the save_stack.
923 for parm_name in main_func_parm_list:
924 # Get the parm_value if it was saved on the stack.
925 try:
926 parm_value = save_stack.pop(parm_name)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500927 except BaseException:
Michael Walshff340002017-08-29 11:18:27 -0500928 # If it was not saved, no further action is required.
929 continue
930
931 # Restore the saved value.
932 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
933 "}\", parm_value)"
934 gp.dpissuing(cmd_buf)
935 exec(cmd_buf)
936
937 gp.dprintn(save_stack.sprint_obj())
938
Michael Walsh6741f742017-02-20 16:16:38 -0600939
Michael Walshc9116812017-03-10 14:23:06 -0600940def test_teardown():
Michael Walshc9116812017-03-10 14:23:06 -0600941 r"""
942 Clean up after this test case.
943 """
944
945 gp.qprintn()
946 cmd_buf = ["Print Error",
947 "A keyword timeout occurred ending this program.\n"]
948 BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
949
Michael Walshb5839d02017-04-12 16:11:20 -0500950 grp.rqprint_pgm_footer()
951
Michael Walshc9116812017-03-10 14:23:06 -0600952
Michael Walsh89de14a2018-10-01 16:51:37 -0500953def post_stack():
954 r"""
955 Process post_stack plug-in programs.
956 """
957
958 if not call_post_stack_plug:
959 # The caller does not wish to have post_stack plug-in processing done.
960 return
961
962 global boot_success
963
964 # NOTE: A post_stack call-point failure is NOT counted as a boot failure.
965 pre_boot_plug_in_setup()
966 # For the purposes of the following plug-ins, mark the "boot" as a success.
967 boot_success = 1
968 plug_in_setup()
969 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
970 call_point='post_stack', stop_on_plug_in_failure=0)
971
972 plug_in_setup()
973 if rc == 0:
974 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
975 call_point='ffdc_check', shell_rc=dump_ffdc_rc(),
976 stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
977 if rc != 0 or shell_rc == dump_ffdc_rc():
978 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
979 if status != 'PASS':
980 gp.qprint_error("Call to my_ffdc failed.\n")
981
982 plug_in_setup()
983 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
984 call_point='stop_check', shell_rc=stop_test_rc(),
985 stop_on_non_zero_rc=1)
986 if shell_rc == stop_test_rc():
987 message = "Stopping as requested by user.\n"
988 gp.print_time(message)
989 BuiltIn().fail(message)
990
991
Michael Walshff340002017-08-29 11:18:27 -0500992def obmc_boot_test_py(loc_boot_stack=None,
993 loc_stack_mode=None,
994 loc_quiet=None):
Michael Walsh6741f742017-02-20 16:16:38 -0600995 r"""
996 Do main program processing.
997 """
998
Michael Walshff340002017-08-29 11:18:27 -0500999 global save_stack
1000
1001 # Process function parms.
1002 for parm_name in main_func_parm_list:
1003 # Get parm's value.
1004 cmd_buf = "parm_value = loc_" + parm_name
1005 exec(cmd_buf)
1006 gp.dpvar(parm_name)
1007 gp.dpvar(parm_value)
1008
1009 if parm_value is None:
1010 # Parm was not specified by the calling function so set it to its
1011 # corresponding global value.
1012 cmd_buf = "loc_" + parm_name + " = BuiltIn().get_variable_value" +\
1013 "(\"${" + parm_name + "}\")"
1014 gp.dpissuing(cmd_buf)
1015 exec(cmd_buf)
1016 else:
1017 # Save the global value on a stack.
1018 cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\
1019 parm_name + "}\"), \"" + parm_name + "\")"
1020 gp.dpissuing(cmd_buf)
1021 exec(cmd_buf)
1022
1023 # Set the global value to the passed value.
1024 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
1025 "}\", loc_" + parm_name + ")"
1026 gp.dpissuing(cmd_buf)
1027 exec(cmd_buf)
1028
1029 gp.dprintn(save_stack.sprint_obj())
Michael Walshb5839d02017-04-12 16:11:20 -05001030
Michael Walsh6741f742017-02-20 16:16:38 -06001031 setup()
1032
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001033 init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
1034
Michael Walsha20da402017-03-31 16:27:45 -05001035 if ffdc_only:
1036 gp.qprint_timen("Caller requested ffdc_only.")
Michael Walshe0cf8d72017-05-17 13:20:46 -05001037 pre_boot_plug_in_setup()
Michael Walsh83f4bc72017-04-20 16:49:43 -05001038 grk.run_key_u("my_ffdc")
Michael Walsh764d2f82017-04-27 16:01:08 -05001039 return
Michael Walsha20da402017-03-31 16:27:45 -05001040
Michael Walsh6741f742017-02-20 16:16:38 -06001041 # Process caller's boot_stack.
1042 while (len(boot_stack) > 0):
1043 test_loop_body()
1044
Michael Walshb5839d02017-04-12 16:11:20 -05001045 gp.qprint_timen("Finished processing stack.")
Michael Walsh30dadae2017-02-27 14:25:52 -06001046
Michael Walsh89de14a2018-10-01 16:51:37 -05001047 post_stack()
1048
Michael Walsh6741f742017-02-20 16:16:38 -06001049 # Process caller's boot_list.
1050 if len(boot_list) > 0:
1051 for ix in range(1, max_num_tests + 1):
1052 test_loop_body()
1053
Michael Walshb5839d02017-04-12 16:11:20 -05001054 gp.qprint_timen("Completed all requested boot tests.")
1055
1056 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001057 new_fail = boot_fail - init_boot_fail
1058 if new_fail > boot_fail_threshold:
Michael Walshb5839d02017-04-12 16:11:20 -05001059 error_message = "Boot failures exceed the boot failure" +\
1060 " threshold:\n" +\
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001061 gp.sprint_var(new_fail) +\
Michael Walshb5839d02017-04-12 16:11:20 -05001062 gp.sprint_var(boot_fail_threshold)
1063 BuiltIn().fail(gp.sprint_error(error_message))