Sincronizar archivos y directorios entre dos máquinas de una red con RSYNC

0
1548

Una de las actividades más críticas y quizás complejas en el área de administración de servidores, es el respaldo de su contenido y/o información, el cual requiere ser precisa y automatizada de manera que se garantice la continuidad de los servicios, donde rsync es una de las herramientas más usadas.

Rsync es una poderosa herramienta que permite sincronizar los contenidos de dos diferentes ubicaciones, tanto locales como remotas. Se considera como el reemplazo de rcp, ya que permite realizar copias mediante una conexión encriptada, tiene su propio algoritmo que verifica el contenido del archivo y en caso de cambios, envía sólo la parte modificada, facilita la administración de respaldos y está liberado bajo la GNU GPL.

El proceso de copiado es sumamente rápido, sin embargo, se debe notar que el consumo de recursos, tanto en memoria como procesador, puede ser muy alto, especialmente cuando se levantan múltiples solicitudes por parte de los usuarios a través de ssh.

Este es un proyecto auspiciado por Samba.org y se encuentra presente en múltiples sabores de Unix, incluyendo Linux, Mac OS y Solaris; de hecho, existe un procedimiento, vía Cywin, para instalarlo en Windows, tutorial que se verá en otra ocasión.

Esta herramienta tiene la particularidad de poderse ejecutar tanto como cliente – servidor o invocarlo en el cliente para realizar la copia en el destino. Estas y otras formas de su utilización será tratados brevemente posteriormente

Descarga e instalación.

En el caso que el equipo no tenga rsync, se puede descargar del sitio del proyecto. En http://rsync.samba.org/ftp/rsync/ se encuentra el código fuente, mientras que en http://rsync.samba.org/ftp/rsync/binaries/ se pueden obtener binarios para diferentes sistemas operativos, como Linux (Red Hat, Debian, PPC), Solaris (Sparc e Intel), AIX, IRIX, SCO y algunos más.

De acuerdo a la plataforma será el procedimiento de instalación. En el caso de usar RPM (Red Hat), el comando sería:

# rpm -Uvh rsync-2.X.X.i386.rpm

Para Solaris, sólo se debe extraer los contenidos del TARBALL y colocar el binario en la ubicación que el sistema requiera.

Compilación del código fuente.

Se deberá descargar y descompactar el TARBALL, nos deja una carpeta a donde entramos para realizar este proceso:

# cd rsync-2.5.5
$ ./configure
$ make
# make install (este paso lo debe realizar root)

En caso que queramos cambiar los parámetros de configuración, lo podemos hacer desde ./configure [opciones], se recomienda usar ./configure –help para ver las opciones disponibles.

Funciones principales de rsync.

  • Copiar archivos localmente.
  • Copiar archivos locales a un equipo remoto, usando un programa de shell como transporte.
  • Copiar archivos remotos al equipo local, usando un programa de shell como transporte.
  • Copiar archivos remotos de un servidor remoto de rsync al equipo local.
  • Copiar archivos locales a un servidor remoto de rsync.
  • Copiar archivos remotos de un servidor de rsync al equipo local, usando un programa de shell como transporte.
  • Listar archivos de un servidor remoto.

Notemos que en la mayoría de los casos se involucra el equipo local y uno remoto. En ninguna circunstancia pueden ser dos equipos remotos.

Sintaxis y comandos.

Su formato básico es:

# rsync [opciones] [origen] [destino]

Algunos de sus comandos más comunes son:

-v, –verbose incrementa los mensajes
-q, –quiet elimina los mensajes
-c, –checksum verifica los tamaños de los archivos enviados (lento).
-a, –archive respalda incrementalmente los archivos (no elimina los originales).
-r, –recursive recursivo entre los directorios.
-R, –relative utiliza rutas relativas.
-u, –update sólo actualiza los archivos (no elimina los originales).
-t, –times mantiene las horas de modificación.
-n, –dry-run muestra lo que será trasnferido.
-W, –whole-file copia los archivos completos, no sólo las partes modificadas (lento).
-I, –ignore-times Copia archivos con diferencia de horas, aunque sean del mismo tamaño.
–existing sólo actualiza archivos que ya existen.
–delete elimina archivos que no existen en el receptor.
–delete-after elimina después de copiar, no antes.
–force force elimina carpetas aunque no estén vacias.
-c, –checksum verifica los tamaños de los archivos enviados (lento).
–size-only sólo compara el tamaño para decidir el envío.
–progress muestra el progreso durante la transferencia.
-z, –compress comprime el archivo al enviarlo (deben soportarlo el cliente y el servidor).
–exclude=NOMBRE excluye archivos con dicho nombre o extensión. Se pueden usar comodines.
-e, –rsh=COMANDO especifica el comando que reemplaza a rsh. Usualmente es ssh.
–daemon inicia el demonio de rsync.
–server inicia el servidor de rsync.
–password-file=ARCHIVO obtiene la contraseña de un archivo.
–version muestra la versión de rsync.

