En las últimas versiones de Plesk, Parallels ha incluido una herramienta estupenda que permite realizar migraciones entre servidores Linux, o servidores Windows, e incluso de un servidor Linux a un servidor Windows, utilizando internamente ssh y rsync para realizar el transporte de datos, pero no da la posibilidad de realizar una migración automatizada de Windows a Linux, así que para este caso no ha quedado más remedio que recurrir a procedimientos más artesanales.

El plan consiste básicamente en realizar consultas SQL a la base de datos de Plesk para Windows, a partir de las cuáles se pueda obtener una serie de scripts que utilicen los comandos CLI provistos por Plesk. Una vez replicada la estructura de clientes y dominios, ya se comienza a pasar los datos, vía FTP, del código de las webs, y mediante exports de MySQL para las bases de datos. Para el correo se creó una utilidad en Python que analizaba el fichero AUTH.TAB de MailEnable, generando un script que crea los buzones en Plesk, y después invoca a imapsync para copiar el contenido de los mismos.

Estructura de dominios en Plesk

Comenzamos generando la estructura de revendedores, clientes y dominios en el servidor destino, creando una serie de comandos para el CLI de Plesk, ejecutando comandos SQL en el servidor origen:

SQL que genera los revendedores:

SELECT "reseller -c " + cl.login +
" -name """ + cl.pname + """" +
" -passwd " + cl.passwd +
" -company """ + cl.cname + """" +
" -phone """ + cl.phone + """" +
" -email """ + cl.email + """" +
" -address """ + cl.address + """" +
" -city """ + cl.city + """" +
" -zip """ + cl.pcode + """" +
" -country """ + cl.country + """" +
" -creation-date """ + FORMAT(cl.cr_date,"YYYY-MM-DD") + """"
FROM clients cl
WHERE type = "reseller"

SQL que genera un script para la creación de clientes, obviando los suscriptores, que ya tienen su cuenta del paso anterior:

SELECT "customer -c " + cl.login +
" -name """ + cl.pname + """" +
" -passwd " + cl.passwd +
" -company """ + cl.cname + """" +
" -phone """ + cl.phone + """" +
" -email """ + cl.email + """" +
" -address """ + cl.address + """" +
" -city """ + cl.city + """" +
" -zip """ + cl.pcode + """" +
" -country """ + cl.country + """" +
" -creation-date """ + FORMAT(cl.cr_date,"YYYY-MM-DD") + """" +
" -owner """ + res.login + """"
FROM clients cl
LEFT JOIN clients res ON (res.id = cl.parent_id)
  WHERE type <> "reseller"

En este punto, nosotros reemplazamos el owner “admin” por nuestra empresa, para que nada dependiese del usuario raíz, ya que según la nueva estructura de Plesk 10, parece más correcto.

Por último, el SQL que genera un script para la creación de suscripciones a partir de los dominios de Plesk 9. Los dominios los crea con el DNS desactivado, dado que seguiremos manejando el servicio DNS con el otro servidor, y a la IP compartida (que está, claramente, modificada). También el login utiliza sólo minúsculas, ya que se ha introducido esta restricción en Plesk 10.

SELECT "domain -c " + dom.name +
" -owner """ + cl.login + """" +
" -dns false" +
" -hosting true " +
" -ip 192.168.0.164 " +
" -login """ + LCASE(hos.fp_adm) + """" +
" -passwd """ + hos.fp_pass + """" +
" -creation-date """ + FORMAT(dom.cr_date,"YYYY-MM-DD") + """"
FROM (domains dom
LEFT JOIN clients cl ON (cl.id = dom.cl_id))
LEFT JOIN hosting hos ON (hos.dom_id = dom.id)

Puntos mejorables:

  • Hay que revisar los DNS a mano. Hemos preferido hacerlo así, para hacer limpieza, pero tampoco sería complejo realizar un script similar a los mostrados, y marcar las suscripciones con el servicio DNS activado por defecto, de forma que sólo quedase pendiente realizar la modificación en el dominio.
  • Las redirecciones de correo y demás opciones específicas deben ser revisadas, ya que el script únicamente ignora las cuentas que estén desactivadas en MailEnable, pero nada más.
  • Todas las suscripciones pasan como hosting, así que las que son redirecciones o simplemente sin hosting no pasan mediante el script. Esto es debido a que se hace un JOIN con la tabla hosting de Plesk 9.
  • Las suscripciones y revendedores pasan con un plan personalizado. En nuestro caso nos da igual, porque vamos a aprovechar para repasar todos los clientes y revisar así usos y precios.

Correo electrónico

Bien, tras esto ya tenemos los revendedores, clientes, suscripciones y dominios en Plesk 10. A continuación presentamos una pequeña utilidad en Python que genera dos ficheros, uno que permite la creación de los buzones en Plesk, y otro que sincroniza los correos entre los dos servidores mediante IMAP, creando la estructura de carpetas existente en el antiguo.

# This Python file uses the following encoding: utf-8
'''
me2plesk: Utilidad para la transformación de AUTH.TAB en scripts Plesk 10 e imapsync
Created on 13/10/2011
@author: Vicente Monroig (Digital Disseny)
'''

import os
import sys

def parse_authtab(fichero):
    '''Abre el fichero AUTH.TAB, lo parsea y devuelve una lista con los buzones y contraseñas.'''
    print "Procesando fichero AUTH.TAB " + fichero + "..."
    f = open(fichero, "r")
    lista = []
    while True:
        lin = f.readline().strip()
        if not lin: break
        campos = lin.split('\t')
        # Ignoramos los que estén desactivados
        if campos[1] <> 1:
            lista.append([campos[0], campos[2]])
    f.close()
    return lista

# Obtenemos la ruta donde se está ejecutando el archivo
ruta = os.path.dirname(os.path.abspath(__file__)) + '/'
# Recogemos el parámetro donde está el AUTH.TAB o mostramos la ayuda
if (len(sys.argv) > 1):
    # Extraemos los pares correo, contraseña
    lista = parse_authtab(sys.argv[1])
    print("Generando scripts...")
    # Creamos los archivos de script
    fplesk = open(ruta + 'me2plesk_plesk.txt', "w")
    fsync = open(ruta + 'me2plesk_imapsync.txt', "w")
    for elemento in lista:
        # Creamos una nueva línea en ambos scripts
        fplesk.write("/opt/psa/bin/mail --create " + elemento[0] + " -passwd " + elemento[1] +
                     " -mailbox true\n")
        fsync.write("imapsync --host1 origen.com" +
                    " --user1 " + elemento[0] + " --password1 " + elemento[1] +
                    " --host2 destino.com" +
                    " --user2 " + elemento[0] + " --password2 " + elemento[1] +
                    " --sep1 / --prefix1 ""  --subscribe --fastio1 --fastio2 --fast\n")
    fplesk.close()
    fsync.close()
    print("Scripts me2plesk_plesk.txt y me2plesk_imapsync.txt generados en %s." % ruta)
else:
    print """
