Browse Source

migrate to bareos, initial commit

can be buggy
Maximilian Ronniger 6 years ago
parent
commit
737b5a9c68
52 changed files with 2222 additions and 712 deletions
  1. 0 565
      bacula-dir.conf
  2. 0 44
      bacula-fd.conf
  3. 0 99
      bacula-sd.conf
  4. 8 0
      bareos-dir.d/catalog/MyCatalog.conf
  5. 6 0
      bareos-dir.d/client/bareos-fd.conf
  6. 11 0
      bareos-dir.d/client/raid.conf
  7. 7 0
      bareos-dir.d/console/bareos-mon.conf
  8. 24 0
      bareos-dir.d/director/bareos-dir.conf
  9. 11 0
      bareos-dir.d/fileset/Catalog.conf
  10. 31 0
      bareos-dir.d/fileset/LinuxAll.conf
  11. 10 0
      bareos-dir.d/fileset/SelfTest.conf
  12. 17 0
      bareos-dir.d/fileset/Windows All Drives.conf
  13. 225 0
      bareos-dir.d/fileset/share-work.conf
  14. 21 0
      bareos-dir.d/job/BackupCatalog.conf
  15. 11 0
      bareos-dir.d/job/RestoreFiles.conf
  16. 5 0
      bareos-dir.d/job/backup-bareos-fd.conf
  17. 16 0
      bareos-dir.d/jobdefs/DefaultJob.conf
  18. 9 0
      bareos-dir.d/messages/Daemon.conf
  19. 11 0
      bareos-dir.d/messages/Standard.conf
  20. 10 0
      bareos-dir.d/pool/Differential.conf
  21. 10 0
      bareos-dir.d/pool/Full.conf
  22. 10 0
      bareos-dir.d/pool/Incremental.conf
  23. 4 0
      bareos-dir.d/pool/Scratch.conf
  24. 19 0
      bareos-dir.d/profile/operator.conf
  25. 6 0
      bareos-dir.d/schedule/WeeklyCycle.conf
  26. 5 0
      bareos-dir.d/schedule/WeeklyCycleAfterBackup.conf
  27. 7 0
      bareos-dir.d/storage/File.conf
  28. 9 0
      bareos-dir.d/storage/Tape.conf.example
  29. 15 0
      bareos-fd.d/client/myself.conf
  30. 5 0
      bareos-fd.d/director/bareos-dir.conf
  31. 6 0
      bareos-fd.d/director/bareos-mon.conf
  32. 5 0
      bareos-fd.d/messages/Standard.conf
  33. 23 0
      bareos-sd.d/autochanger/autochanger-0.conf.example
  34. 11 0
      bareos-sd.d/device/FileStorage.conf
  35. 39 0
      bareos-sd.d/device/tapedrive-0.conf.example
  36. 5 0
      bareos-sd.d/director/bareos-dir.conf
  37. 6 0
      bareos-sd.d/director/bareos-mon.conf
  38. 5 0
      bareos-sd.d/messages/Standard.conf
  39. 11 0
      bareos-sd.d/storage/bareos-sd.conf
  40. 4 4
      bconsole.conf
  41. 11 0
      common_default_passwords
  42. 56 0
      mtx-changer.conf
  43. 32 0
      scripts/btraceback.gdb
  44. 7 0
      scripts/delete_catalog_backup
  45. 390 0
      scripts/disk-changer
  46. 498 0
      scripts/dvd-handler
  47. 107 0
      scripts/make_catalog_backup
  48. 159 0
      scripts/make_catalog_backup.pl
  49. 3 0
      scripts/make_catalog_backup_awk
  50. 258 0
      scripts/mtx-changer
  51. 56 0
      scripts/mtx-changer.conf
  52. 7 0
      scripts/query.sql

+ 0 - 565
bacula-dir.conf

@@ -1,565 +0,0 @@
-#
-# Default Bacula Director Configuration file
-#
-#  The only thing that MUST be changed is to add one or more
-#   file or directory names in the Include directive of the
-#   FileSet resource.
-#
-#  For Bacula release 5.2.5 (26 January 2012) -- ubuntu 12.04
-#
-#  You might also want to change the default email address
-#   from root to your address.  See the "mail" and "operator"
-#   directives in the Messages resource.
-#
-
-Director {                            # define myself
-  Name = lto-director
-  DIRport = 9101                # where we listen for UA connections
-  QueryFile = "/etc/bacula/scripts/query.sql"
-  WorkingDirectory = "/var/lib/bacula"
-  PidDirectory = "/var/run/bacula"
-  Maximum Concurrent Jobs = 1
-  Password = "vOchjaYxGgFnKdbE5me5a3Tp5vs763FyoIhXdqUF733A"         # Console password
-  Messages = Daemon
-  #DirAddress = 127.0.0.1
-  DirAddress = 10.0.21.4
-}
-
-JobDefs {
-  Name = "RAIDToTape"
-  Type = Backup
-  Level = Full
-  Client = raid-fd 
-  FileSet = "share-work"
-  Schedule = "Manual"
-  Storage = TapeDrive
-  Messages = Standard
-  Pool = Tape
-  Priority = 10
-  Write Bootstrap = "/var/lib/bacula/bootstrap/%c.bsr"
-}
-
-
-JobDefs {
-  Name = "CatalogeToTape"
-  Type = Backup
-  Level = Full
-  Client = lto-fd 
-  FileSet = "Catalog"
-  Schedule = "Manual"
-  Storage = TapeDrive
-  Messages = Standard
-  Pool = Tape
-  Priority = 10
-  Write Bootstrap = "/var/lib/bacula/bootstrap/%c.bsr"
-}
-
-JobDefs {
-  Name = "BackupToDisk"
-  Type = Backup
-  Level = Full
-  Client = lto-fd 
-  FileSet = "share-work"
-  Schedule = "Manual"
-  Storage = File
-  Messages = Standard
-  Pool = File
-  Priority = 10
-  Write Bootstrap = "/var/lib/bacula/bootstrap/%c.bsr"
-}
-
-
-#
-# Define the main nightly save backup job
-#   By default, this job will back up to disk in /nonexistant/path/to/file/archive/dir
-Job {
-  Name = "RAID Backup"
-  JobDefs = "RAIDToTape"
-  Level = Full
-  FileSet="share-work"
-  Schedule = "Manual"
-  # This creates an ASCII copy of the catalog
-  # Arguments to make_catalog_backup.pl are:
-  #  make_catalog_backup.pl <catalog-name>
-  RunBeforeJob = "/etc/bacula/scripts/make_catalog_backup.pl MyCatalog"
-  # This deletes the copy of the catalog
-  #RunAfterJob  = "/etc/bacula/scripts/delete_catalog_backup"
-  RunAfterJob  = "/usr/local/bin/eject_tape"
-  Write Bootstrap = "/var/lib/bacula/%n.bsr"
-  Priority = 1                   # run after main backup
-}
-
-#Job {
-#  Name = "BackupClient2"
-#  Client = lto2-fd
-#  JobDefs = "DefaultJob"
-#}
-
-# Backup the catalog database (after the nightly save)
-Job {
-  Name = "BackupCatalog"
-  JobDefs = "BackupToDisk"
-  Level = Full
-  FileSet="Catalog"
-  Schedule = "Manual"
-  # This creates an ASCII copy of the catalog
-  # Arguments to make_catalog_backup.pl are:
-  #  make_catalog_backup.pl <catalog-name>
-  RunBeforeJob = "/etc/bacula/scripts/make_catalog_backup.pl MyCatalog"
-  # This deletes the copy of the catalog
-  RunAfterJob  = "/etc/bacula/scripts/delete_catalog_backup"
-  Write Bootstrap = "/var/lib/bacula/%n.bsr"
-  Priority = 11                   # run after main backup
-}
-
-#
-# Standard Restore template, to be changed by Console program
-#  Only one such job is needed for all Jobs/Clients/Storage ...
-#
-Job {
-  Name = "RestoreFiles"
-  Type = Restore
-  Client=lto-fd                 
-  FileSet="share-work"                  
-  Storage = File                      
-  Pool = Tape
-  Messages = Standard
-  Where = /storage/bacula/restore
-  RunAfterJob = "/bin/chown -R proav:proav /storage/bacula/restore/"
-}
-
-
-# List of files to be backed up
-FileSet {
-  Name = "share-work"
-  Include {
-    Options {
-      signature = MD5
-      #compression=LZO
-      #compression=GZIP
-    }
-    #File = /storage/backup/
-    File = /storage/share/
-    # Backup Bacula Catalog with each run
-    File = "/var/lib/bacula/bacula.sql"
-  }
-  Exclude {
-    File = /proc
-    File = /.journal
-    File = /.fsck
-    File = /.DS_Store
-  }
-}
-
-# List of files to be backed up
-FileSet {
-  Name = "WORK"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/WORK/
-  }
-}
-
-FileSet {
-  Name = "PART01"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART01/
-  }
-}
-
-FileSet {
-  Name = "PART02"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART02/
-  }
-}
-
-FileSet {
-  Name = "PART03"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART03/
-  }
-}
-
-FileSet {
-  Name = "PART04"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART04/
-  }
-}
-
-FileSet {
-  Name = "PART05"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART05/
-  }
-}
-
-FileSet {
-  Name = "PART06"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART06/
-  }
-}
-
-FileSet {
-  Name = "PART07"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART07/
-  }
-}
-
-FileSet {
-  Name = "PART08"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART08/
-  }
-}
-
-FileSet {
-  Name = "PART09"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART09/
-  }
-}
-
-FileSet {
-  Name = "PART10"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART10/
-  }
-}
-
-FileSet {
-  Name = "PART11"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART11/
-  }
-}
-
-FileSet {
-  Name = "PART12"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART12/
-  }
-}
-
-FileSet {
-  Name = "PART13"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART13/
-  }
-}
-
-FileSet {
-  Name = "PART14"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART14/
-  }
-}
-
-FileSet {
-  Name = "PART15"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART15/
-  }
-}
-
-FileSet {
-  Name = "PART16"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART16/
-  }
-}
-
-FileSet {
-  Name = "PART17"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART17/
-  }
-}
-
-FileSet {
-  Name = "PART18"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART18/
-  }
-}
-
-FileSet {
-  Name = "PART19"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/PART19/
-  }
-}
-
-FileSet {
-  Name = "MISC"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/MISC/
-  }
-}
-
-#===DP HDD Archiv LTO5 - BEGIN===
-
-FileSet {
-  Name = "Das_Instrument_Stimme"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/WORK/20140511 Das Instrument Stimme/
-  }
-}
-
-FileSet {
-  Name = "test"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/test/
-  }
-}
-
-FileSet {
-  Name = "DP001-DP004"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/DP001-DP004/
-  }
-}
-
-FileSet {
-  Name = "DPR01"
-  Include {
-    Options { signature = MD5 }
-    File = /storage/share/DPR01/
-  }
-}
-
-#===DP HDD Archiv LTO5 - END===
-
-FileSet {
-  Name = "Catalog"
-  Include {
-    Options {
-      signature = MD5
-      compression=GZIP
-    }
-    File = "/var/lib/bacula/bacula.sql"
-  }
-}
-
-
-# LocalhostBacup FileSet.
-FileSet {
-  Name = "LocalhostFiles"
-  Include {
-    Options {
-      signature = MD5
-      compression=GZIP
-    }
-    File = /etc
-    File = /home
-  }
-}
-
-
-
-#
-# When to do the backups, full backup on first sunday of the month,
-#  differential (i.e. incremental since full) every other sunday,
-#  and incremental backups other days
-Schedule {
-  Name = "Manual"
-  #Run = Full 1st sun at 23:05
-  #Run = Differential 2nd-5th sun at 23:05
-  #Run = Incremental mon-sat at 23:05
-}
-
-# Client (File Services) to backup
-Client {
-  Name = lto-fd
-  Address = 10.0.21.4
-  FDPort = 9102
-  Catalog = MyCatalog
-  Password = "XhF4v2yOaAf_gv2J3ox0mnHG12p_ru9YY"          # password for FileDaemon
-  File Retention = 90 days            # 30 days
-  Job Retention = 12 months            # six months
-  AutoPrune = no                      # Prune expired Jobs/Files
-}
-
-#
-# Second Client (File Services) to backup
-#  You should change Name, Address, and Password before using
-#
-Client {
-  Name = raid-fd
-  Address = 10.0.21.4
-  FDPort = 9102
-  Catalog = MyCatalog
-  Password = "toYT1TeL-6TMvlva6iKlw7qZ-ckbhY0v7"         # password for FileDaemon 2
-  File Retention = 90 days            # 30 days
-  Job Retention = 12 months            # six months
-  AutoPrune = no                     # Prune expired Jobs/Files
-}
-
-
-
-
-
-
-# Definition of file storage device
-Storage {
-  Name = File
-# Do not use "localhost" here    
-  Address = 10.0.21.4                # N.B. Use a fully qualified name here
-  SDPort = 9103
-  Password = "YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg"
-  Device = FileStorage
-  Media Type = File
-}
-
-# Definition of "Tape Drive" storage device
-Storage {
-  Name = TapeDrive
-  # Do not use "localhost" here    
-  Address = 10.0.21.4               # N.B. Use a fully qualified name here
-  SDPort = 9103
-  Password = "YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg"
-  Device = TapeStorage
-  Media Type = LTO5
-}
-
-# Definition of DDS tape storage device
-#Storage {
-#  Name = DDS-4    
-#  Do not use "localhost" here
-#  Address = localhost                # N.B. Use a fully qualified name here
-#  SDPort = 9103
-#  Password = "YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg"          # password for Storage daemon
-#  Device = DDS-4                      # must be same as Device in Storage daemon
-#  Media Type = DDS-4                  # must be same as MediaType in Storage daemon
-#  Autochanger = yes                   # enable for autochanger device
-#}
-
-# Definition of 8mm tape storage device
-#Storage {
-#  Name = "8mmDrive"
-#  Do not use "localhost" here
-#  Address = localhost                # N.B. Use a fully qualified name here
-#  SDPort = 9103
-#  Password = "YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg"
-#  Device = "Exabyte 8mm"
-#  MediaType = "8mm"
-#}
-
-# Definition of DVD storage device
-#Storage {
-#  Name = "DVD"
-#  Do not use "localhost" here
-#  Address = localhost                # N.B. Use a fully qualified name here
-#  SDPort = 9103
-#  Password = "YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg"
-#  Device = "DVD Writer"
-#  MediaType = "DVD"
-#}
-
-
-# Generic catalog service
-Catalog {
-  Name = MyCatalog
-# Uncomment the following line if you want the dbi driver
-# dbdriver = "dbi:sqlite3"; dbaddress = 127.0.0.1; dbport =  
-  dbname = "bacula"; dbuser = ""; dbpassword = ""
-}
-
-# Reasonable message delivery -- send most everything to email address
-#  and to the console
-Messages {
-  Name = Standard
-#
-# NOTE! If you send to two email or more email addresses, you will need
-#  to replace the %r in the from field (-f part) with a single valid
-#  email address in both the mailcommand and the operatorcommand.
-#  What this does is, it sets the email address that emails would display
-#  in the FROM field, which is by default the same email as they're being
-#  sent to.  However, if you send email to more than one address, then
-#  you'll have to set the FROM address manually, to a single address. 
-#  for example, a 'no-reply@mydomain.com', is better since that tends to
-#  tell (most) people that its coming from an automated source.
-
-#
-  mailcommand = "/usr/lib/bacula/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula: %t %e of %c %l\" %r"
-  operatorcommand = "/usr/lib/bacula/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula: Intervention needed for %j\" %r"
-  mail = root@localhost = all, !skipped            
-  operator = root@localhost = mount
-  console = all, !skipped, !saved
-#
-# WARNING! the following will create a file that you must cycle from
-#          time to time as it will grow indefinitely. However, it will
-#          also keep all your messages if they scroll off the console.
-#
-  append = "/var/lib/bacula/log" = all, !skipped
-  catalog = all
-}
-
-
-#
-# Message delivery for daemon messages (no job).
-Messages {
-  Name = Daemon
-  mailcommand = "/usr/lib/bacula/bsmtp -h localhost -f \"\(Bacula\) \<%r\>\" -s \"Bacula daemon message\" %r"
-  mail = root@localhost = all, !skipped            
-  console = all, !skipped, !saved
-  append = "/var/lib/bacula/log" = all, !skipped
-}
-
-# File Pool definition
-Pool {
-  Name = File
-  Pool Type = Backup
-  Recycle = yes                       # Bacula can automatically recycle Volumes
-  AutoPrune = yes                     # Prune expired volumes
-  Volume Retention = 365 days         # one year
-  Maximum Volume Bytes = 50G          # Limit Volume size to something reasonable
-  Maximum Volumes = 100               # Limit number of Volumes in Pool
-}
-
-# Tape Pool definition
-Pool {
-  Name = Tape
-  Pool Type = Backup
-  Recycle = yes                       # Bacula can automatically recycle Volumes
-  AutoPrune = no                     # Prune expired volumes
-  Volume Retention = 3650 days       # one year
-  #Maximum Volume Bytes = 1500G       # Limit Volume size to something reasonable
-  Maximum Volumes = 999              # Limit number of Volumes in Pool
-  LabelFormat = "PART"
-}
-
-#
-# Restricted console used by tray-monitor to get the status of the director
-#
-Console {
-  Name = lto-mon
-  Password = "Al215m_QeLZHvCtRCc7tqUHG_HQIldY3V"
-  CommandACL = status, .status
-}

