Bună ziua, Habr!
Sarcină
În organizația mea folosim un server de email pe platforma Kerio Connect, având servere de email instalate în diferite orașe care deservesc utilizatorii lor. Structura distribuită nu exista inițial, deoarece domeniile difereau la nivelul trei, indicând orașul locației. Totul funcționa și toată lumea era mulțumită. Într-o zi splendidă — conducerea a dat sarcina, un calendar comun de afaceri pentru toate locațiile!
Povestea
Inițial ideea a fost — să ridicăm un domeniu de email distribuit Kerio și el se ocupa de tot. Spus și făcut, domeniul distribuit a fost creat, dar, din păcate, serverul era pregătit să sincronizeze calendare, foldere, contacte — între domeniile aflate pe același server, dar nu era deloc dispus să sincronizeze datele între mai multe servere.
Un astfel de șoc, desigur, nu m-am așteptat și mult timp nu am putut să cred în absența funcționalității necesare pentru mine. Mai târziu am găsit o confirmare documentară a acestui fapt. Am fost foarte derutat și dezamăgit.
Sarcina s-a transformat treptat într-o problemă.
Ce opțiuni am avut
- Să creez doi clienți pe servere diferite, care să schimbe datele necesare prin intermediul unei aplicații externe. Trebuia să găsesc această aplicație externă care ar implementa acea funcționalitate – nu îmi plac aceste capcane, dar părea că aceasta este singura soluție rapidă.
- Să scriu propriul meu script pentru sincronizarea datelor între servere. Problema este că Kerio stochează fiecare obiect ca un fișier separat, așadar era necesar să dezvolt un script care să lucreze cu fișierele, dar având în vedere numărul suficient de surse, sarcina părea oarecum complicată, mai ales că trebuia să efectuez multiple verificări ale corectitudinii datelor, în cazul în care cineva ar crea o sarcină în aceeași perioadă de timp și așa mai departe.
Să anticipez, Kerio, deși stochează obiectul ca un fișier separat, nu este atât de prost încât să întrebe la fiecare accesare a obiectului — cum stau lucrurile cu sistemul de fișiere.
După ce am petrecut mult timp gândindu-mă, desenând o mulțime de hârtii cu planuri „de cucerire a teritoriului inamic”, la ora 6 dimineața am luat două decizii corecte:
- Prima decizie – să fac ceea ce trebuie și să nu caut nimic extern.
- A doua decizie — să merg la somn.
Deja dimineața m-am trezit cu un singur gând, care s-a redus la câteva litere – DFS
Soluție
Soluția arăta astfel
- să aduc toate serverele care vor participa la sincronizare la OS Windows. (Unele erau pe Linux. era necesară migrarea datelor de e-mail pe un alt OS)
- Să stabilim structura directoarelor care vor participa la sincronizare — acestea trebuie să fie identice.
- Să definim toate serverele de e-mail pentru un singur domeniu cu un spațiu DFS unic.
- Să creăm domeniul distribuțional Kerio menționat mai sus, deoarece în cazul meu este necesară sincronizarea datelor, nu doar între servere, ci și între domenii, cel de-al doilea putând fi gestionat de serverul Kerio pe cont propriu. (spre deosebire de primul)
- Să alocăm directoarele sincronizate pe spațiul DFS.
- Să ne gândim la o soluție alternativă (căci fără o soluție alternativă nu se poate)
Implementarea
Exemplu pe două servere de e-mail (pot fi mai multe)
1. Domeniul distribuit Kerio

Master-ul nu participă la sincronizare, dar aceasta nu este o condiție obligatorie.
Nu voi detalia cum se creează un domeniu distribuit Kerio, nu este nimic complicat, se poate studia documentația oficială
În cele din urmă, în consola de administrare ar trebui să vezi următoarea imagine:
![]()

Apoi m-au interesat folderele comune, pe serverul Master se pot specifica următoarele opțiuni:
![]()

