Jó napot, Habr!
Feladat
A szervezetemben a Kerio Connect platformján működő levelezőszervert használunk, különböző városokban telepített levelezőszerverek szolgálják ki a felhasználókat. Eleinte nem volt elosztott struktúra, mivel a domainek a harmadik szinten várossal jelölt helyszínek szerint különböztek. Minden jól működött és mindenkit elégedett volt. Egy szép napon – a vezetőség feladatot adott, közös üzleti naptárat keresztül minden helyszínre!
Háttér
Eredetileg az volt az ötlet, hogy létrehozzuk a Kerio elosztott levelezési domaint, és az majd mindent megold. Meglett, az elosztott domain létrejött, de nem úgy volt, a szerver készen állt a naptárak, mappák, kapcsolatok szinkronizálására – a közös szervereken lévő domainek között, de egyáltalán nem volt kész arra, hogy adatokat szinkronizáljon több szerver között.
Erre a meglepetésre, persze, nem számítottam, és sokáig nem is tudtam elhinni a szükséges funkció hiányát. Később találtam dokumentált megerősítést erre a tényre. Ezen nagyon meglepődtem és csalódott voltam.
A feladat fokozatosan problémává alakult.
Mik voltak a lehetőségek
- Két klienst létrehozni különböző szervereken, amelyek valamilyen külső szoftverrel cserélték a szükséges adatokat. Meg kellett találni ezt a külső szoftvert, amely megvalósította volna ezt a funkciót – nem szeretem ezeket a buktatókat, de úgy tűnt, hogy ez az egyetlen gyors megoldás.
- Saját adat szinkronizáló szkriptet írni a szerverek közötti adatokhoz. Az a helyzet, hogy a Kerio minden objektumot külön fájlként tárol, ezért egy fájlokkal kapcsolatos szkript kidolgozása szükséges, de a sok forrás miatt a feladat kissé bonyolultnak tűnt, különösen, hogy több adatellenőrzést is el kellett végezni, mi van, ha valaki azonos időtartamban hoz létre feladatot, és így tovább.
Előreugorva, elmondhatom, hogy a Kerio, bár külön fájlként tárolja az objektumokat, nem olyan ostoba, hogy minden egyes objektumhoz való hozzáféréskor megkérdezze – hogy áll a fájlrendszer.
Sok időt töltve a gondolkodással, rengeteg papírt teleírva a 'megoldani az ellenséges terület megszerzését' terveivel, reggel 6-kor két helyes döntést hoztam:
- Az első megoldás – sajátot csinálni, és semmi mást nem keresni.
- A második megoldás — aludni menni.
Már reggel egyetlen, helyes gondolattal ébredtem, amely néhány betűre rövidült – DFS
Megoldás
Magának a megoldásnak a következőképpen kellett kinéznie
- az összes szervert Windows OS-re kellett állítani, amely részt vesz a szinkronizálásban. (Néhány Linuxon volt, az e-mail adatok migrálása másik OS-re szükséges volt)
- Meg kell határozni a szinkronizációban részt vevő mappák struktúráját — ezeknek azonosnak kell lenniük.
- Meg kell határozni az összes e-mail szervert egy domain alatt, egyetlen DFS térrel.
- Létre kell hozni a fent említett elosztott domain-t Kerio-ban, mivel az én esetemben az adatok szinkronizálása szükséges, nemcsak a szerverek között, hanem a domainek között is, a másodikra a Kerio szerver önállóan is képes. (ellentétben az elsővel)
- A szinkronizált mappákat a DFS térre kell irányítani.
- Ki kell találni valamilyen trükköt (hiszen trükk nélkül nem lehet)
Megvalósítás
Példa két e-mail szerverre (lehet több is)
1. Kerio elosztott domain

A Master nem vesz részt a szinkronizálásban, de ez nem kötelező feltétel.
Nem fogom részletesen leírni, hogyan lehet létrehozni egy Kerio elosztott domaint, semmi bonyolult nincs benne, lehet hivatalos forrást tanulmányozni.
Végül az adminisztrációs konzolon a következő képet kell látnod:
![]()

Ezután az érdekeltek közös mappák, a Master szerveren a következő lehetőségeket adhatjuk meg:
![]()

