xref: /openbmc/openbmc-test-automation/lib/openbmc_ffdc.py (revision 4e8c09b1a6aace6f6bd1dfae1b999ba871f5c9b5)
1#!/usr/bin/env python
2
3r"""
4This module is the python counterpart to openbmc_ffdc.robot..
5"""
6
7import os
8
9import gen_print as gp
10import gen_robot_print as grp
11import gen_valid as gv
12import gen_robot_keyword as grk
13import state as st
14
15from robot.libraries.BuiltIn import BuiltIn
16
17
18###############################################################################
19def ffdc(ffdc_dir_path=None,
20         ffdc_prefix=None,
21         ffdc_function_list=""):
22
23    r"""
24    Gather First Failure Data Capture (FFDC).
25
26    This includes:
27    - Set global FFDC_TIME.
28    - Create FFDC work space directory.
29    - Write test info details.
30    - Call BMC methods to write/collect FFDC data.
31
32    Description of arguments:
33    ffdc_dir_path       The dir path where FFDC data should be put.
34    ffdc_prefix         The prefix to be given to each FFDC file name
35                        generated.
36    ffdc_function_list  A colon-delimited list of all the types of FFDC data
37                        you wish to have collected.  A blank value means that
38                        all possible kinds of FFDC are to be collected.  See
39                        FFDC_METHOD_CALL object in lib/openbmc_ffdc_list.py
40                        for possible choices.
41    """
42
43    ffdc_file_list = []
44
45    # Check if Ping and SSH connection is alive
46    OPENBMC_HOST = BuiltIn().get_variable_value("${OPENBMC_HOST}")
47
48    state = st.get_state(req_states=['ping', 'uptime'])
49    gp.qprint_var(state)
50    if not int(state['ping']):
51        gp.print_error("BMC is not ping-able.  Terminating FFDC collection.\n")
52        return ffdc_file_list
53
54    if state['uptime'] == "":
55        gp.print_error("BMC is not communicating.  Terminating FFDC" +
56                       " collection.\n")
57        return ffdc_file_list
58
59    gp.qprint_timen("Collecting FFDC.")
60
61    # Get default values for arguments.
62    ffdc_dir_path, ffdc_prefix = set_ffdc_defaults(ffdc_dir_path, ffdc_prefix)
63    gp.qprint_var(ffdc_dir_path)
64    gp.qprint_var(ffdc_prefix)
65
66    # LOG_PREFIX is used by subordinate functions.
67    LOG_PREFIX = ffdc_dir_path + ffdc_prefix
68    BuiltIn().set_global_variable("${LOG_PREFIX}", LOG_PREFIX)
69
70    cmd_buf = ["Create Directory", ffdc_dir_path]
71    grp.rqpissuing_keyword(cmd_buf)
72    status, output = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
73    if status != "PASS":
74        error_message = grp.sprint_error_report("Create Directory failed" +
75                                                " with the following" +
76                                                " error:\n" + output)
77        BuiltIn().fail(error_message)
78
79    # FFDC_FILE_PATH is used by Header Message.
80    FFDC_FILE_PATH = ffdc_dir_path + ffdc_prefix + "BMC_general.txt"
81    BuiltIn().set_global_variable("${FFDC_FILE_PATH}", FFDC_FILE_PATH)
82
83    status, ffdc_file_list = grk.run_key("Header Message")
84    status, ffdc_file_sub_list = \
85        grk.run_key_u("Call FFDC Methods  ffdc_function_list=" +
86                      ffdc_function_list)
87
88    # Combine lists, remove duplicates and sort.
89    ffdc_file_list = list(set(ffdc_file_list + ffdc_file_sub_list))
90    ffdc_file_list.sort()
91
92    gp.qprint_timen("Finished collecting FFDC.")
93
94    return ffdc_file_list
95
96###############################################################################
97
98
99###############################################################################
100def set_ffdc_defaults(ffdc_dir_path=None,
101                      ffdc_prefix=None):
102
103    r"""
104    Set a default value for ffdc_dir_path and ffdc_prefix if they don't
105    already have values.  Return both values.
106
107    Description of arguments:
108    ffdc_dir_path  The dir path where FFDC data should be put.
109    ffdc_prefix    The prefix to be given to each FFDC file name generated.
110
111    NOTE: If global variable ffdc_dir_path_style is set to ${1}, this function
112    will create default values in a newer way.  Otherwise, its behavior
113    will remain unchanged.
114    """
115
116    # Note: Several subordinate functions like 'Get Test Dir and Name' and
117    # 'Header Message' expect global variable FFDC_TIME to be set.
118    cmd_buf = ["Get Current Time Stamp"]
119    grp.rdpissuing_keyword(cmd_buf)
120    FFDC_TIME = BuiltIn().run_keyword(*cmd_buf)
121    BuiltIn().set_global_variable("${FFDC_TIME}", FFDC_TIME)
122
123    ffdc_dir_path_style = BuiltIn().get_variable_value(
124        "${ffdc_dir_path_style}")
125
126    if ffdc_dir_path is None:
127        if ffdc_dir_path_style:
128            try:
129                ffdc_dir_path = os.environ['FFDC_DIR_PATH']
130            except KeyError:
131                ffdc_dir_path = os.path.dirname(
132                    BuiltIn().get_variable_value("${LOG_FILE}")) + "/"
133        else:
134            FFDC_LOG_PATH = os.getcwd() + "/logs/"
135            if FFDC_LOG_PATH is None:
136                FFDC_LOG_PATH = ""
137            if FFDC_LOG_PATH == "":
138                FFDC_LOG_PATH = os.path.dirname(
139                    BuiltIn().get_variable_value("${LOG_FILE}")) + "/"
140            error_message = gv.svalid_value(FFDC_LOG_PATH,
141                                            var_name="FFDC_LOG_PATH")
142            if error_message != "":
143                error_message = grp.sprint_error_report(error_message)
144                BuiltIn().fail(error_message)
145            FFDC_LOG_PATH = os.path.normpath(FFDC_LOG_PATH) + os.sep
146
147            cmd_buf = ["Get Test Dir and Name"]
148            grp.rpissuing_keyword(cmd_buf)
149            suitename, testname = BuiltIn().run_keyword(*cmd_buf)
150
151            ffdc_dir_path = FFDC_LOG_PATH + suitename + "/" + testname + "/"
152
153    # Add trailing slash.
154    ffdc_dir_path = os.path.normpath(ffdc_dir_path) + os.sep
155
156    if ffdc_prefix is None:
157        FFDC_TIME = BuiltIn().get_variable_value("${FFDC_TIME}")
158        if ffdc_prefix is None:
159            if ffdc_dir_path_style:
160                OPENBMC_HOST = BuiltIn().get_variable_value("${OPENBMC_HOST}")
161                OPENBMC_NICKNAME = BuiltIn().get_variable_value(
162                    "${OPENBMC_NICKNAME}", default=OPENBMC_HOST)
163                ffdc_prefix = OPENBMC_NICKNAME + "." + FFDC_TIME[2:8] + "." +\
164                    FFDC_TIME[8:14] + "."
165            else:
166                ffdc_prefix = FFDC_TIME + "_"
167
168    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
169    BuiltIn().set_global_variable("${FFDC_PREFIX}", ffdc_prefix)
170
171    return ffdc_dir_path, ffdc_prefix
172
173###############################################################################
174