Bacula and Bareos
CentOS 6.5 Install
yum install mysql-server mysql-devel
service mysqld start chkconfig mysqld on mysqladmin -u root password Y0uR3l173P455w0rd
yum install bareos-database-mysql yum install bareos
/usr/lib/bareos/scripts/create_bareos_database -u root -p /usr/lib/bareos/scripts/make_bareos_tables -u root -p /usr/lib/bareos/scripts/grant_bareos_privileges -u root -p
service bareos-dir start service bareos-sd start service bareos-fd start
Links
- http://www.unixmen.com/install-and-configure-bacula-server-in-centos-6-4-rhel-6-4/
- http://www.bareos.org/en/documentation.html
- http://doc.bareos.org/master/html/bareos-manual-main-reference.html
Archlinux GUI Admin
yaourt bareos-bat
Configure On CentOS 6.5
nano /etc/bareos/vchanger
#!/bin/sh
#
# Bacula interface to virtual autochanger using removable disk drives
#
# Based (somewhat) on the "disk-changer" script from bacula 1.39.26
#
# Vchanger is a Bacula autochanger script that emulates a conventional
# magazine-based tape library device using removable disk drives.
# Partitions on the removable drives are used as virtual magazines,
# where each "magazine" contains the same number of virtual slots. Each
# "slot" holds one virtual tape, where a "tape" is a regular file that
# Bacula treats as a "Device Type = File" volume.
#
# This script will be invoked by Bacula using the Bacula Autochanger
# Interface and will be passed the following arguments:
#
# vchanger "changer-device" "command" "slot" "archive-device" "drive-index"
# $1 $2 $3 #4 #5
#
# See the Bacula documentation and the Bacula Removable Disk Howto for
# further details.
#
# Copyright (C) 2006 Josh Fisher
#
# Permission to use, copy, modify, distribute, and sell this software
# and its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies. This
# software is provided "as is" without express or implied warranty.
#
# This software 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.
#
# $Id: vchanger,v 0.7.4 2006/12/01 09:29:04 jfisher Exp $
#
# log whats done
#
# to turn on logging, uncomment the following line
#touch $wd/vchanger.log
#
#
# Write to a log file
# To log debugging info, create file /var/bacula/vchanger.log
# with write permission for bacula-sd user. To stop logging,
# delete file /var/bacula/vchanger.log
#
dbgfile="/var/bacula/vchanger.log"
function debug()
{
if test -e $dbgfile; then
echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
fi
}
#
# Return length of string $1
#
if [ `uname` = "FreeBSD" ]
then
function strlen ()
{
expr -- "$1" : ".*"
}
else
function strlen ()
{
expr length $1
}
fi
#
# Prepend zeros to $1 and return a string that is $2 characters long
#
function mklen ()
{
o1=$1
while [ `eval strlen ${o1}` -lt ${2} ]; do
o1="0${o1}"
done
echo $o1
}
#
# Get uid of $1 (or current user if $1 empty)
#
function get_uid() {
id $1 2>/dev/null | cut -d ' ' -f 1 | sed "s/uid=//" | cut -d '(' -f 1
}
#
# Initialize autochanger's state directory if not already initialized
#
function init_statedir() {
debug "Initializing $statedir"
# Create state directory if needed
if [ ! -d "${statedir}" ]; then
if [ "$su_uid" != "" ]; then
su -c "mkdir ${statedir} &>/dev/null" $su_uid
else
mkdir ${statedir} &>/dev/null
fi
if [ $? -ne 0 ]; then
echo "Could not create ${statedir}"
exit 1
fi
chmod 770 ${statedir} &>/dev/null
if [ $? -ne 0 ]; then
echo "Could not chmod ${statedir}"
exit 1
fi
fi
# Create nextmag file to hold max magazine index used
if [ ! -f "${statedir}/nextmag" ]; then
if [ "$su_uid" != "" ]; then
su -c "echo 0 >${statedir}/nextmag" $su_uid
else
echo 0 >${statedir}/nextmag
fi
if [ $? -ne 0 ]; then
echo "Could not create ${statedir}/nextmag"
exit 1
fi
chmod 660 ${statedir}/nextmag
if [ $? -ne 0 ]; then
echo "Could not chmod ${statedir}/nextmag"
exit 1
fi
fi
# Check nextmag value
nextmag=`cat "${statedir}/nextmag"`
if [ $? -ne 0 -o "${nextmag}" == "" -o $nextmag -lt 0 -o $nextmag -gt 99 ]; then
echo "${statedir}/nextmag has invalid value"
return 1
fi
# Create 'loaded' files for each virtual drive that hold the slot
# number currently loaded in that 'drive'
i=0
while [ $i -le $maxdrive ]; do
if [ ! -f "${statedir}/loaded${i}" ]; then
if [ "$su_uid" != "" ]; then
su -c "echo 0 >${statedir}/loaded${i}" $su_uid
else
echo 0 >${statedir}/loaded${i}
fi
if [ $? -ne 0 ]; then
echo "Could not create ${statedir}/loaded${i}"
exit 1
fi
if [ "$su_uid" != "" ]; then
su -c "chmod 660 ${statedir}/loaded${i}" $su_uid
else
chmod 660 ${statedir}/loaded${i}
fi
if [ $? -ne 0 ]; then
echo "Could not chmod ${statedir}/loaded${i}"
exit 1
fi
fi
i=`expr ${i} + 1`
done
}
#
# Get magazine index of currently loaded magazine
#
function get_magazine() {
debug "Get magazine index"
# Check for mountpoint dir
if [ ! -d ${mountpoint} ]; then
echo "No magazine loaded at ${mountpoint}"
exit 1
fi
# Check magazine for existing index
if [ ! -f "${mountpoint}/index" ]; then
echo "00"
return 1
fi
mi=`cat "${mountpoint}/index"`
if [ $? -ne 0 ]; then
echo "Failed to read ${mountpoint}/index"
exit 1
fi
# must be 1-99
if [ $mi -lt 1 -o $mi -gt 99 ]; then
echo "Magazine has invalid index ${mi}"
exit 1
fi
# make magazine index 2 digits
eval mklen ${mi} 2
return 0
}
#
# Initialize magazine if not already initialized
#
function init_magazine() {
debug "Initializing magazine"
# Get max magazine index that has been used
nextmag=`cat "${statedir}/nextmag"`
if [ $? -ne 0 -o "${nextmag}" == "" ]; then
echo "Failed to read ${statedir}/nextmag"
exit 1
fi
# Check magazine for existing index
if [ -f "${mountpoint}/index" ]; then
# retrieve existing magazine index
mi=`cat "${mountpoint}/index"`
if [ $? -ne 0 ]; then
echo "Failed to read ${mountpoint}/index"
exit 1
fi
# must be 1-99
if [ $mi -lt 1 -o $mi -gt 99 ]; then
echo "Magazine has invalid index ${mi}"
exit 1
fi
else
# new magazine, so assign it the next avail index
mi=`expr ${nextmag} + 1`
if [ $mi -lt 0 -o $mi -gt 99 ]; then
echo "Max magazines exceeded"
exit 1
fi
if [ "$su_uid" != "" ]; then
su -c "echo ${mi} >${mountpoint}/index" $su_uid
else
echo ${mi} >${mountpoint}/index
fi
if [ $? -ne 0 ]; then
echo "Failed to write ${mountpoint}/index"
exit 1
fi
chmod 640 ${mountpoint}/index 2>/dev/null
fi
# make sure max index used is up to date
if [ $mi -gt $nextmag ]; then
echo $mi 2>/dev/null >"${statedir}/nextmag"
if [ $? -ne 0 ]; then
echo "Failed to update ${statedir}/nextmag"
exit 1
fi
fi
# make magazine index 2 digits
magindex=`eval mklen ${mi} 2`
# setup slot files (ie. virtual tapes)
i=1
while [ $i -le $magslots ]; do
s=`eval mklen ${i} 3`
f="${mountpoint}/m${magindex}s${s}"
if [ ! -f "${f}" ]; then
if [ "$su_uid" != "" ]; then
su -c "touch ${f} &>/dev/null" $su_uid
else
touch ${f} &>/dev/null
fi
if [ $? -ne 0 ]; then
echo "Failed to create ${f}"
exit 1
fi
fi
i=`expr ${i} + 1`
done
return 0
}
#
# Get sd status with bconsole
#
function bconsole_sd_status() {
debug "Doing 'status storage' with bconsole"
$bconsole <<EOD_SDSTAT
status storage=$baculasd
quit
EOD_SDSTAT
}
#
# Delete volume with bconsole param1 = slot
#
function bconsole_delete_volume() {
debug "Doing 'delete volume' with bconsole"
s=`eval mklen $1 3`
$bconsole <<EOD_DELVOL
delete volume=m${magindex}s${s}
yes
quit
EOD_DELVOL
}
#
# Label volumes from barcodes with bconsole
#
function bconsole_label_barcodes() {
debug "Doing 'label barcodes' with bconsole"
$bconsole <<EOD_SDSTAT
label storage=$baculasd pool=$purgepool drive=0 barcodes
yes
quit
EOD_SDSTAT
}
#
# Checks if any of magazine's volumes are in use
#
function volumes_in_use() {
debug "Checking for in use volumes"
inuse=""
bconsole_sd_status | while read f; do
#echo $f
a=`echo ${f} | grep ^${magindex}`
if [ "$a" != "" -a "$inuse" == "" ]; then
inuse=`echo $f | cut -d ' ' -f 1`
fi
done
if [ "$inuse" != "" ]; then
echo $inuse
fi
}
#
# Unload all drives
#
function unload_drives() {
debug "Unloading all drives"
vuse=`eval volumes_in_use`
if [ "${vuse}" != "" ]; then
return 1
fi
i=0
while [ $i -le $maxdrive ]; do
unlink "${statedir}/drive${i}" 2>/dev/null >/dev/null
echo "0" >"${statedir}/loaded${i}"
i=`expr ${i} + 1`
done
return 0
}
#
# check parameter count on commandline
#
function check_parm_count() {
pCount=$1
pCountNeed=$2
if test $pCount -lt $pCountNeed; then
echo "usage: vchanger 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
}
# Setup arguments
check_parm_count $# 2
ctl=$1
cmd=$2
slot=$3
device=$4
drive=$5
# Setup default config values
baculasd=
baculasd_user=bacula
bconsole="/etc/bacula/bconsole"
magslots=10
maxdrive=0
mountpoint=
purgepool="Scratch"
statedir=
# Pull in conf file
if [ -f $ctl ]; then
. $ctl
else
echo "Config file ${ctl} not found"
exit 1
fi
# When invoked by root, create files/dirs as bacula-sd user
su_uid=
myuid=`eval get_uid`
if [ "$myuid" == "0" -a "$baculasd_user" != "" ]; then
buid=`eval get_uid $baculasd_user`
if [ "$buid" == "" ]; then
echo "bacula-sd user $baculasd_user not found"
exit 1
fi
if [ "$buid" != "0" ]; then
su_uid=baculasd_user
fi
fi
# check for required config values
if [ "${mountpoint}" == "" ]; then
echo "Required variable 'mountpoint' not defined in ${ctl}"
exit 1
fi
if [ "${baculasd}" == "" ]; then
echo "Required variable 'baculasd' not defined in ${ctl}"
exit 1
fi
if [ "${statedir}" == "" ]; then
echo "Required variable 'statedir' not defined in ${ctl}"
exit 1
fi
if [ "${magslots}" == "" -o $magslots -lt 1 -o $magslots -gt 999 ]; then
echo "Ivalid value for 'magslots' in ${ctl}"
exit 1
fi
if [ "${maxdrive}" == "" -o $maxdrive -lt 0 -o $maxdrive -ge $magslots ]; then
echo "Invalid value for 'maxdrive' in ${ctl}"
exit 1
fi
if [ "${bconsole}" == "" -o ! -f "${bconsole}" ]; then
echo "Ivalid value for 'bconsole' in ${ctl}"
exit 1
fi
if [ "${purgepool}" == "" ]; then
echo "Invalid value for 'purgepool' in ${ctl}"
exit 1
fi
# attempt to set defaults for params not specified on command line
if [ "${drive}" == "" ]; then
drive=0
fi
if [ "${device}" == "" ]; then
device="${statedir}/drive${drive}"
fi
# make sure archive device makes sense
if [ "${device}" != "${statedir}/drive${drive}" ]; then
echo "Param 4 (archive device) must be ${statedir}/driveN,"
echo " where N is the drive number passed as param 5"
exit 1
fi
# Initialize state directory for this autochanger
init_statedir
debug "Parms: $ctl $cmd $slot $device $drive"
#
# Process command
#
case $cmd in
list)
check_parm_count $# 2
debug "Doing list command"
init_magazine
if [ $? -ne 0 ]; then
echo "Magazine Not Loaded"
exit 1
fi
i=1
while [ $i -le $magslots ]; do
s=`eval mklen ${i} 3`
echo "${i}:m${magindex}s${s}"
i=`expr ${i} + 1`
done
;;
slots)
check_parm_count $# 2
debug "Doing slots command"
echo $magslots
;;
load)
check_parm_count $# 5
debug "Doing load slot $slot into drive $drive"
if [ $drive -gt $maxdrive ]; then
echo "Drive ($drive) out of range (0-${maxdrive})"
exit 1
fi
if [ $slot -gt $magslots ]; then
echo "Slot ($slot) out of range (1-$magslots)"
exit 1
fi
ld=`cat "${statedir}/loaded${drive}"`
if [ $? -ne 0 ]; then
echo "Failed to read ${statedir}/loaded${drive}"
exit 1
fi
if [ $ld -eq 0 ]; then
unlink "${device}" &>/dev/null
# make sure slot is not loaded in another drive
i=0
while [ $i -le $maxdrive ]; do
if [ $i -ne $drive ]; then
ldi=`cat "${statedir}/loaded${i}"`
if [ $ldi -eq $slot ]; then
echo "Storage Element ${slot} Empty (loaded in drive ${i})"
exit 1
fi
fi
i=`expr ${i} + 1`
done
init_magazine
if [ $? -ne 0 ]; then
echo "Magazine Not Loaded"
exit 1
fi
s=`eval mklen ${slot} 3`
if [ "$su_uid" != "" ]; then
su -c "ln -s '${mountpoint}/m${magindex}s${s}' '${device}'" $su_uid
else
ln -s "${mountpoint}/m${magindex}s${s}" "${device}"
fi
echo $slot >"${statedir}/loaded${drive}"
else
echo "Drive ${drive} Full (Storage element ${ld} loaded)"
exit 1
fi
;;
unload)
check_parm_count $# 5
debug "Doing unload drive $drive into slot $slot"
if [ $drive -gt $maxdrive ]; then
echo "Drive ($drive) out of range (0-${maxdrive})"
exit 1
fi
if [ $slot -gt $magslots ]; then
echo "Slot ($slot) out of range (1-$magslots)"
exit 1
fi
ld=`cat "${statedir}/loaded${drive}"`
if [ $? -ne 0 ]; then
echo "Failed to read ${statedir}/loaded${drive}"
exit 1
fi
if [ $slot -eq $ld ]; then
echo "0" >"${statedir}/loaded${drive}"
if [ $? -ne 0 ]; then
echo "Failed to write ${statedir}/loaded${drive}"
exit 1
fi
unlink "${device}" 2>/dev/null >/dev/null
exit 0
fi
if [ $ld -eq 0 ]; then
echo "Drive ${drive} Is Empty"
exit 1
else
echo "Storage Element ${slot} is Already Full"
exit 1
fi
;;
loaded)
check_parm_count $# 5
debug "Doing loaded command for drive $drive"
if [ $drive -gt $maxdrive ]; then
echo "Drive ($drive) out of range (0-${maxdrive})"
exit 1
fi
if [ $slot -gt $magslots ]; then
echo "Slot ($slot) out of range (1-$magslots)"
exit 1
fi
cat "${statedir}/loaded${drive}"
;;
purge)
check_parm_count $# 2
debug "Doing purge command"
magindex=`eval get_magazine`
if [ "$magazine" == "00" ]; then
echo No magazine loaded
fi
cm=""
while [ "$cm" != "y" -a "$cm" != "n" ]; do
echo -n "Purge all volumes on magazine $magindex (y/n)? "
read cm
if [ "$cm" == "Y" ]; then
cm="y"
fi
if [ "$cm" == "N" ]; then
cm="n"
fi
done
if [ "$cm" == "n" ]; then
exit 0
fi
echo "Unloading $baculasd drives"
unload_drives
if [ $? -ne 0 ]; then
echo Volume `eval volumes_in_use` in use...aborting
exit 1
fi
echo "Deleting magazine $magindex volumes"
i=1
while [ $i -le $magslots ]; do
bconsole_delete_volume $i &>/tmp/vclog
rm -f "${mountpoint}/m${magindex}s${s}"
echo "deleted volume m${magindex}s${s}"
i=`expr ${i} + 1`
done
echo "Doing 'label barcodes' to re-create magazine's volumes"
bconsole_label_barcodes | while read f; do
echo $f
done
;;
*)
echo "Command not recognized"
exit 1
;;
esac
exit 0
# eof