Se recomienda ejecutar rsync –help para ver todas las opciones disponibles.

Respaldos en un mismo equipo.

Supongamos que tenemos una partición o un disco duro extra, donde colocamos un respaldo de nuestra información, pudiendo usar rsync para sincronizar sus contenidos, con esta sencilla instrucción:

# rsync -avz --recursive /ruta/carpetaorigen/ /ruta/carpetadestino/

Dado que es en el mismo disco duro, no necesitamos definir un medio de transporte ni se solicita una contraseña.

Respaldos usando un programa de shell.

Esta es la forma más sencilla de utilizarlo, ya que en caso de tenerlo instalado en ambos equipos, sólo es necesario invocar a rsync y pasarle los parámetros necesarios.

En este primer caso, haremos un envío de un archivo local al servidor de respaldos usando ssh como medio de transporte.

# rsync -avz --rsh=/usr/bin/ssh archivo.txt usuario@10.1.1.45:/alguna/carpeta

En este caso tenemos que el archivo.txt es copiado a la carpeta de destino en el servidor que indicamos; cada vez que se conecte, nos solicitará la contraseña correspondiente al usuario que declaramos. Debemos tener permisos de escritura en la carpeta de destino para que pueda funcionar. Una variación del mismo ejercicio, pero usando el nombre de dominio del servidor, es:

# rsync -avz --rsh=/usr/bin/ssh archivo.txt usuario@respaldos.servidor.com:/alguna/carpeta

Por otro lado podemos hacer una copia recursiva de una carpeta.

# rsync -avz --rsh=/usr/bin/ssh --recursive /home/usuario/carpetaoriginal/  
usuario@10.1.1.45:/alguna/carpeta

La diagonal al final de la carpeta de origen es muy importante. Supongamos que hacemos esta pequeña variación, incluyendo un comodín.

