10bbd860fSMichael Walsh#!/usr/bin/env python 20bbd860fSMichael Walsh 30bbd860fSMichael Walshr""" 40bbd860fSMichael WalshThis module is the python counterpart to obmc_boot_test. 50bbd860fSMichael Walsh""" 60bbd860fSMichael Walsh 70bbd860fSMichael Walshfrom tally_sheet import * 80bbd860fSMichael Walshimport gen_robot_print as grp 955302295SMichael Walshimport gen_robot_plug_in as grpi 1055302295SMichael Walshimport state as st 110bbd860fSMichael Walsh 120bbd860fSMichael Walshimport os 130bbd860fSMichael Walshimport time 140bbd860fSMichael Walshimport subprocess 15*341c21ebSMichael Walshimport glob 160bbd860fSMichael Walsh 170bbd860fSMichael Walshfrom robot.utils import DotDict 180bbd860fSMichael Walshfrom robot.libraries.BuiltIn import BuiltIn 190bbd860fSMichael Walshfrom robot.libraries.OperatingSystem import OperatingSystem 200bbd860fSMichael Walsh 210bbd860fSMichael Walsh# Create boot_results_fields for use in creating boot_results. 220bbd860fSMichael Walshboot_results_fields = DotDict([('total', 0), ('pass', 0), ('fail', 0)]) 230bbd860fSMichael Walsh# Create boot_results which is global to this module. 240bbd860fSMichael Walshboot_results = tally_sheet('boot type', 250bbd860fSMichael Walsh boot_results_fields, 260bbd860fSMichael Walsh 'boot_test_results') 270bbd860fSMichael Walsh 280bbd860fSMichael Walshboot_results.set_sum_fields(['total', 'pass', 'fail']) 290bbd860fSMichael Walshboot_results.set_calc_fields(['total=pass+fail']) 300bbd860fSMichael Walsh 310bbd860fSMichael Walsh 320bbd860fSMichael Walsh############################################################################### 330bbd860fSMichael Walshdef plug_in_setup(): 340bbd860fSMichael Walsh 350bbd860fSMichael Walsh r""" 360bbd860fSMichael Walsh Initialize all plug-in environment variables for use by the plug-in 370bbd860fSMichael Walsh programs. 380bbd860fSMichael Walsh """ 390bbd860fSMichael Walsh 400bbd860fSMichael Walsh boot_pass = int(BuiltIn().get_variable_value("${boot_pass}")) 410bbd860fSMichael Walsh if boot_pass > 1: 420bbd860fSMichael Walsh test_really_running = 1 430bbd860fSMichael Walsh else: 440bbd860fSMichael Walsh test_really_running = 0 450bbd860fSMichael Walsh 460bbd860fSMichael Walsh BuiltIn().set_global_variable("${test_really_running}", 470bbd860fSMichael Walsh test_really_running) 480bbd860fSMichael Walsh 490bbd860fSMichael Walsh next_boot = BuiltIn().get_variable_value("${next_boot}") 500bbd860fSMichael Walsh BuiltIn().set_global_variable("${boot_type_desc}", next_boot) 510bbd860fSMichael Walsh 520bbd860fSMichael Walsh # Setting master_pid correctly influences the behavior of plug-ins like 530bbd860fSMichael Walsh # DB_Logging 540bbd860fSMichael Walsh program_pid = BuiltIn().get_variable_value("${program_pid}") 550bbd860fSMichael Walsh try: 560bbd860fSMichael Walsh master_pid = OperatingSystem().get_environment_variable( 570bbd860fSMichael Walsh "AUTOBOOT_MASTER_PID") 580bbd860fSMichael Walsh except RuntimeError: 590bbd860fSMichael Walsh master_pid = program_pid 600bbd860fSMichael Walsh if master_pid == "": 610bbd860fSMichael Walsh master_pid = program_pid 620bbd860fSMichael Walsh 630bbd860fSMichael Walsh BuiltIn().set_global_variable("${master_pid}", master_pid) 640bbd860fSMichael Walsh 650bbd860fSMichael Walsh seconds = time.time() 660bbd860fSMichael Walsh loc_time = time.localtime(seconds) 670bbd860fSMichael Walsh time_string = time.strftime("%y%m%d.%H%M%S.", loc_time) 680bbd860fSMichael Walsh 690bbd860fSMichael Walsh openbmc_nickname = BuiltIn().get_variable_value("${openbmc_nickname}") 700bbd860fSMichael Walsh openbmc_host = BuiltIn().get_variable_value("${openbmc_host}") 71769c2a1bSMichael Walsh if openbmc_nickname == "": 7255302295SMichael Walsh openbmc_nickname = openbmc_host 730bbd860fSMichael Walsh ffdc_prefix = openbmc_nickname 740bbd860fSMichael Walsh 750bbd860fSMichael Walsh ffdc_prefix += "." + time_string 760bbd860fSMichael Walsh 7786de0d2eSMichael Walsh try: 7886de0d2eSMichael Walsh ffdc_dir_path = os.environ['FFDC_DIR_PATH'] 790bbd860fSMichael Walsh # Add trailing slash. 800bbd860fSMichael Walsh ffdc_dir_path = os.path.normpath(ffdc_dir_path) + os.sep 8186de0d2eSMichael Walsh except KeyError: 8286de0d2eSMichael Walsh ffdc_dir_path = "" 830bbd860fSMichael Walsh BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path) 840bbd860fSMichael Walsh 8555302295SMichael Walsh status_dir_path = os.environ.get('STATUS_DIR_PATH', "") 8655302295SMichael Walsh if status_dir_path != "": 8755302295SMichael Walsh # Add trailing slash. 8855302295SMichael Walsh status_dir_path = os.path.normpath(status_dir_path) + os.sep 8955302295SMichael Walsh BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path) 9055302295SMichael Walsh 9155302295SMichael Walsh base_tool_dir_path = os.environ.get('AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp") 924c9a6453SMichael Walsh base_tool_dir_path = os.path.normpath(base_tool_dir_path) + os.sep 934c9a6453SMichael Walsh BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path) 944c9a6453SMichael Walsh 9555302295SMichael Walsh ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\ 9655302295SMichael Walsh "/FFDC_FILE_LIST" 974c9a6453SMichael Walsh 984c9a6453SMichael Walsh BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}", 994c9a6453SMichael Walsh ffdc_list_file_path) 1004c9a6453SMichael Walsh 1010bbd860fSMichael Walsh # For each program parameter, set the corresponding AUTOBOOT_ environment 1020bbd860fSMichael Walsh # variable value. Also, set an AUTOBOOT_ environment variable for every 1030bbd860fSMichael Walsh # element in additional_values. 1040bbd860fSMichael Walsh additional_values = ["boot_type_desc", "boot_success", "boot_pass", 1050bbd860fSMichael Walsh "boot_fail", "test_really_running", "program_pid", 1064c9a6453SMichael Walsh "master_pid", "ffdc_prefix", "ffdc_dir_path", 10755302295SMichael Walsh "status_dir_path", "base_tool_dir_path", 10855302295SMichael Walsh "ffdc_list_file_path"] 1090bbd860fSMichael Walsh BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix) 1100bbd860fSMichael Walsh 1110bbd860fSMichael Walsh parm_list = BuiltIn().get_variable_value("@{parm_list}") 1120bbd860fSMichael Walsh 1130bbd860fSMichael Walsh plug_in_vars = parm_list + additional_values 1140bbd860fSMichael Walsh 1150bbd860fSMichael Walsh for var_name in plug_in_vars: 1160bbd860fSMichael Walsh var_value = BuiltIn().get_variable_value("${" + var_name + "}") 1170bbd860fSMichael Walsh var_name = var_name.upper() 1180bbd860fSMichael Walsh if var_value is None: 1190bbd860fSMichael Walsh var_value = "" 1200bbd860fSMichael Walsh OperatingSystem().set_environment_variable( 1210bbd860fSMichael Walsh "AUTOBOOT_" + var_name, var_value) 1220bbd860fSMichael Walsh 1230bbd860fSMichael Walsh debug = int(BuiltIn().get_variable_value("${debug}")) 1240bbd860fSMichael Walsh if debug: 1250bbd860fSMichael Walsh cmd_buf = "printenv | egrep AUTOBOOT_ | sort -u" 1260bbd860fSMichael Walsh grp.rpissuing(cmd_buf) 1270bbd860fSMichael Walsh sub_proc = subprocess.Popen(cmd_buf, shell=True, 1280bbd860fSMichael Walsh stdout=subprocess.PIPE, 1290bbd860fSMichael Walsh stderr=subprocess.STDOUT) 1300bbd860fSMichael Walsh out_buf, err_buf = sub_proc.communicate() 1310bbd860fSMichael Walsh shell_rc = sub_proc.returncode 1320bbd860fSMichael Walsh grp.rprint(out_buf) 1330bbd860fSMichael Walsh 1340bbd860fSMichael Walsh############################################################################### 1350bbd860fSMichael Walsh 1360bbd860fSMichael Walsh 1370bbd860fSMichael Walsh############################################################################### 1380bbd860fSMichael Walshdef create_boot_results_table(): 1390bbd860fSMichael Walsh 1400bbd860fSMichael Walsh r""" 1410bbd860fSMichael Walsh Create our boot_results_table. 1420bbd860fSMichael Walsh """ 1430bbd860fSMichael Walsh 1440bbd860fSMichael Walsh # At some point we'll want to change to reading in our boot types from 1450bbd860fSMichael Walsh # some external source (e.g. file). 1460bbd860fSMichael Walsh 1470bbd860fSMichael Walsh boot_results.add_row('BMC Power On') 1480bbd860fSMichael Walsh boot_results.add_row('BMC Power Off') 1490bbd860fSMichael Walsh 1500bbd860fSMichael Walsh############################################################################### 1510bbd860fSMichael Walsh 1520bbd860fSMichael Walsh 1530bbd860fSMichael Walsh############################################################################### 1540bbd860fSMichael Walshdef update_boot_results_table(boot_type, 1550bbd860fSMichael Walsh boot_status): 1560bbd860fSMichael Walsh 1570bbd860fSMichael Walsh r""" 1580bbd860fSMichael Walsh Update our boot_results_table. This includes: 1590bbd860fSMichael Walsh - Updating the record for the given boot_type by incrementing the pass or 1600bbd860fSMichael Walsh fail field. 1610bbd860fSMichael Walsh - Calling the calc method to have the totals, etc. calculated. 1620bbd860fSMichael Walsh - Updating global variables boot_pass/boot_fail. 1630bbd860fSMichael Walsh 1640bbd860fSMichael Walsh Description of arguments: 1650bbd860fSMichael Walsh boot_type The type of boot just done (e.g. "BMC Power On"). 1660bbd860fSMichael Walsh boot_status The status of the boot just done. This should be equal to 1670bbd860fSMichael Walsh either "pass" or "fail" (case-insensitive). 1680bbd860fSMichael Walsh """ 1690bbd860fSMichael Walsh 1700bbd860fSMichael Walsh boot_results.inc_row_field(boot_type, boot_status.lower()) 1710bbd860fSMichael Walsh totals_line = boot_results.calc() 1720bbd860fSMichael Walsh 1730bbd860fSMichael Walsh # The caller of obmc_boot_test can pass boot_pass/boot_fail values because 1740bbd860fSMichael Walsh # the caller may have already done some testing (e.g. "BMC OOB"). For the 1750bbd860fSMichael Walsh # sake of DB logging done by plug-ins, we want to include these in our 1760bbd860fSMichael Walsh # overall totals. 1770bbd860fSMichael Walsh initial_boot_pass = int(BuiltIn().get_variable_value( 1780bbd860fSMichael Walsh "${initial_boot_pass}")) 1790bbd860fSMichael Walsh initial_boot_fail = int(BuiltIn().get_variable_value( 1800bbd860fSMichael Walsh "${initial_boot_fail}")) 1810bbd860fSMichael Walsh 1820bbd860fSMichael Walsh BuiltIn().set_global_variable("${boot_pass}", 1830bbd860fSMichael Walsh totals_line['pass'] + initial_boot_pass) 1840bbd860fSMichael Walsh BuiltIn().set_global_variable("${boot_fail}", 1850bbd860fSMichael Walsh totals_line['fail'] + initial_boot_fail) 1860bbd860fSMichael Walsh 1870bbd860fSMichael Walsh############################################################################### 1880bbd860fSMichael Walsh 1890bbd860fSMichael Walsh 1900bbd860fSMichael Walsh############################################################################### 1910bbd860fSMichael Walshdef print_boot_results_table(header_footer="\n"): 1920bbd860fSMichael Walsh 1930bbd860fSMichael Walsh r""" 1940bbd860fSMichael Walsh Print the formatted boot_resuls_table to the console. 1950bbd860fSMichael Walsh """ 1960bbd860fSMichael Walsh 197*341c21ebSMichael Walsh grp.rqprint(header_footer) 198*341c21ebSMichael Walsh grp.rqprint(boot_results.sprint_report()) 199*341c21ebSMichael Walsh grp.rqprint(header_footer) 200*341c21ebSMichael Walsh 201*341c21ebSMichael Walsh############################################################################### 202*341c21ebSMichael Walsh 203*341c21ebSMichael Walsh 204*341c21ebSMichael Walsh############################################################################### 205*341c21ebSMichael Walshdef select_boot(state): 206*341c21ebSMichael Walsh 207*341c21ebSMichael Walsh r""" 208*341c21ebSMichael Walsh Select a boot test to be run based on our current state and return the 209*341c21ebSMichael Walsh chosen boot type. 210*341c21ebSMichael Walsh 211*341c21ebSMichael Walsh Description of arguments: 212*341c21ebSMichael Walsh state The state of the machine, which will include the power state.. 213*341c21ebSMichael Walsh """ 214*341c21ebSMichael Walsh 215*341c21ebSMichael Walsh if 'chassis' in state: 216*341c21ebSMichael Walsh # New style state. 217*341c21ebSMichael Walsh if state['chassis'] == 'Off': 218*341c21ebSMichael Walsh boot = 'BMC Power On' 219*341c21ebSMichael Walsh else: 220*341c21ebSMichael Walsh boot = 'BMC Power Off' 221*341c21ebSMichael Walsh else: 222*341c21ebSMichael Walsh # Old style state. 223*341c21ebSMichael Walsh if state['power'] == 0: 224*341c21ebSMichael Walsh boot = 'BMC Power On' 225*341c21ebSMichael Walsh else: 226*341c21ebSMichael Walsh boot = 'BMC Power Off' 227*341c21ebSMichael Walsh 228*341c21ebSMichael Walsh return boot 2290bbd860fSMichael Walsh 2300bbd860fSMichael Walsh############################################################################### 23155302295SMichael Walsh 23255302295SMichael Walsh 23355302295SMichael Walsh############################################################################### 23455302295SMichael Walshdef my_ffdc(): 23555302295SMichael Walsh 23655302295SMichael Walsh r""" 23755302295SMichael Walsh Collect FFDC data. 23855302295SMichael Walsh """ 23955302295SMichael Walsh 24055302295SMichael Walsh plug_in_setup() 24155302295SMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 24255302295SMichael Walsh call_point='ffdc', stop_on_plug_in_failure=1) 24355302295SMichael Walsh 24455302295SMichael Walsh AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX'] 24555302295SMichael Walsh 24655302295SMichael Walsh # FFDC_LOG_PATH is used by "FFDC" keyword. 24755302295SMichael Walsh FFDC_DIR_PATH = BuiltIn().get_variable_value("${FFDC_DIR_PATH}") 24855302295SMichael Walsh BuiltIn().set_global_variable("${FFDC_LOG_PATH}", 24955302295SMichael Walsh FFDC_DIR_PATH) 25055302295SMichael Walsh 25155302295SMichael Walsh cmd_buf = ["FFDC", "ffdc_prefix=" + AUTOBOOT_FFDC_PREFIX] 25255302295SMichael Walsh grp.rpissuing_keyword(cmd_buf) 25355302295SMichael Walsh BuiltIn().run_keyword(*cmd_buf) 25455302295SMichael Walsh 25555302295SMichael Walsh state = st.get_state() 25655302295SMichael Walsh BuiltIn().set_global_variable("${state}", 25755302295SMichael Walsh state) 25855302295SMichael Walsh 25955302295SMichael Walsh cmd_buf = ["Print Defect Report"] 26055302295SMichael Walsh grp.rpissuing_keyword(cmd_buf) 26155302295SMichael Walsh BuiltIn().run_keyword(*cmd_buf) 26255302295SMichael Walsh 26355302295SMichael Walsh############################################################################### 264*341c21ebSMichael Walsh 265*341c21ebSMichael Walsh 266*341c21ebSMichael Walsh############################################################################### 267*341c21ebSMichael Walshdef print_last_boots(): 268*341c21ebSMichael Walsh 269*341c21ebSMichael Walsh r""" 270*341c21ebSMichael Walsh Print the last ten boots done with their time stamps. 271*341c21ebSMichael Walsh """ 272*341c21ebSMichael Walsh 273*341c21ebSMichael Walsh # indent 0, 90 chars wide, linefeed, char is "=" 274*341c21ebSMichael Walsh grp.rqprint_dashes(0, 90) 275*341c21ebSMichael Walsh grp.rqprintn("Last 10 boots:\n") 276*341c21ebSMichael Walsh last_ten = BuiltIn().get_variable_value("${LAST_TEN}") 277*341c21ebSMichael Walsh 278*341c21ebSMichael Walsh for boot_entry in last_ten: 279*341c21ebSMichael Walsh grp.rqprint(boot_entry) 280*341c21ebSMichael Walsh grp.rqprint_dashes(0, 90) 281*341c21ebSMichael Walsh 282*341c21ebSMichael Walsh############################################################################### 283*341c21ebSMichael Walsh 284*341c21ebSMichael Walsh 285*341c21ebSMichael Walsh############################################################################### 286*341c21ebSMichael Walshdef print_test_start_message(boot_keyword): 287*341c21ebSMichael Walsh 288*341c21ebSMichael Walsh r""" 289*341c21ebSMichael Walsh Print a message indicating what boot test is about to run. 290*341c21ebSMichael Walsh 291*341c21ebSMichael Walsh Description of arguments: 292*341c21ebSMichael Walsh boot_keyword The name of the boot which is to be run 293*341c21ebSMichael Walsh (e.g. "BMC Power On"). 294*341c21ebSMichael Walsh """ 295*341c21ebSMichael Walsh 296*341c21ebSMichael Walsh doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".") 297*341c21ebSMichael Walsh grp.rqprint(doing_msg) 298*341c21ebSMichael Walsh 299*341c21ebSMichael Walsh last_ten = BuiltIn().get_variable_value("${LAST_TEN}") 300*341c21ebSMichael Walsh last_ten.append(doing_msg) 301*341c21ebSMichael Walsh 302*341c21ebSMichael Walsh if len(last_ten) > 10: 303*341c21ebSMichael Walsh del last_ten[0] 304*341c21ebSMichael Walsh 305*341c21ebSMichael Walsh############################################################################### 306*341c21ebSMichael Walsh 307*341c21ebSMichael Walsh 308*341c21ebSMichael Walsh############################################################################### 309*341c21ebSMichael Walshdef print_defect_report(): 310*341c21ebSMichael Walsh 311*341c21ebSMichael Walsh r""" 312*341c21ebSMichael Walsh Print a defect report. 313*341c21ebSMichael Walsh """ 314*341c21ebSMichael Walsh 315*341c21ebSMichael Walsh grp.rqprintn() 316*341c21ebSMichael Walsh # indent=0, width=90, linefeed=1, char="=" 317*341c21ebSMichael Walsh grp.rqprint_dashes(0, 90, 1, "=") 318*341c21ebSMichael Walsh grp.rqprintn("Copy this data to the defect:\n") 319*341c21ebSMichael Walsh 320*341c21ebSMichael Walsh parm_list = BuiltIn().get_variable_value("${parm_list}") 321*341c21ebSMichael Walsh 322*341c21ebSMichael Walsh grp.rqpvars(*parm_list) 323*341c21ebSMichael Walsh 324*341c21ebSMichael Walsh grp.rqprintn() 325*341c21ebSMichael Walsh 326*341c21ebSMichael Walsh print_last_boots() 327*341c21ebSMichael Walsh grp.rqprintn() 328*341c21ebSMichael Walsh state = BuiltIn().get_variable_value("${state}") 329*341c21ebSMichael Walsh grp.rqpvar(state) 330*341c21ebSMichael Walsh 331*341c21ebSMichael Walsh # At some point I'd like to have the 'Call FFDC Methods' return a list 332*341c21ebSMichael Walsh # of files it has collected. In that case, the following "ls" command 333*341c21ebSMichael Walsh # would no longer be needed. For now, however, glob shows the files 334*341c21ebSMichael Walsh # named in FFDC_LIST_FILE_PATH so I will refrain from printing those 335*341c21ebSMichael Walsh # out (so we don't see duplicates in the list). 336*341c21ebSMichael Walsh 337*341c21ebSMichael Walsh LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}") 338*341c21ebSMichael Walsh 339*341c21ebSMichael Walsh output = '\n'.join(glob.glob(LOG_PREFIX + '*')) 340*341c21ebSMichael Walsh 341*341c21ebSMichael Walsh FFDC_LIST_FILE_PATH = \ 342*341c21ebSMichael Walsh BuiltIn().get_variable_value("${FFDC_LIST_FILE_PATH}") 343*341c21ebSMichael Walsh 344*341c21ebSMichael Walsh try: 345*341c21ebSMichael Walsh ffdc_list = open(FFDC_LIST_FILE_PATH, 'r') 346*341c21ebSMichael Walsh except IOError: 347*341c21ebSMichael Walsh ffdc_list = "" 348*341c21ebSMichael Walsh 349*341c21ebSMichael Walsh status_file_path = BuiltIn().get_variable_value("${status_file_path}") 350*341c21ebSMichael Walsh 351*341c21ebSMichael Walsh grp.rqprintn() 352*341c21ebSMichael Walsh grp.rqprintn("FFDC data files:") 353*341c21ebSMichael Walsh if status_file_path != "": 354*341c21ebSMichael Walsh grp.rqprintn(status_file_path) 355*341c21ebSMichael Walsh 356*341c21ebSMichael Walsh grp.rqprintn(output) 357*341c21ebSMichael Walsh # grp.rqprintn(ffdc_list) 358*341c21ebSMichael Walsh grp.rqprintn() 359*341c21ebSMichael Walsh 360*341c21ebSMichael Walsh grp.rqprint_dashes(0, 90, 1, "=") 361*341c21ebSMichael Walsh 362*341c21ebSMichael Walsh############################################################################### 363