+ 0 - 44
bacula-fd.conf

@@ -1,44 +0,0 @@
-#
-# Default  Bacula File Daemon Configuration file
-#
-#  For Bacula release 5.2.5 (26 January 2012) -- ubuntu 12.04
-#
-# There is not much to change here except perhaps the
-# File daemon Name to
-#
-
-#
-# List Directors who are permitted to contact this File daemon
-#
-Director {
-  Name = lto-director
-  Password = "XhF4v2yOaAf_gv2J3ox0mnHG12p_ru9YY"
-}
-
-#
-# Restricted Director, used by tray-monitor to get the
-#   status of the file daemon
-#
-#Director {
-#  Name = lto-mon
-#  Password = "KlQZEMStI04Z66stUTkDKCcguF5t6PB-H"
-#  Monitor = yes
-#}
-
-#
-# "Global" File daemon configuration specifications
-#
-FileDaemon {                          # this is me
-  Name = lto-fd
-  FDport = 9102                  # where we listen for the director
-  WorkingDirectory = /var/lib/bacula
-  Pid Directory = /var/run/bacula
-  Maximum Concurrent Jobs = 20
-  FDAddress = 10.0.21.4
-}
-
-# Send all messages except skipped files back to Director
-Messages {
-  Name = Standard
-  director = lto-dir = all, !skipped, !restored
-}

+ 0 - 99
bacula-sd.conf

@@ -1,99 +0,0 @@
-#
-# Default Bacula Storage Daemon Configuration file
-#
-#  For Bacula release 5.2.5 (26 January 2012) -- ubuntu 12.04
-#
-# You may need to change the name of your tape drive
-#   on the "Archive Device" directive in the Device
-#   resource.  If you change the Name and/or the 
-#   "Media Type" in the Device resource, please ensure
-#   that dird.conf has corresponding changes.
-#
-
-Storage {                             # definition of myself
-  Name = lto-sd
-  SDPort = 9103                  # Director's port      
-  WorkingDirectory = "/var/lib/bacula"
-  Pid Directory = "/var/run/bacula"
-  Maximum Concurrent Jobs = 20
-  #SDAddress = 192.168.5.2
-  SDAddress = 10.0.21.4
-}
-
-#
-# List Directors who are permitted to contact Storage daemon
-#
-Director {
-  Name = lto-director
-  Password = "YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg"
-}
-
-#
-# Restricted Director, used by tray-monitor to get the
-#   status of the storage daemon
-#
-#Director {
-#  Name = lto-mon
-#  Password = "YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg"
-#  Monitor = yes
-#}
-
-#
-# Note, for a list of additional Device templates please
-#  see the directory <bacula-source>/examples/devices
-# Or follow the following link:
-#  http://bacula.svn.sourceforge.net/viewvc/bacula/trunk/bacula/examples/devices/
-#
-
-#
-# Devices supported by this Storage daemon
-# To connect, the Director's bacula-dir.conf must have the
-#  same Name and MediaType. 
-#
-
-Device {
-  Name = FileStorage
-  Media Type = File
-  Archive Device = /storage/bacula/backups/
-  LabelMedia = yes;                   # lets Bacula label unlabeled media
-  Random Access = Yes;
-  AutomaticMount = yes;               # when device opened, read it
-  RemovableMedia = no;
-  AlwaysOpen = no;
-}
-
-#
-# A Linux or Solaris LTO-4 tape drive
-#
-Device {
-  Name = TapeStorage
-  Media Type = LTO5
-  Archive Device = /dev/nst0	# no auto reqind after writing
-  #Archive Device = /dev/st0	# auto revind after finished writing
-  LabelMedia = yes;                   # lets Bacula label unlabeled media
-  AutomaticMount = yes;         # when device opened, read it
-  AlwaysOpen = yes;
-  RemovableMedia = yes;
-  RandomAccess = no;
-  Maximum File Size = 100GB
-# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
-#  Changer Command = "/bin/mt -f /dev/st0 offline"
-#  Changer Device = /dev/sg0
-# AutoChanger = yes
-  # Enable the Alert command only if you have the mtx package loaded
-# Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
-# If you have smartctl, enable this, it has more info than tapeinfo 
-  Alert Command = "sh -c 'smartctl -H -l error %c'"  
-}
-
-
-
-
-# 
-# Send all messages to the Director, 
-# mount messages also are sent to the email address
-#
-Messages {
-  Name = Standard
-  director = lto-dir = all
-}

+ 8 - 0
bareos-dir.d/catalog/MyCatalog.conf

@@ -0,0 +1,8 @@
+Catalog {
+  Name = MyCatalog
+  #dbdriver = ""
+  dbdriver = postgresql
+  dbname = bareos
+  dbuser = bareos
+  dbpassword = uUw8GMHB4rk0
+}

+ 6 - 0
bareos-dir.d/client/bareos-fd.conf

@@ -0,0 +1,6 @@
+Client {
+  Name = bareos-fd
+  Description = "Client resource of the Director itself."
+  Address = localhost
+  Password = "QS9sgKW3MOKrTUIr6S3cZqGLFOqKyYFZtktiKs+U8z/R"          # password for FileDaemon
+}

+ 11 - 0
bareos-dir.d/client/raid.conf

@@ -0,0 +1,11 @@
+Client {
+  Name = raid-fd
+
+  Address = 10.0.21.3
+  FDPort = 9102
+  Catalog = MyCatalog
+  Password = "toYT1TeL-6TMvlva6iKlw7qZ-ckbhY0v7"         # password for FileDaemon 2
+  File Retention = 90 days            # 30 days
+  Job Retention = 12 months            # six months
+  AutoPrune = no                     # Prune expired Jobs/Files
+}

+ 7 - 0
bareos-dir.d/console/bareos-mon.conf

@@ -0,0 +1,7 @@
+Console {
+  Name = bareos-mon
+  Description = "Restricted console used by tray-monitor to get the status of the director."
+  Password = "juw8ffncONJZsHop9oqvrabhEpr1wX3EQNMKdCUqhm7W"
+  CommandACL = status, .status
+  JobACL = *all*
+}

+ 24 - 0
bareos-dir.d/director/bareos-dir.conf

@@ -0,0 +1,24 @@
+Director {                            # define myself
+  Name = bareos-dir
+  QueryFile = "/usr/lib/bareos/scripts/query.sql"
+  Maximum Concurrent Jobs = 10
+  Password = "kk6j7jCl6+SlbfBNAavyUjZcQRHu+5lMCwUD9vb9lLHz"         # Console password
+  Messages = Daemon
+  Auditing = yes
+
+  # Enable the Heartbeat if you experience connection losses
+  # (eg. because of your router or firewall configuration).
+  # Additionally the Heartbeat can be enabled in bareos-sd and bareos-fd.
+  #
+  # Heartbeat Interval = 1 min
+
+  # remove comment in next line to load dynamic backends from specified directory
+  # Backend Directory = /usr/lib/bareos/backends
+
+  # remove comment from "Plugin Directory" to load plugins from specified directory.
+  # if "Plugin Names" is defined, only the specified plugins will be loaded,
+  # otherwise all director plugins (*-dir.so) from the "Plugin Directory".
+  #
+  # Plugin Directory = "/usr/lib/bareos/plugins"
+  # Plugin Names = ""
+}

