blob: 42b97334d46c38f2daed94663bd7b53663be6b2b [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
308# @brief Calculate file or directory compressed size based on input
309# and check whether the size in the the allowed size limit.
310# Remove the file or directory from the name_dir
311# if the check fails.
312# @param $1 Source file or directory
313# @return 0 on success, error code if size exceeds the limit.
314# Limitation: compress and tar will have few bytes size difference
Jayanth Othayothc2ece2d2017-08-09 06:57:12 -0500315function check_size()
316{
317 source=$1
318
319 #No size check required incase dump_size is set to unlimited
320 if [ $dump_size = $UNLIMITED ]; then
321 return 0
322 fi
323
324 #get the file or directory size
325 if [[ -d $source ]] && [[ -n $source ]]; then
326 tar -cf "$source.tar" -C \
327 $(dirname "$source") $(basename "$source")
328 size=$(stat -c%s "$source.tar")
329 rm "$source.tar"
330 else
331 size=$(stat -c%s "$source")
332 fi
333
334 if [ $((size + cur_dump_size)) -gt $dump_size ]; then
335 #Exceed the allowed limit,
336 #tar and compress the files and check the size
337 tar -Jcf "$name_dir.tar.xz" -C \
338 $(dirname "$name_dir") $(basename "$name_dir")
339 size=$(stat -c%s "$name_dir.tar.xz")
340 if [ $size -gt $dump_size ]; then
341 #Remove the the specific data from the name_dir and contniue
342 rm "$source" "$name_dir.tar.xz"
343 return $RESOURCE_UNAVAILABLE
344 else
345 rm "$name_dir.tar.xz"
346 fi
347 fi
348
349 #Remove the compressed file from the name directory
350 cur_dump_size=$((size + cur_dump_size))
351 return $SUCCESS
352}
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500353
Jayanth Othayothe20d5e02017-08-09 06:48:45 -0500354# @brief Initial version of the summary log
355init_summary()
356{
357 log_summary "Name: $name.tar.xz"
358 log_summary "Epochtime: $EPOCHTIME"
359 log_summary "ID: $dump_id"
360 log_summary "Type: $dump_type"
361 log_summary "Optional file: $optional_file"
362}
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500363
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500364# @brief Check the validity of user inputs and initialize global
365# variables. Create directory for temporary data collection
366# @return 0 on success, error code otherwise
367
368function initialize()
369{
370 #Dump file name
371 if [ -z $name ]; then
372 name=$"obmcdump_"$dump_id"_$EPOCHTIME"
373 fi
374
375 #Create temporary data directory.
376 mkdir -p "$TMP_DIR/$name"
377 if [ $? -ne 0 ]; then
378 echo "Error: Failed to create the temporary directory."
379 return $RESOURCE_UNAVAILABLE;
380 fi
381
382 #name directory
383 name_dir="$TMP_DIR/$name"
384
385 #dreport log file
386 dreport_log="$name_dir/$DREPORT_LOG"
387
388 #summary log file
389 summary_log="$name_dir/$SUMMARY_LOG"
390
391 #Type
392 if [[ !($dump_type = $TYPE_USER || $dump_type = $TYPE_CORE) ]]; then
393 log_error "Invalid -type, Only summary log is available"
394 dump_type=$SUMMARY_DUMP
395 fi
396
397 #Size
398 #Check the input is integer.
399 if [ "$dump_size" -eq "$dump_size" ] 2>/dev/null; then
400 #Converts in to bytes.
401 dump_size="$((dump_size * 1024))"
402 else
403 dump_size=$UNLIMITED
404 fi
405
406 return $SUCCESS
407}
408
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500409# @brief Packaging the dump and transferring to dump location.
410function package()
411{
412 mkdir -p "$dump_dir"
413 if [ $? -ne 0 ]; then
414 log_error "Could not create the destination directory $dump_dir"
415 dest_dir=$TMP_DIR
416 fi
417
418 #TODO openbmc/openbmc#1506 Enable file level compression.
419 #tar and compress the files.
420 tar_file="$name_dir.tar.xz"
421 tar -Jcf "$tar_file" -C "$TMP_DIR" "$name"
422
423 #remove the temporary name specific directory
424 rm -r "$name_dir"
425
426 #check the file size is in the allowed limit
427 if [ $(stat -c%s "$tar_file") -gt $dump_size ]; then
428 echo "File size exceeds the limit allowed"
429 rm -rf "$TMP_DIR"
430 exit 1
431 #TODO openbmc/openbmc#1506 Revisit the error handling
432 fi
433
434 echo "Report is available in $dump_dir"
435
436 if [ "$TMP_DIR" == "$dump_dir" ]; then
437 return
438 fi
439
440 #copy the compressed tar file into the destination
441 cp "$tar_file" "$dump_dir"
442 if [ $? -ne 0 ]; then
443 echo "Failed to copy the $tar_file to $dump_dir"
444 return
445 else
446 rm -rf "$TMP_DIR"
447 fi
448}
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500449# @brief log the error message
450# @param error message
451function log_error()
452{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500453 echo "ERROR: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500454 if ((quiet != TRUE)); then
455 echo "ERROR: $@" >&2
456 fi
457}
458
459# @brief log warning message
460# @param warning message
461function log_warning()
462{
463 if ((verbose == TRUE)); then
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500464 echo "WARNING: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500465 if ((quiet != TRUE)); then
466 echo "WARNING: $@" >&2
467 fi
468 fi
469}
470
471# @brief log info message
472# @param info message
473function log_info()
474{
475 if ((verbose == TRUE)); then
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500476 echo "INFO: $@" >> $dreport_log
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500477 if ((quiet != TRUE)); then
478 echo "INFO: $@" >&1
479 fi
480 fi
481}
482
483# @brief log summary message
484# @param message
485function log_summary()
486{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500487 echo "$@" >> $summary_log
488 if ((quiet != TRUE)); then
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500489 echo "$@" >&1
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500490 fi
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500491}
492
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500493# @brief Main function
494function main()
495{
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500496 #initialize the global variables and
497 #create temporary storage locations
498 initialize
499 result=$?
500 if [[ ${result} -ne $SUCCESS ]]; then
501 echo $(date -u)" Error: Failed to initialize, Exiting"
502 exit;
503 fi
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500504
Jayanth Othayothe20d5e02017-08-09 06:48:45 -0500505 #Initilize the summary log
506 init_summary
507
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500508 #TODO Add Dump report generating script.
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500509
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500510 package #package the dump
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500511}
512
513TEMP=`getopt -o n:d:i:t:s:f:vVqh \
514 --long name:,dir:,dumpid:,type:,size:,file:,verbose,version,quiet,help \
515 -- "$@"`
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500516
517if [ $? -ne 0 ]
518then
519 echo "Error: Invalid options"
520 exit 1
521fi
522
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500523eval set -- "$TEMP"
524
525while [[ $# -gt 1 ]]; do
526 key="$1"
527 case $key in
528 -n|--name)
529 name=$2
530 shift 2;;
531 -d|--dir)
Jayanth Othayothff0699d2017-07-26 07:53:03 -0500532 dump_dir=$2
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500533 shift 2;;
534 -i|--dumpid)
535 dump_id=$2
536 shift 2;;
537 -t|--type)
538 dump_type=$2
539 shift 2;;
540 -s|--size)
541 dump_size=$2
542 shift 2;;
543 -f|--file)
Jayanth Othayoth230e9a32017-08-09 06:39:59 -0500544 optional_file=$2
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500545 shift 2;;
546 -v|—-verbose)
547 verbose=$TRUE
548 shift;;
549 -V|--version)
550 shift;;
551 -q|—-quiet)
552 quiet=$TRUE
553 shift;;
554 -h|--help)
555 echo "$help"
556 exit;;
557 *) # unknown option
Jayanth Othayoth6d3ee1c2017-07-26 05:18:31 -0500558 log_error "Unknown argument: $1"
559 log_info "$help"
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500560 exit 1;;
561 esac
Jayanth Othayoth9e95f4b2017-07-24 06:42:24 -0500562done
Jayanth Othayoth7b774872017-07-26 05:02:53 -0500563
564main #main program
565exit $?