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:
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).
__Restauramos imágenes.
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.
La imagen será un archivo con un sistema de fichero que contenga los datos de la partición.
__Creamos el archivo vací
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
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
Montamos la imagen y la partición que queremos clonar y sincronizamos tomando como origen la partición.
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.
ogMount 1 X
mkdir /tmp/vacio
rsync -aHvn --delete /mnt/sdaX/ /tmp/vacio > /tmp/ogimg.lista
# 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
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"
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.
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.
truncate --size=">$NEWSIZEREQUIRED"k "$IMGFILE"
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
La imagen puede estar en la cache o en repo.
# 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
ogMount 1 X
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
# 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
{
umount /opt/opengnsys/images/mount/$IMGNAME
/ 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)
*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"
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
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"