blob: 555027730b34c1ef0d88a09cb00a5c45a7085e73 [file] [log] [blame]
George Keishinge7e91712021-09-03 11:28:44 -05001#!/usr/bin/env python3
Michael Walsh0bbd8602016-11-22 11:31:49 -06002
3r"""
4This module is the python counterpart to obmc_boot_test.
5"""
6
George Keishinge635ddc2022-12-08 07:38:02 -06007import glob
Brian Ma139f1da2024-10-18 13:34:14 +08008import importlib.util
Patrick Williams20f38712022-12-08 06:18:26 -06009import os
Michael Walsh0b93fbf2017-03-02 14:42:41 -060010import random
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050011import re
Michael Walshf566fb12019-02-01 14:35:09 -060012import signal
Patrick Williams20f38712022-12-08 06:18:26 -060013import time
14
George Keishingd54bbc22018-08-03 08:24:58 -050015try:
16 import cPickle as pickle
17except ImportError:
18 import pickle
Patrick Williams20f38712022-12-08 06:18:26 -060019
Michael Walshdc80d672017-05-09 12:58:32 -050020import socket
Michael Walsh0b93fbf2017-03-02 14:42:41 -060021
George Keishinge635ddc2022-12-08 07:38:02 -060022import gen_arg as ga
George Keishinge635ddc2022-12-08 07:38:02 -060023import gen_cmd as gc
Patrick Williams20f38712022-12-08 06:18:26 -060024import gen_misc as gm
25import gen_plug_in_utils as gpu
26import gen_print as gp
George Keishinge635ddc2022-12-08 07:38:02 -060027import gen_robot_keyword as grk
Patrick Williams20f38712022-12-08 06:18:26 -060028import gen_robot_plug_in as grpi
29import gen_valid as gv
30import logging_utils as log
31import pel_utils as pel
Michael Walsh55302292017-01-10 11:43:02 -060032import state as st
Michael Walshff340002017-08-29 11:18:27 -050033import var_stack as vs
Patrick Williams20f38712022-12-08 06:18:26 -060034from boot_data import *
35from robot.libraries.BuiltIn import BuiltIn
36from robot.utils import DotDict
Michael Walsh0bbd8602016-11-22 11:31:49 -060037
Patrick Williams20f38712022-12-08 06:18:26 -060038base_path = (
Brian Ma139f1da2024-10-18 13:34:14 +080039 os.path.dirname(
40 os.path.dirname(importlib.util.find_spec("gen_robot_print").origin)
41 )
Patrick Williams20f38712022-12-08 06:18:26 -060042 + os.sep
43)
Michael Walsh0b93fbf2017-03-02 14:42:41 -060044sys.path.append(base_path + "extended/")
George Keishing09679892022-12-08 08:21:52 -060045import run_keyword as rk # NOQA
Michael Walsh0bbd8602016-11-22 11:31:49 -060046
Michael Walshe1e26442017-03-06 17:50:07 -060047# Setting master_pid correctly influences the behavior of plug-ins like
48# DB_Logging
49program_pid = os.getpid()
Patrick Williams20f38712022-12-08 06:18:26 -060050master_pid = os.environ.get("AUTOBOOT_MASTER_PID", program_pid)
51pgm_name = re.sub("\\.py$", "", os.path.basename(__file__))
Michael Walshe1e26442017-03-06 17:50:07 -060052
Michael Walshb5839d02017-04-12 16:11:20 -050053# Set up boot data structures.
Michael Walsh986d8ae2019-07-17 10:02:23 -050054os_host = BuiltIn().get_variable_value("${OS_HOST}", default="")
Michael Walsh0b93fbf2017-03-02 14:42:41 -060055
Michael Walsh6741f742017-02-20 16:16:38 -060056boot_lists = read_boot_lists()
Michael Walsh986d8ae2019-07-17 10:02:23 -050057
58# The maximum number of entries that can be in the boot_history global variable.
Michael Walsh815b1d52018-10-30 13:32:26 -050059max_boot_history = 10
Michael Walsh986d8ae2019-07-17 10:02:23 -050060boot_history = []
Michael Walsh6741f742017-02-20 16:16:38 -060061
Patrick Williams20f38712022-12-08 06:18:26 -060062state = st.return_state_constant("default_state")
Michael Walsh6741f742017-02-20 16:16:38 -060063cp_setup_called = 0
64next_boot = ""
Patrick Williams20f38712022-12-08 06:18:26 -060065base_tool_dir_path = (
66 os.path.normpath(os.environ.get("AUTOBOOT_BASE_TOOL_DIR_PATH", "/tmp"))
67 + os.sep
68)
Michael Walshb5839d02017-04-12 16:11:20 -050069
Patrick Williams20f38712022-12-08 06:18:26 -060070ffdc_dir_path = os.path.normpath(os.environ.get("FFDC_DIR_PATH", "")) + os.sep
Michael Walsh6741f742017-02-20 16:16:38 -060071boot_success = 0
George Keishingce90a7d2021-10-12 02:38:51 -050072
Patrick Williams20f38712022-12-08 06:18:26 -060073status_dir_path = os.environ.get(
74 "STATUS_DIR_PATH", ""
75) or BuiltIn().get_variable_value("${STATUS_DIR_PATH}", default="")
Michael Walsh6741f742017-02-20 16:16:38 -060076if status_dir_path != "":
77 status_dir_path = os.path.normpath(status_dir_path) + os.sep
George Keishingce90a7d2021-10-12 02:38:51 -050078 # For plugin expecting env gen_call_robot.py
Patrick Williams20f38712022-12-08 06:18:26 -060079 os.environ["STATUS_DIR_PATH"] = status_dir_path
George Keishingce90a7d2021-10-12 02:38:51 -050080
Patrick Williams20f38712022-12-08 06:18:26 -060081redfish_support_trans_state = int(
82 os.environ.get("REDFISH_SUPPORT_TRANS_STATE", 0)
83) or int(
84 BuiltIn().get_variable_value("${REDFISH_SUPPORT_TRANS_STATE}", default=0)
85)
86redfish_supported = BuiltIn().get_variable_value(
87 "${REDFISH_SUPPORTED}", default=False
88)
89redfish_rest_supported = BuiltIn().get_variable_value(
90 "${REDFISH_REST_SUPPORTED}", default=False
91)
92redfish_delete_sessions = int(
93 BuiltIn().get_variable_value("${REDFISH_DELETE_SESSIONS}", default=1)
94)
Michael Walshe58df1c2019-08-07 09:57:43 -050095if redfish_supported:
Patrick Williams20f38712022-12-08 06:18:26 -060096 redfish = BuiltIn().get_library_instance("redfish")
Michael Walshe58df1c2019-08-07 09:57:43 -050097 default_power_on = "Redfish Power On"
98 default_power_off = "Redfish Power Off"
George Keishing870999a2021-03-31 23:43:57 -050099 if not redfish_support_trans_state:
Michael Sheposcc490b42020-08-26 12:53:01 -0500100 delete_errlogs_cmd = "Delete Error Logs ${quiet}=${1}"
Michael Shepos92a54bf2020-11-11 11:48:55 -0600101 delete_bmcdump_cmd = "Delete All BMC Dump"
George Keishingeb1fe352020-06-19 03:02:22 -0500102 default_set_power_policy = "Set BMC Power Policy ALWAYS_POWER_OFF"
103 else:
104 delete_errlogs_cmd = "Redfish Purge Event Log"
Michael Shepos92a54bf2020-11-11 11:48:55 -0600105 delete_bmcdump_cmd = "Redfish Delete All BMC Dumps"
George Keishing2ef6a7d2021-05-19 09:05:32 -0500106 delete_sysdump_cmd = "Redfish Delete All System Dumps"
Patrick Williams20f38712022-12-08 06:18:26 -0600107 default_set_power_policy = (
108 "Redfish Set Power Restore Policy AlwaysOff"
109 )
Michael Walshe58df1c2019-08-07 09:57:43 -0500110else:
111 default_power_on = "REST Power On"
112 default_power_off = "REST Power Off"
Michael Sheposcc490b42020-08-26 12:53:01 -0500113 delete_errlogs_cmd = "Delete Error Logs ${quiet}=${1}"
Michael Shepos92a54bf2020-11-11 11:48:55 -0600114 delete_bmcdump_cmd = "Delete All BMC Dump"
George Keishinga54e06f2020-06-12 10:42:41 -0500115 default_set_power_policy = "Set BMC Power Policy ALWAYS_POWER_OFF"
Michael Walsh6741f742017-02-20 16:16:38 -0600116boot_count = 0
Michael Walsh0bbd8602016-11-22 11:31:49 -0600117
Michael Walsh85678942017-03-27 14:34:22 -0500118LOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
Patrick Williams20f38712022-12-08 06:18:26 -0600119AUTOBOOT_FFDC_PREFIX = os.environ.get("AUTOBOOT_FFDC_PREFIX", "")
Michael Walsh986d8ae2019-07-17 10:02:23 -0500120ffdc_prefix = AUTOBOOT_FFDC_PREFIX
Sunil M325eb542017-08-10 07:09:43 -0500121boot_start_time = ""
122boot_end_time = ""
Patrick Williams20f38712022-12-08 06:18:26 -0600123save_stack = vs.var_stack("save_stack")
124main_func_parm_list = ["boot_stack", "stack_mode", "quiet"]
Michael Walsh85678942017-03-27 14:34:22 -0500125
126
Michael Walsh89de14a2018-10-01 16:51:37 -0500127def dump_ffdc_rc():
128 r"""
129 Return the constant dump ffdc test return code value.
130
131 When a plug-in call point program returns this value, it indicates that
132 this program should collect FFDC.
133 """
134
135 return 0x00000200
136
137
138def stop_test_rc():
139 r"""
140 Return the constant stop test return code value.
141
142 When a plug-in call point program returns this value, it indicates that
143 this program should stop running.
144 """
145
146 return 0x00000200
147
148
Patrick Williams20f38712022-12-08 06:18:26 -0600149def process_host(host, host_var_name=""):
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500150 r"""
151 Process a host by getting the associated host name and IP address and
152 setting them in global variables.
153
154 If the caller does not pass the host_var_name, this function will try to
155 figure out the name of the variable used by the caller for the host parm.
156 Callers are advised to explicitly specify the host_var_name when calling
157 with an exec command. In such cases, the get_arg_name cannot figure out
158 the host variable name.
159
160 This function will then create similar global variable names by
161 removing "_host" and appending "_host_name" or "_ip" to the host variable
162 name.
163
164 Example:
165
166 If a call is made like this:
167 process_host(openbmc_host)
168
169 Global variables openbmc_host_name and openbmc_ip will be set.
170
171 Description of argument(s):
172 host A host name or IP. The name of the variable used should
173 have a suffix of "_host".
174 host_var_name The name of the variable being used as the host parm.
175 """
176
177 if host_var_name == "":
178 host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
179
180 host_name_var_name = re.sub("host", "host_name", host_var_name)
181 ip_var_name = re.sub("host", "ip", host_var_name)
Patrick Williams20f38712022-12-08 06:18:26 -0600182 cmd_buf = (
183 "global "
184 + host_name_var_name
185 + ", "
186 + ip_var_name
187 + " ; "
188 + host_name_var_name
189 + ", "
190 + ip_var_name
191 + " = gm.get_host_name_ip('"
192 + host
193 + "')"
194 )
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500195 exec(cmd_buf)
196
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500197
Michael Walshb5839d02017-04-12 16:11:20 -0500198def process_pgm_parms():
Michael Walshb5839d02017-04-12 16:11:20 -0500199 r"""
200 Process the program parameters by assigning them all to corresponding
201 globals. Also, set some global values that depend on program parameters.
202 """
203
204 # Program parameter processing.
205 # Assign all program parms to python variables which are global to this
206 # module.
207
208 global parm_list
209 parm_list = BuiltIn().get_variable_value("${parm_list}")
210 # The following subset of parms should be processed as integers.
Patrick Williams20f38712022-12-08 06:18:26 -0600211 int_list = [
212 "max_num_tests",
213 "boot_pass",
214 "boot_fail",
215 "ffdc_only",
216 "boot_fail_threshold",
217 "delete_errlogs",
218 "call_post_stack_plug",
219 "do_pre_boot_plug_in_setup",
220 "quiet",
221 "test_mode",
222 "debug",
223 ]
Michael Walshb5839d02017-04-12 16:11:20 -0500224 for parm in parm_list:
225 if parm in int_list:
Patrick Williams20f38712022-12-08 06:18:26 -0600226 sub_cmd = (
227 'int(BuiltIn().get_variable_value("${' + parm + '}", "0"))'
228 )
Michael Walshb5839d02017-04-12 16:11:20 -0500229 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600230 sub_cmd = 'BuiltIn().get_variable_value("${' + parm + '}")'
Michael Walshb5839d02017-04-12 16:11:20 -0500231 cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
Michael Walshff340002017-08-29 11:18:27 -0500232 gp.dpissuing(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500233 exec(cmd_buf)
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500234 if re.match(r".*_host$", parm):
235 cmd_buf = "process_host(" + parm + ", '" + parm + "')"
236 exec(cmd_buf)
237 if re.match(r".*_password$", parm):
238 # Register the value of any parm whose name ends in _password.
239 # This will cause the print functions to replace passwords with
240 # asterisks in the output.
241 cmd_buf = "gp.register_passwords(" + parm + ")"
242 exec(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500243
244 global ffdc_dir_path_style
245 global boot_list
246 global boot_stack
247 global boot_results_file_path
248 global boot_results
Michael Walsh986d8ae2019-07-17 10:02:23 -0500249 global boot_history
Michael Walshb5839d02017-04-12 16:11:20 -0500250 global ffdc_list_file_path
Michael Walshe0cf8d72017-05-17 13:20:46 -0500251 global ffdc_report_list_path
Michael Walsh600876d2017-05-30 17:58:58 -0500252 global ffdc_summary_list_path
Michael Walsha3e7b222020-02-03 15:32:16 -0600253 global boot_table
254 global valid_boot_types
Michael Walshb5839d02017-04-12 16:11:20 -0500255
256 if ffdc_dir_path_style == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600257 ffdc_dir_path_style = int(os.environ.get("FFDC_DIR_PATH_STYLE", "0"))
Michael Walshb5839d02017-04-12 16:11:20 -0500258
259 # Convert these program parms to lists for easier processing..
George Keishing36efbc02018-12-12 10:18:23 -0600260 boot_list = list(filter(None, boot_list.split(":")))
261 boot_stack = list(filter(None, boot_stack.split(":")))
Michael Walshb5839d02017-04-12 16:11:20 -0500262
Michael Walsha3e7b222020-02-03 15:32:16 -0600263 boot_table = create_boot_table(boot_table_path, os_host=os_host)
264 valid_boot_types = create_valid_boot_list(boot_table)
265
Michael Walsh903e0b22017-09-19 17:00:33 -0500266 cleanup_boot_results_file()
Patrick Williams20f38712022-12-08 06:18:26 -0600267 boot_results_file_path = create_boot_results_file_path(
268 pgm_name, openbmc_nickname, master_pid
269 )
Michael Walshb5839d02017-04-12 16:11:20 -0500270
271 if os.path.isfile(boot_results_file_path):
272 # We've been called before in this run so we'll load the saved
Michael Walsh986d8ae2019-07-17 10:02:23 -0500273 # boot_results and boot_history objects.
Patrick Williams20f38712022-12-08 06:18:26 -0600274 boot_results, boot_history = pickle.load(
275 open(boot_results_file_path, "rb")
276 )
Michael Walshb5839d02017-04-12 16:11:20 -0500277 else:
278 boot_results = boot_results(boot_table, boot_pass, boot_fail)
279
Patrick Williams20f38712022-12-08 06:18:26 -0600280 ffdc_list_file_path = (
281 base_tool_dir_path + openbmc_nickname + "/FFDC_FILE_LIST"
282 )
283 ffdc_report_list_path = (
284 base_tool_dir_path + openbmc_nickname + "/FFDC_REPORT_FILE_LIST"
285 )
Michael Walshb5839d02017-04-12 16:11:20 -0500286
Patrick Williams20f38712022-12-08 06:18:26 -0600287 ffdc_summary_list_path = (
288 base_tool_dir_path + openbmc_nickname + "/FFDC_SUMMARY_FILE_LIST"
289 )
Michael Walsh600876d2017-05-30 17:58:58 -0500290
Michael Walshb5839d02017-04-12 16:11:20 -0500291
Michael Walsh85678942017-03-27 14:34:22 -0500292def initial_plug_in_setup():
Michael Walsh85678942017-03-27 14:34:22 -0500293 r"""
294 Initialize all plug-in environment variables which do not change for the
295 duration of the program.
296
297 """
298
299 global LOG_LEVEL
300 BuiltIn().set_log_level("NONE")
301
302 BuiltIn().set_global_variable("${master_pid}", master_pid)
303 BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
304 BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
305 BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
Patrick Williams20f38712022-12-08 06:18:26 -0600306 BuiltIn().set_global_variable(
307 "${FFDC_LIST_FILE_PATH}", ffdc_list_file_path
308 )
309 BuiltIn().set_global_variable(
310 "${FFDC_REPORT_LIST_PATH}", ffdc_report_list_path
311 )
312 BuiltIn().set_global_variable(
313 "${FFDC_SUMMARY_LIST_PATH}", ffdc_summary_list_path
314 )
Michael Walsh85678942017-03-27 14:34:22 -0500315
Patrick Williams20f38712022-12-08 06:18:26 -0600316 BuiltIn().set_global_variable(
317 "${FFDC_DIR_PATH_STYLE}", ffdc_dir_path_style
318 )
319 BuiltIn().set_global_variable("${FFDC_CHECK}", ffdc_check)
Michael Walsh85678942017-03-27 14:34:22 -0500320
321 # For each program parameter, set the corresponding AUTOBOOT_ environment
322 # variable value. Also, set an AUTOBOOT_ environment variable for every
323 # element in additional_values.
Patrick Williams20f38712022-12-08 06:18:26 -0600324 additional_values = [
325 "program_pid",
326 "master_pid",
327 "ffdc_dir_path",
328 "status_dir_path",
329 "base_tool_dir_path",
330 "ffdc_list_file_path",
331 "ffdc_report_list_path",
332 "ffdc_summary_list_path",
333 "execdir",
334 "redfish_supported",
335 "redfish_rest_supported",
336 "redfish_support_trans_state",
337 ]
Michael Walsh85678942017-03-27 14:34:22 -0500338
339 plug_in_vars = parm_list + additional_values
340
341 for var_name in plug_in_vars:
342 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
343 var_name = var_name.upper()
344 if var_value is None:
345 var_value = ""
346 os.environ["AUTOBOOT_" + var_name] = str(var_value)
347
348 BuiltIn().set_log_level(LOG_LEVEL)
349
Michael Walsh68a61162017-04-25 11:54:06 -0500350 # Make sure the ffdc list directory exists.
351 ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
352 if not os.path.exists(ffdc_list_dir_path):
353 os.makedirs(ffdc_list_dir_path)
Michael Walsh85678942017-03-27 14:34:22 -0500354
Michael Walsh85678942017-03-27 14:34:22 -0500355
Michael Walsh0bbd8602016-11-22 11:31:49 -0600356def plug_in_setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600357 r"""
Michael Walsh85678942017-03-27 14:34:22 -0500358 Initialize all changing plug-in environment variables for use by the
359 plug-in programs.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600360 """
361
Michael Walsh85678942017-03-27 14:34:22 -0500362 global LOG_LEVEL
363 global test_really_running
364
365 BuiltIn().set_log_level("NONE")
366
Michael Walsh6741f742017-02-20 16:16:38 -0600367 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600368 if boot_pass > 1:
369 test_really_running = 1
370 else:
371 test_really_running = 0
372
Patrick Williams20f38712022-12-08 06:18:26 -0600373 BuiltIn().set_global_variable(
374 "${test_really_running}", test_really_running
375 )
Michael Walsh6741f742017-02-20 16:16:38 -0600376 BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
Michael Walsh6741f742017-02-20 16:16:38 -0600377 BuiltIn().set_global_variable("${boot_pass}", boot_pass)
378 BuiltIn().set_global_variable("${boot_fail}", boot_fail)
379 BuiltIn().set_global_variable("${boot_success}", boot_success)
380 BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
Sunil M325eb542017-08-10 07:09:43 -0500381 BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
382 BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
Michael Walsh4c9a6452016-12-13 16:03:11 -0600383
Michael Walsh0bbd8602016-11-22 11:31:49 -0600384 # For each program parameter, set the corresponding AUTOBOOT_ environment
385 # variable value. Also, set an AUTOBOOT_ environment variable for every
386 # element in additional_values.
Patrick Williams20f38712022-12-08 06:18:26 -0600387 additional_values = [
388 "boot_type_desc",
389 "boot_success",
390 "boot_pass",
391 "boot_fail",
392 "test_really_running",
393 "ffdc_prefix",
394 "boot_start_time",
395 "boot_end_time",
396 ]
Michael Walsh0bbd8602016-11-22 11:31:49 -0600397
Michael Walsh85678942017-03-27 14:34:22 -0500398 plug_in_vars = additional_values
Michael Walsh0bbd8602016-11-22 11:31:49 -0600399
400 for var_name in plug_in_vars:
401 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
402 var_name = var_name.upper()
403 if var_value is None:
404 var_value = ""
Michael Walsh6741f742017-02-20 16:16:38 -0600405 os.environ["AUTOBOOT_" + var_name] = str(var_value)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600406
Michael Walsh0bbd8602016-11-22 11:31:49 -0600407 if debug:
Patrick Williams20f38712022-12-08 06:18:26 -0600408 shell_rc, out_buf = gc.cmd_fnc_u(
409 "printenv | egrep AUTOBOOT_ | sort -u"
410 )
Michael Walsh0bbd8602016-11-22 11:31:49 -0600411
Michael Walsh85678942017-03-27 14:34:22 -0500412 BuiltIn().set_log_level(LOG_LEVEL)
413
Michael Walsh0bbd8602016-11-22 11:31:49 -0600414
Michael Walshe0cf8d72017-05-17 13:20:46 -0500415def pre_boot_plug_in_setup():
Michael Walshe0cf8d72017-05-17 13:20:46 -0500416 # Clear the ffdc_list_file_path file. Plug-ins may now write to it.
417 try:
418 os.remove(ffdc_list_file_path)
419 except OSError:
420 pass
421
422 # Clear the ffdc_report_list_path file. Plug-ins may now write to it.
423 try:
424 os.remove(ffdc_report_list_path)
425 except OSError:
426 pass
427
Michael Walsh600876d2017-05-30 17:58:58 -0500428 # Clear the ffdc_summary_list_path file. Plug-ins may now write to it.
429 try:
430 os.remove(ffdc_summary_list_path)
431 except OSError:
432 pass
433
Michael Walshe1974b92017-08-03 13:39:51 -0500434 global ffdc_prefix
435
436 seconds = time.time()
437 loc_time = time.localtime(seconds)
438 time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
439
440 ffdc_prefix = openbmc_nickname + "." + time_string
441
Michael Walshe0cf8d72017-05-17 13:20:46 -0500442
Patrick Williams20f38712022-12-08 06:18:26 -0600443def default_sigusr1(signal_number=0, frame=None):
Michael Walshf566fb12019-02-01 14:35:09 -0600444 r"""
445 Handle SIGUSR1 by doing nothing.
446
447 This function assists in debugging SIGUSR1 processing by printing messages
448 to stdout and to the log.html file.
449
450 Description of argument(s):
451 signal_number The signal number (should always be 10 for SIGUSR1).
452 frame The frame data.
453 """
454
Michael Walsh80dddde2019-10-22 13:54:38 -0500455 gp.qprintn()
456 gp.qprint_executing()
Michael Walshf566fb12019-02-01 14:35:09 -0600457 gp.lprint_executing()
458
459
460def set_default_siguser1():
461 r"""
462 Set the default_sigusr1 function to be the SIGUSR1 handler.
463 """
464
Michael Walsh80dddde2019-10-22 13:54:38 -0500465 gp.qprintn()
466 gp.qprint_executing()
Michael Walshf566fb12019-02-01 14:35:09 -0600467 gp.lprint_executing()
468 signal.signal(signal.SIGUSR1, default_sigusr1)
469
470
Michael Walsh6741f742017-02-20 16:16:38 -0600471def setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600472 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600473 Do general program setup tasks.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600474 """
475
Michael Walsh6741f742017-02-20 16:16:38 -0600476 global cp_setup_called
Michael Walsh81816742017-09-27 11:02:29 -0500477 global transitional_boot_selected
Michael Walsh0bbd8602016-11-22 11:31:49 -0600478
Michael Walshb5839d02017-04-12 16:11:20 -0500479 gp.qprintn()
480
George Keishinga54e06f2020-06-12 10:42:41 -0500481 if redfish_supported:
482 redfish.login()
483
Michael Walshf566fb12019-02-01 14:35:09 -0600484 set_default_siguser1()
Michael Walsh81816742017-09-27 11:02:29 -0500485 transitional_boot_selected = False
486
Michael Walsh83f4bc72017-04-20 16:49:43 -0500487 robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
488 repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
Michael Walshd061c042017-05-23 14:46:57 -0500489 # If we can't find process_plug_in_packages.py, ssh_pw or
490 # validate_plug_ins.py, then we don't have our repo bin in PATH.
Patrick Williams20f38712022-12-08 06:18:26 -0600491 shell_rc, out_buf = gc.cmd_fnc_u(
492 "which process_plug_in_packages.py" + " ssh_pw validate_plug_ins.py",
493 quiet=1,
494 print_output=0,
495 show_err=0,
496 )
Michael Walshb5839d02017-04-12 16:11:20 -0500497 if shell_rc != 0:
Patrick Williams20f38712022-12-08 06:18:26 -0600498 os.environ["PATH"] = repo_bin_path + ":" + os.environ.get("PATH", "")
Michael Walsh83f4bc72017-04-20 16:49:43 -0500499 # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
500 if robot_pgm_dir_path not in sys.path:
501 sys.path.append(robot_pgm_dir_path)
502 PYTHONPATH = os.environ.get("PYTHONPATH", "")
503 if PYTHONPATH == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600504 os.environ["PYTHONPATH"] = robot_pgm_dir_path
Michael Walsh83f4bc72017-04-20 16:49:43 -0500505 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600506 os.environ["PYTHONPATH"] = robot_pgm_dir_path + ":" + PYTHONPATH
Michael Walsh6741f742017-02-20 16:16:38 -0600507
508 validate_parms()
509
Michael Walshc108e422019-03-28 12:27:18 -0500510 gp.qprint_pgm_header()
Michael Walsh6741f742017-02-20 16:16:38 -0600511
George Keishingeae945b2021-12-13 11:05:04 -0600512 grk.run_key_u(default_set_power_policy, ignore=1)
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500513
Michael Walsh85678942017-03-27 14:34:22 -0500514 initial_plug_in_setup()
515
Michael Walsh6741f742017-02-20 16:16:38 -0600516 plug_in_setup()
517 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -0600518 call_point="setup"
519 )
Michael Walsh6741f742017-02-20 16:16:38 -0600520 if rc != 0:
521 error_message = "Plug-in setup failed.\n"
Michael Walshc108e422019-03-28 12:27:18 -0500522 gp.print_error_report(error_message)
Michael Walsh6741f742017-02-20 16:16:38 -0600523 BuiltIn().fail(error_message)
524 # Setting cp_setup_called lets our Teardown know that it needs to call
525 # the cleanup plug-in call point.
526 cp_setup_called = 1
527
528 # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
529 BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
Michael Walsh85678942017-03-27 14:34:22 -0500530 # FFDC_LOG_PATH is used by "FFDC" keyword.
531 BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
Michael Walsh6741f742017-02-20 16:16:38 -0600532
Michael Walshdc80d672017-05-09 12:58:32 -0500533 # Also printed by FFDC.
534 global host_name
535 global host_ip
536 host = socket.gethostname()
537 host_name, host_ip = gm.get_host_name_ip(host)
538
Michael Walsh986d8ae2019-07-17 10:02:23 -0500539 gp.dprint_var(boot_table)
Michael Walshb5839d02017-04-12 16:11:20 -0500540 gp.dprint_var(boot_lists)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600541
Michael Walsh0bbd8602016-11-22 11:31:49 -0600542
Michael Walsh6741f742017-02-20 16:16:38 -0600543def validate_parms():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600544 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600545 Validate all program parameters.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600546 """
547
Michael Walshb5839d02017-04-12 16:11:20 -0500548 process_pgm_parms()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600549
Michael Walshb5839d02017-04-12 16:11:20 -0500550 gp.qprintn()
551
552 global openbmc_model
Michael Walshf5ce38c2020-02-27 12:46:20 -0600553 if openbmc_model == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600554 status, ret_values = grk.run_key_u("Get BMC System Model", ignore=1)
George Keishingec2836d2022-01-19 12:05:54 -0600555 # Set the model to default "OPENBMC" if getting it from BMC fails.
Patrick Williams20f38712022-12-08 06:18:26 -0600556 if status == "FAIL":
557 openbmc_model = "OPENBMC"
George Keishingec2836d2022-01-19 12:05:54 -0600558 else:
559 openbmc_model = ret_values
Michael Walshf5ce38c2020-02-27 12:46:20 -0600560 BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
561 gv.set_exit_on_error(True)
Michael Walsh44cef252019-08-01 12:38:56 -0500562 gv.valid_value(openbmc_host)
563 gv.valid_value(openbmc_username)
564 gv.valid_value(openbmc_password)
565 gv.valid_value(rest_username)
566 gv.valid_value(rest_password)
567 gv.valid_value(ipmi_username)
568 gv.valid_value(ipmi_password)
Michael Walsh6741f742017-02-20 16:16:38 -0600569 if os_host != "":
Michael Walsh44cef252019-08-01 12:38:56 -0500570 gv.valid_value(os_username)
571 gv.valid_value(os_password)
Michael Walsh6741f742017-02-20 16:16:38 -0600572 if pdu_host != "":
Michael Walsh44cef252019-08-01 12:38:56 -0500573 gv.valid_value(pdu_username)
574 gv.valid_value(pdu_password)
575 gv.valid_integer(pdu_slot_no)
Michael Walsh6741f742017-02-20 16:16:38 -0600576 if openbmc_serial_host != "":
Michael Walsh44cef252019-08-01 12:38:56 -0500577 gv.valid_integer(openbmc_serial_port)
Michael Walsh44cef252019-08-01 12:38:56 -0500578 gv.valid_value(openbmc_model)
579 gv.valid_integer(max_num_tests)
580 gv.valid_integer(boot_pass)
581 gv.valid_integer(boot_fail)
Michael Walsh6741f742017-02-20 16:16:38 -0600582 plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
Patrick Williams20f38712022-12-08 06:18:26 -0600583 BuiltIn().set_global_variable(
584 "${plug_in_packages_list}", plug_in_packages_list
585 )
586 gv.valid_value(stack_mode, valid_values=["normal", "skip"])
Michael Walshf5ce38c2020-02-27 12:46:20 -0600587 gv.set_exit_on_error(False)
Michael Walsha20da402017-03-31 16:27:45 -0500588 if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
Patrick Williams20f38712022-12-08 06:18:26 -0600589 error_message = (
590 "You must provide either a value for either the"
591 + " boot_list or the boot_stack parm.\n"
592 )
Michael Walsh6741f742017-02-20 16:16:38 -0600593 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -0600594 valid_boot_list(boot_list, valid_boot_types)
595 valid_boot_list(boot_stack, valid_boot_types)
Patrick Williams20f38712022-12-08 06:18:26 -0600596 selected_PDU_boots = list(
597 set(boot_list + boot_stack) & set(boot_lists["PDU_reboot"])
598 )
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500599 if len(selected_PDU_boots) > 0 and pdu_host == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600600 error_message = (
601 "You have selected the following boots which"
602 + " require a PDU host but no value for pdu_host:\n"
603 )
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500604 error_message += gp.sprint_var(selected_PDU_boots)
Michael Walsh986d8ae2019-07-17 10:02:23 -0500605 error_message += gp.sprint_var(pdu_host, fmt=gp.blank())
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500606 BuiltIn().fail(gp.sprint_error(error_message))
607
Michael Walsh6741f742017-02-20 16:16:38 -0600608 return
Michael Walsh0bbd8602016-11-22 11:31:49 -0600609
Michael Walsh0bbd8602016-11-22 11:31:49 -0600610
Michael Walsh6741f742017-02-20 16:16:38 -0600611def my_get_state():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600612 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600613 Get the system state plus a little bit of wrapping.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600614 """
615
Michael Walsh6741f742017-02-20 16:16:38 -0600616 global state
617
Patrick Williams20f38712022-12-08 06:18:26 -0600618 req_states = ["epoch_seconds"] + st.default_req_states
Michael Walsh6741f742017-02-20 16:16:38 -0600619
Michael Walshb5839d02017-04-12 16:11:20 -0500620 gp.qprint_timen("Getting system state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600621 if test_mode:
Patrick Williams20f38712022-12-08 06:18:26 -0600622 state["epoch_seconds"] = int(time.time())
Michael Walsh6741f742017-02-20 16:16:38 -0600623 else:
Michael Walshb5839d02017-04-12 16:11:20 -0500624 state = st.get_state(req_states=req_states, quiet=quiet)
625 gp.qprint_var(state)
Michael Walsh341c21e2017-01-17 16:25:20 -0600626
Michael Walsh341c21e2017-01-17 16:25:20 -0600627
Michael Walsh45ca6e42017-09-14 17:29:12 -0500628def valid_state():
Michael Walsh45ca6e42017-09-14 17:29:12 -0500629 r"""
630 Verify that our state dictionary contains no blank values. If we don't get
631 valid state data, we cannot continue to work.
632 """
633
Patrick Williams20f38712022-12-08 06:18:26 -0600634 if st.compare_states(state, st.invalid_state_match, "or"):
635 error_message = (
636 "The state dictionary contains blank fields which"
637 + " is illegal.\n"
638 + gp.sprint_var(state)
639 )
Michael Walsh45ca6e42017-09-14 17:29:12 -0500640 BuiltIn().fail(gp.sprint_error(error_message))
641
Michael Walsh45ca6e42017-09-14 17:29:12 -0500642
Michael Walsh6741f742017-02-20 16:16:38 -0600643def select_boot():
Michael Walsh341c21e2017-01-17 16:25:20 -0600644 r"""
645 Select a boot test to be run based on our current state and return the
646 chosen boot type.
647
648 Description of arguments:
Michael Walsh6741f742017-02-20 16:16:38 -0600649 state The state of the machine.
Michael Walsh341c21e2017-01-17 16:25:20 -0600650 """
651
Michael Walsh81816742017-09-27 11:02:29 -0500652 global transitional_boot_selected
Michael Walsh30dadae2017-02-27 14:25:52 -0600653 global boot_stack
654
Michael Walshb5839d02017-04-12 16:11:20 -0500655 gp.qprint_timen("Selecting a boot test.")
Michael Walsh6741f742017-02-20 16:16:38 -0600656
Michael Walsh81816742017-09-27 11:02:29 -0500657 if transitional_boot_selected and not boot_success:
658 prior_boot = next_boot
659 boot_candidate = boot_stack.pop()
Patrick Williams20f38712022-12-08 06:18:26 -0600660 gp.qprint_timen(
661 "The prior '"
662 + next_boot
663 + "' was chosen to"
664 + " transition to a valid state for '"
665 + boot_candidate
666 + "' which was at the top of the boot_stack. Since"
667 + " the '"
668 + next_boot
669 + "' failed, the '"
670 + boot_candidate
671 + "' has been removed from the stack"
672 + " to avoid and endless failure loop."
673 )
Michael Walsh81816742017-09-27 11:02:29 -0500674 if len(boot_stack) == 0:
675 return ""
676
Michael Walsh6741f742017-02-20 16:16:38 -0600677 my_get_state()
Michael Walsh45ca6e42017-09-14 17:29:12 -0500678 valid_state()
Michael Walsh6741f742017-02-20 16:16:38 -0600679
Michael Walsh81816742017-09-27 11:02:29 -0500680 transitional_boot_selected = False
Michael Walsh6741f742017-02-20 16:16:38 -0600681 stack_popped = 0
682 if len(boot_stack) > 0:
683 stack_popped = 1
Michael Walshb5839d02017-04-12 16:11:20 -0500684 gp.qprint_dashes()
685 gp.qprint_var(boot_stack)
686 gp.qprint_dashes()
687 skip_boot_printed = 0
688 while len(boot_stack) > 0:
689 boot_candidate = boot_stack.pop()
Patrick Williams20f38712022-12-08 06:18:26 -0600690 if stack_mode == "normal":
Michael Walshb5839d02017-04-12 16:11:20 -0500691 break
692 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600693 if st.compare_states(state, boot_table[boot_candidate]["end"]):
Michael Walshb5839d02017-04-12 16:11:20 -0500694 if not skip_boot_printed:
Michael Walshff340002017-08-29 11:18:27 -0500695 gp.qprint_var(stack_mode)
696 gp.qprintn()
Patrick Williams20f38712022-12-08 06:18:26 -0600697 gp.qprint_timen(
698 "Skipping the following boot tests"
699 + " which are unnecessary since their"
700 + " required end states match the"
701 + " current machine state:"
702 )
Michael Walshb5839d02017-04-12 16:11:20 -0500703 skip_boot_printed = 1
Michael Walshff340002017-08-29 11:18:27 -0500704 gp.qprint_var(boot_candidate)
Michael Walshb5839d02017-04-12 16:11:20 -0500705 boot_candidate = ""
706 if boot_candidate == "":
707 gp.qprint_dashes()
708 gp.qprint_var(boot_stack)
709 gp.qprint_dashes()
710 return boot_candidate
Patrick Williams20f38712022-12-08 06:18:26 -0600711 if st.compare_states(state, boot_table[boot_candidate]["start"]):
712 gp.qprint_timen(
713 "The machine state is valid for a '"
714 + boot_candidate
715 + "' boot test."
716 )
Michael Walshb5839d02017-04-12 16:11:20 -0500717 gp.qprint_dashes()
718 gp.qprint_var(boot_stack)
719 gp.qprint_dashes()
Michael Walsh6741f742017-02-20 16:16:38 -0600720 return boot_candidate
Michael Walsh341c21e2017-01-17 16:25:20 -0600721 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600722 gp.qprint_timen(
723 "The machine state does not match the required"
724 + " starting state for a '"
725 + boot_candidate
726 + "' boot test:"
727 )
728 gp.qprint_varx(
729 "boot_table_start_entry", boot_table[boot_candidate]["start"]
730 )
Michael Walsh6741f742017-02-20 16:16:38 -0600731 boot_stack.append(boot_candidate)
Michael Walsh81816742017-09-27 11:02:29 -0500732 transitional_boot_selected = True
Michael Walsh6741f742017-02-20 16:16:38 -0600733 popped_boot = boot_candidate
734
735 # Loop through your list selecting a boot_candidates
736 boot_candidates = []
737 for boot_candidate in boot_list:
Patrick Williams20f38712022-12-08 06:18:26 -0600738 if st.compare_states(state, boot_table[boot_candidate]["start"]):
Michael Walsh6741f742017-02-20 16:16:38 -0600739 if stack_popped:
Patrick Williams20f38712022-12-08 06:18:26 -0600740 if st.compare_states(
741 boot_table[boot_candidate]["end"],
742 boot_table[popped_boot]["start"],
743 ):
Michael Walsh6741f742017-02-20 16:16:38 -0600744 boot_candidates.append(boot_candidate)
745 else:
746 boot_candidates.append(boot_candidate)
747
748 if len(boot_candidates) == 0:
Patrick Williams20f38712022-12-08 06:18:26 -0600749 gp.qprint_timen(
750 "The user's boot list contained no boot tests"
751 + " which are valid for the current machine state."
752 )
Michael Walsh6741f742017-02-20 16:16:38 -0600753 boot_candidate = default_power_on
Patrick Williams20f38712022-12-08 06:18:26 -0600754 if not st.compare_states(state, boot_table[default_power_on]["start"]):
Michael Walsh6741f742017-02-20 16:16:38 -0600755 boot_candidate = default_power_off
756 boot_candidates.append(boot_candidate)
Patrick Williams20f38712022-12-08 06:18:26 -0600757 gp.qprint_timen(
758 "Using default '"
759 + boot_candidate
760 + "' boot type to transition to valid state."
761 )
Michael Walsh6741f742017-02-20 16:16:38 -0600762
Michael Walshb5839d02017-04-12 16:11:20 -0500763 gp.dprint_var(boot_candidates)
Michael Walsh6741f742017-02-20 16:16:38 -0600764
765 # Randomly select a boot from the candidate list.
766 boot = random.choice(boot_candidates)
Michael Walsh341c21e2017-01-17 16:25:20 -0600767
768 return boot
Michael Walsh0bbd8602016-11-22 11:31:49 -0600769
Michael Walsh55302292017-01-10 11:43:02 -0600770
Michael Walshb2e53ec2017-10-30 15:04:36 -0500771def print_defect_report(ffdc_file_list):
Michael Walsh341c21e2017-01-17 16:25:20 -0600772 r"""
773 Print a defect report.
Michael Walshb2e53ec2017-10-30 15:04:36 -0500774
775 Description of argument(s):
776 ffdc_file_list A list of files which were collected by our ffdc functions.
Michael Walsh341c21e2017-01-17 16:25:20 -0600777 """
778
Michael Walsh600876d2017-05-30 17:58:58 -0500779 # Making deliberate choice to NOT run plug_in_setup(). We don't want
780 # ffdc_prefix updated.
781 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -0600782 call_point="ffdc_report", stop_on_plug_in_failure=0
783 )
Michael Walsh600876d2017-05-30 17:58:58 -0500784
Michael Walshe0cf8d72017-05-17 13:20:46 -0500785 # Get additional header data which may have been created by ffdc plug-ins.
786 # Also, delete the individual header files to cleanup.
Patrick Williams20f38712022-12-08 06:18:26 -0600787 cmd_buf = (
788 "file_list=$(cat "
789 + ffdc_report_list_path
790 + " 2>/dev/null)"
791 + ' ; [ ! -z "${file_list}" ] && cat ${file_list}'
792 + " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
793 )
794 shell_rc, more_header_info = gc.cmd_fnc_u(
795 cmd_buf, print_output=0, show_err=0
796 )
Michael Walshe0cf8d72017-05-17 13:20:46 -0500797
Michael Walshb2e53ec2017-10-30 15:04:36 -0500798 # Get additional summary data which may have been created by ffdc plug-ins.
Michael Walsh600876d2017-05-30 17:58:58 -0500799 # Also, delete the individual header files to cleanup.
Patrick Williams20f38712022-12-08 06:18:26 -0600800 cmd_buf = (
801 "file_list=$(cat "
802 + ffdc_summary_list_path
803 + " 2>/dev/null)"
804 + ' ; [ ! -z "${file_list}" ] && cat ${file_list}'
805 + " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
806 )
807 shell_rc, ffdc_summary_info = gc.cmd_fnc_u(
808 cmd_buf, print_output=0, show_err=0
809 )
Michael Walsh600876d2017-05-30 17:58:58 -0500810
Michael Walshb2e53ec2017-10-30 15:04:36 -0500811 # ffdc_list_file_path contains a list of any ffdc files created by plug-
812 # ins, etc. Read that data into a list.
Michael Walsh341c21e2017-01-17 16:25:20 -0600813 try:
Patrick Williams20f38712022-12-08 06:18:26 -0600814 plug_in_ffdc_list = (
815 open(ffdc_list_file_path, "r").read().rstrip("\n").split("\n")
816 )
George Keishing36efbc02018-12-12 10:18:23 -0600817 plug_in_ffdc_list = list(filter(None, plug_in_ffdc_list))
Michael Walsh341c21e2017-01-17 16:25:20 -0600818 except IOError:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500819 plug_in_ffdc_list = []
820
821 # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
822 # in. Eliminate duplicates and sort the list.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500823 ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
Michael Walshb2e53ec2017-10-30 15:04:36 -0500824
825 if status_file_path != "":
826 ffdc_file_list.insert(0, status_file_path)
827
828 # Convert the list to a printable list.
829 printable_ffdc_file_list = "\n".join(ffdc_file_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600830
Michael Walsh68a61162017-04-25 11:54:06 -0500831 # Open ffdc_file_list for writing. We will write a complete list of
832 # FFDC files to it for possible use by plug-ins like cp_stop_check.
Patrick Williams20f38712022-12-08 06:18:26 -0600833 ffdc_list_file = open(ffdc_list_file_path, "w")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500834 ffdc_list_file.write(printable_ffdc_file_list + "\n")
835 ffdc_list_file.close()
836
837 indent = 0
838 width = 90
839 linefeed = 1
840 char = "="
Michael Walsh68a61162017-04-25 11:54:06 -0500841
842 gp.qprintn()
Michael Walshb2e53ec2017-10-30 15:04:36 -0500843 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500844 gp.qprintn("Copy this data to the defect:\n")
845
Michael Walshe0cf8d72017-05-17 13:20:46 -0500846 if len(more_header_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500847 gp.qprintn(more_header_info)
Patrick Williams20f38712022-12-08 06:18:26 -0600848 gp.qpvars(
849 host_name,
850 host_ip,
851 openbmc_nickname,
852 openbmc_host,
853 openbmc_host_name,
854 openbmc_ip,
855 openbmc_username,
856 openbmc_password,
857 rest_username,
858 rest_password,
859 ipmi_username,
860 ipmi_password,
861 os_host,
862 os_host_name,
863 os_ip,
864 os_username,
865 os_password,
866 pdu_host,
867 pdu_host_name,
868 pdu_ip,
869 pdu_username,
870 pdu_password,
871 pdu_slot_no,
872 openbmc_serial_host,
873 openbmc_serial_host_name,
874 openbmc_serial_ip,
875 openbmc_serial_port,
876 )
Michael Walsh68a61162017-04-25 11:54:06 -0500877
878 gp.qprintn()
Michael Walsh986d8ae2019-07-17 10:02:23 -0500879 print_boot_history(boot_history)
Michael Walsh68a61162017-04-25 11:54:06 -0500880 gp.qprintn()
881 gp.qprint_var(state)
Michael Walshb5839d02017-04-12 16:11:20 -0500882 gp.qprintn()
883 gp.qprintn("FFDC data files:")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500884 gp.qprintn(printable_ffdc_file_list)
Michael Walshb5839d02017-04-12 16:11:20 -0500885 gp.qprintn()
Michael Walsh341c21e2017-01-17 16:25:20 -0600886
Michael Walsh600876d2017-05-30 17:58:58 -0500887 if len(ffdc_summary_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500888 gp.qprintn(ffdc_summary_info)
Michael Walsh600876d2017-05-30 17:58:58 -0500889
Michael Walshb2e53ec2017-10-30 15:04:36 -0500890 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500891
Michael Walsh6741f742017-02-20 16:16:38 -0600892
Michael Walsh6741f742017-02-20 16:16:38 -0600893def my_ffdc():
Michael Walsh6741f742017-02-20 16:16:38 -0600894 r"""
895 Collect FFDC data.
896 """
897
898 global state
899
900 plug_in_setup()
901 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -0600902 call_point="ffdc", stop_on_plug_in_failure=0
903 )
Michael Walsh6741f742017-02-20 16:16:38 -0600904
Patrick Williams20f38712022-12-08 06:18:26 -0600905 AUTOBOOT_FFDC_PREFIX = os.environ["AUTOBOOT_FFDC_PREFIX"]
906 status, ffdc_file_list = grk.run_key_u(
907 "FFDC ffdc_prefix="
908 + AUTOBOOT_FFDC_PREFIX
909 + " ffdc_function_list="
910 + ffdc_function_list,
911 ignore=1,
912 )
913 if status != "PASS":
Michael Walshff340002017-08-29 11:18:27 -0500914 gp.qprint_error("Call to ffdc failed.\n")
Michael Walshc9bd2e82019-04-18 11:06:52 -0500915 if type(ffdc_file_list) is not list:
916 ffdc_file_list = []
917 # Leave a record for caller that "soft" errors occurred.
918 soft_errors = 1
919 gpu.save_plug_in_value(soft_errors, pgm_name)
Michael Walsh6741f742017-02-20 16:16:38 -0600920
921 my_get_state()
922
Michael Walshb2e53ec2017-10-30 15:04:36 -0500923 print_defect_report(ffdc_file_list)
Michael Walsh6741f742017-02-20 16:16:38 -0600924
Michael Walsh6741f742017-02-20 16:16:38 -0600925
Michael Walsh6741f742017-02-20 16:16:38 -0600926def print_test_start_message(boot_keyword):
Michael Walsh6741f742017-02-20 16:16:38 -0600927 r"""
928 Print a message indicating what boot test is about to run.
929
930 Description of arguments:
931 boot_keyword The name of the boot which is to be run
932 (e.g. "BMC Power On").
933 """
934
Michael Walsh986d8ae2019-07-17 10:02:23 -0500935 global boot_history
Sunil M325eb542017-08-10 07:09:43 -0500936 global boot_start_time
Michael Walsh6741f742017-02-20 16:16:38 -0600937
Patrick Williams20f38712022-12-08 06:18:26 -0600938 doing_msg = gp.sprint_timen('Doing "' + boot_keyword + '".')
Sunil M325eb542017-08-10 07:09:43 -0500939
940 # Set boot_start_time for use by plug-ins.
941 boot_start_time = doing_msg[1:33]
942 gp.qprint_var(boot_start_time)
943
Michael Walshb5839d02017-04-12 16:11:20 -0500944 gp.qprint(doing_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600945
Michael Walsh986d8ae2019-07-17 10:02:23 -0500946 update_boot_history(boot_history, doing_msg, max_boot_history)
Michael Walsh6741f742017-02-20 16:16:38 -0600947
Michael Walsh6741f742017-02-20 16:16:38 -0600948
Patrick Williams20f38712022-12-08 06:18:26 -0600949def stop_boot_test(signal_number=0, frame=None):
Michael Walshf566fb12019-02-01 14:35:09 -0600950 r"""
951 Handle SIGUSR1 by aborting the boot test that is running.
952
953 Description of argument(s):
954 signal_number The signal number (should always be 10 for SIGUSR1).
955 frame The frame data.
956 """
957
Michael Walsh80dddde2019-10-22 13:54:38 -0500958 gp.qprintn()
959 gp.qprint_executing()
Michael Walshf566fb12019-02-01 14:35:09 -0600960 gp.lprint_executing()
961
962 # Restore original sigusr1 handler.
963 set_default_siguser1()
964
965 message = "The caller has asked that the boot test be stopped and marked"
966 message += " as a failure."
967
968 function_stack = gm.get_function_stack()
969 if "wait_state" in function_stack:
Michael Walshc44aa532019-06-14 13:33:29 -0500970 st.set_exit_wait_early_message(message)
Michael Walshf566fb12019-02-01 14:35:09 -0600971 else:
972 BuiltIn().fail(gp.sprint_error(message))
973
974
Michael Walsh6741f742017-02-20 16:16:38 -0600975def run_boot(boot):
Michael Walsh6741f742017-02-20 16:16:38 -0600976 r"""
977 Run the specified boot.
978
979 Description of arguments:
980 boot The name of the boot test to be performed.
981 """
982
983 global state
984
Michael Walshf566fb12019-02-01 14:35:09 -0600985 signal.signal(signal.SIGUSR1, stop_boot_test)
986 gp.qprint_timen("stop_boot_test is armed.")
987
Michael Walsh6741f742017-02-20 16:16:38 -0600988 print_test_start_message(boot)
989
990 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -0600991 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
992 call_point="pre_boot"
993 )
Michael Walsh6741f742017-02-20 16:16:38 -0600994 if rc != 0:
Patrick Williams20f38712022-12-08 06:18:26 -0600995 error_message = (
996 "Plug-in failed with non-zero return code.\n"
997 + gp.sprint_var(rc, fmt=gp.hexa())
998 )
Michael Walshf566fb12019-02-01 14:35:09 -0600999 set_default_siguser1()
Michael Walsh6741f742017-02-20 16:16:38 -06001000 BuiltIn().fail(gp.sprint_error(error_message))
1001
1002 if test_mode:
1003 # In test mode, we'll pretend the boot worked by assigning its
1004 # required end state to the default state value.
Patrick Williams20f38712022-12-08 06:18:26 -06001005 state = st.strip_anchor_state(boot_table[boot]["end"])
Michael Walsh6741f742017-02-20 16:16:38 -06001006 else:
1007 # Assertion: We trust that the state data was made fresh by the
1008 # caller.
1009
Michael Walshb5839d02017-04-12 16:11:20 -05001010 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -06001011
Patrick Williams20f38712022-12-08 06:18:26 -06001012 if boot_table[boot]["method_type"] == "keyword":
1013 rk.my_run_keywords(
1014 boot_table[boot].get("lib_file_path", ""),
1015 boot_table[boot]["method"],
1016 quiet=quiet,
1017 )
Michael Walsh6741f742017-02-20 16:16:38 -06001018
Patrick Williams20f38712022-12-08 06:18:26 -06001019 if boot_table[boot]["bmc_reboot"]:
1020 st.wait_for_comm_cycle(int(state["epoch_seconds"]))
Michael Walsh30dadae2017-02-27 14:25:52 -06001021 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001022 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1023 call_point="post_reboot"
1024 )
Michael Walsh30dadae2017-02-27 14:25:52 -06001025 if rc != 0:
Michael Walsh0b93fbf2017-03-02 14:42:41 -06001026 error_message = "Plug-in failed with non-zero return code.\n"
Michael Walsh986d8ae2019-07-17 10:02:23 -05001027 error_message += gp.sprint_var(rc, fmt=gp.hexa())
Michael Walshf566fb12019-02-01 14:35:09 -06001028 set_default_siguser1()
Michael Walsh30dadae2017-02-27 14:25:52 -06001029 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -06001030 else:
1031 match_state = st.anchor_state(state)
Patrick Williams20f38712022-12-08 06:18:26 -06001032 del match_state["epoch_seconds"]
Michael Walsh6741f742017-02-20 16:16:38 -06001033 # Wait for the state to change in any way.
Patrick Williams20f38712022-12-08 06:18:26 -06001034 st.wait_state(
1035 match_state,
1036 wait_time=state_change_timeout,
1037 interval="10 seconds",
1038 invert=1,
1039 )
Michael Walsh6741f742017-02-20 16:16:38 -06001040
Michael Walshb5839d02017-04-12 16:11:20 -05001041 gp.qprintn()
Patrick Williams20f38712022-12-08 06:18:26 -06001042 if boot_table[boot]["end"]["chassis"] == "Off":
Michael Walsh6741f742017-02-20 16:16:38 -06001043 boot_timeout = power_off_timeout
1044 else:
1045 boot_timeout = power_on_timeout
Patrick Williams20f38712022-12-08 06:18:26 -06001046 st.wait_state(
1047 boot_table[boot]["end"],
1048 wait_time=boot_timeout,
1049 interval="10 seconds",
1050 )
Michael Walsh6741f742017-02-20 16:16:38 -06001051
1052 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001053 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1054 call_point="post_boot"
1055 )
Michael Walsh6741f742017-02-20 16:16:38 -06001056 if rc != 0:
Patrick Williams20f38712022-12-08 06:18:26 -06001057 error_message = (
1058 "Plug-in failed with non-zero return code.\n"
1059 + gp.sprint_var(rc, fmt=gp.hexa())
1060 )
Michael Walshf566fb12019-02-01 14:35:09 -06001061 set_default_siguser1()
Michael Walsh6741f742017-02-20 16:16:38 -06001062 BuiltIn().fail(gp.sprint_error(error_message))
1063
Michael Walshf566fb12019-02-01 14:35:09 -06001064 # Restore original sigusr1 handler.
1065 set_default_siguser1()
1066
Michael Walsh6741f742017-02-20 16:16:38 -06001067
Michael Walsh6741f742017-02-20 16:16:38 -06001068def test_loop_body():
Michael Walsh6741f742017-02-20 16:16:38 -06001069 r"""
1070 The main loop body for the loop in main_py.
1071
1072 Description of arguments:
1073 boot_count The iteration number (starts at 1).
1074 """
1075
1076 global boot_count
1077 global state
1078 global next_boot
1079 global boot_success
Sunil M325eb542017-08-10 07:09:43 -05001080 global boot_end_time
Michael Walsh6741f742017-02-20 16:16:38 -06001081
Yi Hu02d32762024-03-07 14:34:34 -08001082 # The flag can be enabled or disabled on the go
1083 redfish_delete_sessions = int(
1084 BuiltIn().get_variable_value("${REDFISH_DELETE_SESSIONS}", default=1)
1085 )
1086
Michael Walshb5839d02017-04-12 16:11:20 -05001087 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -06001088
1089 next_boot = select_boot()
Michael Walshb5839d02017-04-12 16:11:20 -05001090 if next_boot == "":
1091 return True
Michael Walsh6741f742017-02-20 16:16:38 -06001092
Michael Walshb5839d02017-04-12 16:11:20 -05001093 boot_count += 1
1094 gp.qprint_timen("Starting boot " + str(boot_count) + ".")
Michael Walsh6741f742017-02-20 16:16:38 -06001095
Michael Walshe0cf8d72017-05-17 13:20:46 -05001096 pre_boot_plug_in_setup()
Michael Walsh6741f742017-02-20 16:16:38 -06001097
1098 cmd_buf = ["run_boot", next_boot]
1099 boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
1100 if boot_status == "FAIL":
Michael Walshb5839d02017-04-12 16:11:20 -05001101 gp.qprint(msg)
Michael Walsh6741f742017-02-20 16:16:38 -06001102
Michael Walshb5839d02017-04-12 16:11:20 -05001103 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -06001104 if boot_status == "PASS":
1105 boot_success = 1
Patrick Williams20f38712022-12-08 06:18:26 -06001106 completion_msg = gp.sprint_timen(
1107 'BOOT_SUCCESS: "' + next_boot + '" succeeded.'
1108 )
Michael Walsh6741f742017-02-20 16:16:38 -06001109 else:
1110 boot_success = 0
Patrick Williams20f38712022-12-08 06:18:26 -06001111 completion_msg = gp.sprint_timen(
1112 'BOOT_FAILED: "' + next_boot + '" failed.'
1113 )
Sunil M325eb542017-08-10 07:09:43 -05001114
1115 # Set boot_end_time for use by plug-ins.
1116 boot_end_time = completion_msg[1:33]
1117 gp.qprint_var(boot_end_time)
1118
1119 gp.qprint(completion_msg)
Michael Walsh6741f742017-02-20 16:16:38 -06001120
1121 boot_results.update(next_boot, boot_status)
1122
1123 plug_in_setup()
1124 # NOTE: A post_test_case call point failure is NOT counted as a boot
1125 # failure.
1126 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001127 call_point="post_test_case", stop_on_plug_in_failure=0
1128 )
Michael Walsh6741f742017-02-20 16:16:38 -06001129
1130 plug_in_setup()
1131 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001132 call_point="ffdc_check",
1133 shell_rc=dump_ffdc_rc(),
1134 stop_on_plug_in_failure=1,
1135 stop_on_non_zero_rc=1,
1136 )
1137 if ffdc_check == "All" or shell_rc == dump_ffdc_rc():
Michael Walsh83f4bc72017-04-20 16:49:43 -05001138 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
Patrick Williams20f38712022-12-08 06:18:26 -06001139 if status != "PASS":
Michael Walshff340002017-08-29 11:18:27 -05001140 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walshc9bd2e82019-04-18 11:06:52 -05001141 # Leave a record for caller that "soft" errors occurred.
1142 soft_errors = 1
1143 gpu.save_plug_in_value(soft_errors, pgm_name)
Michael Walsh6741f742017-02-20 16:16:38 -06001144
Michael Walshaabef1e2017-09-20 15:16:17 -05001145 if delete_errlogs:
Michael Shepos1a67b082020-08-28 16:01:58 -05001146 # print error logs before delete
George Keishing438fd3b2021-10-08 02:15:18 -05001147 if redfish_support_trans_state:
1148 status, error_logs = grk.run_key_u("Get Redfish Event Logs")
Patrick Williams20f38712022-12-08 06:18:26 -06001149 log.print_error_logs(
1150 error_logs, "AdditionalDataURI Message Severity"
1151 )
George Keishing438fd3b2021-10-08 02:15:18 -05001152 else:
1153 status, error_logs = grk.run_key_u("Get Error Logs")
1154 log.print_error_logs(error_logs, "AdditionalData Message Severity")
Michael Shepos1a67b082020-08-28 16:01:58 -05001155 pels = pel.peltool("-l", ignore_err=1)
Michael Shepos0e5f1132020-09-30 16:24:25 -05001156 gp.qprint_var(pels)
Michael Shepos1a67b082020-08-28 16:01:58 -05001157
Michael Walshaabef1e2017-09-20 15:16:17 -05001158 # We need to purge error logs between boots or they build up.
Michael Walsh409ad352020-02-06 11:46:35 -06001159 grk.run_key(delete_errlogs_cmd, ignore=1)
Michael Shepos92a54bf2020-11-11 11:48:55 -06001160 grk.run_key(delete_bmcdump_cmd, ignore=1)
George Keishing2ef6a7d2021-05-19 09:05:32 -05001161 if redfish_support_trans_state:
1162 grk.run_key(delete_sysdump_cmd, ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -05001163
Michael Walsh952f9b02017-03-09 13:11:14 -06001164 boot_results.print_report()
Michael Walshb5839d02017-04-12 16:11:20 -05001165 gp.qprint_timen("Finished boot " + str(boot_count) + ".")
Michael Walsh952f9b02017-03-09 13:11:14 -06001166
Michael Walsh6741f742017-02-20 16:16:38 -06001167 plug_in_setup()
1168 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001169 call_point="stop_check", shell_rc=stop_test_rc(), stop_on_non_zero_rc=1
1170 )
Michael Walsh89de14a2018-10-01 16:51:37 -05001171 if shell_rc == stop_test_rc():
Michael Walsh3ba8ecd2018-04-24 11:33:25 -05001172 message = "Stopping as requested by user.\n"
Michael Walsh80dddde2019-10-22 13:54:38 -05001173 gp.qprint_time(message)
Michael Walsh3ba8ecd2018-04-24 11:33:25 -05001174 BuiltIn().fail(message)
Michael Walsh6741f742017-02-20 16:16:38 -06001175
Michael Walshd139f282017-04-04 18:00:23 -05001176 # This should help prevent ConnectionErrors.
George Keishing4d65c862020-12-03 06:52:11 -06001177 # Purge all redfish and REST connection sessions.
George Keishingd86e45c2021-03-19 07:38:14 -05001178 if redfish_delete_sessions:
1179 grk.run_key_u("Close All Connections", ignore=1)
1180 grk.run_key_u("Delete All Redfish Sessions", ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -05001181
Michael Walsh6741f742017-02-20 16:16:38 -06001182 return True
1183
Michael Walsh6741f742017-02-20 16:16:38 -06001184
Michael Walsh83f4bc72017-04-20 16:49:43 -05001185def obmc_boot_test_teardown():
Michael Walsh6741f742017-02-20 16:16:38 -06001186 r"""
Michael Walshf75d4352019-12-05 17:01:20 -06001187 Clean up after the main keyword.
Michael Walsh6741f742017-02-20 16:16:38 -06001188 """
Michael Walshf75d4352019-12-05 17:01:20 -06001189 gp.qprint_executing()
1190
1191 if ga.psutil_imported:
1192 ga.terminate_descendants()
Michael Walsh6741f742017-02-20 16:16:38 -06001193
1194 if cp_setup_called:
1195 plug_in_setup()
1196 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001197 call_point="cleanup", stop_on_plug_in_failure=0
1198 )
Michael Walsh6741f742017-02-20 16:16:38 -06001199
Patrick Williams20f38712022-12-08 06:18:26 -06001200 if "boot_results_file_path" in globals():
Michael Walsh986d8ae2019-07-17 10:02:23 -05001201 # Save boot_results and boot_history objects to a file in case they are
Michael Walsh6c645742018-08-17 15:02:17 -05001202 # needed again.
Michael Walsh600876d2017-05-30 17:58:58 -05001203 gp.qprint_timen("Saving boot_results to the following path.")
1204 gp.qprint_var(boot_results_file_path)
Patrick Williams20f38712022-12-08 06:18:26 -06001205 pickle.dump(
1206 (boot_results, boot_history),
1207 open(boot_results_file_path, "wb"),
1208 pickle.HIGHEST_PROTOCOL,
1209 )
Michael Walsh0b93fbf2017-03-02 14:42:41 -06001210
Michael Walshff340002017-08-29 11:18:27 -05001211 global save_stack
1212 # Restore any global values saved on the save_stack.
1213 for parm_name in main_func_parm_list:
1214 # Get the parm_value if it was saved on the stack.
1215 try:
1216 parm_value = save_stack.pop(parm_name)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -05001217 except BaseException:
Michael Walshff340002017-08-29 11:18:27 -05001218 # If it was not saved, no further action is required.
1219 continue
1220
1221 # Restore the saved value.
Patrick Williams20f38712022-12-08 06:18:26 -06001222 cmd_buf = (
1223 'BuiltIn().set_global_variable("${' + parm_name + '}", parm_value)'
1224 )
Michael Walshff340002017-08-29 11:18:27 -05001225 gp.dpissuing(cmd_buf)
1226 exec(cmd_buf)
1227
1228 gp.dprintn(save_stack.sprint_obj())
1229
Michael Walsh6741f742017-02-20 16:16:38 -06001230
Michael Walshc9116812017-03-10 14:23:06 -06001231def test_teardown():
Michael Walshc9116812017-03-10 14:23:06 -06001232 r"""
1233 Clean up after this test case.
1234 """
1235
1236 gp.qprintn()
Michael Walshf75d4352019-12-05 17:01:20 -06001237 gp.qprint_executing()
1238
1239 if ga.psutil_imported:
1240 ga.terminate_descendants()
1241
Patrick Williams20f38712022-12-08 06:18:26 -06001242 cmd_buf = [
1243 "Print Error",
1244 "A keyword timeout occurred ending this program.\n",
1245 ]
Michael Walshc9116812017-03-10 14:23:06 -06001246 BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
1247
George Keishinga54e06f2020-06-12 10:42:41 -05001248 if redfish_supported:
1249 redfish.logout()
1250
Michael Walshc108e422019-03-28 12:27:18 -05001251 gp.qprint_pgm_footer()
Michael Walshb5839d02017-04-12 16:11:20 -05001252
Michael Walshc9116812017-03-10 14:23:06 -06001253
Michael Walsh89de14a2018-10-01 16:51:37 -05001254def post_stack():
1255 r"""
1256 Process post_stack plug-in programs.
1257 """
1258
1259 if not call_post_stack_plug:
1260 # The caller does not wish to have post_stack plug-in processing done.
1261 return
1262
1263 global boot_success
1264
1265 # NOTE: A post_stack call-point failure is NOT counted as a boot failure.
1266 pre_boot_plug_in_setup()
1267 # For the purposes of the following plug-ins, mark the "boot" as a success.
1268 boot_success = 1
1269 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001270 (
1271 rc,
1272 shell_rc,
1273 failed_plug_in_name,
1274 history,
1275 ) = grpi.rprocess_plug_in_packages(
1276 call_point="post_stack", stop_on_plug_in_failure=0, return_history=True
1277 )
Michael Walsh986d8ae2019-07-17 10:02:23 -05001278 for doing_msg in history:
1279 update_boot_history(boot_history, doing_msg, max_boot_history)
Michael Walsh815b1d52018-10-30 13:32:26 -05001280 if rc != 0:
1281 boot_success = 0
Michael Walsh89de14a2018-10-01 16:51:37 -05001282
1283 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001284 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1285 call_point="ffdc_check",
1286 shell_rc=dump_ffdc_rc(),
1287 stop_on_plug_in_failure=1,
1288 stop_on_non_zero_rc=1,
1289 )
Michael Walsh815b1d52018-10-30 13:32:26 -05001290 if shell_rc == dump_ffdc_rc():
Michael Walsh89de14a2018-10-01 16:51:37 -05001291 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
Patrick Williams20f38712022-12-08 06:18:26 -06001292 if status != "PASS":
Michael Walsh89de14a2018-10-01 16:51:37 -05001293 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walshc9bd2e82019-04-18 11:06:52 -05001294 # Leave a record for caller that "soft" errors occurred.
1295 soft_errors = 1
1296 gpu.save_plug_in_value(soft_errors, pgm_name)
Michael Walsh89de14a2018-10-01 16:51:37 -05001297
1298 plug_in_setup()
1299 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001300 call_point="stop_check", shell_rc=stop_test_rc(), stop_on_non_zero_rc=1
1301 )
Michael Walsh89de14a2018-10-01 16:51:37 -05001302 if shell_rc == stop_test_rc():
1303 message = "Stopping as requested by user.\n"
Michael Walsh80dddde2019-10-22 13:54:38 -05001304 gp.qprint_time(message)
Michael Walsh89de14a2018-10-01 16:51:37 -05001305 BuiltIn().fail(message)
1306
1307
Patrick Williams20f38712022-12-08 06:18:26 -06001308def obmc_boot_test_py(
1309 loc_boot_stack=None, loc_stack_mode=None, loc_quiet=None
1310):
Michael Walsh6741f742017-02-20 16:16:38 -06001311 r"""
1312 Do main program processing.
1313 """
1314
Michael Walshff340002017-08-29 11:18:27 -05001315 global save_stack
1316
Patrick Williams20f38712022-12-08 06:18:26 -06001317 ga.set_term_options(
1318 term_requests={"pgm_names": ["process_plug_in_packages.py"]}
1319 )
Michael Walshf75d4352019-12-05 17:01:20 -06001320
George Keishing36efbc02018-12-12 10:18:23 -06001321 gp.dprintn()
Michael Walshff340002017-08-29 11:18:27 -05001322 # Process function parms.
1323 for parm_name in main_func_parm_list:
1324 # Get parm's value.
George Keishing36efbc02018-12-12 10:18:23 -06001325 parm_value = eval("loc_" + parm_name)
1326 gp.dpvars(parm_name, parm_value)
Michael Walshff340002017-08-29 11:18:27 -05001327
George Keishing36efbc02018-12-12 10:18:23 -06001328 if parm_value is not None:
Michael Walshff340002017-08-29 11:18:27 -05001329 # Save the global value on a stack.
Patrick Williams20f38712022-12-08 06:18:26 -06001330 cmd_buf = (
1331 'save_stack.push(BuiltIn().get_variable_value("${'
1332 + parm_name
1333 + '}"), "'
1334 + parm_name
1335 + '")'
1336 )
Michael Walshff340002017-08-29 11:18:27 -05001337 gp.dpissuing(cmd_buf)
1338 exec(cmd_buf)
1339
1340 # Set the global value to the passed value.
Patrick Williams20f38712022-12-08 06:18:26 -06001341 cmd_buf = (
1342 'BuiltIn().set_global_variable("${'
1343 + parm_name
1344 + '}", loc_'
1345 + parm_name
1346 + ")"
1347 )
Michael Walshff340002017-08-29 11:18:27 -05001348 gp.dpissuing(cmd_buf)
1349 exec(cmd_buf)
1350
1351 gp.dprintn(save_stack.sprint_obj())
Michael Walshb5839d02017-04-12 16:11:20 -05001352
Michael Walsh6741f742017-02-20 16:16:38 -06001353 setup()
1354
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001355 init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
1356
Michael Walsha20da402017-03-31 16:27:45 -05001357 if ffdc_only:
1358 gp.qprint_timen("Caller requested ffdc_only.")
Michael Walsh986d8ae2019-07-17 10:02:23 -05001359 if do_pre_boot_plug_in_setup:
1360 pre_boot_plug_in_setup()
Michael Walsh83f4bc72017-04-20 16:49:43 -05001361 grk.run_key_u("my_ffdc")
Michael Walsh764d2f82017-04-27 16:01:08 -05001362 return
Michael Walsha20da402017-03-31 16:27:45 -05001363
Michael Walsh409ad352020-02-06 11:46:35 -06001364 if delete_errlogs:
Michael Shepos1a67b082020-08-28 16:01:58 -05001365 # print error logs before delete
George Keishing438fd3b2021-10-08 02:15:18 -05001366 if redfish_support_trans_state:
1367 status, error_logs = grk.run_key_u("Get Redfish Event Logs")
Patrick Williams20f38712022-12-08 06:18:26 -06001368 log.print_error_logs(
1369 error_logs, "AdditionalDataURI Message Severity"
1370 )
George Keishing438fd3b2021-10-08 02:15:18 -05001371 else:
1372 status, error_logs = grk.run_key_u("Get Error Logs")
1373 log.print_error_logs(error_logs, "AdditionalData Message Severity")
Michael Shepos1a67b082020-08-28 16:01:58 -05001374 pels = pel.peltool("-l", ignore_err=1)
Michael Shepos0e5f1132020-09-30 16:24:25 -05001375 gp.qprint_var(pels)
Michael Shepos1a67b082020-08-28 16:01:58 -05001376
Michael Walsh409ad352020-02-06 11:46:35 -06001377 # Delete errlogs prior to doing any boot tests.
1378 grk.run_key(delete_errlogs_cmd, ignore=1)
Michael Shepos92a54bf2020-11-11 11:48:55 -06001379 grk.run_key(delete_bmcdump_cmd, ignore=1)
George Keishing2ef6a7d2021-05-19 09:05:32 -05001380 if redfish_support_trans_state:
1381 grk.run_key(delete_sysdump_cmd, ignore=1)
Michael Walsh409ad352020-02-06 11:46:35 -06001382
Michael Walsh6741f742017-02-20 16:16:38 -06001383 # Process caller's boot_stack.
Patrick Williams20f38712022-12-08 06:18:26 -06001384 while len(boot_stack) > 0:
Michael Walsh6741f742017-02-20 16:16:38 -06001385 test_loop_body()
1386
Michael Walshb5839d02017-04-12 16:11:20 -05001387 gp.qprint_timen("Finished processing stack.")
Michael Walsh30dadae2017-02-27 14:25:52 -06001388
Michael Walsh89de14a2018-10-01 16:51:37 -05001389 post_stack()
1390
Michael Walsh6741f742017-02-20 16:16:38 -06001391 # Process caller's boot_list.
1392 if len(boot_list) > 0:
1393 for ix in range(1, max_num_tests + 1):
1394 test_loop_body()
1395
Michael Walshb5839d02017-04-12 16:11:20 -05001396 gp.qprint_timen("Completed all requested boot tests.")
1397
1398 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001399 new_fail = boot_fail - init_boot_fail
1400 if new_fail > boot_fail_threshold:
Patrick Williams20f38712022-12-08 06:18:26 -06001401 error_message = (
1402 "Boot failures exceed the boot failure"
1403 + " threshold:\n"
1404 + gp.sprint_var(new_fail)
1405 + gp.sprint_var(boot_fail_threshold)
1406 )
Michael Walshb5839d02017-04-12 16:11:20 -05001407 BuiltIn().fail(gp.sprint_error(error_message))