+ 11 - 0
bareos-dir.d/fileset/Catalog.conf

@@ -0,0 +1,11 @@
+FileSet {
+  Name = "Catalog"
+  Description = "Backup the catalog dump and Bareos configuration files."
+  Include {
+    Options {
+      signature = MD5
+    }
+    File = "/var/lib/bareos/bareos.sql" # database dump
+    File = "/etc/bareos"                   # configuration
+  }
+}

+ 31 - 0
bareos-dir.d/fileset/LinuxAll.conf

@@ -0,0 +1,31 @@
+FileSet {
+  Name = "LinuxAll"
+  Description = "Backup all regular filesystems, determined by filesystem type."
+  Include {
+    Options {
+      Signature = MD5 # calculate md5 checksum per file
+      One FS = No     # change into other filessytems
+      FS Type = btrfs
+      FS Type = ext2  # filesystems of given types will be backed up
+      FS Type = ext3  # others will be ignored
+      FS Type = ext4
+      FS Type = reiserfs
+      FS Type = jfs
+      FS Type = xfs
+      FS Type = zfs
+    }
+    File = /
+  }
+  # Things that usually have to be excluded
+  # You have to exclude /var/lib/bareos/storage
+  # on your bareos server
+  Exclude {
+    File = /var/lib/bareos
+    File = /var/lib/bareos/storage
+    File = /proc
+    File = /tmp
+    File = /var/tmp
+    File = /.journal
+    File = /.fsck
+  }
+}

+ 10 - 0
bareos-dir.d/fileset/SelfTest.conf

@@ -0,0 +1,10 @@
+FileSet {
+  Name = "SelfTest"
+  Description = "fileset just to backup some files for selftest"
+  Include {
+    Options {
+      Signature = MD5 # calculate md5 checksum per file
+    }
+    File = "/usr/sbin"
+  }
+}

+ 17 - 0
bareos-dir.d/fileset/Windows All Drives.conf

@@ -0,0 +1,17 @@
+FileSet {
+  Name = "Windows All Drives"
+  Enable VSS = yes
+  Include {
+    Options {
+      Signature = MD5
+      Drive Type = fixed
+      IgnoreCase = yes
+      WildFile = "[A-Z]:/pagefile.sys"
+      WildDir = "[A-Z]:/RECYCLER"
+      WildDir = "[A-Z]:/$RECYCLE.BIN"
+      WildDir = "[A-Z]:/System Volume Information"
+      Exclude = yes
+    }
+    File = /
+  }
+}

+ 225 - 0
bareos-dir.d/fileset/share-work.conf

@@ -0,0 +1,225 @@
+# List of files to be backed up
+FileSet {
+  Name = "share-work"
+  Include {
+    Options {
+      signature = MD5
+      #compression=LZO
+      #compression=GZIP
+    }
+    #File = /storage/backup/
+    File = /storage/share/
+    # Backup Bacula Catalog with each run
+    File = "/var/lib/bacula/bacula.sql"
+  }
+  Exclude {
+    File = /proc
+    File = /.journal
+    File = /.fsck
+    File = /.DS_Store
+  }
+}
+
+# List of files to be backed up
+FileSet {
+  Name = "WORK"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/WORK/
+  }
+}
+
+FileSet {
+  Name = "PART01"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART01/
+  }
+}
+
+FileSet {
+  Name = "PART02"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART02/
+  }
+}
+
+FileSet {
+  Name = "PART03"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART03/
+  }
+}
+
+FileSet {
+  Name = "PART04"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART04/
+  }
+}
+
+FileSet {
+  Name = "PART05"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART05/
+  }
+}
+
+FileSet {
+  Name = "PART06"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART06/
+  }
+}
+
+FileSet {
+  Name = "PART07"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART07/
+  }
+}
+
+FileSet {
+  Name = "PART08"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART08/
+  }
+}
+
+FileSet {
+  Name = "PART09"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART09/
+  }
+}
+
+FileSet {
+  Name = "PART10"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART10/
+  }
+}
+
+FileSet {
+  Name = "PART11"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART11/
+  }
+}
+
+FileSet {
+  Name = "PART12"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART12/
+  }
+}
+
+FileSet {
+  Name = "PART13"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART13/
+  }
+}
+
+FileSet {
+  Name = "PART14"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART14/
+  }
+}
+
+FileSet {
+  Name = "PART15"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART15/
+  }
+}
+
+FileSet {
+  Name = "PART16"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART16/
+  }
+}
+
+FileSet {
+  Name = "PART17"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART17/
+  }
+}
+
+FileSet {
+  Name = "PART18"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART18/
+  }
+}
+
+FileSet {
+  Name = "PART19"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/PART19/
+  }
+}
+
+FileSet {
+  Name = "MISC"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/MISC/
+  }
+}
+
+#===DP HDD Archiv LTO5 - BEGIN===
+
+FileSet {
+  Name = "Das_Instrument_Stimme"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/WORK/20140511 Das Instrument Stimme/
+  }
+}
+
+FileSet {
+  Name = "test"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/test/
+  }
+}
+
+FileSet {
+  Name = "DP001-DP004"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/DP001-DP004/
+  }
+}
+
+FileSet {
+  Name = "DPR01"
+  Include {
+    Options { signature = MD5 }
+    File = /storage/share/DPR01/
+  }
+}
+

+ 21 - 0
bareos-dir.d/job/BackupCatalog.conf

@@ -0,0 +1,21 @@
+Job {
+  Name = "BackupCatalog"
+  Description = "Backup the catalog database (after the nightly save)"
+  JobDefs = "DefaultJob"
+  Level = Full
+  FileSet="Catalog"
+  Schedule = "WeeklyCycleAfterBackup"
+
+  # This creates an ASCII copy of the catalog
+  # Arguments to make_catalog_backup.pl are:
+  #  make_catalog_backup.pl <catalog-name>
+  RunBeforeJob = "/usr/lib/bareos/scripts/make_catalog_backup.pl MyCatalog"
+
+  # This deletes the copy of the catalog
+  RunAfterJob  = "/usr/lib/bareos/scripts/delete_catalog_backup"
+
+  # This sends the bootstrap via mail for disaster recovery.
+  # Should be sent to another system, please change recipient accordingly
+  Write Bootstrap = "|/usr/bin/bsmtp -h root@localhost -f \"\(Bareos\) \" -s \"Bootstrap for Job %j\" root@localhost" # (#01)
+  Priority = 11                   # run after main backup
+}

+ 11 - 0
bareos-dir.d/job/RestoreFiles.conf

@@ -0,0 +1,11 @@
+Job {
+  Name = "RestoreFiles"
+  Description = "Standard Restore template. Only one such job is needed for all standard Jobs/Clients/Storage ..."
+  Type = Restore
+  Client = bareos-fd
+  FileSet = "LinuxAll"
+  Storage = File
+  Pool = Incremental
+  Messages = Standard
+  Where = /tmp/bareos-restores
+}

+ 5 - 0
bareos-dir.d/job/backup-bareos-fd.conf

@@ -0,0 +1,5 @@
+Job {
+  Name = "backup-bareos-fd"
+  JobDefs = "DefaultJob"
+  Client = "bareos-fd"
+}

+ 16 - 0
bareos-dir.d/jobdefs/DefaultJob.conf

@@ -0,0 +1,16 @@
+JobDefs {
+  Name = "DefaultJob"
+  Type = Backup
+  Level = Incremental
+  Client = bareos-fd
+  FileSet = "SelfTest"                     # selftest fileset                            (#13)
+  Schedule = "WeeklyCycle"
+  Storage = File
+  Messages = Standard
+  Pool = Incremental
+  Priority = 10
+  Write Bootstrap = "/var/lib/bareos/%c.bsr"
+  Full Backup Pool = Full                  # write Full Backups into "Full" Pool         (#05)
+  Differential Backup Pool = Differential  # write Diff Backups into "Differential" Pool (#08)
+  Incremental Backup Pool = Incremental    # write Incr Backups into "Incremental" Pool  (#11)
+}

+ 9 - 0
bareos-dir.d/messages/Daemon.conf

@@ -0,0 +1,9 @@
+Messages {
+  Name = Daemon
+  Description = "Message delivery for daemon messages (no job)."
+  mailcommand = "/usr/bin/bsmtp -h root@localhost -f \"\(Bareos\) \<%r\>\" -s \"Bareos daemon message\" %r"
+  mail = root@localhost = all, !skipped, !audit # (#02)
+  console = all, !skipped, !saved, !audit
+  append = "/var/log/bareos/bareos.log" = all, !skipped, !audit
+  append = "/var/log/bareos/bareos-audit.log" = audit
+}

+ 11 - 0
bareos-dir.d/messages/Standard.conf

@@ -0,0 +1,11 @@
+Messages {
+  Name = Standard
+  Description = "Reasonable message delivery -- send most everything to email address and to the console."
+  operatorcommand = "/usr/bin/bsmtp -h root@localhost -f \"\(Bareos\) \<%r\>\" -s \"Bareos: Intervention needed for %j\" %r"
+  mailcommand = "/usr/bin/bsmtp -h root@localhost -f \"\(Bareos\) \<%r\>\" -s \"Bareos: %t %e of %c %l\" %r"
+  operator = root@localhost = mount                                 # (#03)
+  mail = root@localhost = all, !skipped, !saved, !audit             # (#02)
+  console = all, !skipped, !saved, !audit
+  append = "/var/log/bareos/bareos.log" = all, !skipped, !saved, !audit
+  catalog = all, !skipped, !saved, !audit
+}

+ 10 - 0
bareos-dir.d/pool/Differential.conf

@@ -0,0 +1,10 @@
+Pool {
+  Name = Differential
+  Pool Type = Backup
+  Recycle = yes                       # Bareos can automatically recycle Volumes
+  AutoPrune = yes                     # Prune expired volumes
+  Volume Retention = 90 days          # How long should the Differential Backups be kept? (#09)
+  Maximum Volume Bytes = 10G          # Limit Volume size to something reasonable
+  Maximum Volumes = 100               # Limit number of Volumes in Pool
+  Label Format = "Differential-"      # Volumes will be labeled "Differential-<volume-id>"
+}

+ 10 - 0
bareos-dir.d/pool/Full.conf

@@ -0,0 +1,10 @@
+Pool {
+  Name = Full
+  Pool Type = Backup
+  Recycle = yes                       # Bareos can automatically recycle Volumes
+  AutoPrune = no                      # Prune expired volumes
+  Volume Retention = 3650 days         # How long should the Full Backups be kept? (#06)
+  #Maximum Volume Bytes = 50G          # Limit Volume size to something reasonable
+  Maximum Volumes = 100               # Limit number of Volumes in Pool
+  Label Format = "Full-"              # Volumes will be labeled "Full-<volume-id>"
+}

+ 10 - 0
bareos-dir.d/pool/Incremental.conf

@@ -0,0 +1,10 @@
+Pool {
+  Name = Incremental
+  Pool Type = Backup
+  Recycle = yes                       # Bareos can automatically recycle Volumes
+  AutoPrune = yes                     # Prune expired volumes
+  Volume Retention = 30 days          # How long should the Incremental Backups be kept?  (#12)
+  Maximum Volume Bytes = 1G           # Limit Volume size to something reasonable
+  Maximum Volumes = 100               # Limit number of Volumes in Pool
+  Label Format = "Incremental-"       # Volumes will be labeled "Incremental-<volume-id>"
+}

+ 4 - 0
bareos-dir.d/pool/Scratch.conf

@@ -0,0 +1,4 @@
+Pool {
+  Name = Scratch
+  Pool Type = Scratch
+}

+ 19 - 0
bareos-dir.d/profile/operator.conf

@@ -0,0 +1,19 @@
+Profile {
+   Name = operator
+   Description = "Profile allowing normal Bareos operations."
+
+   Command ACL = !.bvfs_clear_cache, !.exit, !.sql
+   Command ACL = !configure, !create, !delete, !purge, !prune, !sqlquery, !umount, !unmount
+   Command ACL = *all*
+
+   Catalog ACL = *all*
+   Client ACL = *all*
+   FileSet ACL = *all*
+   Job ACL = *all*
+   Plugin Options ACL = *all*
+   Pool ACL = *all*
+   Schedule ACL = *all*
+   Storage ACL = *all*
+   Where ACL = *all*
+}
+

