blob: 4aa63cd74f61a083059dfb01c6a87b6e79613c93 [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",
245 "ffdc_summary_list_path"]
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")
420 if os_host != "":
421 grv.rvalid_value("os_username")
422 grv.rvalid_value("os_password")
Michael Walsh0bbd8602016-11-22 11:31:49 -0600423
Michael Walsh6741f742017-02-20 16:16:38 -0600424 if pdu_host != "":
425 grv.rvalid_value("pdu_username")
426 grv.rvalid_value("pdu_password")
Michael Walsh85678942017-03-27 14:34:22 -0500427 grv.rvalid_integer("pdu_slot_no")
Michael Walsh6741f742017-02-20 16:16:38 -0600428 if openbmc_serial_host != "":
429 grv.rvalid_integer("openbmc_serial_port")
Michael Walshb5839d02017-04-12 16:11:20 -0500430 if openbmc_model == "":
431 status, ret_values =\
432 grk.run_key_u("Get BMC System Model")
433 openbmc_model = ret_values
434 BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
Michael Walsh6741f742017-02-20 16:16:38 -0600435 grv.rvalid_value("openbmc_model")
Michael Walshb5839d02017-04-12 16:11:20 -0500436 grv.rvalid_integer("max_num_tests")
Michael Walsh6741f742017-02-20 16:16:38 -0600437 grv.rvalid_integer("boot_pass")
438 grv.rvalid_integer("boot_fail")
439
440 plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
441 BuiltIn().set_global_variable("${plug_in_packages_list}",
442 plug_in_packages_list)
443
Michael Walshb5839d02017-04-12 16:11:20 -0500444 grv.rvalid_value("stack_mode", valid_values=['normal', 'skip'])
Michael Walsha20da402017-03-31 16:27:45 -0500445 if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
Michael Walsh6741f742017-02-20 16:16:38 -0600446 error_message = "You must provide either a value for either the" +\
447 " boot_list or the boot_stack parm.\n"
448 BuiltIn().fail(gp.sprint_error(error_message))
449
450 valid_boot_list(boot_list, valid_boot_types)
451 valid_boot_list(boot_stack, valid_boot_types)
452
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500453 selected_PDU_boots = list(set(boot_list + boot_stack)
454 & set(boot_lists['PDU_reboot']))
Michael Walsh11cfc8c2017-03-31 09:40:55 -0500455
456 if len(selected_PDU_boots) > 0 and pdu_host == "":
457 error_message = "You have selected the following boots which" +\
458 " require a PDU host but no value for pdu_host:\n"
459 error_message += gp.sprint_var(selected_PDU_boots)
460 error_message += gp.sprint_var(pdu_host, 2)
461 BuiltIn().fail(gp.sprint_error(error_message))
462
Michael Walsh6741f742017-02-20 16:16:38 -0600463 return
Michael Walsh0bbd8602016-11-22 11:31:49 -0600464
Michael Walsh0bbd8602016-11-22 11:31:49 -0600465
Michael Walsh6741f742017-02-20 16:16:38 -0600466def my_get_state():
Michael Walsh0bbd8602016-11-22 11:31:49 -0600467 r"""
Michael Walsh6741f742017-02-20 16:16:38 -0600468 Get the system state plus a little bit of wrapping.
Michael Walsh0bbd8602016-11-22 11:31:49 -0600469 """
470
Michael Walsh6741f742017-02-20 16:16:38 -0600471 global state
472
473 req_states = ['epoch_seconds'] + st.default_req_states
474
Michael Walshb5839d02017-04-12 16:11:20 -0500475 gp.qprint_timen("Getting system state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600476 if test_mode:
477 state['epoch_seconds'] = int(time.time())
478 else:
Michael Walshb5839d02017-04-12 16:11:20 -0500479 state = st.get_state(req_states=req_states, quiet=quiet)
480 gp.qprint_var(state)
Michael Walsh341c21e2017-01-17 16:25:20 -0600481
Michael Walsh341c21e2017-01-17 16:25:20 -0600482
Michael Walsh45ca6e42017-09-14 17:29:12 -0500483def valid_state():
Michael Walsh45ca6e42017-09-14 17:29:12 -0500484 r"""
485 Verify that our state dictionary contains no blank values. If we don't get
486 valid state data, we cannot continue to work.
487 """
488
489 if st.compare_states(state, st.invalid_state_match, 'or'):
490 error_message = "The state dictionary contains blank fields which" +\
491 " is illegal.\n" + gp.sprint_var(state)
492 BuiltIn().fail(gp.sprint_error(error_message))
493
Michael Walsh45ca6e42017-09-14 17:29:12 -0500494
Michael Walsh6741f742017-02-20 16:16:38 -0600495def select_boot():
Michael Walsh341c21e2017-01-17 16:25:20 -0600496 r"""
497 Select a boot test to be run based on our current state and return the
498 chosen boot type.
499
500 Description of arguments:
Michael Walsh6741f742017-02-20 16:16:38 -0600501 state The state of the machine.
Michael Walsh341c21e2017-01-17 16:25:20 -0600502 """
503
Michael Walsh81816742017-09-27 11:02:29 -0500504 global transitional_boot_selected
Michael Walsh30dadae2017-02-27 14:25:52 -0600505 global boot_stack
506
Michael Walshb5839d02017-04-12 16:11:20 -0500507 gp.qprint_timen("Selecting a boot test.")
Michael Walsh6741f742017-02-20 16:16:38 -0600508
Michael Walsh81816742017-09-27 11:02:29 -0500509 if transitional_boot_selected and not boot_success:
510 prior_boot = next_boot
511 boot_candidate = boot_stack.pop()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500512 gp.qprint_timen("The prior '" + next_boot + "' was chosen to"
513 + " transition to a valid state for '" + boot_candidate
514 + "' which was at the top of the boot_stack. Since"
515 + " the '" + next_boot + "' failed, the '"
516 + boot_candidate + "' has been removed from the stack"
517 + " to avoid and endless failure loop.")
Michael Walsh81816742017-09-27 11:02:29 -0500518 if len(boot_stack) == 0:
519 return ""
520
Michael Walsh6741f742017-02-20 16:16:38 -0600521 my_get_state()
Michael Walsh45ca6e42017-09-14 17:29:12 -0500522 valid_state()
Michael Walsh6741f742017-02-20 16:16:38 -0600523
Michael Walsh81816742017-09-27 11:02:29 -0500524 transitional_boot_selected = False
Michael Walsh6741f742017-02-20 16:16:38 -0600525 stack_popped = 0
526 if len(boot_stack) > 0:
527 stack_popped = 1
Michael Walshb5839d02017-04-12 16:11:20 -0500528 gp.qprint_dashes()
529 gp.qprint_var(boot_stack)
530 gp.qprint_dashes()
531 skip_boot_printed = 0
532 while len(boot_stack) > 0:
533 boot_candidate = boot_stack.pop()
534 if stack_mode == 'normal':
535 break
536 else:
537 if st.compare_states(state, boot_table[boot_candidate]['end']):
538 if not skip_boot_printed:
Michael Walshff340002017-08-29 11:18:27 -0500539 gp.qprint_var(stack_mode)
540 gp.qprintn()
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500541 gp.qprint_timen("Skipping the following boot tests"
542 + " which are unnecessary since their"
543 + " required end states match the"
544 + " current machine state:")
Michael Walshb5839d02017-04-12 16:11:20 -0500545 skip_boot_printed = 1
Michael Walshff340002017-08-29 11:18:27 -0500546 gp.qprint_var(boot_candidate)
Michael Walshb5839d02017-04-12 16:11:20 -0500547 boot_candidate = ""
548 if boot_candidate == "":
549 gp.qprint_dashes()
550 gp.qprint_var(boot_stack)
551 gp.qprint_dashes()
552 return boot_candidate
Michael Walsh6741f742017-02-20 16:16:38 -0600553 if st.compare_states(state, boot_table[boot_candidate]['start']):
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500554 gp.qprint_timen("The machine state is valid for a '"
555 + boot_candidate + "' boot test.")
Michael Walshb5839d02017-04-12 16:11:20 -0500556 gp.qprint_dashes()
557 gp.qprint_var(boot_stack)
558 gp.qprint_dashes()
Michael Walsh6741f742017-02-20 16:16:38 -0600559 return boot_candidate
Michael Walsh341c21e2017-01-17 16:25:20 -0600560 else:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500561 gp.qprint_timen("The machine state does not match the required"
562 + " starting state for a '" + boot_candidate
563 + "' boot test:")
Michael Walshff340002017-08-29 11:18:27 -0500564 gp.qprint_varx("boot_table[" + boot_candidate + "][start]",
565 boot_table[boot_candidate]['start'], 1)
Michael Walsh6741f742017-02-20 16:16:38 -0600566 boot_stack.append(boot_candidate)
Michael Walsh81816742017-09-27 11:02:29 -0500567 transitional_boot_selected = True
Michael Walsh6741f742017-02-20 16:16:38 -0600568 popped_boot = boot_candidate
569
570 # Loop through your list selecting a boot_candidates
571 boot_candidates = []
572 for boot_candidate in boot_list:
573 if st.compare_states(state, boot_table[boot_candidate]['start']):
574 if stack_popped:
575 if st.compare_states(boot_table[boot_candidate]['end'],
Gunnar Mills096cd562018-03-26 10:19:12 -0500576 boot_table[popped_boot]['start']):
Michael Walsh6741f742017-02-20 16:16:38 -0600577 boot_candidates.append(boot_candidate)
578 else:
579 boot_candidates.append(boot_candidate)
580
581 if len(boot_candidates) == 0:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500582 gp.qprint_timen("The user's boot list contained no boot tests"
583 + " which are valid for the current machine state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600584 boot_candidate = default_power_on
585 if not st.compare_states(state, boot_table[default_power_on]['start']):
586 boot_candidate = default_power_off
587 boot_candidates.append(boot_candidate)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500588 gp.qprint_timen("Using default '" + boot_candidate
589 + "' boot type to transition to valid state.")
Michael Walsh6741f742017-02-20 16:16:38 -0600590
Michael Walshb5839d02017-04-12 16:11:20 -0500591 gp.dprint_var(boot_candidates)
Michael Walsh6741f742017-02-20 16:16:38 -0600592
593 # Randomly select a boot from the candidate list.
594 boot = random.choice(boot_candidates)
Michael Walsh341c21e2017-01-17 16:25:20 -0600595
596 return boot
Michael Walsh0bbd8602016-11-22 11:31:49 -0600597
Michael Walsh55302292017-01-10 11:43:02 -0600598
Michael Walsh341c21e2017-01-17 16:25:20 -0600599def print_last_boots():
Michael Walsh341c21e2017-01-17 16:25:20 -0600600 r"""
601 Print the last ten boots done with their time stamps.
602 """
603
604 # indent 0, 90 chars wide, linefeed, char is "="
Michael Walshb5839d02017-04-12 16:11:20 -0500605 gp.qprint_dashes(0, 90)
606 gp.qprintn("Last 10 boots:\n")
Michael Walsh341c21e2017-01-17 16:25:20 -0600607
608 for boot_entry in last_ten:
609 grp.rqprint(boot_entry)
Michael Walshb5839d02017-04-12 16:11:20 -0500610 gp.qprint_dashes(0, 90)
Michael Walsh341c21e2017-01-17 16:25:20 -0600611
Michael Walsh341c21e2017-01-17 16:25:20 -0600612
Michael Walshb2e53ec2017-10-30 15:04:36 -0500613def print_defect_report(ffdc_file_list):
Michael Walsh341c21e2017-01-17 16:25:20 -0600614 r"""
615 Print a defect report.
Michael Walshb2e53ec2017-10-30 15:04:36 -0500616
617 Description of argument(s):
618 ffdc_file_list A list of files which were collected by our ffdc functions.
Michael Walsh341c21e2017-01-17 16:25:20 -0600619 """
620
Michael Walsh600876d2017-05-30 17:58:58 -0500621 # Making deliberate choice to NOT run plug_in_setup(). We don't want
622 # ffdc_prefix updated.
623 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
624 call_point='ffdc_report', stop_on_plug_in_failure=0)
625
Michael Walshe0cf8d72017-05-17 13:20:46 -0500626 # Get additional header data which may have been created by ffdc plug-ins.
627 # Also, delete the individual header files to cleanup.
628 cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\
629 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
630 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
631 shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
632 show_err=0)
633
Michael Walshb2e53ec2017-10-30 15:04:36 -0500634 # Get additional summary data which may have been created by ffdc plug-ins.
Michael Walsh600876d2017-05-30 17:58:58 -0500635 # Also, delete the individual header files to cleanup.
636 cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\
637 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
638 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
639 shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
640 show_err=0)
641
Michael Walshb2e53ec2017-10-30 15:04:36 -0500642 # ffdc_list_file_path contains a list of any ffdc files created by plug-
643 # ins, etc. Read that data into a list.
Michael Walsh341c21e2017-01-17 16:25:20 -0600644 try:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500645 plug_in_ffdc_list = \
646 open(ffdc_list_file_path, 'r').read().rstrip("\n").split("\n")
George Keishing36efbc02018-12-12 10:18:23 -0600647 plug_in_ffdc_list = list(filter(None, plug_in_ffdc_list))
Michael Walsh341c21e2017-01-17 16:25:20 -0600648 except IOError:
Michael Walshb2e53ec2017-10-30 15:04:36 -0500649 plug_in_ffdc_list = []
650
651 # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
652 # in. Eliminate duplicates and sort the list.
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500653 ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
Michael Walshb2e53ec2017-10-30 15:04:36 -0500654
655 if status_file_path != "":
656 ffdc_file_list.insert(0, status_file_path)
657
658 # Convert the list to a printable list.
659 printable_ffdc_file_list = "\n".join(ffdc_file_list)
Michael Walsh341c21e2017-01-17 16:25:20 -0600660
Michael Walsh68a61162017-04-25 11:54:06 -0500661 # Open ffdc_file_list for writing. We will write a complete list of
662 # FFDC files to it for possible use by plug-ins like cp_stop_check.
663 ffdc_list_file = open(ffdc_list_file_path, 'w')
Michael Walshb2e53ec2017-10-30 15:04:36 -0500664 ffdc_list_file.write(printable_ffdc_file_list + "\n")
665 ffdc_list_file.close()
666
667 indent = 0
668 width = 90
669 linefeed = 1
670 char = "="
Michael Walsh68a61162017-04-25 11:54:06 -0500671
672 gp.qprintn()
Michael Walshb2e53ec2017-10-30 15:04:36 -0500673 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500674 gp.qprintn("Copy this data to the defect:\n")
675
Michael Walshe0cf8d72017-05-17 13:20:46 -0500676 if len(more_header_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500677 gp.qprintn(more_header_info)
Michael Walshdc80d672017-05-09 12:58:32 -0500678 gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
679 openbmc_host_name, openbmc_ip, openbmc_username,
680 openbmc_password, os_host, os_host_name, os_ip, os_username,
681 os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
682 pdu_password, pdu_slot_no, openbmc_serial_host,
683 openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
Michael Walsh68a61162017-04-25 11:54:06 -0500684
685 gp.qprintn()
Michael Walsh68a61162017-04-25 11:54:06 -0500686 print_last_boots()
687 gp.qprintn()
688 gp.qprint_var(state)
Michael Walshb5839d02017-04-12 16:11:20 -0500689 gp.qprintn()
690 gp.qprintn("FFDC data files:")
Michael Walshb2e53ec2017-10-30 15:04:36 -0500691 gp.qprintn(printable_ffdc_file_list)
Michael Walshb5839d02017-04-12 16:11:20 -0500692 gp.qprintn()
Michael Walsh341c21e2017-01-17 16:25:20 -0600693
Michael Walsh600876d2017-05-30 17:58:58 -0500694 if len(ffdc_summary_info) > 0:
Michael Walshff340002017-08-29 11:18:27 -0500695 gp.qprintn(ffdc_summary_info)
Michael Walsh600876d2017-05-30 17:58:58 -0500696
Michael Walshb2e53ec2017-10-30 15:04:36 -0500697 gp.qprint_dashes(indent, width, linefeed, char)
Michael Walsh68a61162017-04-25 11:54:06 -0500698
Michael Walsh6741f742017-02-20 16:16:38 -0600699
Michael Walsh6741f742017-02-20 16:16:38 -0600700def my_ffdc():
Michael Walsh6741f742017-02-20 16:16:38 -0600701 r"""
702 Collect FFDC data.
703 """
704
705 global state
706
707 plug_in_setup()
708 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500709 call_point='ffdc', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600710
711 AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500712 status, ffdc_file_list = grk.run_key_u("FFDC ffdc_prefix="
713 + AUTOBOOT_FFDC_PREFIX
714 + " ffdc_function_list="
715 + ffdc_function_list, ignore=1)
Michael Walsh83f4bc72017-04-20 16:49:43 -0500716 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500717 gp.qprint_error("Call to ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600718
719 my_get_state()
720
Michael Walshb2e53ec2017-10-30 15:04:36 -0500721 print_defect_report(ffdc_file_list)
Michael Walsh6741f742017-02-20 16:16:38 -0600722
Michael Walsh6741f742017-02-20 16:16:38 -0600723
Michael Walsh6741f742017-02-20 16:16:38 -0600724def print_test_start_message(boot_keyword):
Michael Walsh6741f742017-02-20 16:16:38 -0600725 r"""
726 Print a message indicating what boot test is about to run.
727
728 Description of arguments:
729 boot_keyword The name of the boot which is to be run
730 (e.g. "BMC Power On").
731 """
732
733 global last_ten
Sunil M325eb542017-08-10 07:09:43 -0500734 global boot_start_time
Michael Walsh6741f742017-02-20 16:16:38 -0600735
736 doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
Sunil M325eb542017-08-10 07:09:43 -0500737
738 # Set boot_start_time for use by plug-ins.
739 boot_start_time = doing_msg[1:33]
740 gp.qprint_var(boot_start_time)
741
Michael Walshb5839d02017-04-12 16:11:20 -0500742 gp.qprint(doing_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600743
744 last_ten.append(doing_msg)
745
Michael Walsh815b1d52018-10-30 13:32:26 -0500746 # Trim list to max number of entries.
747 del last_ten[:max(0, len(last_ten) - max_boot_history)]
Michael Walsh6741f742017-02-20 16:16:38 -0600748
Michael Walsh6741f742017-02-20 16:16:38 -0600749
Michael Walsh6741f742017-02-20 16:16:38 -0600750def run_boot(boot):
Michael Walsh6741f742017-02-20 16:16:38 -0600751 r"""
752 Run the specified boot.
753
754 Description of arguments:
755 boot The name of the boot test to be performed.
756 """
757
758 global state
759
760 print_test_start_message(boot)
761
762 plug_in_setup()
763 rc, shell_rc, failed_plug_in_name = \
764 grpi.rprocess_plug_in_packages(call_point="pre_boot")
765 if rc != 0:
766 error_message = "Plug-in failed with non-zero return code.\n" +\
767 gp.sprint_var(rc, 1)
768 BuiltIn().fail(gp.sprint_error(error_message))
769
770 if test_mode:
771 # In test mode, we'll pretend the boot worked by assigning its
772 # required end state to the default state value.
Michael Walsh30dadae2017-02-27 14:25:52 -0600773 state = st.strip_anchor_state(boot_table[boot]['end'])
Michael Walsh6741f742017-02-20 16:16:38 -0600774 else:
775 # Assertion: We trust that the state data was made fresh by the
776 # caller.
777
Michael Walshb5839d02017-04-12 16:11:20 -0500778 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600779
780 if boot_table[boot]['method_type'] == "keyword":
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600781 rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
Michael Walshb5839d02017-04-12 16:11:20 -0500782 boot_table[boot]['method'],
783 quiet=quiet)
Michael Walsh6741f742017-02-20 16:16:38 -0600784
785 if boot_table[boot]['bmc_reboot']:
786 st.wait_for_comm_cycle(int(state['epoch_seconds']))
Michael Walsh30dadae2017-02-27 14:25:52 -0600787 plug_in_setup()
788 rc, shell_rc, failed_plug_in_name = \
789 grpi.rprocess_plug_in_packages(call_point="post_reboot")
790 if rc != 0:
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600791 error_message = "Plug-in failed with non-zero return code.\n"
792 error_message += gp.sprint_var(rc, 1)
Michael Walsh30dadae2017-02-27 14:25:52 -0600793 BuiltIn().fail(gp.sprint_error(error_message))
Michael Walsh6741f742017-02-20 16:16:38 -0600794 else:
795 match_state = st.anchor_state(state)
796 del match_state['epoch_seconds']
797 # Wait for the state to change in any way.
798 st.wait_state(match_state, wait_time=state_change_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500799 interval="10 seconds", invert=1)
Michael Walsh6741f742017-02-20 16:16:38 -0600800
Michael Walshb5839d02017-04-12 16:11:20 -0500801 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600802 if boot_table[boot]['end']['chassis'] == "Off":
803 boot_timeout = power_off_timeout
804 else:
805 boot_timeout = power_on_timeout
806 st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
Michael Walsh600876d2017-05-30 17:58:58 -0500807 interval="10 seconds")
Michael Walsh6741f742017-02-20 16:16:38 -0600808
809 plug_in_setup()
810 rc, shell_rc, failed_plug_in_name = \
811 grpi.rprocess_plug_in_packages(call_point="post_boot")
812 if rc != 0:
813 error_message = "Plug-in failed with non-zero return code.\n" +\
814 gp.sprint_var(rc, 1)
815 BuiltIn().fail(gp.sprint_error(error_message))
816
Michael Walsh6741f742017-02-20 16:16:38 -0600817
Michael Walsh6741f742017-02-20 16:16:38 -0600818def test_loop_body():
Michael Walsh6741f742017-02-20 16:16:38 -0600819 r"""
820 The main loop body for the loop in main_py.
821
822 Description of arguments:
823 boot_count The iteration number (starts at 1).
824 """
825
826 global boot_count
827 global state
828 global next_boot
829 global boot_success
Sunil M325eb542017-08-10 07:09:43 -0500830 global boot_end_time
Michael Walsh6741f742017-02-20 16:16:38 -0600831
Michael Walshb5839d02017-04-12 16:11:20 -0500832 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600833
834 next_boot = select_boot()
Michael Walshb5839d02017-04-12 16:11:20 -0500835 if next_boot == "":
836 return True
Michael Walsh6741f742017-02-20 16:16:38 -0600837
Michael Walshb5839d02017-04-12 16:11:20 -0500838 boot_count += 1
839 gp.qprint_timen("Starting boot " + str(boot_count) + ".")
Michael Walsh6741f742017-02-20 16:16:38 -0600840
Michael Walshe0cf8d72017-05-17 13:20:46 -0500841 pre_boot_plug_in_setup()
Michael Walsh6741f742017-02-20 16:16:38 -0600842
843 cmd_buf = ["run_boot", next_boot]
844 boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
845 if boot_status == "FAIL":
Michael Walshb5839d02017-04-12 16:11:20 -0500846 gp.qprint(msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600847
Michael Walshb5839d02017-04-12 16:11:20 -0500848 gp.qprintn()
Michael Walsh6741f742017-02-20 16:16:38 -0600849 if boot_status == "PASS":
850 boot_success = 1
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500851 completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot
852 + "\" succeeded.")
Michael Walsh6741f742017-02-20 16:16:38 -0600853 else:
854 boot_success = 0
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500855 completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot
856 + "\" failed.")
Sunil M325eb542017-08-10 07:09:43 -0500857
858 # Set boot_end_time for use by plug-ins.
859 boot_end_time = completion_msg[1:33]
860 gp.qprint_var(boot_end_time)
861
862 gp.qprint(completion_msg)
Michael Walsh6741f742017-02-20 16:16:38 -0600863
864 boot_results.update(next_boot, boot_status)
865
866 plug_in_setup()
867 # NOTE: A post_test_case call point failure is NOT counted as a boot
868 # failure.
869 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500870 call_point='post_test_case', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600871
872 plug_in_setup()
873 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh89de14a2018-10-01 16:51:37 -0500874 call_point='ffdc_check', shell_rc=dump_ffdc_rc(),
Michael Walsh6741f742017-02-20 16:16:38 -0600875 stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
Michael Walsh89de14a2018-10-01 16:51:37 -0500876 if boot_status != "PASS" or ffdc_check == "All" or\
877 shell_rc == dump_ffdc_rc():
Michael Walsh83f4bc72017-04-20 16:49:43 -0500878 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
879 if status != 'PASS':
Michael Walshff340002017-08-29 11:18:27 -0500880 gp.qprint_error("Call to my_ffdc failed.\n")
Michael Walsh6741f742017-02-20 16:16:38 -0600881
Michael Walshaabef1e2017-09-20 15:16:17 -0500882 if delete_errlogs:
883 # We need to purge error logs between boots or they build up.
884 grk.run_key("Delete Error logs", ignore=1)
Michael Walshd139f282017-04-04 18:00:23 -0500885
Michael Walsh952f9b02017-03-09 13:11:14 -0600886 boot_results.print_report()
Michael Walshb5839d02017-04-12 16:11:20 -0500887 gp.qprint_timen("Finished boot " + str(boot_count) + ".")
Michael Walsh952f9b02017-03-09 13:11:14 -0600888
Michael Walsh6741f742017-02-20 16:16:38 -0600889 plug_in_setup()
890 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh89de14a2018-10-01 16:51:37 -0500891 call_point='stop_check', shell_rc=stop_test_rc(),
892 stop_on_non_zero_rc=1)
893 if shell_rc == stop_test_rc():
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500894 message = "Stopping as requested by user.\n"
895 gp.print_time(message)
896 BuiltIn().fail(message)
Michael Walsh6741f742017-02-20 16:16:38 -0600897
Michael Walshd139f282017-04-04 18:00:23 -0500898 # This should help prevent ConnectionErrors.
Michael Walsh0960b382017-06-22 16:23:37 -0500899 grk.run_key_u("Close All Connections")
Michael Walshd139f282017-04-04 18:00:23 -0500900
Michael Walsh6741f742017-02-20 16:16:38 -0600901 return True
902
Michael Walsh6741f742017-02-20 16:16:38 -0600903
Michael Walsh83f4bc72017-04-20 16:49:43 -0500904def obmc_boot_test_teardown():
Michael Walsh6741f742017-02-20 16:16:38 -0600905 r"""
Michael Walshc9116812017-03-10 14:23:06 -0600906 Clean up after the Main keyword.
Michael Walsh6741f742017-02-20 16:16:38 -0600907 """
908
909 if cp_setup_called:
910 plug_in_setup()
911 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
Michael Walsh600876d2017-05-30 17:58:58 -0500912 call_point='cleanup', stop_on_plug_in_failure=0)
Michael Walsh6741f742017-02-20 16:16:38 -0600913
Michael Walsh600876d2017-05-30 17:58:58 -0500914 if 'boot_results_file_path' in globals():
Michael Walsh6c645742018-08-17 15:02:17 -0500915 # Save boot_results and last_ten objects to a file in case they are
916 # needed again.
Michael Walsh600876d2017-05-30 17:58:58 -0500917 gp.qprint_timen("Saving boot_results to the following path.")
918 gp.qprint_var(boot_results_file_path)
Michael Walsh6c645742018-08-17 15:02:17 -0500919 pickle.dump((boot_results, last_ten),
920 open(boot_results_file_path, 'wb'),
Michael Walsh600876d2017-05-30 17:58:58 -0500921 pickle.HIGHEST_PROTOCOL)
Michael Walsh0b93fbf2017-03-02 14:42:41 -0600922
Michael Walshff340002017-08-29 11:18:27 -0500923 global save_stack
924 # Restore any global values saved on the save_stack.
925 for parm_name in main_func_parm_list:
926 # Get the parm_value if it was saved on the stack.
927 try:
928 parm_value = save_stack.pop(parm_name)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500929 except BaseException:
Michael Walshff340002017-08-29 11:18:27 -0500930 # If it was not saved, no further action is required.
931 continue
932
933 # Restore the saved value.
934 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
935 "}\", parm_value)"
936 gp.dpissuing(cmd_buf)
937 exec(cmd_buf)
938
939 gp.dprintn(save_stack.sprint_obj())
940
Michael Walsh6741f742017-02-20 16:16:38 -0600941
Michael Walshc9116812017-03-10 14:23:06 -0600942def test_teardown():
Michael Walshc9116812017-03-10 14:23:06 -0600943 r"""
944 Clean up after this test case.
945 """
946
947 gp.qprintn()
948 cmd_buf = ["Print Error",
949 "A keyword timeout occurred ending this program.\n"]
950 BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
951
Michael Walshb5839d02017-04-12 16:11:20 -0500952 grp.rqprint_pgm_footer()
953
Michael Walshc9116812017-03-10 14:23:06 -0600954
Michael Walsh89de14a2018-10-01 16:51:37 -0500955def post_stack():
956 r"""
957 Process post_stack plug-in programs.
958 """
959
960 if not call_post_stack_plug:
961 # The caller does not wish to have post_stack plug-in processing done.
962 return
963
964 global boot_success
965
966 # NOTE: A post_stack call-point failure is NOT counted as a boot failure.
967 pre_boot_plug_in_setup()
968 # For the purposes of the following plug-ins, mark the "boot" as a success.
969 boot_success = 1
970 plug_in_setup()
Michael Walsh815b1d52018-10-30 13:32:26 -0500971 rc, shell_rc, failed_plug_in_name, history =\
972 grpi.rprocess_plug_in_packages(call_point='post_stack',
973 stop_on_plug_in_failure=0,
974 return_history=True)
975 last_ten.extend(history)
976 # Trim list to max number of entries.
977 del last_ten[:max(0, len(last_ten) - max_boot_history)]
978 if rc != 0:
979 boot_success = 0
Michael Walsh89de14a2018-10-01 16:51:37 -0500980
981 plug_in_setup()
Michael Walsh815b1d52018-10-30 13:32:26 -0500982 rc, shell_rc, failed_plug_in_name =\
983 grpi.rprocess_plug_in_packages(call_point='ffdc_check',
984 shell_rc=dump_ffdc_rc(),
985 stop_on_plug_in_failure=1,
986 stop_on_non_zero_rc=1)
987 if shell_rc == dump_ffdc_rc():
Michael Walsh89de14a2018-10-01 16:51:37 -0500988 status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
989 if status != 'PASS':
990 gp.qprint_error("Call to my_ffdc failed.\n")
991
992 plug_in_setup()
993 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
994 call_point='stop_check', shell_rc=stop_test_rc(),
995 stop_on_non_zero_rc=1)
996 if shell_rc == stop_test_rc():
997 message = "Stopping as requested by user.\n"
998 gp.print_time(message)
999 BuiltIn().fail(message)
1000
1001
Michael Walshff340002017-08-29 11:18:27 -05001002def obmc_boot_test_py(loc_boot_stack=None,
1003 loc_stack_mode=None,
1004 loc_quiet=None):
Michael Walsh6741f742017-02-20 16:16:38 -06001005 r"""
1006 Do main program processing.
1007 """
1008
Michael Walshff340002017-08-29 11:18:27 -05001009 global save_stack
1010
George Keishing36efbc02018-12-12 10:18:23 -06001011 gp.dprintn()
Michael Walshff340002017-08-29 11:18:27 -05001012 # Process function parms.
1013 for parm_name in main_func_parm_list:
1014 # Get parm's value.
George Keishing36efbc02018-12-12 10:18:23 -06001015 parm_value = eval("loc_" + parm_name)
1016 gp.dpvars(parm_name, parm_value)
Michael Walshff340002017-08-29 11:18:27 -05001017
George Keishing36efbc02018-12-12 10:18:23 -06001018 if parm_value is not None:
Michael Walshff340002017-08-29 11:18:27 -05001019 # Save the global value on a stack.
1020 cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\
1021 parm_name + "}\"), \"" + parm_name + "\")"
1022 gp.dpissuing(cmd_buf)
1023 exec(cmd_buf)
1024
1025 # Set the global value to the passed value.
1026 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
1027 "}\", loc_" + parm_name + ")"
1028 gp.dpissuing(cmd_buf)
1029 exec(cmd_buf)
1030
1031 gp.dprintn(save_stack.sprint_obj())
Michael Walshb5839d02017-04-12 16:11:20 -05001032
Michael Walsh6741f742017-02-20 16:16:38 -06001033 setup()
1034
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001035 init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
1036
Michael Walsha20da402017-03-31 16:27:45 -05001037 if ffdc_only:
1038 gp.qprint_timen("Caller requested ffdc_only.")
Michael Walshe0cf8d72017-05-17 13:20:46 -05001039 pre_boot_plug_in_setup()
Michael Walsh83f4bc72017-04-20 16:49:43 -05001040 grk.run_key_u("my_ffdc")
Michael Walsh764d2f82017-04-27 16:01:08 -05001041 return
Michael Walsha20da402017-03-31 16:27:45 -05001042
Michael Walsh6741f742017-02-20 16:16:38 -06001043 # Process caller's boot_stack.
1044 while (len(boot_stack) > 0):
1045 test_loop_body()
1046
Michael Walshb5839d02017-04-12 16:11:20 -05001047 gp.qprint_timen("Finished processing stack.")
Michael Walsh30dadae2017-02-27 14:25:52 -06001048
Michael Walsh89de14a2018-10-01 16:51:37 -05001049 post_stack()
1050
Michael Walsh6741f742017-02-20 16:16:38 -06001051 # Process caller's boot_list.
1052 if len(boot_list) > 0:
1053 for ix in range(1, max_num_tests + 1):
1054 test_loop_body()
1055
Michael Walshb5839d02017-04-12 16:11:20 -05001056 gp.qprint_timen("Completed all requested boot tests.")
1057
1058 boot_pass, boot_fail = boot_results.return_total_pass_fail()
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001059 new_fail = boot_fail - init_boot_fail
1060 if new_fail > boot_fail_threshold:
Michael Walshb5839d02017-04-12 16:11:20 -05001061 error_message = "Boot failures exceed the boot failure" +\
1062 " threshold:\n" +\
Michael Walshcd9fbfd2017-09-19 12:00:08 -05001063 gp.sprint_var(new_fail) +\
Michael Walshb5839d02017-04-12 16:11:20 -05001064 gp.sprint_var(boot_fail_threshold)
1065 BuiltIn().fail(gp.sprint_error(error_message))