Goedemiddag, Habr!
Task
In mijn organisatie gebruiken we een e-mailserver op het Kerio Connect-platform, met in verschillende steden e-mailservers die hun gebruikers bedienen. Aanvankelijk was er geen verspreide structuur, omdat de domeinen op het derde niveau verschilden met vermelding van de stad van de locatie. Alles werkte en iedereen was tevreden. Op een mooie dag stelde het management de taak om een gezamenlijke agenda voor alle locaties op te stellen!
Achtergrond
In eerste instantie was het idee om een Verspreid e-maildomein in Kerio op te zetten en dat zou het wel regelen. Gezegd, gedaan, het verspreide domein werd aangemaakt, maar zo eenvoudig was het niet. De server was klaar om agenda's, mappen, contacten te synchroniseren ā tussen de domeinen op ƩƩn server, maar had absoluut geen intentie om gegevens tussen meerdere servers te synchroniseren.
Zo'n valkuil had ik natuurlijk niet verwacht en kon lange tijd niet geloven dat de noodzakelijke functionaliteit ontbrak. Later vond ik documentair bewijs voor dit feit. Dit heeft me zeer verontrust en teleurgesteld.
De taak vloeide soepel over in een probleem.
Wat waren de mogelijkheden?
- Twee clients op verschillende servers opzetten die met behulp van een of andere externe software de benodigde gegevens uitwisselden. Ik moest die externe software vinden die deze functionaliteit zou realiseren ā ik hou niet van dergelijke hobbels, maar het leek het enige snelle oplossing.
- Een eigen synchronisatiescript ontwikkelen voor de gegevens tussen servers. Het probleem is dat Kerio elk object als een apart bestand opslaat, dus er moest een script ontwikkeld worden dat met bestanden zou werken, maar gezien het aantal bronnen leek de taak vrij complex, vooral omdat er meerdere controles van gegevenscorrectheid moesten worden uitgevoerd, wat als iemand een taak op hetzelfde tijdstip aanmaakt, enzovoorts.
Voordat ik verder ga, moet ik zeggen dat Kerio, hoewel het een object als een apart bestand opslaat, niet zo dom is dat het bij elke benadering van het object vraagt ā hoe gaat het met het bestandssysteem.
Na veel tijd te hebben besteed aan het overdenken, en een hoop papiertjes met plannen 'voor het veroveren van vijandelijk terrein' te hebben volgeschreven, nam ik om zes uur twee juiste beslissingen:
- De eerste oplossing is om zelf iets te maken en niets van derden te zoeken.
- De tweede oplossing is om te gaan slapen.
Al 's ochtends werd ik wakker met ƩƩn enkele en juiste gedachte, die zich beperkte tot enkele letters ā DFS.
Oplossing
De oplossing zag er als volgt uit.
- Alle servers die betrokken zijn bij de synchronisatie moeten op Windows OS draaien. (Een deel was op Linux. migratie van e-mailgegevens naar een ander OS was vereist.)
- Bepaal de directorystructuur die betrokken zal zijn bij de synchronisatie ā deze moeten identiek zijn.
- Bepaal alle mailservers onder ƩƩn domein met een enkele DFS-ruimte.
- Maak het eerder genoemde gedistribueerde domein Kerio aan, aangezien in mijn geval gegevenssynchronisatie vereist is, niet alleen tussen servers maar ook tussen domeinen, het tweede kan de Kerio-server zelfstandig beheren. (in tegenstelling tot de eerste)
- Koppel de te synchroniseren directories aan de DFS-ruimte.
- Bedacht iets van een workaround (want zonder workaround kan het niet).
Implementatie
Voorbeeld met twee mailservers (er kunnen er meer zijn).
1. Gedistribueerd domein Kerio.

De Master neemt niet deel aan de synchronisatie, maar dat is geen vereiste.
Ik zal niet beschrijven hoe je een gedistribueerd domein Kerio opzet, daar is niks ingewikkelds aan, je kunt de officiƫle handleiding bestuderen.
Uiteindelijk zou je in de beheersconsole het volgende beeld moeten zien:
![]()

Vervolgens had ik interesse in de gedeelde mappen, op de Master-server kunnen de volgende opties worden opgegeven:
![]()