+ 6 - 0
bareos-dir.d/schedule/WeeklyCycle.conf

@@ -0,0 +1,6 @@
+Schedule {
+  Name = "WeeklyCycle"
+  Run = Full 1st sat at 21:00                   # (#04)
+  Run = Differential 2nd-5th sat at 21:00       # (#07)
+  Run = Incremental mon-fri at 21:00            # (#10)
+}

+ 5 - 0
bareos-dir.d/schedule/WeeklyCycleAfterBackup.conf

@@ -0,0 +1,5 @@
+Schedule {
+  Name = "WeeklyCycleAfterBackup"
+  Description = "This schedule does the catalog. It starts after the WeeklyCycle."
+  Run = Full mon-fri at 21:10
+}

+ 7 - 0
bareos-dir.d/storage/File.conf

@@ -0,0 +1,7 @@
+Storage {
+  Name = File
+  Address = lto5                # N.B. Use a fully qualified name here (do not use "localhost" here).
+  Password = "fxljHYaOJY0vGFp5Ysml9WStvrUEFl2Q4oYCaHD0aaBj"
+  Device = FileStorage
+  Media Type = File
+}

+ 9 - 0
bareos-dir.d/storage/Tape.conf.example

@@ -0,0 +1,9 @@
+Storage {
+  Name = Tape
+  Address  = "Replace this by the Bareos Storage Daemon FQDN or IP address"
+  Password = "Replace this by the Bareos Storage Daemon director password"
+  Device = autochanger-0
+  Media Type = LTO
+  Auto Changer = yes
+}
+

+ 15 - 0
bareos-fd.d/client/myself.conf

@@ -0,0 +1,15 @@
+Client {
+  Name = lto5-fd
+  Maximum Concurrent Jobs = 20
+
+  # remove comment from "Plugin Directory" to load plugins from specified directory.
+  # if "Plugin Names" is defined, only the specified plugins will be loaded,
+  # otherwise all filedaemon plugins (*-fd.so) from the "Plugin Directory".
+  #
+  # Plugin Directory = "/usr/lib/bareos/plugins"
+  # Plugin Names = ""
+
+  # if compatible is set to yes, we are compatible with bacula
+  # if set to no, new bareos features are enabled which is the default
+  # compatible = yes
+}

+ 5 - 0
bareos-fd.d/director/bareos-dir.conf

@@ -0,0 +1,5 @@
+Director {
+  Name = bareos-dir
+  Password = "QS9sgKW3MOKrTUIr6S3cZqGLFOqKyYFZtktiKs+U8z/R"
+  Description = "Allow the configured Director to access this file daemon."
+}

+ 6 - 0
bareos-fd.d/director/bareos-mon.conf

@@ -0,0 +1,6 @@
+Director {
+  Name = bareos-mon
+  Password = "94zJs+QjEjbwx2aErYsDMFswNeLTWAj/uQPYua221I06"
+  Monitor = yes
+  Description = "Restricted Director, used by tray-monitor to get the status of this file daemon."
+}

+ 5 - 0
bareos-fd.d/messages/Standard.conf

@@ -0,0 +1,5 @@
+Messages {
+  Name = Standard
+  Director = bareos-dir = all, !skipped, !restored
+  Description = "Send relevant messages to the Director."
+}

+ 23 - 0
bareos-sd.d/autochanger/autochanger-0.conf.example

@@ -0,0 +1,23 @@
+#
+# Preparations:
+#
+# on Linux use "lsscsi --generic"
+# to get a list of your SCSI devices.
+# However, normaly you should access your devices by-id
+# (eg. /dev/tape/by-id/scsi-SSTK_L700_XYZZY_A) or by-path,
+# because the short device names like /dev/sg7
+# might change on reboot.
+#
+
+Autochanger {
+  Name = "autochanger-0"
+  # adapt this, to match your storage loader
+  Changer Device = /dev/tape/by-id/scsi-1TANDBERGStorageLoader_AA45JC001732
+
+  # an Autochanger can contain multiple drive devices
+  Device = tapedrive-0
+  #Device = tapedrive-1
+
+  Changer Command = "/usr/lib/bareos/scripts/mtx-changer %c %o %S %a %d"
+}
+

+ 11 - 0
bareos-sd.d/device/FileStorage.conf

@@ -0,0 +1,11 @@
+Device {
+  Name = FileStorage
+  Media Type = File
+  Archive Device = /var/lib/bareos/storage
+  LabelMedia = yes;                   # lets Bareos label unlabeled media
+  Random Access = yes;
+  AutomaticMount = yes;               # when device opened, read it
+  RemovableMedia = no;
+  AlwaysOpen = no;
+  Description = "File device. A connecting Director must have the same Name and MediaType."
+}

+ 39 - 0
bareos-sd.d/device/tapedrive-0.conf.example

@@ -0,0 +1,39 @@
+#
+# Preparations:
+#
+# on Linux use "lsscsi --generic"
+# to get a list of your SCSI devices.
+# However, normaly you should access your devices by-id
+# (eg. /dev/tape/by-id/scsi-350011d00018a5f03-nst)
+# or by-path
+# (eg. /dev/tape/by-path/pci-0000:0d:08.0-sas-phy4-0x500110a0015ec9e0-lun-0-nst),
+# because the short device names like /dev/nst1
+# might change on reboot.
+#
+
+Device {
+
+    Name = "tapedrive-0"
+    DeviceType = tape
+
+    # default:0, only required if the autoloader have multiple drives.
+    DriveIndex = 0
+
+    # if only one drive is available, this is normally /dev/nst0.
+    # However, it is advised to access it via id (/dev/tape/by-id/...).
+    ArchiveDevice = /dev/nst0
+    #ArchiveDevice = /dev/tape/by-id/scsi-350011d00018a5f03-nst
+
+    # arbitrary string that descripes the the storage media.
+    # Bareos uses this to determine, which device can be handle what media.
+    MediaType = LTO
+
+    # enable "Check Labels" if tapes with ANSI/IBM labels
+    # should be preserved
+    #Check Labels = yes
+
+    AutoChanger = yes                       # default: no
+    AutomaticMount = yes                    # default: no
+    MaximumFileSize = 10GB                  # default: 1000000000 (1GB)
+}
+

+ 5 - 0
bareos-sd.d/director/bareos-dir.conf

@@ -0,0 +1,5 @@
+Director {
+  Name = bareos-dir
+  Password = "fxljHYaOJY0vGFp5Ysml9WStvrUEFl2Q4oYCaHD0aaBj"
+  Description = "Director, who is permitted to contact this storage daemon."
+}

+ 6 - 0
bareos-sd.d/director/bareos-mon.conf

@@ -0,0 +1,6 @@
+Director {
+  Name = bareos-mon
+  Password = "krsU3EZ1Un7VNc+xuyr/TS/1Gd5AL6UZB1dqkVFndo8W"
+  Monitor = yes
+  Description = "Restricted Director, used by tray-monitor to get the status of this storage daemon."
+}

+ 5 - 0
bareos-sd.d/messages/Standard.conf

@@ -0,0 +1,5 @@
+Messages {
+  Name = Standard
+  Director = bareos-dir = all
+  Description = "Send all messages to the Director."
+}

+ 11 - 0
bareos-sd.d/storage/bareos-sd.conf

@@ -0,0 +1,11 @@
+Storage {
+  Name = bareos-sd
+  Maximum Concurrent Jobs = 20
+
+  # remove comment from "Plugin Directory" to load plugins from specified directory.
+  # if "Plugin Names" is defined, only the specified plugins will be loaded,
+  # otherwise all storage plugins (*-sd.so) from the "Plugin Directory".
+  #
+  # Plugin Directory = "/usr/lib/bareos/plugins"
+  # Plugin Names = ""
+}

+ 4 - 4
bconsole.conf

@@ -1,10 +1,10 @@
 #
-# Bacula User Agent (or Console) Configuration File
+# Bareos User Agent (or Console) Configuration File
 #
 
 Director {
-  Name = localhost-dir
-  DIRport = 9101
+  Name = bareos-dir
   address = localhost
-  Password = "vOchjaYxGgFnKdbE5me5a3Tp5vs763FyoIhXdqUF733A"
+  Password = "kk6j7jCl6+SlbfBNAavyUjZcQRHu+5lMCwUD9vb9lLHz"
+  Description = "Bareos Console credentials for local Director"
 }

+ 11 - 0
common_default_passwords

@@ -0,0 +1,11 @@
+# 
+# This file holds defaults for new Bacula packages installed on this system.
+# It is used only when you install a new Bacula package, and can be
+# safely removed at any time.
+
+DIRPASSWD=sBrchFhIyxXuZzJcbIqYerCc8b4pA5Yz5
+DIRMPASSWD=Al215m_QeLZHvCtRCc7tqUHG_HQIldY3V
+SDPASSWD=YJZtoICDQycm3inl-RmiNpFEaT-M_yCpg
+SDMPASSWD=utGV4QjJnn8nKU_f8LuK8EQpcCzzYDOFO
+FDPASSWD=XhF4v2yOaAf_gv2J3ox0mnHG12p_ru9YY
+FDMPASSWD=KlQZEMStI04Z66stUTkDKCcguF5t6PB-H

+ 56 - 0
mtx-changer.conf

@@ -0,0 +1,56 @@
+#
+# This file is sourced by the mtx-changer script every time it runs.
+#   You can put your site customization here, and when you do an
+#   upgrade, the process should not modify this file.  Thus you
+#   preserve your mtx-changer configuration.
+#
+
+# Set to 1 if you want to do offline before unload
+offline=0
+
+# Set to amount of time in seconds to wait after an offline
+offline_sleep=0
+
+# Set to amount of time in seconds to wait after a load
+load_sleep=0
+
+# Set to 1 to do an inventory before a status. Not normally needed.
+inventory=0
+
+# If you have a VXA PacketLoader, it might display a different
+#  Storage Element line, so try setting the following to 1
+vxa_packetloader=0
+
+# Set to 1 if you want debug info written to a log
+debug_log=0
+
+
+# mt status output
+# SunOS     No Additional Sense
+# FreeBSD   Current Driver State: at rest.
+# Linux     ONLINE
+#  Note Debian has a different mt than the standard Linux version.
+#    When no tape is in the drive it waits 2 minutes.
+#    When a tape is in the drive, it prints user unfriendly output.
+#  Note, with Ubuntu Gusty (8.04), there are two versions of mt,
+#    so we attempt to figure out which one.
+#
+
+OS=`uname`
+case ${OS} in
+  SunOS)
+    ready="No Additional Sense"
+    ;;
+  FreeBSD)
+    ready="Current Driver State: at rest."
+    ;;
+  Linux)
+    ready="ONLINE"
+    if test -f /etc/debian_version ; then
+       mt --version|grep "mt-st" >/dev/null 2>&1
+       if test $? -eq 1 ; then
+          ready="drive status"
+       fi
+    fi
+  ;;
+esac

+ 32 - 0
scripts/btraceback.gdb

@@ -0,0 +1,32 @@
+print my_name
+print exename
+print exepath
+print catalog_db
+print version
+print host_os
+print distname
+print distver
+print host_name
+print dist_name
+print beef
+show env TestName
+bt
+thread apply all bt
+f 0
+info locals
+f 1
+info locals
+f 2
+info locals
+f 3
+info locals
+f 4
+info locals
+f 5 
+info locals
+f 6
+info locals
+f 7
+info locals
+detach
+quit

+ 7 - 0
scripts/delete_catalog_backup

@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# This script deletes a catalog dump
+#
+db_name=XXX_DBNAME_XXX
+
+rm -f /var/lib/bacula/${db_name}.sql

+ 390 - 0
scripts/disk-changer

