commit 837d177af12a86f2ad14ea901209aa772e418665 Author: root Date: Wed Sep 9 11:31:10 2015 +0200 integration check-bareos-plugin diff --git a/check_bareos/Makefile.in b/check_bareos/Makefile.in new file mode 100644 index 0000000..3637c32 --- /dev/null +++ b/check_bareos/Makefile.in @@ -0,0 +1,93 @@ +# +# Version $Id: Makefile.in,v 1.4 2004/09/25 10:19:59 nboichat Exp $ +# +@MCOMMON@ + +srcdir = ../src + +# one up +basedir = ../src/include +# top dir +topdir = .. +# this dir relative to top dir +thisdir = ../check_bareos + +DEBUG=@DEBUG@ + +first_rule: all +dummy: + +# +CHECKSRCS = check_bareos.c authenticate.c +CHECKOBJS = check_bareos.o authenticate.o + +CHECK_CPPFLAGS= +CHECK_LDFLAGS= + +.SUFFIXES: .c .o +.PHONY: +.DONTCARE: + +# inference rules +.c.o: + @echo "Compiling $<" + $(NO_ECHO) $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) $(CHECK_CPPFLAGS) \ + -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CXXFLAGS) $< +#------------------------------------------------------------------------- +all: Makefile check_bareos + @echo "==== Make of check_bareos is good ====" + @echo " " + +check_bareos: Makefile $(CHECKOBJS) $(srcdir)/lib/libbareos$(DEFAULT_ARCHIVE_TYPE) + $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) $(CHECK_LDFLAGS) -L$(srcdir)/lib -o $@ \ + $(CHECKOBJS) $(DLIB) -lbareos -lm $(LIBS) $(OPENSSL_LIBS) + + +Makefile: $(srcdir)/Makefile.in $(topdir)/config.status + cd $(topdir) \ + && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +libtool-clean: + $(RMF) -r .libs _libs + +clean: + @$(RMF) check_bareos core core.* a.out *.o *.bak *~ *.intpro *.extpro 1 2 3 + +realclean: clean + @$(RMF) tags + +distclean: realclean + if test $(srcdir) = .; then $(MAKE) realclean; fi + (cd $(srcdir); $(RMF) Makefile) + +devclean: realclean + if test $(srcdir) = .; then $(MAKE) realclean; fi + (cd $(srcdir); $(RMF) Makefile) + +install: all + $(INSTALL_PROGRAM) check_bareos $(DESTDIR)$(sbindir)/check_bareos + +uninstall: + (cd $(DESTDIR)$(sbindir); $(RMF) check_bareos) + + + +# Semi-automatic generation of dependencies: +# Use gcc -MM because X11 `makedepend' doesn't work on all systems +# and it also includes system headers. +# `semi'-automatic since dependencies are generated at distribution time. + +depend: + @$(MV) Makefile Makefile.bak + @$(SED) "/^# DO NOT DELETE:/,$$ d" Makefile.bak > Makefile + @$(ECHO) "# DO NOT DELETE: nice dependency list follows" >> Makefile + @$(CXX) -S -M $(CPPFLAGS) $(CHECK_CPPFLAGS) -I$(srcdir) -I$(basedir) *.c >> Makefile + @if test -f Makefile ; then \ + $(RMF) Makefile.bak; \ + else \ + $(MV) Makefile.bak Makefile; \ + echo -e "Something went wrong\n\a"; \ + fi + +# ----------------------------------------------------------------------- +# DO NOT DELETE: nice dependency list follows diff --git a/check_bareos/README b/check_bareos/README new file mode 100755 index 0000000..984d402 --- /dev/null +++ b/check_bareos/README @@ -0,0 +1,15 @@ +# It's more or less untested, though. +# Submitted by Arno Lehmann +# + +run ./configure with your usual options at the toplevel. Afterwards, use +'make' to create your binaries. + +If you encounter problems, you'll have to setup the Bacula source manually. + +Note that check_bareos does not support TLS and is an unsupported add-on to +Bacula. Even if it's not part of the core Bacula programs, questions can be +asked at the bareos-users mailing list. + +Bacula is a Trademark of Kern Sibbald. Bacula and the accompanying programs +are open source. See the LICENSE file for more information. diff --git a/check_bareos/authenticate.c b/check_bareos/authenticate.c new file mode 100644 index 0000000..79c5544 --- /dev/null +++ b/check_bareos/authenticate.c @@ -0,0 +1,176 @@ +/* + * + * Bacula authentication. Provides authentication with + * File and Storage daemons. + * + * Nicolas Boichat, August MMIV + * + * This routine runs as a thread and must be thread reentrant. + * + * Basic tasks done here: + * + */ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2004-2010 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation plus additions + that are listed in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ + +#include "bareos.h" +#include "check_bareos.h" + +void senditf(const char *fmt, ...); +void sendit(const char *buf); + +/* Commands sent to Director */ +static char DIRhello[] = "Hello %s calling\n"; + +/* Response from Director */ +static char DIROKhello[] = "1000 OK:"; + +/* Commands sent to Storage daemon and File daemon and received + * from the User Agent */ +static char SDFDhello[] = "Hello Director %s calling\n"; + +/* Response from SD */ +static char SDOKhello[] = "3000 OK Hello\n"; +/* Response from FD */ +static char FDOKhello[] = "2000 OK Hello"; + +/* Forward referenced functions */ + +/* + * Authenticate Director + */ +int authenticate_director(BSOCK *dir, char *dirname, char *password) +{ + int tls_local_need = BNET_TLS_NONE; + int tls_remote_need = BNET_TLS_NONE; + bool compatible = true; + char bashed_name[MAX_NAME_LENGTH]; + + bstrncpy(bashed_name, dirname, sizeof(bashed_name)); + bash_spaces(bashed_name); + + /* Timeout Hello after 5 mins */ + btimer_t *tid = start_bsock_timer(dir, 60 * 5); + bnet_fsend(dir, DIRhello, bashed_name); + + if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) || + !cram_md5_challenge(dir, password, tls_local_need, compatible)) { + stop_bsock_timer(tid); + return 0; + } + + Dmsg1(6, ">dird: %s", dir->msg); + if (bnet_recv(dir) <= 0) { + stop_bsock_timer(tid); + return 0; + } + Dmsg1(10, "msg); + stop_bsock_timer(tid); + if (!bstrncmp(dir->msg, DIROKhello, sizeof(DIROKhello)-1)) { + return 0; + } + return 1; +} + +/* + * Authenticate Storage daemon connection + */ +int authenticate_storage_daemon(BSOCK *sd, char *sdname, char* password) +{ + char dirname[MAX_NAME_LENGTH]; + int tls_local_need = BNET_TLS_NONE; + int tls_remote_need = BNET_TLS_NONE; + bool compatible = true; + + /* + * Send my name to the Storage daemon then do authentication + */ + bstrncpy(dirname, sdname, sizeof(dirname)); + bash_spaces(dirname); + /* Timeout Hello after 5 mins */ + btimer_t *tid = start_bsock_timer(sd, 60 * 5); + if (!bnet_fsend(sd, SDFDhello, dirname)) { + stop_bsock_timer(tid); + return 0; + } + if (!cram_md5_respond(sd, password, &tls_remote_need, &compatible) || + !cram_md5_challenge(sd, password, tls_local_need, compatible)) { + stop_bsock_timer(tid); + return 0; + } + Dmsg1(116, ">stored: %s", sd->msg); + if (bnet_recv(sd) <= 0) { + stop_bsock_timer(tid); + return 0; + } + Dmsg1(110, "msg); + stop_bsock_timer(tid); + if (!bstrncmp(sd->msg, SDOKhello, sizeof(SDOKhello))) { + return 0; + } + return 1; +} + +/* + * Authenticate File daemon connection + */ +int authenticate_file_daemon(BSOCK *fd, char *fdname, char *password) +{ + char dirname[MAX_NAME_LENGTH]; + int tls_local_need = BNET_TLS_NONE; + int tls_remote_need = BNET_TLS_NONE; + bool compatible = true; + + /* + * Send my name to the File daemon then do authentication + */ + bstrncpy(dirname, fdname, sizeof(dirname)); + bash_spaces(dirname); + /* Timeout Hello after 5 mins */ + btimer_t *tid = start_bsock_timer(fd, 60 * 5); + if (!bnet_fsend(fd, SDFDhello, dirname)) { + stop_bsock_timer(tid); + return 0; + } + if (!cram_md5_respond(fd, password, &tls_remote_need, &compatible) || + !cram_md5_challenge(fd, password, tls_local_need, compatible)) { + stop_bsock_timer(tid); + return 0; + } + Dmsg1(116, ">filed: %s", fd->msg); + if (bnet_recv(fd) <= 0) { + stop_bsock_timer(tid); + return 0; + } + Dmsg1(110, "msg); + stop_bsock_timer(tid); + if (!bstrncmp(fd->msg, FDOKhello, strlen(FDOKhello))) { + return 0; + } + return 1; +} diff --git a/check_bareos/check_bareos.c b/check_bareos/check_bareos.c new file mode 100644 index 0000000..de22ab3 --- /dev/null +++ b/check_bareos/check_bareos.c @@ -0,0 +1,373 @@ +/* + * + * Nagios Plugin check_bareos + * + * Christian Masopust, (c)2005 + * + * Version $Id: check_bareos.c,v 1.0 2005/02/25 + */ + +/* + Copyright (C) 2005 Christian Masopust + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bareos.h" +#include "check_bareos.h" + +#define STATE_OK 0 +#define STATE_WARNING 1 +#define STATE_CRITICAL 2 +#define STATE_UNKNOWN 3 + + +/* Imported functions */ +int authenticate_director(BSOCK *s, char *dirname, char *password); +int authenticate_file_daemon(BSOCK *s, char *fdname, char *password); +int authenticate_storage_daemon(BSOCK *s, char* sdname, char *password); + +/* Forward referenced functions */ +void writecmd(monitoritem* item, const char* command); +int docmd(monitoritem* item, const char* command, char *answer); + +/* Static variables */ +static monitoritem mitem; + +/* Data received from DIR/FD/SD */ +static char OKqstatus[] = "%c000 OK .status\n"; + + + +static void usage() +{ + fprintf(stderr, _( +"Copyright (C) 2005 Christian Masopust\n" +"Written by Christian Masopust (2005)\n" +"\nVersion: " VERSION " (" BDATE ") %s %s %s\n\n" +"Usage: check_bareos [-d debug_level] -H host -D daemon -M name -P port\n" +" -H hostname where daemon runs\n" +" -D which daemon to check: dir|sd|fd\n" +" -M name of monitor (as in bareos-*.conf)\n" +" -K password for access to daemon\n" +" -P port where daemon listens\n" +" -dnn set debug level to nn\n" +" -? print this message.\n" +"\n"), HOST_OS, DISTNAME, DISTVER); +} + + +/********************************************************************* + * + * Main Bacula Tray Monitor -- User Interface Program + * + */ +int main(int argc, char *argv[]) +{ + int ch; + DIRRES s_dird; + CLIENTRES s_filed; + STORERES s_stored; + + char host[250]; + char daemon[20]; + char monitorname[100]; + char pw[200]; + int port = 0; + + char answer[1024]; + int retcode = STATE_UNKNOWN; + + unsigned int i, j; + MD5_CTX md5c; + unsigned char signature[16]; + + + struct sigaction sigignore; + sigignore.sa_flags = 0; + sigignore.sa_handler = SIG_IGN; + sigfillset(&sigignore.sa_mask); + sigaction(SIGPIPE, &sigignore, NULL); + + strcpy (pw, ""); + + init_stack_dump(); + my_name_is(argc, argv, "check_bareos"); + textdomain("bareos"); + init_msg(NULL, NULL); + + while ((ch = getopt(argc, argv, "H:D:M:P:K:d:h?")) != -1) { + + switch (ch) { + + case 'H': + strcpy (host, optarg); + break; + + case 'D': + strcpy (daemon, optarg); + break; + + case 'M': + strcpy (monitorname, optarg); + break; + + case 'P': + port = atoi(optarg); + break; + + case 'K': + strcpy (pw, optarg); + break; + + case 'd': + debug_level = atoi(optarg); + if (debug_level <= 0) { + debug_level = 1; + } + break; + + case 'h': + case '?': + default: + usage(); + exit(1); + } + } + argc -= optind; + //argv += optind; + + if (argc) { + usage(); + exit(STATE_UNKNOWN); + } + + lmgr_init_thread(); + + char sig[100]; + MD5_Init(&md5c); + MD5_Update(&md5c, (unsigned char *) pw, strlen(pw)); + MD5_Final(signature, &md5c); + for (i = j = 0; i < sizeof(signature); i++) { + sprintf(&sig[j], "%02x", signature[i]); + j += 2; + } + + + /* director ? */ + if (bstrcmp(daemon, "dir")) { + + if (port != 0) + s_dird.DIRport = port; + else + s_dird.DIRport = 9101; + + s_dird.address = host; + s_dird.password = sig; + s_dird.hdr.name = monitorname; + + mitem.type = R_DIRECTOR; + mitem.resource = &s_dird; + mitem.D_sock = NULL; + + } else if (bstrcmp(daemon, "sd")) { + + if (port != 0) + s_stored.SDport = port; + else + s_stored.SDport = 9103; + + s_stored.address = host; + s_stored.password = sig; + s_stored.hdr.name = monitorname; + + mitem.type = R_STORAGE; + mitem.resource = &s_stored; + mitem.D_sock = NULL; + + } else if (bstrcmp(daemon, "fd")) { + + if (port != 0) + s_filed.FDport = port; + else + s_filed.FDport = 9102; + + s_filed.address = host; + s_filed.password = sig; + s_filed.hdr.name = monitorname; + + mitem.type = R_CLIENT; + mitem.resource = &s_filed; + mitem.D_sock = NULL; + + } else { + + usage(); + exit(1); + } + + + if (mitem.type == R_DIRECTOR) + retcode = docmd(&mitem, ".status dir current\n", answer); + else + retcode = docmd(&mitem, ".status current\n", answer); + + + if (mitem.D_sock) { + mitem.D_sock->signal(BNET_TERMINATE); /* send EOF */ + mitem.D_sock->close(); + mitem.D_sock = NULL; + } + + printf ("%s\n", answer); + return retcode; +} + + +static int authenticate_daemon(monitoritem* item) { + + DIRRES *d; + CLIENTRES *f; + STORERES *s; + + switch (item->type) { + case R_DIRECTOR: + d = (DIRRES *)item->resource; + return authenticate_director(item->D_sock, d->hdr.name, d->password); + break; + case R_CLIENT: + f = (CLIENTRES *)item->resource; + return authenticate_file_daemon(item->D_sock, f->hdr.name, f->password); + break; + case R_STORAGE: + s = (STORERES *)item->resource; + return authenticate_storage_daemon(item->D_sock, s->hdr.name, s->password); + break; + default: + printf("Error, currentitem is not a Client or a Storage..\n"); + return FALSE; + } +} + + + +int docmd(monitoritem* item, const char* command, char *answer) { + + int stat; + char num; + const char *dname; + + dname = ""; + + if (!item->D_sock) { + + DIRRES* dird; + CLIENTRES* filed; + STORERES* stored; + item->D_sock = (BSOCK *)malloc(sizeof(BSOCK)); +// item->D_sock->init(); + + switch (item->type) { + case R_DIRECTOR: + dird = (DIRRES*)item->resource; + item->D_sock->connect(NULL, 0, 0, 0, "Director daemon" , dird->address, NULL, dird->DIRport, 0); + dname = "Director"; + break; + case R_CLIENT: + filed = (CLIENTRES*)item->resource; + item->D_sock->connect(NULL, 0, 0, 0, "File daemon" , filed->address, NULL, filed->FDport, 0); + dname = "FileDaemon"; + break; + case R_STORAGE: + stored = (STORERES*)item->resource; + item->D_sock->connect(NULL, 0, 0, 0, "Storage daemon" , stored->address, NULL, stored->SDport, 0); + dname = "StorageDaemon"; + break; + default: + printf("Error, currentitem is not a Client, a Storage or a Director..\n"); + return STATE_UNKNOWN; + } + + if (item->D_sock == NULL) { + sprintf (answer, "BACULA CRITICAL - Cannot connect to %s!", dname); + return STATE_CRITICAL; + } + + if (!authenticate_daemon(item)) { + sprintf (answer, "BACULA CRITICAL - Cannot authenticate to %s: %s", dname, item->D_sock->msg); + item->D_sock = NULL; + return STATE_CRITICAL; + } + + } + + if (command[0] != 0) + writecmd(item, command); + + while(1) { + if ((stat = bnet_recv(item->D_sock)) >= 0) { + + /* welcome message of director */ + if ((item->type == R_DIRECTOR) && bstrncmp(item->D_sock->msg, "Using ", 6)) + continue; + + if (sscanf(item->D_sock->msg, OKqstatus, &num) != 1) { + /* Error, couldn't find OK */ + sprintf (answer, "BACULA CRITICAL - %s Status: %s", dname, item->D_sock->msg); + return STATE_CRITICAL; + } else { + sprintf (answer, "BACULA OK - %s Status OK", dname); + return STATE_OK; + } + } + else if (stat == BNET_SIGNAL) { + if (item->D_sock->msglen == BNET_EOD) { + strcpy(answer, "BACULA WARNING - << EOD >>"); + return STATE_WARNING; + } + else if (item->D_sock->msglen == BNET_SUB_PROMPT) { + strcpy(answer, "BACULA WARNING - BNET_SUB_PROMPT signal received."); + return STATE_WARNING; + } + else if (item->D_sock->msglen == BNET_HEARTBEAT) { + bnet_sig(item->D_sock, BNET_HB_RESPONSE); + } + else { + sprintf(answer, "BACULA WARNING - Unexpected signal received : %s ", bnet_sig_to_ascii(item->D_sock)); + } + } + else { /* BNET_HARDEOF || BNET_ERROR */ + strcpy(answer, "BACULA CRITICAL - ERROR: BNET_HARDEOF or BNET_ERROR"); + item->D_sock = NULL; + return STATE_CRITICAL; + } + + if (is_bnet_stop(item->D_sock)) { + item->D_sock = NULL; + return STATE_WARNING; + } + } +} + +void writecmd(monitoritem* item, const char* command) { + if (item->D_sock) { + item->D_sock->msglen = strlen(command); + pm_strcpy(&item->D_sock->msg, command); + bnet_send(item->D_sock); + } +} + diff --git a/check_bareos/check_bareos.h b/check_bareos/check_bareos.h new file mode 100644 index 0000000..73971ee --- /dev/null +++ b/check_bareos/check_bareos.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2004 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ +/* + * Includes specific to the tray monitor + * + * Nicolas Boichat, August MMIV + */ + +/* + * Resource codes -- they must be sequential for indexing + */ +enum rescode { + R_MONITOR = 1001, + R_DIRECTOR, + R_CLIENT, + R_STORAGE, + R_FIRST = R_MONITOR, + R_LAST = R_STORAGE /* keep this updated */ +}; + +/* + * Some resource attributes + */ +enum { + R_NAME = 1020, + R_ADDRESS, + R_PASSWORD, + R_TYPE, + R_BACKUP +}; + +/* Director */ +struct DIRRES { + RES hdr; + + int DIRport; /* UA server port */ + char *address; /* UA server address */ + char *password; /* UA server password */ + int enable_ssl; /* Use SSL */ +}; + +/* + * Tray Monitor Resource + * + */ +//struct MONITORRES { +// RES hdr; +// +// int require_ssl; /* Require SSL for all connections */ +// MSGSRES *messages; /* Daemon message handler */ +// char *password; /* UA server password */ +// utime_t RefreshInterval; /* Status refresh interval */ +// utime_t FDConnectTimeout; /* timeout for connect in seconds */ +// utime_t SDConnectTimeout; /* timeout in seconds */ +//}; + +/* + * Client Resource + * + */ +struct CLIENTRES { + RES hdr; + + int FDport; /* Where File daemon listens */ + char *address; + char *password; + int enable_ssl; /* Use SSL */ +}; + +/* + * Store Resource + * + */ +struct STORERES { + RES hdr; + + int SDport; /* port where Directors connect */ + char *address; + char *password; + int enable_ssl; /* Use SSL */ +}; + +/* Define the Union of all the above + * resource structure definitions. + */ +//union URES { +// //MONITOR res_monitor; +// DIRRES res_dir; +// CLIENT res_client; +// STORE res_store; +// RES hdr; +//}; + +struct monitoritem { + rescode type; /* R_DIRECTOR, R_CLIENT or R_STORAGE */ + void* resource; /* DIRRES*, CLIENT* or STORE* */ + BSOCK *D_sock; +}; diff --git a/check_bareos/check_bareos_pools.sh b/check_bareos/check_bareos_pools.sh new file mode 100644 index 0000000..e81cbe1 --- /dev/null +++ b/check_bareos/check_bareos_pools.sh @@ -0,0 +1,159 @@ +#! /bin/sh +# Author : Ludovic Strappazon. l.strappazon@gmail.com +# Copyright 2004, Free Software Foundation Europe e.V. +# Any comment, advice or enhancement are welcome :-) + +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin +MYSQL="/usr/bin/mysql -u bacula --password=mypassword" +TMP=/tmp +BACULA=/usr/local/bacula + +PROGNAME=`basename $0` +PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'` +STATUS="" + +. $PROGPATH/utils.sh + +print_usage() { + echo "Usage: $PROGNAME -P -M -w -c [-S]" +} + +print_help() { + echo "" + print_usage + echo "" + echo "This plugin checks the space available in the pool against the space required for the next scheduled backups" + echo "Example : $PROGNAME -P default -M LTO -w 20 -c 10 will check the default pool, return OK if (available space) > 1,20*(required space), WARNING if 1,20*(required space) > (available space) > 1,10*(required space), and CRITICAL else." + echo "" + echo "With the -S option, it will check the pool named Scratch and return WARNING instead of CRITICAL if the Scratch pool can save the situation." + echo "Example : $PROGNAME -P default -M LTO -w 20 -c 10 -S will check the default pool, return OK if (available space) > 1,20*(required space), WARNING if 1,20*(required space) > (available space) > 1,10*(required space) or if (available space in default and Scratch) > 1,10*(required space) > (available space in default), and CRITICAL else." + echo "" + echo "The evaluation of the space required is done by adding the biggest backups of the same level than the scheduled jobs" + echo "The available space is evaluated by the number of out of retention tapes and the average VolBytes of these Full tapes" + echo "" + echo "The Information Status are : \"Required, Available, Volume Errors\" and \"Will use Scratch pool\" if necessary." + echo "" + echo "I think this plugin should be used in passive mode, and ran by a RunAfterJob" + exit 3 +} + +NB_ARGS=$# +SCRATCH=0 +while getopts :P:M:w:c:hS OPTION +do + case $OPTION in + P) POOL="$OPTARG" + ;; + M) MEDIA_TYPE="$OPTARG" + ;; + S) SCRATCH=1 + ;; + w) WARNING="$OPTARG" + ;; + c) CRITICAL="$OPTARG" + ;; + h) print_help + exit 3 + ;; + *) print_usage + exit 3 + ;; + esac +done +shift $(($OPTIND - 1)) + +if [ "$NB_ARGS" -ne 8 -a "$NB_ARGS" -ne 9 ]; then + print_revision $PROGNAME 25/05/2005 + print_usage + exit 3 +fi + +LAST_CHECK=`ps -ef | grep check_ba[Cc]ula_pools.sh | awk {'print $5'} | uniq | wc -l` +if [ "$LAST_CHECK" -gt 1 ]; then + echo "The last check was not complete, you should increase the check_period." + exit 3 +fi + + NB_VOLUMES_OUT_OF_RETENTION=`$MYSQL << EOF +USE bacula +SELECT COUNT(MediaId) from Media, Pool where Media.PoolId=Pool.PoolId and Pool.Name="$POOL" AND LastWritten <> "0000-00-00 00:00:00" AND UNIX_TIMESTAMP()-UNIX_TIMESTAMP(LastWritten)>Media.VolRetention AND Inchanger = "1"; +EOF +` + NB_VOLUMES_OUT_OF_RETENTION=`echo $NB_VOLUMES_OUT_OF_RETENTION | cut -f 2 -d ' '` + +NB_VOLUMES_ERROR=`$MYSQL << EOF +USE bacula +SELECT COUNT(MediaId) from Media, Pool where Media.PoolId=Pool.PoolId and Pool.Name="$POOL" AND VolStatus="Error" AND Inchanger = "1"; +EOF +` +NB_VOLUMES_ERROR=`echo $NB_VOLUMES_ERROR | cut -f 2 -d ' '` + +AVERAGE_CAPA_VOLUME=`$MYSQL << EOF +USE bacula +SELECT SUM(VolBytes)/COUNT(MediaId) FROM Media where VolStatus="Full" AND MediaType="$MEDIA_TYPE"; +EOF +` +AVERAGE_CAPA_VOLUME=`echo $AVERAGE_CAPA_VOLUME | cut -f 2 -d ' ' | cut -f 1 -d '.'` + +CAPA_VOLUMES_APPEND=`$MYSQL << EOF +USE bacula +SELECT SUM("$AVERAGE_CAPA_VOLUME"-VolBytes) from Media, Pool where Media.PoolId=Pool.PoolId and Pool.Name="$POOL" AND (VolStatus = "Append" OR VolStatus = "Recycle" OR VolStatus = "Purge") AND Inchanger = "1" AND MediaType="$MEDIA_TYPE"; +EOF +` +CAPA_VOLUMES_APPEND=`echo $CAPA_VOLUMES_APPEND | cut -f 2 -d ' '` + +if [ $SCRATCH -eq 1 ] +then +CAPA_VOLUMES_SCRATCH=`$MYSQL << EOF +USE bacula +SELECT SUM("$AVERAGE_CAPA_VOLUME"-VolBytes) from Media, Pool where Media.PoolId=Pool.PoolId and Pool.Name="Scratch" AND VolStatus = "Append" AND Inchanger = "1" AND MediaType="$MEDIA_TYPE"; +EOF +` +CAPA_VOLUMES_SCRATCH=`echo $CAPA_VOLUMES_SCRATCH | cut -f 2 -d ' '` +else +CAPA_VOLUMES_SCRATCH=0 +fi + +echo "st +1 +q" | $BACULA/etc/bconsole | sed -n /Scheduled/,/Running/p | grep Backup | tr -s [:blank:] | tr '[:blank:]' '@' > ${TMP}/Scheduled.txt + +CAPA_REQUIRED=0 +for LINE in `cat ${TMP}/Scheduled.txt` +do + SCHEDULED_JOB=`echo $LINE | awk -F@ '{print $6}'` + LEVEL=`echo $LINE | awk -F@ '{print $1}' | cut -c 1` + +MAX_VOLUME_JOB_FOR_LEVEL=`$MYSQL << EOF +USE bacula +SELECT MAX(JobBytes) from Job, Pool where Level="$LEVEL" AND Job.Name="$SCHEDULED_JOB" AND Job.PoolId=Pool.PoolId AND Pool.Name="$POOL"; +EOF +` +MAX_VOLUME_JOB_FOR_LEVEL=`echo $MAX_VOLUME_JOB_FOR_LEVEL | cut -f 2 -d ' ' ` + +CAPA_REQUIRED=$[CAPA_REQUIRED+MAX_VOLUME_JOB_FOR_LEVEL] +done + +rm ${TMP}/Scheduled.txt + +CAPA_WARNING=`echo $[(WARNING+100)*CAPA_REQUIRED]/100 | bc | cut -f 1 -d '.'` +CAPA_CRITICAL=`echo $[(CRITICAL+100)*CAPA_REQUIRED]/100 | bc | cut -f 1 -d '.'` +CAPA_DISP=$[NB_VOLUMES_OUT_OF_RETENTION*AVERAGE_CAPA_VOLUME+CAPA_VOLUMES_APPEND] +CAPA_DISP_INCLUDING_SCRATCH=$[CAPA_DISP+CAPA_VOLUMES_SCRATCH] + +MESSAGE="Required : $[CAPA_REQUIRED/1000000000] Go, available : $[CAPA_DISP/1000000000] Go, Volumes Error : $NB_VOLUMES_ERROR" + +if [ "$CAPA_DISP" -gt $CAPA_WARNING ]; then + echo $MESSAGE + exit 0 +elif [ "$CAPA_DISP" -gt $CAPA_CRITICAL ];then + echo $MESSAGE + exit 1 +elif [ "$CAPA_DISP_INCLUDING_SCRATCH" -gt $CAPA_CRITICAL ];then + MESSAGE="${MESSAGE}. Will use Scratch Pool !" + echo $MESSAGE + exit 1 +else + exit 2 +fi +exit 3