¡Buen día, Habr!
Tarea
En mi organización utilizamos un servidor de correo en la plataforma Kerio Connect, y en diferentes ciudades se han instalado servidores de correo que atienden a sus usuarios. Inicialmente no había una estructura distribuida, ya que los dominios diferían en el tercer nivel indicando la ciudad de la ubicación. Todo funcionaba bien y todos estaban satisfechos. Un buen día, la dirección planteó la tarea de tener un calendario común de tareas entre todas las ubicaciones.
Antecedentes
Inicialmente, la idea era levantar un dominio de correo distribuido de Kerio que se encargara de todo. Dicho y hecho, se creó el dominio distribuido, pero no fue tan fácil; el servidor estaba preparado para sincronizar calendarios, carpetas y contactos entre dominios que se encontraban en un mismo servidor, pero no tenía intención de sincronizar datos entre varios servidores.
No esperaba tal sorpresa y durante mucho tiempo no podía creer que faltaba la funcionalidad que necesitaba. Más tarde encontré un documento que confirmaba este hecho, lo que me dejó muy perplejo y decepcionado.
La tarea se convirtió suavemente en un problema.
¿Cuáles eran las opciones?
- Crear dos clientes en diferentes servidores que intercambiaran los datos necesarios mediante algún software de terceros. Tenía que encontrar ese software de terceros que implementara esta funcionalidad; no me gustan esos obstáculos, pero parecía que era la única solución rápida.
- Escribir mi propio script de sincronización de datos entre servidores. El hecho es que Kerio almacena cada objeto como un archivo separado, por lo que era necesario desarrollar un script que trabajara con archivos, pero dado el considerable número de fuentes, la tarea parecía algo complicada, especialmente porque había que realizar múltiples verificaciones de la validez de los datos; si de repente alguien creaba una tarea en el mismo intervalo de tiempo, etc.
Anticipándome, diré que Kerio, aunque almacena objetos como archivos separados, no es tan tonto como para preguntar cada vez que se accede a un objeto: ¿cómo está el sistema de archivos?
Después de haber pasado mucho tiempo pensando, llenando un montón de papeles con planes 'para tomar el territorio enemigo', a las seis de la mañana, tomé dos decisiones correctas:
- La primera decisión: hacer lo mío y no buscar nada externo.
- La segunda decisión: ir a dormir.
Ya me desperté por la mañana con un único y verdadero pensamiento, que se redujo a pocas letras: DFS
Solución
La solución se veía de la siguiente manera
- llevar todos los servidores que participarán en la sincronización a OS Windows. (Una parte estaba en Linux, se requería la migración de los datos de correo a otro OS)
- Definir la estructura de las carpetas que participarán en la sincronización; deben ser idénticas.
- Determinar todos los servidores de correo bajo un dominio con un único espacio DFS.
- Crear el dominio distribuido mencionado anteriormente de Kerio, ya que en mi caso se requiere sincronización de datos no solo entre servidores, sino también entre dominios, el segundo puede ser manejado por el servidor de Kerio por sí mismo. (a diferencia del primero)
- Apuntar las carpetas sincronizadas al espacio DFS.
- Inventar alguna solución alternativa (pues sin algún truco no se puede)
Implementación
Ejemplo en dos servidores de correo (puede haber más)
1. Dominio distribuido de Kerio

El maestro no participa en la sincronización, pero esto no es un requisito obligatorio.
No voy a detallar cómo levantar un dominio distribuido de Kerio, no hay nada complicado en ello; se puede estudiar el oficial
Al final, en la consola de administración deberías ver la siguiente imagen:
![]()

A continuación, me interesaban las carpetas compartidas; en el servidor maestro se pueden especificar las siguientes opciones:
![]()

Particular para cada dominio — el servidor no sincronizará las carpetas públicas entre dominios
Comunes para todos los dominios — todos los servidores renunciarán a las carpetas compartidas existentes en cada dominio y crearán nuevas carpetas unificadas para todos los dominios en cada uno de los servidores de correo.
¡Atención! Esta opción, aunque cambia la política de configuración en todos los servidores, realiza la sincronización de forma separada en cada uno de los servidores (es decir, sin un único espacio común)
Al administrador le quedará la posibilidad de distribuir accesos entre los usuarios.
en mi caso: todos los míos y necesito una sincronización completa (en su caso la solución puede ser diferente) en cada servidor se deben crear conjuntos idénticos de dominios que necesitan ser sincronizados.
2. Directorios de datos de Kerio
Ahora es necesario crear directorios comunes idénticos que deben ser sincronizados en cada uno de los servidores. Carpetas, Calendarios, Contactos.
Consejo: crea catálogos en inglés, ya que si los creas en caracteres latinos, el directorio tendrá un nombre en una codificación incomprensible, lo que es al menos incómodo.
Ahora es necesario encontrar las rutas físicas de las carpetas de correo en cada servidor.
Comunes para todos los dominios ~DataMailmail#publicCatálogo sincronizado#msgs
Particular para cada dominio ~DataMailmail**Dominio**#publicCatálogo sincronizado#msgs
Presta atención a que solo sincronizaremos el contenedor de datos y no todo el catálogo. #msgs — aquí se almacenan los propios objetos, todos los demás datos para cada uno de los servidores deben ser específicos.
3. DFS
No explicaré en detalle cómo configurar DFS, hay suficiente información sobre este tema.
DFS es un servicio de rol en Windows Server que permite combinar carpetas compartidas en diferentes servidores.
Antes de configurar DFS, es necesario detener todos los servidores de correo que participarán en la sincronización de datos.
Al finalizar la configuración, deberías obtener la siguiente imagen para cada una de las carpetas sincronizadas.

No necesitamos publicar carpetas replicadas, por supuesto.

Una vez que se complete la replicación (y realmente no hay mucho que replicar, ya que las carpetas están vacías), se pueden iniciar los servidores de correo.
Luego, puedes llenar uno de los servidores de correo con datos y verificar que los datos se replican correctamente.
4. Solución improvisada
Descripción de reflexiones
Como puedes ver, después de que los datos comienzan a sincronizarse (DFS), en caso de que crees algo en el primer servidor, en el segundo servidor algo no aparece, o aparece, pero no siempre.
No te desesperes, tarde o temprano aparecerá, pero es mejor que sea pronto, ya que tarde se refiere a 6 a 12 horas.
El problema es que tan pronto como creas algo en el primer servidor, en el segundo y en los demás archivos, por supuesto, aparecerá de inmediato gracias al sistema DFS, sin embargo, en el caso de que este catálogo de correo ya haya sido leído por alguien antes y se solicite nuevamente, el servidor no volverá a leer la carpeta #msgs y devolverá datos de su propio índice, que puede no corresponder a nuestra realidad desde hace mucho tiempo.
Kerio tiene un mecanismo de relectura del índice, pero puede tardar unas seis horas, durante las cuales la relevancia de la tarea en el calendario puede haberse perdido.
Para verificar el funcionamiento de la sincronización ahora mismo, se puede eliminar el archivo index.fld en el directorio sincronizado correspondiente; tras acceder de nuevo a la carpeta en el servidor de correo y en ausencia de este archivo, Kerio volverá a leer el directorio y los datos aparecerán. Aparentemente, esta sería la solución: eliminar el archivo al modificar los datos, pero esto no funciona cada vez, solo la primera vez; luego, Kerio, por alguna razón, pierde todo interés en index.fld.
Además, empieza a emitir mensajes incomprensibles para el usuario — sobre algún índice y que ya está haciendo algo.
Hay otra opción, algo que crear; en el momento de crear un nuevo objeto, el servidor podría darse cuenta de que el nombre de archivo que quería asignar ya está ocupado, pero esto es un efecto dominó y es una opción muerta.
¿Qué hacer entonces?
Si echamos un vistazo de nuevo a la imagen que ya conocemos.