@@ -0,0 +1,390 @@
+#!/bin/sh
+#
+# Bacula interface to virtual autoloader using disk storage
+#
+#  Written by Kern Sibbald
+#
+#  Copyright (C) 2000-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, which is 
+#  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 Kern Sibbald.
+#  The licensor of Bacula is the Free Software Foundation Europe
+#  (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+#  Switzerland, email:ftf@fsfeurope.org.
+#
+#
+#  If you set in your Device resource
+#
+#  Changer Command = "path-to-this-script/disk-changer %c %o %S %a %d"
+#    you will have the following input to this script:
+#
+#  So Bacula will always call with all the following arguments, even though
+#    in come cases, not all are used. Note, the Volume name is not always
+#    included.
+#
+#  disk-changer "changer-device" "command" "slot" "archive-device" "drive-index" "volume"
+#                   $1              $2       $3        $4               $5         $6
+#
+# By default the autochanger has 10 Volumes and 1 Drive.
+#
+# Note: For this script to work, you *must" specify
+#    Device Type = File 
+# in each of the Devices associated with your AutoChanger resource.
+#
+# changer-device is the name of a file that overrides the default
+#   volumes and drives.  It may have:
+#        maxslot=n   where n is one based (default 10)
+#        maxdrive=m  where m is zero based (default 1 -- i.e. 2 drives)
+#  
+#   This code can also simulate barcodes. You simply put
+#   a list of the slots and barcodes in the "base" directory/barcodes.
+#   See below for the base directory definition.  Example of a 
+#   barcodes file:
+#      /var/bacula/barcodes
+#      1:Vol001
+#      2:Vol002
+#      ...
+# 
+# archive-device is the name of the base directory where you want the
+#  Volumes stored appended with /drive0 for the first drive; /drive1
+#  for the second drive, ... For example, you might use
+#  /var/bacula/drive0  Note: you must not have a trailing slash, and
+#  the string (e.g. /drive0) must be unique, and it must not match
+#  any other part of the directory name. These restrictions could be
+#  easily removed by any clever script jockey.
+#
+#  Full example: disk-changer /var/bacula/conf load 1 /var/bacula/drive0 0 TestVol001
+#
+# The Volumes will be created with names slot1, slot2, slot3, ... maxslot in the
+#  base directory. In the above example the base directory is /var/bacula.
+#  However, as with tapes, their Bacula Volume names will be stored inside the
+#  Volume label. In addition to the Volumes (e.g. /var/bacula/slot1, 
+#  /var/bacula/slot3, ...) this script will create a /var/bacula/loadedn
+#  file to keep track of what Slot is loaded. You should not change this file.
+#
+# Modified 8 June 2010 to accept Volume names from the calling program as arg 6.
+#  In this case, rather than storing the data in slotn, it is stored in the
+#  Volume name.  Note: for this to work, Volume names may not include spaces.
+#
+
+wd=/var/lib/bacula
+
+#
+# log whats done
+#
+# to turn on logging, uncomment the following line
+#touch $wd/disk-changer.log
+#
+dbgfile="$wd/disk-changer.log"
+debug() {
+    if test -f $dbgfile; then
+        echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
+    fi
+}
+
+
+#
+# Create a temporary file
+#
+make_temp_file() {
+  TMPFILE=`mktemp -t mtx.XXXXXXXXXX`
+  if test x${TMPFILE} = x; then
+     TMPFILE="$wd/disk-changer.$$"
+     if test -f ${TMPFILE}; then
+        echo "Temp file security problem on: ${TMPFILE}"
+        exit 1
+     fi
+  fi
+}
+
+# check parameter count on commandline
+#
+check_parm_count() {
+    pCount=$1
+    pCountNeed=$2
+    if test $pCount -lt $pCountNeed; then
+        echo "usage: disk-changer ctl-device command [slot archive-device drive-index]"
+        echo "  Insufficient number of arguments arguments given."
+        if test $pCount -lt 2; then
+            echo "  Mimimum usage is first two arguments ..."
+        else
+            echo "  Command expected $pCountNeed arguments"
+        fi
+        exit 1
+    fi
+}
+
+#
+# Strip off the final name in order to get the Directory ($dir)
+#  that we are dealing with.
+#
+get_dir() {
+   bn=`basename $device`
+   dir=`echo "$device" | sed -e s%/$bn%%g`
+   if [ ! -d $dir ]; then
+      echo "ERROR: Autochanger directory \"$dir\" does not exist."
+      echo "       You must create it."
+      exit 1
+   fi
+}
+
+#
+# Get the Volume name from the call line, or directly from
+#  the volslotn information.
+#
+get_vol() {
+   havevol=0
+   debug "vol=$volume"
+   if test "x$volume" != x && test "x$volume" != "x*NONE*" ; then
+      debug "touching $dir/$volume"
+      touch $dir/$volume
+      echo "$volume" >$dir/volslot${slot}
+      havevol=1
+   elif [ -f $dir/volslot${slot} ]; then
+      volume=`cat $dir/volslot${slot}`
+      havevol=1
+   fi
+}
+
+
+# Setup arguments
+ctl=$1
+cmd="$2"
+slot=$3
+device=$4
+drive=$5
+volume=$6
+
+# set defaults
+maxdrive=1
+maxslot=10
+
+# Pull in conf file
+if [ -f $ctl ]; then 
+   . $ctl
+fi
+
+
+# Check for special cases where only 2 arguments are needed, 
+#  all others are a minimum of 5
+#
+case $2 in
+    list|listall)
+        check_parm_count $# 2
+        ;;
+    slots)
+        check_parm_count $# 2
+        ;;
+    transfer)
+        check_parm_count $# 4
+        if [ $slot -gt $maxslot ]; then
+           echo "Slot ($slot) out of range (1-$maxslot)"
+           exit 1
+        fi
+        ;;
+    *)
+        check_parm_count $# 5
+        if [ $drive -gt $maxdrive ]; then
+           echo "Drive ($drive) out of range (0-$maxdrive)"
+           exit 1
+        fi
+        if [ $slot -gt $maxslot ]; then
+           echo "Slot ($slot) out of range (1-$maxslot)"
+           exit 1
+        fi
+        ;;
+esac
+
+
+debug "Parms: $ctl $cmd $slot $device $drive $volume $havevol"
+
+case $cmd in 
+   unload)
+      debug "Doing disk -f $ctl unload $slot $device $drive $volume"
+      get_dir
+      if [ -f $dir/loaded${drive} ]; then
+         ld=`cat $dir/loaded${drive}`
+      else 
+         echo "Storage Element $slot is Already Full"
+         exit 1
+      fi
+      if [ $slot -eq $ld ]; then
+         echo "0" >$dir/loaded${drive}
+         unlink $device 2>/dev/null >/dev/null
+         rm -f $device
+      else
+         echo "Storage Element $slot is Already Full"
+         exit 1
+      fi
+      ;;
+
+   load)
+      debug "Doing disk $ctl load $slot $device $drive $volume"
+      get_dir
+      i=0
+      while [ $i -le $maxdrive ]; do
+         if [ -f $dir/loaded${i} ]; then
+            ld=`cat $dir/loaded${i}`
+         else    
+            ld=0
+         fi
+         if [ $ld -eq $slot ]; then
+            echo "Drive ${i} Full (Storage element ${ld} loaded)"
+            exit 1
+         fi
+         i=`expr $i + 1`
+      done
+      # Check if we have a Volume name
+      get_vol
+      if [ $havevol -eq 0 ]; then
+         # check if slot exists
+         if [ ! -f $dir/slot${slot} ] ; then
+            echo "source Element Address $slot is Empty"
+            exit 1
+         fi
+      fi
+      if [ -f $dir/loaded${drive} ]; then
+         ld=`cat $dir/loaded${drive}`
+      else
+         ld=0
+      fi
+      if [ $ld -ne 0 ]; then
+         echo "Drive ${drive} Full (Storage element ${ld} loaded)"
+         exit 1
+      fi
+      echo "0" >$dir/loaded${drive}
+      unlink $device 2>/dev/null >/dev/null
+      rm -f $device
+      if [ $havevol -ne 0 ]; then
+         ln -s $dir/$volume $device
+         rtn=$?
+      else
+         ln -s $dir/slot${slot} $device
+         rtn=$?
+      fi
+      if [ $rtn -eq 0 ]; then
+         echo $slot >$dir/loaded${drive}
+      fi
+      exit $rtn
+      ;;
+
+   list) 
+      debug "Doing disk -f $ctl -- to list volumes"
+      get_dir 
+      if [ -f $dir/barcodes ]; then
+         cat $dir/barcodes
+      else
+         i=1
+         while [ $i -le $maxslot ]; do
+            slot=$i
+            volume=
+            get_vol
+            if [ $havevol -eq 0 ]; then
+               echo "$i:"
+            else
+               echo "$i:$volume"
+            fi
+            i=`expr $i + 1`
+         done
+      fi
+      exit 0
+      ;;
+
+   listall) 
+      # ***FIXME*** must add new Volume stuff
+      make_temp_file
+      debug "Doing disk -f $ctl -- to list volumes"
+      get_dir 
+      if [ ! -f $dir/barcodes ]; then
+          exit 0
+      fi
+
+      # we print drive content seen by autochanger
+      # and we also remove loaded media from the barcode list
+      i=0
+      while [ $i -le $maxdrive ]; do
+         if [ -f $dir/loaded${i} ]; then
+             ld=`cat $dir/loaded${i}`
+             v=`awk -F: "/^$ld:/"' { print $2 }' $dir/barcodes`
+             echo "D:$i:F:$ld:$v"
+             echo "^$ld:" >> $TMPFILE
+         fi
+         i=`expr $i + 1`
+      done
+
+      # Empty slots are not in barcodes file
+      # When we detect a gap, we print missing rows as empty
+      # At the end, we fill the gap between the last entry and maxslot
+      grep -v -f $TMPFILE $dir/barcodes | sort -n | \
+      perl -ne 'BEGIN { $cur=1 } 
+       if (/(\d+):(.+)?/) {
+         if ($cur == $1) { 
+           print "S:$1:F:$2\n" 
+         } else { 
+           while ($cur < $1) {
+              print "S:$cur:E\n";
+              $cur++;
+           }
+         }
+         $cur++;
+       } 
+       END { while ($cur < '"$maxslot"') { print "S:$cur:E\n"; $cur++; } } '
+
+      rm -f $TMPFILE
+      exit 0
+      ;;
+   transfer)
+      #  ***FIXME*** must add new Volume stuff
+      get_dir
+      make_temp_file
+      slotdest=$device
+      if [ -f $dir/slot{$slotdest} ]; then
+         echo "destination Element Address $slot is Full"
+         exit 1
+      fi
+      if [ ! -f $dir/slot${slot} ] ; then
+         echo "source Element Address $slot is Empty"
+         exit 1
+      fi
+
+      echo "Transfering $slot to $slotdest"
+      mv $dir/slot${slot} $dir/slot{$slotdest}
+
+      if [ -f $dir/barcodes ]; then
+         sed "s/^$slot:/$slotdest:/" >  $TMPFILE
+         sort -n $TMPFILE > $dir/barcodes
+      fi
+      exit 0
+      ;;
+   loaded)
+      debug "Doing disk -f $ctl $drive -- to find what is loaded"
+      get_dir
+      if [ -f $dir/loaded${drive} ]; then
+         cat $dir/loaded${drive}
+      else
+         echo "0"
+      fi
+      exit
+      ;;
+
+   slots)
+      debug "Doing disk -f $ctl -- to get count of slots"
+      echo $maxslot
+      ;;
+esac

+ 498 - 0
scripts/dvd-handler