Información:
    me2plesk es una pequeña utilidad que analiza sintácticamente el fichero AUTH.TAB del
    servidor de correo MailEnable para Windows, generando dos scripts, uno que llama a la
    función mail del CLI de Plesk 10, creando los buzones encontrados, y un segundo que
    invoca a la utilidad imapsync, una vez por cada buzón, permitiendo con la combinación
    de ambos la mudanza de un servidor MailEnable Windows a un Plesk 10.
Uso:
    me2plesk.py <AUTH.TAB>
       """

Además, como algunos ISPs son algo lentos cambiando los registros DNS, tenemos la ventaja de que no perderemos ningún correo, al poder ejecutar la sincronización varias veces, incluso con los DNS ya cambiados y propagados.

Una pega: Aquellos clientes que mantengan correo en el servidor y utilicen POP3 como protocolo, verán sus correos duplicados en los clientes. Sin embargo, los que utilicen IMAP no tendrán este problema, dado que imapsync, la utilidad llamada por el script para sincronizar los buzones, respeta las flags de cada mensaje.

Webs (código y bases de datos)

Para pasar el código de las webs utilizaremos FTP, y más concretamente LFTP, que incorpora un comando mirror que nos va a permitir realizar todo el traspaso en una única línea de comandos ejecutada en el servidor destino:

lftp -e "mirror httpdocs /var/www/vhosts/<dominio>/httpdocs --parallel=10" -u <usuario>,<contraseña> <servidor_fuente>

Quedaría ajustar los permisos y propietario de los distintos archivos. Podemos poner unos estándar para Plesk y después repasar lo que necesite permisos de escritura, como carpetas para ficheros temporales.

chown -R <usuarioplesk>:psacln /var/www/vhosts/<dominio>/httpdocs/*
find /var/www/vhosts/<dominio>/httpdocs/* -type d -exec chmod 755 {} \;
find /var/www/vhosts/<dominio>/httpdocs/* -type f -exec chmod 644 {} \;

Vamos a por las bases de datos. Nos centraremos en MySQL, que son las que nos vamos a encontrar en su mayoría (WordPress, Joomla, Magento, Drupal…). Aprovechando que todavía tenemos un servidor Windows, podemos utilizar HeidiSQL para realizar una copia de seguridad, y si configuramos debidamente el servidor destino para aceptar conexiones externas, también podremos utilizarlo para restaurar, todo desde el mismo servidor origen.

DNS

Ya están la estructura de usuarios recreada, correos pasados, código fuente transferido y bases de datos restauradas. Tan sólo queda modificar los DNS de los dominios para que dirijan al nuevo servidor.

Como último apunte, antes de comenzar con los cambios de IPs en los DNS es muy recomendable modificar los registros SOA, indicando un TTL de 5 minutos, con lo que podremos realizar modificaciones que se propaguen mucho más rápido. Por supuesto, esto conlleva un aumento del tráfico, pero con las máquinas y anchos de banda de hoy en día, no debería ser ningún problema.

Recordad también que el archivo hosts es nuestro amigo, y que es muy conveniente realizar pruebas en el nuevo servidor antes de cambiar los DNS. Siempre podemos relanzar la sincronización de correos y volver a pasar la copia de seguridad de la base de datos cuando estemos seguros de que todo está operativo de nuevo.

Organización

Lo más crucial, lo más importante y lo único que no puede fallar durante el proceso es la organización. Sobre esto poco voy a decir, pues esto es un blog técnico, pero sí quiero remarcar que antes de empezar hay que planificar y dividir las tareas que van a tener que hacerse fuera de horario de oficina. Hay que comunicar a los clientes previamente lo que se va a hacer, y que les quede claro que puede haber problemas, y cuándo se va a hacer, no sea que les dé por liarse a actualizar su web justo cuando tenemos pensado ponernos a migrar sus servicios.

Organización en hoja de cálculo

Prepara una hoja de cálculo, verifica y anota los servicios a trasladar, agrúpalos por similitud y anota los posibles problemas y su resolución. Como mínimo.