blob: 908d6ec554095243741c52ac13ed99755a6806d6 [file] [log] [blame]
Jayanth Othayoth5ce15502017-10-16 00:02:44 -05001#! /bin/bash
2
3help=$"
4 dreport creates an archive(xz compressed) consisting of the following:
5 * Configuration information
6 * Debug information
7 * A summary report
8 The type parameter controls the content of the data. The generated
9 archive is stored in the user specified location.
10
11usage: dreport [OPTION]
12
13Options:
14 -n, —-name <name> Name to be used for the archive.
15 Default name format obmcdump_<id>_<epochtime>
16 -d, —-dir <directory> Archive directory to copy the compressed report.
17 Default output directory is /tmp
18 -i, —-id <id> Dump identifier to associate with the archive.
19 Identifiers include numeric characters.
20 Default dump identifier is 0
21 -t, —-type <type> Data collection type. Valid types are
22 "user", "core", "elog".
23 Default type is "user" initiated.
24 -p, —-path <path> Optional contents to be included in the archive.
25 Valid paths are absolute file path or d-bus path
26 based on type parameter.
27 -Absolute file path for "core" type.
28 -elog d-bus object for "elog" type.
29 -s, --size <size> Maximum allowed size(in KB) of the archive.
30 Report will be truncated in case size exceeds
31 this limit. Default size is unlimited.
32 -v, —-verbose Increase logging verbosity.
33 -V, --version Output version information.
34 -q, —-quiet Only log fatal errors to stderr
35 -h, —-help Display this help and exit.
36"
37
38#CONSTANTS
39declare -rx TRUE=1
40declare -rx FALSE=0
41declare -rx UNLIMITED="unlimited"
42declare -rx SUMMARY_DUMP="summary"
43declare -rx TYPE_USER="user"
44declare -rx TYPE_CORE="core"
45declare -rx TYPE_ELOG="elog"
46declare -rx SUMMARY_LOG="summary.log"
47declare -rx DREPORT_LOG="dreport.log"
48declare -rx TMP_DIR="/tmp"
49declare -rx EPOCHTIME=$(date +"%s")
50declare -rx TIME_STAMP="date -u"
51declare -rx PLUGIN="pl_"
52declare -rx DREPORT_SOURCE="/usr/share/dreport.d"
53declare -rx DREPORT_INCLUDE="$DREPORT_SOURCE/include.d"
54
55#Error Codes
56declare -rx SUCCESS="0"
57declare -rx INTERNAL_FAILURE="1"
58declare -rx RESOURCE_UNAVAILABLE="2"
59
60#VARIABLES
61declare -x name=""
62declare -x dump_dir="/tmp"
63declare -x dump_id="00000000"
64declare -x dump_type=$TYPE_USER
65declare -x verbose=$FALSE
66declare -x quiet=$FALSE
67declare -x dump_size="unlimited"
68declare -x name_dir=""
69declare -x optional_path=""
70declare -x dreport_log=""
71declare -x summary_log=""
72declare -x cur_dump_size=0
73declare -x pid="0"
74declare -x elog_id=""
75
76#Source dreport common functions
77. $DREPORT_INCLUDE/functions
78
79# @brief Initiate data collection based on the type.
80# @return 0 on success, error code otherwise
81function collect_data()
82{
83 case $dump_type in
84 $TYPE_USER)
85 ;;
86 $TYPE_CORE)
87 log_summary "Core: $optional_path"
88 set_core_pid
89 ;;
90 $TYPE_ELOG)
91 log_summary "ELOG: $optional_path"
92 elog_id=$(basename "$optional_path")
93 set_elog_pid
94 ;;
95
96 $SUMMARY_DUMP)
97 #No data collection is required.
98 return
99 ;;
100 *) # unknown option
101 log_error "Skipping: Unknown dump type: $dump_type"
102 return
103 ;;
104 esac
105
106 plugin_path=$DREPORT_SOURCE/$PLUGIN$dump_type.d
107
108 # check plugin directory for this dump type?
109 if [ ! -d $plugin_path ]; then
110 log_error "$plugin_path does not exist, skipping dump collection"
111 return 0
112 fi
113
114 #Executes plugins based on the type.
115 for i in $plugin_path/* ; do
116 $i
117 done
118}
119
120# @brief set pid by reading information from the optional path.
121# dreport "core" type user provides core file as optional path parameter.
122# As per coredump source code systemd-coredump uses below format
123# https://github.com/systemd/systemd/blob/master/src/coredump/coredump.c
124# /var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR “.
125# <process ID>.%s000000"
126function set_core_pid()
127{
128 #Escape bash characters in file name
129 file=$(printf %q "$optional_path")
130
131 #matching systemd-coredump core file format.
132 pid=$(echo $file | awk -F . '{ print $5}')
133}
134
135# @brief set elog pid by reading _PID information from the elog d-bus object.
136# _PID information is stored elog Additional data field
137# Data format "_PID=<pid>"
138function set_elog_pid()
139{
140 additional_data=$(busctl get-property xyz.openbmc_project.Logging \
141 $optional_path \
142 xyz.openbmc_project.Logging.Entry \
143 AdditionalData)
144
145 #read _PID data.
146 if [ ! -z "$additional_data" ]; then
147 pid=$(echo $additional_data | \
148 awk -F _PID= '{ print ($2+0)}')
149 fi
150}
151
152# @brief Initial version of the summary log
153init_summary()
154{
155 log_summary "Name: $name.tar.xz"
156 log_summary "Epochtime: $EPOCHTIME"
157 log_summary "ID: $dump_id"
158 log_summary "Type: $dump_type"
159}
160
161# @brief Check the validity of user inputs and initialize global
162# variables. Create directory for temporary data collection
163# @return 0 on success, error code otherwise
164
165function initialize()
166{
167 #Dump file name
168 if [ -z $name ]; then
169 name=$"obmcdump_"$dump_id"_$EPOCHTIME"
170 fi
171
172 #Create temporary data directory.
173 mkdir -p "$TMP_DIR/$name"
174 if [ $? -ne 0 ]; then
175 echo "Error: Failed to create the temporary directory."
176 return $RESOURCE_UNAVAILABLE;
177 fi
178
179 #name directory
180 name_dir="$TMP_DIR/$name"
181
182 #dreport log file
183 dreport_log="$name_dir/$DREPORT_LOG"
184
185 #summary log file
186 summary_log="$name_dir/$SUMMARY_LOG"
187
188 #Type
189 if [[ !($dump_type = $TYPE_USER || \
190 $dump_type = $TYPE_CORE || \
191 $dump_type = $TYPE_ELOG) ]]; then
192 log_error "Invalid -type, Only summary log is available"
193 dump_type=$SUMMARY_DUMP
194 fi
195
196 #Size
197 #Check the input is integer.
198 if [ "$dump_size" -eq "$dump_size" ] 2>/dev/null; then
199 #Converts in to bytes.
200 dump_size="$((dump_size * 1024))"
201 else
202 dump_size=$UNLIMITED
203 fi
204
205 return $SUCCESS
206}
207
208# @brief Packaging the dump and transferring to dump location.
209function package()
210{
211 mkdir -p "$dump_dir"
212 if [ $? -ne 0 ]; then
213 log_error "Could not create the destination directory $dump_dir"
214 dest_dir=$TMP_DIR
215 fi
216
217 #tar and compress the files.
218 tar -Jcf "$name_dir.tar.xz" -C \
219 $(dirname "$name_dir") $(basename "$name_dir")
220
221 if [ $? -ne 0 ]; then
222 echo $($TIME_STAMP) "Could not create the compressed tar file"
223 rm -r "$name_dir"
224 return $INTERNAL_FAILURE
225 fi
226
227 #remove the temporary name specific directory
228 rm -r "$name_dir"
229
230 echo $($TIME_STAMP) "Report is available in $dump_dir"
231
232 if [ "$TMP_DIR" == "$dump_dir" ]; then
233 return $SUCCESS
234 fi
235
236 #copy the compressed tar file into the destination
237 cp "$name_dir.tar.xz" "$dump_dir"
238 if [ $? -ne 0 ]; then
239 echo "Failed to copy the $name_dir.tar.xz to $dump_dir"
240 rm "$name_dir.tar.xz"
241 return $INTERNAL_FAILURE
242 fi
243
244 #Remove the temporary copy of the file
245 rm "$name_dir.tar.xz"
246}
247
248# @brief Main function
249function main()
250{
251 #initialize the global variables and
252 #create temporary storage locations
253 initialize
254 result=$?
255 if [[ ${result} -ne $SUCCESS ]]; then
256 echo $($TIME_STAMP) "Error: Failed to initialize, Exiting"
257 exit;
258 fi
259
260 #Initilize the summary log
261 init_summary
262
263 #collect data based on the type.
264 collect_data
265
266 package #package the dump
267 result=$?
268 if [[ ${result} -ne $SUCCESS ]]; then
269 echo $($TIME_STAMP) "Error: Failed to package, Exiting"
270 else
271 echo $($TIME_STAMP) "Sucessfully completed"
272 exit;
273 fi
274}
275
276TEMP=`getopt -o n:d:i:t:s:p:vVqh \
277 --long name:,dir:,dumpid:,type:,size:,path:,verbose,version,quiet,help \
278 -- "$@"`
279
280if [ $? -ne 0 ]
281then
282 echo "Error: Invalid options"
283 exit 1
284fi
285
286eval set -- "$TEMP"
287
288while [[ $# -gt 1 ]]; do
289 key="$1"
290 case $key in
291 -n|--name)
292 name=$2
293 shift 2;;
294 -d|--dir)
295 dump_dir=$2
296 shift 2;;
297 -i|--dumpid)
298 dump_id=$2
299 shift 2;;
300 -t|--type)
301 dump_type=$2
302 shift 2;;
303 -s|--size)
304 dump_size=$2
305 shift 2;;
306 -p|--path)
307 optional_path=$2
308 shift 2;;
309 -v|—-verbose)
310 verbose=$TRUE
311 shift;;
312 -V|--version)
313 shift;;
314 -q|—-quiet)
315 quiet=$TRUE
316 shift;;
317 -h|--help)
318 echo "$help"
319 exit;;
320 *) # unknown option
321 log_error "Unknown argument: $1"
322 log_info "$help"
323 exit 1;;
324 esac
325done
326
327main #main program
328exit $?