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