blob: 96d9a39639605d4c77da0de3d899d0ef56690ef4 [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)
Patrick Williams20f38712022-12-08 06:18:26 -060089redfish_delete_sessions = int(
90 BuiltIn().get_variable_value("${REDFISH_DELETE_SESSIONS}", default=1)
91)
Michael Walshe58df1c2019-08-07 09:57:43 -050092if redfish_supported:
Patrick Williams20f38712022-12-08 06:18:26 -060093 redfish = BuiltIn().get_library_instance("redfish")
Michael Walshe58df1c2019-08-07 09:57:43 -050094 default_power_on = "Redfish Power On"
95 default_power_off = "Redfish Power Off"
George Keishing870999a2021-03-31 23:43:57 -050096 if not redfish_support_trans_state:
Michael Sheposcc490b42020-08-26 12:53:01 -050097 delete_errlogs_cmd = "Delete Error Logs ${quiet}=${1}"
Michael Shepos92a54bf2020-11-11 11:48:55 -060098 delete_bmcdump_cmd = "Delete All BMC Dump"
George Keishingeb1fe352020-06-19 03:02:22 -050099 default_set_power_policy = "Set BMC Power Policy ALWAYS_POWER_OFF"
100 else:
101 delete_errlogs_cmd = "Redfish Purge Event Log"
Michael Shepos92a54bf2020-11-11 11:48:55 -0600102 delete_bmcdump_cmd = "Redfish Delete All BMC Dumps"
George Keishing2ef6a7d2021-05-19 09:05:32 -0500103 delete_sysdump_cmd = "Redfish Delete All System Dumps"
Patrick Williams20f38712022-12-08 06:18:26 -0600104 default_set_power_policy = (
105 "Redfish Set Power Restore Policy AlwaysOff"
106 )
Michael Walshe58df1c2019-08-07 09:57:43 -0500107else:
108 default_power_on = "REST Power On"
109 default_power_off = "REST Power Off"
Michael Sheposcc490b42020-08-26 12:53:01 -0500110 delete_errlogs_cmd = "Delete Error Logs ${quiet}=${1}"
Michael Shepos92a54bf2020-11-11 11:48:55 -0600111 delete_bmcdump_cmd = "Delete All BMC Dump"
George Keishinga54e06f2020-06-12 10:42:41 -0500112 default_set_power_policy = "Set BMC Power Policy ALWAYS_POWER_OFF"
Michael Walsh6741f742017-02-20 16:16:38 -0600113boot_count = 0
Michael Walsh0bbd8602016-11-22 11:31:49 -0600114
Michael Walsh85678942017-03-27 14:34:22 -0500115LOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
Patrick Williams20f38712022-12-08 06:18:26 -0600116AUTOBOOT_FFDC_PREFIX = os.environ.get("AUTOBOOT_FFDC_PREFIX", "")
Michael Walsh986d8ae2019-07-17 10:02:23 -0500117ffdc_prefix = AUTOBOOT_FFDC_PREFIX
Sunil M325eb542017-08-10 07:09:43 -0500118boot_start_time = ""
119boot_end_time = ""
Patrick Williams20f38712022-12-08 06:18:26 -0600120save_stack = vs.var_stack("save_stack")
121main_func_parm_list = ["boot_stack", "stack_mode", "quiet"]
Michael Walsh85678942017-03-27 14:34:22 -0500122
123
Michael Walsh89de14a2018-10-01 16:51:37 -0500124def dump_ffdc_rc():
125 r"""
126 Return the constant dump ffdc test return code value.
127
128 When a plug-in call point program returns this value, it indicates that
129 this program should collect FFDC.
130 """
131
132 return 0x00000200
133
134
135def stop_test_rc():
136 r"""
137 Return the constant stop test return code value.
138
139 When a plug-in call point program returns this value, it indicates that
140 this program should stop running.
141 """
142
143 return 0x00000200
144
145
Patrick Williams20f38712022-12-08 06:18:26 -0600146def process_host(host, host_var_name=""):
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500147 r"""
148 Process a host by getting the associated host name and IP address and
149 setting them in global variables.
150
151 If the caller does not pass the host_var_name, this function will try to
152 figure out the name of the variable used by the caller for the host parm.
153 Callers are advised to explicitly specify the host_var_name when calling
154 with an exec command. In such cases, the get_arg_name cannot figure out
155 the host variable name.
156
157 This function will then create similar global variable names by
158 removing "_host" and appending "_host_name" or "_ip" to the host variable
159 name.
160
161 Example:
162
163 If a call is made like this:
164 process_host(openbmc_host)
165
166 Global variables openbmc_host_name and openbmc_ip will be set.
167
168 Description of argument(s):
169 host A host name or IP. The name of the variable used should
170 have a suffix of "_host".
171 host_var_name The name of the variable being used as the host parm.
172 """
173
174 if host_var_name == "":
175 host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
176
177 host_name_var_name = re.sub("host", "host_name", host_var_name)
178 ip_var_name = re.sub("host", "ip", host_var_name)
Patrick Williams20f38712022-12-08 06:18:26 -0600179 cmd_buf = (
180 "global "
181 + host_name_var_name
182 + ", "
183 + ip_var_name
184 + " ; "
185 + host_name_var_name
186 + ", "
187 + ip_var_name
188 + " = gm.get_host_name_ip('"
189 + host
190 + "')"
191 )
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500192 exec(cmd_buf)
193
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500194
Michael Walshb5839d02017-04-12 16:11:20 -0500195def process_pgm_parms():
Michael Walshb5839d02017-04-12 16:11:20 -0500196 r"""
197 Process the program parameters by assigning them all to corresponding
198 globals. Also, set some global values that depend on program parameters.
199 """
200
201 # Program parameter processing.
202 # Assign all program parms to python variables which are global to this
203 # module.
204
205 global parm_list
206 parm_list = BuiltIn().get_variable_value("${parm_list}")
207 # The following subset of parms should be processed as integers.
Patrick Williams20f38712022-12-08 06:18:26 -0600208 int_list = [
209 "max_num_tests",
210 "boot_pass",
211 "boot_fail",
212 "ffdc_only",
213 "boot_fail_threshold",
214 "delete_errlogs",
215 "call_post_stack_plug",
216 "do_pre_boot_plug_in_setup",
217 "quiet",
218 "test_mode",
219 "debug",
220 ]
Michael Walshb5839d02017-04-12 16:11:20 -0500221 for parm in parm_list:
222 if parm in int_list:
Patrick Williams20f38712022-12-08 06:18:26 -0600223 sub_cmd = (
224 'int(BuiltIn().get_variable_value("${' + parm + '}", "0"))'
225 )
Michael Walshb5839d02017-04-12 16:11:20 -0500226 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600227 sub_cmd = 'BuiltIn().get_variable_value("${' + parm + '}")'
Michael Walshb5839d02017-04-12 16:11:20 -0500228 cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
Michael Walshff340002017-08-29 11:18:27 -0500229 gp.dpissuing(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500230 exec(cmd_buf)
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500231 if re.match(r".*_host$", parm):
232 cmd_buf = "process_host(" + parm + ", '" + parm + "')"
233 exec(cmd_buf)
234 if re.match(r".*_password$", parm):
235 # Register the value of any parm whose name ends in _password.
236 # This will cause the print functions to replace passwords with
237 # asterisks in the output.
238 cmd_buf = "gp.register_passwords(" + parm + ")"
239 exec(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500240
241 global ffdc_dir_path_style
242 global boot_list
243 global boot_stack
244 global boot_results_file_path
245 global boot_results
Michael Walsh986d8ae2019-07-17 10:02:23 -0500246 global boot_history
Michael Walshb5839d02017-04-12 16:11:20 -0500247 global ffdc_list_file_path
Michael Walshe0cf8d72017-05-17 13:20:46 -0500248 global ffdc_report_list_path
Michael Walsh600876d2017-05-30 17:58:58 -0500249 global ffdc_summary_list_path
Michael Walsha3e7b222020-02-03 15:32:16 -0600250 global boot_table
251 global valid_boot_types
Michael Walshb5839d02017-04-12 16:11:20 -0500252
253 if ffdc_dir_path_style == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600254 ffdc_dir_path_style = int(os.environ.get("FFDC_DIR_PATH_STYLE", "0"))
Michael Walshb5839d02017-04-12 16:11:20 -0500255
256 # Convert these program parms to lists for easier processing..
George Keishing36efbc02018-12-12 10:18:23 -0600257 boot_list = list(filter(None, boot_list.split(":")))
258 boot_stack = list(filter(None, boot_stack.split(":")))
Michael Walshb5839d02017-04-12 16:11:20 -0500259
Michael Walsha3e7b222020-02-03 15:32:16 -0600260 boot_table = create_boot_table(boot_table_path, os_host=os_host)
261 valid_boot_types = create_valid_boot_list(boot_table)
262
Michael Walsh903e0b22017-09-19 17:00:33 -0500263 cleanup_boot_results_file()
Patrick Williams20f38712022-12-08 06:18:26 -0600264 boot_results_file_path = create_boot_results_file_path(
265 pgm_name, openbmc_nickname, master_pid
266 )
Michael Walshb5839d02017-04-12 16:11:20 -0500267
268 if os.path.isfile(boot_results_file_path):
269 # We've been called before in this run so we'll load the saved
Michael Walsh986d8ae2019-07-17 10:02:23 -0500270 # boot_results and boot_history objects.
Patrick Williams20f38712022-12-08 06:18:26 -0600271 boot_results, boot_history = pickle.load(
272 open(boot_results_file_path, "rb")
273 )
Michael Walshb5839d02017-04-12 16:11:20 -0500274 else:
275 boot_results = boot_results(boot_table, boot_pass, boot_fail)
276
Patrick Williams20f38712022-12-08 06:18:26 -0600277 ffdc_list_file_path = (
278 base_tool_dir_path + openbmc_nickname + "/FFDC_FILE_LIST"
279 )
280 ffdc_report_list_path = (
281 base_tool_dir_path + openbmc_nickname + "/FFDC_REPORT_FILE_LIST"
282 )
Michael Walshb5839d02017-04-12 16:11:20 -0500283
Patrick Williams20f38712022-12-08 06:18:26 -0600284 ffdc_summary_list_path = (
285 base_tool_dir_path + openbmc_nickname + "/FFDC_SUMMARY_FILE_LIST"
286 )
Michael Walsh600876d2017-05-30 17:58:58 -0500287
Michael Walshb5839d02017-04-12 16:11:20 -0500288
Michael Walsh85678942017-03-27 14:34:22 -0500289def initial_plug_in_setup():
Michael Walsh85678942017-03-27 14:34:22 -0500290 r"""
291 Initialize all plug-in environment variables which do not change for the
292 duration of the program.
293
294 """
295
296 global LOG_LEVEL
297 BuiltIn().set_log_level("NONE")
298
299 BuiltIn().set_global_variable("${master_pid}", master_pid)
300 BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
301 BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
302 BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
Patrick Williams20f38712022-12-08 06:18:26 -0600303 BuiltIn().set_global_variable(
304 "${FFDC_LIST_FILE_PATH}", ffdc_list_file_path
305 )
306 BuiltIn().set_global_variable(
307 "${FFDC_REPORT_LIST_PATH}", ffdc_report_list_path
308 )
309 BuiltIn().set_global_variable(
310 "${FFDC_SUMMARY_LIST_PATH}", ffdc_summary_list_path
311 )
Michael Walsh85678942017-03-27 14:34:22 -0500312
Patrick Williams20f38712022-12-08 06:18:26 -0600313 BuiltIn().set_global_variable(
314 "${FFDC_DIR_PATH_STYLE}", ffdc_dir_path_style
315 )
316 BuiltIn().set_global_variable("${FFDC_CHECK}", ffdc_check)
Michael Walsh85678942017-03-27 14:34:22 -0500317
318 # For each program parameter, set the corresponding AUTOBOOT_ environment
319 # variable value. Also, set an AUTOBOOT_ environment variable for every
320 # element in additional_values.
Patrick Williams20f38712022-12-08 06:18:26 -0600321 additional_values = [
322 "program_pid",
323 "master_pid",
324 "ffdc_dir_path",
325 "status_dir_path",
326 "base_tool_dir_path",
327 "ffdc_list_file_path",
328 "ffdc_report_list_path",
329 "ffdc_summary_list_path",
330 "execdir",
331 "redfish_supported",
Patrick Williams20f38712022-12-08 06:18:26 -0600332 "redfish_support_trans_state",
333 ]
Michael Walsh85678942017-03-27 14:34:22 -0500334
335 plug_in_vars = parm_list + additional_values
336
337 for var_name in plug_in_vars:
338 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
339 var_name = var_name.upper()
340 if var_value is None:
341 var_value = ""
342 os.environ["AUTOBOOT_" + var_name] = str(var_value)
343
344 BuiltIn().set_log_level(LOG_LEVEL)
345
Michael Walsh68a61162017-04-25 11:54:06 -0500346 # Make sure the ffdc list directory exists.
347 ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
348 if not os.path.exists(ffdc_list_dir_path):
349 os.makedirs(ffdc_list_dir_path)
Michael Walsh85678942017-03-27 14:34:22 -0500350
Michael Walsh85678942017-03-27 14:34:22 -0500351
Michael Walsh0bbd8602016-11-22 11:31:49 -0600352def plug_in_setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600353 r"""
Michael Walsh85678942017-03-27 14:34:22 -0500354 Initialize all changing plug-in environment variables for use by the
355 plug-in programs.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600356 """
357
Michael Walsh85678942017-03-27 14:34:22 -0500358 global LOG_LEVEL
359 global test_really_running
360
361 BuiltIn().set_log_level("NONE")
362
Michael Walsh6741f742017-02-20 16:16:38 -0600363 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600364 if boot_pass > 1:
365 test_really_running = 1
366 else:
367 test_really_running = 0
368
Patrick Williams20f38712022-12-08 06:18:26 -0600369 BuiltIn().set_global_variable(
370 "${test_really_running}", test_really_running
371 )
Michael Walsh6741f742017-02-20 16:16:38 -0600372 BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
Michael Walsh6741f742017-02-20 16:16:38 -0600373 BuiltIn().set_global_variable("${boot_pass}", boot_pass)
374 BuiltIn().set_global_variable("${boot_fail}", boot_fail)
375 BuiltIn().set_global_variable("${boot_success}", boot_success)
376 BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
Sunil M325eb542017-08-10 07:09:43 -0500377 BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
378 BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
Michael Walsh4c9a6452016-12-13 16:03:11 -0600379
Michael Walsh0bbd8602016-11-22 11:31:49 -0600380 # For each program parameter, set the corresponding AUTOBOOT_ environment
381 # variable value. Also, set an AUTOBOOT_ environment variable for every
382 # element in additional_values.
Patrick Williams20f38712022-12-08 06:18:26 -0600383 additional_values = [
384 "boot_type_desc",
385 "boot_success",
386 "boot_pass",
387 "boot_fail",
388 "test_really_running",
389 "ffdc_prefix",
390 "boot_start_time",
391 "boot_end_time",
392 ]
Michael Walsh0bbd8602016-11-22 11:31:49 -0600393
Michael Walsh85678942017-03-27 14:34:22 -0500394 plug_in_vars = additional_values
Michael Walsh0bbd8602016-11-22 11:31:49 -0600395
396 for var_name in plug_in_vars:
397 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
398 var_name = var_name.upper()
399 if var_value is None:
400 var_value = ""
Michael Walsh6741f742017-02-20 16:16:38 -0600401 os.environ["AUTOBOOT_" + var_name] = str(var_value)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600402
Michael Walsh0bbd8602016-11-22 11:31:49 -0600403 if debug:
Patrick Williams20f38712022-12-08 06:18:26 -0600404 shell_rc, out_buf = gc.cmd_fnc_u(
405 "printenv | egrep AUTOBOOT_ | sort -u"
406 )
Michael Walsh0bbd8602016-11-22 11:31:49 -0600407
Michael Walsh85678942017-03-27 14:34:22 -0500408 BuiltIn().set_log_level(LOG_LEVEL)
409
Michael Walsh0bbd8602016-11-22 11:31:49 -0600410
Michael Walshe0cf8d72017-05-17 13:20:46 -0500411def pre_boot_plug_in_setup():
Michael Walshe0cf8d72017-05-17 13:20:46 -0500412 # Clear the ffdc_list_file_path file. Plug-ins may now write to it.
413 try:
414 os.remove(ffdc_list_file_path)
415 except OSError:
416 pass
417
418 # Clear the ffdc_report_list_path file. Plug-ins may now write to it.
419 try:
420 os.remove(ffdc_report_list_path)
421 except OSError:
422 pass
423
Michael Walsh600876d2017-05-30 17:58:58 -0500424 # Clear the ffdc_summary_list_path file. Plug-ins may now write to it.
425 try:
426 os.remove(ffdc_summary_list_path)
427 except OSError:
428 pass
429
Michael Walshe1974b92017-08-03 13:39:51 -0500430 global ffdc_prefix
431
432 seconds = time.time()
433 loc_time = time.localtime(seconds)
434 time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
435
436 ffdc_prefix = openbmc_nickname + "." + time_string
437
Michael Walshe0cf8d72017-05-17 13:20:46 -0500438
Patrick Williams20f38712022-12-08 06:18:26 -0600439def default_sigusr1(signal_number=0, frame=None):
Michael Walshf566fb12019-02-01 14:35:09 -0600440 r"""
441 Handle SIGUSR1 by doing nothing.
442
443 This function assists in debugging SIGUSR1 processing by printing messages
444 to stdout and to the log.html file.
445
446 Description of argument(s):
447 signal_number The signal number (should always be 10 for SIGUSR1).
448 frame The frame data.
449 """
450
Michael Walsh80dddde2019-10-22 13:54:38 -0500451 gp.qprintn()
452 gp.qprint_executing()
Michael Walshf566fb12019-02-01 14:35:09 -0600453 gp.lprint_executing()
454
455
456def set_default_siguser1():
457 r"""
458 Set the default_sigusr1 function to be the SIGUSR1 handler.
459 """
460
Michael Walsh80dddde2019-10-22 13:54:38 -0500461 gp.qprintn()
462 gp.qprint_executing()
Michael Walshf566fb12019-02-01 14:35:09 -0600463 gp.lprint_executing()
464 signal.signal(signal.SIGUSR1, default_sigusr1)
465
466
Michael Walsh6741f742017-02-20 16:16:38 -0600467def setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600468 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600469 Do general program setup tasks.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600470 """
471
Michael Walsh6741f742017-02-20 16:16:38 -0600472 global cp_setup_called
Michael Walsh81816742017-09-27 11:02:29 -0500473 global transitional_boot_selected
Michael Walsh0bbd8602016-11-22 11:31:49 -0600474
Michael Walshb5839d02017-04-12 16:11:20 -0500475 gp.qprintn()
476
George Keishinga54e06f2020-06-12 10:42:41 -0500477 if redfish_supported:
478 redfish.login()
479
Michael Walshf566fb12019-02-01 14:35:09 -0600480 set_default_siguser1()
Michael Walsh81816742017-09-27 11:02:29 -0500481 transitional_boot_selected = False
482
Michael Walsh83f4bc72017-04-20 16:49:43 -0500483 robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
484 repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
Michael Walshd061c042017-05-23 14:46:57 -0500485 # If we can't find process_plug_in_packages.py, ssh_pw or
486 # validate_plug_ins.py, then we don't have our repo bin in PATH.
Patrick Williams20f38712022-12-08 06:18:26 -0600487 shell_rc, out_buf = gc.cmd_fnc_u(
488 "which process_plug_in_packages.py" + " ssh_pw validate_plug_ins.py",
489 quiet=1,
490 print_output=0,
491 show_err=0,
492 )
Michael Walshb5839d02017-04-12 16:11:20 -0500493 if shell_rc != 0:
Patrick Williams20f38712022-12-08 06:18:26 -0600494 os.environ["PATH"] = repo_bin_path + ":" + os.environ.get("PATH", "")
Michael Walsh83f4bc72017-04-20 16:49:43 -0500495 # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
496 if robot_pgm_dir_path not in sys.path:
497 sys.path.append(robot_pgm_dir_path)
498 PYTHONPATH = os.environ.get("PYTHONPATH", "")
499 if PYTHONPATH == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600500 os.environ["PYTHONPATH"] = robot_pgm_dir_path
Michael Walsh83f4bc72017-04-20 16:49:43 -0500501 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600502 os.environ["PYTHONPATH"] = robot_pgm_dir_path + ":" + PYTHONPATH
Michael Walsh6741f742017-02-20 16:16:38 -0600503
504 validate_parms()
505
Michael Walshc108e422019-03-28 12:27:18 -0500506 gp.qprint_pgm_header()
Michael Walsh6741f742017-02-20 16:16:38 -0600507
George Keishingeae945b2021-12-13 11:05:04 -0600508 grk.run_key_u(default_set_power_policy, ignore=1)
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500509
Michael Walsh85678942017-03-27 14:34:22 -0500510 initial_plug_in_setup()
511
Michael Walsh6741f742017-02-20 16:16:38 -0600512 plug_in_setup()
513 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -0600514 call_point="setup"
515 )
Michael Walsh6741f742017-02-20 16:16:38 -0600516 if rc != 0:
517 error_message = "Plug-in setup failed.\n"
Michael Walshc108e422019-03-28 12:27:18 -0500518 gp.print_error_report(error_message)
Michael Walsh6741f742017-02-20 16:16:38 -0600519 BuiltIn().fail(error_message)
520 # Setting cp_setup_called lets our Teardown know that it needs to call
521 # the cleanup plug-in call point.
522 cp_setup_called = 1
523
524 # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
525 BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
Michael Walsh85678942017-03-27 14:34:22 -0500526 # FFDC_LOG_PATH is used by "FFDC" keyword.
527 BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
Michael Walsh6741f742017-02-20 16:16:38 -0600528
Michael Walshdc80d672017-05-09 12:58:32 -0500529 # Also printed by FFDC.
530 global host_name
531 global host_ip
532 host = socket.gethostname()
533 host_name, host_ip = gm.get_host_name_ip(host)
534
Michael Walsh986d8ae2019-07-17 10:02:23 -0500535 gp.dprint_var(boot_table)
Michael Walshb5839d02017-04-12 16:11:20 -0500536 gp.dprint_var(boot_lists)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600537
Michael Walsh0bbd8602016-11-22 11:31:49 -0600538
Michael Walsh6741f742017-02-20 16:16:38 -0600539def validate_parms():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600540 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600541 Validate all program parameters.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600542 """
543
Michael Walshb5839d02017-04-12 16:11:20 -0500544 process_pgm_parms()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600545
Michael Walshb5839d02017-04-12 16:11:20 -0500546 gp.qprintn()
547
548 global openbmc_model
Michael Walshf5ce38c2020-02-27 12:46:20 -0600549 if openbmc_model == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600550 status, ret_values = grk.run_key_u("Get BMC System Model", ignore=1)
George Keishingec2836d2022-01-19 12:05:54 -0600551 # Set the model to default "OPENBMC" if getting it from BMC fails.
Patrick Williams20f38712022-12-08 06:18:26 -0600552 if status == "FAIL":
553 openbmc_model = "OPENBMC"
George Keishingec2836d2022-01-19 12:05:54 -0600554 else:
555 openbmc_model = ret_values
Michael Walshf5ce38c2020-02-27 12:46:20 -0600556 BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
557 gv.set_exit_on_error(True)
Michael Walsh44cef252019-08-01 12:38:56 -0500558 gv.valid_value(openbmc_host)
559 gv.valid_value(openbmc_username)
560 gv.valid_value(openbmc_password)
561 gv.valid_value(rest_username)
562 gv.valid_value(rest_password)
563 gv.valid_value(ipmi_username)
564 gv.valid_value(ipmi_password)
Michael Walsh6741f742017-02-20 16:16:38 -0600565 if os_host != "":
Michael Walsh44cef252019-08-01 12:38:56 -0500566 gv.valid_value(os_username)
567 gv.valid_value(os_password)
Michael Walsh6741f742017-02-20 16:16:38 -0600568 if pdu_host != "":
Michael Walsh44cef252019-08-01 12:38:56 -0500569 gv.valid_value(pdu_username)
570 gv.valid_value(pdu_password)
571 gv.valid_integer(pdu_slot_no)
Michael Walsh6741f742017-02-20 16:16:38 -0600572 if openbmc_serial_host != "":
Michael Walsh44cef252019-08-01 12:38:56 -0500573 gv.valid_integer(openbmc_serial_port)
Michael Walsh44cef252019-08-01 12:38:56 -0500574 gv.valid_value(openbmc_model)
575 gv.valid_integer(max_num_tests)
576 gv.valid_integer(boot_pass)
577 gv.valid_integer(boot_fail)
Michael Walsh6741f742017-02-20 16:16:38 -0600578 plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
Patrick Williams20f38712022-12-08 06:18:26 -0600579 BuiltIn().set_global_variable(
580 "${plug_in_packages_list}", plug_in_packages_list
581 )
582 gv.valid_value(stack_mode, valid_values=["normal", "skip"])
Michael Walshf5ce38c2020-02-27 12:46:20 -0600583 gv.set_exit_on_error(False)
Michael Walsha20da402017-03-31 16:27:45 -0500584 if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
Patrick Williams20f38712022-12-08 06:18:26 -0600585 error_message = (
586 "You must provide either a value for either the"
587 + " boot_list or the boot_stack parm.\n"
588 )
Michael Walsh6741f742017-02-20 16:16:38 -0600589 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -0600590 valid_boot_list(boot_list, valid_boot_types)
591 valid_boot_list(boot_stack, valid_boot_types)
Patrick Williams20f38712022-12-08 06:18:26 -0600592 selected_PDU_boots = list(
593 set(boot_list + boot_stack) & set(boot_lists["PDU_reboot"])
594 )
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500595 if len(selected_PDU_boots) > 0 and pdu_host == "":
Patrick Williams20f38712022-12-08 06:18:26 -0600596 error_message = (
597 "You have selected the following boots which"
598 + " require a PDU host but no value for pdu_host:\n"
599 )
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500600 error_message += gp.sprint_var(selected_PDU_boots)
Michael Walsh986d8ae2019-07-17 10:02:23 -0500601 error_message += gp.sprint_var(pdu_host, fmt=gp.blank())
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500602 BuiltIn().fail(gp.sprint_error(error_message))
603
Michael Walsh6741f742017-02-20 16:16:38 -0600604 return
Michael Walsh0bbd8602016-11-22 11:31:49 -0600605
Michael Walsh0bbd8602016-11-22 11:31:49 -0600606
Michael Walsh6741f742017-02-20 16:16:38 -0600607def my_get_state():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600608 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600609 Get the system state plus a little bit of wrapping.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600610 """
611
Michael Walsh6741f742017-02-20 16:16:38 -0600612 global state
613
Patrick Williams20f38712022-12-08 06:18:26 -0600614 req_states = ["epoch_seconds"] + st.default_req_states
Michael Walsh6741f742017-02-20 16:16:38 -0600615
Michael Walshb5839d02017-04-12 16:11:20 -0500616 gp.qprint_timen("Getting system state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600617 if test_mode:
Patrick Williams20f38712022-12-08 06:18:26 -0600618 state["epoch_seconds"] = int(time.time())
Michael Walsh6741f742017-02-20 16:16:38 -0600619 else:
Michael Walshb5839d02017-04-12 16:11:20 -0500620 state = st.get_state(req_states=req_states, quiet=quiet)
621 gp.qprint_var(state)
Michael Walsh341c21e2017-01-17 16:25:20 -0600622
Michael Walsh341c21e2017-01-17 16:25:20 -0600623
Michael Walsh45ca6e42017-09-14 17:29:12 -0500624def valid_state():
Michael Walsh45ca6e42017-09-14 17:29:12 -0500625 r"""
626 Verify that our state dictionary contains no blank values. If we don't get
627 valid state data, we cannot continue to work.
628 """
629
Patrick Williams20f38712022-12-08 06:18:26 -0600630 if st.compare_states(state, st.invalid_state_match, "or"):
631 error_message = (
632 "The state dictionary contains blank fields which"
633 + " is illegal.\n"
634 + gp.sprint_var(state)
635 )
Michael Walsh45ca6e42017-09-14 17:29:12 -0500636 BuiltIn().fail(gp.sprint_error(error_message))
637
Michael Walsh45ca6e42017-09-14 17:29:12 -0500638
Michael Walsh6741f742017-02-20 16:16:38 -0600639def select_boot():
Michael Walsh341c21e2017-01-17 16:25:20 -0600640 r"""
641 Select a boot test to be run based on our current state and return the
642 chosen boot type.
643
644 Description of arguments:
Michael Walsh6741f742017-02-20 16:16:38 -0600645 state The state of the machine.
Michael Walsh341c21e2017-01-17 16:25:20 -0600646 """
647
Michael Walsh81816742017-09-27 11:02:29 -0500648 global transitional_boot_selected
Michael Walsh30dadae2017-02-27 14:25:52 -0600649 global boot_stack
650
Michael Walshb5839d02017-04-12 16:11:20 -0500651 gp.qprint_timen("Selecting a boot test.")
Michael Walsh6741f742017-02-20 16:16:38 -0600652
Michael Walsh81816742017-09-27 11:02:29 -0500653 if transitional_boot_selected and not boot_success:
654 prior_boot = next_boot
655 boot_candidate = boot_stack.pop()
Patrick Williams20f38712022-12-08 06:18:26 -0600656 gp.qprint_timen(
657 "The prior '"
658 + next_boot
659 + "' was chosen to"
660 + " transition to a valid state for '"
661 + boot_candidate
662 + "' which was at the top of the boot_stack. Since"
663 + " the '"
664 + next_boot
665 + "' failed, the '"
666 + boot_candidate
667 + "' has been removed from the stack"
668 + " to avoid and endless failure loop."
669 )
Michael Walsh81816742017-09-27 11:02:29 -0500670 if len(boot_stack) == 0:
671 return ""
672
Michael Walsh6741f742017-02-20 16:16:38 -0600673 my_get_state()
Michael Walsh45ca6e42017-09-14 17:29:12 -0500674 valid_state()
Michael Walsh6741f742017-02-20 16:16:38 -0600675
Michael Walsh81816742017-09-27 11:02:29 -0500676 transitional_boot_selected = False
Michael Walsh6741f742017-02-20 16:16:38 -0600677 stack_popped = 0
678 if len(boot_stack) > 0:
679 stack_popped = 1
Michael Walshb5839d02017-04-12 16:11:20 -0500680 gp.qprint_dashes()
681 gp.qprint_var(boot_stack)
682 gp.qprint_dashes()
683 skip_boot_printed = 0
684 while len(boot_stack) > 0:
685 boot_candidate = boot_stack.pop()
Patrick Williams20f38712022-12-08 06:18:26 -0600686 if stack_mode == "normal":
Michael Walshb5839d02017-04-12 16:11:20 -0500687 break
688 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600689 if st.compare_states(state, boot_table[boot_candidate]["end"]):
Michael Walshb5839d02017-04-12 16:11:20 -0500690 if not skip_boot_printed:
Michael Walshff340002017-08-29 11:18:27 -0500691 gp.qprint_var(stack_mode)
692 gp.qprintn()
Patrick Williams20f38712022-12-08 06:18:26 -0600693 gp.qprint_timen(
694 "Skipping the following boot tests"
695 + " which are unnecessary since their"
696 + " required end states match the"
697 + " current machine state:"
698 )
Michael Walshb5839d02017-04-12 16:11:20 -0500699 skip_boot_printed = 1
Michael Walshff340002017-08-29 11:18:27 -0500700 gp.qprint_var(boot_candidate)
Michael Walshb5839d02017-04-12 16:11:20 -0500701 boot_candidate = ""
702 if boot_candidate == "":
703 gp.qprint_dashes()
704 gp.qprint_var(boot_stack)
705 gp.qprint_dashes()
706 return boot_candidate
Patrick Williams20f38712022-12-08 06:18:26 -0600707 if st.compare_states(state, boot_table[boot_candidate]["start"]):
708 gp.qprint_timen(
709 "The machine state is valid for a '"
710 + boot_candidate
711 + "' boot test."
712 )
Michael Walshb5839d02017-04-12 16:11:20 -0500713 gp.qprint_dashes()
714 gp.qprint_var(boot_stack)
715 gp.qprint_dashes()
Michael Walsh6741f742017-02-20 16:16:38 -0600716 return boot_candidate
Michael Walsh341c21e2017-01-17 16:25:20 -0600717 else:
Patrick Williams20f38712022-12-08 06:18:26 -0600718 gp.qprint_timen(
719 "The machine state does not match the required"
720 + " starting state for a '"
721 + boot_candidate
722 + "' boot test:"
723 )
724 gp.qprint_varx(
725 "boot_table_start_entry", boot_table[boot_candidate]["start"]
726 )
Michael Walsh6741f742017-02-20 16:16:38 -0600727 boot_stack.append(boot_candidate)
Michael Walsh81816742017-09-27 11:02:29 -0500728 transitional_boot_selected = True
Michael Walsh6741f742017-02-20 16:16:38 -0600729 popped_boot = boot_candidate
730
731 # Loop through your list selecting a boot_candidates
732 boot_candidates = []
733 for boot_candidate in boot_list:
Patrick Williams20f38712022-12-08 06:18:26 -0600734 if st.compare_states(state, boot_table[boot_candidate]["start"]):
Michael Walsh6741f742017-02-20 16:16:38 -0600735 if stack_popped:
Patrick Williams20f38712022-12-08 06:18:26 -0600736 if st.compare_states(
737 boot_table[boot_candidate]["end"],
738 boot_table[popped_boot]["start"],
739 ):
Michael Walsh6741f742017-02-20 16:16:38 -0600740 boot_candidates.append(boot_candidate)
741 else:
742 boot_candidates.append(boot_candidate)
743
744 if len(boot_candidates) == 0:
Patrick Williams20f38712022-12-08 06:18:26 -0600745 gp.qprint_timen(
746 "The user's boot list contained no boot tests"
747 + " which are valid for the current machine state."
748 )
Michael Walsh6741f742017-02-20 16:16:38 -0600749 boot_candidate = default_power_on
Patrick Williams20f38712022-12-08 06:18:26 -0600750 if not st.compare_states(state, boot_table[default_power_on]["start"]):
Michael Walsh6741f742017-02-20 16:16:38 -0600751 boot_candidate = default_power_off
752 boot_candidates.append(boot_candidate)
Patrick Williams20f38712022-12-08 06:18:26 -0600753 gp.qprint_timen(
754 "Using default '"
755 + boot_candidate
756 + "' boot type to transition to valid state."
757 )
Michael Walsh6741f742017-02-20 16:16:38 -0600758
Michael Walshb5839d02017-04-12 16:11:20 -0500759 gp.dprint_var(boot_candidates)
Michael Walsh6741f742017-02-20 16:16:38 -0600760
761 # Randomly select a boot from the candidate list.
762 boot = random.choice(boot_candidates)
Michael Walsh341c21e2017-01-17 16:25:20 -0600763
764 return boot
Michael Walsh0bbd8602016-11-22 11:31:49 -0600765
Michael Walsh55302292017-01-10 11:43:02 -0600766
Michael Walshb2e53ec2017-10-30 15:04:36 -0500767def print_defect_report(ffdc_file_list):
Michael Walsh341c21e2017-01-17 16:25:20 -0600768 r"""
769 Print a defect report.
Michael Walshb2e53ec2017-10-30 15:04:36 -0500770
771 Description of argument(s):
772 ffdc_file_list A list of files which were collected by our ffdc functions.
Michael Walsh341c21e2017-01-17 16:25:20 -0600773 """
774
Michael Walsh600876d2017-05-30 17:58:58 -0500775 # Making deliberate choice to NOT run plug_in_setup(). We don't want
776 # ffdc_prefix updated.
777 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -0600778 call_point="ffdc_report", stop_on_plug_in_failure=0
779 )
Michael Walsh600876d2017-05-30 17:58:58 -0500780
Michael Walshe0cf8d72017-05-17 13:20:46 -0500781 # Get additional header data which may have been created by ffdc plug-ins.
782 # Also, delete the individual header files to cleanup.
Patrick Williams20f38712022-12-08 06:18:26 -0600783 cmd_buf = (
784 "file_list=$(cat "
785 + ffdc_report_list_path
786 + " 2>/dev/null)"
787 + ' ; [ ! -z "${file_list}" ] && cat ${file_list}'
788 + " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
789 )
790 shell_rc, more_header_info = gc.cmd_fnc_u(
791 cmd_buf, print_output=0, show_err=0
792 )
Michael Walshe0cf8d72017-05-17 13:20:46 -0500793
Michael Walshb2e53ec2017-10-30 15:04:36 -0500794 # Get additional summary data which may have been created by ffdc plug-ins.
Michael Walsh600876d2017-05-30 17:58:58 -0500795 # Also, delete the individual header files to cleanup.
Patrick Williams20f38712022-12-08 06:18:26 -0600796 cmd_buf = (
797 "file_list=$(cat "
798 + ffdc_summary_list_path
799 + " 2>/dev/null)"
800 + ' ; [ ! -z "${file_list}" ] && cat ${file_list}'
801 + " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
802 )
803 shell_rc, ffdc_summary_info = gc.cmd_fnc_u(
804 cmd_buf, print_output=0, show_err=0
805 )
Michael Walsh600876d2017-05-30 17:58:58 -0500806
Michael Walshb2e53ec2017-10-30 15:04:36 -0500807 # ffdc_list_file_path contains a list of any ffdc files created by plug-
808 # ins, etc. Read that data into a list.
Michael Walsh341c21e2017-01-17 16:25:20 -0600809 try:
Patrick Williams20f38712022-12-08 06:18:26 -0600810 plug_in_ffdc_list = (
811 open(ffdc_list_file_path, "r").read().rstrip("\n").split("\n")
812 )
George Keishing36efbc02018-12-12 10:18:23 -0600813 plug_in_ffdc_list = list(filter(None, plug_in_ffdc_list))
Michael Walsh341c21e2017-01-17 16:25:20 -0600814 except IOError:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500815 plug_in_ffdc_list = []
816
817 # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
818 # in. Eliminate duplicates and sort the list.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500819 ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
Michael Walshb2e53ec2017-10-30 15:04:36 -0500820
821 if status_file_path != "":
822 ffdc_file_list.insert(0, status_file_path)
823
824 # Convert the list to a printable list.
825 printable_ffdc_file_list = "\n".join(ffdc_file_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600826
Michael Walsh68a61162017-04-25 11:54:06 -0500827 # Open ffdc_file_list for writing. We will write a complete list of
828 # FFDC files to it for possible use by plug-ins like cp_stop_check.
Patrick Williams20f38712022-12-08 06:18:26 -0600829 ffdc_list_file = open(ffdc_list_file_path, "w")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500830 ffdc_list_file.write(printable_ffdc_file_list + "\n")
831 ffdc_list_file.close()
832
833 indent = 0
834 width = 90
835 linefeed = 1
836 char = "="
Michael Walsh68a61162017-04-25 11:54:06 -0500837
838 gp.qprintn()
Michael Walshb2e53ec2017-10-30 15:04:36 -0500839 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500840 gp.qprintn("Copy this data to the defect:\n")
841
Michael Walshe0cf8d72017-05-17 13:20:46 -0500842 if len(more_header_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500843 gp.qprintn(more_header_info)
Patrick Williams20f38712022-12-08 06:18:26 -0600844 gp.qpvars(
845 host_name,
846 host_ip,
847 openbmc_nickname,
848 openbmc_host,
849 openbmc_host_name,
850 openbmc_ip,
851 openbmc_username,
852 openbmc_password,
853 rest_username,
854 rest_password,
855 ipmi_username,
856 ipmi_password,
857 os_host,
858 os_host_name,
859 os_ip,
860 os_username,
861 os_password,
862 pdu_host,
863 pdu_host_name,
864 pdu_ip,
865 pdu_username,
866 pdu_password,
867 pdu_slot_no,
868 openbmc_serial_host,
869 openbmc_serial_host_name,
870 openbmc_serial_ip,
871 openbmc_serial_port,
872 )
Michael Walsh68a61162017-04-25 11:54:06 -0500873
874 gp.qprintn()
Michael Walsh986d8ae2019-07-17 10:02:23 -0500875 print_boot_history(boot_history)
Michael Walsh68a61162017-04-25 11:54:06 -0500876 gp.qprintn()
877 gp.qprint_var(state)
Michael Walshb5839d02017-04-12 16:11:20 -0500878 gp.qprintn()
879 gp.qprintn("FFDC data files:")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500880 gp.qprintn(printable_ffdc_file_list)
Michael Walshb5839d02017-04-12 16:11:20 -0500881 gp.qprintn()
Michael Walsh341c21e2017-01-17 16:25:20 -0600882
Michael Walsh600876d2017-05-30 17:58:58 -0500883 if len(ffdc_summary_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500884 gp.qprintn(ffdc_summary_info)
Michael Walsh600876d2017-05-30 17:58:58 -0500885
Michael Walshb2e53ec2017-10-30 15:04:36 -0500886 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500887
Michael Walsh6741f742017-02-20 16:16:38 -0600888
Michael Walsh6741f742017-02-20 16:16:38 -0600889def my_ffdc():
Michael Walsh6741f742017-02-20 16:16:38 -0600890 r"""
891 Collect FFDC data.
892 """
893
894 global state
895
896 plug_in_setup()
897 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -0600898 call_point="ffdc", stop_on_plug_in_failure=0
899 )
Michael Walsh6741f742017-02-20 16:16:38 -0600900
Patrick Williams20f38712022-12-08 06:18:26 -0600901 AUTOBOOT_FFDC_PREFIX = os.environ["AUTOBOOT_FFDC_PREFIX"]
902 status, ffdc_file_list = grk.run_key_u(
903 "FFDC ffdc_prefix="
904 + AUTOBOOT_FFDC_PREFIX
905 + " ffdc_function_list="
906 + ffdc_function_list,
907 ignore=1,
908 )
909 if status != "PASS":
Michael Walshff340002017-08-29 11:18:27 -0500910 gp.qprint_error("Call to ffdc failed.\n")
Michael Walshc9bd2e82019-04-18 11:06:52 -0500911 if type(ffdc_file_list) is not list:
912 ffdc_file_list = []
913 # Leave a record for caller that "soft" errors occurred.
914 soft_errors = 1
915 gpu.save_plug_in_value(soft_errors, pgm_name)
Michael Walsh6741f742017-02-20 16:16:38 -0600916
917 my_get_state()
918
Michael Walshb2e53ec2017-10-30 15:04:36 -0500919 print_defect_report(ffdc_file_list)
Michael Walsh6741f742017-02-20 16:16:38 -0600920
Michael Walsh6741f742017-02-20 16:16:38 -0600921
Michael Walsh6741f742017-02-20 16:16:38 -0600922def print_test_start_message(boot_keyword):
Michael Walsh6741f742017-02-20 16:16:38 -0600923 r"""
924 Print a message indicating what boot test is about to run.
925
926 Description of arguments:
927 boot_keyword The name of the boot which is to be run
928 (e.g. "BMC Power On").
929 """
930
Michael Walsh986d8ae2019-07-17 10:02:23 -0500931 global boot_history
Sunil M325eb542017-08-10 07:09:43 -0500932 global boot_start_time
Michael Walsh6741f742017-02-20 16:16:38 -0600933
Patrick Williams20f38712022-12-08 06:18:26 -0600934 doing_msg = gp.sprint_timen('Doing "' + boot_keyword + '".')
Sunil M325eb542017-08-10 07:09:43 -0500935
936 # Set boot_start_time for use by plug-ins.
937 boot_start_time = doing_msg[1:33]
938 gp.qprint_var(boot_start_time)
939
Michael Walshb5839d02017-04-12 16:11:20 -0500940 gp.qprint(doing_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600941
Michael Walsh986d8ae2019-07-17 10:02:23 -0500942 update_boot_history(boot_history, doing_msg, max_boot_history)
Michael Walsh6741f742017-02-20 16:16:38 -0600943
Michael Walsh6741f742017-02-20 16:16:38 -0600944
Patrick Williams20f38712022-12-08 06:18:26 -0600945def stop_boot_test(signal_number=0, frame=None):
Michael Walshf566fb12019-02-01 14:35:09 -0600946 r"""
947 Handle SIGUSR1 by aborting the boot test that is running.
948
949 Description of argument(s):
950 signal_number The signal number (should always be 10 for SIGUSR1).
951 frame The frame data.
952 """
953
Michael Walsh80dddde2019-10-22 13:54:38 -0500954 gp.qprintn()
955 gp.qprint_executing()
Michael Walshf566fb12019-02-01 14:35:09 -0600956 gp.lprint_executing()
957
958 # Restore original sigusr1 handler.
959 set_default_siguser1()
960
961 message = "The caller has asked that the boot test be stopped and marked"
962 message += " as a failure."
963
964 function_stack = gm.get_function_stack()
965 if "wait_state" in function_stack:
Michael Walshc44aa532019-06-14 13:33:29 -0500966 st.set_exit_wait_early_message(message)
Michael Walshf566fb12019-02-01 14:35:09 -0600967 else:
968 BuiltIn().fail(gp.sprint_error(message))
969
970
Michael Walsh6741f742017-02-20 16:16:38 -0600971def run_boot(boot):
Michael Walsh6741f742017-02-20 16:16:38 -0600972 r"""
973 Run the specified boot.
974
975 Description of arguments:
976 boot The name of the boot test to be performed.
977 """
978
979 global state
980
Michael Walshf566fb12019-02-01 14:35:09 -0600981 signal.signal(signal.SIGUSR1, stop_boot_test)
982 gp.qprint_timen("stop_boot_test is armed.")
983
Michael Walsh6741f742017-02-20 16:16:38 -0600984 print_test_start_message(boot)
985
986 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -0600987 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
988 call_point="pre_boot"
989 )
Michael Walsh6741f742017-02-20 16:16:38 -0600990 if rc != 0:
Patrick Williams20f38712022-12-08 06:18:26 -0600991 error_message = (
992 "Plug-in failed with non-zero return code.\n"
993 + gp.sprint_var(rc, fmt=gp.hexa())
994 )
Michael Walshf566fb12019-02-01 14:35:09 -0600995 set_default_siguser1()
Michael Walsh6741f742017-02-20 16:16:38 -0600996 BuiltIn().fail(gp.sprint_error(error_message))
997
998 if test_mode:
999 # In test mode, we'll pretend the boot worked by assigning its
1000 # required end state to the default state value.
Patrick Williams20f38712022-12-08 06:18:26 -06001001 state = st.strip_anchor_state(boot_table[boot]["end"])
Michael Walsh6741f742017-02-20 16:16:38 -06001002 else:
1003 # Assertion: We trust that the state data was made fresh by the
1004 # caller.
1005
Michael Walshb5839d02017-04-12 16:11:20 -05001006 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -06001007
Patrick Williams20f38712022-12-08 06:18:26 -06001008 if boot_table[boot]["method_type"] == "keyword":
1009 rk.my_run_keywords(
1010 boot_table[boot].get("lib_file_path", ""),
1011 boot_table[boot]["method"],
1012 quiet=quiet,
1013 )
Michael Walsh6741f742017-02-20 16:16:38 -06001014
Patrick Williams20f38712022-12-08 06:18:26 -06001015 if boot_table[boot]["bmc_reboot"]:
1016 st.wait_for_comm_cycle(int(state["epoch_seconds"]))
Michael Walsh30dadae2017-02-27 14:25:52 -06001017 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001018 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1019 call_point="post_reboot"
1020 )
Michael Walsh30dadae2017-02-27 14:25:52 -06001021 if rc != 0:
Michael Walsh0b93fbf2017-03-02 14:42:41 -06001022 error_message = "Plug-in failed with non-zero return code.\n"
Michael Walsh986d8ae2019-07-17 10:02:23 -05001023 error_message += gp.sprint_var(rc, fmt=gp.hexa())
Michael Walshf566fb12019-02-01 14:35:09 -06001024 set_default_siguser1()
Michael Walsh30dadae2017-02-27 14:25:52 -06001025 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -06001026 else:
1027 match_state = st.anchor_state(state)
Patrick Williams20f38712022-12-08 06:18:26 -06001028 del match_state["epoch_seconds"]
Michael Walsh6741f742017-02-20 16:16:38 -06001029 # Wait for the state to change in any way.
Patrick Williams20f38712022-12-08 06:18:26 -06001030 st.wait_state(
1031 match_state,
1032 wait_time=state_change_timeout,
1033 interval="10 seconds",
1034 invert=1,
1035 )
Michael Walsh6741f742017-02-20 16:16:38 -06001036
Michael Walshb5839d02017-04-12 16:11:20 -05001037 gp.qprintn()
Patrick Williams20f38712022-12-08 06:18:26 -06001038 if boot_table[boot]["end"]["chassis"] == "Off":
Michael Walsh6741f742017-02-20 16:16:38 -06001039 boot_timeout = power_off_timeout
1040 else:
1041 boot_timeout = power_on_timeout
Patrick Williams20f38712022-12-08 06:18:26 -06001042 st.wait_state(
1043 boot_table[boot]["end"],
1044 wait_time=boot_timeout,
1045 interval="10 seconds",
1046 )
Michael Walsh6741f742017-02-20 16:16:38 -06001047
1048 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001049 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1050 call_point="post_boot"
1051 )
Michael Walsh6741f742017-02-20 16:16:38 -06001052 if rc != 0:
Patrick Williams20f38712022-12-08 06:18:26 -06001053 error_message = (
1054 "Plug-in failed with non-zero return code.\n"
1055 + gp.sprint_var(rc, fmt=gp.hexa())
1056 )
Michael Walshf566fb12019-02-01 14:35:09 -06001057 set_default_siguser1()
Michael Walsh6741f742017-02-20 16:16:38 -06001058 BuiltIn().fail(gp.sprint_error(error_message))
1059
Michael Walshf566fb12019-02-01 14:35:09 -06001060 # Restore original sigusr1 handler.
1061 set_default_siguser1()
1062
Michael Walsh6741f742017-02-20 16:16:38 -06001063
Michael Walsh6741f742017-02-20 16:16:38 -06001064def test_loop_body():
Michael Walsh6741f742017-02-20 16:16:38 -06001065 r"""
1066 The main loop body for the loop in main_py.
1067
1068 Description of arguments:
1069 boot_count The iteration number (starts at 1).
1070 """
1071
1072 global boot_count
1073 global state
1074 global next_boot
1075 global boot_success
Sunil M325eb542017-08-10 07:09:43 -05001076 global boot_end_time
Michael Walsh6741f742017-02-20 16:16:38 -06001077
Yi Hu02d32762024-03-07 14:34:34 -08001078 # The flag can be enabled or disabled on the go
1079 redfish_delete_sessions = int(
1080 BuiltIn().get_variable_value("${REDFISH_DELETE_SESSIONS}", default=1)
1081 )
1082
Michael Walshb5839d02017-04-12 16:11:20 -05001083 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -06001084
1085 next_boot = select_boot()
Michael Walshb5839d02017-04-12 16:11:20 -05001086 if next_boot == "":
1087 return True
Michael Walsh6741f742017-02-20 16:16:38 -06001088
Michael Walshb5839d02017-04-12 16:11:20 -05001089 boot_count += 1
1090 gp.qprint_timen("Starting boot " + str(boot_count) + ".")
Michael Walsh6741f742017-02-20 16:16:38 -06001091
Michael Walshe0cf8d72017-05-17 13:20:46 -05001092 pre_boot_plug_in_setup()
Michael Walsh6741f742017-02-20 16:16:38 -06001093
1094 cmd_buf = ["run_boot", next_boot]
1095 boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
1096 if boot_status == "FAIL":
Michael Walshb5839d02017-04-12 16:11:20 -05001097 gp.qprint(msg)
Michael Walsh6741f742017-02-20 16:16:38 -06001098
Michael Walshb5839d02017-04-12 16:11:20 -05001099 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -06001100 if boot_status == "PASS":
1101 boot_success = 1
Patrick Williams20f38712022-12-08 06:18:26 -06001102 completion_msg = gp.sprint_timen(
1103 'BOOT_SUCCESS: "' + next_boot + '" succeeded.'
1104 )
Michael Walsh6741f742017-02-20 16:16:38 -06001105 else:
1106 boot_success = 0
Patrick Williams20f38712022-12-08 06:18:26 -06001107 completion_msg = gp.sprint_timen(
1108 'BOOT_FAILED: "' + next_boot + '" failed.'
1109 )
Sunil M325eb542017-08-10 07:09:43 -05001110
1111 # Set boot_end_time for use by plug-ins.
1112 boot_end_time = completion_msg[1:33]
1113 gp.qprint_var(boot_end_time)
1114
1115 gp.qprint(completion_msg)
Michael Walsh6741f742017-02-20 16:16:38 -06001116
1117 boot_results.update(next_boot, boot_status)
1118
1119 plug_in_setup()
1120 # NOTE: A post_test_case call point failure is NOT counted as a boot
1121 # failure.
1122 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001123 call_point="post_test_case", stop_on_plug_in_failure=0
1124 )
Michael Walsh6741f742017-02-20 16:16:38 -06001125
1126 plug_in_setup()
1127 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001128 call_point="ffdc_check",
1129 shell_rc=dump_ffdc_rc(),
1130 stop_on_plug_in_failure=1,
1131 stop_on_non_zero_rc=1,
1132 )
1133 if ffdc_check == "All" or shell_rc == dump_ffdc_rc():
Michael Walsh83f4bc72017-04-20 16:49:43 -05001134 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
Patrick Williams20f38712022-12-08 06:18:26 -06001135 if status != "PASS":
Michael Walshff340002017-08-29 11:18:27 -05001136 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walshc9bd2e82019-04-18 11:06:52 -05001137 # Leave a record for caller that "soft" errors occurred.
1138 soft_errors = 1
1139 gpu.save_plug_in_value(soft_errors, pgm_name)
Michael Walsh6741f742017-02-20 16:16:38 -06001140
Michael Walshaabef1e2017-09-20 15:16:17 -05001141 if delete_errlogs:
Michael Shepos1a67b082020-08-28 16:01:58 -05001142 # print error logs before delete
George Keishing438fd3b2021-10-08 02:15:18 -05001143 if redfish_support_trans_state:
1144 status, error_logs = grk.run_key_u("Get Redfish Event Logs")
Patrick Williams20f38712022-12-08 06:18:26 -06001145 log.print_error_logs(
1146 error_logs, "AdditionalDataURI Message Severity"
1147 )
George Keishing438fd3b2021-10-08 02:15:18 -05001148 else:
1149 status, error_logs = grk.run_key_u("Get Error Logs")
1150 log.print_error_logs(error_logs, "AdditionalData Message Severity")
Michael Shepos1a67b082020-08-28 16:01:58 -05001151 pels = pel.peltool("-l", ignore_err=1)
Michael Shepos0e5f1132020-09-30 16:24:25 -05001152 gp.qprint_var(pels)
Michael Shepos1a67b082020-08-28 16:01:58 -05001153
Michael Walshaabef1e2017-09-20 15:16:17 -05001154 # We need to purge error logs between boots or they build up.
Michael Walsh409ad352020-02-06 11:46:35 -06001155 grk.run_key(delete_errlogs_cmd, ignore=1)
Michael Shepos92a54bf2020-11-11 11:48:55 -06001156 grk.run_key(delete_bmcdump_cmd, ignore=1)
George Keishing2ef6a7d2021-05-19 09:05:32 -05001157 if redfish_support_trans_state:
1158 grk.run_key(delete_sysdump_cmd, ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -05001159
Michael Walsh952f9b02017-03-09 13:11:14 -06001160 boot_results.print_report()
Michael Walshb5839d02017-04-12 16:11:20 -05001161 gp.qprint_timen("Finished boot " + str(boot_count) + ".")
Michael Walsh952f9b02017-03-09 13:11:14 -06001162
Michael Walsh6741f742017-02-20 16:16:38 -06001163 plug_in_setup()
1164 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001165 call_point="stop_check", shell_rc=stop_test_rc(), stop_on_non_zero_rc=1
1166 )
Michael Walsh89de14a2018-10-01 16:51:37 -05001167 if shell_rc == stop_test_rc():
Michael Walsh3ba8ecd2018-04-24 11:33:25 -05001168 message = "Stopping as requested by user.\n"
Michael Walsh80dddde2019-10-22 13:54:38 -05001169 gp.qprint_time(message)
Michael Walsh3ba8ecd2018-04-24 11:33:25 -05001170 BuiltIn().fail(message)
Michael Walsh6741f742017-02-20 16:16:38 -06001171
Michael Walshd139f282017-04-04 18:00:23 -05001172 # This should help prevent ConnectionErrors.
George Keishing4d65c862020-12-03 06:52:11 -06001173 # Purge all redfish and REST connection sessions.
George Keishingd86e45c2021-03-19 07:38:14 -05001174 if redfish_delete_sessions:
1175 grk.run_key_u("Close All Connections", ignore=1)
1176 grk.run_key_u("Delete All Redfish Sessions", ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -05001177
Michael Walsh6741f742017-02-20 16:16:38 -06001178 return True
1179
Michael Walsh6741f742017-02-20 16:16:38 -06001180
Michael Walsh83f4bc72017-04-20 16:49:43 -05001181def obmc_boot_test_teardown():
Michael Walsh6741f742017-02-20 16:16:38 -06001182 r"""
Michael Walshf75d4352019-12-05 17:01:20 -06001183 Clean up after the main keyword.
Michael Walsh6741f742017-02-20 16:16:38 -06001184 """
Michael Walshf75d4352019-12-05 17:01:20 -06001185 gp.qprint_executing()
1186
1187 if ga.psutil_imported:
1188 ga.terminate_descendants()
Michael Walsh6741f742017-02-20 16:16:38 -06001189
1190 if cp_setup_called:
1191 plug_in_setup()
1192 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001193 call_point="cleanup", stop_on_plug_in_failure=0
1194 )
Michael Walsh6741f742017-02-20 16:16:38 -06001195
Patrick Williams20f38712022-12-08 06:18:26 -06001196 if "boot_results_file_path" in globals():
Michael Walsh986d8ae2019-07-17 10:02:23 -05001197 # Save boot_results and boot_history objects to a file in case they are
Michael Walsh6c645742018-08-17 15:02:17 -05001198 # needed again.
Michael Walsh600876d2017-05-30 17:58:58 -05001199 gp.qprint_timen("Saving boot_results to the following path.")
1200 gp.qprint_var(boot_results_file_path)
Patrick Williams20f38712022-12-08 06:18:26 -06001201 pickle.dump(
1202 (boot_results, boot_history),
1203 open(boot_results_file_path, "wb"),
1204 pickle.HIGHEST_PROTOCOL,
1205 )
Michael Walsh0b93fbf2017-03-02 14:42:41 -06001206
Michael Walshff340002017-08-29 11:18:27 -05001207 global save_stack
1208 # Restore any global values saved on the save_stack.
1209 for parm_name in main_func_parm_list:
1210 # Get the parm_value if it was saved on the stack.
1211 try:
1212 parm_value = save_stack.pop(parm_name)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -05001213 except BaseException:
Michael Walshff340002017-08-29 11:18:27 -05001214 # If it was not saved, no further action is required.
1215 continue
1216
1217 # Restore the saved value.
Patrick Williams20f38712022-12-08 06:18:26 -06001218 cmd_buf = (
1219 'BuiltIn().set_global_variable("${' + parm_name + '}", parm_value)'
1220 )
Michael Walshff340002017-08-29 11:18:27 -05001221 gp.dpissuing(cmd_buf)
1222 exec(cmd_buf)
1223
1224 gp.dprintn(save_stack.sprint_obj())
1225
Michael Walsh6741f742017-02-20 16:16:38 -06001226
Michael Walshc9116812017-03-10 14:23:06 -06001227def test_teardown():
Michael Walshc9116812017-03-10 14:23:06 -06001228 r"""
1229 Clean up after this test case.
1230 """
1231
1232 gp.qprintn()
Michael Walshf75d4352019-12-05 17:01:20 -06001233 gp.qprint_executing()
1234
1235 if ga.psutil_imported:
1236 ga.terminate_descendants()
1237
Patrick Williams20f38712022-12-08 06:18:26 -06001238 cmd_buf = [
1239 "Print Error",
1240 "A keyword timeout occurred ending this program.\n",
1241 ]
Michael Walshc9116812017-03-10 14:23:06 -06001242 BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
1243
George Keishinga54e06f2020-06-12 10:42:41 -05001244 if redfish_supported:
1245 redfish.logout()
1246
Michael Walshc108e422019-03-28 12:27:18 -05001247 gp.qprint_pgm_footer()
Michael Walshb5839d02017-04-12 16:11:20 -05001248
Michael Walshc9116812017-03-10 14:23:06 -06001249
Michael Walsh89de14a2018-10-01 16:51:37 -05001250def post_stack():
1251 r"""
1252 Process post_stack plug-in programs.
1253 """
1254
1255 if not call_post_stack_plug:
1256 # The caller does not wish to have post_stack plug-in processing done.
1257 return
1258
1259 global boot_success
1260
1261 # NOTE: A post_stack call-point failure is NOT counted as a boot failure.
1262 pre_boot_plug_in_setup()
1263 # For the purposes of the following plug-ins, mark the "boot" as a success.
1264 boot_success = 1
1265 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001266 (
1267 rc,
1268 shell_rc,
1269 failed_plug_in_name,
1270 history,
1271 ) = grpi.rprocess_plug_in_packages(
1272 call_point="post_stack", stop_on_plug_in_failure=0, return_history=True
1273 )
Michael Walsh986d8ae2019-07-17 10:02:23 -05001274 for doing_msg in history:
1275 update_boot_history(boot_history, doing_msg, max_boot_history)
Michael Walsh815b1d52018-10-30 13:32:26 -05001276 if rc != 0:
1277 boot_success = 0
Michael Walsh89de14a2018-10-01 16:51:37 -05001278
1279 plug_in_setup()
Patrick Williams20f38712022-12-08 06:18:26 -06001280 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1281 call_point="ffdc_check",
1282 shell_rc=dump_ffdc_rc(),
1283 stop_on_plug_in_failure=1,
1284 stop_on_non_zero_rc=1,
1285 )
Michael Walsh815b1d52018-10-30 13:32:26 -05001286 if shell_rc == dump_ffdc_rc():
Michael Walsh89de14a2018-10-01 16:51:37 -05001287 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
Patrick Williams20f38712022-12-08 06:18:26 -06001288 if status != "PASS":
Michael Walsh89de14a2018-10-01 16:51:37 -05001289 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walshc9bd2e82019-04-18 11:06:52 -05001290 # Leave a record for caller that "soft" errors occurred.
1291 soft_errors = 1
1292 gpu.save_plug_in_value(soft_errors, pgm_name)
Michael Walsh89de14a2018-10-01 16:51:37 -05001293
1294 plug_in_setup()
1295 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Patrick Williams20f38712022-12-08 06:18:26 -06001296 call_point="stop_check", shell_rc=stop_test_rc(), stop_on_non_zero_rc=1
1297 )
Michael Walsh89de14a2018-10-01 16:51:37 -05001298 if shell_rc == stop_test_rc():
1299 message = "Stopping as requested by user.\n"
Michael Walsh80dddde2019-10-22 13:54:38 -05001300 gp.qprint_time(message)
Michael Walsh89de14a2018-10-01 16:51:37 -05001301 BuiltIn().fail(message)
1302
1303
Patrick Williams20f38712022-12-08 06:18:26 -06001304def obmc_boot_test_py(
1305 loc_boot_stack=None, loc_stack_mode=None, loc_quiet=None
1306):
Michael Walsh6741f742017-02-20 16:16:38 -06001307 r"""
1308 Do main program processing.
1309 """
1310
Michael Walshff340002017-08-29 11:18:27 -05001311 global save_stack
1312
Patrick Williams20f38712022-12-08 06:18:26 -06001313 ga.set_term_options(
1314 term_requests={"pgm_names": ["process_plug_in_packages.py"]}
1315 )
Michael Walshf75d4352019-12-05 17:01:20 -06001316
George Keishing36efbc02018-12-12 10:18:23 -06001317 gp.dprintn()
Michael Walshff340002017-08-29 11:18:27 -05001318 # Process function parms.
1319 for parm_name in main_func_parm_list:
1320 # Get parm's value.
George Keishing36efbc02018-12-12 10:18:23 -06001321 parm_value = eval("loc_" + parm_name)
1322 gp.dpvars(parm_name, parm_value)
Michael Walshff340002017-08-29 11:18:27 -05001323
George Keishing36efbc02018-12-12 10:18:23 -06001324 if parm_value is not None:
Michael Walshff340002017-08-29 11:18:27 -05001325 # Save the global value on a stack.
Patrick Williams20f38712022-12-08 06:18:26 -06001326 cmd_buf = (
1327 'save_stack.push(BuiltIn().get_variable_value("${'
1328 + parm_name
1329 + '}"), "'
1330 + parm_name
1331 + '")'
1332 )
Michael Walshff340002017-08-29 11:18:27 -05001333 gp.dpissuing(cmd_buf)
1334 exec(cmd_buf)
1335
1336 # Set the global value to the passed value.
Patrick Williams20f38712022-12-08 06:18:26 -06001337 cmd_buf = (
1338 'BuiltIn().set_global_variable("${'
1339 + parm_name
1340 + '}", loc_'
1341 + parm_name
1342 + ")"
1343 )
Michael Walshff340002017-08-29 11:18:27 -05001344 gp.dpissuing(cmd_buf)
1345 exec(cmd_buf)
1346
1347 gp.dprintn(save_stack.sprint_obj())
Michael Walshb5839d02017-04-12 16:11:20 -05001348
Michael Walsh6741f742017-02-20 16:16:38 -06001349 setup()
1350
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001351 init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
1352
Michael Walsha20da402017-03-31 16:27:45 -05001353 if ffdc_only:
1354 gp.qprint_timen("Caller requested ffdc_only.")
Michael Walsh986d8ae2019-07-17 10:02:23 -05001355 if do_pre_boot_plug_in_setup:
1356 pre_boot_plug_in_setup()
Michael Walsh83f4bc72017-04-20 16:49:43 -05001357 grk.run_key_u("my_ffdc")
Michael Walsh764d2f82017-04-27 16:01:08 -05001358 return
Michael Walsha20da402017-03-31 16:27:45 -05001359
Michael Walsh409ad352020-02-06 11:46:35 -06001360 if delete_errlogs:
Michael Shepos1a67b082020-08-28 16:01:58 -05001361 # print error logs before delete
George Keishing438fd3b2021-10-08 02:15:18 -05001362 if redfish_support_trans_state:
1363 status, error_logs = grk.run_key_u("Get Redfish Event Logs")
Patrick Williams20f38712022-12-08 06:18:26 -06001364 log.print_error_logs(
1365 error_logs, "AdditionalDataURI Message Severity"
1366 )
George Keishing438fd3b2021-10-08 02:15:18 -05001367 else:
1368 status, error_logs = grk.run_key_u("Get Error Logs")
1369 log.print_error_logs(error_logs, "AdditionalData Message Severity")
Michael Shepos1a67b082020-08-28 16:01:58 -05001370 pels = pel.peltool("-l", ignore_err=1)
Michael Shepos0e5f1132020-09-30 16:24:25 -05001371 gp.qprint_var(pels)
Michael Shepos1a67b082020-08-28 16:01:58 -05001372
Michael Walsh409ad352020-02-06 11:46:35 -06001373 # Delete errlogs prior to doing any boot tests.
1374 grk.run_key(delete_errlogs_cmd, ignore=1)
Michael Shepos92a54bf2020-11-11 11:48:55 -06001375 grk.run_key(delete_bmcdump_cmd, ignore=1)
George Keishing2ef6a7d2021-05-19 09:05:32 -05001376 if redfish_support_trans_state:
1377 grk.run_key(delete_sysdump_cmd, ignore=1)
Michael Walsh409ad352020-02-06 11:46:35 -06001378
Michael Walsh6741f742017-02-20 16:16:38 -06001379 # Process caller's boot_stack.
Patrick Williams20f38712022-12-08 06:18:26 -06001380 while len(boot_stack) > 0:
Michael Walsh6741f742017-02-20 16:16:38 -06001381 test_loop_body()
1382
Michael Walshb5839d02017-04-12 16:11:20 -05001383 gp.qprint_timen("Finished processing stack.")
Michael Walsh30dadae2017-02-27 14:25:52 -06001384
Michael Walsh89de14a2018-10-01 16:51:37 -05001385 post_stack()
1386
Michael Walsh6741f742017-02-20 16:16:38 -06001387 # Process caller's boot_list.
1388 if len(boot_list) > 0:
1389 for ix in range(1, max_num_tests + 1):
1390 test_loop_body()
1391
Michael Walshb5839d02017-04-12 16:11:20 -05001392 gp.qprint_timen("Completed all requested boot tests.")
1393
1394 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001395 new_fail = boot_fail - init_boot_fail
1396 if new_fail > boot_fail_threshold:
Patrick Williams20f38712022-12-08 06:18:26 -06001397 error_message = (
1398 "Boot failures exceed the boot failure"
1399 + " threshold:\n"
1400 + gp.sprint_var(new_fail)
1401 + gp.sprint_var(boot_fail_threshold)
1402 )
Michael Walshb5839d02017-04-12 16:11:20 -05001403 BuiltIn().fail(gp.sprint_error(error_message))