Speciaal voor elk domein. ā de server zal geen openbare mappen tussen de domeinen synchroniseren.
Gedeeld voor alle domeinen. ā alle servers zullen de bestaande gedeelde mappen in elk domein opgeven en nieuwe gezamenlijke mappen voor alle domeinen op elke mailserver creĆ«ren.
Let op! Deze optie verandert weliswaar het beleid van de configuratie op alle servers, de synchronisatie vindt echter afzonderlijk van elke server plaats (dat wil zeggen - zonder een enkele gezamenlijke ruimte).
De admin behoudt de mogelijkheid om de toegang tussen gebruikers te verdelen.
In mijn geval ā alles is van mij en heb ik een volledige synchronisatie nodig (In jouw geval kan de oplossing anders zijn) op elke server moeten identieke sets domeinen worden aangemaakt die gesynchroniseerd moeten worden.
2. Data directories Kerio.
Nu moeten we gelijke algemene mappen aanmaken die we op elke server moeten synchroniseren. Mappen, Agenda's, Contacten.
Tip ā maak mappen aan in het Engels; als je ze in het Latijns maakt, zal de directory een naam in een onbegrijpelijke codering hebben, wat op zijn minst onhandig is.
Nu moeten we de fysieke paden van de postmappen op elke server vinden.
Gedeeld voor alle domeinen. ~DataMailmail#publicGecorrigeerde map#msgs
Speciaal voor elk domein. ~DataMailmail**Domein**#publicGecorrigeerde map#msgs
Let op dat we niet de hele map synchroniseren, maar alleen de container met gegevens. #msgs ā hier worden de objecten zelf opgeslagen; alle andere gegevens voor elke server moeten uniek zijn.
3. DFS
Ik zal niet gedetailleerd uitleggen hoe je DFS instelt, er is genoeg informatie over dit onderwerp.
DFS is een rolservice in Windows Server die de mogelijkheid biedt om gedeelde mappen te combineren die zich op verschillende servers bevinden.
Voordat je DFS instelt, moet je alle postservers die betrokken zijn bij de gegevenssynchronisatie stopzetten.
Na de configuratie zou je de volgende weergave voor elke gesynchroniseerde map moeten krijgen.

Het publiceren van gerepliceerde mappen is uiteraard niet nodig.

Nadat de replicatie heeft plaatsgevonden (en er is weinig te repliceren ā de mappen zijn leeg) kunnen de postservers weer worden opgestart.
Daarna kan je een van de postservers met gegevens vullen en controleren of de gegevens correct worden gerepliceerd.
4. Workaround
Beschrijving van de overpeinzing
Zoals je kunt zien, nadat de gegevens begonnen te synchroniseren (DFS), als je iets hebt aangemaakt op de eerste server, verschijnt er op de tweede server iets maar soms verschijnt er niets, of het verschijnt maar niet altijd.
Maak je geen zorgen, het zal vroeg of laat daar verschijnen, maar liever vroeg dan laat. Want laat betekent na 6 tot 12 uur.
Het zit zo, zodra je iets hebt gemaakt op de eerste server, verschijnt het bestand natuurlijk onmiddellijk op de tweede en daaropvolgende servers dankzij het DFS-systeem. Echter, als deze e-mailmap eerder door iemand is gelezen en opnieuw wordt opgevraagd, zal de server de map #msgs niet opnieuw lezen, maar de gegevens uit zijn eigen index geven, die mogelijk al lang niet meer overeenkomt met onze werkelijkheid.
Kerio heeft een mechanisme voor het opnieuw lezen van de index, maar dit kan pas na ongeveer zes uur gebeuren. In die zes uur kan de actualiteit van de taak in de agenda wat verloren gaan.
Om direct te controleren of de synchronisatie werkt, kun je het bestand index.fld in de overeenkomstige gesynchroniseerde map verwijderen. Na een nieuwe oproep naar de map op de mailserver en bij afwezigheid van dit bestand zal Kerio de map opnieuw lezen en verschijnen de gegevens. Het lijkt simpel: verwijder het bestand bij het wijzigen van gegevens, maar dit werkt niet elke keer, alleen de eerste keer. Daarna verliest Kerio om de een of andere reden zijn interesse in index.fld.
En dan begint het ook nog onduidelijke berichten voor de gebruiker te geven - over een of andere index en dat hij daar al iets mee aan het doen is.
Er is ook nog een andere optie, iets creƫren - op het moment dat een nieuw object wordt gemaakt, beseft de server plotseling dat de bestandsnaam die hij wilde toekennen al bezet is. Dit lijkt misschien een sneeuwbal-effect, wat een doodlopende weg is.
Wat te doen?
Als we nog een keer kijken naar de al bekende afbeelding.

