Skip to content

Instantly share code, notes, and snippets.

@waa
Last active August 22, 2019 07:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save waa/0046ea8f75c46430d4ef84322a978f11 to your computer and use it in GitHub Desktop.
Save waa/0046ea8f75c46430d4ef84322a978f11 to your computer and use it in GitHub Desktop.
Bacula Status widget for the Smashing Dashboard

This is a widget for the Smashing dashboard. It displays quite a bit of statistics about your Bacula backup server environment.

Preview

Prerequisites

It should be opbvious, but you will need a fully functional Bacula (community or enterprise edition) installation. This widget makes use of the Bacula command line tool called bconsole to query the Director for information, then sends the data to the Smashing server via curl.

Installation

Copy the smashing-BaculaStatus.sh bash shell script to any directory you like. It may be somewhere on the smashing server, on the Bacula Director, or any machine where cron is available. Near the top of this file, edit the variables to match your system. You will need to create a bconsole-smashing.conf file, and the information (password etc) in this file will need to match a console section in the Director's "bacula-dir.conf" config file. (see examples below)

bacula-dir.conf

Here is a snippet of a Console resource in the bacula-dir.conf file which will restrict our script/widget to just being able to issue the "list" command. After editing the bacula-dir.conf file, type reload in bconsole or restart the Director:

Console {
  Name = smashing
  Password = "dpvCLchbz0I4/tf5HAB8sN0z"  # Some pseudo random password
  CatalogACL = MyCatalog                 # Set this to the name of your Bacula catalog database
  CommandACL = list                      # Only allow "list" command
  JobACL = *all*                         # Allow "list jobs" command to show all jobs
  ClientACL = *all*                      # Required for Bacula Enterprise Edition
  FilesetACL = *all*                     # Required for Bacula Enterprise Edition
}

bconsole-smashing.conf

Director {
  Name = bacula-dir            # Set this to the name of your Bacula director
  DIRport = 9101
  Address = bacula.example.com # IP address or FQDN of your Bacula Director
  Password = ""                # Not used, so it may be blank 
}

Console {
  Name = smashing                         # Must match the name of the Console in the bacula-dir.conf
  Password = "dpvCLchbz0I4/tf5HAB8sN0z"   # Must match the Console's Password in the bacula-dir.conf above
  Director = bacula-dir                   # Must match the Name of the Director in this file just above
}

Testing bconsole connectivity

At this point, we should be able to connect to the Director with bconsole using the bconsole-smashing.conf configuration file and type the "list jobs" "list jobtotals" and "list clients" commands that the widget will use:

$ bconsole -c /path/to/bconsole-smashing.conf
Connecting to Director bacula.example.com:9101
1000 OK: 103 bacula-dir Version: 9.0.3 (08 August 2017)
Enter a period to cancel a command.
*list jobs limit=10
Automatically selected Catalog: MyCatalog
Using Catalog "MyCatalog"
+-------+-------------+---------------------+------+-------+----------+----------+-----------+
| jobid | name        | starttime           | type | level | jobfiles | jobbytes | jobstatus |
+-------+-------------+---------------------+------+-------+----------+----------+-----------+
| 9,730 | SpeedyVMs   | 2016-06-21 20:00:00 | B    | I     |        0 |        0 | T         |
| 9,743 | SpeedyMusic | 2016-06-22 20:00:01 | B    | I     |        0 |        0 | T         |
[...]

And now the "list jobtotals" command:

*list jobtotals
+------+------------+---------------+------------------------+
| jobs | files      | bytes         | job                    |
+------+------------+---------------+------------------------+
|   24 |     22,886 | 506377942     | upsmon                 |
|    2 |  1,247,407 | 169475049168  | Speedy                 |
|  159 |          0 | 0             | UpdateSlots            |
|   29 | 19,578,500 | 1296746802362 | Zimbra8                |
|   33 |      3,680 | 191430895439  | Catalog                |
|   65 |      7,402 | 394530438401  | RestoreCatalog         |
|   30 |    629,553 | 6319028879    | dns1                   |
[...]
|   10 |     81,558 | 3967342055    | proxmox-a              |
|    1 |         47 | 907607706207  | Proxmox_VM_Backups     |
+------+------------+---------------+------------------------+
+-------+------------+---------------+
| jobs  | files      | bytes         |
+-------+------------+---------------+
| 1,458 | 29,611,195 | 6526958283636 |
+-------+------------+---------------+