@@ -0,0 +1,498 @@
+#!/usr/bin/python
+#
+# Check the free space available on a writable DVD
+# Should always exit with 0 status, otherwise it indicates a serious error.
+# (wrong number of arguments, Python exception...)
+#
+#  called:  dvd-handler <dvd-device-name> operation args
+#
+#  operations used by Bacula:
+#
+#   free  (no arguments)
+#	      Scan the device and report the available space. It returns:
+#	      Prints on the first output line the free space available in bytes.
+#	      If an error occurs, prints a negative number (-errno), followed,
+#	      on the second line, by an error message.
+#
+#   write  op filename
+#	       Write a part file to disk.
+#	       This operation needs two additional arguments.
+#	       The first (op) indicates to
+#		   0 -- append
+#		   1 -- first write to a blank disk
+#		   2 -- blank or truncate a disk
+#
+#		The second is the filename to write
+#
+#   operations available but not used by Bacula:
+#
+#   test      Scan the device and report the information found.
+#	       This operation needs no further arguments.
+#   prepare   Prepare a DVD+/-RW for being used by Bacula.
+#	       Note: This is only useful if you already have some
+#	       non-Bacula data on a medium, and you want to use
+#	       it with Bacula. Don't run this on blank media, it
+#	       is useless.
+#
+# 
+# $Id$
+#
+
+import popen2
+import os
+import os.path
+import errno
+import sys
+import re
+import signal
+import time
+import array
+
+class disk:
+# Configurable values:
+   
+   dvdrwmediainfo = "dvd+rw-mediainfo"
+   growcmd = "growisofs"
+   dvdrwformat = "dvd+rw-format"
+   dd = "/bin/dd"
+   margin = 10485760 # 10 mb security margin
+
+   # Comment the following line if you want the tray to be reloaded
+   # when writing ends.
+   growcmd += " -use-the-force-luke=notray"
+
+# end of configurable values
+
+###############################################################################
+#
+# This class represents DVD disk informations.
+# When instantiated, it needs a device name.
+# Status information about the device and the disk loaded is collected only when
+# asked for (for example dvd-freespace doesn't need to know the media type, and
+# dvd-writepart doesn't not always need to know the free space).
+#
+# The following methods are implemented:
+# __init__	 we need that...
+# __repr__	 this seems to be a good idea to have.
+#		 Quite minimalistic implementation, though.
+# __str__	 For casts to string. Return the current disk information
+# is_empty	 Returns TRUE if the disk is empty, blank... this needs more
+#		 work, especially concerning non-RW media and blank vs. no
+#		 filesystem considerations. Here, we should also look for
+#		 other filesystems - probably we don't want to silently
+#		 overwrite UDF or ext2 or anything not mentioned in fstab...
+#		 (NB: I don't think it is a problem)
+# free		 Returns the available free space.
+# write 	 Writes one part file to disk, either starting a new file
+#		 system on disk, or appending to it.
+#		 This method should also prepare a blank disk so that a
+#		 certain part of the disk is used to allow detection of a
+#		 used disk by all / more disk drives.
+# prepare 	 Blank the device
+#
+###############################################################################
+   def __init__(self, devicename):
+      self.device = devicename
+      self.disktype = "none"
+      self.diskmode = "none"
+      self.diskstatus = "none"
+      self.hardwaredevice = "none"
+      self.pid = 0
+      self.next_session = -1
+      self.capacity = -1
+
+      self.freespace_collected = 0
+      self.mediumtype_collected = 0
+
+      self.growcmd += " -quiet"
+
+      if self.is4gbsupported():
+	 self.growcmd += " -use-the-force-luke=4gms"
+
+      self.growparams = " -A 'Bacula Data' -input-charset=default -iso-level 3 -pad " + \
+			"-p 'dvd-handler / growisofs' -sysid 'BACULADATA' -R"
+
+      return
+
+   def __repr__(self):
+      return "disk(" + self.device + ") # This is an instance of class disk"
+
+   def __str__(self):
+      if not self.freespace_collected:
+	 self.collect_freespace();
+      if not self.mediumtype_collected:
+	 self.collect_mediumtype();
+      
+      self.me  = "Class disk, initialized with device '" + self.device + "'\n"
+      self.me += "type = '" + self.disktype + "' mode='" + self.diskmode + "' status = '" + self.diskstatus + "'\n"
+      self.me += " next_session = " + str(self.next_session) + " capacity = " + str(self.capacity) + "\n"
+      self.me += "Hardware device is '" + self.hardwaredevice + "'\n"
+      self.me += "growcmd = '" + self.growcmd + "'\ngrowparams = '" + self.growparams + "'\n"
+      return self.me
+
+   ## Check if we want to allow growisofs to cross the 4gb boundary
+   def is4gbsupported(self):
+      processi = popen2.Popen4("uname -s -r")
+      status = processi.wait()
+      if not os.WIFEXITED(status):
+	 return 1
+      if os.WEXITSTATUS(status) != 0:
+	 return 1
+      strres = processi.fromchild.readline()[0:-1]
+      version = re.search(r"Linux (\d+)\.(\d+)\.(\d+)", strres)
+      if not version: # Non-Linux: allow
+	 return 1
+      
+      if (int(version.group(1)) > 2) or (int(version.group(2)) > 6) or ((int(version.group(1)) == 2) and (int(version.group(2)) == 6) and (int(version.group(3)) >= 8)):
+	 return 1
+      else:
+	 return 0
+
+   def collect_freespace(self): # Collects current free space
+      self.cmd = self.growcmd + " -F " + self.device
+      processi = popen2.Popen4(self.cmd)
+      status = processi.wait()
+      if not os.WIFEXITED(status):
+	 raise DVDError(0, "growisofs process did not exit correctly.")
+      result = processi.fromchild.read()
+      if os.WEXITSTATUS(status) != 0:
+	 if (os.WEXITSTATUS(status) & 0x7F) == errno.ENOSPC:
+	    # Kludge to force dvd-handler to return a free space of 0
+	    self.next_session = 1
+	    self.capacity = 1
+	    self.freespace_collected = 1
+	    return
+	 else:
+	    raise DVDError(os.WEXITSTATUS(status), "growisofs returned with an error " + result + ". Please check your are using a patched version of dvd+rw-tools.")
+      next_sess = re.search(r"\snext_session=(\d+)\s", result, re.MULTILINE)
+      capa = re.search(r"\scapacity=(\d+)\s", result, re.MULTILINE)
+   
+      if next_sess and capa:
+	 self.next_session = long(next_sess.group(1))
+	 self.capacity = long(capa.group(1))
+	 
+	 # testing cheat (emulate 4GB boundary at 100MB)
+	 #if self.next_session > 100000000:
+	 #   self.capacity = self.next_session
+      else:
+	 raise DVDError(0, "Cannot get next_session and capacity from growisofs.\nReturned: " + result)
+      
+      self.freespace_collected = 1
+      return
+   
+   def collect_mediumtype(self): # Collects current medium type
+      self.lasterror = ""
+      cmd = self.dvdrwmediainfo + " " + self.device
+      processi = popen2.Popen4(cmd)
+      status = processi.wait()
+      if not os.WIFEXITED(status):
+	 raise DVDError(0, self.dvdrwmediainfo + " process did not exit correctly.")
+      if os.WEXITSTATUS(status) != 0:
+	 raise DVDError(0, "Cannot get media info from " + self.dvdrwmediainfo)
+	 return
+      result = processi.fromchild.read()
+      
+      hardware = re.search(r"INQUIRY:\s+(.*)\n", result, re.MULTILINE)
+      mediatype = re.search(r"\sMounted Media:\s+([0-9A-F]{2})h, (\S*)\s", result, re.MULTILINE)
+      mediamode = re.search(r"\sMounted Media:\s+[0-9A-F]{2}h, \S* (.*)\n", result, re.MULTILINE)
+      status = re.search(r"\sDisc status:\s+(.*)\n", result, re.MULTILINE)
+      
+      if hardware:
+	 self.hardwaredevice = hardware.group(1)
+      
+      if mediatype:
+	 self.disktype = mediatype.group(2)
+      else:
+	 raise DVDError(0, "Media type not found in " + self.dvdrwmediainfo + " output")
+      
+      if self.disktype == "DVD-RW":
+	 if mediamode:
+	    self.diskmode = mediamode.group(1)
+	 else:
+	    raise DVDError(0, "Media mode not found for DVD-RW in " + self.dvdrwmediainfo + " output")
+      
+      if status:
+	 self.diskstatus = status.group(1)
+      else:
+	 raise DVDError(0, "Disc status not found in " + self.dvdrwmediainfo + " output")
+
+      
+      self.mediumtype_collected = 1
+      return
+
+   def is_empty(self):
+      if not self.freespace_collected:
+	 self.collect_freespace();
+      
+      return 0 == self.next_session
+
+   def is_RW(self):
+      if not self.mediumtype_collected:
+	 self.collect_mediumtype();
+      return "DVD-RW" == self.disktype or "DVD+RW" == self.disktype or "DVD-RAM" == self.disktype
+
+   def is_plus_RW(self):
+      if not self.mediumtype_collected:
+	 self.collect_mediumtype();
+      return "DVD+RW" == self.disktype
+
+   def is_minus_RW(self):
+      if not self.mediumtype_collected:
+	 self.collect_mediumtype();
+      return "DVD-RW" == self.disktype
+      
+   def is_restricted_overwrite(self):
+      if not self.mediumtype_collected:
+	 self.collect_mediumtype();
+      return self.diskmode == "Restricted Overwrite"
+
+   def is_blank(self):
+      if not self.mediumtype_collected:
+	 self.collect_mediumtype();
+      
+      return self.diskstatus == "blank"
+
+   def free(self):
+      if not self.freespace_collected:
+	 self.collect_freespace();
+      
+      fr = self.capacity-self.next_session-self.margin
+      if fr < 0:
+	 return 0
+      else:
+	 return fr
+
+   def term_handler(self, signum, frame):
+      print 'dvd-handler: Signal term_handler called with signal', signum
+      if self.pid != 0:
+	 print "dvd-handler: Sending SIGTERM to pid", self.pid
+	 os.kill(self.pid, signal.SIGTERM)
+	 time.sleep(10)
+	 print "dvd-handler: Sending SIGKILL to pid", self.pid
+	 os.kill(self.pid, signal.SIGKILL)
+	 sys.exit(1)
+
+   def write(self, newvol, partfile):
+      # Blank DVD+RW when there is no data on it
+      if newvol and self.is_plus_RW() and self.is_blank():
+	 print "DVD+RW looks brand-new, blank it to fix some DVD-writers bugs."
+	 self.blank()
+	 print "Done, now writing the part file."
+      
+      if newvol and self.is_minus_RW() and (not self.is_restricted_overwrite()):
+	 print "DVD-RW is in " + self.diskmode + " mode, reformating it to Restricted Overwrite"
+	 self.reformat_minus_RW()
+	 print "Done, now writing the part file."
+      
+      cmd = self.growcmd + self.growparams
+      if newvol:
+	 # Ignore any existing iso9660 filesystem - used for truncate
+	 if newvol == 2:
+	     cmd += " -use-the-force-luke=tty"
+	 cmd += " -Z "
+      else:
+	 cmd += " -M "
+      cmd += self.device + " " + str(partfile)
+      print "Running " + cmd
+      oldsig = signal.signal(signal.SIGTERM, self.term_handler)
+      proc = popen2.Popen4(cmd)
+      self.pid = proc.pid
+      status = proc.poll()
+      while status == -1:
+	 line = proc.fromchild.readline()
+	 while len(line) > 0:
+	    print line,
+	    line = proc.fromchild.readline()
+	 time.sleep(1)
+	 status = proc.poll()
+      self.pid = 0
+      print
+      signal.signal(signal.SIGTERM, oldsig)
+      if not os.WIFEXITED(status):
+	 raise DVDError(0, cmd + " process did not exit correctly, signal/status " + str(status))
+      if os.WEXITSTATUS(status) != 0:
+	 raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
+
+   def prepare(self):
+      if not self.is_RW():
+	 raise DVDError(0, "I won't prepare a non-rewritable medium")
+      
+      # Blank DVD+RW when there is no data on it
+      if self.is_plus_RW() and self.is_blank():
+	 print "DVD+RW looks brand-new, blank it to fix some DVD-writers bugs."
+	 self.blank()
+	 return # It has been completely blanked: Medium is ready to be used by Bacula
+      
+      if self.is_minus_RW() and (not self.is_restricted_overwrite()):
+	 print "DVD-RW is in " + self.diskmode + " mode, reformating it to Restricted Overwrite"
+	 self.reformat_minus_RW()
+	 return # Reformated: Medium is ready to be used by Bacula
+      
+      # TODO: Check if /dev/fd/0 and /dev/zero exists, otherwise, run self.blank()
+      if not os.path.exists("/dev/fd/0") or not os.path.exists("/dev/zero"):
+	 print "/dev/fd/0 or /dev/zero doesn't exist, blank the medium completely."
+	 self.blank()
+	 return
+      
+      cmd = self.dd + " if=/dev/zero bs=1024 count=512 | " + self.growcmd + " -Z " + self.device + "=/dev/fd/0"
+      print "Running " + cmd
+      oldsig = signal.signal(signal.SIGTERM, self.term_handler)
+      proc = popen2.Popen4(cmd)
+      self.pid = proc.pid
+      status = proc.poll() 
+      while status == -1:
+	 line = proc.fromchild.readline()
+	 while len(line) > 0:
+	    print line,
+	    line = proc.fromchild.readline()
+	 time.sleep(1)
+	 status = proc.poll()
+      self.pid = 0
+      print
+      signal.signal(signal.SIGTERM, oldsig)
+      if os.WEXITSTATUS(status) != 0:
+	 raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
+
+   def blank(self):
+      cmd = self.growcmd + " -Z " + self.device + "=/dev/zero"
+      print "Running " + cmd
+      oldsig = signal.signal(signal.SIGTERM, self.term_handler)
+      proc = popen2.Popen4(cmd)
+      self.pid = proc.pid
+      status = proc.poll()
+      while status == -1:
+	 line = proc.fromchild.readline()
+	 while len(line) > 0:
+	    print line,
+	    line = proc.fromchild.readline()
+	 time.sleep(1)
+	 status = proc.poll()
+      self.pid = 0
+      print
+      signal.signal(signal.SIGTERM, oldsig)
+      if os.WEXITSTATUS(status) != 0:
+	 raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
+
+   def reformat_minus_RW(self):
+      cmd = self.dvdrwformat + " -force " + self.device
+      print "Running " + cmd
+      oldsig = signal.signal(signal.SIGTERM, self.term_handler)
+      proc = popen2.Popen4(cmd)
+      self.pid = proc.pid
+      status = proc.poll()
+      while status == -1:
+	 line = proc.fromchild.readline()
+	 while len(line) > 0:
+	    print line,
+	    line = proc.fromchild.readline()
+	 time.sleep(1)
+	 status = proc.poll()
+      self.pid = 0
+      print
+      signal.signal(signal.SIGTERM, oldsig)
+      if os.WEXITSTATUS(status) != 0:
+	 raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
+
+# class disk ends here.
+
+class DVDError(Exception):
+   def __init__(self, errno, value):
+      self.errno = errno
+      self.value = value
+      if self.value[-1] == '\n':
+	 self.value = self.value[0:-1]
+   def __str__(self):
+      return str(self.value) + " || errno = " + str(self.errno) + " (" + os.strerror(self.errno & 0x7F) + ")"
+
+def usage():
+   print "Wrong number of arguments."
+   print """
+Usage:
+
+dvd-handler DEVICE test
+dvd-handler DEVICE free
+dvd-handler DEVICE write APPEND FILE
+dvd-handler DEVICE prepare
+
+where DEVICE is a device name like /dev/sr0 or /dev/dvd.
+
+Operations:
+test	  Scan the device and report the information found.
+	   This operation needs no further arguments.
+free	  Scan the device and report the available space.
+write	  Write a part file to disk.
+	   This operation needs two additional arguments.
+	   The first indicates to append (0), restart the
+	   disk (1) or restart existing disk (2). The second
+	   is the file to write.
+prepare   Prepare a DVD+/-RW for being used by Bacula.
+	   Note: This is only useful if you already have some
+	   non-Bacula data on a medium, and you want to use
+	   it with Bacula. Don't run this on blank media, it
+	   is useless.
+"""
+   sys.exit(1)
+
+if len(sys.argv) < 3:
+   usage()
+
+dvd = disk(sys.argv[1])
+
+if "free" == sys.argv[2]:
+   if len(sys.argv) == 3:
+      try:
+	 free = dvd.free()
+      except DVDError, e:
+	 if e.errno != 0:
+	    print -e.errno
+	 else:
+	    print errno.EPIPE
+	 print str(e)
+      else:
+	 print free
+	 print "No Error reported."
+   else:
+      print "Wrong number of arguments for free operation. Wanted 3 got", len(sys.argv)
+      usage()
+elif "prepare" == sys.argv[2]:
+   if len(sys.argv) == 3:
+      try:
+	 dvd.prepare()
+      except DVDError, e:
+	 print "Error while preparing medium: ", str(e)
+	 if e.errno != 0:
+	    sys.exit(e.errno & 0x7F)
+	 else:
+	    sys.exit(errno.EPIPE)
+      else:
+	 print "Medium prepared successfully."
+   else:
+      print "Wrong number of arguments for prepare operation. Wanted 3 got", len(sys.argv)
+      usage()
+elif "test" == sys.argv[2]:
+   try:
+      print str(dvd)
+      print "Blank disk: " + str(dvd.is_blank()) + " ReWritable disk: " + str(dvd.is_RW())
+      print "Free space: " + str(dvd.free())
+   except DVDError, e:
+      print "Error while getting informations: ", str(e)
+elif "write" == sys.argv[2]:
+   if len(sys.argv) == 5:
+      try:
+	 dvd.write(long(sys.argv[3]), sys.argv[4])
+      except DVDError, e:
+	 print "Error while writing part file: ", str(e)
+	 if e.errno != 0:
+	    sys.exit(e.errno & 0x7F)
+	 else:
+	    sys.exit(errno.EPIPE)
+      else:
+	 print "Part file " + sys.argv[4] + " successfully written to disk."
+   else:
+      print "Wrong number of arguments for write operation. Wanted 5 got", len(sys.argv)
+      usage()
+      sys.exit(1)
+else:
+   print "No operation - use test, free, prepare or write."
+   print "THIS MIGHT BE A CASE OF DEBUGGING BACULA OR AN ERROR!"
+sys.exit(0)

