Compare commits
No commits in common. "master" and "create-job-for-gitea" have entirely different histories.
master
...
create-job
Binary file not shown.
|
@ -0,0 +1,33 @@
|
|||
when you buy new tapes, install them in your library and run the
|
||||
|
||||
*label pool=Scratch storage=Iron-Autochanger slots=3,11,27,28 barcodes
|
||||
|
||||
command to write the initial label onto the tape (so bacula knows it's allowed to use the tape) and then bacula and scratch pool will do everything else
|
||||
libraries have slots, that command says "load the tape from slot 1 into the drive, and write a label to it matching its barcode. then repeat for slot 2. then repeat for slot 3"
|
||||
|
||||
# mt -f /dev/nst0 erase 1 to quick erase disk
|
||||
|
||||
*status dir days=15
|
||||
|
||||
<kenwoodfox> Can i change that behavior?
|
||||
<kenwoodfox> https://cdn.discordapp.com/attachments/306060488163328001/715312740876550164/unknown.png
|
||||
<kenwoodfox> What if have a job that takes up 4.5 tapes, and later on, i purge the first four tapes that are 100% full will the last tape that only has half of its volume used by the now purged job go back to being Append or will i have to pudge that tape too?
|
||||
* Topic for #bacula is "If you can't send to the channel, please register with FreeNode. || Please don't ask if you can ask... just ask || Please use pastebin.ca to paste || auth problems? http://tinyurl.com/47u2lck || SQLite no longer supported http://bit.ly/dUw2zN (login as anonymous/anonymous)"
|
||||
* Topic set by dvl!~dvl@freebsd/developer/dvl on 2016-06-08 23:22:21 UTC
|
||||
[@ChanServ] This is the support channel for Bacula, an open-source cross-platform enterprise backup solution from one of the principal authors of apcupsd. If you have questions, please just speak up - ve don't bite, and ve von't suck your blut. Honest!
|
||||
* Homepage for #bacula is http://www.bacula.org
|
||||
*** Mode #bacula +nt by orwell.freenode.net
|
||||
* Channel #bacula created on 2005-08-08 07:51:28 UTC
|
||||
- {Day changed to Thursday, May 28, 2020}
|
||||
<kenwoodfox_> Do my incremental, difs and fulls have to line up? is that the way to do it?
|
||||
<kenwoodfox_> Like doing one incremental twice a week, retaining them for four weeks, doing a diff every four weeks, retaining them for three months, and doing four full backups a year
|
||||
<kenwoodfox_> I only have so many tapes,
|
||||
<kenwoodfox_> Right now i do an incremental twice a week, a full backup four times a year and a diff backup every other month, just starting out so i dont know how much that will be eventually
|
||||
<optiz0r> <kenwoodfox> Can i change that behavior? << No. you can only force bacula to reuse a purged volume by making sure it cannot label new volumes. i.e. by disabling autolabelling or by setting a PoolMaximumPoolVolumes to an upper limit on the size of the pool
|
||||
<optiz0r> prune/purge only affects volumes in the full or used states. If a volume is half-full and still in append state, deleting the job will not cause that volume to be purged. Instead it will remain in the append state, the next job will continue writing in the second half of the tape, and only when it is filled does the expiration counter start
|
||||
<optiz0r> if you know you have half-full volumes and you're about to delete the contents of that volume, you would want to manually set the VolStatus to Full and then prune it
|
||||
<optiz0r> <kenwoodfox_> Do my incremental, difs and fulls have to line up? is that the way to do it? << I keep each successive level for longer than the interval of the parent level. e.g. if I take monthly fulls, weekly diffs, and daily incrementals, I would retain the incrementals for at least 5 weeks, and incrementals for at least 10 days
|
||||
<optiz0r> also for each level, make sure you are retaining volumes for longer than the interval. If you had monthly fulls in a 30-day pool, you would only be keeping one backup at a time. and if the most recent backup failed (e.g. network interruptionm, server crash) then you no longer have any viable backups
|
||||
|
||||
Todo for major name-change
|
||||
Purge all volumes in pools that have that name
|
Binary file not shown.
|
@ -0,0 +1,76 @@
|
|||
Storage { # definition of myself
|
||||
Name = temp-iron-sd
|
||||
SDPort = 9103 # Director's port
|
||||
WorkingDirectory = "/var/lib/bacula"
|
||||
Pid Directory = "/run/bacula"
|
||||
Plugin Directory = "/usr/lib/bacula"
|
||||
Maximum Concurrent Jobs = 20
|
||||
SDAddress = 10.85.3.39
|
||||
}
|
||||
|
||||
Director { # Director who is allowed to contact us
|
||||
Name = bacula-dir
|
||||
Password = "iamnotacrook"
|
||||
}
|
||||
|
||||
Autochanger {
|
||||
Name = "Iron-Autochanger"
|
||||
Device = LTO-3
|
||||
Changer Device = /dev/sg3
|
||||
Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
}
|
||||
|
||||
Device {
|
||||
Name = LTO-3
|
||||
Media Type = LTO-3
|
||||
Archive Device = /dev/nst0
|
||||
AutomaticMount = yes; # when device opened, read it
|
||||
AlwaysOpen = yes;
|
||||
RemovableMedia = yes;
|
||||
RandomAccess = no;
|
||||
Maximum File Size = 4GB
|
||||
#Changer Command = "/opt/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
Changer Device = /dev/sg3
|
||||
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'"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# A Linux or Solaris LTO-3 tape drive
|
||||
#
|
||||
#Device {
|
||||
# Name = LTO-3
|
||||
# Media Type = LTO-3
|
||||
# Archive Device = /dev/nst0
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# Maximum File Size = 4GB
|
||||
# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
# Changer Device = /dev/sg0
|
||||
# AutoChanger = yes
|
||||
# #
|
||||
# # New alert command in Bacula 9.0.0
|
||||
# # Note: you must have the sg3_utils (rpms) or the
|
||||
# # sg3-utils (deb) installed on your system.
|
||||
# # and you must set the correct control device that
|
||||
# # corresponds to the Archive Device
|
||||
# Control Device = /dev/sg?? # must be SCSI ctl for /dev/nst0
|
||||
# Alert Command = "/etc/bacula/scripts/tapealert %l"
|
||||
#
|
||||
# # 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'"
|
||||
#}
|
||||
|
||||
Messages {
|
||||
Name = Standard
|
||||
director = bacula-dir = all
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
#
|
||||
# Default Bacula Storage Daemon Configuration file
|
||||
#
|
||||
# For Bacula release 9.4.2 (04 February 2019) -- ubuntu 20.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.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2000-2017 Kern Sibbald
|
||||
# License: BSD 2-Clause; see file LICENSE-FOSS
|
||||
#
|
||||
|
||||
Storage { # definition of myself
|
||||
Name = temp-iron-sd
|
||||
SDPort = 9103 # Director's port
|
||||
WorkingDirectory = "/var/lib/bacula"
|
||||
Pid Directory = "/run/bacula"
|
||||
Plugin Directory = "/usr/lib/bacula"
|
||||
Maximum Concurrent Jobs = 20
|
||||
SDAddress = 127.0.0.1
|
||||
}
|
||||
|
||||
#
|
||||
# List Directors who are permitted to contact Storage daemon
|
||||
#
|
||||
Director {
|
||||
Name = temp-iron-dir
|
||||
Password = "dA5Tbqzqo4hPGJAEFvy7zD7wGdQZe6HVn"
|
||||
}
|
||||
|
||||
#
|
||||
# Restricted Director, used by tray-monitor to get the
|
||||
# status of the storage daemon
|
||||
#
|
||||
Director {
|
||||
Name = temp-iron-mon
|
||||
Password = "4MvmdJSLRuIGy90YEe2LZNKDg-M42S8I6"
|
||||
Monitor = yes
|
||||
}
|
||||
|
||||
#
|
||||
# Note, for a list of additional Device templates please
|
||||
# see the directory <bacula-source>/examples/devices
|
||||
# Or follow the following link:
|
||||
# http://www.bacula.org/git/cgit.cgi/bacula/tree/bacula/examples/devices?h=Branch-7.4
|
||||
#
|
||||
|
||||
#
|
||||
# Devices supported by this Storage daemon
|
||||
# To connect, the Director's bacula-dir.conf must have the
|
||||
# same Name and MediaType.
|
||||
#
|
||||
|
||||
#
|
||||
# Define a Virtual autochanger
|
||||
#
|
||||
Autochanger {
|
||||
Name = FileChgr1
|
||||
Device = FileChgr1-Dev1, FileChgr1-Dev2
|
||||
Changer Command = ""
|
||||
Changer Device = /dev/null
|
||||
}
|
||||
|
||||
Device {
|
||||
Name = FileChgr1-Dev1
|
||||
Media Type = File1
|
||||
Archive Device = /nonexistant/path/to/file/archive/dir
|
||||
LabelMedia = yes; # lets Bacula label unlabeled media
|
||||
Random Access = Yes;
|
||||
AutomaticMount = yes; # when device opened, read it
|
||||
RemovableMedia = no;
|
||||
AlwaysOpen = no;
|
||||
Maximum Concurrent Jobs = 5
|
||||
}
|
||||
|
||||
Device {
|
||||
Name = FileChgr1-Dev2
|
||||
Media Type = File1
|
||||
Archive Device = /nonexistant/path/to/file/archive/dir
|
||||
LabelMedia = yes; # lets Bacula label unlabeled media
|
||||
Random Access = Yes;
|
||||
AutomaticMount = yes; # when device opened, read it
|
||||
RemovableMedia = no;
|
||||
AlwaysOpen = no;
|
||||
Maximum Concurrent Jobs = 5
|
||||
}
|
||||
|
||||
#
|
||||
# Define a second Virtual autochanger
|
||||
#
|
||||
Autochanger {
|
||||
Name = FileChgr2
|
||||
Device = FileChgr2-Dev1, FileChgr2-Dev2
|
||||
Changer Command = ""
|
||||
Changer Device = /dev/null
|
||||
}
|
||||
|
||||
Device {
|
||||
Name = FileChgr2-Dev1
|
||||
Media Type = File2
|
||||
Archive Device = /nonexistant/path/to/file/archive/dir
|
||||
LabelMedia = yes; # lets Bacula label unlabeled media
|
||||
Random Access = Yes;
|
||||
AutomaticMount = yes; # when device opened, read it
|
||||
RemovableMedia = no;
|
||||
AlwaysOpen = no;
|
||||
Maximum Concurrent Jobs = 5
|
||||
}
|
||||
|
||||
Device {
|
||||
Name = FileChgr2-Dev2
|
||||
Media Type = File2
|
||||
Archive Device = /nonexistant/path/to/file/archive/dir
|
||||
LabelMedia = yes; # lets Bacula label unlabeled media
|
||||
Random Access = Yes;
|
||||
AutomaticMount = yes; # when device opened, read it
|
||||
RemovableMedia = no;
|
||||
AlwaysOpen = no;
|
||||
Maximum Concurrent Jobs = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
#
|
||||
# An autochanger device with two drives
|
||||
#
|
||||
#Autochanger {
|
||||
# Name = Autochanger
|
||||
# Device = Drive-1
|
||||
# Device = Drive-2
|
||||
# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
# Changer Device = /dev/sg0
|
||||
#}
|
||||
|
||||
#Device {
|
||||
# Name = Drive-1 #
|
||||
# Drive Index = 0
|
||||
# Media Type = DLT-8000
|
||||
# Archive Device = /dev/nst0
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# AutoChanger = yes
|
||||
# #
|
||||
# # New alert command in Bacula 9.0.0
|
||||
# # Note: you must have the sg3_utils (rpms) or the
|
||||
# # sg3-utils (deb) installed on your system.
|
||||
# # and you must set the correct control device that
|
||||
# # corresponds to the Archive Device
|
||||
# Control Device = /dev/sg?? # must be SCSI ctl for /dev/nst0
|
||||
# Alert Command = "/etc/bacula/scripts/tapealert %l"
|
||||
#
|
||||
# #
|
||||
# # Enable the Alert command only if you have the mtx package loaded
|
||||
# # Note, apparently on some systems, tapeinfo resets the SCSI controller
|
||||
# # thus if you turn this on, make sure it does not reset your SCSI
|
||||
# # controller. I have never had any problems, and smartctl does
|
||||
# # not seem to cause such problems.
|
||||
# #
|
||||
# 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'"
|
||||
#}
|
||||
|
||||
#Device {
|
||||
# Name = Drive-2 #
|
||||
# Drive Index = 1
|
||||
# Media Type = DLT-8000
|
||||
# Archive Device = /dev/nst1
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# 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'"
|
||||
#}
|
||||
|
||||
#
|
||||
# A Linux or Solaris LTO-2 tape drive
|
||||
#
|
||||
#Device {
|
||||
# Name = LTO-2
|
||||
# Media Type = LTO-2
|
||||
# Archive Device = /dev/nst0
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# Maximum File Size = 3GB
|
||||
## Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
## 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'"
|
||||
#}
|
||||
|
||||
#
|
||||
# A Linux or Solaris LTO-3 tape drive
|
||||
#
|
||||
#Device {
|
||||
# Name = LTO-3
|
||||
# Media Type = LTO-3
|
||||
# Archive Device = /dev/nst0
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# Maximum File Size = 4GB
|
||||
# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
# Changer Device = /dev/sg0
|
||||
# AutoChanger = yes
|
||||
# #
|
||||
# # New alert command in Bacula 9.0.0
|
||||
# # Note: you must have the sg3_utils (rpms) or the
|
||||
# # sg3-utils (deb) installed on your system.
|
||||
# # and you must set the correct control device that
|
||||
# # corresponds to the Archive Device
|
||||
# Control Device = /dev/sg?? # must be SCSI ctl for /dev/nst0
|
||||
# Alert Command = "/etc/bacula/scripts/tapealert %l"
|
||||
#
|
||||
# # 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'"
|
||||
#}
|
||||
|
||||
#
|
||||
# A Linux or Solaris LTO-4 tape drive
|
||||
#
|
||||
#Device {
|
||||
# Name = LTO-4
|
||||
# Media Type = LTO-4
|
||||
# Archive Device = /dev/nst0
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# Maximum File Size = 5GB
|
||||
# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
# Changer Device = /dev/sg0
|
||||
# AutoChanger = yes
|
||||
# #
|
||||
# # New alert command in Bacula 9.0.0
|
||||
# # Note: you must have the sg3_utils (rpms) or the
|
||||
# # sg3-utils (deb) installed on your system.
|
||||
# # and you must set the correct control device that
|
||||
# # corresponds to the Archive Device
|
||||
# Control Device = /dev/sg?? # must be SCSI ctl for /dev/nst0
|
||||
# Alert Command = "/etc/bacula/scripts/tapealert %l"
|
||||
#
|
||||
# # 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'"
|
||||
#}
|
||||
|
||||
#
|
||||
# An HP-UX tape drive
|
||||
#
|
||||
#Device {
|
||||
# Name = Drive-1 #
|
||||
# Drive Index = 0
|
||||
# Media Type = DLT-8000
|
||||
# Archive Device = /dev/rmt/1mnb
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# AutoChanger = no
|
||||
# Two EOF = yes
|
||||
# Hardware End of Medium = no
|
||||
# Fast Forward Space File = no
|
||||
# #
|
||||
# # New alert command in Bacula 9.0.0
|
||||
# # Note: you must have the sg3_utils (rpms) or the
|
||||
# # sg3-utils (deb) installed on your system.
|
||||
# # and you must set the correct control device that
|
||||
# # corresponds to the Archive Device
|
||||
# Control Device = /dev/sg?? # must be SCSI ctl for /dev/rmt/1mnb
|
||||
# Alert Command = "/etc/bacula/scripts/tapealert %l"
|
||||
#
|
||||
# #
|
||||
# # 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'"
|
||||
#}
|
||||
|
||||
#
|
||||
# A FreeBSD tape drive
|
||||
#
|
||||
#Device {
|
||||
# Name = DDS-4
|
||||
# Description = "DDS-4 for FreeBSD"
|
||||
# Media Type = DDS-4
|
||||
# Archive Device = /dev/nsa1
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes
|
||||
# Offline On Unmount = no
|
||||
# Hardware End of Medium = no
|
||||
# BSF at EOM = yes
|
||||
# Backward Space Record = no
|
||||
# Fast Forward Space File = no
|
||||
# TWO EOF = yes
|
||||
# #
|
||||
# # New alert command in Bacula 9.0.0
|
||||
# # Note: you must have the sg3_utils (rpms) or the
|
||||
# # sg3-utils (deb) installed on your system.
|
||||
# # and you must set the correct control device that
|
||||
# # corresponds to the Archive Device
|
||||
# Control Device = /dev/sg?? # must be SCSI ctl for /dev/nsa1
|
||||
# Alert Command = "/etc/bacula/scripts/tapealert %l"
|
||||
#
|
||||
# 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 = temp-iron-dir = all
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
# This file has been autogenerated during package installation and
|
||||
# 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=3C28A3DhJVCEoPqm8T6c5D9mmyjlZdaSf
|
||||
DIRMPASSWD=e-8O6VmwLjMITumbNEZEEiXSkiAjjf6bu
|
||||
SDPASSWD=dA5Tbqzqo4hPGJAEFvy7zD7wGdQZe6HVn
|
||||
SDMPASSWD=4MvmdJSLRuIGy90YEe2LZNKDg-M42S8I6
|
||||
FDPASSWD=aMyJeb4FOPQvCCK7CZdMB0dGm0oxWS26k
|
||||
FDMPASSWD=0-uGad5qtutFyTPlzsjmdyLDiVaR9ZuBR
|
|
@ -0,0 +1,33 @@
|
|||
print fail_time
|
||||
print my_name
|
||||
print exename
|
||||
print exepath
|
||||
print assert_msg
|
||||
print db_engine_name
|
||||
print version
|
||||
print host_os
|
||||
print distname
|
||||
print distver
|
||||
print host_name
|
||||
print dist_name
|
||||
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
|
|
@ -0,0 +1,397 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Bacula interface to virtual autoloader using disk storage
|
||||
#
|
||||
# Written by Kern Sibbald
|
||||
#
|
||||
# Bacula(R) - The Network Backup Solution
|
||||
#
|
||||
# Copyright (C) 2000-2016 Kern Sibbald
|
||||
#
|
||||
# The original author of Bacula is Kern Sibbald, with contributions
|
||||
# from many others, a complete list can be found in the file AUTHORS.
|
||||
#
|
||||
# You may use this file and others of this release according to the
|
||||
# license defined in the LICENSE file, which includes the Affero General
|
||||
# Public License, v3.0 ("AGPLv3") and some additional permissions and
|
||||
# terms pursuant to its AGPLv3 Section 7.
|
||||
#
|
||||
# This notice must be preserved when any source code is
|
||||
# conveyed and/or propagated.
|
||||
#
|
||||
# Bacula(R) is a registered trademark of Kern Sibbald.
|
||||
# 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)"
|
||||
debug "Error: 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)"
|
||||
debug "Error: Drive ($drive) out of range (0-$maxdrive)"
|
||||
exit 1
|
||||
fi
|
||||
if [ $slot -gt $maxslot ]; then
|
||||
echo "Slot ($slot) out of range (1-$maxslot)"
|
||||
debug "Error: 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"
|
||||
debug "Unload error: $dir/loaded${drive} is already unloaded"
|
||||
exit 1
|
||||
fi
|
||||
if [ $slot -eq $ld ]; then
|
||||
echo "0" >$dir/loaded${drive}
|
||||
unlink $device 2>/dev/null >/dev/null
|
||||
unlink ${device}.add 2>/dev/null >/dev/null
|
||||
rm -f ${device} ${device}.add
|
||||
else
|
||||
echo "Storage Element $slot is Already Full"
|
||||
debug "Unload error: $dir/loaded${drive} slot=$ld is already unloaded"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
load)
|
||||
debug "Doing disk $ctl load $slot $device $drive $volume"
|
||||
get_dir
|
||||
i=0
|
||||
# Check if slot already in a drive
|
||||
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)"
|
||||
debug "Load error: Cannot load Slot=${ld} in drive=$drive. Already in drive=${i}"
|
||||
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"
|
||||
debug "Load error: 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)"
|
||||
echo "Load error: Drive ${drive} Full (Storage element ${ld} loaded)"
|
||||
exit 1
|
||||
fi
|
||||
echo "0" >$dir/loaded${drive}
|
||||
unlink $device 2>/dev/null >/dev/null
|
||||
unlink ${device}.add 2>/dev/null >/dev/null
|
||||
rm -f ${device} ${device}.add
|
||||
if [ $havevol -ne 0 ]; then
|
||||
ln -s $dir/$volume $device
|
||||
ln -s $dir/${volume}.add ${device}.add
|
||||
rtn=$?
|
||||
else
|
||||
ln -s $dir/slot${slot} $device
|
||||
ln -s $dir/slot${slot}.add ${device}.add
|
||||
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}
|
||||
mv $dir/slot${slot}.add $dir/slot{$slotdest}.add
|
||||
|
||||
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
|
||||
a=`cat $dir/loaded${drive}`
|
||||
else
|
||||
a="0"
|
||||
fi
|
||||
debug "Loaded: drive=$drive is $a"
|
||||
echo $a
|
||||
exit
|
||||
;;
|
||||
|
||||
slots)
|
||||
debug "Doing disk -f $ctl -- to get count of slots"
|
||||
echo $maxslot
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,84 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2000-2018 Kern Sibbald
|
||||
# License: BSD 2-Clause; see file LICENSE-FOSS
|
||||
#
|
||||
# Bacula interface to get worm status of tape
|
||||
#
|
||||
# isworm %l (control device name)
|
||||
#
|
||||
# Typical output:
|
||||
# sdparm --page=0x1D -f /dev/sg0
|
||||
# /dev/st0: HP Ultrium 5-SCSI I5AW [tape]
|
||||
# Medium configuration (SSC) mode page:
|
||||
# WORMM 1 [cha: n, def: 1, sav: 1]
|
||||
# WMLR 1 [cha: n, def: 1, sav: 1]
|
||||
# WMFR 2 [cha: n, def: 2, sav: 2]
|
||||
#
|
||||
# Where WORMM is worm mode
|
||||
# WMLR is worm mode label restrictions
|
||||
# 0 - No blocks can be overwritten
|
||||
# 1 - Some types of format labels may not be overwritten
|
||||
# 2 - All format labels can be overwritten
|
||||
# WMFR is worm mode filemark restrictions
|
||||
# 0-1 - Reserved
|
||||
# 2 - Any number of filemarks immediately preceding EOD can be
|
||||
# overwritten except file mark closest to BOP (beginning of
|
||||
# partition).
|
||||
# 3 - Any number of filemarks immediately preceding the EOD
|
||||
# can be overwritten
|
||||
# 4-FF - Reserved
|
||||
#
|
||||
|
||||
if [ x$1 = x ] ; then
|
||||
echo "First argument missing. Must be device control name."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sdparm=`which sdparm`
|
||||
if [ x${sdparm} = x ] ; then
|
||||
echo "sdparm program not found, but is required."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#
|
||||
# This should be the correct way to determine if the tape is WORM
|
||||
# but it does not work for mhvtl. Comment out the next 5 lines
|
||||
# and the code that follows will detect correctly on mhtvl.
|
||||
#
|
||||
worm=`$sdparm --page=0x1D -f $1 |grep " *WORMM"|cut -b12-16|sed "s:^ *::"`
|
||||
if [ $? = 0 ] ; then
|
||||
echo $worm
|
||||
exit 0
|
||||
fi
|
||||
|
||||
tapeinfo=`which tapeinfo`
|
||||
if [ x${tapeinfo} = x ] ; then
|
||||
echo "tapeinfo program not found, but is required."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Unfortunately IBM and HP handle the Medium Type differently,
|
||||
# so we detect the vendor and get the appropriate Worm flag.
|
||||
#
|
||||
vendor=`$tapeinfo -f $1|grep "^Vendor ID:"|cut -b13-15`
|
||||
if [ x$vendor = xHP ] ; then
|
||||
worm=`$tapeinfo -f $1|grep "^Medium Type: 0x"|cut -b16-16`
|
||||
echo $worm
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ x$vendor = xIBM ] ; then
|
||||
worm=`$tapeinfo -f $1|grep "^Medium Type: 0x"|cut -b17-17`
|
||||
if [ x$worm = xc ]; then
|
||||
echo "1"
|
||||
exit 0
|
||||
fi
|
||||
if [ x$worm = xC ]; then
|
||||
echo "1"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
echo "0"
|
||||
exit 0
|
|
@ -0,0 +1,353 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Bacula(R) - The Network Backup Solution
|
||||
#
|
||||
# Copyright (C) 2000-2016 Kern Sibbald
|
||||
#
|
||||
# The original author of Bacula is Kern Sibbald, with contributions
|
||||
# from many others, a complete list can be found in the file AUTHORS.
|
||||
#
|
||||
# You may use this file and others of this release according to the
|
||||
# license defined in the LICENSE file, which includes the Affero General
|
||||
# Public License, v3.0 ("AGPLv3") and some additional permissions and
|
||||
# terms pursuant to its AGPLv3 Section 7.
|
||||
#
|
||||
# This notice must be preserved when any source code is
|
||||
# conveyed and/or propagated.
|
||||
#
|
||||
# Bacula(R) is a registered trademark of Kern Sibbald.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# myversion must be the same as version in mtx-changer.conf
|
||||
myversion=2
|
||||
|
||||
# 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
|
||||
|
||||
if test "${version}" != "${myversion}" ; then
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "ERROR: /etc/bacula/scripts/mtx-changer.conf has wrong version. Wanted ${myversion}, got ${version} !!!"
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
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 -a ${debug_level} -ge $1; then
|
||||
echo "`date +%m%d-%H:%M:%S.%N|cut -c1-16` ${chgr_id} $2" >> $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
|
||||
}
|
||||
|
||||
#
|
||||
# Create a temporary file for stderr
|
||||
#
|
||||
# Note, this file is used because sometime mtx emits
|
||||
# unexpected error messages followed by the output
|
||||
# expected during success.
|
||||
# So we separate STDOUT and STDERR in
|
||||
# certain of the mtx commands. The contents of STDERR
|
||||
# is then printed after the STDOUT produced by mtx
|
||||
# thus we sometimes get better changer results.
|
||||
#
|
||||
make_err_file() {
|
||||
ERRFILE=`mktemp /var/lib/bacula/mtx.err.XXXXXXXXXX`
|
||||
if test x${ERRFILE} = x; then
|
||||
ERRFILE="/var/lib/bacula/mtx.err.$$"
|
||||
if test -f ${ERRFILE}; then
|
||||
echo "ERROR: Temp file security problem on: ${ERRFILE}"
|
||||
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 $dbglvl "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 $dbglvl "Parms: $ctl $cmd $slot $device $drive"
|
||||
|
||||
case $cmd in
|
||||
unload)
|
||||
|
||||
if test ${offline} -eq 1 ; then
|
||||
mt -f $device offline
|
||||
fi
|
||||
if test ${offline_sleep} -ne 0 ; then
|
||||
sleep ${offline_sleep}
|
||||
fi
|
||||
make_err_file
|
||||
for i in 1 2 3 4 5 ; do
|
||||
debug $idbglvl "Doing mtx -f $ctl unload slot=$slot drv=$drive"
|
||||
${MTX} -f $ctl unload $slot $drive 2>${ERRFILE}
|
||||
rtn=$?
|
||||
if test $rtn -eq 0 ; then
|
||||
break
|
||||
fi
|
||||
grep "Error Code=" ${ERRFILE} 2>/dev/null 1>/dev/null
|
||||
if test $? -ne 0 ; then
|
||||
break
|
||||
fi
|
||||
sleep $i
|
||||
done
|
||||
cat ${ERRFILE}
|
||||
rm -f ${ERRFILE} >/dev/null 2>&1
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl unload slot=$slot drv=$drive"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
load)
|
||||
make_err_file
|
||||
for i in 1 2 3 4 5 ; do
|
||||
debug $idbglvl "Doing mtx -f $ctl load slot=$slot drv=$drive"
|
||||
${MTX} -f $ctl load $slot $drive 2>${ERRFILE}
|
||||
rtn=$?
|
||||
if test $rtn -eq 0 ; then
|
||||
break
|
||||
fi
|
||||
grep "Error Code=" ${ERRFILE} 2>/dev/null 1>/dev/null
|
||||
if test $? -ne 0 ; then
|
||||
break
|
||||
fi
|
||||
sleep $i
|
||||
done
|
||||
if test ${load_sleep} -ne 0 ; then
|
||||
sleep ${load_sleep}
|
||||
fi
|
||||
wait_for_drive $device
|
||||
cat ${ERRFILE}
|
||||
rm -f ${ERRFILE} >/dev/null 2>&1
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl load slot=$slot drv=$drive"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
list)
|
||||
make_temp_file
|
||||
if test ${inventory} -ne 0 ; then
|
||||
${MTX} -f $ctl inventory
|
||||
fi
|
||||
debug $dbglvl "Doing mtx -f $ctl list"
|
||||
${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
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl list"
|
||||
fi
|
||||
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
|
||||
|
||||
make_temp_file
|
||||
if test ${inventory} -ne 0 ; then
|
||||
${MTX} -f $ctl inventory
|
||||
fi
|
||||
debug $dbglvl "Doing mtx -f $ctl -- to list all"
|
||||
${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 $dbglvl "Doing transfer from $slot to $slotdest"
|
||||
${MTX} -f $ctl transfer $slot $slotdest
|
||||
rtn=$?
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl transfer from=$slot to=$slotdest"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
loaded)
|
||||
make_temp_file
|
||||
debug $idbglvl "Doing mtx -f $ctl $drive -- to find what is loaded"
|
||||
${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
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl loaded drv=$drive"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
slots)
|
||||
debug $dbglvl "Doing mtx -f $ctl -- to get count of slots"
|
||||
${MTX} -f $ctl status | grep " *Storage Changer" | awk "{print \$5}"
|
||||
rtn=$?
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl slots"
|
||||
fi
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,89 @@
|
|||
#
|
||||
# Copyright (C) 2000-2015 Kern Sibbald
|
||||
# License: BSD 2-Clause; see file LICENSE-FOSS
|
||||
#
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# We update the version when an incompatible change
|
||||
# to mtx-changer or this conf file is made, such as
|
||||
# adding a new required variable.
|
||||
version=2
|
||||
|
||||
# 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
|
||||
|
||||
#
|
||||
# Debug logging
|
||||
#
|
||||
|
||||
# If you have multiple SD's, set this differently for each one
|
||||
# so you know which message comes from which one. This can
|
||||
# be any string, and will appear in each debug message just
|
||||
# after the time stamp.
|
||||
chgr_id=0
|
||||
|
||||
# Set to 1 if you want debug info written to a log
|
||||
debug_log=0
|
||||
|
||||
# Set to debug level you want to see
|
||||
# 0 is off
|
||||
# 10 is important events (load, unload, loaded)
|
||||
# 100 is everything
|
||||
# Note debug_log must be set to 1 for anything to be generated
|
||||
#
|
||||
debug_level=10
|
||||
|
||||
# Debug levels by importance
|
||||
# Normally you do not need to change this
|
||||
dbglvl=100
|
||||
# More important messages
|
||||
idbglvl=10
|
||||
|
||||
#
|
||||
# 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
|
|
@ -0,0 +1,68 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2000-2016 Kern Sibbald
|
||||
# License: BSD 2-Clause; see file LICENSE-FOSS
|
||||
#
|
||||
# Bacula interface to tapeinfo to get tape alerts
|
||||
#
|
||||
# tapealert %l (control device name)
|
||||
#
|
||||
# Note: you must have in your SD Device resource:
|
||||
# Alert Command = /full-path/tapealert %l
|
||||
# Control Device = /dev/sg0n (where this is the scsi control
|
||||
# device for the device you are using).
|
||||
#
|
||||
|
||||
# Note: to test
|
||||
# 1. uncomment out the DEBUG=1 line below
|
||||
# 2. Possibly remove or add TapeAlert[nn]: that you want to test.
|
||||
# Note, the message following the : is not used.
|
||||
# 3. Run Bacula
|
||||
#
|
||||
#DEBUG=1
|
||||
|
||||
tapeinfo=`which tapeinfo`
|
||||
|
||||
if [ x${tapeinfo} = x ] ; then
|
||||
echo "tapeinfo program not found, but is required."
|
||||
exit 1
|
||||
fi
|
||||
if [ x$1 = x ] ; then
|
||||
echo "First argument missing. Must be device control name."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
if [ x$DEBUG = x ] ; then
|
||||
$tapeinfo -f $1 |grep "^TapeAlert" - |cut -b1-13
|
||||
exit $?
|
||||
|
||||
else
|
||||
|
||||
# For testing only
|
||||
cat <<EOF |grep "^TapeAlert" - |cut -b1-13
|
||||
Product Type: Tape Drive
|
||||
Vendor ID: 'IBM '
|
||||
Product ID: 'ULTRIUM-TD6 '
|
||||
Revision: 'G350'
|
||||
Attached Changer API: No
|
||||
SerialNumber: 'F3A2930090'
|
||||
TapeAlert[3]: Hard Error: Uncorrectable read/write error.
|
||||
TapeAlert[5]: Read Failure: Tape faulty or tape drive broken.
|
||||
TapeAlert[39]: Undefined.
|
||||
MinBlock: 1
|
||||
MaxBlock: 8388608
|
||||
SCSI ID: 9
|
||||
SCSI LUN: 0
|
||||
Ready: yes
|
||||
BufferedMode: yes
|
||||
Medium Type: 0x58
|
||||
Density Code: 0x58
|
||||
BlockSize: 0
|
||||
DataCompEnabled: yes
|
||||
DataCompCapable: yes
|
||||
DataDeCompEnabled: yes
|
||||
CompType: 0xff
|
||||
DeCompType: 0xff
|
||||
EOF
|
||||
fi
|
|
@ -0,0 +1,76 @@
|
|||
Storage { # definition of myself
|
||||
Name = bacula-iron-sd
|
||||
SDPort = 9103 # Director's port
|
||||
WorkingDirectory = "/var/db/bacula"
|
||||
Pid Directory = "/var/run"
|
||||
Plugin Directory = "/usr/local/lib"
|
||||
Maximum Concurrent Jobs = 20
|
||||
SDAddress = 10.85.3.31
|
||||
}
|
||||
|
||||
Director { # Director who is allowed to contact us
|
||||
Name = bacula-dir
|
||||
Password = "iamnotacrook"
|
||||
}
|
||||
|
||||
Autochanger {
|
||||
Name = "Iron-Autochanger"
|
||||
Device = Drive-0-LTO-3
|
||||
Changer Device = /dev/pass1
|
||||
Changer Command = "/usr/local/sbin/mtx-changer %c %o %S %a %d"
|
||||
}
|
||||
|
||||
Device {
|
||||
Name = Drive-0-LTO-3
|
||||
Media Type = LTO-3
|
||||
Archive Device = /dev/nsa0
|
||||
AutomaticMount = yes; # when device opened, read it
|
||||
AlwaysOpen = yes;
|
||||
RemovableMedia = yes;
|
||||
RandomAccess = no;
|
||||
Maximum File Size = 4GB
|
||||
#Changer Command = "/opt/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
Changer Command = "/usr/local/sbin/mtx-changer %c %o %S %a %d"
|
||||
Changer Device = /dev/pass1
|
||||
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'"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# A Linux or Solaris LTO-3 tape drive
|
||||
#
|
||||
#Device {
|
||||
# Name = LTO-3
|
||||
# Media Type = LTO-3
|
||||
# Archive Device = /dev/nst0
|
||||
# AutomaticMount = yes; # when device opened, read it
|
||||
# AlwaysOpen = yes;
|
||||
# RemovableMedia = yes;
|
||||
# RandomAccess = no;
|
||||
# Maximum File Size = 4GB
|
||||
# Changer Command = "/etc/bacula/scripts/mtx-changer %c %o %S %a %d"
|
||||
# Changer Device = /dev/sg0
|
||||
# AutoChanger = yes
|
||||
# #
|
||||
# # New alert command in Bacula 9.0.0
|
||||
# # Note: you must have the sg3_utils (rpms) or the
|
||||
# # sg3-utils (deb) installed on your system.
|
||||
# # and you must set the correct control device that
|
||||
# # corresponds to the Archive Device
|
||||
# Control Device = /dev/sg?? # must be SCSI ctl for /dev/nst0
|
||||
# Alert Command = "/etc/bacula/scripts/tapealert %l"
|
||||
#
|
||||
# # 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'"
|
||||
#}
|
||||
|
||||
Messages {
|
||||
Name = Standard
|
||||
director = bacula-dir = all
|
||||
}
|
|
@ -0,0 +1,353 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Bacula(R) - The Network Backup Solution
|
||||
#
|
||||
# Copyright (C) 2000-2016 Kern Sibbald
|
||||
#
|
||||
# The original author of Bacula is Kern Sibbald, with contributions
|
||||
# from many others, a complete list can be found in the file AUTHORS.
|
||||
#
|
||||
# You may use this file and others of this release according to the
|
||||
# license defined in the LICENSE file, which includes the Affero General
|
||||
# Public License, v3.0 ("AGPLv3") and some additional permissions and
|
||||
# terms pursuant to its AGPLv3 Section 7.
|
||||
#
|
||||
# This notice must be preserved when any source code is
|
||||
# conveyed and/or propagated.
|
||||
#
|
||||
# Bacula(R) is a registered trademark of Kern Sibbald.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# myversion must be the same as version in mtx-changer.conf
|
||||
myversion=2
|
||||
|
||||
# source our conf file
|
||||
if test ! -f /usr/local/share/bacula/mtx-changer.conf ; then
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "ERROR: /usr/local/share/bacula/mtx-changer.conf file not found!!!!"
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
exit 1
|
||||
fi
|
||||
. /usr/local/share/bacula/mtx-changer.conf
|
||||
|
||||
if test "${version}" != "${myversion}" ; then
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "ERROR: /usr/local/share/bacula/mtx-changer.conf has wrong version. Wanted ${myversion}, got ${version} !!!"
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MTX=mtx
|
||||
|
||||
if test ${debug_log} -ne 0 ; then
|
||||
touch /var/db/bacula/mtx.log
|
||||
fi
|
||||
dbgfile="/var/db/bacula/mtx.log"
|
||||
debug() {
|
||||
if test -f $dbgfile -a ${debug_level} -ge $1; then
|
||||
echo "`date +%m%d-%H:%M:%S.%N|cut -c1-16` ${chgr_id} $2" >> $dbgfile
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Create a temporary file
|
||||
#
|
||||
make_temp_file() {
|
||||
TMPFILE=`mktemp /var/db/bacula/mtx.XXXXXXXXXX`
|
||||
if test x${TMPFILE} = x; then
|
||||
TMPFILE="/var/db/bacula/mtx.$$"
|
||||
if test -f ${TMPFILE}; then
|
||||
echo "ERROR: Temp file security problem on: ${TMPFILE}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Create a temporary file for stderr
|
||||
#
|
||||
# Note, this file is used because sometime mtx emits
|
||||
# unexpected error messages followed by the output
|
||||
# expected during success.
|
||||
# So we separate STDOUT and STDERR in
|
||||
# certain of the mtx commands. The contents of STDERR
|
||||
# is then printed after the STDOUT produced by mtx
|
||||
# thus we sometimes get better changer results.
|
||||
#
|
||||
make_err_file() {
|
||||
ERRFILE=`mktemp /var/db/bacula/mtx.err.XXXXXXXXXX`
|
||||
if test x${ERRFILE} = x; then
|
||||
ERRFILE="/var/db/bacula/mtx.err.$$"
|
||||
if test -f ${ERRFILE}; then
|
||||
echo "ERROR: Temp file security problem on: ${ERRFILE}"
|
||||
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 $dbglvl "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 $dbglvl "Parms: $ctl $cmd $slot $device $drive"
|
||||
|
||||
case $cmd in
|
||||
unload)
|
||||
|
||||
if test ${offline} -eq 1 ; then
|
||||
mt -f $device offline
|
||||
fi
|
||||
if test ${offline_sleep} -ne 0 ; then
|
||||
sleep ${offline_sleep}
|
||||
fi
|
||||
make_err_file
|
||||
for i in 1 2 3 4 5 ; do
|
||||
debug $idbglvl "Doing mtx -f $ctl unload slot=$slot drv=$drive"
|
||||
${MTX} -f $ctl unload $slot $drive 2>${ERRFILE}
|
||||
rtn=$?
|
||||
if test $rtn -eq 0 ; then
|
||||
break
|
||||
fi
|
||||
grep "Error Code=" ${ERRFILE} 2>/dev/null 1>/dev/null
|
||||
if test $? -ne 0 ; then
|
||||
break
|
||||
fi
|
||||
sleep $i
|
||||
done
|
||||
cat ${ERRFILE}
|
||||
rm -f ${ERRFILE} >/dev/null 2>&1
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl unload slot=$slot drv=$drive"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
load)
|
||||
make_err_file
|
||||
for i in 1 2 3 4 5 ; do
|
||||
debug $idbglvl "Doing mtx -f $ctl load slot=$slot drv=$drive"
|
||||
${MTX} -f $ctl load $slot $drive 2>${ERRFILE}
|
||||
rtn=$?
|
||||
if test $rtn -eq 0 ; then
|
||||
break
|
||||
fi
|
||||
grep "Error Code=" ${ERRFILE} 2>/dev/null 1>/dev/null
|
||||
if test $? -ne 0 ; then
|
||||
break
|
||||
fi
|
||||
sleep $i
|
||||
done
|
||||
if test ${load_sleep} -ne 0 ; then
|
||||
sleep ${load_sleep}
|
||||
fi
|
||||
wait_for_drive $device
|
||||
cat ${ERRFILE}
|
||||
rm -f ${ERRFILE} >/dev/null 2>&1
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl load slot=$slot drv=$drive"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
list)
|
||||
make_temp_file
|
||||
if test ${inventory} -ne 0 ; then
|
||||
${MTX} -f $ctl inventory
|
||||
fi
|
||||
debug $dbglvl "Doing mtx -f $ctl list"
|
||||
${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
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl list"
|
||||
fi
|
||||
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
|
||||
|
||||
make_temp_file
|
||||
if test ${inventory} -ne 0 ; then
|
||||
${MTX} -f $ctl inventory
|
||||
fi
|
||||
debug $dbglvl "Doing mtx -f $ctl -- to list all"
|
||||
${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 $dbglvl "Doing transfer from $slot to $slotdest"
|
||||
${MTX} -f $ctl transfer $slot $slotdest
|
||||
rtn=$?
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl transfer from=$slot to=$slotdest"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
loaded)
|
||||
make_temp_file
|
||||
debug $idbglvl "Doing mtx -f $ctl $drive -- to find what is loaded"
|
||||
${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
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl loaded drv=$drive"
|
||||
fi
|
||||
exit $rtn
|
||||
;;
|
||||
|
||||
slots)
|
||||
debug $dbglvl "Doing mtx -f $ctl -- to get count of slots"
|
||||
${MTX} -f $ctl status | grep " *Storage Changer" | awk "{print \$5}"
|
||||
rtn=$?
|
||||
if test $rtn -ne 0 ; then
|
||||
debug $idbglvl "FAIL: mtx -f $ctl slots"
|
||||
fi
|
||||
;;
|
||||
esac
|
Loading…
Reference in New Issue