Dhruvaraj Subhashchandran | 35714cd | 2024-05-16 05:54:38 -0500 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | # shellcheck disable=SC2034 # Variable is used elsewhere |
| 3 | |
| 4 | help=$(cat << EOF |
| 5 | opdreport creates an archive consisting of the following: |
| 6 | * host dump files and header applied on top of it |
| 7 | The type parameter controls the content of the data. The generated |
| 8 | archive is stored in the user specified location. |
| 9 | |
| 10 | usage: opdreport [OPTION] |
| 11 | |
| 12 | Options: |
| 13 | -n, --name <name> Name to be used for the archive. |
| 14 | Default name format |
| 15 | SYSDUMP.<serial number>.<dump_id>.<time> |
| 16 | Optional parameter. |
| 17 | -d, --dir <directory> Archive directory to copy the compressed report. |
| 18 | Default output directory is current working |
| 19 | directory. Optional parameter. |
| 20 | -i, --dumpid <id> Dump identifier to associate with the archive. |
| 21 | Identifiers include numeric characters. |
| 22 | Default dump identifier is 0 |
| 23 | -s, --size <size> Maximum allowed size (in KB) of the archive. |
| 24 | Report will be truncated if size exceeds |
| 25 | this limit. Default size is unlimited. |
| 26 | -f, --failingunit The id of the failed unit |
| 27 | -e, --eid Error log associated with the failure |
| 28 | -t, --type Type of the dump to be collected |
| 29 | 1 - Hardware dump |
| 30 | 3 - Performance dump |
| 31 | 5 - Hostboot dump |
| 32 | 10 - SBE Dump |
| 33 | -h, --help Display this help and exit. |
| 34 | EOF |
| 35 | ) |
| 36 | |
| 37 | # Constants |
| 38 | readonly OP_DUMP="opdump" |
| 39 | readonly DREPORT_SOURCE="/usr/share/dreport.d" |
| 40 | readonly TRUE=1 |
| 41 | readonly FALSE=0 |
| 42 | readonly TIME_STAMP="date -u" |
| 43 | readonly UNLIMITED="unlimited" |
| 44 | readonly DREPORT_INCLUDE="$DREPORT_SOURCE/include.d" |
| 45 | readonly INVENTORY_MANAGER='xyz.openbmc_project.Inventory.Manager' |
| 46 | readonly INVENTORY_PATH='/xyz/openbmc_project/inventory/system' |
| 47 | readonly INVENTORY_ASSET_INT='xyz.openbmc_project.Inventory.Decorator.Asset' |
| 48 | readonly INVENTORY_BMC_BOARD='/xyz/openbmc_project/inventory/system/chassis/motherboard' |
| 49 | readonly HEADER_EXTENSION="$DREPORT_INCLUDE/gendumpheader" |
| 50 | readonly FILE_SCRIPT="$DREPORT_SOURCE/include.d/gendumpinfo" |
| 51 | |
| 52 | # Error Codes |
| 53 | readonly SUCCESS=0 |
| 54 | readonly INTERNAL_FAILURE=1 |
| 55 | readonly RESOURCE_UNAVAILABLE=2 |
| 56 | |
| 57 | # Variables |
| 58 | declare -x dump_type="$OP_DUMP" |
| 59 | declare -x dump_sbe_type=100 |
| 60 | declare -x size_dump="" |
| 61 | declare -x elog_id="00000000" |
| 62 | declare -x EPOCHTIME |
| 63 | EPOCHTIME=$(date +"%s") |
| 64 | declare -x name="" |
| 65 | declare -x dump_dir="/tmp" |
| 66 | declare -x dump_id="00000000" |
| 67 | declare -x dump_size="unlimited" |
| 68 | declare -x content_path="" |
| 69 | declare -x name_dir="" |
| 70 | declare -x serialNo="0000000" |
| 71 | declare -x dDay |
| 72 | dDay=$(date -d @"$EPOCHTIME" +'%Y%m%d%H%M%S') |
| 73 | declare -x dump_content_type="" |
| 74 | declare -x FILE="" |
| 75 | |
| 76 | # @brief Get serial number property from inventory |
| 77 | function fetch_serial_number() { |
| 78 | serialNo=$(busctl get-property "$INVENTORY_MANAGER" "$INVENTORY_PATH" \ |
| 79 | "$INVENTORY_ASSET_INT" SerialNumber | cut -d " " -f 2 | \ |
| 80 | sed 's/^"\(.*\)"$/\1/') |
| 81 | |
| 82 | if [ -z "$serialNo" ]; then |
| 83 | serialNo="0000000" |
| 84 | fi |
| 85 | } |
| 86 | |
| 87 | # @brief Check the validity of user inputs and initialize global variables |
| 88 | function initialize() { |
| 89 | # shellcheck disable=SC2154 # name comes from elsewhere |
| 90 | if [ -z "$name" ]; then |
| 91 | name="SYSDUMP" |
| 92 | fi |
| 93 | fetch_serial_number |
| 94 | # shellcheck disable=SC2154 # dump_id comes from elsewhere |
| 95 | name="${name}.${serialNo}.${dump_id}.${dDay}" |
| 96 | |
| 97 | if [ -z "$dump_sbe_type" ]; then |
| 98 | echo "Error: Dump type is not provided." |
| 99 | return "$RESOURCE_UNAVAILABLE" |
| 100 | fi |
| 101 | |
| 102 | if [ -z "$dump_dir" ]; then |
| 103 | dump_dir=$PWD |
| 104 | fi |
| 105 | |
| 106 | if [[ "$dump_size" =~ ^[0-9]+$ ]]; then |
| 107 | dump_size=$((dump_size * 1024)) |
| 108 | else |
| 109 | dump_size=$UNLIMITED |
| 110 | fi |
| 111 | |
| 112 | return "$SUCCESS" |
| 113 | } |
| 114 | |
| 115 | # @brief Collect the dump |
| 116 | function collect() { |
| 117 | content_path="/tmp/dump_${dump_id}_${EPOCHTIME}" |
| 118 | dump_outpath="$content_path/plat_dump" |
| 119 | if ! mkdir -p "$dump_outpath"; then |
| 120 | echo "Could not create the destination directory $dump_outpath" |
| 121 | return "$INTERNAL_FAILURE" |
| 122 | fi |
| 123 | |
| 124 | dump-collect --type "$dump_sbe_type" --id "0x$dump_id" \ |
| 125 | --failingunit "$failing_unit" --path "$dump_outpath" |
| 126 | } |
| 127 | |
| 128 | # @brief Package the dump and transfer to dump location |
| 129 | function package() { |
| 130 | FILE="/tmp/dumpheader_${dump_id}_${EPOCHTIME}" |
| 131 | if ! mkdir -p "$dump_dir"; then |
| 132 | echo "Could not create the destination directory $dump_dir" |
| 133 | dump_dir="/tmp" |
| 134 | fi |
| 135 | |
| 136 | cd "$content_path" || exit "$INTERNAL_FAILURE" |
| 137 | |
SwethaParasa | c14bf2c | 2024-09-18 02:19:34 -0500 | [diff] [blame^] | 138 | dump_content_type=${dump_id:0:2} |
Dhruvaraj Subhashchandran | 35714cd | 2024-05-16 05:54:38 -0500 | [diff] [blame] | 139 | "$FILE_SCRIPT" |
| 140 | elog_id=$eid |
| 141 | |
| 142 | if ! tar -cvzf "$name" plat_dump/*Sbe* info.yaml; then |
| 143 | echo "$($TIME_STAMP)" "Could not create the compressed tar file" |
| 144 | return "$INTERNAL_FAILURE" |
| 145 | fi |
| 146 | |
| 147 | size_dump=$(stat -c %s "$name") |
| 148 | |
| 149 | if [ "$dump_size" != "$UNLIMITED" ] && \ |
| 150 | [ "$size_dump" -gt "$dump_size" ]; then |
| 151 | rm "$name" |
| 152 | return "$RESOURCE_UNAVAILABLE" |
| 153 | fi |
| 154 | |
| 155 | echo "Adding Dump Header: $HEADER_EXTENSION" |
| 156 | "$HEADER_EXTENSION" |
| 157 | |
| 158 | if ! tee -a "$FILE" < "$name" > /dev/null; then |
| 159 | echo "$($TIME_STAMP)" "Could not create the compressed file" |
| 160 | rm -rf "$name" "$FILE" |
| 161 | return "$INTERNAL_FAILURE" |
| 162 | fi |
| 163 | |
| 164 | if ! mv "$FILE" "$name"; then |
| 165 | echo "$($TIME_STAMP)" "Could not create the compressed file" |
| 166 | rm -rf "$name" "$FILE" |
| 167 | return "$INTERNAL_FAILURE" |
| 168 | fi |
| 169 | |
| 170 | mv "$name" "$dump_dir" |
| 171 | |
| 172 | rm -rf "$content_path" |
| 173 | rm -rf "$FILE" "$name" |
| 174 | |
| 175 | return "$SUCCESS" |
| 176 | } |
| 177 | |
| 178 | # @brief Initiate BMC dump |
| 179 | function initiate_bmc_dump() { |
| 180 | bmcDumpPath=$(busctl call xyz.openbmc_project.Dump.Manager \ |
| 181 | /xyz/openbmc_project/dump/bmc \ |
| 182 | xyz.openbmc_project.Dump.Create CreateDump a\{sv\} 0) |
| 183 | result=$? |
| 184 | if [[ $result -ne $SUCCESS ]]; then |
| 185 | echo "Error in creating BMC dump associated with system dump" |
| 186 | else |
| 187 | echo "BMC dump initiated $bmcDumpPath" |
| 188 | fi |
| 189 | } |
| 190 | |
| 191 | # @brief Main function |
| 192 | function main() { |
| 193 | initialize |
| 194 | result=$? |
| 195 | if [[ $result -ne $SUCCESS ]]; then |
| 196 | echo "$($TIME_STAMP)" "Error: Failed to initialize, Exiting" |
| 197 | return "$INTERNAL_FAILURE" |
| 198 | fi |
| 199 | |
| 200 | collect |
| 201 | result=$? |
| 202 | if [[ $result -ne $SUCCESS ]]; then |
| 203 | echo "$($TIME_STAMP)" "Error: Failed to collect dump, Exiting" |
| 204 | return "$INTERNAL_FAILURE" |
| 205 | fi |
| 206 | |
| 207 | package |
| 208 | result=$? |
| 209 | if [[ $result -ne $SUCCESS ]]; then |
| 210 | echo "$($TIME_STAMP)" "Error: Failed to package, Exiting" |
| 211 | return "$INTERNAL_FAILURE" |
| 212 | else |
| 213 | echo "$($TIME_STAMP)" "Successfully completed" |
| 214 | fi |
| 215 | |
| 216 | initiate_bmc_dump |
| 217 | return "$SUCCESS" |
| 218 | } |
| 219 | |
| 220 | if ! TEMP=$(getopt -o n:d:i:s:t:e:f:h \ |
| 221 | --long name:,dir:,dumpid:,size:,type:,eid:,failingunit:,help \ |
| 222 | -- "$@"); then |
| 223 | echo "Error: Invalid options" |
| 224 | exit 1 |
| 225 | fi |
| 226 | |
| 227 | eval set -- "$TEMP" |
| 228 | |
| 229 | while [[ $# -gt 1 ]]; do |
| 230 | key="$1" |
| 231 | case $key in |
| 232 | -n|--name) |
| 233 | name=$2 |
| 234 | shift 2 ;; |
| 235 | -d|--dir) |
| 236 | dump_dir=$2 |
| 237 | shift 2 ;; |
| 238 | -i|--dumpid) |
| 239 | dump_id=$2 |
| 240 | shift 2 ;; |
| 241 | -s|--size) |
| 242 | dump_size=$2 |
| 243 | shift 2 ;; |
| 244 | -f|--failingunit) |
| 245 | failing_unit=$2 |
| 246 | shift 2 ;; |
| 247 | -e|--eid) |
| 248 | eid=$2 |
| 249 | shift 2 ;; |
| 250 | -t|--type) |
| 251 | dump_sbe_type=$2 |
| 252 | shift 2 ;; |
| 253 | -h|--help) |
| 254 | echo "$help" |
| 255 | exit ;; |
| 256 | *) # unknown option |
| 257 | echo "Unknown argument: $1" |
| 258 | echo "$help" |
| 259 | exit 1 ;; |
| 260 | esac |
| 261 | done |
| 262 | |
| 263 | main |
| 264 | exit $? |