[[PageOutline(2-5,Índice)]] = Sincronización de imágenes con Btrfs o ext4 = == Introducción == Hasta ahora Opengnsys permite crear un archivo imagen de una partición completa que luego puede clonarse en otra. Estas imágenes hay que tratarlas como un todo y no permiten ver su contenido. Con la sincronización de imágenes pretendemos: * comparar la imagen con el contenido de la partición y sólo copiar o borrar los archivos que difieran. * comparar la imagen con el contenido de la partición y crear una imagen diferencial con los archivos que difieran y la información de los archivos que sobran, de forma que al restaurar primero la imagen completa y luego la diferencial la partición destino quede como la del equipo modelo. La sincronización de imágenes se introducirá en la versión 1.0.5 en modo de prueba. Tenemos dos aproximaciones diferentes que denominamos "tipo directorio" y "tipo archivo" la diferencia principal es que la versión 1ª guarda los datos de las imágenes en un directorio del servidor y la versión 2ª lo empaqueta en un archivo que contiene un sistema de ficheros, según el kernel del cliente de OpenGnsys será ext4 o btrfs. Estos sistemas de ficheros son de lectura y escritura, por lo que nos permite modificar la imagen una vez creada. Además el btrfs permite montarlo en modo comprimido, de forma que la compresión y descompresión se realiza de modo transparente para el usuario. En esta página vamos a documentar los procedimientos que se utilizan en la versión tipo archivo, con los comandos del sistema operativo. Si se van a hacer pruebas es mejor instalar la versión 1.0.5 o 1.0.6 para utilizar las funciones y los script del proyecto. '''Procedimiento''' __Creamos imágenes (en cache o repo).__ * Creamos un archivo vacío, lo montamos en modo loop y creamos dentro de él un sistema de ficheros. * Montamos el sistema de fichero y clonamos dentro con los datos de la partición sincronizándolos con rsync. * Para windows crearemos un backup de las ACL con ntfs-3g.secaudit __Restauramos imágenes.__ * Montamos la imagen (en cache o repo) * Utilizaremos rsync para sincronizar la partición. * Para windows restauraremos las ACL con ntfs-3g.secaudit La partición puede estar vacía o haber sido restaurada y luego modificada por el uso. En el servidor puedo montar la imagen y modificar, borrar o añadir los archivos que queramos. '''Problemas conocidos.''' Al crear la imagen en el servidor hay veces que no se monta bien, la sincronización se realiza sobre el directorio de montaje y la imagen queda vacía. Al restaurar se monta la imagen sobre el directorio y no tiene datos. Es muy importante comprobar el contenido de la imagen. Al restaurar la cache no se pueden mostrar log, si ponemos esta opción a rsync se cuelga el equipo. Esto pasaba con las imágenes en squash, no se ha vuelto a probar con las que son en ext4 o btrfs. Al crear la imagen se hace una estimación del tamaño de los datos para crear el archivo vacío inicial, al terminar se reduce hasta el tamaño real que ocupan los datos. Esto funciona bien en ext4, pero en btrfs no se puede hacer porque el comando que trae la distribución da error muy a menudo. La transferencia de la imagen con formato ext4 y btrfs a través de la red ha ido bien con multicast, unicast y rsync. No se ha probado con torrent. == Crear una imagen tipo ext4 o btrfs == La imagen será un archivo con un sistema de fichero que contenga los datos de la partición. __Creamos el archivo vacío__ Podemos utilizar los comandos dd o truncate, dd tarda bastante y truncate es inmediato: {{{ dd if=/dev/zero of=$IMGFILE bs=1024 count=$SIZEREQUIRED }}} o: {{{ truncate --size=">$SIZEREQUIRED"k "$IMGFILE" }}} IMGFILE: nombre archivo imagen.\\ SIZEREQUIRED: tamaño de la imagen en kilobytes. __Creamos el sistema de ficheros__ Detectamos cual es el kernel del cliente para elegir el sistema de ficheros a utilizar. Si es menor que 3.7 usamos ext4, si es mayor o igual btrfs: {{{ KERNEL=$(file $BASEDIR/tftpboot/ogclient/ogvmlinuz |awk -F . '{print $2}') [ $KERNEL -lt 7 ] && IMGFS="EXT4" || IMGFS="BTRFS" }}} Utilizamos el comando mkfs del fs elegido: {{{ LOOPDEVICE=$(losetup -f) if [ "$IMGFS" == "EXT4" ]; then mkfs.ext4 -i 4096 -b 4096 -L "${2##*\/}" $LOOPDEVICE 2>&1 |tee -a $OGLOGCOMMAND else mkfs.btrfs -L "${2##*\/}" $LOOPDEVICE 2>&1 | tee -a $OGLOGCOMMAND fi }}} Para guardar la información de la imagen (como tenemos en partclone: tipo de sistema operativo, tamaño, archivos de que contiene, ...) necesitaremos incluir uno o varios archivos en el sistema de fichero original antes de realizar la creación. __Sincronización imagen__ Montamos la imagen y la partición que queremos clonar y sincronizamos tomando como origen la partición. 1) Montamos la imagen. En el servidor: {{{ LOOPDEVICE=$(losetup -f) if [ $IMGFS == "EXT4" ]; then mount $OPTMOUNT -t ext4 $1 $2 else mount $OPTMOUNT -o compress=lzo "$1" "$2" fi }}} OPTMOUNT: ro cuando restauramos, vacío al crearla, ya que por defecto es de lectura y escritura. 2) Montamos la partición, en el cliente: {{{ ogMount 1 X }}} 3) Creamos la lista del contenido. {{{ mkdir /tmp/vacio rsync -aHvn --delete /mnt/sdaX/ /tmp/vacio > /tmp/ogimg.lista }}} 4) Sólo para windows: creamos la lista de acl: {{{ # Desmontamos la particion ogUnmount 1 X # Guardamos las ACL: ntfs-3g.secaudit -b /dev/sdaX / > /tmp/ogimg.acl # Montamos la partición para seguir el proceso. ogMount 1 X }}} 5) Sincronizamos la imagen desde la partición. {{{ rsync -aHAX$OPTRSYNC --inplace --delete /mnt/sdaX/ "$DIRMOUNT" # Guardamos la lista del contenido y las acl si existen: rsync -aHAX$OPTRSYNC --inplace /tmp/ogimg.* "$DIRMOUNT" }}} 6) Desmontamos la imagen. En el servidor: {{{ umount /opt/opengnsys/images/mount/$IMGNAME }}} Importante: Es mejor utilizar el servicio de rsync en el servidor ya que cuando utilizamos rsync sobre samba va peor, la transferencia es más lenta. Este tema excede el objeto de está documentación. == Redimensionar imagen == Cuando se crea una imagen por segunda vez puede ser necesario que el tamaño sea mayor. Se creará exactamente como la primera vez salvo que en vez de crear el archivo de imagen y su sistema de fichero los redimensiono. 1) Redimiensiono el archivo {{{ truncate --size=">$NEWSIZEREQUIRED"k "$IMGFILE" }}} 2) Redimiensiono el sistema de ficheros {{{ LOOPDEVICE=$(losetup -f) if [ $IMGFS == "EXT4" ]; then losetup $LOOPDEVICE "$IMGNAME.img" resize2fs -f $LOOPDEVICE &> $REPOLOG else mount -o compress=lzo "$IMGNAME.img" "$DIRMOUNT" btrfs filesystem resize max "$DIRMOUNT" 2>&1 > $REPOLOG fi }}} == Restaurar - Sincronizar una imagen tipo ext4 o btrfs == La imagen puede estar en la cache o en repo. 1) Montamos la imagen, por ejemplo en el servidor {{{ # Creamos el punto de montaje: mkdir /opt/opengnsy/images/mount/$IMGNAME # Montamos la imagen: if [ $IMGFS == "EXT4" ]; then mount -o ro -t ext4 $IMGNAME.img /opt/opengnsy/images/mount/$IMGNAME else mount -o ro,compress=lzo "$IMGNAME.img" "/opt/opengnsy/images/mount/$IMGNAME" fi }}} 2) Montamos la partición, en el cliente {{{ ogMount 1 X }}} 3) Sincronizamos la partición tomando como origen la imagen La partición puede estar vacía o haber sido restaurada con anterioridad y sólo hay que restaurar las modificaciones que haya hecho por el uso. {{{ rsync -aHAXq$OPTRSYNC --password-file=/passrsync opengnsys@$REPOIP::ogimages/mount/$IMGNAME /mnt/sdaX }}} 4) Sólo para windows restauramos las ACL {{{ # Copiamos las acl a /tmp cp //mnt/sdaX/ogimg.acl /tmp # Desmontamos la partición: ogUnmount 1 X # Restauramos las acl: ntfs-3g.secaudit -se /dev/sdaX /tmp/ogimg.acl }}} 5) Desmontamos la imagen {{{ { umount /opt/opengnsys/images/mount/$IMGNAME }}} == Opciones rsync == / la barra en el directorio de origen hace que transfiera el contenido del directorio al directorio destino (si no la ponemos copia también el directorio) -a, --archive modo archivo: igual que -rlptgoD (no -H,-A,-X) conserva los enlaces simbólicos, dispositivos, permisos y propietario. -q –quiet: no muestra mensajes que no sean errores. Si no se pone a veces se cuelga el equipo. --delete Borra los ficheros que no existían en el original. Si no lo ponemos actualizará los existentes en el origen y no tocará los nuevos. -A preserva ACLs -X preserva atributos extendidos (como los de Selinux) -H preserva enlaces “duros” -n realiza la prueba pero no hace cambios, nos sirve para crear el listado. -z, --compress Comprime el fichero en la transferencia. Puede convenir o no dependiendo de dos factores: la capacidad de cálculo de ambos equipos para comprimir/descomprimir y el ancho de banda de la red (opcional). No utilizamos: -v, --verbose : Muestra todos los archivos que se van copiando) → cuelga el equipo. --progress: muestra los archivos y el progreso → cuelga el equipo. -g preserva grupo (incluido en a) -o preserva propietario (incluido en a) == Crear una imagen diferencial == '''Definición de imagen diferencial: ''' Supongamos que tenemos una imagen completa y la hemos restaurado en un equipo que hará de modelo. Instalamos una serie de programas. Llamaremos imagen diferencial de una completa a la que contengan los archivos nuevos y la información de los archivos que sobran, de forma que al restaurar primero la imagen completa y luego la diferencial la partición destino quede como la del equipo modelo. '''Procedimiento''' Se monta la imagen completa y se compara el contenido de la partición con la imagen: se crea la lista de las diferencias con rsync {{{ # Montamos imagen completa (con la que vamos a comparar) if [ $IMGFS == "EXT4" ]; then mount -o ro -t ext4 $IMGNAME.img /opt/opengnsy/images/mount/$IMGNAME else mount -o ro,compress=lzo "$IMGNAME.img" "/opt/opengnsy/images/mount/$IMGNAME" fi # Creamos las diferencias rsync -aHvn --delete /mnt/sda2/ /opt/opengnsy/images/mount/$IMGNAME > /tmp/ogimg.lista }}} Se trata la lista de diferencias: se separan los archivos a copiar, a borrar y los enlaces (simbólicos o no), ya que se tendrán que procesar de forma diferente al restaurar {{{ # Eliminamos comentarios de rsync y el directorio raíz. sed -i -e s/"^sent.*.bytes\/sec"//g -e s/^total.*.speedup.*.$//g -e s/"sending.*.list"//g /tmp/ogimg.lista sed -i '/^\.\//d' $IMGINFO grep -e '\->' -e '\=>' lista_img > /tmp/ogimg.ln grep -e ^deleting lista_img | sed s/^deleting\ //g > /tmp/ogimg.rm grep -v -e '\->' -e '\=>' -e ^deleting -e ^created lista_img > /tmp/ogimg.info }}} En caso de windows se genera el fichero de acl de la partición y se extraen las que corresponden a los ficheros que contiene la diferencial. Es un proceso que tarda mucho pero que nos ahorra tiempo cuando restauramos. Creamos la lista de acl completa: {{{ # Desmontamos la particion ogUnmount 1 X # Guardamos las ACL: ntfs-3g.secaudit -b /dev/sdaX / > /tmp/ogimg.acl }}} Filtramos la lista de acl, extrayendo las de los ficheros que contiene la diferencial: {{{ # Al fichero le quitamos las líneas sobrantes: comentarios y lineas vacías. sed -e s/"^#.*$"//g /tmp/ogimg.info > $FILES sed -i '/^$/d' $FILES touch $ACLTMP # Recorremos el listado y extraemos la acl correspondiente al fichero o directorio. while read LINE; do read END INI <<< "$(grep -n -e "File" -e "Directory" $IMGACL| grep -A 1 "$LINE"| awk -F : '!(NR%2){print $1" "p}{p=$1}' )" let NUM=$END-$INI-1 # Si algún archivo no se encuentra, el error lo mandamos a /dev/null sed -n -e $INI,+"$NUM"p /tmp/ogimg.acl 2>/dev/null | tee -a $ACLTMP > $OGLOGCOMMAND done < $FILES cp $ACLTMP /tmp/ogimg.acl }}} Se crea el archivo de imagen diferencial vacío conteniendo un sistema de archivos (igual que en la completa) {{{ # Creamos archivo vacio. dd if=/dev/zero of=$IMGFILE bs=1024 count=$SIZEREQUIRED #Detectamos cual es el kernel del cliente para elegir el sistema de ficheros a utilizar. KERNEL=$(file $BASEDIR/tftpboot/ogclient/ogvmlinuz |awk -F . '{print $2}') [ $KERNEL -lt 7 ] && IMGFS="EXT4" || IMGFS="BTRFS" # Creamos el sistema de ficheros: LOOPDEVICE=$(losetup -f) if [ $IMGFS == "EXT4" ]; then losetup $LOOPDEVICE "$IMGNAME.img" resize2fs -f $LOOPDEVICE &> $REPOLOG else mount -o compress=lzo "$IMGNAME.img" "$DIRMOUNT" btrfs filesystem resize max "$DIRMOUNT" 2>&1 > $REPOLOG fi }}} Se sincroniza de la partición a la imagen diferencial pasando a rsync la lista de archivo que debe copiar. {{{ # Se monta la imagen diferencial (si es btrfs ya está montada en el paso anterior.) [ $IMGFS == "EXT4" ] && mount $OPTMOUNT -t ext4 "$IMGNAME.img.diff" "$DIRMOUNT" # Se sincroniza. rsync -aHq --files-from=/tmp/ogimg.info /mnt/sda2/ "$DIRMOUNT" # Se guardan los ficheros de información en la imagen. rsync -aHAX$OPTRSYNC --inplace /tmp/ogimg.* "$DIRMOUNT" }}} == Restaurar - Sincronizar una imagen diferencial == Tras restaurar la imagen completa, la restauración de la imagen diferencial hará lo siguiente: Montará la partición destino y la imagen diferencial {{{ ogMount 1 X mount $OGCAC$OGIM/$IMGNAME.img.diff "$DIRMOUNT" }}} Con rsync copiará los archivos incluidos en la lista de la diferencial (Es más rápido que si se le permite que compare el contenido de la imagen con la partición). {{{ # Copiamos los archivos de información a la partición destino: rm /tmp/ogimg.* $DEST cp $DIRMOUNT/ogimg.* $DEST rsync -aHq –files-from=$DEST/ogimg.info "$DIRMOUNT"/ /mnt/sdaX }}} Borrará los archivos sobrantes, con la información de la lista para borrar: {{{ # "Diferencial: creando enlaces y borrando" cd /mnt/sdaX cat "$DIRMOUNT/ogimg.rm" 2>/dev/null | xargs rm -rf }}} Creará o modificamos los enlaces, con la información de la lista de enlaces {{{ # La imagen diferencial tiene ogimg.ln # para la completa lo generamos con los enlaces que contengan /mnt/ [ -r "$DEST/ogimg.ln" ] || grep -e "->" -e "=>" "$DEST/ogimg.info"|grep "/mnt/" > "$DEST/ogimg.ln " if [ $(wc -l "$DEST/ogimg.ln"|cut -f1 -d" ") -ne 0 ]; then while read LINEA do ORIGLN="${LINEA#*> }" # Si origen hace referencia a la particion lo modificamos echo $ORIGLN|grep "/mnt/"> /dev/null && ORIGLN="$DEST/${ORIGLN#/mnt/*/}" # rsync marca - los enlaces simbolicos y = enlaces "duros" LINEA="${LINEA%>*}" TYPELN="${LINEA##* }" DESTLN="${LINEA% *}" if [ "$TYPELN" == "-" ] then OPTLN='-s' else OPTLN='' fi cd "$DEST/$(dirname "$DESTLN")" rm "$(basename "$DESTLN")" ln $OPTLN "$ORIGLN" "$(basename "$DESTLN")" echo -n "." done < "$DEST/ogimg.ln" 2>/dev/null echo "" fi }}} En caso de windows restauramos las acl, exactamente igual que en la completa: {{{ # Copiamos las acl a /tmp cp /mnt/sdaX/ogimg.acl /tmp # Desmontamos la partición: ogUnmount 1 X # Restauramos las acl: ntfs-3g.secaudit -se /dev/sdaX /tmp/ogimg.acl }}} == Transformando una imagen de partclone en sqfs == Partimos de una imagen de partclone comprimida, la transformamos en una que se pueda montar. Se restaura la imagen en un fichero (dos opciones según el compresor): {{{ cat Imagen.img.gz | gzip -d -c | partclone.restore -C -s - -O imgMontable.img lzop -dc Ubuntu11.img | partclone.restore -C -s - -O ubuntu11Montar.img }}} Montando la imagen del partclone: {{{ mkdir montar mount -o loop ubuntuMontar.img montar/ mount.ntfs-3g -o loop w7BasicaMontar.img montar/ }}} Para la imagen sincronizable creamos el archivo de la imagen vacio y generamos dentro un sistema de ficheros: {{{ # Creamos archivo vacío. dd if=/dev/zero of=$IMGFILE bs=1024 count=$SIZEREQUIRED #Detectamos cual es el kernel del cliente para elegir el sistema de ficheros a utilizar. KERNEL=$(file $BASEDIR/tftpboot/ogclient/ogvmlinuz |awk -F . '{print $2}') [ $KERNEL -lt 7 ] && IMGFS="EXT4" || IMGFS="BTRFS" # Creamos el sistema de ficheros y lo montamos: LOOPDEVICE=$(losetup -f) if [ $IMGFS == "EXT4" ]; then losetup $LOOPDEVICE "$IMGNAME.img" resize2fs -f $LOOPDEVICE &> $REPOLOG mount -o ro -t ext4 $IMGNAME.img "$DIRMOUNT" else mount -o compress=lzo "$IMGNAME.img" "$DIRMOUNT" btrfs filesystem resize max "$DIRMOUNT" 2>&1 > $REPOLOG fi }}} Sincronizamos la imagen nueva desde la del partclone {{{ rsync -aHAX montar/ "$DIRMOUNT" }}}