# rsync -avz --rsh=/usr/bin/ssh --recursive /home/usuario/carpetaoriginal/*  
usuario@10.1.1.45:/alguna/carpeta/*

La diferencia radica en que en el primer caso, la carpeta de origen se copia con todo su contenido, mientras que en el segundo, se copia el contenido dentro de la carpeta de destino directamente.

En un momento dado, para excluir ciertos archivos, digamos los arhivos .bak, se realiza así:

# rsync -avz --rsh=/usr/bin/ssh --recursive --exclude "*bak" 
/home/usuario/carpetaoriginal/ usuario@10.1.1.45:/alguna/carpeta/

En todos estos casos, los archivos son guardados con el propietario y los permisos del usuario que realiza el respaldo, pero si deseamos mantener sus características originales, podemos adicionar estos parámetros.

# rsync -avz --rsh=/usr/bin/ssh --recursive --exclude "*bak" --perms  --owner --group
/home/usuario/carpetaoriginal/ usuario@10.1.1.45:/alguna/carpeta/

En este caso no es necesario que existan los usuarios, propietarios de los archivos, en el sistema.

Si deseamos recuperar un respaldo, es decir, del servidor remoto a nuestro equipo, sería con esta instrucción.

# rsync -avz --rsh=/usr/bin/ssh --recursive usuario@10.1.1.45:/alguna/carpetaorigen/ 
/home/usuario/carpetadestino/*

Para solicitar la lista de los archivos en una carpeta remota, se hace de forma muy similar al ejercicio anterior, pero sin definir el destino.

# rsync -avz --rsh=/usr/bin/ssh --recursive usuario@10.1.1.45:/alguna/carpetaorigen/

Scripts automatizados.

A continuación presentaremos dos scripts que pueden realizar el proceso de copia y, con una buena parametrización, realizarla de forma automática mediante cron.

Primeramente tenemos uno genérico, ejecutable en la mayoría de los Unix.

#############################
#!/bin/bash

# Simple rsync "driver" script. (Uses SSH as the transport layer.)
# http://www.scrounge.org/linux/rsync.html

# Modificado y traducido al español por Crowley (http://www.mexicoextremo.com.mx)
# Debe poder trabajar con Linux y otros Unix, incluyendo Mac OS

# Sincroniza dos carpetas con sólo ejecutarlo. Sólo necesita cambiar los
# parámetros para tenerlo funcionando

# Nombre o IP de la máquina de destino
DEST="respaldos.servidor.com"

# Usuario que se conectará al servidor
# Puede ser root, pero no se recomienda
USER="root"

# Directorio de origen
BACKDIR="/carpeta/del/usuario/"

# Directorio de destino (remoto)
DESTDIR="/carpeta/de/destino/"

# Archivo de exclusiones. Contiene comodines de los archivos a excluir
# por ejemplo, *~, *.bak, etc. Una especificación por línea.
# Se debe crear este archivo y descomentar la línea. Opcional
# EXCLUDES=/root/bin/excludes

# Opciones de prueba. Despliega las acciones, pero no las realiza.
# OPTS="-n -vv -u -a --rsh=ssh --exclude-from=$EXCLUDES --stats --progress"
# Realiza la copia, mostrando a detalle lo que hace.
OPTS="-v -u -a --rsh=ssh --exclude-from=$EXCLUDES --stats"
# Realiza la copia, pero no manda ningún mensaje.
#OPTS="--archive --update --rsh=ssh --exclude-from=$EXCLUDES --quiet"

# Variables de ambiente, en caso de necesitarlas cron
export PATH=$PATH:/bin:/usr/bin:/usr/local/bin

# Se ejecuta sólo si el $DEST responde.
VAR=`ping -s 1 -c 1 $DEST > /dev/null; echo $?`
if [ $VAR -eq 0 ]; then

rsync $OPTS $BACKDIR $USER@$DEST:$DESTDIR
else
echo "No puedo conectarme a $DEST."
fi
#############################

Por otro lado, a continuación tenemos uno más, creado expresamente para Mac OS X, cortesía de Mike Bombich.

#############################
#!/bin/tcsh

# image-me.sh, Copyright 2002, Mike Bombich
# This script handles the self-imaging process. This is intended
# to replace the functionality of the revrdist prefs file.
# This is the script that you will modify to customize how this
# particular computer is imaged. The customizable options are "syncDirs"
# and "args".
# This script can be run from the cron whenever.

## Indicate the directories that should be synchronized
# Encode the spaces with "%space"
#set syncDirs = (.hidden Applications Applications%space(Mac%spaceOS%space9)
# System System%spaceFolder Library usr bin sbin mach_kernel private)
set syncDirs = ( Applications )

# Determine if script was run by root
set user = `whoami`
if ( $user != root ) then
echo "You must run this script as root, else you may not have privileges"
echo "to properly restore all files."
exit 1
endif


## Setup the argument components
set masterDir = "/Volumes/imacnroll/MacOSX/MasterBase"
set rsync = "/usr/bin/rsync"
set ssh = "--rsh=/usr/bin/ssh"
set recursive = "--recursive"
set preserve = "--times -og --links"
set prog = "--progress"
set stats = "--stats"
set delete = "--delete"
set remoteUser = "admin"
set server = "imacnroll"

## Assemble the arguments
#set args = ($prog $stats $ssh $recursive $preserve $delete)
set args = ($prog $stats $ssh $recursive $preserve)

# Synch the directories one at a time
foreach dir ($syncDirs)
set theDir = `echo $dir | sed 's/%space/ /g'`
$rsync $args ${remoteUser}@${server}:${masterDir}/${theDir}/ /${theDir}/

# # Repair any custom folder icon flags if Dev tools present
# if (-e /Developer/Tools/SetFile) then
# set iconFiles = `find $targetDir -name "Icon?" | tr -d 'r' | sed 's/ /%space/g'`
#
# foreach icon ($iconFiles)
# set dcIcon = "`echo "$icon" | sed 's/%space/ /g'`"
# /Developer/Tools/SetFile -a C "$dcIcon:h"
# end
# endif

end
#############################

Respaldos usando un servidor de rsync.

En todos los casos anteriores, salvo que nos conectemos a una cuenta sin contraseña, siempre se nos solicita que nos firmemos para poder tener acceso; sin embargo, ese paso es un problema si deseamos automatizar los envíos mediante cron. Esto se puede resolver mediante la configuración del servidor de respaldos como uno de rsync. Dado que esto puede ser un poco más complicado que lo visto anteriormente, analizaremos algunos elementos paso a paso.

1. Siendo que utilizamos encriptación fuerte para autenticar a los usuarios, es necesario crear las llaves dsa y rsa para cada cliente.

# ssh-keygen -t dsa -C "Llave dsa de usuario en servidor"
# ssh-keygen -t rsa -C "Llave rsa de usuario en servidor"

Se recomienda que cada usuario defina un comentario que determine su username y el servidor de origen, ya que en caso contrario, al tener demasiadas llaves almacenadas, se prestará a confusiones. Se deben de ubicar en la carpeta ~/.ssh/ (nótese que es una carpeta oculta). Este proceso genera dos archivos por cada llave, uno que contiene la llave privada y el otro, la llave pública (con extensión .pub).

Pueden dejarse sin contraseña, de manera que se accedan más rápidamente; sin embargo, por seguridad se recomienda ponerla.

2. Copiar el contenido las llaves públicas al archivo ~/.ssh/authorized_keys en el servidor de rsync, de manera que se puedan leer al realizar la conexión. Primero creamos el archivo, porque no existe en un inicio.

# touch  ~/.ssh/authorized_keys

Después, se debe copiar el contenido de los archivos .pub, uno por cada línea, a este archivo, de manera que se tenga una lista de conexiones autorizadas.

vi ~/.ssh/authorized_keys

Esto se debe realizar por cada cuenta que vaya a manejar la conexión, o mejor dicho, la cuenta que tenga los permisos necesarios para realizar el respaldo, no necesariamente root.

En principio, el servidor debe tener todas las llaves y los clientes sólo la suya.

3. Editar el sshd.conf en el servidor para habilitar la autenticación pública.

# pico  /etc/ssh/sshd_config (Linux)

# pico /etc/sshd_config (Mac OS X)

Buscar la siguiente línea y descomentarla:

#PubkeyAuthentication yes

4. Crear el archivo /etc/rsync.conf en el servidor de respaldos. Su configuración puede ser como esta:

#/etc/rsyncd.conf
secrets file = /etc/rsyncd.secrets
motd file = /etc/rsyncd.motd
log format = %h %o %f %l %b
log file = /var/log/rsyncd.log
max connections = 5
lock file = /var/run/rsyncd.lock
read only = no
list = yes
uid = nobody
gid = nobody

[publico]
comment = Acceso general de respaldo en el servidor
path = /home/rsync/publico

[privado]
comment = Sección privada
path = /home/rsync/privado
auth users = usuario1,usuario2
hosts allow = *.acme.com 10.1.1.0/255.255.255.0 200.54.23.75/250
hosts deny = *
list = false

Dada su importancia, desglosaremos brevemente su estructura.

El archivo consta de una sección general y una por cada módulo compartido. Los primeros afectan a todo el servicio, mientras que los segundos son especificos de cada recurso. A continuación, describimos los parámetros utilizados, aunque existen otros.

secrets file es un archivo que contiene los nombres de usuario y contraseñas correspondientes. Se explica más adelante.

motd file es un saludo o identificación del servidor. Se explica más adelante.

log format y log file son complementarios. El primero define la estructura y el segundo el destino donde se alojarán los mensajes cada vez que inicie el servidor.

max connections es el máximo de conexiones simultáneas en el servidor, en caso de llegar al límite, se avisa al usuario que lo intente después. El default es cero (sin límite).

lock file es el archivo de apoyo de max connections.

read only limita a sólo lectura los recursos, poco recomendable en caso de necesitar permisos de escritura.

list permite ver el contenido de la carpeta de respaldo cuando se solicita la lista.

uid es el usuario que realiza el proceso. Por defecto es nobody, sin embargo se deberá empatar con el que tenga permisos de lectura/escritura en las carpetas de destino. Se recomienda que vaya por cada módulo, pero en este caso afecta a todo el servicio.

gid es el grupo al que pertenece el usuario que realiza el proceso. Por defecto es nobody, sin embargo se deberá empatar con el grupo del usuario que tenga permisos de lectura/escritura en las carpetas de destino. Se recomienda que vaya por cada módulo, pero en este caso afecta a todo el servicio.

La sección publico es una carpeta pública, mientras que privado es con acceso restringuido por usuario y rango de IP o dominio. A continuación veremos sus parámetros.

comment es un comentario que identifica el módulo.

path es la ruta a la carpeta.

auth users es una lista de usuarios con permisos. Van sepadados con comas.

hosts allow son los equipos con permiso de acceso. Van sepados por espacios.

hosts deny son los equipos sin acceso.

list permite listar los contenidos de la carpeta.

Se pueden crear tantos módulos como sean necesarios y modificar los permisos de acuerdo a las necesidades de cada uno.

Nota: dependiendo de la versión o la distribución de origen, es posible que el archivo se tenga que llamar rsynd.conf en vez de rsync.conf. Al momento de iniciar el servidor y no encontrar el archivo, el sistema nos lo indicará.

Un ejemplo, un poco más complejo del rsync.conf, sería:

#/etc/rsyncd.conf
motd file = /etc/rsyncd.motd
log format = %h %o %f %l %b
log file = /var/log/rsyncd.log
max connections = 5
lock file = /var/run/rsyncd.lock
read only = no
list = yes

[publico1]
comment = Acceso general de respaldo en el servidor
path = /home/rsync/publico
secrets file = /ruta1/rsyncd.secrets
uid = usuario
gid = grupo

[ftp]
comment = Servidor ftp
path = /var/ftp/pub
uid = usuario

[miacceso]
comment = Acceso publico a mi respaldo
path = /home/usuario/mirespaldo
uid = usuario

[usuario1]
comment = Sección de un usuario
path = /home/usuario1/privado
secrets file = /ruta2/rsyncd.secrets
auth users = usuario1,root
hosts allow = *.acme.com 10.1.1.0/255.255.255.0 200.54.23.10
hosts deny = *
list = true

[usuario2]
comment = Sección de otro usuario
path = /home/usuario2/privado
secrets file = /ruta3/rsyncd.secrets
uid = usuario
gid = grupo
auth users = usuario2,root
hosts allow = *.acme.com 10.1.1.0/255.255.255.0 200.54.23.80
hosts deny = *
list = true

5. Crear el archivo /etc/rsyncd.secrets en el servidor de respaldos, donde se guardan los usuarios y contraseña que ejecutan rsync, uno por línea, con el siguiente formato (cada usuario puede tener uno propio):

usuario:password

No es necesario que estos usuarios existan en el sistema, sólo es para comparar el usuario y contraseña que se manda con la residente en este documento. Debido a que se encuentra en texto plano, puede ser recomendable crear un usuario sin privilegios para que sea el que ejecute el programa. No se recomienda usar root para esta acción.

Igualmente, este archivo debe ser de sólo lectura (chmod 700) y no dar acceso al otros más que al propietario.

Muchos administradores prefieren crear un usuario y grupo rsync con el cual ejecutar todos estos procesos.

6. Crear el archivo /etc/rsyncd.motd en el servidor de respaldos, donde se guarda un mensaje de bienvenida o identificación al entrar al servidor.

7. Iniciar el servidor. Esto se hace mediante la siguiente instrucción, que además lo habilita como daemonio. Al final debe llevar un punto para asegurar que está presente el archivo de configuración.

# rsync --server --daemon .

Si necesitamos direccionar la ruta del archivo de configuración, usamos esta excepción:

# rsync --server --daemon --config=/ruta/archivo .

Es importante observar que escucha al puerto 873, por lo que deberemos parametrizar el firewall en caso necesario.

8. Configuración de inicio del servidor

8.1 Linux

a) Editar el archivo services para iniciarlo como daemon.

# pico  /etc/services

Declaramos esta línea para especificar el servicio y el puerto:

 rsync 873/tcp

b) Modificar el /etc/inetd.conf (en algunas distribuciones, este archivo ya no existe). Se debe incluir esta línea.

rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon

c) Crear el archivo /etc/rc.d/init.d/rsyncd con el siguiente script:

    #!/bin/sh
# Rsyncd This shell script takes care of starting and stopping the rsync daemon
# description: Rsync is an awesome replication tool.

# Source function library.
. /etc/rc.d/init.d/functions

[ -f /usr/bin/rsync ] || exit 0

case "$1" in
start)
action "Starting rsyncd: " /usr/bin/rsync --daemon
;;
stop)
action "Stopping rsyncd: " killall rsync
;;
*)
echo "Usage: rsyncd {start|stop}"
exit 1
esac
exit 0

8.2 Mac OS X

a) Descargar y editar un wrapper, para controlar el número de accesos de los clientes de http://www.bombich.com/mactips/rsync-wrapper.sh. sólo es necesario definir la ubicación del archivo de log. Aunque no es requisito, es recomendable.

b) Editar authorized_keys, verificando que cada llave se encuentre en sólo una línea y colocando la llamada al wrapper al inicio del documento, con una línea como la siguiente:

command="/private/etc/rsync-wrapper.sh"

Conectándose a un servidor rsync.

Una vez que ya parametrizamos el servidor, lo podemos probar para ver su funcionamiento. A diferencia de los ejecrcios anteriores, donde el servidor remoto se definía con la estructura usuario@servidor:/ruta/, en este caso será así:

# rsync -avz archivo.txt usuario@respaldos.servidor.com::modulo

Donde modulo es, valga la redundancia, el módulo declarado en rsync.conf. Basándonos en la configuración anterior, dejamos la instrucción de la siguiente manera:

# rsync -avz archivo.txt usuario@respaldos.servidor.com::publico

Al realizar la conexión y si el recurso no es estricto, como es el caso del módulo privado, no se solicitará la contraseña, sino que será leída directamente del archivo ~/.ssh/authorized_keys.

Para evitar que un módulo con autenticación solicite la contraseña, usamos el parámetro –password-file.

# rsync -avz  --password-file=rsync.secrets archivo.txt usuario@respaldos.servidor.com::privado

Recuerden que este archivo debe tener permisos 700 y pertenecerle al usuario que ejecuta el proceso.

Programar respaldos automáticos.

Ya teniendo configurando el servidor sólo es necesario configurar cron para que se ejecute regularmente el respaldo. Para esto, utilizaremos el script anteriormente mencionado, pero con algunas modificaciones.

Donde especificamos la carpeta de destino, declaramos el módulo, por ejemplo:

DESTDIR="temporal"

En las líneas de OPTS, donde se declaran las opciones, eliminamos el –rsh=ssh para que no se utilice como medio de transporte:

OPTS="-v -u -a --exclude-from=$EXCLUDES --stats"

Acto seguido, cambiamos la línea para conectarnos al servidor; nótese que se tiene ahora un doble dos puntos, valga la expresión:

rsync $OPTS $BACKDIR $USER@$DEST::$DESTDIR

Con esto, el programa está listo, ya sólo debemos crear un crontab con la ejecución del programa.

# crontab -e

Una vez en vi, definimos, por ejemplo, que se ejecute el programa a las 3:00 todos los días. Para esto, supondremos que el script se localiza en /usr/bin/respaldo.sh.

00 3 * * * /usr/bin/respaldo.sh

Eso es suficiente para que el servicio quede configurado y ejecutándose regularmente.

Interfaces gráficas de rsync.

Sync2NAS (Windows): http://sync2nas.sourceforge.net
RsyncX (Mac OS X): http://www.macosxlabs.org/rsyncx/rsyncx.html
rsback (Unix): http://www.pollux.franken.de/hjb/rsback/
rcopy (script en Perl y XML): http://sourceforge.net/projects/rcopy/

Referencias.

Rsync: http://rsync.samba.org/
Man de Rsync: http://rsync.samba.org/ftp/rsync/rsync.html
Howto and FAQ: http://sunsite.dk/info/guides/rsync/rsync-mirroring.html
Rsync tutorial: http://perso.club-internet.fr/ffaure/rsync.html
Remote Administration/Backup of Mac OS X: http://www.bombich.com/mactips/rsync.html
Back up a directory tree of files: http://www.scrounge.org/linux/rsync.html
rsyncd.conf: http://sunsite.dk/info/guides/rsync/rsyncd.conf.html

LEAVE A REPLY

Please enter your comment!
Please enter your name here