blob: 03f6e134506d4b3a4fe6f3ffe3fda02ccdba13c2 [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
Jayanth Othayothe61aee32017-08-09 07:05:06 -050091# @brief Initialize core type command array
92function runlevel_core()
93{
94command_list=(
95 move_optional_file
96 get_proc_journal
97 get_fw_level
98 get_uname
99 get_uptime
100 get_disk_usage
101 bmc_state
102 host_state
103 chassis_state
104 get_host_info
105 get_failed_services
106 get_obmc_console
107 get_cpuinfo
108 get_meminfo
109 get_top
110)
111}
112
Jayanth Othayoth0862c482017-08-09 07:02:36 -0500113function get_fw_level()
114{
115 desc="Firmware Release"
116 command="cat /etc/os-release"
117 copy_loc="firmware_release.log"
118 run_command "$command" "$copy_loc" "$desc"
119}
120
121function get_uname()
122{
123 desc="uname"
124 command="uname -a"
125 copy_loc="uname.log"
126 run_command "$command" "$copy_loc" "$desc"
127}
128
129function get_uptime()
130{
131 desc="uptime"
132 command="uptime"
133 copy_loc="uptime.log"
134 run_command "$command" "$copy_loc" "$desc"
135}
136
137function get_disk_usage()
138{
139 desc="Disk Usage"
140 command="df -hT"
141 copy_loc="disk_usage.log"
142 run_command "$command" "$copy_loc" "$desc"
143}
144
145function get_journal()
146{
147 desc="Journal log"
148 command="journalctl -o json-pretty -r"
149 copy_loc="journal.log"
150 run_command "$command" "$copy_loc" "$desc"
151}
152
Jayanth Othayothe61aee32017-08-09 07:05:06 -0500153function get_proc_journal()
154{
155 desc="Process Journal log"
156 command="journalctl -o verbose _PID=$core_pid"
157 copy_loc="proc_journal.log"
158 run_command "$command" "$copy_loc" "$desc"
159}
160
Jayanth Othayoth0862c482017-08-09 07:02:36 -0500161function get_host_info()
162{
163 desc="Host information"
164 command="hostnamectl status"
165 copy_loc="hostnamectl.log"
166 run_command "$command" "$copy_loc" "$desc"
167}
168
169function get_failed_services()
170{
171 desc="Failed Services"
172 command="systemctl --failed"
173 copy_loc="failed_services.log"
174 run_command "$command" "$copy_loc" "$desc"
175}
176
177function get_obmc_console()
178{
179 desc="OBMC Console"
180 command="cat /var/log/obmc-console.log"
181 copy_loc="obmc_console.log"
182 run_command "$command" "$copy_loc" "$desc"
183}
184
185function get_cpuinfo()
186{
187 desc="cpuinfo"
188 command="cat /proc/cpuinfo"
189 copy_loc="cpuinfo.log"
190 run_command "$command" "$copy_loc" "$desc"
191}
192
193function get_meminfo()
194{
195 desc="meminfo"
196 command="cat /proc/meminfo"
197 copy_loc="meminfo.log"
198 run_command "$command" "$copy_loc" "$desc"
199}
200
201function get_top()
202{
203 desc="top"
204 command="top -n 1 -b"
205 copy_loc="top.log"
206 run_command "$command" "$copy_loc" "$desc"
207}
208
209function bmc_state()
210{
211 desc="BMC State"
212 command="busctl get-property \
213 xyz.openbmc_project.State.BMC \
214 /xyz/openbmc_project/state/bmc0 \
215 xyz.openbmc_project.State.BMC \
216 CurrentBMCState"
217 copy_loc="BMCState.log"
218 run_command "$command" "$copy_loc" "$desc"
219}
220
221function host_state()
222{
223 desc="Host State"
224 command="busctl get-property \
225 xyz.openbmc_project.State.Host \
226 /xyz/openbmc_project/state/host0 \
227 xyz.openbmc_project.State.Host \
228 CurrentHostState"
229 copy_loc="HostState.log"
230 run_command "$command" "$copy_loc" "$desc"
231}
232
233function chassis_state()
234{
235 desc="Chassis State"
236 command="busctl get-property \
237 xyz.openbmc_project.State.Chassis \
238 /xyz/openbmc_project/state/chassis0 \
239 xyz.openbmc_project.State.Chassis \
240 CurrentPowerState"
241 copy_loc="HostState.log"
242 run_command "$command" "$copy_loc" "$desc"
243}
244
245function get_esel()
246{
247 desc="eSEL"
248
249 entries=$(busctl --list --no-pager tree \
250 xyz.openbmc_project.Logging | grep \
251 '/xyz/openbmc_project/logging/entry/')
252
253 #check for eSEL entries.
254 if [ -z "$entries" ]; then
255 log_info "No $desc entries"
256 return 0
257 fi
258
259 command="busctl --list --no-pager tree \
260 xyz.openbmc_project.Logging | grep \
261 '/xyz/openbmc_project/logging/entry/' \
262 | xargs -I {} busctl --verbose --no-pager \
263 call xyz.openbmc_project.Logging {} \
264 org.freedesktop.DBus.Properties GetAll s \
265 xyz.openbmc_project.Logging.Entry"
266 copy_loc="eSEL.log"
267 run_command "$command" "$copy_loc" "$desc"
268}
269
Jayanth Othayothe61aee32017-08-09 07:05:06 -0500270function move_optional_file()
271{
272 desc="Move Optional file"
273
274 mv $optional_file $name_dir
275 if [ $? -ne 0 ]; then
276 log_error "Failed to move file $optional_file"
277 return 1
278 fi
279 if check_size "$name_dir/$(basename "$optional_file")"; then
280 log_info "Moving file $file_name"
281 else
282 log_warning "Skipping $file_name move"
283 fi
284}
285
Jayanth Othayoth0862c482017-08-09 07:02:36 -0500286# @brief Run the requested command and save the output
287# into temporary location for successful size check
288
289function run_command()
290{
291 command="$1"
292 copy_loc="$2"
293 desc="$3"
294
295 eval $command >> "$name_dir/$copy_loc"
296 if [ $? -ne 0 ]; then
297 log_error "Failed to collect $desc"
298 return 1
299 fi
300
301 if check_size "$name_dir/$copy_loc"; then
302 log_info "Collected $desc"
303 else
304 log_warning "Skipping $desc"
305 fi
306}
Jayanth Othayothc2ece2d2017-08-09 06:57:12 -0500307
Jayanth Othayothf1e02d32017-08-09 07:06:45 -0500308# @brief Capture debug data based on the input command array.
309# and stores in to global temporary name specific location.
310# @param $1 Source array
311# @return 0 on success, error code otherwise
312function capture_data()
313{
314 source=("$@")
315
316 for ((i=0;i<${#source[@]};i+=1)); do
317 ${source[i]}
318 done
319
320 return 0
321}
322
Jayanth Othayothc2ece2d2017-08-09 06:57:12 -0500323# @brief Calculate file or directory compressed size based on input
324# and check whether the size in the the allowed size limit.
325# Remove the file or directory from the name_dir
326# if the check fails.
327# @param $1 Source file or directory
328# @return 0 on success, error code if size exceeds the limit.
329# Limitation: compress and tar will have few bytes size difference
Jayanth Othayothc2ece2d2017-08-09 06:57:12 -0500330function check_size()
331{
332 source=$1
333
334 #No size check required incase dump_size is set to unlimited
335 if [ $dump_size = $UNLIMITED ]; then
336 return 0
337 fi
338
339 #get the file or directory size
340 if [[ -d $source ]] && [[ -n $source ]]; then
341 tar -cf "$source.tar" -C \
342 $(dirname "$source") $(basename "$source")
343 size=$(stat -c%s "$source.tar")
344 rm "$source.tar"
345 else
346 size=$(stat -c%s "$source")
347 fi
348
349 if [ $((size + cur_dump_size)) -gt $dump_size ]; then
350 #Exceed the allowed limit,
351 #tar and compress the files and check the size
352 tar -Jcf "$name_dir.tar.xz" -C \
353 $(dirname "$name_dir") $(basename "$name_dir")
354 size=$(stat -c%s "$name_dir.tar.xz")
355 if [ $size -gt $dump_size ]; then
356 #Remove the the specific data from the name_dir and contniue
357 rm "$source" "$name_dir.tar.xz"
358 return $RESOURCE_UNAVAILABLE
359 else
360 rm "$name_dir.tar.xz"
361 fi
362 fi
363
364 #Remove the compressed file from the name directory
365 cur_dump_size=$((size + cur_dump_size))
366 return $SUCCESS
367}
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500368
Jayanth Othayothe20d5e02017-08-09 06:48:45 -0500369# @brief Initial version of the summary log
370init_summary()
371{
372 log_summary "Name: $name.tar.xz"
373 log_summary "Epochtime: $EPOCHTIME"
374 log_summary "ID: $dump_id"
375 log_summary "Type: $dump_type"
376 log_summary "Optional file: $optional_file"
377}
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500378
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500379# @brief Check the validity of user inputs and initialize global
380# variables. Create directory for temporary data collection
381# @return 0 on success, error code otherwise
382
383function initialize()
384{
385 #Dump file name
386 if [ -z $name ]; then
387 name=$"obmcdump_"$dump_id"_$EPOCHTIME"
388 fi
389
390 #Create temporary data directory.
391 mkdir -p "$TMP_DIR/$name"
392 if [ $? -ne 0 ]; then
393 echo "Error: Failed to create the temporary directory."
394 return $RESOURCE_UNAVAILABLE;
395 fi
396
397 #name directory
398 name_dir="$TMP_DIR/$name"
399
400 #dreport log file
401 dreport_log="$name_dir/$DREPORT_LOG"
402
403 #summary log file
404 summary_log="$name_dir/$SUMMARY_LOG"
405
406 #Type
407 if [[ !($dump_type = $TYPE_USER || $dump_type = $TYPE_CORE) ]]; then
408 log_error "Invalid -type, Only summary log is available"
409 dump_type=$SUMMARY_DUMP
410 fi
411
412 #Size
413 #Check the input is integer.
414 if [ "$dump_size" -eq "$dump_size" ] 2>/dev/null; then
415 #Converts in to bytes.
416 dump_size="$((dump_size * 1024))"
417 else
418 dump_size=$UNLIMITED
419 fi
420
421 return $SUCCESS
422}
423
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500424# @brief Packaging the dump and transferring to dump location.
425function package()
426{
427 mkdir -p "$dump_dir"
428 if [ $? -ne 0 ]; then
429 log_error "Could not create the destination directory $dump_dir"
430 dest_dir=$TMP_DIR
431 fi
432
433 #TODO openbmc/openbmc#1506 Enable file level compression.
434 #tar and compress the files.
435 tar_file="$name_dir.tar.xz"
436 tar -Jcf "$tar_file" -C "$TMP_DIR" "$name"
437
438 #remove the temporary name specific directory
439 rm -r "$name_dir"
440
441 #check the file size is in the allowed limit
442 if [ $(stat -c%s "$tar_file") -gt $dump_size ]; then
443 echo "File size exceeds the limit allowed"
444 rm -rf "$TMP_DIR"
445 exit 1
446 #TODO openbmc/openbmc#1506 Revisit the error handling
447 fi
448
449 echo "Report is available in $dump_dir"
450
451 if [ "$TMP_DIR" == "$dump_dir" ]; then
452 return
453 fi
454
455 #copy the compressed tar file into the destination
456 cp "$tar_file" "$dump_dir"
457 if [ $? -ne 0 ]; then
458 echo "Failed to copy the $tar_file to $dump_dir"
459 return
460 else
461 rm -rf "$TMP_DIR"
462 fi
463}
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500464# @brief log the error message
465# @param error message
466function log_error()
467{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500468 echo "ERROR: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500469 if ((quiet != TRUE)); then
470 echo "ERROR: $@" >&2
471 fi
472}
473
474# @brief log warning message
475# @param warning message
476function log_warning()
477{
478 if ((verbose == TRUE)); then
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500479 echo "WARNING: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500480 if ((quiet != TRUE)); then
481 echo "WARNING: $@" >&2
482 fi
483 fi
484}
485
486# @brief log info message
487# @param info message
488function log_info()
489{
490 if ((verbose == TRUE)); then
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500491 echo "INFO: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500492 if ((quiet != TRUE)); then
493 echo "INFO: $@" >&1
494 fi
495 fi
496}
497
498# @brief log summary message
499# @param message
500function log_summary()
501{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500502 echo "$@" >> $summary_log
503 if ((quiet != TRUE)); then
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500504 echo "$@" >&1
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500505 fi
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500506}
507
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500508# @brief Main function
509function main()
510{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500511 #initialize the global variables and
512 #create temporary storage locations
513 initialize
514 result=$?
515 if [[ ${result} -ne $SUCCESS ]]; then
516 echo $(date -u)" Error: Failed to initialize, Exiting"
517 exit;
518 fi
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500519
Jayanth Othayothe20d5e02017-08-09 06:48:45 -0500520 #Initilize the summary log
521 init_summary
522
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500523 #TODO Add Dump report generating script.
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500524
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500525 package #package the dump
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500526}
527
528TEMP=`getopt -o n:d:i:t:s:f:vVqh \
529 --long name:,dir:,dumpid:,type:,size:,file:,verbose,version,quiet,help \
530 -- "$@"`
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500531
532if [ $? -ne 0 ]
533then
534 echo "Error: Invalid options"
535 exit 1
536fi
537
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500538eval set -- "$TEMP"
539
540while [[ $# -gt 1 ]]; do
541 key="$1"
542 case $key in
543 -n|--name)
544 name=$2
545 shift 2;;
546 -d|--dir)
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500547 dump_dir=$2
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500548 shift 2;;
549 -i|--dumpid)
550 dump_id=$2
551 shift 2;;
552 -t|--type)
553 dump_type=$2
554 shift 2;;
555 -s|--size)
556 dump_size=$2
557 shift 2;;
558 -f|--file)
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500559 optional_file=$2
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500560 shift 2;;
561 -v|—-verbose)
562 verbose=$TRUE
563 shift;;
564 -V|--version)
565 shift;;
566 -q|—-quiet)
567 quiet=$TRUE
568 shift;;
569 -h|--help)
570 echo "$help"
571 exit;;
572 *) # unknown option
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500573 log_error "Unknown argument: $1"
574 log_info "$help"
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500575 exit 1;;
576 esac
Jayanth Othayoth9e95f4b2017-07-24 06:42:24 -0500577done
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500578
579main #main program
580exit $?