Current File : //usr/local/jetapps/usr/share/rear/lib/bareos-functions.sh |
#
# Bareos helper functions.
#
#
# helper functions for easier handling bconsole output
# (remove irrelevant parts of the output).
#
function bcommand()
{
local OPTIND=1
local pre_commands=( "." )
while getopts ":p:" option "$@"; do
case $option in
(p)
pre_commands+=( "$OPTARG" )
;;
(\?)
BugError "Invalid option: -$OPTARG"
;;
esac
done
shift $((OPTIND-1))
local command="$1"
local output
output=$(
(
for i in "${pre_commands[@]}"; do
echo "$i"
done
echo "$command"
) | bconsole
)
local rc=$?
(( rc > 0 )) && return $rc
local command_as_regex
command_as_regex=$( sed -e 's/\./\\./g' -e 's/\//\\\//g' <<< "$command" )
# Remove all header lines, by searching when the provided command appears in the output.
# In api mode json, a "}" may appear at the start of the line.
sed -r "0,/^[}]?${command_as_regex}$/d" <<< "$output"
}
function bcommand_json()
{
bcommand -p ".api json compact=no" "$1"
return $?
}
function bcommand_extract_value()
{
local key="$1"
local sed_arg
sed_arg="$(printf 's/^ *%s: (.*) *$/\\1/p' "$key")"
sed -n -r "$sed_arg"
}
function bareos_ensure_client_is_available()
{
local client="$1"
[ "$client" ] || Error "No client name given"
# With
# bconsole <<< "status client=$client"
# the local command bconsole first connects to the configured Bareos Director.
# The Bareos Director then connects to the client,
# asks for the status and sends the output back.
# When both systems are reachable, the output looks similar to following:
#
# Connecting to Director 192.168.121.219:9101
# Encryption: TLS_CHACHA20_POLY1305_SHA256 TLSv1.3
# 1000 OK: bareos-dir Version: 23.0.3~pre135.a9e3d95ca (28 May 2024)
# Bareos community build (UNSUPPORTED).
# Get professional support from https://www.bareos.com
# You are logged in as: operator
#
# Enter a period (.) to cancel a command.
# *status client=client1-fd
# Connecting to Client client1-fd at 192.168.121.253:9102
# Probing client protocol... (result will be saved until config reload)
# Handshake: Immediate TLS, Encryption: TLS_CHACHA20_POLY1305_SHA256 TLSv1.3
#
# debian11-fd Version: 21.1.10 (04 June 2024) Debian GNU/Linux 11 (bullseye)
# Daemon started 13-Jun-24 08:50. Jobs: run=0 running=0, Bareos subscription binary
# Sizeof: boffset_t=8 size_t=8 debug=0 trace=0 bwlimit=0kB/s
#
# Running Jobs:
# bareos-dir (director) connected at: 13-Jun-24 13:41
# No Jobs running.
# ====
#
# Terminated Jobs:
# JobId Level Files Bytes Status Finished Name
# ======================================================================
# 18 Full 59,653 2.504 G OK 05-Jun-24 14:00 backup-client1
# ====
# When bconsole can't access the Bareos Director, it exits with an error code.
# When the Director does not know the client, it prints an error message and no "Connecting to Client".
# When the Director knows about the client, but can't reach it,
# the "Running Jobs:" text does not appear.
# The "Running Jobs:" headline even shown when no jobs are running.
# In this case, the additional sentence "No Jobs running." is added.
local rc
local bconsole_client_status
# With bcommand the strip information normally not relevant ("Connecting to the Bareos Director", ...).
# To get all status information we use the plain bconsole command here.
bconsole_client_status=$(bconsole <<< "status client=$client")
rc=$?
if [ $rc -eq 0 ]; then
Log "$bconsole_client_status"
else
LogPrint "$bconsole_client_status"
Error "Failed to connect to Bareos Director."
fi
if ! grep "Connecting to Client $client" <<< "$bconsole_client_status"; then
Error "Failure: The Bareos Director cannot connect to the local filedaemon ($client)."
fi
if ! grep "Running Jobs:" <<< "$bconsole_client_status"; then
Error "Failure: The Bareos Director cannot connect to the local filedaemon ($client)."
fi
LogPrint "Bareos Director: can connect to the local filedaemon ($client)"
}
function get_available_restore_job_names()
{
# example output of 'bcommand_json "show jobs"':
# {
# "jsonrpc": "2.0",
# "id": null,
# "result": {
# "jobs": {
# "RestoreFiles": {
# "name": "RestoreFiles",
# "type": "Restore",
# "fileset": "LinuxAll",
# "where": "/tmp/bareos-restores",
# "jobdefs": "DefaultJob"
# },
# "backup-bareos-fd": {
# "name": "backup-bareos-fd",
# "client": "bareos-fd",
# "jobdefs": "DefaultJob"
# }
# }
# }
# }
local show_jobs
show_jobs="$( bcommand_json "show jobs" )"
jq --exit-status --raw-output '.result.jobs | with_entries(select(.value.type == "Restore")) | .[].name' <<< "$show_jobs"
}
function get_last_restore_jobid()
{
# example output of 'bcommand_json "list jobs client=client1-fd jobtype=R last"':
# {
# "jsonrpc": "2.0",
# "id": null,
# "result": {
# "jobs": [
# {
# "jobid": "59",
# "name": "RestoreFiles",
# "client": "client1-fd",
# "starttime": "2024-06-14 10:30:06",
# "duration": "00:00:28",
# "type": "R",
# "level": "F",
# "jobfiles": "59653",
# "jobbytes": "2504969851",
# "jobstatus": "T"
# }
# ],
# "meta": {
# "range": {
# "filtered": 0
# }
# }
# }
# }
local bcommand_result
bcommand_result=$( bcommand_json "list jobs $RESTOREJOB_AS_JOB client=$BAREOS_CLIENT jobtype=R last" )
jq --exit-status --raw-output '[ .result.jobs[].jobid ] | max' <<< "$bcommand_result"
}
function get_jobstatus_exitcode()
{
local jobstatus="$1"
# example output of 'bcommand_json ".jobstatus=E"':
# {
# "jsonrpc": "2.0",
# "id": null,
# "result": {
# "jobstatus": [
# {
# "jobstatus": "E",
# "jobstatuslong": "Terminated with errors",
# "severity": "25",
# "exitlevel": "2",
# "exitstatus": "Error"
# }
# ]
# }
# }
# Note:
# exitstatus is
# "" when job is still running,
# "0" on OK,
# "1" OK with Warnings
# "2" Errors
local jobstatus_info
jobstatus_info="$( bcommand_json ".jobstatus=$jobstatus" )"
jq --exit-status --raw-output '.result.jobstatus[0].exitlevel' <<< "$jobstatus_info"
}
function get_jobid_exitcode()
{
local jobid="$1"
# example output of 'bcommand_json "list jobid=56"':
# {
# "jsonrpc": "2.0",
# "id": null,
# "result": {
# "jobs": [
# {
# "jobid": "56",
# "name": "RestoreFiles",
# "client": "client1--fd",
# "starttime": "2024-06-14 09:40:33",
# "duration": "00:00:28",
# "type": "R",
# "level": "F",
# "jobfiles": "59653",
# "jobbytes": "2504969851",
# "jobstatus": "T"
# }
# ]
# }
# }
local jobid_info
jobid_info="$( bcommand_json "list jobid=$jobid" )"
local job_jobstatus
job_jobstatus="$( jq --exit-status --raw-output '.result.jobs[0].jobstatus' <<< "$jobid_info" )"
get_jobstatus_exitcode "$job_jobstatus"
}
function wait_for_newer_restore_job_to_start()
{
local last_restore_jobid_old="$1"
ProgressStart "Waiting for Restore Job to start"
local last_restore_jobid="$last_restore_jobid_old"
declare -i count=60
while [ "$last_restore_jobid" = "$last_restore_jobid_old" ]; do
last_restore_jobid=$( get_last_restore_jobid )
(( count-- ))
ProgressInfo "Waiting for Restore Job to start (${count}s) "
if (( count <= 0 )); then
# Restore Job did not start!
return 1
fi
sleep 1
done
ProgressStop
echo "$last_restore_jobid"
}
#
# wait_restore_job():
#
# return code:
# 0: OK
# 1: OK with warnings
# >1: Error
#
function wait_restore_job()
{
local restore_jobid="$1"
[ "$restore_jobid" ] || Error "No restore jobid given"
LogPrint "Information about restore job $restore_jobid:"
LogPrint "$( bcommand "llist jobid=$restore_jobid" )"
LogPrint "Waiting for restore job $restore_jobid to finish."
ProgressStart "Restoring data"
local restore_exitstatus=""
local used_disk_space
local jobid_info
local starttime
local duration
local jobstatus
# empty string means no status yet
while ! [ "$restore_exitstatus" ]; do
# example output of 'bcommand_json "list jobid=56"':
# {
# "jsonrpc": "2.0",
# "id": null,
# "result": {
# "jobs": [
# {
# "jobid": "56",
# "name": "RestoreFiles",
# "client": "client1--fd",
# "starttime": "2024-06-14 09:40:33",
# "duration": "00:00:28",
# "type": "R",
# "level": "F",
# "jobfiles": "59653",
# "jobbytes": "2504969851",
# "jobstatus": "T"
# }
# ]
# }
# }
used_disk_space="$( total_target_fs_used_disk_space )"
jobid_info="$( bcommand_json "list jobid=$restore_jobid" )"
starttime="$( jq -r '.result.jobs[0].starttime' <<< "$jobid_info" )"
duration="$( jq -r '.result.jobs[0].duration' <<< "$jobid_info" )"
jobstatus="$( jq -r '.result.jobs[0].jobstatus' <<< "$jobid_info" )"
restore_exitstatus="$( get_jobstatus_exitcode "$jobstatus" )"
ProgressInfo "Start: [$starttime], Duration: [$duration], Status: [$jobstatus], Restored: [$used_disk_space] "
sleep "$PROGRESS_WAIT_SECONDS"
done
ProgressStop
LogPrint "Information about finished job:"
LogPrint "$( bcommand "llist jobid=$restore_jobid" )"
LogPrint "Restored $(total_target_fs_used_disk_space)"
return "$restore_exitstatus"
}