Maar vanuit een andere invalshoek kunnen we een zeer interessante en nu nuttige knop opmerken - Map opnieuw indexeren
En inderdaad. Als je op deze knop op de mailserver drukt, die niet weet dat er al iets is veranderd in de gesynchroniseerde #msgs, krijgen we een stabiel en snel resultaat. Alles wat verborgen was, wordt zichtbaar.
In het logboek kun je bekijken hoe lang dit proces duurt; in mijn geval met enkele duizenden (15 duizend) records duurt het ongeveer 3-4 minuten.
We moeten alleen nog bedenken hoe we op deze knop kunnen drukken wanneer we dat nodig hebben.
Blijkbaar heeft Kerio zijn eigen API
functie die onze taak uitvoert, deze ziet er als volgt uit -
session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
Op basis van het bovenstaande moeten we een script schrijven dat de status van de interessante mappen controleert en, in het geval dat er iets is veranderd, de benodigde functie voor ons uitvoert.
Ik wil zeggen dat ik verschillende versies van scripts heb geschreven die verschillende controles uitvoeren, en ik ben gebleven bij degene die alle uitvoer opbouwt op basis van het aantal bestanden.
Implementatie van het script
Voorbeeld van een CMD-script en beschrijving
Re-index.bat
@echo off
set dir=%~dp0
%dir:~0,2%
CD "%~dp0"
md "%LOG"
md "%Setup"
ECHO -Start- >> "%LOG%Computername%.log"
ECHO Start -> %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 Folder = %c%
ECHO Folder = %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-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 te% %Time% - Delete !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 - Start - te% %Time% --- >> "%LOG%Computername%.log"
ECHO. >> ----------------------------------- >> "%LOG%Computername%.log"
call PublicFolders.py
timeout 60
goto start
exit
Een kopie van het script wordt op elke mailserver uitgevoerd (kan als dienst, Administrator-rechten zijn niet vereist)
Het script leest een bestand Setup%Computername%.List
Waar %Computername% de naam van de huidige server is (de directory kan lijsten van alle servers bevatten).
Het bestand %Computername%.List bevat de volledige paden van de te synchroniseren directories, elke pad staat op een nieuwe regel en er mogen geen lege regels zijn.
Na de eerste uitvoering van het script voert het een indexeringsprocedure uit, ongeacht of deze nodig is of niet. Ook maakt het script een index van het aantal bestanden in elke gesynchroniseerde directory.
De taak van het script komt neer op het tellen van alle bestanden in de opgegeven directory.
Na het tellen van elke directory, als het huidige aantal bestanden in ten minste ƩƩn directory niet overeenkomt met het vorige aantal, verwijdert het script bestanden uit de rootdirectory van de gesynchroniseerde mailcatalogus: index.fld, indexlog.fld, search.fld en start het indexeerproces - gemeenschappelijke postmappen.
In de directory LOG wordt informatie over de uitvoering van taken opgeslagen.
Indexeerproces
Het indexeerproces bestaat uit het uitvoeren van de API-functie van Kerio
Session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
Een voorbeeld van uitvoering wordt gegeven in - python
PublicFolders.py
import json
import urllib.request
import http.cookiejar
""" Cookie-opslag is noodzakelijk voor sessiebeheer """
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
""" Hostnaam of ip-adres van uw Kerio Control-instantie met protocol, poort en inloggegevens """
server = "http://127.0.0.1:4040"
username = "user"
password = "password"
def callMethod(method, params, token = None):
"""
Roept op afstand de opgegeven methode aan met de gegeven parameters.
:param: method string met volledig gekwalificeerde methodenaam
:param: params dict met parameters van de op afstand aangeroepen methode
:param: token CSRF-token is altijd vereist behalve voor de inlogmethode. Gebruik de methode "Session.login" om deze token te verkrijgen.
"""
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)
kan zo blijven, maar als je HTTPS nodig hebt, moet python het Kerio-certificaat vertrouwd maken.
In het bestand moet ook een account worden opgegeven met rechten om deze functie uit te voeren (Admin - gemeenschappelijke postmappen) van de mailserver.
Ik hoop dat mijn artikel nuttig zal zijn voor beheerders van Kerio Connect.
Bron: habr.com