And finally the "list clients" command:

*list clients
+----------+-------------------+---------------+--------------+
| clientid | name              | fileretention | jobretention |
+----------+-------------------+---------------+--------------+
|        1 | bacula-fd         |    31,536,000 |   31,536,000 |
|        2 | speedy-fd         |    31,536,000 |   31,536,000 |
|        3 | upsmon            |    31,536,000 |   31,536,000 |
|        6 | zimbra8-fd        |    31,536,000 |   31,536,000 |
[...]

Dashboard entry

Add the following to your dashboard.erb file:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="2">
  <div data-id="bacula" data-view="Bacula" data-title="Bacula Backups" data-runningjobs="Waiting on update" data totalclients="Waiting on update" data totaljobs="Waiting on update" data-goodjobs="Waiting on update" data-problemjobs="Waiting on update" data-incompletejobs="Waiting on update" data-firstlast="Waiting on update" data-adminjobs="Waiting on update" data-verifyjobs="Waiting on update" data-restorejobs="Waiting on update" data-totalfiles="Waiting on update" data-totalbytes="Waiting on update">
  </div>
</li>

Widget files

  • Copy the bacula.coffee, bacula.html, and bacula.scss to widgets/bacula
  • Copy the smashing-BaculaStatus.sh script somehere, and set it executable:
    • # chmod +x smashing-BaculaStatus.sh
  • Edit the system variables at the top of the smashing-BaculaStatus.sh script

cron job

  • Add the following line you your cron scheduler. This example will run the script every 30 minutes:
*/30 * * * * /path/to/smashing-BaculaStatus.sh      # Of course, use the correct path here :)

Enjoy!

Please let me know if there is something terrribly wrong with this widget. It is my first one, and I am sure it can use some enhancements, or fixes.

