La sauvegarde et restauration des bases de données est une problématique majeur pour tout DBA. OpenLDAP n’échappe pas à cette règle cependant il n'existe que très peut d'outil pour effectuer des sauvegarde de ces bases.

 

Les outils fournis avec slap pour sauvegarder et restaurer proposent d'exporter la base sous forme d'un fichier plat ldif. Cependant l'exportation et la conversion peut prendre du temps. Pour notre base (environ 200Mo) il faut presque 1h pour réaliser l'export et l'importation qui recalcule les indexes peut prendre jusqu’à 4h.

 

Je vous propose dans ce billet une autre méthode pour faire des export / import de base ldap. Elle se base sur l'utilisation de db-util pour recopier les fichiers bruts avec lesquels travail Openldap. Avec cette methode le temps de sauvegarde restauration peut passer de 1h à 5min.

Sauvegarde

Ce script fonctionne de la façon suivante :

  1. Utilisation de "db5.3_hotbackup" pour faire une sauvegarde cohérente des fichiers ldap
  2. Export en ldif de la configuration uniquement de la base
  3. Réalisation d'un targz contenant le fichier de configuration + les datafile

 

#!/bin/bash
#@****************************************************************************
#@ Author : Mathieu GOULIN ([email protected])
#@ Organization : Gadz.org (www.gadz.org) 
#@ Licence : GNU/GPL
#@ 
#@ Description : 
#@               
#@ Prerequisites :
#@ Arguments : 
#@
#@****************************************************************************
#@ History :
#@  - Mathieu GOULIN - 2015/12/26 : Initialisation du script
#@****************************************************************************
 
# Static configuration
cd `dirname $0`
script=`basename "$0" | cut -f1 -d"."`
log_file=`pwd`/$script.log
 
# Usage function
function usage () {
    # TODO - Write the good stuff here...
    echo "$0 [start|stop|restart]"
}
# Help function
function help () {
    usage
    echo
    grep -e "^#@" $script.sh | sed "s/^#@//"
}
 
# Log function
write_log () {
    log_state=$1
    shift;
    log_txt=$*
    log_date=`date +'%Y/%m/%d %H:%M:%S'`
    case ${log_state} in
        BEG)    chrtra="[START]"      ;;
        CFG)    chrtra="[CONF ERR]"   ;;
        ERR)    chrtra="[ERROR]"      ;;
        END)    chrtra="[END]"        ;;
        INF)    chrtra="[INFO]"       ;;
        *)      chrtra="[ - ]"        ;;
    esac
    echo "$log_date $chrtra : ${log_txt}" | tee -a ${log_file} 2>&1
}

test_rc () {
  if [ "x$1" != "x0" ]
  then
    write_log ERR "Erreur RC=$1"
    exit $1
  fi
}

. `dirname $0`/../config/config.sh

# On netoi les archives logs
write_log INF "Netoyage des archives logs devenu inutile"
$ROOT/shell/clean.sh
test_rc $?

# creation du repertoire de backup
TH=`date +%Y%m%d_%H%M%S`
mkdir -p $ROOT/ldap-backup/$TH
mkdir -p $ROOT/ldap-backup/$TH/ldap-datafile

# Make hotbackup
write_log INF "Sauvegarde a chaud des datafiles"
db5.3_hotbackup -v -b $ROOT/ldap-backup/$TH/ldap-datafile/ -h $ROOT/ldap-datafile 2>&1 | tee -a ${log_file}
test_rc $?

cd $ROOT/ldap-backup/$TH/ldap-datafile
# export config
write_log INF "Export config"
slapcat -n 0 -F $ROOT/config/slapd.d > config.ldif

# Make archive
write_log INF "Archivages et compression : $ROOT/ldap-backup/ldap-datafile_$TH.tar.gz"
tar -czvf $ROOT/ldap-backup/ldap-datafile_$TH.tar.gz *
test_rc $?

cd ~
rm -rf $ROOT/ldap-backup/$TH
write_log INF "Fin de la sauvegarde a chaud"
exit $?

 

Restauration

