blob: 653dde1c0ddcb9420ac56beb672cd9f1e3208569 [file] [log] [blame]
#!/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, "=")
###############################################################################