Külön minden domain számára — a szerver nem fogja szinkronizálni a nyilvános mappákat a domainek között
Közös minden domain számára — az összes szerver el fogja hagyni a meglévő közös mappákat minden domain alatt, és új egységes mappákat hoz létre minden domain számára minden e-mail szerveren.
Figyelem! Ez az opció, bár megváltoztatja a beállítások politikáját az összes szerveren, a szinkronizálást külön-külön végzi az egyes szerverekről (tehát – közös tér nélkül)
Az adminisztrátor számára megmarad a lehetőség, hogy hozzáféréseket osszon ki a felhasználók között.
az én esetemben – minden a sajátom, és teljes szinkronizációra van szükségem (az Ön esetében a megoldás más lehet), minden szerveren az azonos domain szetteket kell létrehozni, amelyeket szinkronizálni kell.
2. Kerio adatmappák
Most már létre kell hozni az azonos közös könyvtárakat, amelyeket szinkronizálni kell minden szerveren. Mappák, Naptárak, Kapcsolatok.
Tipp – angol nyelven hozzon létre könyvtárakat, mivel ha latin karakterekben hozza létre őket, a könyvtár neve valamilyen érthetetlen kódolású lesz, ami legalábbis kényelmetlen.
Most meg kell találni a levelezési mappák fizikai útvonalait minden szerveren.
Közös minden domain számára ~DataMailmail#publicSzinkronizált könyvtár#msgs
Külön minden domain számára ~DataMailmail**Domain**#publicSzinkronizált könyvtár#msgs
Kérjük, vegye figyelembe, hogy nem az egész könyvtárat fogjuk szinkronizálni, hanem csak az adatokat tartalmazó tárolót. #msgs — itt maguk az objektumok tárolódnak, minden más adatnak a szerverek esetében egyedinek kell lennie.
3. DFS
A DFS beállításának részleteit nem fogom kifejteni, a kérdéssel kapcsolatban elegendő információ áll rendelkezésre.
A DFS egy szerepkör szolgáltatás a Windows Server-en, amely lehetővé teszi a különböző szervereken található közös mappák egyesítését.
A DFS beállítása előtt le kell állítani az összes levelezési szervert, amely részt fog venni az adatok szinkronizálásában.
A beállítások végén az alábbi képet kell kapnia minden szinkronizált mappához.

A replikálható mappák publikálása nyilvánvalóan nem szükséges.

Miután megtörtént a replikálás (ami különösebben nem sok mindent jelent — a mappák üresek), a levelezási szervereket újra lehet indítani.
Ezután adatokkal tölthetjük meg az egyik levelezési szervert, és ellenőrizhetjük, hogy az adatok megfelelően replikálódnak.
4. Hibás megoldás
A gondolkodás leírása
Ahogy láthatja, miután az adatok elkezdtek szinkronizálódni (DFS), ha bármit is létrehozott az első szerveren — a második szerveren valami nem jelenik meg, vagy megjelenik, de nem mindig.
Ne adja fel, természetesen előbb-utóbb meg fog jelenni, de jobb korán, mint későn. Mert későn az 6-12 órával később történik.
A lényeg az, hogy amint valamit létrehozott az első szerveren, a másodikon és a továbbiakon a fájl azonnal megjelenik a DFS rendszernek köszönhetően. Ha azonban a megadott levelezési mappát már korábban valaki olvasta, és újra lekérik, a szerver nem olvassa újra a #msgs mappát, hanem az adatokból saját indexéből szolgáltat, amely már régóta nem felel meg a valóságnak.
A Kerio-nak van egy index-frissítési mechanizmusa, de ez körülbelül hat óra elteltével lép működésbe. Ennyi idő alatt a naptárban a feladat relevanciája elveszhet.
Annak érdekében, hogy azonnal ellenőrizhesse a szinkronizálás működését, törölheti a fájlt a megfelelően szinkronizált index.fld mappából. Miután újra megkeresi a mappát a levelezőszerveren, és ennek a fájlnak a hiányában a Kerio újraolvassa a mappát, és az adatok megjelennek. Úgy tűnhet, hogy ez itt a megoldás, törölje a fájlt az adatok módosításakor, de ez nem működik mindig, csak az első alkalommal, később a Kerio valamiért elveszíti az érdeklődést az index.fld iránt.
Emellett kezd furcsa, a felhasználó számára érthetetlen üzeneteket dobálni — valami indexről és arról, hogy már működik valami.
Van egy másik lehetőség is, valamit létrehozni — az új objektum létrehozása pillanatában a szerver hirtelen rájön, hogy a fájlnév, amelyet át akart adni, már foglalt, de ez egy lavina, és ez egy zsákutca.
Mit tegyünk?
Ha még egyszer felhívjuk a figyelmet a már ismert képre.