+ 107 - 0
scripts/make_catalog_backup

@@ -0,0 +1,107 @@
+#!/bin/sh
+#
+# This script dumps your Bacula catalog in ASCII format
+# It works for MySQL, SQLite, and PostgreSQL
+#
+#  $1 is the name of the database to be backed up and the name
+#     of the output file (default = bacula).
+#  $2 is the user name with which to access the database
+#     (default = bacula).
+#  $3 is the password with which to access the database or "" if no password
+#     (default ""). WARNING!!! Passing the password via the command line is 
+#     insecure and should not be used since any user can display the command 
+#     line arguments and the environment using ps.  Please consult your
+#     MySQL or PostgreSQL manual for secure methods of specifying the
+#     password.
+#  $4 is the host on which the database is located
+#     (default "")
+#  $5 is the type of database
+#
+#
+
+default_db_type=sqlite3
+
+#
+# See if the fifth argument is a valid backend name.
+# If so the user overrides the default database backend.
+#
+if [ $# -ge 5 ]; then
+   case $5 in
+     sqlite3)
+       db_type=$5
+       ;;
+     mysql)
+       db_type=$5
+       ;;
+     postgresql)
+       db_type=$5
+       ;;
+     ingres)
+       db_type=$5
+       ;;
+     *)
+       ;;
+   esac
+fi
+
+#
+# If no new db_type is gives use the default db_type.
+#
+if [ -z "${db_type}" ]; then
+   db_type="${default_db_type}"
+fi
+
+cd /var/lib/bacula
+rm -f $1.sql
+
+case ${db_type} in
+  sqlite3)
+    BINDIR=/usr/bin
+    echo ".dump" | ${BINDIR}/sqlite3 $1.db >$1.sql
+    ;;
+  mysql)
+    BINDIR=
+    if test $# -gt 2; then
+      MYSQLPASSWORD=" --password=$3"
+    else
+      MYSQLPASSWORD=""
+    fi
+    if test $# -gt 3; then
+      MYSQLHOST=" --host=$4"
+    else
+      MYSQLHOST=""
+    fi
+    ${BINDIR}/mysqldump -u ${2}${MYSQLPASSWORD}${MYSQLHOST} -f --opt $1 >$1.sql
+    ;;
+  postgresql)
+    BINDIR=
+    if test $# -gt 2; then
+      PGPASSWORD=$3
+      export PGPASSWORD
+    fi
+    if test $# -gt 3; then
+      PGHOST=" --host=$4"
+    else
+      PGHOST=""
+    fi
+    # you could also add --compress for compression.  See man pg_dump
+    exec ${BINDIR}/pg_dump -c $PGHOST -U $2 $1 >$1.sql
+    ;;
+esac
+#
+#  To read back a MySQL database use: 
+#     cd /var/lib/bacula
+#     rm -f ${BINDIR}/../var/bacula/*
+#     mysql <bacula.sql
+#
+#  To read back a SQLite database use:
+#     cd /var/lib/bacula
+#     rm -f bacula.db
+#     sqlite bacula.db <bacula.sql
+#
+#  To read back a PostgreSQL database use:
+#     cd /var/lib/bacula
+#     dropdb bacula
+#     createdb bacula -T template0 -E SQL_ASCII
+#     psql bacula <bacula.sql
+#

+ 159 - 0
scripts/make_catalog_backup.pl

@@ -0,0 +1,159 @@
+#!/usr/bin/env perl
+use strict;
+
+=head1 SCRIPT
+
+  This script dumps your Bacula catalog in ASCII format
+  It works for MySQL, SQLite, and PostgreSQL
+
+=head1 USAGE
+
+    make_catalog_backup.pl MyCatalog
+
+=head1 LICENSE
+
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-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 Kern Sibbald.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
+   Switzerland, email:ftf@fsfeurope.org.
+
+=cut
+
+my $cat = shift or die "Usage: $0 catalogname";
+my $dir_conf='/usr/sbin/dbcheck -B -c /etc/bacula/bacula-dir.conf';
+my $wd = "/var/lib/bacula";
+
+sub dump_sqlite3
+{
+    my %args = @_;
+
+    exec("echo .dump | sqlite3 '$wd/$args{db_name}.db' > '$wd/$args{db_name}.sql'");
+    print "Error while executing sqlite dump $!\n";
+    return 1;
+}
+
+# TODO: use just ENV and drop the pg_service.conf file
+sub dump_pgsql
+{
+    my %args = @_;
+    umask(0077);
+
+    if ($args{db_address}) {
+        $ENV{PGHOST}=$args{db_address};
+    }
+    if ($args{db_socket}) {
+        $ENV{PGHOST}=$args{db_socket};
+    }
+    if ($args{db_port}) {
+        $ENV{PGPORT}=$args{db_port};
+    }
+
+    $ENV{PGDATABASE}=$args{db_name};
+    $ENV{PGUSER}=$args{db_user};
+    $ENV{PGPASSWORD}=$args{db_password};
+    exec("HOME='$wd' pg_dump -c > '$wd/$args{db_name}.sql'");
+    print "Error while executing postgres dump $!\n";
+    return 1;               # in case of error
+}
+
+sub dump_mysql
+{
+    my %args = @_;
+    umask(0077);
+    unlink("$wd/.my.cnf");
+    open(MY, ">$wd/.my.cnf") 
+        or die "Can't open $wd/.my.cnf for writing $@";
+
+    $args{db_address} = $args{db_address} || "localhost";
+    my $addr = "host=$args{db_address}";
+    if ($args{db_socket}) {     # unix socket is fastest than net socket
+        $addr = "socket=$args{db_socket}";
+    }
+
+    print MY "[client]
+$addr
+user=$args{db_user}
+password=$args{db_password}
+";
+    if ($args{db_port}) {
+        print MY "port=$args{db_port}\n";
+    }
+    
+    close(MY);
+
+    exec("HOME='$wd' mysqldump -f --opt $args{db_name} > '$wd/$args{db_name}.sql'");
+    print "Error while executing mysql dump $!\n";
+    return 1;
+}
+
+sub dump_catalog
+{
+    my %args = @_;
+    if ($args{db_type} eq 'SQLite3') {
+        $ENV{PATH}="/usr/bin:$ENV{PATH}";
+        dump_sqlite3(%args);
+    } elsif ($args{db_type} eq 'PostgreSQL') {
+        $ENV{PATH}=":$ENV{PATH}";
+        dump_pgsql(%args);
+    } elsif ($args{db_type} eq 'MySQL') {
+        $ENV{PATH}=":$ENV{PATH}";
+        dump_mysql(%args);
+    } else {
+        die "This database type isn't supported";
+    }
+}
+
+open(FP, "$dir_conf -C '$cat'|") or die "Can't get catalog information $@";
+# catalog=MyCatalog
+# db_type=SQLite
+# db_name=regress
+# db_driver=
+# db_user=regress
+# db_password=
+# db_address=
+# db_port=0
+# db_socket=
+my %cfg;
+
+while(my $l = <FP>)
+{
+    if ($l =~ /catalog=(.+)/) {
+        if (exists $cfg{catalog} and $cfg{catalog} eq $cat) {
+            exit dump_catalog(%cfg);
+        }
+        %cfg = ();              # reset
+    }
+
+    if ($l =~ /(\w+)=(.+)/) {
+        $cfg{$1}=$2;
+    }
+}
+
+if (exists $cfg{catalog} and $cfg{catalog} eq $cat) {
+    exit dump_catalog(%cfg);
+}
+
+print "Can't find your catalog ($cat) in director configuration\n";
+exit 1;