Ce script fonctionne de la facon suivante :

  1. Couper l'instance LDAP
  2. Suppression des fichiers existants et configuration
  3. On fait un split du fichier de configuration présent dans la sauvegarde
  4. On insert les configurations de schema
  5. On insert les configurations de backend
  6. On insert les configurations de olcDatabase
  7. On insert les droits
  8. On démare une premiere fois le ldap (a vide)
  9. On Modifie les entrées qui ne peuvent etre modifié qu'une fois la base lancé (emplacement du répertoire contenant les données, ...)
  10. On coupe la base
  11. On recopie les datafile présent dans la sauvegarde
  12. On fixe les droits sur les fichiers et repertoires
  13. On lance la base

 

#!/bin/bash
#@****************************************************************************
#@ Author : Mathieu GOULIN ([email protected])
#@ Organization : Gadz.org (www.gadz.org) 
#@ Licence : GNU/GPL
#@ 
#@ Description : 
#@               
#@ Prerequisites :
#@ Arguments : 
#@
#@****************************************************************************
#@ History :
#@  - Mathieu GOULIN - 2015/12/26 : Initialisation du script
#@****************************************************************************
 
# Static configuration
cd `dirname $0`
script=`basename "$0" | cut -f1 -d"."`
log_file=`pwd`/$script.log
 
# Usage function
function usage () {
    # TODO - Write the good stuff here...
    echo "$0 [start|stop|restart]"
}
# Help function
function help () {
    usage
    echo
    grep -e "^#@" $script.sh | sed "s/^#@//"
}
 
# Log function
write_log () {
    log_state=$1
    shift;
    log_txt=$*
    log_date=`date +'%Y/%m/%d %H:%M:%S'`
    case ${log_state} in
        BEG)    chrtra="[START]"      ;;
        CFG)    chrtra="[CONF ERR]"   ;;
        ERR)    chrtra="[ERROR]"      ;;
        END)    chrtra="[END]"        ;;
        INF)    chrtra="[INFO]"       ;;
        *)      chrtra="[ - ]"        ;;
    esac
    echo "$log_date $chrtra : ${log_txt}" | tee -a ${log_file} 2>&1
}

test_rc () {
  if [ "x$1" != "x0" ]
  then
    write_log ERR "Erreur RC=$1"
    exit $1
  fi
}

. `dirname $0`/../config/config.sh

echo $1 | grep -q "@"
if [ $? -eq 0 ];then
    ssh_string=`echo $1 | cut -f1 -d":"`
    file=`echo $1 | cut -f2 -d":"`
    ssh=1
else
    ssh=0
    file=$1
fi

if [ -z "$file" ] 
then
    write_log ERR "usage $0 backup.tar.gz"
    exit 355
fi

rm -rf $ROOT/tmp/backup_extract
mkdir $ROOT/tmp/backup_extract
cd $ROOT/tmp/backup_extract

if [ "x$ssh" == "x0" ]
then
  if [ ! -f $file ]
  then
    write_log ERR "le premiere parametres du shell doit etre le fichier"
    exit 1
  fi
  tar xvf $file
  test_rc $?
else
  scp $1 $ROOT/tmp/
  test_rc $?
  tar xvf $ROOT/tmp/`basename $file`
  test_rc $?
  rm $ROOT/tmp/`basename $file`
fi

TMPDIR=$ROOT/tmp

# Coupure de l'instance
write_log INF "Coupure de l'instance LDAP $ENV"
$ROOT/shell/exploit.sh stop
test_rc $?

