#!/usr/bin/env python r""" This module is the python counterpart to obmc_boot_test. """ from tally_sheet import * import gen_robot_print as grp import gen_robot_plug_in as grpi import state as st import os import time import subprocess import glob from robot.utils import DotDict from robot.libraries.BuiltIn import BuiltIn from robot.libraries.OperatingSystem import OperatingSystem # Create boot_results_fields for use in creating boot_results. boot_results_fields = DotDict([('total', 0), ('pass', 0), ('fail', 0)]) # Create boot_results which is global to this module. boot_results = tally_sheet('boot type', boot_results_fields, 'boot_test_results') boot_results.set_sum_fields(['total', 'pass', 'fail']) boot_results.set_calc_fields(['total=pass+fail']) ############################################################################### def plug_in_setup(): r""" Initialize all plug-in environment variables for use by the plug-in programs. """ boot_pass = int(BuiltIn().get_variable_value("${boot_pass}")) if boot_pass > 1: test_really_running = 1 else: test_really_running = 0 BuiltIn().set_global_variable("${test_really_running}", test_really_running) next_boot = BuiltIn().get_variable_value("${next_boot}") BuiltIn().set_global_variable("${boot_type_desc}", next_boot) # Setting master_pid correctly influences the behavior of plug-ins like # DB_Logging program_pid = BuiltIn().get_variable_value("${program_pid}") try: master_pid = OperatingSystem().get_environment_variable( "AUTOBOOT_MASTER_PID") except RuntimeError: master_pid = program_pid if master_pid == "": master_pid = program_pid BuiltIn().set_global_variable("${master_pid}", master_pid) seconds = time.time() loc_time = time.localtime(seconds) time_string = time.strftime("%y%m%d.%H%M%S.", loc_time) openbmc_nickname = BuiltIn().get_variable_value("${openbmc_nickname}") openbmc_host = BuiltIn().get_variable_value("${openbmc_host}") if openbmc_nickname == "": openbmc_nickname = openbmc_host ffdc_prefix = openbmc_nickname ffdc_prefix += "." + time_string try: ffdc_dir_path = os.environ['FFDC_DIR_PATH'] # Add trailing slash. ffdc_dir_path = os.path.normpath(ffdc_dir_path) + os.sep except KeyError: ffdc_dir_path = "" BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path) status_dir_path = os.environ.get('STATUS_DIR_PATH', "") if status_dir_path != "": # Add trailing slash. status_dir_path = os.path.normpath(status_dir_path) + os.sep BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path) base_tool_dir_path = os.environ.get('AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp") base_tool_dir_path = os.path.normpath(base_tool_dir_path) + os.sep BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path) ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\ "/FFDC_FILE_LIST" BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}", ffdc_list_file_path) # For each program parameter, set the corresponding AUTOBOOT_ environment # variable value. Also, set an AUTOBOOT_ environment variable for every # element in additional_values. additional_values = ["boot_type_desc", "boot_success", "boot_pass", "boot_fail", "test_really_running", "program_pid", "master_pid", "ffdc_prefix", "ffdc_dir_path", "status_dir_path", "base_tool_dir_path", "ffdc_list_file_path"] BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix) parm_list = BuiltIn().get_variable_value("@{parm_list}") plug_in_vars = parm_list + additional_values for var_name in plug_in_vars: var_value = BuiltIn().get_variable_value("${" + var_name + "}") var_name = var_name.upper() if var_value is None: var_value = "" OperatingSystem().set_environment_variable( "AUTOBOOT_" + var_name, var_value) debug = int(BuiltIn().get_variable_value("${debug}")) if debug: cmd_buf = "printenv | egrep AUTOBOOT_ | sort -u" grp.rpissuing(cmd_buf) sub_proc = subprocess.Popen(cmd_buf, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out_buf, err_buf = sub_proc.communicate() shell_rc = sub_proc.returncode grp.rprint(out_buf) ############################################################################### ############################################################################### def create_boot_results_table(): r""" Create our boot_results_table. """ # At some point we'll want to change to reading in our boot types from # some external source (e.g. file). boot_results.add_row('BMC Power On') boot_results.add_row('BMC Power Off') ############################################################################### ############################################################################### def update_boot_results_table(boot_type, boot_status): r""" Update our boot_results_table. This includes: - Updating the record for the given boot_type by incrementing the pass or fail field. - Calling the calc method to have the totals, etc. calculated. - Updating global variables boot_pass/boot_fail. Description of arguments: boot_type The type of boot just done (e.g. "BMC Power On"). boot_status The status of the boot just done. This should be equal to either "pass" or "fail" (case-insensitive). """ boot_results.inc_row_field(boot_type, boot_status.lower()) totals_line = boot_results.calc() # The caller of obmc_boot_test can pass boot_pass/boot_fail values because # the caller may have already done some testing (e.g. "BMC OOB"). For the # sake of DB logging done by plug-ins, we want to include these in our # overall totals. initial_boot_pass = int(BuiltIn().get_variable_value( "${initial_boot_pass}")) initial_boot_fail = int(BuiltIn().get_variable_value( "${initial_boot_fail}")) BuiltIn().set_global_variable("${boot_pass}", totals_line['pass'] + initial_boot_pass) BuiltIn().set_global_variable("${boot_fail}", totals_line['fail'] + initial_boot_fail) ############################################################################### ############################################################################### def print_boot_results_table(header_footer="\n"): r""" Print the formatted boot_resuls_table to the console. """ grp.rqprint(header_footer) grp.rqprint(boot_results.sprint_report()) grp.rqprint(header_footer) ############################################################################### ############################################################################### def select_boot(state): r""" Select a boot test to be run based on our current state and return the chosen boot type. Description of arguments: state The state of the machine, which will include the power state.. """ if 'chassis' in state: # New style state. if state['chassis'] == 'Off': boot = 'BMC Power On' else: boot = 'BMC Power Off' else: # Old style state. if state['power'] == 0: boot = 'BMC Power On' else: boot = 'BMC Power Off' return boot ############################################################################### ############################################################################### def my_ffdc(): r""" Collect FFDC data. """ plug_in_setup() rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( call_point='ffdc', stop_on_plug_in_failure=1) AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX'] # FFDC_LOG_PATH is used by "FFDC" keyword. FFDC_DIR_PATH = BuiltIn().get_variable_value("${FFDC_DIR_PATH}") BuiltIn().set_global_variable("${FFDC_LOG_PATH}", FFDC_DIR_PATH) cmd_buf = ["FFDC", "ffdc_prefix=" + AUTOBOOT_FFDC_PREFIX] grp.rpissuing_keyword(cmd_buf) BuiltIn().run_keyword(*cmd_buf) state = st.get_state() BuiltIn().set_global_variable("${state}", state) cmd_buf = ["Print Defect Report"] grp.rpissuing_keyword(cmd_buf) BuiltIn().run_keyword(*cmd_buf) ############################################################################### ############################################################################### def print_last_boots(): r""" Print the last ten boots done with their time stamps. """ # indent 0, 90 chars wide, linefeed, char is "=" grp.rqprint_dashes(0, 90) grp.rqprintn("Last 10 boots:\n") last_ten = BuiltIn().get_variable_value("${LAST_TEN}") for boot_entry in last_ten: grp.rqprint(boot_entry) grp.rqprint_dashes(0, 90) ############################################################################### ############################################################################### def print_test_start_message(boot_keyword): r""" Print a message indicating what boot test is about to run. Description of arguments: boot_keyword The name of the boot which is to be run (e.g. "BMC Power On"). """ doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".") grp.rqprint(doing_msg) last_ten = BuiltIn().get_variable_value("${LAST_TEN}") last_ten.append(doing_msg) if len(last_ten) > 10: del last_ten[0] ############################################################################### ############################################################################### def print_defect_report(): r""" Print a defect report. """ grp.rqprintn() # indent=0, width=90, linefeed=1, char="=" grp.rqprint_dashes(0, 90, 1, "=") grp.rqprintn("Copy this data to the defect:\n") parm_list = BuiltIn().get_variable_value("${parm_list}") grp.rqpvars(*parm_list) grp.rqprintn() print_last_boots() grp.rqprintn() state = BuiltIn().get_variable_value("${state}") grp.rqpvar(state) # At some point I'd like to have the 'Call FFDC Methods' return a list # of files it has collected. In that case, the following "ls" command # would no longer be needed. For now, however, glob shows the files # named in FFDC_LIST_FILE_PATH so I will refrain from printing those # out (so we don't see duplicates in the list). LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}") output = '\n'.join(glob.glob(LOG_PREFIX + '*')) FFDC_LIST_FILE_PATH = \ BuiltIn().get_variable_value("${FFDC_LIST_FILE_PATH}") try: ffdc_list = open(FFDC_LIST_FILE_PATH, 'r') except IOError: ffdc_list = "" status_file_path = BuiltIn().get_variable_value("${status_file_path}") grp.rqprintn() grp.rqprintn("FFDC data files:") if status_file_path != "": grp.rqprintn(status_file_path) grp.rqprintn(output) # grp.rqprintn(ffdc_list) grp.rqprintn() grp.rqprint_dashes(0, 90, 1, "=") ###############################################################################