George Keishing | e7e9171 | 2021-09-03 11:28:44 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 2 | |
| 3 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 4 | This module has functions to support various data structures such as the boot_table, valid_boot_list and |
| 5 | boot_results_table. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 6 | """ |
| 7 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 8 | import glob |
| 9 | import json |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 10 | import os |
| 11 | import tempfile |
Patrick Williams | 5731818 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 12 | |
George Keishing | e635ddc | 2022-12-08 07:38:02 -0600 | [diff] [blame] | 13 | from robot.libraries.BuiltIn import BuiltIn |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 14 | from tally_sheet import * |
| 15 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 16 | try: |
| 17 | from robot.utils import DotDict |
| 18 | except ImportError: |
| 19 | import collections |
| 20 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 21 | import gen_cmd as gc |
| 22 | import gen_misc as gm |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 23 | import gen_print as gp |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 24 | import gen_valid as gv |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 25 | import var_funcs as vf |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 26 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 27 | # The code base directory will be one level up from the directory containing this module. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 28 | code_base_dir_path = os.path.dirname(os.path.dirname(__file__)) + os.sep |
| 29 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 30 | redfish_support_trans_state = int( |
| 31 | os.environ.get("REDFISH_SUPPORT_TRANS_STATE", 0) |
| 32 | ) or int( |
| 33 | BuiltIn().get_variable_value("${REDFISH_SUPPORT_TRANS_STATE}", default=0) |
| 34 | ) |
Michael Shepos | da40c1d | 2020-12-01 22:30:00 -0600 | [diff] [blame] | 35 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 36 | platform_arch_type = os.environ.get( |
| 37 | "PLATFORM_ARCH_TYPE", "" |
| 38 | ) or BuiltIn().get_variable_value("${PLATFORM_ARCH_TYPE}", default="power") |
George Keishing | 1e2fbee | 2021-03-19 11:19:29 -0500 | [diff] [blame] | 39 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 40 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 41 | def create_boot_table(file_path=None, os_host=""): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 42 | r""" |
| 43 | Read the boot table JSON file, convert it to an object and return it. |
| 44 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 45 | Note that if the user is running without a global OS_HOST robot variable specified, this function will |
| 46 | remove all of the "os_" start and end state requirements from the JSON data. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 47 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 48 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 49 | file_path The path to the boot_table file. If this value is not specified, it will |
| 50 | be obtained from the "BOOT_TABLE_PATH" environment variable, if set. |
| 51 | Otherwise, it will default to "data/boot_table.json". If this value is a |
| 52 | relative path, this function will use the code_base_dir_path as the base |
| 53 | directory (see definition above). |
| 54 | os_host The host name or IP address of the host associated with the machine being |
| 55 | tested. If the user is running without an OS_HOST (i.e. if this argument |
| 56 | is blank), we remove os starting and ending state requirements from the |
| 57 | boot entries. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 58 | """ |
| 59 | if file_path is None: |
George Keishing | b51d150 | 2021-03-25 03:30:33 -0500 | [diff] [blame] | 60 | if redfish_support_trans_state and platform_arch_type != "x86": |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 61 | file_path = os.environ.get( |
| 62 | "BOOT_TABLE_PATH", "data/boot_table_redfish.json" |
| 63 | ) |
George Keishing | 1e2fbee | 2021-03-19 11:19:29 -0500 | [diff] [blame] | 64 | elif platform_arch_type == "x86": |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 65 | file_path = os.environ.get( |
| 66 | "BOOT_TABLE_PATH", "data/boot_table_x86.json" |
| 67 | ) |
Michael Shepos | da40c1d | 2020-12-01 22:30:00 -0600 | [diff] [blame] | 68 | else: |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 69 | file_path = os.environ.get( |
| 70 | "BOOT_TABLE_PATH", "data/boot_table.json" |
| 71 | ) |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 72 | |
| 73 | if not file_path.startswith("/"): |
| 74 | file_path = code_base_dir_path + file_path |
| 75 | |
| 76 | # Pre-process the file by removing blank lines and comment lines. |
| 77 | temp = tempfile.NamedTemporaryFile() |
| 78 | temp_file_path = temp.name |
| 79 | |
| 80 | cmd_buf = "egrep -v '^[ ]*$|^[ ]*#' " + file_path + " > " + temp_file_path |
| 81 | gc.cmd_fnc_u(cmd_buf, quiet=1) |
| 82 | |
| 83 | boot_file = open(temp_file_path) |
| 84 | boot_table = json.load(boot_file, object_hook=DotDict) |
| 85 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 86 | # If the user is running without an OS_HOST, we remove os starting and ending state requirements from |
| 87 | # the boot entries. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 88 | if os_host == "": |
| 89 | for boot in boot_table: |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 90 | state_keys = ["start", "end"] |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 91 | for state_key in state_keys: |
Michael Walsh | 37f833d | 2019-03-04 17:09:12 -0600 | [diff] [blame] | 92 | for sub_state in list(boot_table[boot][state_key]): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 93 | if sub_state.startswith("os_"): |
| 94 | boot_table[boot][state_key].pop(sub_state, None) |
| 95 | |
Michael Walsh | 07a01ef | 2017-02-27 14:20:22 -0600 | [diff] [blame] | 96 | # For every boot_type we should have a corresponding mfg mode boot type. |
| 97 | enhanced_boot_table = DotDict() |
George Keishing | 36efbc0 | 2018-12-12 10:18:23 -0600 | [diff] [blame] | 98 | for key, value in boot_table.items(): |
Michael Walsh | 07a01ef | 2017-02-27 14:20:22 -0600 | [diff] [blame] | 99 | enhanced_boot_table[key] = value |
| 100 | enhanced_boot_table[key + " (mfg)"] = value |
| 101 | |
| 102 | return enhanced_boot_table |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 103 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 104 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 105 | def create_valid_boot_list(boot_table): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 106 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 107 | Return a list of all of the valid boot types (e.g. ['REST Power On', 'REST Power Off', ...]). |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 108 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 109 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 110 | boot_table A boot table such as is returned by the create_boot_table function. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 111 | """ |
| 112 | |
| 113 | return list(boot_table.keys()) |
| 114 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 115 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 116 | def read_boot_lists(dir_path="data/boot_lists/"): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 117 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 118 | Read the contents of all the boot lists files found in the given boot lists directory and return |
| 119 | dictionary of the lists. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 120 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 121 | Boot lists are simply files containing a boot test name on each line. These files are useful for |
| 122 | categorizing and organizing boot tests. For example, there may be a "Power_on" list, a "Power_off" list, |
| 123 | etc. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 124 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 125 | The names of the boot list files will be the keys to the top level dictionary. Each dictionary entry is |
| 126 | a list of all the boot tests found in the corresponding file. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 127 | |
| 128 | Here is an abbreviated look at the resulting boot_lists dictionary. |
| 129 | |
| 130 | boot_lists: |
| 131 | boot_lists[All]: |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 132 | boot_lists[All][0]: REST Power On |
| 133 | boot_lists[All][1]: REST Power Off |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 134 | ... |
| 135 | boot_lists[Code_update]: |
| 136 | boot_lists[Code_update][0]: BMC oob hpm |
| 137 | boot_lists[Code_update][1]: BMC ib hpm |
| 138 | ... |
| 139 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 140 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 141 | dir_path The path to the directory containing the boot list files. If this value |
| 142 | is a relative path, this function will use the code_base_dir_path as the |
| 143 | base directory (see definition above). |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 144 | """ |
| 145 | |
| 146 | if not dir_path.startswith("/"): |
| 147 | # Dir path is relative. |
| 148 | dir_path = code_base_dir_path + dir_path |
| 149 | |
| 150 | # Get a list of all file names in the directory. |
| 151 | boot_file_names = os.listdir(dir_path) |
| 152 | |
| 153 | boot_lists = DotDict() |
| 154 | for boot_category in boot_file_names: |
| 155 | file_path = gm.which(dir_path + boot_category) |
| 156 | boot_list = gm.file_to_list(file_path, newlines=0, comments=0, trim=1) |
| 157 | boot_lists[boot_category] = boot_list |
| 158 | |
| 159 | return boot_lists |
| 160 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 161 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 162 | def valid_boot_list(boot_list, valid_boot_types): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 163 | r""" |
| 164 | Verify that each entry in boot_list is a supported boot test. |
| 165 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 166 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 167 | boot_list An array (i.e. list) of boot test types (e.g. "REST Power On"). |
| 168 | valid_boot_types A list of valid boot types such as that returned by |
| 169 | create_valid_boot_list. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 170 | """ |
| 171 | |
| 172 | for boot_name in boot_list: |
| 173 | boot_name = boot_name.strip(" ") |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 174 | error_message = gv.valid_value( |
| 175 | boot_name, valid_values=valid_boot_types, var_name="boot_name" |
| 176 | ) |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 177 | if error_message != "": |
| 178 | BuiltIn().fail(gp.sprint_error(error_message)) |
| 179 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 180 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 181 | class boot_results: |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 182 | r""" |
| 183 | This class defines a boot_results table. |
| 184 | """ |
| 185 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 186 | def __init__( |
| 187 | self, boot_table, boot_pass=0, boot_fail=0, obj_name="boot_results" |
| 188 | ): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 189 | r""" |
| 190 | Initialize the boot results object. |
| 191 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 192 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 193 | boot_table Boot table object (see definition above). The boot table contains all of |
| 194 | the valid boot test types. It can be created with the create_boot_table |
| 195 | function. |
| 196 | boot_pass An initial boot_pass value. This program may be called as part of a |
| 197 | larger test suite. As such there may already have been some successful |
| 198 | boot tests that we need to keep track of. |
| 199 | boot_fail An initial boot_fail value. This program may be called as part of a |
| 200 | larger test suite. As such there may already have been some unsuccessful |
| 201 | boot tests that we need to keep track of. |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 202 | obj_name The name of this object. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 203 | """ |
| 204 | |
| 205 | # Store the method parms as class data. |
| 206 | self.__obj_name = obj_name |
| 207 | self.__initial_boot_pass = boot_pass |
| 208 | self.__initial_boot_fail = boot_fail |
| 209 | |
| 210 | # Create boot_results_fields for use in creating boot_results table. |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 211 | boot_results_fields = DotDict([("total", 0), ("pass", 0), ("fail", 0)]) |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 212 | # Create boot_results table. |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 213 | self.__boot_results = tally_sheet( |
| 214 | "boot type", boot_results_fields, "boot_test_results" |
| 215 | ) |
| 216 | self.__boot_results.set_sum_fields(["total", "pass", "fail"]) |
| 217 | self.__boot_results.set_calc_fields(["total=pass+fail"]) |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 218 | # Create one row in the result table for each kind of boot test in the boot_table (i.e. for all |
| 219 | # supported boot tests). |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 220 | for boot_name in list(boot_table.keys()): |
| 221 | self.__boot_results.add_row(boot_name) |
| 222 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 223 | def add_row(self, *args, **kwargs): |
| 224 | r""" |
| 225 | Add row to tally_sheet class object. |
| 226 | |
| 227 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 228 | See add_row method in tally_sheet.py for a description of all arguments. |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 229 | """ |
| 230 | self.__boot_results.add_row(*args, **kwargs) |
| 231 | |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 232 | def return_total_pass_fail(self): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 233 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 234 | Return the total boot_pass and boot_fail values. This information is comprised of the pass/fail |
| 235 | values from the table plus the initial pass/fail values. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 236 | """ |
| 237 | |
| 238 | totals_line = self.__boot_results.calc() |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 239 | return ( |
| 240 | totals_line["pass"] + self.__initial_boot_pass, |
| 241 | totals_line["fail"] + self.__initial_boot_fail, |
| 242 | ) |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 243 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 244 | def update(self, boot_type, boot_status): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 245 | r""" |
| 246 | Update our boot_results_table. This includes: |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 247 | - Updating the record for the given boot_type by incrementing the pass or fail field. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 248 | - Calling the calc method to have the totals calculated. |
| 249 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 250 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 251 | boot_type The type of boot test just done (e.g. "REST Power On"). |
| 252 | boot_status The status of the boot just done. This should be equal to either "pass" |
| 253 | or "fail" (case-insensitive). |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 254 | """ |
| 255 | |
| 256 | self.__boot_results.inc_row_field(boot_type, boot_status.lower()) |
Michael Walsh | 8f1ef9e | 2017-03-02 14:31:24 -0600 | [diff] [blame] | 257 | self.__boot_results.calc() |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 258 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 259 | def sprint_report(self, header_footer="\n"): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 260 | r""" |
| 261 | String-print the formatted boot_resuls_table and return them. |
| 262 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 263 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 264 | header_footer This indicates whether a header and footer are to be included in the |
| 265 | report. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 266 | """ |
| 267 | |
| 268 | buffer = "" |
| 269 | |
| 270 | buffer += gp.sprint(header_footer) |
| 271 | buffer += self.__boot_results.sprint_report() |
| 272 | buffer += gp.sprint(header_footer) |
| 273 | |
| 274 | return buffer |
| 275 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 276 | def print_report(self, header_footer="\n", quiet=None): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 277 | r""" |
| 278 | Print the formatted boot_resuls_table to the console. |
| 279 | |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 280 | Description of argument(s): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 281 | See sprint_report for details. |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 282 | quiet Only print if this value is 0. This function will search upward in the |
| 283 | stack to get the default value. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 284 | """ |
| 285 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 286 | quiet = int(gm.dft(quiet, gp.get_stack_var("quiet", 0))) |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 287 | |
Michael Walsh | c108e42 | 2019-03-28 12:27:18 -0500 | [diff] [blame] | 288 | gp.qprint(self.sprint_report(header_footer)) |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 289 | |
| 290 | def sprint_obj(self): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 291 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 292 | sprint the fields of this object. This would normally be for debug purposes only. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 293 | """ |
| 294 | |
| 295 | buffer = "" |
| 296 | |
| 297 | buffer += "class name: " + self.__class__.__name__ + "\n" |
| 298 | buffer += gp.sprint_var(self.__obj_name) |
| 299 | buffer += self.__boot_results.sprint_obj() |
| 300 | buffer += gp.sprint_var(self.__initial_boot_pass) |
| 301 | buffer += gp.sprint_var(self.__initial_boot_fail) |
| 302 | |
| 303 | return buffer |
| 304 | |
| 305 | def print_obj(self): |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 306 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 307 | Print the fields of this object to stdout. This would normally be for debug purposes. |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 308 | """ |
| 309 | |
Michael Walsh | c108e42 | 2019-03-28 12:27:18 -0500 | [diff] [blame] | 310 | gp.gp_print(self.sprint_obj()) |
Michael Walsh | ac29d06 | 2017-02-20 16:13:10 -0600 | [diff] [blame] | 311 | |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 312 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 313 | def create_boot_results_file_path(pgm_name, openbmc_nickname, master_pid): |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 314 | r""" |
| 315 | Create a file path to be used to store a boot_results object. |
| 316 | |
| 317 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 318 | pgm_name The name of the program. This will form part of the resulting file name. |
| 319 | openbmc_nickname The name of the system. This could be a nickname, a hostname, an IP, |
| 320 | etc. This will form part of the resulting file name. |
| 321 | master_pid The master process id which will form part of the file name. |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 322 | """ |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 323 | |
Michael Walsh | 8d7b738 | 2017-09-27 16:00:25 -0500 | [diff] [blame] | 324 | USER = os.environ.get("USER", "") |
| 325 | dir_path = "/tmp/" + USER + "/" |
| 326 | if not os.path.exists(dir_path): |
| 327 | os.makedirs(dir_path) |
| 328 | |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 329 | file_name_dict = vf.create_var_dict(pgm_name, openbmc_nickname, master_pid) |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 330 | return vf.create_file_path( |
| 331 | file_name_dict, dir_path=dir_path, file_suffix=":boot_results" |
| 332 | ) |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 333 | |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 334 | |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 335 | def cleanup_boot_results_file(): |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 336 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 337 | Delete all boot results files whose corresponding pids are no longer active. |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 338 | """ |
| 339 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 340 | # Use create_boot_results_file_path to create a globex to find all of the existing boot results files. |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 341 | globex = create_boot_results_file_path("*", "*", "*") |
| 342 | file_list = sorted(glob.glob(globex)) |
| 343 | for file_path in file_list: |
| 344 | # Use parse_file_path to extract info from the file path. |
| 345 | file_dict = vf.parse_file_path(file_path) |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 346 | if gm.pid_active(file_dict["master_pid"]): |
Michael Walsh | b6e3aac | 2017-09-19 16:57:27 -0500 | [diff] [blame] | 347 | gp.qprint_timen("Preserving " + file_path + ".") |
| 348 | else: |
| 349 | gc.cmd_fnc("rm -f " + file_path) |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 350 | |
| 351 | |
| 352 | def update_boot_history(boot_history, boot_start_message, max_boot_history=10): |
| 353 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 354 | Update the boot_history list by appending the boot_start_message and by removing all but the last n |
| 355 | entries. |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 356 | |
| 357 | Description of argument(s): |
| 358 | boot_history A list of boot start messages. |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 359 | boot_start_message This is typically a time-stamped line of text announcing the start of a |
| 360 | boot test. |
| 361 | max_boot_history The max number of entries to be kept in the boot_history list. The |
| 362 | oldest entries are deleted to achieve this list size. |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 363 | """ |
| 364 | |
| 365 | boot_history.append(boot_start_message) |
| 366 | |
| 367 | # Trim list to max number of entries. |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 368 | del boot_history[: max(0, len(boot_history) - max_boot_history)] |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 369 | |
| 370 | |
| 371 | def print_boot_history(boot_history, quiet=None): |
| 372 | r""" |
| 373 | Print the last ten boots done with their time stamps. |
| 374 | |
| 375 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 376 | quiet Only print if this value is 0. This function will search upward in the |
| 377 | stack to get the default value. |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 378 | """ |
| 379 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 380 | quiet = int(gm.dft(quiet, gp.get_stack_var("quiet", 0))) |
Michael Walsh | 6c4520c | 2019-07-16 16:40:00 -0500 | [diff] [blame] | 381 | |
| 382 | # indent 0, 90 chars wide, linefeed, char is "=" |
| 383 | gp.qprint_dashes(0, 90) |
| 384 | gp.qprintn("Last 10 boots:\n") |
| 385 | |
| 386 | for boot_entry in boot_history: |
| 387 | gp.qprint(boot_entry) |
| 388 | gp.qprint_dashes(0, 90) |