...
...
...
This is a summary of the steps needed to perform a backup of a virtual machine:
Bacula Director Daemon (
...
backup01) instructs the Bacula Client Daemon
...
to start a copy of virtual01.
...
- Bacula Client Daemon (
...
- production01) performs the snapshot of the virtual machine with the reflink command. There is no need to suspend or stop the virtual machine to make the copy.
- The copy is compressed, to reduce bandwidth and storage consumption.
- Then, Bacula Client Daemon (production01) instructs Bacula Storage Daemon (desarrollo01) to store the copy of virtual01 in storagebackup.
- Finally, if the copy has been correctly carried out, files created during this process will be deleted.
Now, we will detail the configuration of each component.
Configuration of Bacula Director Deamon
The backup process must be configured in the Bacula Director Deamon, hosted in backup01, in the file /etc/bacula-dir.conf
. Job is the Bacula term for the backup tasks that must be scheduled. To define a new Job, you have to add 3 new elements to that configuration file. The first one is the client that will perform the Job:
Code Block | ||
---|---|---|
|
...
|
...
Storage {
...
| |
Client {
Name = produccion01-fd
Address = produccion01 # IP
FDPort = 9102
Catalog = MyCatalog
Password = "produccion01-fd.password"
File Retention = 1 year
Job Retention = 1 year
AutoPrune = yes
Maximum Concurrent Jobs = 10
} |
Client { Name = produccion01-fd Address = produccion01 # IP FDPort = 9102 Catalog = MyCatalog Password = "produccion01-fd.password" File Retention = 1 year Job Retention = 1 year AutoPrune = yes Maximum Concurrent Jobs = 10 } |
Se añade a continuación donde el cliente almacenara la copia de seguridad:
The second one is the storage where the client will write the backup.
Code Block | ||||
---|---|---|---|---|
| ||||
Storage { Name = "storage_virtual01_full" |
...
Address = desarrollo01 |
...
SDPort = 9103 |
...
Password = "desarrollo01-sd.password" |
...
Device = backup_erp01_full |
...
Maximum Concurrent Jobs = 10 |
...
Media Type = "file_virtual01_full" |
...
}
Por ultimo se añade el Job que el cliente va a realizar.
Schedule {
...
} |
Code Block | ||||
---|---|---|---|---|
| ||||
Schedule { Name = "schedule_virtual01_full" |
...
Run = Level=Full Pool=pool_mensual on 1,16 at 3:00 |
...
Run = Level=Full Pool=pool_quincenal sun-sat at 3:00 |
...
} |
...
FileSet { |
...
Name = "fileset_virtual01_full" |
...
Include |
...
Options { signature = SHA1; onefs =
yes
; }
...
{ Options { signature = SHA1; onefs = yes; } File = /storage/virtual01- |
...
bak. |
...
}
}
Job {
...
gz } } Job { Name = "job_virtual01_full" |
...
Type = Backup |
...
Level = Full |
...
Client = produccion01-fd |
...
FileSet = "fileset_virtual01_full" |
...
Schedule = "schedule_virtual01_full" |
...
Storage = "storage_virtual01_full" |
...
Messages = Standard |
...
Pool = pool_anual |
...
Full Backup Pool = pool_mensual |
...
Incremental Backup Pool = pool_quincenal |
...
Priority = 11 |
...
Write Bootstrap = "/apps/bacula/opt/bacula/working/virtual01_full.bsr" |
...
## Script running on client |
...
Client Run Before Job = "/apps/bacula/script/ |
...
backup_full_ |
...
guest.sh virtual01" |
...
Client Run After Job = "/apps/bacula/script/ |
...
remove_backup_full_guest.sh virtual01" |
...
}
...
} |
There are two things that are worth noting in that configuration. The first one is the file that is going to be copied, in section FileSet:
Code Block | ||||
---|---|---|---|---|
| ||||
File = /storage/virtual01- |
...
bak.gz |
Y los scripts que se van a encargar de parar y restaurar virtual01 y borrar los ficheros creados durante la copia de seguridad. Estos scripts se detallan mas adelante.
...
The second one is the declaration of the scripts in charge of copying and compressing the virtual01 image, on one hand, and removing those files afterwards, on the other. This is done in section Job. Those scripts are detailed later on.
Code Block | ||||
---|---|---|---|---|
| ||||
Client Run Before Job = "/apps/bacula/script/ |
...
backup_full_ |
...
guest.sh virtual01" |
...
Client Run After Job = "/apps/bacula/script/ |
...
remove_backup_full_guest.sh virtual01" |
...
...
Configuration of Bacula Storage Daemon
Once the Job is defined in the Bacula Director Daemon,
...
you must create a Device (place where the backup will be stored) in the Bacula Storage Daemon (desarrollo01). It is done in the configuration file /etc/bacula-sd.conf
...
Device {
...
, adding the following lines:
Code Block | ||||
---|---|---|---|---|
| ||||
Device { Name = backup_virtual01_full |
...
Media Type = file_erp01_sql |
...
Archive Device = /backup/vm/virtual01 |
...
LabelMedia = |
...
Random Access = Yes;
AutomaticMount =
yes
;
RemovableMedia = no;
AlwaysOpen = no;
Maximum Concurrent Jobs = 10
}
Por ultimo, se deben crear dos scripts encargados de suspender la maquina virtual para realizar la copia y de volver a restaurarla y el script que borra la copia de seguridad ya copiada a storagebackup. Estos scripts deben estar almacenados en produccion01 (Bacula Client Daemon)
vm_stop.sh
##/bin/bash
PASS=`
cat
/root/pass
`
MACHINE=$1
...
yes;
Random Access = Yes;
AutomaticMount = yes;
RemovableMedia = no;
AlwaysOpen = no;
Maximum Concurrent Jobs = 10
} |
Configuration of Bacula Client Daemon
Finally, we need to define two scripts, to perform the snapshot of the virtual machine and remove it once it is transferred to storagebackup. These scripts will be stored in the Bacula Client Daemon (produccion01).
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
#!/bin/sh MACHINE=$1 [ -n "$MACHINE" ] || { echo Usage: ./backup_full_guest.sh guest_name exit 1 } LOGFILE=/apps/bacula/log/log_$MACHINE.log |
...
DATE=`
date
+%d%m%Y`
echo
" "
>> $LOGFILE
echo
"-------------------------------"
$MACHINE
"--"
`
date
+%d`-`
date
+%m`-`
date
+%Y` `
date
+%H`:`
date
+%M`
"---------------------------------------"
>> $LOGFILE
ESTADO=`flexadm guest-status -p $PASS -g $MACHINE`
if
[ $ESTADO =
"running"
]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE esta en ejecucion, se suspende..."
>> $LOGFILE
flexadm -p $PASS -g $MACHINE suspend -w
sleep
300
ESTADO=`flexadm guest-status -p $PASS -g $MACHINE`
if
[ $ESTADO =
"running"
]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE No se ha suspendido después de 5 minutos se suspende la copia."
>> $LOGFILE
flexadm -p $PASS -g $1 restore -w
#Asegurar que la maquina queda en ejecucion
elif
[ $ESTADO =
"suspended"
]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE se ha suspendido, se crea backup ($MACHINE-bk)."
>> $LOGFILE
LUGAR=`flexadm -p $PASS -g $1 guest-images`
reflink $LUGAR $LUGAR-bk
if
[ $? -
eq
0 ]
then
if
[ -f $LUGAR-bk ]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE-bk creado, se comprime ($MACHINE-bk_$DATE.tar.gz)."
>> $LOGFILE
fi
tar
-cf $LUGAR-bk_$DATE.
tar
.gz $LUGAR-bk
if
[ $? -
eq
0 ]
then
if
[ -f $LUGAR-bk_$DATE.
tar
.gz ]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE-bk comprimida ($MACHINE-bk_$DATE.tar.gz), se borra $MACHINE-bk."
>> $LOGFILE
rm
-rf $LUGAR-bk
if
[ $? -
eq
0 ]
then
if
[ ! -f $LUGAR-bk ]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE-bk borrada."
>> $LOGFILE
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` Backup de $MACHINE creado correctamente."
>> $LOGFILE
fi
else
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` ERROR AL BORRAR $MACHINE-bk"
>> $LOGFILE
fi
fi
else
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` ERROR AL COMPRIMIR $MACHINE-bk NO SE HA CREADO ($MACHINE-bk_$DATE.tar.gz)"
>> $LOGFILE
fi
else
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` ERROR AL CREAR $MACHINE-bk"
>> $LOGFILE
fi
fi
elif
[ $ESTADO =
"suspended"
]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE suspendida"
>> $LOGFILE
fi
echo
"--------------------------------------------------------------------------------------------------------"
>> $LOGFILE
Este script es el encargado de borrar la copia de la maquina virtual, virtual01 que ya ha sido guardada en storagebackup.
vm_stop.sh
#!/bin/bash
PASS=`
cat
/root/pass
`
MACHINE=$1
LOGFILE=
/bacula/log/log_
$MACHINE.log
DATE=`
date
+%d%m%Y`
echo
" "
>> $LOGFILE
echo
"-------------------------------"
$MACHINE
"--"
`
date
+%d`-`
date
+%m`-`
date
+%Y` `
date
+%H`:`
date
+%M`
"---------------------------------------"
>> $LOGFILE
ESTADO=`flexadm guest-status -p $PASS -g $MACHINE`
if
[ $ESTADO =
"running"
]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE esta restaurada"
>> $LOGFILE
LUGAR=`flexadm -p $PASS -g $MACHINE guest-images`
if
[ -f $LUGAR-bk.
tar
.gz ]
then
rm
-rf $LUGAR-bk.
tar
.gz
if
[ $? -
eq
0 ]
then
if
[ ! -f $LUGAR-bk.
tar
.gz ]
then
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE-bk.tar.gz borrado con exito"
>> $LOGFILE
else
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE-bk.tar.gz no se ha borrado"
>> $LOGFILE
fi
else
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` ERROR AL BORRAR $MACHINE-bk.tar.gz"
>> $LOGFILE
fi
else
echo
"`date +%d`-`date +%m`-`date +%Y` `date +%H`:`date +%M` $MACHINE-bk.tar.gz no existe"
>> $LOGFILE
fi
fi
...
log() {
echo $(date "+%d-%m-%Y %H:%M") "$@" >> $LOGFILE
}
log
IMAGE="/storage/$MACHINE"
[ -f "$IMAGE" ] || {
log ERROR: GUEST $MACHINE DOES NOT EXIST
exit 1
}
BAK="$IMAGE-bak"
log "---- Reflink ---- $MACHINE ----"
if ! reflink "$IMAGE" "$BAK"; then
log ERROR CREATING $MACHINE SNAPSHOT
exit 1
fi
log Reflink of $MACHINE succeeded.
if ! gzip "$BAK"; then
log ERROR COMPRESSING THE BACKUP
exit 1
fi
log Image compressed |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
#!/bin/sh
MACHINE=$1
[ -n "$MACHINE" ] || {
echo Usage: ./remove_backup_full_guest.sh guest_name
exit 1
}
LOGFILE=/apps/bacula/log/log_$MACHINE.log
log() {
echo $(date "+%d-%m-%Y %H:%M") "$@" >> $LOGFILE
}
log
IMAGE="/storage/$MACHINE"
BAK="$IMAGE-bak.gz"
[ -f "$BAK" ] || {
log ERROR: THE BACKUP OF $MACHINE DOES NOT EXIST
exit 1
}
log "---- Remove ---- $MACHINE ----"
if ! rm -f "$BAK"; then
log ERROR REMOVING $BAK
exit 1
fi
log Backup removed |