De egy másik szögből nézve, nagyon érdekes és most szükséges gombot lehet észrevenni — Mappák újraindexelése
És valóban. Ha rákattintunk erre a gombra egy levelezőszerveren, amely nem tudja, hogy a szinkronizált #msgs mappájában már történt változás, stabil, gyors eredményt kapunk. Minden rejtett dolog nyilvánvalóvá válik.
A naplóban megnézheti, mennyi időt vesz igénybe ez a folyamat, az én esetemben néhány ezer (15 ezer) bejegyzés körülbelül 3-4 percet vesz igénybe.
Csak ki kell találni, hogyan nyomjuk meg ezt a gombot, amikor erre szükségünk van.
Kiderül, hogy a Kerio-nak van egy saját API
Funkciója, amely elvégzi a feladatunkat, így néz ki –
session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
A fenti leírásból következően egy olyan scriptet kell írnunk, amely nyomon követi az érdekes mappák állapotát, és ha bármi változás történik, végrehajtja a szükséges funkciót számunkra.
Szeretném megemlíteni, hogy több különböző verziót írtam a különböző ellenőrzéseket végző skriptekből, végül a fájlok számának alapján építem fel az összes kimenetet.
A script megvalósítása
CMD script példa és leírás
Re-index.bat
@echo off
set dir=%~dp0
%dir:~0,2%
CD "%~dp0"
md "%LOG"
md "%Setup"
ECHO -Start- >> "%LOG%Számítógépneve%.log"
ECHO Start -> %Számítógépneve% %Dátum% %Idő% >> "%LOG%Számítógépneve%.log"
SetLocal EnableDelayedExpansion
for /f "UseBackQ Delims=" %%A IN ("%Setup%Számítógépneve%.List") do (
set /a c+=1
set "m!c!=%%A"
)
set d=%c%
Echo Mappa = %c%
ECHO Mappa = %c% >> "%LOG%Számítógépneve%.log"
ECHO.
ECHO. >> "%LOG%Számítógépneve%.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 Szinkronizálva
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 Újraindexálás Számlálva && ECHO Újraindexálás Számlálva %Dátum% %Idő% - Törölve !m%id%! >> "%LOG%Számítógépneve%.log"
set 1DirSize!id!=!2DirSize%id%!
ECHO.
ECHO.
set /a id+=1
goto Find
:Reindex
ECHO. >> "%LOG%Számítógépneve%.log"
ECHO --- ÚJRA-INDEXÁLÁS - Kezdés - %Dátum% %Idő% --- >> "%LOG%Számítógépneve%.log"
ECHO. >> ----------------------------------- >> "%LOG%Számítógépneve%.log"
call PublicFolders.py
timeout 60
goto start
exit
A script másolatát minden levelező szerveren futtatják (szolgáltatásként is működhet, nem szükséges admin jogosultság).
A script egy fájlt olvas Setup%Computername%.List
Ahol %Computername% — a jelenlegi szerver neve (a könyvtár egyszerre tartalmazhat minden szerver listáját).
A %Computername%.List fájl – tartalmazza a szinkronizálni kívánt könyvtárak teljes elérési útját, minden útvonal új sorba van írva, üres sorokat nem tartalmazhat.
Az első indítás után a script elvégzi az indexelési eljárást, függetlenül attól, hogy szükség van-e rá vagy sem, a script emellett létrehozza a fájlok számának indexét minden egyes szinkronizált könyvtárban.
A script célja a megadott könyvtárban található összes fájl számának megszámlálása.
A számolás befejezése után, ha legalább egy könyvtárban az aktuális fájlérték nem egyezik meg a korábbival, a script törli a szinkronizált levelező mappa gyökerében található fájlokat: index.fld, indexlog.fld, search.fld és elindítja a közös levelezési mappák indexelési folyamatát.
A LOG mappába mentődnek a végrehajtott feladatok információi.
Indexelési folyamat
Az indexelési folyamat a Kerio API függvényének végrehajtására korlátozódik
Session = callMethod("Domains.checkPublicFoldersIntegrity", {}, token)
A végrehajtás példája a – python
PublicFolders.py
import json
import urllib.request
import http.cookiejar
""" A sütik tárolása szükséges a munkamenetek kezeléséhez """
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
""" A Kerio Control példányod hostnevének vagy IP-címének megadása protokollal, porttal és hitelesítő adatokkal """
server = "http://127.0.0.1:4040"
username = "user"
password = "password"
def callMethod(method, params, token = None):
"""
A megadott metódus távoli hívása a megadott paraméterekkel.
:param: method teljes nevét tartalmazó karakterlánc
:param: params a távoli hívott metódus paramétereit tartalmazó szótár
:param: token A CSRF token mindig szükséges, kivéve a bejelentkezési metódusnál. Használj "Session.login" metódust ennek megszerzésére.
"""
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)
maradhat úgy, ahogy van, de ha HTTPS-t igényel, a python-nak bízni kell a Kerio tanúsítványában.
A fájlban meg kell adni egy fiókot is, amely jogosultságokkal rendelkezik a funkció végrehajtására (Admin – közös levelezési mappák) a levelezőszerveren.
Remélem, hogy a cikkem hasznos lesz a Kerio Connect rendszergazdái számára.
Forrás: habr.com