Special pentru fiecare domeniu — serverul nu va sincroniza folderele publice între domenii
Comune pentru toate domeniile — toate serverele vor renunța la folderele publice existente în fiecare domeniu și vor crea foldere noi unificate pentru toate domeniile pe fiecare dintre serverele de e-mail.
Atenție! Această opțiune, deși schimbă politica de configurare pe toate serverele, efectuează sincronizarea separat pentru fiecare dintre servere (adică — fără un spațiu comun unic)
Administratorului îi va rămâne posibilitatea de a distribui accesul între utilizatori.
în cazul meu — toate ale mele și am nevoie de o sincronizare completă (În cazul vostru, soluția poate fi diferită) pe fiecare server trebuie să se creeze seturi identice de domenii care trebuie sincronizate.
2. Directoarele de date Kerio
Acum este necesar să creezi directoare comune identice, care trebuie sincronizate pe fiecare dintre servere. Foldere, Calendar, Contacte.
Sfat – creați directoare în limba engleză; în cazul în care le creați în latină, directorul va avea un nume într-o codificare oarecum incomprehensibilă, ceea ce este cel puțin inconvenient.
Acum trebuie să găsim căile fizice ale folderelor de poștă de pe fiecare server.
Comune pentru toate domeniile ~DataMailmail#publicCatalog sincronizat#msgs
Special pentru fiecare domeniu ~DataMailmail**Domeniu**#publicCatalog sincronizat#msgs
Rețineți că vom sincroniza nu întregul director, ci doar containerul cu date. #msgs — aici sunt stocate obiectele în sine; toate celelalte date pentru fiecare dintre servere ar trebui să fie proprii.
3. DFS
Voi detașa cum se configurează DFS, nu voi detalia, informația cu privire la această problemă este suficientă.
DFS este un serviciu de rol în Windows Server, care oferă posibilitatea de a uni folderele partajate situate pe servere diferite.
Înainte de a configura DFS, trebuie să opriți toate serverele de poștă care vor participa la sincronizarea datelor.
La finalizarea configurării ar trebui să obțineți următoarea imagine pentru fiecare dintre folderele sincronizate.

nu trebuie să publicăm folded replicabile, evident.

După ce are loc replicarea (iar acolo de replicat nu este cu adevărat nimic — folderele sunt goale), serverele de poștă pot fi repornite.
Apoi, puteți umple unul dintre serverele de poștă cu date și verificați că datele sunt replicate corect.
4. Soluție temporară
Descrierea reflecției
După cum puteți observa, după ce datele au început să se sincronizeze (DFS), în cazul în care ați creat ceva pe primul server, pe al doilea server nu apare nimic sau poate apărea, dar nu întotdeauna.
Nu trebuie să vă descurajați, evident că mai devreme sau mai târziu vor apărea, dar mai bine mai devreme decât mai târziu. Deoarece mai târziu înseamnă între 6 și 12 ore.
Totul se datorează faptului că, de îndată ce ați creat ceva pe primul server, pe cel de-al doilea și pe serverele următoare, fișierul va apărea imediat datorită sistemului DFS; totuși, în cazul în care acest director de poștă a fost deja citit de cineva anterior și este solicitat din nou, serverul nu va reciti folderul #msgs, ci va returna datele din propriul său index, care poate fi deja demult neactualizat.
Kerio dispune de un mecanism de reasigurare a indexului, dar acesta poate să se activeze după aproximativ șase ore; în acest răstimp, relevanța sarcinii în calendar poate fi deja afectată.
Pentru a verifica sincronizarea în acest moment, se poate șterge fișierul index.fld din directorul sincronizat corespunzător; după o revenire în folderul de pe serverul de poștă și în absența acestui fișier, Kerio va reîncărca directorul și datele vor apărea. Ar părea o soluție, să ștergi fișierul la modificarea datelor, dar aceasta funcționează doar o dată, apoi, dintr-un motiv oarecare, Kerio își pierde interesul pentru index.fld.
În plus, acesta începe să emită mesaje neclare pentru utilizator - despre un anumit index și că deja face ceva acolo.
Există și varianta de a crea ceva - în momentul creării unui nou obiect, serverul ar putea să realizeze că numele fișierului dorit este deja ocupat, dar acesta este un cerc vicios și o variantă fără ieșire.
Ce să facem?
Dacă ne uităm din nou la imaginea deja familiară.

