Initial base infrastructure support for open BMC FFDC
This change includes the following
- initial support struture for FFDC
- scp connection introduced
Resolves openbmc/openbmc-test-automation#39
Change-Id: Id0656401b1f4b73d4b2500e70c9ba78f11bd7879
Signed-off-by: George Keishing <gkeishin@in.ibm.com>
diff --git a/.gitignore b/.gitignore
index 8d80b3a..1cdf9a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
/.tox/
/tools/argument_file.txt
/logsdir/
+/logs
diff --git a/lib/connection_client.robot b/lib/connection_client.robot
index b67996c..e3bbdff 100755
--- a/lib/connection_client.robot
+++ b/lib/connection_client.robot
@@ -53,6 +53,14 @@
Login ${username} ${password}
+Open Connection for SCP
+ Import Library SCPLibrary WITH NAME scp
+ Run Keyword If '${SSH_PORT}' == '${EMPTY}' scp.Open connection ${OPENBMC_HOST}
+ ... username=${OPENBMC_USERNAME} password=${OPENBMC_PASSWORD}
+ ... ELSE Run Keyword scp.Open connection ${OPENBMC_HOST} port=${SSH_PORT}
+ ... username=${OPENBMC_USERNAME} password=${OPENBMC_PASSWORD}
+
+
User input SSH and HTTPs Ports
[Documentation] Update the global SSH and HTTPs port variable for QEMU
${port_num}= Convert To Integer ${SSH_PORT}
diff --git a/lib/openbmc_ffdc.robot b/lib/openbmc_ffdc.robot
new file mode 100644
index 0000000..eb0bd71
--- /dev/null
+++ b/lib/openbmc_ffdc.robot
@@ -0,0 +1,156 @@
+*** Settings ***
+Documentation This module is for collecting data on test case failure
+... for openbmc systems. It will collect the data with a
+... default name openbmc_ffdc_report.txt under directory
+... logs/testSuite/testcaseName/ on failure.
+
+Library String
+Library DateTime
+Library openbmc_ffdc_list.py
+
+Resource resource.txt
+Resource connection_client.robot
+
+*** Variables ***
+
+${PRINT_LINE} ------------------------------------------------------------------------
+
+${MSG_INTRO} This document contains the following information:
+${MSG_DETAIL} ${\n}\t\t[ Detailed Logs Captured Section ]
+${HEADER_MSG} ${\n}${PRINT_LINE}${\n}\t\tOPEN BMC TEST FAILURE DATA CAPTURE
+... ${\n}\t\t----------------------------------
+... ${\n}${\n}TEST SUITE FILE\t\t: ${SUITE_NAME} ${\n}
+${FOOTER_MSG} ${PRINT_LINE} ${\n}
+
+${FFDC_LOG_PATH} ${EXECDIR}${/}logs${/}
+
+*** Keywords ***
+
+Log FFDC
+ [Documentation] Generic FFDC entry point. Place holder to hook in
+ ... other data collection
+
+ Log FFDC If Test Case Failed
+
+
+Log FFDC If Test Case Failed
+ [Documentation] Main entry point to gather logs on Test case failure
+
+ # Return from here if the test case is a PASS
+ Return From Keyword If '${TEST_STATUS}' != 'FAIL'
+
+ ${cur_time}= get current time stamp
+ Log To Console ${\n}FFDC Collection Started \t: ${cur_time}
+ # Log directory setup
+ ${suite_dir}= get strip string ${SUITE_NAME}
+ ${testname_dir}= get strip string ${TEST_NAME}
+
+ Set Suite Variable ${FFDC_DIR_PATH} ${FFDC_LOG_PATH}${suite_dir}${/}${testname_dir}
+
+ # -- FFDC workspace create --
+ create ffdc directory
+ openbmc header message
+
+ # -- FFDC processing entry point --
+ Execute FFDC command list on BMC
+
+ ${cur_time}= get current time stamp
+ Log To Console FFDC Collection Completed \t: ${cur_time}
+ Log ${\n}${FFDC_DIR_PATH}
+
+
+create ffdc directory
+ [Documentation] Creates directory and report file
+ Create Directory ${FFDC_DIR_PATH}
+ create ffdc report file
+
+
+create ffdc report file
+ [Documentation] Create a generic file name for ffdc
+ Set Suite Variable ${FFDC_FILE_PATH} ${FFDC_DIR_PATH}${/}openbmc_ffdc_report.txt
+ Create File ${FFDC_FILE_PATH}
+
+
+write data to file
+ [Documentation] Write data to the ffdc report document
+ [Arguments] ${data}=""
+ Append To File ${FFDC_FILE_PATH} ${data}
+
+
+get current time stamp
+ [Documentation] Get the current time stamp data
+ ${cur_time}= Get Current Date result_format=%Y-%m-%d %H:%M:%S,%f
+ [return] ${cur_time}
+
+openbmc header message
+ [Documentation] Write header message to the report document
+ ${cur_time}= get current time stamp
+ write data to file ${HEADER_MSG}
+ write data to file TEST CASE NAME\t\t: ${TEST_NAME}${\n}
+ write data to file FAILURE TIME STAMP\t: ${cur_time}${\n}
+ write data to file ${\n}${MSG_INTRO}${\n}
+
+ # --- FFDC header notes ---
+ @{entries}= Get ffdc index
+ :FOR ${index} IN @{entries}
+ \ write data to file * ${index.upper()}
+ \ write data to file ${\n}
+
+ write data to file ${FOOTER_MSG}
+ write data to file ${MSG_DETAIL}
+
+write cmd output to ffdc file
+ [Documentation] Write cmd output data to the report document
+ [Arguments] ${data_str}="" ${data_cmd}=""
+ write data to file ${\n}${FOOTER_MSG}
+ write data to file ${ENTRY_CMD_TYPE.upper()} : ${data_str}\t
+ write data to file Executed : ${data_cmd} ${\n}
+ write data to file ${FOOTER_MSG}
+
+
+Execute FFDC command list on BMC
+ [Documentation] Get the commands, connect to BMC and execute commands
+ ${con_status}= Run Keyword And Return Status Open Connection And Log In
+ Run Keyword And Return If ${con_status} == ${False} Log Open Connection Failed
+
+ @{entries}= Get ffdc index
+ :FOR ${index} IN @{entries}
+ \ Loop through ffdc dict list and execute ${index}
+
+
+Loop through ffdc dict list and execute
+ [Documentation] Feed in key pair list from dictionary to execute
+ [Arguments] ${data_str}=
+ @{ffdc_default_list}= Get ffdc cmd ${data_str}
+
+ Set Suite Variable ${ENTRY_CMD_TYPE} ${data_str}
+ :FOR ${cmd} IN @{ffdc_default_list}
+ \ Execute command and write to ffdc ${cmd[0]} ${cmd[1]}
+
+
+Execute command and write to ffdc
+ [Documentation] Execute command on bmc box and write to ffdc
+ [Arguments] ${data_str}="" ${data_cmd}=""
+ write cmd output to ffdc file ${data_str} ${data_cmd}
+
+ ${stdout} ${stderr}= Execute Command ${data_cmd} return_stderr=True
+ # Write stdout data on success and error msg to the file on failure
+ Run Keyword If '${stderr}' == '${EMPTY}' write data to file ${stdout} ${\n}
+ ... ELSE Run Keyword write data to file ${stderr} ${\n}
+ write data to file ${FOOTER_MSG}
+
+
+Offload file list from BMC
+ [Documentation] Copy files to current log directory
+ ${con_status}= Run Keyword And Return Status Open Connection for SCP
+ Run Keyword And Return If ${con_status} == ${False} Log SCP Connection Failed
+
+ # --- Files to be copied ---
+ @{ffdc_default_list}= Get ffdc file BMC Files
+ Set Suite Variable ${ENTRY_CMD_TYPE} BMC Files
+
+ :FOR ${cmd} IN @{ffdc_default_list}
+ # Get File from server to current test FFDC directory
+ \ write cmd output to ffdc file ${cmd[0]} scp file ${cmd[1]}
+ \ scp.Get File ${cmd[1]} ${FFDC_DIR_PATH}
+
diff --git a/lib/openbmc_ffdc_list.py b/lib/openbmc_ffdc_list.py
new file mode 100644
index 0000000..3a2950a
--- /dev/null
+++ b/lib/openbmc_ffdc_list.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+'''
+#############################################################
+# @file openbmc_ffdc_list.py
+# @author: George Keishing
+#
+# @brief List for FFDC ( First failure data capture )
+# commands and files to be collected as a part
+# of the test case failure.
+#############################################################
+'''
+
+#-------------------
+# FFDC default list
+#-------------------
+
+#-----------------------------------------------------------------
+#Dict Name { Index string : { Key String : Comand string} }
+#-----------------------------------------------------------------
+FFDC_CMD = {
+ 'DRIVER INFO' :
+ {
+ 'FW Level' : 'cat /etc/os-release',
+ 'OS Details' : 'uname -a',
+ 'Build Info' : 'cat /etc/version',
+ },
+ 'BMC DATA' :
+ {
+ 'System journal log' : 'journalctl --no-pager',
+ 'Displays processor activity' : 'top -n 1 -b',
+ },
+ 'APPLICATION DATA' :
+ {
+ 'BMC state' : '/usr/sbin/obmcutil state',
+ },
+ }
+
+# add file list needed to be offload from BMC
+FFDC_FILE = {
+ 'BMC FILES' :
+ {
+ # Sample example how to add the file that
+ # is needed to be offloaded
+ #'Release info' : '/etc/os-release',
+ },
+ }
+
+#-----------------------------------------------------------------
+
+
+# base class for FFDC default list
+class openbmc_ffdc_list():
+
+ ########################################################################
+ # @@brief This method returns the list from the dictionary for cmds
+ # @param i_type: @type string: string index lookup
+ # @return List of key pair from the dictionary
+ ########################################################################
+ def get_ffdc_cmd(self,i_type):
+ return FFDC_CMD[i_type].items()
+
+ ########################################################################
+ # @@brief This method returns the list from the dictionary for scp
+ # @param i_type: @type string: string index lookup
+ # @return List of key pair from the dictionary
+ ########################################################################
+ def get_ffdc_file(self,i_type):
+ return FFDC_FILE[i_type].items()
+
+ ########################################################################
+ # @@brief This method returns the list index from dictionary
+ # @return List of index to the dictionary
+ ########################################################################
+ def get_ffdc_index(self):
+ return FFDC_CMD.keys()
+
+ ########################################################################
+ # @brief Returns the stripped strings
+ # @param i_str: @type string: string name
+ # @return Remove all special chars and return the string
+ ########################################################################
+ def get_strip_string(self, i_str):
+ return ''.join(e for e in i_str if e.isalnum())
+