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# @brief Get serial number property from inventory 77function 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 88function 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 116function 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 129function 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 138 dump_content_type=${id:0:2} 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 179function 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 192function 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 220if ! 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 225fi 226 227eval set -- "$TEMP" 228 229while [[ $# -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 261done 262 263main 264exit $? 265