Dar într-o altă dimensiune, putem observa un buton foarte interesant și de care avem nevoie acum - Reindexare a folderelor
Și, într-adevăr. Dacă facem clic pe acest buton pe serverul de poștă, care nu știe că ceva s-a schimbat deja în #msgs sincronizat, vom obține un rezultat stabil și rapid. Tot ce era ascuns devine evident.
În jurnal se poate verifica cât timp durează acest proces; în cazul meu, cu câteva mii (15 mii) de înregistrări, a durat aproximativ 3-4 minute.
Rămâne doar să ne gândim cum să dăm click pe acest buton atunci când avem nevoie.
Se pare că Kerio are propria API
funcție care îndeplinește sarcina noastră, arată așa -
session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
Din tot ce am expus mai sus, trebuie să scriem un script care să monitorizeze starea folderelor de interes și, în cazul în care ceva s-a schimbat, să execute funcția dorită pentru noi.
Vreau să spun că am scris câteva versiuni diferite de scripturi care efectuează verificări diferite, m-am oprit la cel care generează toate rezultatele pe baza numărului de fișiere.
Implementarea scriptului
Exemplu de script CMD și descriere
Reindex.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
O copie a scriptului este executată pe fiecare server de poștă electronică (poate fi utilizat ca un serviciu, drepturi de administrator nu sunt necesare)
Scriptul citește fișierul Setup%Computername%.List
Unde %Computername% este numele serverului curent (Directoria poate conține imediat listele tuturor serverelor.)
Fișierul %Computername%.List conține căile complete ale directoarelor sincronizate, fiecare cale fiind scrisă pe o nouă linie, fără linii goale.
După prima rulare, scriptul realizează o procedură de indexare, indiferent dacă este necesară sau nu; de asemenea, scriptul creează un index al numărului de fișiere din fiecare director sincronizat.
Sarcina scriptului constă în a număra toate fișierele din directorul specificat.
La finalizarea numărării fiecărui director, dacă măcar în unul dintre directoare valoarea curentă a fișierelor nu corespunde cu cea anterioară, scriptul șterge fișierele din directorul rădăcină al catalogului de poștă sincronizat: index.fld, indexlog.fld, search.fld și inițiază procesul de indexare - al căsuțelor poștale comune.
Informațiile despre execuția sarcinilor sunt scrise în directorul LOG.
Procesul de indexare
Procesul de indexare constă în executarea funcției API Kerio
Session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)
Un exemplu de execuție este prezentat în - python
PublicFolders.py
import json
import urllib.request
import http.cookiejar
""" Stocarea cookie-urilor este necesară pentru gestionarea sesiunilor """
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
""" Numele gazdei sau adresa IP a instanței dvs. Kerio Control, împreună cu protocolul, portul și acreditivele """
server = "http://127.0.0.1:4040"
username = "user"
password = "password"
def callMethod(method, params, token = None):
"""
Apelează la distanță metoda dată cu parametrii furnizați.
:param: method string cu numele metodei complet calificate
:param: params dict cu parametrii metodei apelate la distanță
:param: token Token CSRF este întotdeauna necesar, cu excepția metodei de autentificare. Folosiți metoda "Session.login" pentru a obține acest 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)
poate fi lăsat așa cum este, totuși, dacă aveți nevoie de HTTPS — python ar trebui să aibă încredere în certificatul Kerio.
De asemenea, în fișier trebuie specificat un cont cu drepturi de executare pentru această funcție (Admin – foldere poștale publice) ale serverului de mail.
Sper că articolul meu va fi util administratorilor Kerio Connect.
Sursa: habr.com