+ 3 - 0
scripts/make_catalog_backup_awk

@@ -0,0 +1,3 @@
+#!/usr/bin/gawk -f
+
+BEGIN {system("echo '.dump' | /usr/bin/sqlite3 /var/lib/bacula/bacula.db > /var/lib/bacula/bacula.sql")}

+ 258 - 0
scripts/mtx-changer

@@ -0,0 +1,258 @@
+#!/bin/sh
+#
+# Bacula interface to mtx autoloader
+#
+#  If you set in your Device resource
+#
+#  Changer Command = "path-to-this-script/mtx-changer %c %o %S %a %d"
+#    you will have the following input to this script:
+#
+#  So Bacula will always call with all the following arguments, even though
+#    in come cases, not all are used.
+#
+#  mtx-changer "changer-device" "command" "slot" "archive-device" "drive-index"
+#		   $1		   $2	    $3	      $4	       $5
+#
+#  for example:
+#
+#  mtx-changer /dev/sg0 load 1 /dev/nst0 0 (on a Linux system)
+# 
+#  will request to load the first cartidge into drive 0, where
+#   the SCSI control channel is /dev/sg0, and the read/write device
+#   is /dev/nst0.
+#
+#  The commands are:
+#      Command		  Function
+#      unload		  unload a given slot
+#      load		  load a given slot
+#      loaded		  which slot is loaded?
+#      list		  list Volume names (requires barcode reader)
+#      slots		  how many slots total?
+#      listall		  list all info
+#      transfer
+#
+#  Slots are numbered from 1 ...
+#  Drives are numbered from 0 ...
+#
+#
+#  If you need to an offline, refer to the drive as $4
+#    e.g.   mt -f $4 offline
+#
+#  Many changers need an offline after the unload. Also many
+#   changers need a sleep 60 after the mtx load.
+#
+#  N.B. If you change the script, take care to return either 
+#   the mtx exit code or a 0. If the script exits with a non-zero
+#   exit code, Bacula will assume the request failed.
+#
+
+# source our conf file
+if test ! -f /etc/bacula/scripts/mtx-changer.conf ; then
+  echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+  echo "ERROR: /etc/bacula/scripts/mtx-changer.conf file not found!!!!"
+  echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+  exit 1
+fi
+. /etc/bacula/scripts/mtx-changer.conf
+
+MTX=/usr/sbin/mtx
+
+if test ${debug_log} -ne 0 ; then
+  touch /var/lib/bacula/mtx.log
+fi
+dbgfile="/var/lib/bacula/mtx.log"
+debug() {
+    if test -f $dbgfile; then
+	echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
+    fi
+}
+
+
+#
+# Create a temporary file
+#
+make_temp_file() {
+  TMPFILE=`mktemp /var/lib/bacula/mtx.XXXXXXXXXX`
+  if test x${TMPFILE} = x; then
+     TMPFILE="/var/lib/bacula/mtx.$$"
+     if test -f ${TMPFILE}; then
+	echo "ERROR: Temp file security problem on: ${TMPFILE}"
+	exit 1
+     fi
+  fi
+}
+
+#
+# The purpose of this function to wait a maximum 
+#   time for the drive. It will
+#   return as soon as the drive is ready, or after
+#   waiting a maximum of 300 seconds.
+# Note, this is very system dependent, so if you are
+#   not running on Linux, you will probably need to
+#   re-write it, or at least change the grep target.
+#   We've attempted to get the appropriate OS grep targets
+#   in the code at the top of this script.
+#
+wait_for_drive() {
+  i=0 
+  while [ $i -le 300 ]; do  # Wait max 300 seconds
+    if mt -f $1 status 2>&1 | grep "${ready}" >/dev/null 2>&1; then
+      break
+    fi
+    debug "Device $1 - not ready, retrying..."
+    sleep 1
+    i=`expr $i + 1`
+  done
+}
+
+# check parameter count on commandline
+#
+check_parm_count() {
+    pCount=$1
+    pCountNeed=$2
+    if test $pCount -lt $pCountNeed; then
+	echo "ERROR: usage: mtx-changer ctl-device command [slot archive-device drive-index]"
+	echo "	Insufficient number of arguments given."
+	if test $pCount -lt 2; then
+	    echo "  Mimimum usage is first two arguments ..."
+	else
+	    echo "  Command expected $pCountNeed arguments"
+	fi
+	exit 1
+    fi
+}
+
+# Check for special cases where only 2 arguments are needed, 
+#  all others are a minimum of 5
+#
+case $2 in
+    list|listall)
+	check_parm_count $# 2
+	;;
+    slots)
+	check_parm_count $# 2
+	;;
+    transfer)
+	check_parm_count $# 4
+	;;
+    *)
+	check_parm_count $# 5
+	;;
+esac
+
+
+# Setup arguments
+ctl=$1
+cmd="$2"
+slot=$3
+device=$4
+drive=$5
+
+debug "Parms: $ctl $cmd $slot $device $drive"
+
+case $cmd in 
+   unload)
+      debug "Doing mtx -f $ctl unload $slot $drive"
+
+      if test ${offline} -eq 1 ; then
+	mt -f $device offline
+      fi
+      if test ${offline_sleep} -ne 0 ; then
+	sleep ${offline_sleep}
+      fi
+      ${MTX} -f $ctl unload $slot $drive
+      ;;
+
+   load)
+      debug "Doing mtx -f $ctl load $slot $drive"
+      ${MTX} -f $ctl load $slot $drive
+      rtn=$?
+      if test ${load_sleep} -ne 0 ; then
+	sleep ${load_sleep}
+      fi
+      wait_for_drive $device
+      exit $rtn
+      ;;
+
+   list) 
+      debug "Doing mtx -f $ctl -- to list volumes"
+      make_temp_file
+      if test ${inventory} -ne 0 ; then
+	${MTX} -f $ctl inventory
+      fi
+      ${MTX} -f $ctl status >${TMPFILE}
+      rtn=$?
+      if test ${vxa_packetloader} -ne 0 ; then
+	cat ${TMPFILE} | grep " *Storage Element [0-9]*:.*Full" | sed "s/ Storage Element //" | sed "s/Full :VolumeTag=//"
+      else
+	cat ${TMPFILE} | grep " Storage Element [0-9]*:.*Full" | awk "{print \$3 \$4}" | sed "s/Full *\(:VolumeTag=\)*//"
+      fi
+      cat ${TMPFILE} | grep "^Data Transfer Element [0-9]*:Full (Storage Element [0-9]" | awk '{printf "%s:%s\n",$7,$10}'
+      rm -f ${TMPFILE} >/dev/null 2>&1
+      exit $rtn
+      ;;
+
+   listall)
+#  Drive content:	  D:Drive num:F:Slot loaded:Volume Name
+#  D:0:F:2:vol2        or D:Drive num:E
+#  D:1:F:42:vol42   
+#  D:3:E
+# 
+#  Slot content:
+#  S:1:F:vol1		  S:Slot num:F:Volume Name
+#  S:2:E	       or S:Slot num:E
+#  S:3:F:vol4
+# 
+#  Import/Export tray slots:
+#  I:10:F:vol10 	  I:Slot num:F:Volume Name
+#  I:11:E	       or I:Slot num:E
+#  I:12:F:vol40
+ 
+      debug "Doing mtx -f $ctl -- to list all"
+      make_temp_file
+      if test ${inventory} -ne 0 ; then
+	${MTX} -f $ctl inventory
+      fi
+      ${MTX} -f $ctl status >${TMPFILE}
+      rtn=$?
+      # can be converted to awk+sed+cut, see below
+      perl -ne '
+/Data Transfer Element (\d+):Empty/ && print "D:$1:E\n";
+/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "D:$1:F:$2:$4\n";
+/Storage Element (\d+):Empty/ && print "S:$1:E\n";
+/Storage Element (\d+):Full( :VolumeTag=(.+))?/ && print "S:$1:F:$3\n";
+/Storage Element (\d+) IMPORT.EXPORT:Empty/ && print "I:$1:E\n";
+/Storage Element (\d+) IMPORT.EXPORT:Full( :VolumeTag=(.+))?/ && print "I:$1:F:$3\n";' ${TMPFILE}
+      # If perl isn't installed, you can use by those commands
+#cat ${TMPFILE} | grep "Data Transfer Element" | awk "{print \"D:\"\$4 \$7 \$9 \$10}" | sed "s/=/:/" | sed "s/Full/F:/" | sed "s/Empty/E/"
+#cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep -v "IMPORT/EXPORT" | awk "{print \"S:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/"
+#cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep "IMPORT/EXPORT" | awk "{print \"I:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" 
+
+      rm -f ${TMPFILE} >/dev/null 2>&1
+      exit $rtn
+      ;;
+
+   transfer)
+      slotdest=$device
+      debug "Doing transfer from $slot to $slotdest"
+      ${MTX} -f $ctl transfer $slot $slotdest
+      rtn=$?
+      exit $rtn
+      ;;
+
+   loaded)
+      debug "Doing mtx -f $ctl $drive -- to find what is loaded"
+      make_temp_file
+      ${MTX} -f $ctl status >${TMPFILE}
+      rtn=$?
+      cat ${TMPFILE} | grep "^Data Transfer Element $drive:Full" | awk "{print \$7}"
+      cat ${TMPFILE} | grep "^Data Transfer Element $drive:Empty" | awk "{print 0}"
+      rm -f ${TMPFILE} >/dev/null 2>&1
+      exit $rtn
+      ;;
+
+   slots)
+      debug "Doing mtx -f $ctl -- to get count of slots"
+      ${MTX} -f $ctl status | grep " *Storage Changer" | awk "{print \$5}"
+      ;;
+esac

+ 56 - 0
scripts/mtx-changer.conf

@@ -0,0 +1,56 @@
+#
+# This file is sourced by the mtx-changer script every time it runs.
+#   You can put your site customization here, and when you do an
+#   upgrade, the process should not modify this file.  Thus you
+#   preserve your mtx-changer configuration.
+#
+
+# Set to 1 if you want to do offline before unload
+offline=0
+
+# Set to amount of time in seconds to wait after an offline
+offline_sleep=0
+
+# Set to amount of time in seconds to wait after a load
+load_sleep=0
+
+# Set to 1 to do an inventory before a status. Not normally needed. 
+inventory=0
+
+# If you have a VXA PacketLoader, it might display a different 
+#  Storage Element line, so try setting the following to 1
+vxa_packetloader=0
+
+# Set to 1 if you want debug info written to a log
+debug_log=0
+
+
+# mt status output
+# SunOS     No Additional Sense
+# FreeBSD   Current Driver State: at rest.
+# Linux     ONLINE
+#  Note Debian has a different mt than the standard Linux version. 
+#    When no tape is in the drive it waits 2 minutes.  
+#    When a tape is in the drive, it prints user unfriendly output.
+#  Note, with Ubuntu Gusty (8.04), there are two versions of mt,
+#    so we attempt to figure out which one.
+#
+
+OS=`uname`
+case ${OS} in
+  SunOS)
+    ready="No Additional Sense"
+    ;;
+  FreeBSD)
+    ready="Current Driver State: at rest."
+    ;;
+  Linux)
+    ready="ONLINE"
+    if test -f /etc/debian_version ; then
+       mt --version|grep "mt-st" >/dev/null 2>&1
+       if test $? -eq 1 ; then
+          ready="drive status"
+       fi
+    fi
+  ;;
+esac

+ 7 - 0
scripts/query.sql

@@ -0,0 +1,7 @@
+#
+# See the file <bacula-source>/examples/sample-query.sql
+#  for some sample queries. 
+#
+# 1
+:The default file is empty, see <bacula-source>/examples/sample-query.sql for samples
+SELECT 'See <bacula-source>/examples/sample-query.sql for samples' AS Info;