<h1 class="title" data-bind="title"></h1>
<hr>
<h3 data-bind="runningjobs"></h3>
<h3 data-bind="totalclients"></h3>
<h3 data-bind="totaljobs"></h3>
<h3 data-bind="goodjobs"></h3>
<h3 data-bind="problemjobs"></h3>
<h3 data-bind="incompletejobs"></h3>
<h3 data-bind="firstlast"></h3>
<hr>
<h3 data-bind="adminjobs"></h3>
<h3 data-bind="verifyjobs"></h3>
<h3 data-bind="restorejobs"></h3>
<hr>
<center>Total Files & Bytes</center>
<h3 data-bind="totalfiles"></h3>
<h3 data-bind="totalbytes"></h3>
<p class="updated-at" data-bind="updatedAtMessage"></p>
class Dashing.Bacula extends Dashing.Widget
ready: ->
# This is fired when the widget is done being rendered
onData: (data) ->
# Handle incoming data
# You can access the html node of this widget with `@node`
# Example: $(@node).fadeOut().fadeIn() will make the node flash each time data comes in.
# $(@node).fadeOut().fadeIn()
.widget-bacula {
background: #ca1108;
font-size: 30px;
}
#!/bin/bash
#
# smashing-BaculaStatus.sh
#
# ------------------------------------------------------------------------------
#
# waa - 20170923 - Initial release. Full changlog at bottom of script
#
# ------------------------------------------------------------------------------
#
# Copyright (c) 2017, William A. Arlofski waa-at-revpol-dot-com
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ------------------------------------------------------------------------------
# System variables
# ----------------
bc="/usr/sbin/bconsole"
bcconfig="/etc/bacula/bconsole-smashing.conf"
http="http" # Does smashing server use http or https?
smashinghost="smashing.example.com"
smashingport="3030"
smashingauthtoken="123xyz"
smashingwidget="bacula"
smashingwidgettitle="Bacula Status"
# --------------------------------------------------
# Nothing should need to be modified below this line
# --------------------------------------------------
# Get data from Bacula Director
# -----------------------------
listjobs=$(echo "list jobs" | ${bc} -c ${bcconfig} | grep "^| \+[0-9]")
jobtotals=$(echo "list jobtotals" | ${bc} -c ${bcconfig} | tail -n4 | grep "^| \+[0-9]")
totalclients=$(echo "list clients" | ${bc} -c ${bcconfig} | grep "^| \+[0-9]" | wc -l)
# Parse the data for each of the variables we want to display
# -----------------------------------------------------------
runningjobs=$(printf "%'d\n" $(echo "${listjobs}" | grep "^| \+[0-9]" | grep -v "| [ADEefIT] \+|$" | wc -l))
totaljobs=$(echo ${jobtotals} | awk '{print $2}')
firstjob=$(echo "${listjobs}" | head -n 1 | cut -d '|' -f2 | tr -d ' ')
lastjob=$(echo "${listjobs}" | tail -n 1 | cut -d '|' -f2 | tr -d ' ')
goodjobs=$(printf "%'d\n" $(echo "${listjobs}" | grep "| T \+|$" | wc -l))
abortedjobs=$(echo "${listjobs}" | grep "| A \+|$" | wc -l)
errorjobs=$(echo "${listjobs}" | grep "| E \+|$" | wc -l)
diffjobs=$(echo "${listjobs}" | grep "| D \+|$" | wc -l)
failedjobs=$(echo "${listjobs}" | grep "| f \+|$" | wc -l)
incompletejobs=$(printf "%'d\n" $(echo "${listjobs}" | grep "| I \+|$" | wc -l))
problemjobs=$(printf "%'d\n" $(echo "${abortedjobs} + ${errorjobs} + ${diffjobs} + ${failedjobs} + ${incompletejobs}" | bc))
adminjobs=$(printf "%'d\n" $(echo "${listjobs}" | grep "^| \+[0-9]" | grep "[0-9] | D |" | wc -l))
verifyjobs=$(printf "%'d\n" $(echo "${listjobs}" | grep "^| \+[0-9]" | grep "[0-9] | V |" | wc -l))
restorejobs=$(printf "%'d\n" $(echo "${listjobs}" | grep "^| \+[0-9]" | grep "[0-9] | R |" | wc -l))
totalfiles=$(echo "${jobtotals}" | awk '{print $4}')
totalbytes=$(echo "${jobtotals}" | awk '{print $6}' | numfmt --to=iec --suffix=B)
# Send data to smashing server
# ----------------------------
curl -m 10 -s -d "{ \"auth_token\": \"${smashingauthtoken}\", \
\"title\": \"${smashingwidgettitle}\", \
\"runningjobs\": \"Running Jobs: ${runningjobs}\", \
\"totalclients\": \"Total Clients: ${totalclients}\", \
\"totaljobs\": \"Total Jobs: ${totaljobs}\", \
\"goodjobs\": \"Good Jobs: ${goodjobs}\", \
\"problemjobs\": \"Problem Jobs: ${problemjobs}\", \
\"incompletejobs\": \"Incomplete Jobs: ${incompletejobs}\", \
\"firstlast\": \"First/Last: ${firstjob}/${lastjob}\", \
\"adminjobs\": \"Admin Jobs: ${adminjobs}\", \
\"verifyjobs\": \"Verify Jobs: ${verifyjobs}\", \
\"restorejobs\": \"Restore Jobs: ${restorejobs}\", \
\"totalfiles\": \"Files: ${totalfiles}\", \
\"totalbytes\": \"Bytes: ${totalbytes}\" }" \
${http}://${smashinghost}:${smashingport}/widgets/${smashingwidget}
# -------------
# End of script
# -------------
# ----------
# Change Log
# ----------
# ----------------------------
# William A. Arlofski
# Reverse Polarity, LLC
# helpdesk@revpol.com
# http://www.revpol.com/bacula
# ----------------------------
#
#
# 20170923 - Initial release
#
# 20170925 - Re-write script so that only three bconsole calls are made, and 'bc'
# is no longer necessary to perform any math.
# - Added $smashingwidgettitle variable to allow setting the title from
# the script.
# - Rearranged the order of the output a little. Changed in the
# widgets/bacula/bacula.html file too.
# - Added a $totalclients variable to report.
# - Set 10 second timeout on curl command
# -------------------------------------------------------------------------------
# I like small tabs. Use :set list in vim to see tabbing etc
# vim: set tabstop=2:softtabstop=2:shiftwidth=2 #
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment