Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Goedemiddag, Habr!

Taak

Mijn organisatie gebruikt een mailserver op het Kerio Connect-platform; mailservers zijn in verschillende steden geïnstalleerd om hun gebruikers te bedienen. Aanvankelijk was er geen gedistribueerde structuur, omdat de domeinen op het derde niveau verschillen, wat de stad van de site aangeeft. Alles werkte en iedereen was blij. Op een mooie dag stelde het management een taak op: een gemeenschappelijke activiteitenkalender voor alle locaties!

prehistorie

Aanvankelijk was het idee om het Kerio Distributed Mail Domain op te richten en het zou alles zelf doen. Zo gezegd zo gedaan, er werd een gedistribueerd domein aangemaakt, maar dat was niet het geval, de server was klaar om agenda's, mappen, contacten te synchroniseren - tussen domeinen die zich op dezelfde server bevonden, maar was helemaal niet van plan om gegevens tussen verschillende te synchroniseren servers.

Ik had zo'n vangst natuurlijk niet verwacht en kon lange tijd niet geloven dat de functionaliteit die ik nodig had ontbrak. Later vond ik schriftelijk bewijs van dit feit. Ik was hierdoor erg verbaasd en teleurgesteld.

De taak veranderde soepel in een probleem.

Wat waren de opties?

  • Maak twee clients op verschillende servers die de benodigde gegevens uitwisselen met software van derden. Het was nodig om software van derden te vinden die deze functionaliteit zou implementeren - ik hou niet van zulke hark, maar het leek erop dat dit de enige snelle oplossing was.
  • Schrijf uw eigen script voor gegevenssynchronisatie tussen servers. Feit is dat Kerio elk object als een afzonderlijk bestand opslaat, dus het was nodig om een ​​script te ontwikkelen voor het werken met bestanden, maar gezien het voldoende aantal bronnen leek de taak enigszins ingewikkeld, vooral omdat het nodig was om meerdere controleert de juistheid van de gegevens, voor het geval iemand in dezelfde periode een taak aanmaakt, enz., enz.

Vooruitkijkend zal ik zeggen dat hoewel Kerio een object als een afzonderlijk bestand opslaat, het niet zo stom is om elke keer dat u het object opent, te vragen hoe het met het bestandssysteem gaat.

Nadat ik veel tijd had besteed aan nadenken en een aantal stukjes papier had opgesteld met plannen “om vijandelijk gebied te veroveren”, nam ik om zes uur twee juiste beslissingen:

  • De eerste beslissing is om je eigen ding te doen en niets van buitenaf te zoeken.
  • De tweede oplossing is om te gaan slapen.

Al in de ochtend werd ik wakker met één enkele en ware gedachte, die werd teruggebracht tot een paar letters: DFS

beslissing

De oplossing zelf zag er zo uit

  • breng alle servers die zullen deelnemen aan de synchronisatie naar OS Windows. (Een deel ervan stond op Linux. Migratie van e-mailgegevens naar een ander besturingssysteem was vereist)
  • Bepaal de structuur van de mappen die zullen deelnemen aan de synchronisatie - ze moeten identiek zijn.
  • Definieer alle mailservers onder één domein met één enkele DFS-ruimte.
  • Maak het bovengenoemde gedistribueerde Kerio-domein aan, omdat in mijn geval gegevenssynchronisatie vereist is, niet alleen tussen servers maar ook tussen domeinen; de tweede kan onafhankelijk door de Kerio-server worden afgehandeld. (in tegenstelling tot de eerste)
  • Stel gesynchroniseerde mappen in op DFS-ruimte.
  • Verzin een soort kruk (je kunt immers niet leven zonder kruk)

uitvoering

Voorbeeld op twee mailservers (misschien meer)

1. Kerio gedistribueerd domein

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

De Master neemt niet deel aan de synchronisatie, maar dit is geen vereiste.

Ik zal niet beschrijven hoe je een gedistribueerd Kerio-domein kunt opzetten, er is niets ingewikkelds aan, je kunt de ambtenaar bestuderen manueel

Uiteindelijk zou u de volgende afbeelding in de beheerconsole moeten zien:

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Vervolgens was ik geïnteresseerd in gedeelde mappen; op de Master-server kun je de volgende opties opgeven:

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Specifiek voor elk domein - de server synchroniseert geen openbare mappen tussen domeinen

Gemeenschappelijk voor alle domeinen - alle servers zullen de bestaande openbare mappen in elk domein verlaten en nieuwe afzonderlijke mappen maken voor alle domeinen op elke mailserver.

Waarschuwing! Hoewel deze optie het configuratiebeleid op alle servers wijzigt, synchroniseert deze afzonderlijk vanaf elke server (dat wil zeggen, zonder een enkele gemeenschappelijke ruimte)

De beheerder heeft nog steeds de mogelijkheid om de toegang tussen gebruikers te verdelen.
in mijn geval zijn ze allemaal van mij en heb ik volledige synchronisatie nodig (in jouw geval kan de oplossing anders zijn). Op elke server moet je identieke sets domeinen maken die moeten worden gesynchroniseerd.

2. Kerio-gegevensmappen

Nu moet u identieke gedeelde mappen maken die op elk van de servers moeten worden gesynchroniseerd. Mappen, agenda's, contacten.

Advies - maak mappen in het Engels, als je ze in het Latijn maakt, zal de map een naam hebben in een of andere onbegrijpelijke codering, dit is op zijn minst lastig.

Nu moet u de fysieke paden van de e-mailmappen op elke server vinden.

Gemeenschappelijk voor alle domeinen ~DataMailmail#publicСинхронизируемый каталог#msgs
Specifiek voor elk domein ~DataMailmail**Domain**#publicСинхронизируемый каталог#msgs

Houd er rekening mee dat we niet de hele map synchroniseren, maar alleen de container met de gegevens #berichten — de objecten zelf worden hier opgeslagen, alle overige gegevens moeten voor elke server gescheiden zijn.

3.DFS

Ik zal niet in detail beschrijven hoe DFS moet worden geconfigureerd, er is voldoende informatie over dit probleem.

DFS is een rolservice in Windows Server die de mogelijkheid biedt om gedeelde mappen op verschillende servers te combineren
Link naar MS DFS-document

Voordat u DFS instelt, moet u alle e-mailservers stoppen die deelnemen aan de gegevenssynchronisatie.

Na voltooiing van de installatie zou u voor elk van de gesynchroniseerde mappen de volgende afbeelding moeten ontvangen

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Uiteraard hoeven we geen gerepliceerde mappen te publiceren.

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Nadat de replicatie heeft plaatsgevonden (en er is niets bijzonders om te repliceren - de mappen zijn leeg), kunnen de mailservers worden gestart.

Vervolgens kunt u een van de mailservers vullen met gegevens en controleren of de gegevens correct worden gerepliceerd.

4. Kruk

Beschrijving van reflectie

Zoals je kunt zien nadat de gegevens beginnen te synchroniseren (DFS), verschijnt er op de een of andere manier niets op de tweede server als je iets op de eerste server hebt gemaakt, of het verschijnt maar op de een of andere manier niet altijd.

Wanhoop niet; het zal daar natuurlijk vroeg of laat verschijnen, maar beter vroeg dan laat. Omdat het over 6 – 12 uur te laat is.

Het punt is dat zodra je iets hebt aangemaakt op de eerste server, op de tweede en daaropvolgende servers het bestand uiteraard meteen verschijnt dankzij het DFS-systeem, maar in het geval dat deze maildirectory al eerder door iemand is gelezen en opnieuw wordt opgevraagd, zal de server de map #msgs niet opnieuw lezen, maar gegevens uit zijn eigen index uitspugen, wat mogelijk niet langer overeenkomt met onze realiteit.

Kerio heeft een mechanisme om de index opnieuw te lezen, maar het kan in ongeveer zes uur werken, en tijdens deze zes uur kan de relevantie van de taak in de kalender enigszins verloren gaan.
Om de synchronisatie nu te testen, kunt u het bestand verwijderen in de overeenkomstige gesynchroniseerde map index.fld, nadat u opnieuw toegang heeft gekregen tot de map op de mailserver. Als dit bestand ontbreekt, zal Kerio de map en de gegevens opnieuw lezen. zal verschijnen. Het lijkt erop dat dit de oplossing is, verwijder het bestand wanneer de gegevens veranderen, maar dit werkt niet elke keer, maar alleen de eerste keer, dan verliest Kerio om de een of andere reden alle interesse in index.fld
Het begint ook berichten uit te spugen die onbegrijpelijk zijn voor de gebruiker - over een soort index en dat het daar al iets doet.

Er is nog een andere optie: om iets te maken - op het moment dat een nieuw object wordt gemaakt, realiseert de server zich plotseling dat de bestandsnaam die hij wilde toewijzen al in gebruik is, maar het sneeuwbalt en dit is een doodlopende weg.

Hoe kan dat?

Als we nogmaals aandacht besteden aan het beeld dat ons al bekend is.

Volledige synchronisatie van gedeelde mappen, contacten en agenda's tussen gedistribueerde Kerio Connect-servers

Maar op een ander vlak zie je een heel interessante knop die we nu nodig hebben: Mappen opnieuw indexeren

En inderdaad. Als we op deze knop klikken op een mailserver die niet weet dat er al iets is veranderd in de gesynchroniseerde #berichten, krijgen we een stabiel, snel resultaat. Alles wat verborgen is, zal duidelijk worden.

In het log kun je zien hoe lang dit proces duurt; in mijn geval met enkele duizenden (15 duizend) records duurt het ongeveer 3-4 minuten.

Het enige wat we moeten doen is uitzoeken hoe we deze knop daadwerkelijk kunnen indrukken wanneer we hem nodig hebben.

Het blijkt Kerio Hebben hun eigen API

beschrijving
Документация

De functie die onze taak uitvoert, ziet er als volgt uit:
session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)

Op basis van al het bovenstaande moeten we een script schrijven dat de status van de interessante mappen controleert en, als er iets is veranderd, de functie uitvoert die we nodig hebben.

Ik wil zeggen dat ik verschillende versies van scripts heb geschreven die verschillende controles uitvoeren, en heb gekozen voor degene die alle conclusies trekt op basis van het aantal bestanden.

Scriptimplementatie

CMD-scriptvoorbeeld en beschrijving

Index.bat opnieuw

@echo off
set dir=%~dp0
%dir:~0,2%
CD "%~dp0"
md "%CD%LOG"
md "%CD%Setup"

ECHO -Start- >> "%CD%LOG%Computername%.log"
ECHO Start -> %Computername% %Date% %Time% >> "%CD%LOG%Computername%.log"

SetLocal EnableDelayedExpansion
for /f "UseBackQ Delims=" %%A IN ("%CD%Setup%Computername%.List") do (
  set /a c+=1
  set "m!c!=%%A"
)

set d=%c%
Echo Folder = %c%
ECHO Folder = %c% >> "%CD%LOG%Computername%.log"
ECHO.
ECHO. >> "%CD%LOG%Computername%.log"

:start
cls
if %c% LSS 1 exit
set /a id=1
set R=0

:Find
REM PF-Start
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 Count        [ !1DirSize%id%! -- !2DirSize%id%! ]

if "!1DirSize%id%!" == "!2DirSize%id%!" ECHO Synk

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 RE-index Count && ECHO RE-index Count %Date% %Time% - Delete !m%id%! >> "%CD%LOG%Computername%.log"

set 1DirSize!id!=!2DirSize%id%!

ECHO.
ECHO.

set /a id+=1
goto Find

:Reindex
ECHO. >> "%CD%LOG%Computername%.log"
ECHO --- RE-INDEX - Start - %Date% %Time% --- >> "%CD%LOG%Computername%.log"
ECHO. >> ----------------------------------- >> "%CD%LOG%Computername%.log"
call PublicFolders.py
timeout 60
goto start

exit

Op elke mailserver draait een kopie van het script (kan als service worden gebruikt, er zijn geen beheerdersrechten vereist)

Het script leest het bestand Setup%Computername%.List

Waarbij %Computernaam% de naam is van de huidige server (de map kan lijsten van alle servers tegelijk bevatten.)

Het bestand %Computernaam%.List – bevat de volledige paden van de gesynchroniseerde mappen. Elk pad wordt op een nieuwe regel geschreven en mag geen lege regels bevatten.

Na de eerste keer opstarten voert het script de indexeringsprocedure uit, ongeacht of dit nodig is of niet, en maakt het script ook een index van het aantal bestanden in elke gesynchroniseerde map.

Het doel van het script is om alle bestanden in de opgegeven map te tellen.

Als aan het einde van het tellen van elke map in ten minste één map de huidige waarde van de bestanden niet overeenkomt met de vorige, verwijdert het script bestanden uit de hoofdmap van de gesynchroniseerde mailmap: index.fld, indexlog.fld, search.fld en start het indexeringsproces van gedeelde e-mailmappen.

Informatie over de taakuitvoering wordt in de LOG-directory gedumpt.

Indexeringsproces
Het indexeringsproces komt neer op het uitvoeren van een Kerio API-functie
Sessie = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)

Een voorbeeldimplementatie wordt gegeven in – python
PublicFolders.py

import json
import urllib.request
import http.cookiejar
""" Cookie storage is necessary for session handling """
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
""" Hostname or ip address of your Kerio Control instance with protocol, port and credentials """

server = "http://127.0.0.1:4040"
username = "user"
password = "password"

def callMethod(method, params, token = None):
    """
    Remotely calls given method with given params.
    :param: method string with fully qualified method name
    :param: params dict with parameters of remotely called method
    :param: token CSRF token is always required except login method. Use method "Session.login" to obtain this 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)

http://127.0.0.1:4040 je kunt het laten zoals het is, maar als je HTTPS nodig hebt, moet Python het Kerio-certificaat vertrouwen.

Ook in het bestand moet u een account opgeven met rechten om deze functie (Adm - openbare mailmappen) van de mailserver uit te voeren.

Ik hoop dat mijn artikel nuttig zal zijn voor Kerio Connect-beheerders.

Bron: www.habr.com

Voeg een reactie