Pero en otro plano, se puede notar un botón muy interesante y necesario para nosotros en este momento — Reindexar carpetas
Y efectivamente. Si hacemos clic en este botón en el servidor de correo, que no sabe que ya algo ha cambiado en el #msgs sincronizado, obtendremos un resultado estable y rápido. Todo lo oculto se volverá evidente.
En el registro se puede ver cuánto tiempo dura este proceso; en mi caso, con varios miles (15 mil) de registros, dura alrededor de 3-4 minutos.
Solo queda pensar en cómo realmente pulsar este botón en el momento que lo necesitamos.
Resulta que Kerio tiene su propia API
función que realiza nuestra tarea, que es la siguiente -
session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
De todo lo anterior, necesitamos escribir un script que monitoree el estado de las carpetas de interés y que, en caso de que algo cambie, ejecute la función que necesitamos.
Quiero mencionar que escribí varias versiones diferentes de scripts que realizan diferentes verificaciones, y me detuve en el que genera todos los resultados en función de la cantidad de archivos.
Implementación del script
Ejemplo de script CMD y descripción
Re-index.bat
@echo off
set dir=%~dp0
%dir:~0,2%
CD "%~dp0"
md "%LOG"
md "%Setup"
ECHO -Inicio- >> "%LOG%Computername%.log"
ECHO Inicio -> %Computername% te% %Time% >> "%LOG%Computername%.log"
SetLocal EnableDelayedExpansion
for /f "UseBackQ Delims=" %%A IN ("%Setup%Computername%.List") do (
set /a c+=1
set "m!c!=%%A"
)
set d=%c%
Echo Carpeta = %c%
ECHO Carpeta = %c% >> "%LOG%Computername%.log"
ECHO.
ECHO. >> "%LOG%Computername%.log"
:start
cls
if %c% LSS 1 exit
set /a id=1
set R=0
:Find
REM PF-Inicio
if "%id%" gtr "%c%" if %R% == 1 Goto Reindex
if "%id%" gtr "%c%" timeout 60 && Goto start
For /F "tokens=1-3" %%a IN ('Dir "!m%id%!#msgs" \/-C\/S\/A:-D') Do Set 2DirSize!id!=!DS!& Set DS=%%c
if "2DirSize!id!" == "" set 1DirSize!id!=!2DirSize%id%!
echo %id%
ECHO !m%id%!
echo Contador [ !1DirSize%id%! -- !2DirSize%id%! ]
if "!1DirSize%id%!" == "!2DirSize%id%!" ECHO Sincronizar
REM DEL index.fld
if "!1DirSize%id%!" NEQ "!2DirSize%id%!" del /f /q !m%id%!index.fld && del /f /q !m%id%!indexlog.fld && del /f /q !m%id%!search.fld && set R=1 && ECHO Reindexar Contador && ECHO Reindexar Contador te% %Time% - Eliminar !m%id%! >> "%LOG%Computername%.log"
set 1DirSize!id!=!2DirSize%id%!
ECHO.
ECHO.
set /a id+=1
goto Find
:Reindex
ECHO. >> "%LOG%Computername%.log"
ECHO --- RE-INDEX - Inicio - te% %Time% --- >> "%LOG%Computername%.log"
ECHO. >> ----------------------------------- >> "%LOG%Computername%.log"
call PublicFolders.py
timeout 60
goto start
exit
Una copia del script se ejecuta en cada servidor de correo (puede ser como servicio, no se requieren derechos de administrador)
El script lee el archivo Setup%Computername%.List
Donde %Computername% es el nombre del servidor actual (el directorio puede contener listas de todos los servidores).
El archivo %Computername%.List contiene las rutas completas de los directorios a sincronizar, cada ruta está escrita en una nueva línea y no debe contener líneas vacías.
Después de la primera ejecución, el script realiza un procedimiento de indexación, independientemente de si es necesario o no, además el script crea un índice del número de archivos en cada uno de los directorios a sincronizar.
La tarea del script se reduce al conteo de todos los archivos en el directorio especificado.
Al finalizar el conteo de cada directorio, si al menos en uno de los directorios el valor actual de archivos no coincide con el anterior, el script elimina los archivos del directorio raíz del catálogo de correo sincronizado: index.fld, indexlog.fld, search.fld y comienza el proceso de indexación - de las carpetas públicas comunes.
En el directorio LOG se guarda información sobre la ejecución de tareas.
Proceso de indexación
El proceso de indexación se reduce a ejecutar la función API Kerio
Session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
Un ejemplo de ejecución se proporciona en - python
PublicFolders.py
import json
import urllib.request
import http.cookiejar
""" Almacenamiento de cookies es necesario para el manejo de sesiones """
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
""" Nombre de host o dirección IP de su instancia de Kerio Control con protocolo, puerto y credenciales """
server = "http://127.0.0.1:4040"
username = "user"
password = "password"
def callMethod(method, params, token = None):
"""
Llama remotamente al método dado con los parámetros dados.
:param: method cadena con el nombre del método completamente calificado
:param: params dict con los parámetros del método llamado remotamente
:param: token El token CSRF siempre es requerido excepto en el método de inicio de sesión. Use el método "Session.login" para obtener este token.
"""
data = {"method": method, "id": 1, "jsonrpc": "2.0", "params": params}
req = urllib.request.Request(url = server + '/admin/api/jsonrpc/')
req.add_header('Content-Type', 'application/json')
if (token is not None):
req.add_header('X-Token', token)
httpResponse = urllib.request.urlopen(req, json.dumps(data).encode())
if (httpResponse.status == 200):
body = httpResponse.read().decode()
return json.loads(body)
session = callMethod("Session.login", {"userName": username, "password": password, "application": {"vendor": "Kerio", "name": "Control Api-Local", "version": "Python"}})
token = session["result"]["token"]
print(session)
session = callMethod("Domains.checkPublicFoldersIntegrity",{"domainId": "test2.local"}, token)
print(session)
callMethod("Session.logout", {}, token)
se puede dejar como está, sin embargo, si necesita HTTPS, Python debe confiar en el certificado de Kerio.
Además, en el archivo es necesario especificar una cuenta con permisos para ejecutar esta función (Admin – de carpetas de correo compartidas) del servidor de correo.
Espero que mi artículo sea útil para los administradores de Kerio Connect.
Fuente: habr.com