# Suppression des datafile
write_log INF "Suppression des datafile"
rm -r $ROOT/ldap-datafile/*

write_log INF "suppression des schema"
rm -rf $ROOT/config/slapd.d/cn\=config/cn\=schema/*

write_log INF "suppression des bases"
rm $ROOT/config/slapd.d/cn\=config/olcDatabase* 

write_log INF "suppression des backend"
rm $ROOT/config/slapd.d/cn=\config/olcBackend*

write_log INF "suppression des modules"
rm $ROOT/config/slapd.d/cn\=config/cn\=module*

# Recupeartion de la configuration distante
CONFIG=$ROOT/tmp/backup_extract/config.ldif
write_log INF "Dump de la config dans $CONFIG"
test_rc $?

cd $TMPDIR
csplit $CONFIG '/^$/' '{*}' 2>/dev/null >/dev/null
for file in `ls xx*`
do
  newname=`head $file | sed -e "2q" -e "1d" | sed "s/^dn: //"`
  echo $newname | grep -q "="
  RC=$?
  if [ "x$RC" == "x0" ]
  then
    mv $file $newname
  fi
done 
rm $CONFIG

write_log INF "Insersion des modules"
for file in `ls cn\=module*,cn\=config`
do
  write_log INF "  -> chargement du fichier $file"
  slapadd -n 0 -F $ROOT/config/slapd.d < $file
  test_rc $?
done

write_log INF "Insersion des Backend"
for file in `ls olcBackend*,cn\=config`
do
  write_log INF "  -> chargement du fichier $file"
  slapadd -n 0 -F $ROOT/config/slapd.d < $file
  test_rc $?
done

write_log INF "Insersion des schemas"
for file in `ls *,cn\=schema\,cn\=config`
do
  write_log INF "  -> chargement du fichier $file"
  slapadd -n 0 -F $ROOT/config/slapd.d < $file
  test_rc $?
done

write_log INF "Insersion des bases techniques"
# on ignore la base frontend
rm olcDatabase\=\{-1\}frontend\,cn\=config
write_log INF "  -> chargement du fichier olcDatabase\=\{0\}config\,cn\=config"
slapadd -n 0 -F $ROOT/config/slapd.d < olcDatabase\=\{0\}config\,cn\=config
rm olcDatabase\=\{0\}config\,cn\=config

# Retablissement des droits 
write_log INF "Retablissement des droits"
chown -R $USER:$GROUP $ROOT/config
test_rc $?

# Lancement de l'instance
write_log INF "Lancement de l'instance LDAP $ENV"
$ROOT/shell/exploit.sh start
test_rc $?

# on change le root dans la base
sed -i "s@olcDbDirectory:.*@olcDbDirectory: $ROOT/ldap-datafile@" olcDatabase\=\{1\}hdb\,cn\=config
# on change le root dans la base accesslog
sed -i "s@olcDbDirectory:.*@olcDbDirectory: $ROOT/ldap-accesslog@" olcDatabase\=\{3\}hdb\,cn\=config
for file in `ls olcDatabase*,cn\=config`
do
  write_log INF "  -> chargement du fichier $file"
  sed -i "/entryCSN/d" $file
  sed -i "/modifiersName/d" $file
  sed -i "/modifyTimestamp/d" $file
  sed -i "/entryUUID/d" $file
  sed -i "/structuralObjectClass/d" $file
  sed -i "/creatorsName/d" $file
  sed -i "/createTimestamp/d" $file
  ldapadd -Y EXTERNAL -H "ldapi://%2Fmnt%2F$ENV%2Frun%2Fldapi" -f $file
  test_rc $?
done

write_log INF "Coupure de l'instance LDAP $ENV"
$ROOT/shell/exploit.sh stop
test_rc $?
sleep 20

write_log INF "Initialisation de la base"
cp $ROOT/tmp/backup_extract/* $ROOT/ldap-datafile/
RC=$?
write_log INF "RC=$RC"

# Construction des index
#write_log INF "Construction des index"
#slapindex -F $ROOT/config/slapd.d
#RC=$?
#write_log INF "RC=$RC"

# Retablissement des droits 
write_log INF "Retablissement des droits"
chown -R $USER:$GROUP $ROOT/config
test_rc $?
chown -R $USER:$GROUP $ROOT/ldap-datafile
test_rc $?
chown -R $USER:$GROUP $ROOT/ldap-accesslog
test_rc $?

# Lancement de l'instance
write_log INF "Lancement de l'instance LDAP $ENV"
$ROOT/shell/exploit.sh start
test_rc $?

rm -rf $TMPDIR/*
exit 0

 

 

 

 

 

  • Aucune étiquette