aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go152
1 files changed, 152 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..10a0d63
--- /dev/null
+++ b/main.go
@@ -0,0 +1,152 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "path"
+ "time"
+)
+
+const (
+ bareosWorkDir = "/var/lib/bareos"
+ bareosStateFile = "bareos-fd.9102.state"
+ baculaWorkDir = "/var/lib/bacula"
+ baculaStateFile = "bacula-fd.9102.state"
+ spoolFile = "bareos-zabbix-check.spool"
+)
+
+// We declare globally the variables that will hold the command line arguments
+var (
+ verbose bool
+ quiet bool
+ stateFile string
+ workDir string
+)
+
+func main() {
+ var (
+ info os.FileInfo
+ err error
+ successfulJobs jobs
+ errorJobs jobs
+ spoolJobs jobs
+ jobName string
+ ts uint64
+ now uint64
+ errorString string
+ missingString string
+ )
+
+ // command line arguments parsing
+ flag.BoolVar(&verbose, "v", false, "Activates verbose debugging output, defaults to false.")
+ flag.BoolVar(&quiet, "q", false, "Suppress all output, suitable to force a silent update of the spool file.")
+ flag.StringVar(&stateFile, "f", "", "Force the state file to use, defaults to "+bareosStateFile+" if it exists else "+baculaStateFile+".")
+ flag.StringVar(&workDir, "w", "", "Force the work directory to use, defaults to "+bareosWorkDir+" if it exists else "+baculaWorkDir+".")
+ flag.Parse()
+
+ // Determine the work directory to use.
+ if workDir != "" {
+ info, err = os.Stat(workDir)
+ if os.IsNotExist(err) || !info.IsDir() {
+ fmt.Printf("INFO Invalid work directory %s : it does not exist or is not a directory.\n", workDir)
+ os.Exit(0)
+ }
+ } else {
+ workDir = "/var/lib/bareos"
+ info, err = os.Stat(workDir)
+ if os.IsNotExist(err) || !info.IsDir() {
+ workDir = "/var/lib/bacula"
+ info, err := os.Stat(workDir)
+ if os.IsNotExist(err) || !info.IsDir() {
+ fmt.Println("INFO Could not find a suitable work directory. Is bareos or bacula installed?")
+ os.Exit(0)
+ }
+ }
+ }
+ workDir = path.Clean(workDir)
+ if verbose {
+ log.Println("Setting work directory to ", workDir)
+ }
+
+ // Finds the state file to parse
+ if stateFile != "" {
+ stateFile = path.Join(workDir, stateFile)
+ info, err = os.Stat(stateFile)
+ if os.IsNotExist(err) || info.IsDir() {
+ fmt.Printf("INFO The state file %s does not exist.\n", stateFile)
+ os.Exit(0)
+ }
+ } else {
+ stateFile = path.Join(workDir, bareosStateFile)
+ info, err = os.Stat(stateFile)
+ if os.IsNotExist(err) || info.IsDir() {
+ stateFile = path.Join(workDir, baculaStateFile)
+ info, err = os.Stat(stateFile)
+ if os.IsNotExist(err) || info.IsDir() {
+ fmt.Println("INFO Could not find a suitable state file. Has a job ever run?")
+ os.Exit(0)
+ }
+ }
+ }
+ if verbose {
+ log.Println("Using state file ", stateFile)
+ }
+
+ successfulJobs, errorJobs, err = parseStateFile()
+ if err != nil {
+ fmt.Print(err)
+ os.Exit(0)
+ }
+ // We will check for errors in loading the spool file only if necessary. If all jobs ran successfully without errors in the state file and we manage to write
+ // a new spool file without errors, then we will ignore any error here to avoid false positives during backup bootstrap
+ spoolJobs, err = loadSpool()
+
+ // if we have jobs in the spool we merge this list with successfull jobs from the state file
+ if err == nil {
+ for jobName, ts = range spoolJobs {
+ var (
+ current uint64
+ ok bool
+ )
+ current, ok = successfulJobs[jobName]
+ if !ok || current < ts {
+ successfulJobs[jobName] = ts
+ }
+ }
+ }
+ // we write this new spool
+ if err2 := saveSpool(successfulJobs); err2 != nil {
+ fmt.Printf("AVERAGE: Couldn't save spool : %s\n", err2)
+ os.Exit(0)
+ }
+
+ // We build the error string listing the jobs in error
+ for jobName, ts = range errorJobs {
+ if errorString == "" {
+ errorString = fmt.Sprintf("errors: %s", jobName)
+ } else {
+ errorString = fmt.Sprintf("%s, %s", errorString, jobName)
+ }
+ }
+ now = uint64(time.Now().Unix())
+ // Next we check if all jobs ran recently and build the missing string
+ for jobName, ts = range successfulJobs {
+ if ts < now-24*3600 {
+ if missingString == "" {
+ missingString = fmt.Sprintf("missing: %s", jobName)
+ } else {
+ missingString = fmt.Sprintf("%s, %s", missingString, jobName)
+ }
+ }
+ }
+ if errorString != "" || missingString != "" {
+ fmt.Printf("AVERAGE: %s %s", errorString, missingString)
+ if err != nil {
+ fmt.Printf(" additionnal errors: %s", err)
+ }
+ } else {
+ fmt.Printf("OK")
+ }
+}