blob: a6cf2b295a7bebaf042b06863c2f552b29f6bb33 [file] [log] [blame]
Jayanth Othayoth9e95f4b2017-07-24 06:42:24 -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.
Jayanth Othayoth230e9a32017-08-09 06:39:59 -050017 Default output directory is /tmp
Jayanth Othayoth9e95f4b2017-07-24 06:42:24 -050018 -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".
23 Default type is "user" initiated.
24 -f, —-file <file> Optional file to be included in the archive.
25 Absolute path of the file must be passed as
26 parameter. This is useful to include application
27 core in the dump.
28 -s, --size <size> Maximum allowed size(in KB) of the archive.
29 Report will be truncated in case size exceeds
30 this limit. Default size is 500KB.
31 -v, —-verbose Increase logging verbosity.
32 -V, --version Output version information.
33 -q, —-quiet Only log fatal errors to stderr
34 -h, —-help Display this help and exit.
35"
36
Jayanth Othayoth7b774872017-07-26 05:02:53 -050037#CONSTANTS
38declare -r TRUE=1
39declare -r FALSE=0
Jayanth Othayoth230e9a32017-08-09 06:39:59 -050040declare -r UNLIMITED="unlimited"
41declare -r SUMMARY_DUMP="summary"
42declare -r TYPE_USER="user"
43declare -r TYPE_CORE="core"
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -050044declare -r SUMMARY_LOG="summary.log"
45declare -r DREPORT_LOG="dreport.log"
Jayanth Othayoth230e9a32017-08-09 06:39:59 -050046declare -r TMP_DIR="/tmp"
47declare -r EPOCHTIME=$(date +"%s")
48
49#Error Codes
50declare -r SUCCESS="0"
51declare -r INTERNAL_FAILURE="1"
52declare -r RESOURCE_UNAVAILABLE="2"
Jayanth Othayoth7b774872017-07-26 05:02:53 -050053
54#VARIABLES
Jayanth Othayoth230e9a32017-08-09 06:39:59 -050055declare -x name=""
Jayanth Othayothff0699d2017-07-26 07:53:03 -050056declare -x dump_dir="/tmp"
Jayanth Othayoth230e9a32017-08-09 06:39:59 -050057declare -x dump_id="00000000"
58declare -x dump_type=$TYPE_USER
Jayanth Othayoth7b774872017-07-26 05:02:53 -050059declare -x verbose=$FALSE
60declare -x quiet=$FALSE
Jayanth Othayoth230e9a32017-08-09 06:39:59 -050061declare -x dump_size="unlimited"
62declare -x name_dir=""
63declare -x optional_file=""
64declare -x dreport_log=""
65declare -x summary_log=""
Jayanth Othayothc2ece2d2017-08-09 06:57:12 -050066declare -x cur_dump_size=0
Jayanth Othayoth0862c482017-08-09 07:02:36 -050067declare -a command_list=("")
68
69# @brief Initialize user type command array
70function runlevel_user()
71{
72command_list=(
73 get_fw_level
74 get_uname
75 get_uptime
76 get_disk_usage
77 bmc_state
78 host_state
79 chassis_state
80 get_host_info
81 get_obmc_console
82 get_cpuinfo
83 get_meminfo
84 get_top
85 get_esel
86 get_journal
87 get_failed_services
88 )
89}
90
91function get_fw_level()
92{
93 desc="Firmware Release"
94 command="cat /etc/os-release"
95 copy_loc="firmware_release.log"
96 run_command "$command" "$copy_loc" "$desc"
97}
98
99function get_uname()
100{
101 desc="uname"
102 command="uname -a"
103 copy_loc="uname.log"
104 run_command "$command" "$copy_loc" "$desc"
105}
106
107function get_uptime()
108{
109 desc="uptime"
110 command="uptime"
111 copy_loc="uptime.log"
112 run_command "$command" "$copy_loc" "$desc"
113}
114
115function get_disk_usage()
116{
117 desc="Disk Usage"
118 command="df -hT"
119 copy_loc="disk_usage.log"
120 run_command "$command" "$copy_loc" "$desc"
121}
122
123function get_journal()
124{
125 desc="Journal log"
126 command="journalctl -o json-pretty -r"
127 copy_loc="journal.log"
128 run_command "$command" "$copy_loc" "$desc"
129}
130
131function get_host_info()
132{
133 desc="Host information"
134 command="hostnamectl status"
135 copy_loc="hostnamectl.log"
136 run_command "$command" "$copy_loc" "$desc"
137}
138
139function get_failed_services()
140{
141 desc="Failed Services"
142 command="systemctl --failed"
143 copy_loc="failed_services.log"
144 run_command "$command" "$copy_loc" "$desc"
145}
146
147function get_obmc_console()
148{
149 desc="OBMC Console"
150 command="cat /var/log/obmc-console.log"
151 copy_loc="obmc_console.log"
152 run_command "$command" "$copy_loc" "$desc"
153}
154
155function get_cpuinfo()
156{
157 desc="cpuinfo"
158 command="cat /proc/cpuinfo"
159 copy_loc="cpuinfo.log"
160 run_command "$command" "$copy_loc" "$desc"
161}
162
163function get_meminfo()
164{
165 desc="meminfo"
166 command="cat /proc/meminfo"
167 copy_loc="meminfo.log"
168 run_command "$command" "$copy_loc" "$desc"
169}
170
171function get_top()
172{
173 desc="top"
174 command="top -n 1 -b"
175 copy_loc="top.log"
176 run_command "$command" "$copy_loc" "$desc"
177}
178
179function bmc_state()
180{
181 desc="BMC State"
182 command="busctl get-property \
183 xyz.openbmc_project.State.BMC \
184 /xyz/openbmc_project/state/bmc0 \
185 xyz.openbmc_project.State.BMC \
186 CurrentBMCState"
187 copy_loc="BMCState.log"
188 run_command "$command" "$copy_loc" "$desc"
189}
190
191function host_state()
192{
193 desc="Host State"
194 command="busctl get-property \
195 xyz.openbmc_project.State.Host \
196 /xyz/openbmc_project/state/host0 \
197 xyz.openbmc_project.State.Host \
198 CurrentHostState"
199 copy_loc="HostState.log"
200 run_command "$command" "$copy_loc" "$desc"
201}
202
203function chassis_state()
204{
205 desc="Chassis State"
206 command="busctl get-property \
207 xyz.openbmc_project.State.Chassis \
208 /xyz/openbmc_project/state/chassis0 \
209 xyz.openbmc_project.State.Chassis \
210 CurrentPowerState"
211 copy_loc="HostState.log"
212 run_command "$command" "$copy_loc" "$desc"
213}
214
215function get_esel()
216{
217 desc="eSEL"
218
219 entries=$(busctl --list --no-pager tree \
220 xyz.openbmc_project.Logging | grep \
221 '/xyz/openbmc_project/logging/entry/')
222
223 #check for eSEL entries.
224 if [ -z "$entries" ]; then
225 log_info "No $desc entries"
226 return 0
227 fi
228
229 command="busctl --list --no-pager tree \
230 xyz.openbmc_project.Logging | grep \
231 '/xyz/openbmc_project/logging/entry/' \
232 | xargs -I {} busctl --verbose --no-pager \
233 call xyz.openbmc_project.Logging {} \
234 org.freedesktop.DBus.Properties GetAll s \
235 xyz.openbmc_project.Logging.Entry"
236 copy_loc="eSEL.log"
237 run_command "$command" "$copy_loc" "$desc"
238}
239
240# @brief Run the requested command and save the output
241# into temporary location for successful size check
242
243function run_command()
244{
245 command="$1"
246 copy_loc="$2"
247 desc="$3"
248
249 eval $command >> "$name_dir/$copy_loc"
250 if [ $? -ne 0 ]; then
251 log_error "Failed to collect $desc"
252 return 1
253 fi
254
255 if check_size "$name_dir/$copy_loc"; then
256 log_info "Collected $desc"
257 else
258 log_warning "Skipping $desc"
259 fi
260}
Jayanth Othayothc2ece2d2017-08-09 06:57:12 -0500261
262# @brief Calculate file or directory compressed size based on input
263# and check whether the size in the the allowed size limit.
264# Remove the file or directory from the name_dir
265# if the check fails.
266# @param $1 Source file or directory
267# @return 0 on success, error code if size exceeds the limit.
268# Limitation: compress and tar will have few bytes size difference
Jayanth Othayothc2ece2d2017-08-09 06:57:12 -0500269function check_size()
270{
271 source=$1
272
273 #No size check required incase dump_size is set to unlimited
274 if [ $dump_size = $UNLIMITED ]; then
275 return 0
276 fi
277
278 #get the file or directory size
279 if [[ -d $source ]] && [[ -n $source ]]; then
280 tar -cf "$source.tar" -C \
281 $(dirname "$source") $(basename "$source")
282 size=$(stat -c%s "$source.tar")
283 rm "$source.tar"
284 else
285 size=$(stat -c%s "$source")
286 fi
287
288 if [ $((size + cur_dump_size)) -gt $dump_size ]; then
289 #Exceed the allowed limit,
290 #tar and compress the files and check the size
291 tar -Jcf "$name_dir.tar.xz" -C \
292 $(dirname "$name_dir") $(basename "$name_dir")
293 size=$(stat -c%s "$name_dir.tar.xz")
294 if [ $size -gt $dump_size ]; then
295 #Remove the the specific data from the name_dir and contniue
296 rm "$source" "$name_dir.tar.xz"
297 return $RESOURCE_UNAVAILABLE
298 else
299 rm "$name_dir.tar.xz"
300 fi
301 fi
302
303 #Remove the compressed file from the name directory
304 cur_dump_size=$((size + cur_dump_size))
305 return $SUCCESS
306}
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500307
Jayanth Othayothe20d5e02017-08-09 06:48:45 -0500308# @brief Initial version of the summary log
309init_summary()
310{
311 log_summary "Name: $name.tar.xz"
312 log_summary "Epochtime: $EPOCHTIME"
313 log_summary "ID: $dump_id"
314 log_summary "Type: $dump_type"
315 log_summary "Optional file: $optional_file"
316}
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500317
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500318# @brief Check the validity of user inputs and initialize global
319# variables. Create directory for temporary data collection
320# @return 0 on success, error code otherwise
321
322function initialize()
323{
324 #Dump file name
325 if [ -z $name ]; then
326 name=$"obmcdump_"$dump_id"_$EPOCHTIME"
327 fi
328
329 #Create temporary data directory.
330 mkdir -p "$TMP_DIR/$name"
331 if [ $? -ne 0 ]; then
332 echo "Error: Failed to create the temporary directory."
333 return $RESOURCE_UNAVAILABLE;
334 fi
335
336 #name directory
337 name_dir="$TMP_DIR/$name"
338
339 #dreport log file
340 dreport_log="$name_dir/$DREPORT_LOG"
341
342 #summary log file
343 summary_log="$name_dir/$SUMMARY_LOG"
344
345 #Type
346 if [[ !($dump_type = $TYPE_USER || $dump_type = $TYPE_CORE) ]]; then
347 log_error "Invalid -type, Only summary log is available"
348 dump_type=$SUMMARY_DUMP
349 fi
350
351 #Size
352 #Check the input is integer.
353 if [ "$dump_size" -eq "$dump_size" ] 2>/dev/null; then
354 #Converts in to bytes.
355 dump_size="$((dump_size * 1024))"
356 else
357 dump_size=$UNLIMITED
358 fi
359
360 return $SUCCESS
361}
362
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500363# @brief Packaging the dump and transferring to dump location.
364function package()
365{
366 mkdir -p "$dump_dir"
367 if [ $? -ne 0 ]; then
368 log_error "Could not create the destination directory $dump_dir"
369 dest_dir=$TMP_DIR
370 fi
371
372 #TODO openbmc/openbmc#1506 Enable file level compression.
373 #tar and compress the files.
374 tar_file="$name_dir.tar.xz"
375 tar -Jcf "$tar_file" -C "$TMP_DIR" "$name"
376
377 #remove the temporary name specific directory
378 rm -r "$name_dir"
379
380 #check the file size is in the allowed limit
381 if [ $(stat -c%s "$tar_file") -gt $dump_size ]; then
382 echo "File size exceeds the limit allowed"
383 rm -rf "$TMP_DIR"
384 exit 1
385 #TODO openbmc/openbmc#1506 Revisit the error handling
386 fi
387
388 echo "Report is available in $dump_dir"
389
390 if [ "$TMP_DIR" == "$dump_dir" ]; then
391 return
392 fi
393
394 #copy the compressed tar file into the destination
395 cp "$tar_file" "$dump_dir"
396 if [ $? -ne 0 ]; then
397 echo "Failed to copy the $tar_file to $dump_dir"
398 return
399 else
400 rm -rf "$TMP_DIR"
401 fi
402}
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500403# @brief log the error message
404# @param error message
405function log_error()
406{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500407 echo "ERROR: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500408 if ((quiet != TRUE)); then
409 echo "ERROR: $@" >&2
410 fi
411}
412
413# @brief log warning message
414# @param warning message
415function log_warning()
416{
417 if ((verbose == TRUE)); then
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500418 echo "WARNING: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500419 if ((quiet != TRUE)); then
420 echo "WARNING: $@" >&2
421 fi
422 fi
423}
424
425# @brief log info message
426# @param info message
427function log_info()
428{
429 if ((verbose == TRUE)); then
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500430 echo "INFO: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500431 if ((quiet != TRUE)); then
432 echo "INFO: $@" >&1
433 fi
434 fi
435}
436
437# @brief log summary message
438# @param message
439function log_summary()
440{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500441 echo "$@" >> $summary_log
442 if ((quiet != TRUE)); then
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500443 echo "$@" >&1
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500444 fi
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500445}
446
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500447# @brief Main function
448function main()
449{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500450 #initialize the global variables and
451 #create temporary storage locations
452 initialize
453 result=$?
454 if [[ ${result} -ne $SUCCESS ]]; then
455 echo $(date -u)" Error: Failed to initialize, Exiting"
456 exit;
457 fi
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500458
Jayanth Othayothe20d5e02017-08-09 06:48:45 -0500459 #Initilize the summary log
460 init_summary
461
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500462 #TODO Add Dump report generating script.
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500463
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500464 package #package the dump
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500465}
466
467TEMP=`getopt -o n:d:i:t:s:f:vVqh \
468 --long name:,dir:,dumpid:,type:,size:,file:,verbose,version,quiet,help \
469 -- "$@"`
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500470
471if [ $? -ne 0 ]
472then
473 echo "Error: Invalid options"
474 exit 1
475fi
476
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500477eval set -- "$TEMP"
478
479while [[ $# -gt 1 ]]; do
480 key="$1"
481 case $key in
482 -n|--name)
483 name=$2
484 shift 2;;
485 -d|--dir)
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500486 dump_dir=$2
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500487 shift 2;;
488 -i|--dumpid)
489 dump_id=$2
490 shift 2;;
491 -t|--type)
492 dump_type=$2
493 shift 2;;
494 -s|--size)
495 dump_size=$2
496 shift 2;;
497 -f|--file)
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500498 optional_file=$2
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500499 shift 2;;
500 -v|—-verbose)
501 verbose=$TRUE
502 shift;;
503 -V|--version)
504 shift;;
505 -q|—-quiet)
506 quiet=$TRUE
507 shift;;
508 -h|--help)
509 echo "$help"
510 exit;;
511 *) # unknown option
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500512 log_error "Unknown argument: $1"
513 log_info "$help"
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500514 exit 1;;
515 esac
Jayanth Othayoth9e95f4b2017-07-24 06:42:24 -0500516done
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500517
518main #main program
519exit $?