blob: f0b6ad3bec58421888ce9be876b64cfa0e123fe5 [file] [log] [blame]
Michael Walsh0bbd8602016-11-22 11:31:49 -06001#!/usr/bin/env python
2
3r"""
4This module is the python counterpart to obmc_boot_test.
5"""
6
Michael Walsh0b93fbf2017-03-02 14:42:41 -06007import os
8import imp
9import time
10import glob
11import random
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050012import re
George Keishingd54bbc22018-08-03 08:24:58 -050013try:
14 import cPickle as pickle
15except ImportError:
16 import pickle
Michael Walshdc80d672017-05-09 12:58:32 -050017import socket
Michael Walsh0b93fbf2017-03-02 14:42:41 -060018
19from robot.utils import DotDict
20from robot.libraries.BuiltIn import BuiltIn
21
Michael Walsh6741f742017-02-20 16:16:38 -060022from boot_data import *
Michael Walshc9116812017-03-10 14:23:06 -060023import gen_print as gp
Michael Walsh0bbd8602016-11-22 11:31:49 -060024import gen_robot_print as grp
Michael Walsh55302292017-01-10 11:43:02 -060025import gen_robot_plug_in as grpi
Michael Walsh6741f742017-02-20 16:16:38 -060026import gen_robot_valid as grv
27import gen_misc as gm
28import gen_cmd as gc
Michael Walshb5839d02017-04-12 16:11:20 -050029import gen_robot_keyword as grk
Michael Walsh55302292017-01-10 11:43:02 -060030import state as st
Michael Walshff340002017-08-29 11:18:27 -050031import var_stack as vs
Michael Walsh0bbd8602016-11-22 11:31:49 -060032
Michael Walsh0b93fbf2017-03-02 14:42:41 -060033base_path = os.path.dirname(os.path.dirname(
34 imp.find_module("gen_robot_print")[1])) +\
Michael Walshc9116812017-03-10 14:23:06 -060035 os.sep
Michael Walsh0b93fbf2017-03-02 14:42:41 -060036sys.path.append(base_path + "extended/")
37import run_keyword as rk
Michael Walsh0bbd8602016-11-22 11:31:49 -060038
Michael Walshe1e26442017-03-06 17:50:07 -060039# Setting master_pid correctly influences the behavior of plug-ins like
40# DB_Logging
41program_pid = os.getpid()
42master_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050043pgm_name = re.sub('\\.py$', '', os.path.basename(__file__))
Michael Walshe1e26442017-03-06 17:50:07 -060044
Michael Walshb5839d02017-04-12 16:11:20 -050045# Set up boot data structures.
46boot_table = create_boot_table()
47valid_boot_types = create_valid_boot_list(boot_table)
Michael Walsh0b93fbf2017-03-02 14:42:41 -060048
Michael Walsh6741f742017-02-20 16:16:38 -060049boot_lists = read_boot_lists()
Michael Walsh815b1d52018-10-30 13:32:26 -050050# The maximum number of entries that can be in the last_ten global variable.
51max_boot_history = 10
Michael Walsh6741f742017-02-20 16:16:38 -060052last_ten = []
Michael Walsh6741f742017-02-20 16:16:38 -060053
Michael Walsh7dc885b2018-03-14 17:51:59 -050054state = st.return_state_constant('default_state')
Michael Walsh6741f742017-02-20 16:16:38 -060055cp_setup_called = 0
56next_boot = ""
57base_tool_dir_path = os.path.normpath(os.environ.get(
58 'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
Michael Walshb5839d02017-04-12 16:11:20 -050059
Michael Walsh6741f742017-02-20 16:16:38 -060060ffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
Michael Walsh6741f742017-02-20 16:16:38 -060061boot_success = 0
Michael Walsh6741f742017-02-20 16:16:38 -060062status_dir_path = os.environ.get('STATUS_DIR_PATH', "")
63if status_dir_path != "":
64 status_dir_path = os.path.normpath(status_dir_path) + os.sep
Michael Walsh0b93fbf2017-03-02 14:42:41 -060065default_power_on = "REST Power On"
66default_power_off = "REST Power Off"
Michael Walsh6741f742017-02-20 16:16:38 -060067boot_count = 0
Michael Walsh0bbd8602016-11-22 11:31:49 -060068
Michael Walsh85678942017-03-27 14:34:22 -050069LOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
Michael Walshe1974b92017-08-03 13:39:51 -050070ffdc_prefix = ""
Sunil M325eb542017-08-10 07:09:43 -050071boot_start_time = ""
72boot_end_time = ""
Michael Walshff340002017-08-29 11:18:27 -050073save_stack = vs.var_stack('save_stack')
74main_func_parm_list = ['boot_stack', 'stack_mode', 'quiet']
Michael Walsh85678942017-03-27 14:34:22 -050075
76
Michael Walsh89de14a2018-10-01 16:51:37 -050077def dump_ffdc_rc():
78 r"""
79 Return the constant dump ffdc test return code value.
80
81 When a plug-in call point program returns this value, it indicates that
82 this program should collect FFDC.
83 """
84
85 return 0x00000200
86
87
88def stop_test_rc():
89 r"""
90 Return the constant stop test return code value.
91
92 When a plug-in call point program returns this value, it indicates that
93 this program should stop running.
94 """
95
96 return 0x00000200
97
98
Michael Walsh0ad0f7f2017-05-04 14:39:58 -050099def process_host(host,
100 host_var_name=""):
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500101 r"""
102 Process a host by getting the associated host name and IP address and
103 setting them in global variables.
104
105 If the caller does not pass the host_var_name, this function will try to
106 figure out the name of the variable used by the caller for the host parm.
107 Callers are advised to explicitly specify the host_var_name when calling
108 with an exec command. In such cases, the get_arg_name cannot figure out
109 the host variable name.
110
111 This function will then create similar global variable names by
112 removing "_host" and appending "_host_name" or "_ip" to the host variable
113 name.
114
115 Example:
116
117 If a call is made like this:
118 process_host(openbmc_host)
119
120 Global variables openbmc_host_name and openbmc_ip will be set.
121
122 Description of argument(s):
123 host A host name or IP. The name of the variable used should
124 have a suffix of "_host".
125 host_var_name The name of the variable being used as the host parm.
126 """
127
128 if host_var_name == "":
129 host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
130
131 host_name_var_name = re.sub("host", "host_name", host_var_name)
132 ip_var_name = re.sub("host", "ip", host_var_name)
133 cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\
134 host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\
135 host + "')"
136 exec(cmd_buf)
137
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500138
Michael Walshb5839d02017-04-12 16:11:20 -0500139def process_pgm_parms():
Michael Walshb5839d02017-04-12 16:11:20 -0500140 r"""
141 Process the program parameters by assigning them all to corresponding
142 globals. Also, set some global values that depend on program parameters.
143 """
144
145 # Program parameter processing.
146 # Assign all program parms to python variables which are global to this
147 # module.
148
149 global parm_list
150 parm_list = BuiltIn().get_variable_value("${parm_list}")
151 # The following subset of parms should be processed as integers.
152 int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only',
Michael Walsh89de14a2018-10-01 16:51:37 -0500153 'boot_fail_threshold', 'delete_errlogs',
154 'call_post_stack_plug', 'quiet', 'test_mode', 'debug']
Michael Walshb5839d02017-04-12 16:11:20 -0500155 for parm in parm_list:
156 if parm in int_list:
157 sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
158 "}\", \"0\"))"
159 else:
160 sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
161 cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
Michael Walshff340002017-08-29 11:18:27 -0500162 gp.dpissuing(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500163 exec(cmd_buf)
Michael Walsh0ad0f7f2017-05-04 14:39:58 -0500164 if re.match(r".*_host$", parm):
165 cmd_buf = "process_host(" + parm + ", '" + parm + "')"
166 exec(cmd_buf)
167 if re.match(r".*_password$", parm):
168 # Register the value of any parm whose name ends in _password.
169 # This will cause the print functions to replace passwords with
170 # asterisks in the output.
171 cmd_buf = "gp.register_passwords(" + parm + ")"
172 exec(cmd_buf)
Michael Walshb5839d02017-04-12 16:11:20 -0500173
174 global ffdc_dir_path_style
175 global boot_list
176 global boot_stack
177 global boot_results_file_path
178 global boot_results
Michael Walsh6c645742018-08-17 15:02:17 -0500179 global last_ten
Michael Walshb5839d02017-04-12 16:11:20 -0500180 global ffdc_list_file_path
Michael Walshe0cf8d72017-05-17 13:20:46 -0500181 global ffdc_report_list_path
Michael Walsh600876d2017-05-30 17:58:58 -0500182 global ffdc_summary_list_path
Michael Walshb5839d02017-04-12 16:11:20 -0500183
184 if ffdc_dir_path_style == "":
185 ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
186
187 # Convert these program parms to lists for easier processing..
George Keishing36efbc02018-12-12 10:18:23 -0600188 boot_list = list(filter(None, boot_list.split(":")))
189 boot_stack = list(filter(None, boot_stack.split(":")))
Michael Walshb5839d02017-04-12 16:11:20 -0500190
Michael Walsh903e0b22017-09-19 17:00:33 -0500191 cleanup_boot_results_file()
192 boot_results_file_path = create_boot_results_file_path(pgm_name,
193 openbmc_nickname,
194 master_pid)
Michael Walshb5839d02017-04-12 16:11:20 -0500195
196 if os.path.isfile(boot_results_file_path):
197 # We've been called before in this run so we'll load the saved
Michael Walsh6c645742018-08-17 15:02:17 -0500198 # boot_results and last_ten objects.
199 boot_results, last_ten =\
200 pickle.load(open(boot_results_file_path, 'rb'))
Michael Walshb5839d02017-04-12 16:11:20 -0500201 else:
202 boot_results = boot_results(boot_table, boot_pass, boot_fail)
203
204 ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\
205 "/FFDC_FILE_LIST"
Michael Walshe0cf8d72017-05-17 13:20:46 -0500206 ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\
207 "/FFDC_REPORT_FILE_LIST"
Michael Walshb5839d02017-04-12 16:11:20 -0500208
Michael Walsh600876d2017-05-30 17:58:58 -0500209 ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\
210 "/FFDC_SUMMARY_FILE_LIST"
211
Michael Walshb5839d02017-04-12 16:11:20 -0500212
Michael Walsh85678942017-03-27 14:34:22 -0500213def initial_plug_in_setup():
Michael Walsh85678942017-03-27 14:34:22 -0500214 r"""
215 Initialize all plug-in environment variables which do not change for the
216 duration of the program.
217
218 """
219
220 global LOG_LEVEL
221 BuiltIn().set_log_level("NONE")
222
223 BuiltIn().set_global_variable("${master_pid}", master_pid)
224 BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
225 BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
226 BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
227 BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
228 ffdc_list_file_path)
Michael Walshe0cf8d72017-05-17 13:20:46 -0500229 BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}",
230 ffdc_report_list_path)
Michael Walsh600876d2017-05-30 17:58:58 -0500231 BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}",
232 ffdc_summary_list_path)
Michael Walsh85678942017-03-27 14:34:22 -0500233
234 BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
235 ffdc_dir_path_style)
236 BuiltIn().set_global_variable("${FFDC_CHECK}",
237 ffdc_check)
238
239 # For each program parameter, set the corresponding AUTOBOOT_ environment
240 # variable value. Also, set an AUTOBOOT_ environment variable for every
241 # element in additional_values.
242 additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
243 "status_dir_path", "base_tool_dir_path",
Michael Walsh600876d2017-05-30 17:58:58 -0500244 "ffdc_list_file_path", "ffdc_report_list_path",
Michael Walsh0a3bdb42019-01-31 16:21:44 +0000245 "ffdc_summary_list_path", "execdir"]
Michael Walsh85678942017-03-27 14:34:22 -0500246
247 plug_in_vars = parm_list + additional_values
248
249 for var_name in plug_in_vars:
250 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
251 var_name = var_name.upper()
252 if var_value is None:
253 var_value = ""
254 os.environ["AUTOBOOT_" + var_name] = str(var_value)
255
256 BuiltIn().set_log_level(LOG_LEVEL)
257
Michael Walsh68a61162017-04-25 11:54:06 -0500258 # Make sure the ffdc list directory exists.
259 ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
260 if not os.path.exists(ffdc_list_dir_path):
261 os.makedirs(ffdc_list_dir_path)
Michael Walsh85678942017-03-27 14:34:22 -0500262
Michael Walsh85678942017-03-27 14:34:22 -0500263
Michael Walsh0bbd8602016-11-22 11:31:49 -0600264def plug_in_setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600265 r"""
Michael Walsh85678942017-03-27 14:34:22 -0500266 Initialize all changing plug-in environment variables for use by the
267 plug-in programs.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600268 """
269
Michael Walsh85678942017-03-27 14:34:22 -0500270 global LOG_LEVEL
271 global test_really_running
272
273 BuiltIn().set_log_level("NONE")
274
Michael Walsh6741f742017-02-20 16:16:38 -0600275 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600276 if boot_pass > 1:
277 test_really_running = 1
278 else:
279 test_really_running = 0
280
Michael Walsh6741f742017-02-20 16:16:38 -0600281 BuiltIn().set_global_variable("${test_really_running}",
282 test_really_running)
283 BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
Michael Walsh6741f742017-02-20 16:16:38 -0600284 BuiltIn().set_global_variable("${boot_pass}", boot_pass)
285 BuiltIn().set_global_variable("${boot_fail}", boot_fail)
286 BuiltIn().set_global_variable("${boot_success}", boot_success)
287 BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
Sunil M325eb542017-08-10 07:09:43 -0500288 BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
289 BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
Michael Walsh4c9a6452016-12-13 16:03:11 -0600290
Michael Walsh0bbd8602016-11-22 11:31:49 -0600291 # For each program parameter, set the corresponding AUTOBOOT_ environment
292 # variable value. Also, set an AUTOBOOT_ environment variable for every
293 # element in additional_values.
294 additional_values = ["boot_type_desc", "boot_success", "boot_pass",
Sunil M325eb542017-08-10 07:09:43 -0500295 "boot_fail", "test_really_running", "ffdc_prefix",
296 "boot_start_time", "boot_end_time"]
Michael Walsh0bbd8602016-11-22 11:31:49 -0600297
Michael Walsh85678942017-03-27 14:34:22 -0500298 plug_in_vars = additional_values
Michael Walsh0bbd8602016-11-22 11:31:49 -0600299
300 for var_name in plug_in_vars:
301 var_value = BuiltIn().get_variable_value("${" + var_name + "}")
302 var_name = var_name.upper()
303 if var_value is None:
304 var_value = ""
Michael Walsh6741f742017-02-20 16:16:38 -0600305 os.environ["AUTOBOOT_" + var_name] = str(var_value)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600306
Michael Walsh0bbd8602016-11-22 11:31:49 -0600307 if debug:
Michael Walsh6741f742017-02-20 16:16:38 -0600308 shell_rc, out_buf = \
309 gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
Michael Walsh0bbd8602016-11-22 11:31:49 -0600310
Michael Walsh85678942017-03-27 14:34:22 -0500311 BuiltIn().set_log_level(LOG_LEVEL)
312
Michael Walsh0bbd8602016-11-22 11:31:49 -0600313
Michael Walshe0cf8d72017-05-17 13:20:46 -0500314def pre_boot_plug_in_setup():
315
316 # Clear the ffdc_list_file_path file. Plug-ins may now write to it.
317 try:
318 os.remove(ffdc_list_file_path)
319 except OSError:
320 pass
321
322 # Clear the ffdc_report_list_path file. Plug-ins may now write to it.
323 try:
324 os.remove(ffdc_report_list_path)
325 except OSError:
326 pass
327
Michael Walsh600876d2017-05-30 17:58:58 -0500328 # Clear the ffdc_summary_list_path file. Plug-ins may now write to it.
329 try:
330 os.remove(ffdc_summary_list_path)
331 except OSError:
332 pass
333
Michael Walshe1974b92017-08-03 13:39:51 -0500334 global ffdc_prefix
335
336 seconds = time.time()
337 loc_time = time.localtime(seconds)
338 time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
339
340 ffdc_prefix = openbmc_nickname + "." + time_string
341
Michael Walshe0cf8d72017-05-17 13:20:46 -0500342
Michael Walsh6741f742017-02-20 16:16:38 -0600343def setup():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600344 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600345 Do general program setup tasks.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600346 """
347
Michael Walsh6741f742017-02-20 16:16:38 -0600348 global cp_setup_called
Michael Walsh81816742017-09-27 11:02:29 -0500349 global transitional_boot_selected
Michael Walsh0bbd8602016-11-22 11:31:49 -0600350
Michael Walshb5839d02017-04-12 16:11:20 -0500351 gp.qprintn()
352
Michael Walsh81816742017-09-27 11:02:29 -0500353 transitional_boot_selected = False
354
Michael Walsh83f4bc72017-04-20 16:49:43 -0500355 robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
356 repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
Michael Walshd061c042017-05-23 14:46:57 -0500357 # If we can't find process_plug_in_packages.py, ssh_pw or
358 # validate_plug_ins.py, then we don't have our repo bin in PATH.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500359 shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py"
360 + " ssh_pw validate_plug_ins.py", quiet=1,
Michael Walshd061c042017-05-23 14:46:57 -0500361 print_output=0, show_err=0)
Michael Walshb5839d02017-04-12 16:11:20 -0500362 if shell_rc != 0:
Michael Walsh83f4bc72017-04-20 16:49:43 -0500363 os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "")
364 # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
365 if robot_pgm_dir_path not in sys.path:
366 sys.path.append(robot_pgm_dir_path)
367 PYTHONPATH = os.environ.get("PYTHONPATH", "")
368 if PYTHONPATH == "":
369 os.environ['PYTHONPATH'] = robot_pgm_dir_path
370 else:
371 os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH
Michael Walsh6741f742017-02-20 16:16:38 -0600372
373 validate_parms()
374
375 grp.rqprint_pgm_header()
376
George Keishingefc3ff22017-12-12 11:49:25 -0600377 grk.run_key("Set BMC Power Policy ALWAYS_POWER_OFF")
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500378
Michael Walsh85678942017-03-27 14:34:22 -0500379 initial_plug_in_setup()
380
Michael Walsh6741f742017-02-20 16:16:38 -0600381 plug_in_setup()
382 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
383 call_point='setup')
384 if rc != 0:
385 error_message = "Plug-in setup failed.\n"
386 grp.rprint_error_report(error_message)
387 BuiltIn().fail(error_message)
388 # Setting cp_setup_called lets our Teardown know that it needs to call
389 # the cleanup plug-in call point.
390 cp_setup_called = 1
391
392 # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
393 BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
Michael Walsh85678942017-03-27 14:34:22 -0500394 # FFDC_LOG_PATH is used by "FFDC" keyword.
395 BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
Michael Walsh6741f742017-02-20 16:16:38 -0600396
Michael Walshdc80d672017-05-09 12:58:32 -0500397 # Also printed by FFDC.
398 global host_name
399 global host_ip
400 host = socket.gethostname()
401 host_name, host_ip = gm.get_host_name_ip(host)
402
Michael Walshb5839d02017-04-12 16:11:20 -0500403 gp.dprint_var(boot_table, 1)
404 gp.dprint_var(boot_lists)
Michael Walsh0bbd8602016-11-22 11:31:49 -0600405
Michael Walsh0bbd8602016-11-22 11:31:49 -0600406
Michael Walsh6741f742017-02-20 16:16:38 -0600407def validate_parms():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600408 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600409 Validate all program parameters.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600410 """
411
Michael Walshb5839d02017-04-12 16:11:20 -0500412 process_pgm_parms()
Michael Walsh0bbd8602016-11-22 11:31:49 -0600413
Michael Walshb5839d02017-04-12 16:11:20 -0500414 gp.qprintn()
415
416 global openbmc_model
Michael Walsh6741f742017-02-20 16:16:38 -0600417 grv.rvalid_value("openbmc_host")
418 grv.rvalid_value("openbmc_username")
419 grv.rvalid_value("openbmc_password")
Michael Walsh0a3bdb42019-01-31 16:21:44 +0000420 grv.rvalid_value("rest_username")
421 grv.rvalid_value("rest_password")
422 grv.rvalid_value("ipmi_username")
423 grv.rvalid_value("ipmi_password")
Michael Walsh6741f742017-02-20 16:16:38 -0600424 if os_host != "":
425 grv.rvalid_value("os_username")
426 grv.rvalid_value("os_password")
Michael Walsh0bbd8602016-11-22 11:31:49 -0600427
Michael Walsh6741f742017-02-20 16:16:38 -0600428 if pdu_host != "":
429 grv.rvalid_value("pdu_username")
430 grv.rvalid_value("pdu_password")
Michael Walsh85678942017-03-27 14:34:22 -0500431 grv.rvalid_integer("pdu_slot_no")
Michael Walsh6741f742017-02-20 16:16:38 -0600432 if openbmc_serial_host != "":
433 grv.rvalid_integer("openbmc_serial_port")
Michael Walshb5839d02017-04-12 16:11:20 -0500434 if openbmc_model == "":
435 status, ret_values =\
436 grk.run_key_u("Get BMC System Model")
437 openbmc_model = ret_values
438 BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
Michael Walsh6741f742017-02-20 16:16:38 -0600439 grv.rvalid_value("openbmc_model")
Michael Walshb5839d02017-04-12 16:11:20 -0500440 grv.rvalid_integer("max_num_tests")
Michael Walsh6741f742017-02-20 16:16:38 -0600441 grv.rvalid_integer("boot_pass")
442 grv.rvalid_integer("boot_fail")
443
444 plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
445 BuiltIn().set_global_variable("${plug_in_packages_list}",
446 plug_in_packages_list)
447
Michael Walshb5839d02017-04-12 16:11:20 -0500448 grv.rvalid_value("stack_mode", valid_values=['normal', 'skip'])
Michael Walsha20da402017-03-31 16:27:45 -0500449 if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
Michael Walsh6741f742017-02-20 16:16:38 -0600450 error_message = "You must provide either a value for either the" +\
451 " boot_list or the boot_stack parm.\n"
452 BuiltIn().fail(gp.sprint_error(error_message))
453
454 valid_boot_list(boot_list, valid_boot_types)
455 valid_boot_list(boot_stack, valid_boot_types)
456
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500457 selected_PDU_boots = list(set(boot_list + boot_stack)
458 & set(boot_lists['PDU_reboot']))
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500459
460 if len(selected_PDU_boots) > 0 and pdu_host == "":
461 error_message = "You have selected the following boots which" +\
462 " require a PDU host but no value for pdu_host:\n"
463 error_message += gp.sprint_var(selected_PDU_boots)
464 error_message += gp.sprint_var(pdu_host, 2)
465 BuiltIn().fail(gp.sprint_error(error_message))
466
Michael Walsh6741f742017-02-20 16:16:38 -0600467 return
Michael Walsh0bbd8602016-11-22 11:31:49 -0600468
Michael Walsh0bbd8602016-11-22 11:31:49 -0600469
Michael Walsh6741f742017-02-20 16:16:38 -0600470def my_get_state():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600471 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600472 Get the system state plus a little bit of wrapping.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600473 """
474
Michael Walsh6741f742017-02-20 16:16:38 -0600475 global state
476
477 req_states = ['epoch_seconds'] + st.default_req_states
478
Michael Walshb5839d02017-04-12 16:11:20 -0500479 gp.qprint_timen("Getting system state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600480 if test_mode:
481 state['epoch_seconds'] = int(time.time())
482 else:
Michael Walshb5839d02017-04-12 16:11:20 -0500483 state = st.get_state(req_states=req_states, quiet=quiet)
484 gp.qprint_var(state)
Michael Walsh341c21e2017-01-17 16:25:20 -0600485
Michael Walsh341c21e2017-01-17 16:25:20 -0600486
Michael Walsh45ca6e42017-09-14 17:29:12 -0500487def valid_state():
Michael Walsh45ca6e42017-09-14 17:29:12 -0500488 r"""
489 Verify that our state dictionary contains no blank values. If we don't get
490 valid state data, we cannot continue to work.
491 """
492
493 if st.compare_states(state, st.invalid_state_match, 'or'):
494 error_message = "The state dictionary contains blank fields which" +\
495 " is illegal.\n" + gp.sprint_var(state)
496 BuiltIn().fail(gp.sprint_error(error_message))
497
Michael Walsh45ca6e42017-09-14 17:29:12 -0500498
Michael Walsh6741f742017-02-20 16:16:38 -0600499def select_boot():
Michael Walsh341c21e2017-01-17 16:25:20 -0600500 r"""
501 Select a boot test to be run based on our current state and return the
502 chosen boot type.
503
504 Description of arguments:
Michael Walsh6741f742017-02-20 16:16:38 -0600505 state The state of the machine.
Michael Walsh341c21e2017-01-17 16:25:20 -0600506 """
507
Michael Walsh81816742017-09-27 11:02:29 -0500508 global transitional_boot_selected
Michael Walsh30dadae2017-02-27 14:25:52 -0600509 global boot_stack
510
Michael Walshb5839d02017-04-12 16:11:20 -0500511 gp.qprint_timen("Selecting a boot test.")
Michael Walsh6741f742017-02-20 16:16:38 -0600512
Michael Walsh81816742017-09-27 11:02:29 -0500513 if transitional_boot_selected and not boot_success:
514 prior_boot = next_boot
515 boot_candidate = boot_stack.pop()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500516 gp.qprint_timen("The prior '" + next_boot + "' was chosen to"
517 + " transition to a valid state for '" + boot_candidate
518 + "' which was at the top of the boot_stack. Since"
519 + " the '" + next_boot + "' failed, the '"
520 + boot_candidate + "' has been removed from the stack"
521 + " to avoid and endless failure loop.")
Michael Walsh81816742017-09-27 11:02:29 -0500522 if len(boot_stack) == 0:
523 return ""
524
Michael Walsh6741f742017-02-20 16:16:38 -0600525 my_get_state()
Michael Walsh45ca6e42017-09-14 17:29:12 -0500526 valid_state()
Michael Walsh6741f742017-02-20 16:16:38 -0600527
Michael Walsh81816742017-09-27 11:02:29 -0500528 transitional_boot_selected = False
Michael Walsh6741f742017-02-20 16:16:38 -0600529 stack_popped = 0
530 if len(boot_stack) > 0:
531 stack_popped = 1
Michael Walshb5839d02017-04-12 16:11:20 -0500532 gp.qprint_dashes()
533 gp.qprint_var(boot_stack)
534 gp.qprint_dashes()
535 skip_boot_printed = 0
536 while len(boot_stack) > 0:
537 boot_candidate = boot_stack.pop()
538 if stack_mode == 'normal':
539 break
540 else:
541 if st.compare_states(state, boot_table[boot_candidate]['end']):
542 if not skip_boot_printed:
Michael Walshff340002017-08-29 11:18:27 -0500543 gp.qprint_var(stack_mode)
544 gp.qprintn()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500545 gp.qprint_timen("Skipping the following boot tests"
546 + " which are unnecessary since their"
547 + " required end states match the"
548 + " current machine state:")
Michael Walshb5839d02017-04-12 16:11:20 -0500549 skip_boot_printed = 1
Michael Walshff340002017-08-29 11:18:27 -0500550 gp.qprint_var(boot_candidate)
Michael Walshb5839d02017-04-12 16:11:20 -0500551 boot_candidate = ""
552 if boot_candidate == "":
553 gp.qprint_dashes()
554 gp.qprint_var(boot_stack)
555 gp.qprint_dashes()
556 return boot_candidate
Michael Walsh6741f742017-02-20 16:16:38 -0600557 if st.compare_states(state, boot_table[boot_candidate]['start']):
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500558 gp.qprint_timen("The machine state is valid for a '"
559 + boot_candidate + "' boot test.")
Michael Walshb5839d02017-04-12 16:11:20 -0500560 gp.qprint_dashes()
561 gp.qprint_var(boot_stack)
562 gp.qprint_dashes()
Michael Walsh6741f742017-02-20 16:16:38 -0600563 return boot_candidate
Michael Walsh341c21e2017-01-17 16:25:20 -0600564 else:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500565 gp.qprint_timen("The machine state does not match the required"
566 + " starting state for a '" + boot_candidate
567 + "' boot test:")
Michael Walshff340002017-08-29 11:18:27 -0500568 gp.qprint_varx("boot_table[" + boot_candidate + "][start]",
569 boot_table[boot_candidate]['start'], 1)
Michael Walsh6741f742017-02-20 16:16:38 -0600570 boot_stack.append(boot_candidate)
Michael Walsh81816742017-09-27 11:02:29 -0500571 transitional_boot_selected = True
Michael Walsh6741f742017-02-20 16:16:38 -0600572 popped_boot = boot_candidate
573
574 # Loop through your list selecting a boot_candidates
575 boot_candidates = []
576 for boot_candidate in boot_list:
577 if st.compare_states(state, boot_table[boot_candidate]['start']):
578 if stack_popped:
579 if st.compare_states(boot_table[boot_candidate]['end'],
Gunnar Mills096cd562018-03-26 10:19:12 -0500580 boot_table[popped_boot]['start']):
Michael Walsh6741f742017-02-20 16:16:38 -0600581 boot_candidates.append(boot_candidate)
582 else:
583 boot_candidates.append(boot_candidate)
584
585 if len(boot_candidates) == 0:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500586 gp.qprint_timen("The user's boot list contained no boot tests"
587 + " which are valid for the current machine state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600588 boot_candidate = default_power_on
589 if not st.compare_states(state, boot_table[default_power_on]['start']):
590 boot_candidate = default_power_off
591 boot_candidates.append(boot_candidate)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500592 gp.qprint_timen("Using default '" + boot_candidate
593 + "' boot type to transition to valid state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600594
Michael Walshb5839d02017-04-12 16:11:20 -0500595 gp.dprint_var(boot_candidates)
Michael Walsh6741f742017-02-20 16:16:38 -0600596
597 # Randomly select a boot from the candidate list.
598 boot = random.choice(boot_candidates)
Michael Walsh341c21e2017-01-17 16:25:20 -0600599
600 return boot
Michael Walsh0bbd8602016-11-22 11:31:49 -0600601
Michael Walsh55302292017-01-10 11:43:02 -0600602
Michael Walsh341c21e2017-01-17 16:25:20 -0600603def print_last_boots():
Michael Walsh341c21e2017-01-17 16:25:20 -0600604 r"""
605 Print the last ten boots done with their time stamps.
606 """
607
608 # indent 0, 90 chars wide, linefeed, char is "="
Michael Walshb5839d02017-04-12 16:11:20 -0500609 gp.qprint_dashes(0, 90)
610 gp.qprintn("Last 10 boots:\n")
Michael Walsh341c21e2017-01-17 16:25:20 -0600611
612 for boot_entry in last_ten:
613 grp.rqprint(boot_entry)
Michael Walshb5839d02017-04-12 16:11:20 -0500614 gp.qprint_dashes(0, 90)
Michael Walsh341c21e2017-01-17 16:25:20 -0600615
Michael Walsh341c21e2017-01-17 16:25:20 -0600616
Michael Walshb2e53ec2017-10-30 15:04:36 -0500617def print_defect_report(ffdc_file_list):
Michael Walsh341c21e2017-01-17 16:25:20 -0600618 r"""
619 Print a defect report.
Michael Walshb2e53ec2017-10-30 15:04:36 -0500620
621 Description of argument(s):
622 ffdc_file_list A list of files which were collected by our ffdc functions.
Michael Walsh341c21e2017-01-17 16:25:20 -0600623 """
624
Michael Walsh600876d2017-05-30 17:58:58 -0500625 # Making deliberate choice to NOT run plug_in_setup(). We don't want
626 # ffdc_prefix updated.
627 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
628 call_point='ffdc_report', stop_on_plug_in_failure=0)
629
Michael Walshe0cf8d72017-05-17 13:20:46 -0500630 # Get additional header data which may have been created by ffdc plug-ins.
631 # Also, delete the individual header files to cleanup.
632 cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\
633 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
634 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
635 shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
636 show_err=0)
637
Michael Walshb2e53ec2017-10-30 15:04:36 -0500638 # Get additional summary data which may have been created by ffdc plug-ins.
Michael Walsh600876d2017-05-30 17:58:58 -0500639 # Also, delete the individual header files to cleanup.
640 cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\
641 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
642 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
643 shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
644 show_err=0)
645
Michael Walshb2e53ec2017-10-30 15:04:36 -0500646 # ffdc_list_file_path contains a list of any ffdc files created by plug-
647 # ins, etc. Read that data into a list.
Michael Walsh341c21e2017-01-17 16:25:20 -0600648 try:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500649 plug_in_ffdc_list = \
650 open(ffdc_list_file_path, 'r').read().rstrip("\n").split("\n")
George Keishing36efbc02018-12-12 10:18:23 -0600651 plug_in_ffdc_list = list(filter(None, plug_in_ffdc_list))
Michael Walsh341c21e2017-01-17 16:25:20 -0600652 except IOError:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500653 plug_in_ffdc_list = []
654
655 # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
656 # in. Eliminate duplicates and sort the list.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500657 ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
Michael Walshb2e53ec2017-10-30 15:04:36 -0500658
659 if status_file_path != "":
660 ffdc_file_list.insert(0, status_file_path)
661
662 # Convert the list to a printable list.
663 printable_ffdc_file_list = "\n".join(ffdc_file_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600664
Michael Walsh68a61162017-04-25 11:54:06 -0500665 # Open ffdc_file_list for writing. We will write a complete list of
666 # FFDC files to it for possible use by plug-ins like cp_stop_check.
667 ffdc_list_file = open(ffdc_list_file_path, 'w')
Michael Walshb2e53ec2017-10-30 15:04:36 -0500668 ffdc_list_file.write(printable_ffdc_file_list + "\n")
669 ffdc_list_file.close()
670
671 indent = 0
672 width = 90
673 linefeed = 1
674 char = "="
Michael Walsh68a61162017-04-25 11:54:06 -0500675
676 gp.qprintn()
Michael Walshb2e53ec2017-10-30 15:04:36 -0500677 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500678 gp.qprintn("Copy this data to the defect:\n")
679
Michael Walshe0cf8d72017-05-17 13:20:46 -0500680 if len(more_header_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500681 gp.qprintn(more_header_info)
Michael Walshdc80d672017-05-09 12:58:32 -0500682 gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
683 openbmc_host_name, openbmc_ip, openbmc_username,
Michael Walsh0a3bdb42019-01-31 16:21:44 +0000684 openbmc_password, rest_username, rest_password, ipmi_username,
685 ipmi_password, os_host, os_host_name, os_ip, os_username,
Michael Walshdc80d672017-05-09 12:58:32 -0500686 os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
687 pdu_password, pdu_slot_no, openbmc_serial_host,
688 openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
Michael Walsh68a61162017-04-25 11:54:06 -0500689
690 gp.qprintn()
Michael Walsh68a61162017-04-25 11:54:06 -0500691 print_last_boots()
692 gp.qprintn()
693 gp.qprint_var(state)
Michael Walshb5839d02017-04-12 16:11:20 -0500694 gp.qprintn()
695 gp.qprintn("FFDC data files:")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500696 gp.qprintn(printable_ffdc_file_list)
Michael Walshb5839d02017-04-12 16:11:20 -0500697 gp.qprintn()
Michael Walsh341c21e2017-01-17 16:25:20 -0600698
Michael Walsh600876d2017-05-30 17:58:58 -0500699 if len(ffdc_summary_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500700 gp.qprintn(ffdc_summary_info)
Michael Walsh600876d2017-05-30 17:58:58 -0500701
Michael Walshb2e53ec2017-10-30 15:04:36 -0500702 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500703
Michael Walsh6741f742017-02-20 16:16:38 -0600704
Michael Walsh6741f742017-02-20 16:16:38 -0600705def my_ffdc():
Michael Walsh6741f742017-02-20 16:16:38 -0600706 r"""
707 Collect FFDC data.
708 """
709
710 global state
711
712 plug_in_setup()
713 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500714 call_point='ffdc', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600715
716 AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500717 status, ffdc_file_list = grk.run_key_u("FFDC ffdc_prefix="
718 + AUTOBOOT_FFDC_PREFIX
719 + " ffdc_function_list="
720 + ffdc_function_list, ignore=1)
Michael Walsh83f4bc72017-04-20 16:49:43 -0500721 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500722 gp.qprint_error("Call to ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600723
724 my_get_state()
725
Michael Walshb2e53ec2017-10-30 15:04:36 -0500726 print_defect_report(ffdc_file_list)
Michael Walsh6741f742017-02-20 16:16:38 -0600727
Michael Walsh6741f742017-02-20 16:16:38 -0600728
Michael Walsh6741f742017-02-20 16:16:38 -0600729def print_test_start_message(boot_keyword):
Michael Walsh6741f742017-02-20 16:16:38 -0600730 r"""
731 Print a message indicating what boot test is about to run.
732
733 Description of arguments:
734 boot_keyword The name of the boot which is to be run
735 (e.g. "BMC Power On").
736 """
737
738 global last_ten
Sunil M325eb542017-08-10 07:09:43 -0500739 global boot_start_time
Michael Walsh6741f742017-02-20 16:16:38 -0600740
741 doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
Sunil M325eb542017-08-10 07:09:43 -0500742
743 # Set boot_start_time for use by plug-ins.
744 boot_start_time = doing_msg[1:33]
745 gp.qprint_var(boot_start_time)
746
Michael Walshb5839d02017-04-12 16:11:20 -0500747 gp.qprint(doing_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600748
749 last_ten.append(doing_msg)
750
Michael Walsh815b1d52018-10-30 13:32:26 -0500751 # Trim list to max number of entries.
752 del last_ten[:max(0, len(last_ten) - max_boot_history)]
Michael Walsh6741f742017-02-20 16:16:38 -0600753
Michael Walsh6741f742017-02-20 16:16:38 -0600754
Michael Walsh6741f742017-02-20 16:16:38 -0600755def run_boot(boot):
Michael Walsh6741f742017-02-20 16:16:38 -0600756 r"""
757 Run the specified boot.
758
759 Description of arguments:
760 boot The name of the boot test to be performed.
761 """
762
763 global state
764
765 print_test_start_message(boot)
766
767 plug_in_setup()
768 rc, shell_rc, failed_plug_in_name = \
769 grpi.rprocess_plug_in_packages(call_point="pre_boot")
770 if rc != 0:
771 error_message = "Plug-in failed with non-zero return code.\n" +\
772 gp.sprint_var(rc, 1)
773 BuiltIn().fail(gp.sprint_error(error_message))
774
775 if test_mode:
776 # In test mode, we'll pretend the boot worked by assigning its
777 # required end state to the default state value.
Michael Walsh30dadae2017-02-27 14:25:52 -0600778 state = st.strip_anchor_state(boot_table[boot]['end'])
Michael Walsh6741f742017-02-20 16:16:38 -0600779 else:
780 # Assertion: We trust that the state data was made fresh by the
781 # caller.
782
Michael Walshb5839d02017-04-12 16:11:20 -0500783 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600784
785 if boot_table[boot]['method_type'] == "keyword":
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600786 rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
Michael Walshb5839d02017-04-12 16:11:20 -0500787 boot_table[boot]['method'],
788 quiet=quiet)
Michael Walsh6741f742017-02-20 16:16:38 -0600789
790 if boot_table[boot]['bmc_reboot']:
791 st.wait_for_comm_cycle(int(state['epoch_seconds']))
Michael Walsh30dadae2017-02-27 14:25:52 -0600792 plug_in_setup()
793 rc, shell_rc, failed_plug_in_name = \
794 grpi.rprocess_plug_in_packages(call_point="post_reboot")
795 if rc != 0:
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600796 error_message = "Plug-in failed with non-zero return code.\n"
797 error_message += gp.sprint_var(rc, 1)
Michael Walsh30dadae2017-02-27 14:25:52 -0600798 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -0600799 else:
800 match_state = st.anchor_state(state)
801 del match_state['epoch_seconds']
802 # Wait for the state to change in any way.
803 st.wait_state(match_state, wait_time=state_change_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500804 interval="10 seconds", invert=1)
Michael Walsh6741f742017-02-20 16:16:38 -0600805
Michael Walshb5839d02017-04-12 16:11:20 -0500806 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600807 if boot_table[boot]['end']['chassis'] == "Off":
808 boot_timeout = power_off_timeout
809 else:
810 boot_timeout = power_on_timeout
811 st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500812 interval="10 seconds")
Michael Walsh6741f742017-02-20 16:16:38 -0600813
814 plug_in_setup()
815 rc, shell_rc, failed_plug_in_name = \
816 grpi.rprocess_plug_in_packages(call_point="post_boot")
817 if rc != 0:
818 error_message = "Plug-in failed with non-zero return code.\n" +\
819 gp.sprint_var(rc, 1)
820 BuiltIn().fail(gp.sprint_error(error_message))
821
Michael Walsh6741f742017-02-20 16:16:38 -0600822
Michael Walsh6741f742017-02-20 16:16:38 -0600823def test_loop_body():
Michael Walsh6741f742017-02-20 16:16:38 -0600824 r"""
825 The main loop body for the loop in main_py.
826
827 Description of arguments:
828 boot_count The iteration number (starts at 1).
829 """
830
831 global boot_count
832 global state
833 global next_boot
834 global boot_success
Sunil M325eb542017-08-10 07:09:43 -0500835 global boot_end_time
Michael Walsh6741f742017-02-20 16:16:38 -0600836
Michael Walshb5839d02017-04-12 16:11:20 -0500837 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600838
839 next_boot = select_boot()
Michael Walshb5839d02017-04-12 16:11:20 -0500840 if next_boot == "":
841 return True
Michael Walsh6741f742017-02-20 16:16:38 -0600842
Michael Walshb5839d02017-04-12 16:11:20 -0500843 boot_count += 1
844 gp.qprint_timen("Starting boot " + str(boot_count) + ".")
Michael Walsh6741f742017-02-20 16:16:38 -0600845
Michael Walshe0cf8d72017-05-17 13:20:46 -0500846 pre_boot_plug_in_setup()
Michael Walsh6741f742017-02-20 16:16:38 -0600847
848 cmd_buf = ["run_boot", next_boot]
849 boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
850 if boot_status == "FAIL":
Michael Walshb5839d02017-04-12 16:11:20 -0500851 gp.qprint(msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600852
Michael Walshb5839d02017-04-12 16:11:20 -0500853 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600854 if boot_status == "PASS":
855 boot_success = 1
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500856 completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot
857 + "\" succeeded.")
Michael Walsh6741f742017-02-20 16:16:38 -0600858 else:
859 boot_success = 0
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500860 completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot
861 + "\" failed.")
Sunil M325eb542017-08-10 07:09:43 -0500862
863 # Set boot_end_time for use by plug-ins.
864 boot_end_time = completion_msg[1:33]
865 gp.qprint_var(boot_end_time)
866
867 gp.qprint(completion_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600868
869 boot_results.update(next_boot, boot_status)
870
871 plug_in_setup()
872 # NOTE: A post_test_case call point failure is NOT counted as a boot
873 # failure.
874 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500875 call_point='post_test_case', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600876
877 plug_in_setup()
878 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh89de14a2018-10-01 16:51:37 -0500879 call_point='ffdc_check', shell_rc=dump_ffdc_rc(),
Michael Walsh6741f742017-02-20 16:16:38 -0600880 stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
Michael Walsh89de14a2018-10-01 16:51:37 -0500881 if boot_status != "PASS" or ffdc_check == "All" or\
882 shell_rc == dump_ffdc_rc():
Michael Walsh83f4bc72017-04-20 16:49:43 -0500883 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
884 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500885 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600886
Michael Walshaabef1e2017-09-20 15:16:17 -0500887 if delete_errlogs:
888 # We need to purge error logs between boots or they build up.
889 grk.run_key("Delete Error logs", ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -0500890
Michael Walsh952f9b02017-03-09 13:11:14 -0600891 boot_results.print_report()
Michael Walshb5839d02017-04-12 16:11:20 -0500892 gp.qprint_timen("Finished boot " + str(boot_count) + ".")
Michael Walsh952f9b02017-03-09 13:11:14 -0600893
Michael Walsh6741f742017-02-20 16:16:38 -0600894 plug_in_setup()
895 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh89de14a2018-10-01 16:51:37 -0500896 call_point='stop_check', shell_rc=stop_test_rc(),
897 stop_on_non_zero_rc=1)
898 if shell_rc == stop_test_rc():
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500899 message = "Stopping as requested by user.\n"
900 gp.print_time(message)
901 BuiltIn().fail(message)
Michael Walsh6741f742017-02-20 16:16:38 -0600902
Michael Walshd139f282017-04-04 18:00:23 -0500903 # This should help prevent ConnectionErrors.
Michael Walsh0960b382017-06-22 16:23:37 -0500904 grk.run_key_u("Close All Connections")
Michael Walshd139f282017-04-04 18:00:23 -0500905
Michael Walsh6741f742017-02-20 16:16:38 -0600906 return True
907
Michael Walsh6741f742017-02-20 16:16:38 -0600908
Michael Walsh83f4bc72017-04-20 16:49:43 -0500909def obmc_boot_test_teardown():
Michael Walsh6741f742017-02-20 16:16:38 -0600910 r"""
Michael Walshc9116812017-03-10 14:23:06 -0600911 Clean up after the Main keyword.
Michael Walsh6741f742017-02-20 16:16:38 -0600912 """
913
914 if cp_setup_called:
915 plug_in_setup()
916 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500917 call_point='cleanup', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600918
Michael Walsh600876d2017-05-30 17:58:58 -0500919 if 'boot_results_file_path' in globals():
Michael Walsh6c645742018-08-17 15:02:17 -0500920 # Save boot_results and last_ten objects to a file in case they are
921 # needed again.
Michael Walsh600876d2017-05-30 17:58:58 -0500922 gp.qprint_timen("Saving boot_results to the following path.")
923 gp.qprint_var(boot_results_file_path)
Michael Walsh6c645742018-08-17 15:02:17 -0500924 pickle.dump((boot_results, last_ten),
925 open(boot_results_file_path, 'wb'),
Michael Walsh600876d2017-05-30 17:58:58 -0500926 pickle.HIGHEST_PROTOCOL)
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600927
Michael Walshff340002017-08-29 11:18:27 -0500928 global save_stack
929 # Restore any global values saved on the save_stack.
930 for parm_name in main_func_parm_list:
931 # Get the parm_value if it was saved on the stack.
932 try:
933 parm_value = save_stack.pop(parm_name)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500934 except BaseException:
Michael Walshff340002017-08-29 11:18:27 -0500935 # If it was not saved, no further action is required.
936 continue
937
938 # Restore the saved value.
939 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
940 "}\", parm_value)"
941 gp.dpissuing(cmd_buf)
942 exec(cmd_buf)
943
944 gp.dprintn(save_stack.sprint_obj())
945
Michael Walsh6741f742017-02-20 16:16:38 -0600946
Michael Walshc9116812017-03-10 14:23:06 -0600947def test_teardown():
Michael Walshc9116812017-03-10 14:23:06 -0600948 r"""
949 Clean up after this test case.
950 """
951
952 gp.qprintn()
953 cmd_buf = ["Print Error",
954 "A keyword timeout occurred ending this program.\n"]
955 BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
956
Michael Walshb5839d02017-04-12 16:11:20 -0500957 grp.rqprint_pgm_footer()
958
Michael Walshc9116812017-03-10 14:23:06 -0600959
Michael Walsh89de14a2018-10-01 16:51:37 -0500960def post_stack():
961 r"""
962 Process post_stack plug-in programs.
963 """
964
965 if not call_post_stack_plug:
966 # The caller does not wish to have post_stack plug-in processing done.
967 return
968
969 global boot_success
970
971 # NOTE: A post_stack call-point failure is NOT counted as a boot failure.
972 pre_boot_plug_in_setup()
973 # For the purposes of the following plug-ins, mark the "boot" as a success.
974 boot_success = 1
975 plug_in_setup()
Michael Walsh815b1d52018-10-30 13:32:26 -0500976 rc, shell_rc, failed_plug_in_name, history =\
977 grpi.rprocess_plug_in_packages(call_point='post_stack',
978 stop_on_plug_in_failure=0,
979 return_history=True)
980 last_ten.extend(history)
981 # Trim list to max number of entries.
982 del last_ten[:max(0, len(last_ten) - max_boot_history)]
983 if rc != 0:
984 boot_success = 0
Michael Walsh89de14a2018-10-01 16:51:37 -0500985
986 plug_in_setup()
Michael Walsh815b1d52018-10-30 13:32:26 -0500987 rc, shell_rc, failed_plug_in_name =\
988 grpi.rprocess_plug_in_packages(call_point='ffdc_check',
989 shell_rc=dump_ffdc_rc(),
990 stop_on_plug_in_failure=1,
991 stop_on_non_zero_rc=1)
992 if shell_rc == dump_ffdc_rc():
Michael Walsh89de14a2018-10-01 16:51:37 -0500993 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
994 if status != 'PASS':
995 gp.qprint_error("Call to my_ffdc failed.\n")
996
997 plug_in_setup()
998 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
999 call_point='stop_check', shell_rc=stop_test_rc(),
1000 stop_on_non_zero_rc=1)
1001 if shell_rc == stop_test_rc():
1002 message = "Stopping as requested by user.\n"
1003 gp.print_time(message)
1004 BuiltIn().fail(message)
1005
1006
Michael Walshff340002017-08-29 11:18:27 -05001007def obmc_boot_test_py(loc_boot_stack=None,
1008 loc_stack_mode=None,
1009 loc_quiet=None):
Michael Walsh6741f742017-02-20 16:16:38 -06001010 r"""
1011 Do main program processing.
1012 """
1013
Michael Walshff340002017-08-29 11:18:27 -05001014 global save_stack
1015
George Keishing36efbc02018-12-12 10:18:23 -06001016 gp.dprintn()
Michael Walshff340002017-08-29 11:18:27 -05001017 # Process function parms.
1018 for parm_name in main_func_parm_list:
1019 # Get parm's value.
George Keishing36efbc02018-12-12 10:18:23 -06001020 parm_value = eval("loc_" + parm_name)
1021 gp.dpvars(parm_name, parm_value)
Michael Walshff340002017-08-29 11:18:27 -05001022
George Keishing36efbc02018-12-12 10:18:23 -06001023 if parm_value is not None:
Michael Walshff340002017-08-29 11:18:27 -05001024 # Save the global value on a stack.
1025 cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\
1026 parm_name + "}\"), \"" + parm_name + "\")"
1027 gp.dpissuing(cmd_buf)
1028 exec(cmd_buf)
1029
1030 # Set the global value to the passed value.
1031 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
1032 "}\", loc_" + parm_name + ")"
1033 gp.dpissuing(cmd_buf)
1034 exec(cmd_buf)
1035
1036 gp.dprintn(save_stack.sprint_obj())
Michael Walshb5839d02017-04-12 16:11:20 -05001037
Michael Walsh6741f742017-02-20 16:16:38 -06001038 setup()
1039
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001040 init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
1041
Michael Walsha20da402017-03-31 16:27:45 -05001042 if ffdc_only:
1043 gp.qprint_timen("Caller requested ffdc_only.")
Michael Walshe0cf8d72017-05-17 13:20:46 -05001044 pre_boot_plug_in_setup()
Michael Walsh83f4bc72017-04-20 16:49:43 -05001045 grk.run_key_u("my_ffdc")
Michael Walsh764d2f82017-04-27 16:01:08 -05001046 return
Michael Walsha20da402017-03-31 16:27:45 -05001047
Michael Walsh6741f742017-02-20 16:16:38 -06001048 # Process caller's boot_stack.
1049 while (len(boot_stack) > 0):
1050 test_loop_body()
1051
Michael Walshb5839d02017-04-12 16:11:20 -05001052 gp.qprint_timen("Finished processing stack.")
Michael Walsh30dadae2017-02-27 14:25:52 -06001053
Michael Walsh89de14a2018-10-01 16:51:37 -05001054 post_stack()
1055
Michael Walsh6741f742017-02-20 16:16:38 -06001056 # Process caller's boot_list.
1057 if len(boot_list) > 0:
1058 for ix in range(1, max_num_tests + 1):
1059 test_loop_body()
1060
Michael Walshb5839d02017-04-12 16:11:20 -05001061 gp.qprint_timen("Completed all requested boot tests.")
1062
1063 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001064 new_fail = boot_fail - init_boot_fail
1065 if new_fail > boot_fail_threshold:
Michael Walshb5839d02017-04-12 16:11:20 -05001066 error_message = "Boot failures exceed the boot failure" +\
1067 " threshold:\n" +\
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001068 gp.sprint_var(new_fail) +\
Michael Walshb5839d02017-04-12 16:11:20 -05001069 gp.sprint_var(boot_fail_threshold)
1070 BuiltIn().fail(gp.sprint_error(error_message))