SyntaxHighlighter

viernes, 21 de marzo de 2014

Data Protector. Recuperación usando la directiva POST-EXEC y SCRIPTING

Con Data Protector podemos programar una agenda de copias de seguridad fácilmente usando la GUI Java, lo que no es tan simple es planificar una calendario de restauración que, por ejemplo, recupere la última copia de seguridad realizada en otra localización.

La primera aproximación sería intentar ejecutar esta restauración llamando al programa omnir con los argumentos necesarios e incluir la llamada en el cron del servidor para que se ejecute periódicamente. Lo que a priori parece algo sencillo se complica con sólo mirar la la página de manual de omnir (o buscar "data protector cli reference" en cualquier buscador). El Backend de comandos de Data Protector da toda la funcionalidad que necesitamos para restaurar una copia de seguridad, pero es necesario la ejecución de varias órdenes para "montar" los argumentos que necesita omnir.

Hay otro problema en cuanto a la inclusión en cron de esta orden podría dar lugar a solapamientos en el uso de la unidad sobre la que estemos haciendo la copia de seguridad.

Imaginad que la copia de seguridad programada comienza a las 2:00 am, y nuestra orden de restauración se ejecuta vía cron a las 4:00 am. Si la copia de seguridad tarda más de 2h, la restauración se podrá en cola. Pasado cierto tiempo de espera configurable en Data Protector, si aún no ha comenzado el trabajo de restauración, se procederá a su cancelación. Esto se puede evitar usando las opciones POST-EXEC y PRE-EXEC del trabajo de copia de seguridad.

Estas dos opciones se encargan de ejecutar un script en el cliente de data protector que indiquemos antes (PRE-EXEC) o después (POST-EXEC) de que se realice el trabajo de backup. El uso más extendido de estas dos opciones es el de parar un servicio antes de realizar el trabajo de copia y levantarlo después.

Para conseguir el comportamiento que necesitamos lo ideal sería ejecutar un script en POST-EXEC que llame a omnir con los datos de la última copia de seguridad. Para conseguir los datos necesarios de la última sesión de copia de seguridad hay que ejecutar la orden onmidb, que consulta la BD de Data Protector para extraer la información que requiere omnir:

/opt/omni/bin/omnir -filesystem [datalist] [label] -session [session] -tree [path] -as [target_path] -target [target_client]

Pasos del script:
  1. Considera un número de días hacia atrás desde la fecha actual para buscar la última sesión de la agenda especificada.
  2. Determinar sesión más reciente que se terminó satisfactoriamente en el intervalo definido en el paso anterior.
  3. Buscar el árbol de directorios que queremos restaurar y extraer el datalist y label, argumentos necesarios para ejecutar omnir.
  4. Ejecutar omnir con los parámetros adecuados.
El código del script (un poco sucio):

#!/bin/bash
OMNI_PATH=/opt/omni/bin/

if [ $# -ne 5 ]; then
  echo "Ilegal number of arguments" >&2
  echo "Use: $0 [dataList] [label] [targetClient] [targetDir] [RestoreOnlyIfFull 0/1]" >&2
  exit 1
fi

ARG_DATALIST=$1
ARG_LABEL=$2
ARG_TARGETCLIENT=$3
ARG_TARGETDIR=$4
ARG_ONLYFULL=$5
DAYSTOINSPECT=30

INITIALDATE=$(date '+%Y/%m/%d' --date="${DAYSTOINSPECT} days ago")
LASTSESSION=$(${OMNI_PATH}omnidb -session -datalist $ARG_DATALIST -since $INITIALDATE | grep -i backup | grep -i completed | tail -n1 | cut -f 1 -d " ")
FILESYSTEM=$(${OMNI_PATH}omnidb -session $LASTSESSION | grep \'${ARG_LABEL}\' | cut -f1 -d " ")
LABEL=$(${OMNI_PATH}omnidb -session $LASTSESSION | grep \'${ARG_LABEL}\' | cut -f2 -d " ")
BACKUP_LEVEL=$(${OMNI_PATH}omnidb -filesystem $FILESYSTEM ${ARG_LABEL} -session $LASTSESSION | egrep -o "Incremental|Full")

if [ -z "$LASTSESSION" ]; then
 echo "Session not found: $ARG_DATALIST. Available schedules:"
 ls /etc/opt/omni/server/schedules >&2
 exit 1
fi

if [[ $ARG_ONLYFULL -eq 1 && $BACKUP_LEVEL != "Full" ]]; then
 echo "Mode is set to full but cannot find full backup" >&2
 exit 1
fi

if [ -z "$LABEL" ]; then 
 echo "Label not found: $ARG_LABEL. Backed up filesystems and labels:"
 omnidb -filesystem >&2
 exit 1
fi

#Print command options
echo "Restoring label: ${LABEL}, filesystem: < $FILESYSTEM > from Session: $LASTSESSION into ${ARG_TARGETCLIENT}:${ARG_TARGETDIR}, backup_level: $BACKUP_LEVEL"
#Print omnir command used to perform the restore job. Debug.
echo ${OMNI_PATH}omnir -filesystem ${FILESYSTEM} ${LABEL} -session ${LASTSESSION} -tree ${ARG_LABEL} -as ${ARG_TARGETDIR} -target ${ARG_TARGETCLIENT}
OMNI_COMMAND="${OMNI_PATH}omnir -filesystem ${FILESYSTEM} ${LABEL} -session ${LASTSESSION} -tree ${ARG_LABEL} -as ${ARG_TARGETDIR} -target ${ARG_TARGETCLIENT}"
eval $OMNI_COMMAND

Si a la orden omnir que se llama al final del script añadimos -full antes del argumento -filesystem se restaurará una copia completa del árbol de directorios usando la última copia completa que se realizó y todas las incrementales hasta la sesión que estamos restaurando. De otra manera sólo se restaurarán los ficheros que se respaldaron en la sesión en cuestión.  El último argumento del script controla los problemas que se puedan derivar de esto: sólo se ejecutará la restauración si la última copia ha sido full.

No está de más ejecutar el script comentando la última línea (eval ...), para comprobar que todo es correcto antes de empezar a utilizarlo. Si alguno de los parámetros no es correcto imprimirá posibles soluciones.

Por último, el directorio en el que tenemos que incluir el script para que no haya problemas es /opt/omni/lbin y así podremos llamarlo sin usar path completo, algo que parece que no funciona bien si configuramos el POST-EXEC desde la GUI Java.

NOTA. Si la restauración toma demasiado tiempo, Data Protector puede abortar el Script. Para evitarlo se puede modificar la opción ScriptOutputTimeout en el fichero /etc/opt/omni/server/options/global

No hay comentarios: