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