Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Доброго дня, Хабре!

Завдання

У моїй організації використовують поштовий сервер на платформі Kerio Connect, у різних містах встановлені поштові сервери, які обслуговують своїх користувачів. Розподіленої структури спочатку не було, тому що домени відрізняються на третьому рівні із зазначенням міста майданчика. Все працювало та всіх влаштовувало. Одного дня — керівництво поставило завдання, спільний календар справ між усіма майданчиками!

Передісторія

Спочатку ідея була - підняти розподілений поштовий домен Kerio і він сам все зробить. Сказано, зроблено розподілений домен був створений, але не було, сервер готовий був синхронізувати календарі, папки, контакти — між доменами що знаходяться на одному сервері, але зовсім не збирався синхронізувати дані між декількома серверами.

Такої каверзи я, звичайно, не очікував і довго не міг повірити у відсутність необхідного мені функціоналу. Пізніше знайшов документальне підтвердження цього факту. Чим був дуже спантеличений і розчарований.

Завдання плавно перетекло у проблему.

Які були варіанти

  • Створити двох клієнтів на різних серверах, які якимось стороннім програмним забезпеченням обмінювали необхідні дані. Потрібно було знайти це саме стороннє програмне забезпечення, яке б реалізовувало даний функціонал - не люблю такі граблі, але здавалося, що це єдино швидке рішення.
  • Написати власний скрипт синхронізації даних між серверами. Справа в тому, що Kerio зберігає кожен об'єкт як окремий файл, відповідно потрібно розробити скрипт роботи з файлами, але через достатню кількість джерел завдання здавалося дещо складним, тим більше що потрібно було виконувати множинні перевірки коректності даних, раптом хтось створить Завдання в однаковий проміжок часу і тд і тп.

Забігаючи наперед, скажу, що Kerio хоч і зберігає об'єкт як окремий файл, він не настільки дурний, щоб при кожному зверненні до об'єкта запитувати — як справи у файлової системи.

Витративши на роздуми велику кількість часу, змалювавши купу папірців з планами "захоплення ворожої території", о 6-й годині ура я прийняв два вірні рішення:

  • Перше рішення – робити своє та нічого стороннього не шукати.
  • Друге рішення – йти спати.

Вже вранці я прокинувся з однією вірною думкою, яка скоротилася до кількох літер – DFS

Рішення

Саме рішення виглядало так

  • привести всі сервери, які братимуть участь у синхронізації до OS Windows. (Частина була на Linux. Потрібна міграція поштових даних на іншу OS)
  • Визначиться зі структурою каталогів, які братимуть участь у синхронізації — вони мають бути ідентичними.
  • Визначити всі поштові сервери під один домен з єдиним простором DFS.
  • Створити вищезгаданий розподілений домен Kerio, тому що в моєму випадку потрібна синхронізація даних, не тільки між серверами, але і між доменами, другим може займатися сервер Kerio самостійно. (На відміну від першого)
  • Нацькувати синхронізовані каталоги на простір DFS.
  • Придумати якийсь милиця (адже без милиці не можна)

Реалізація

Приклад на двох поштових серверах (може бути більше)

1. Kerio Distributed domain

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Master не бере участь у синхронізації, але це не є обов'язковою умовою.

Розписувати, як підняти розподілений домен Kerio не буду, нічого складного в цьому немає, можна вивчити офіційний махнув

Зрештою в консолі адміністрування ви повинні побачити таку картинку:

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Далі мене цікавили спільні папки, на сервері Master можна вказати такі варіанти:

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Особлива для кожного домену — сервер не синхронізуватиме загальнодоступні папки між доменами.

Загальні для всіх доменів — всі сервери відмовляться від існуючих спільних папок у кожному домені та створять нові єдині папки для всіх доменів на кожному з поштових серверів.

Увага! Дана опція хоч і змінює політику налаштування на всіх серверах, синхронізацію робить окремо від кожного із серверів (тобто без єдиного загального простору)

У адміністратора - залишиться можливість розподіляти доступи між користувачами.
у моєму випадку - всі свої і мені потрібна повна синхронізація (У вашому випадку рішення може бути іншим) на кожному сервері потрібно створити однакові набори доменів, які необхідно синхронізувати.

2. Каталоги даних Kerio

Тепер потрібно створити однакові спільні каталоги, які потрібно синхронізувати на кожному із серверів. Папки, Календарі, Контакти.

Порада – створюйте каталоги англійською мовою, у тому випадку, якщо ви створите їх на латиниці, директорія матиме назву в якомусь незрозумілому кодуванні, це як мінімум незручно.

Тепер потрібно знайти фізичні шляхи поштових папок на кожному сервері.

Загальні для всіх доменів ~DataMailmail#publicСинхронизируемый каталог#msgs
Особлива для кожного домену ~DataMailmail**Domain**#publicСинхронизируемый каталог#msgs

Зверніть увагу, що ми синхронізуватимемо не весь каталог, а лише контейнер з даними #msgs — тут зберігаються самі об'єкти, решта даних для кожного із серверів мають бути свої.

3. DFS

Докладно як налаштовувати DFS, також розписувати не буду, інформації з цього питання достатньо.

DFS — це служба ролі в Windows Server, яка надає можливість об'єднання спільних папок на різних серверах.
Посилання на документ MS DFS

Перед налаштуванням DFS – необхідно зупинити всі поштові сервери, які братимуть участь у синхронізації даних.

Після закінчення налаштування ви повинні отримати наступну картинку для кожної з папок, що синхронізуються.

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

публікувати папки, що реплікуються, нам природно не потрібно.

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Після того, як відбудеться реплікування (а реплекувати там особливо нічого - папки порожні) поштові сервери можна запустити.

Далі можна наповнити даними один із поштових серверів і перевірити, чи дані реплікуються коректно.

4. Милиця

Опис роздумів

Як ви можете переконатися після того, як дані почали синхронізуватися (DFS), у тому випадку, якщо ви щось створили на першому сервері — на другому сервері щось якось нічого не з'являється, або з'являється але якось не завжди.

Зневіряється не варто воно звичайно рано чи пізно там з'явиться, але краще рано, ніж пізно. Тому що пізно це через 6 – 12 годин.

Вся справа в тому, що як тільки ви створили щось на першому сервері, на другому і наступних файл звичайно відразу ж з'явиться завдяки системі DFS, проте в тому випадку якщо даний поштовий каталог вже був кимось прочитаний раніше і його запросять повторно, сервер не перечитуватиме папку #msgs а виплюне дані зі свого власного індексу, який може вже давно не відповідати нашій дійсності.

Kerio має механізм перечитування індексу, але він може спрацювати годин так через шість, при цьому за ці 6 годин актуальність завдання в календарі може бути втрачена.
Для того щоб перевірити роботу синхронізації прям зараз, можна видалити файл у відповідному синхронізованому каталозі index.fld, після повторного звернення до папки на поштовому сервері і за відсутності файлу Kerio перечитає каталог і дані з'являться. Здавалося б, ось воно рішення, видаляй файл при зміні даних, але це працює не щоразу, а тільки вперше, далі Kerio чомусь втрачає інтерес до index.fld
Так і ще починає випльовувати незрозумілі для користувача повідомлення про якийсь індекс і що він там уже щось робить.

Є ще варіант, щось створити - в момент створення нового об'єкта сервер раптом зрозуміє, що ім'я файлу, яке він хотів привласнити вже зайняте, але тут снігова куля і це тупиковий варіант.

Як же бути?

Якщо ще раз звернути увагу на вже знайому нам картинку.

Повна синхронізація спільних папок, контактів та календарів між розподіленими серверами Kerio Connect

Але в іншій площині можна помітити дуже цікаву і потрібну нам зараз кнопку. Переіндексувати папки

І дійсно. Якщо натиснути на цю кнопку на поштовому сервері, який не знає про те, що у нього вже щось змінилося в синхронізованому #msgs, ми отримаємо стабільний, швидкий результат. Все приховане стане очевидним.

У журналі можна подивитися, скільки часу займає даний процес, у моєму випадку з кількома тисячами (15 тис) записів близько 3-4 хвилин.

Залишилися тільки придумати, як натиснути на цю кнопку, тоді коли нам це потрібно.

Виявляється у Керіо є свій API

Опис
Документація

Функція, яка виконує наше завдання, має такий вигляд –
session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)

З усього вище викладеного нам потрібно написати скрипт, який моніторив би стан папок, що цікавлять, і в тому випадку, якщо щось змінилося, виконував для нас потрібну нам функцію.

Хочу сказати, що я написав кілька різних версій скриптів, що виконують різні перевірки, зупинився на тому, що всі висновки будує виходячи з кількості файлів.

Реалізація скрипту

Приклад скрипта CMD та опис

Re-index.bat

@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

Копія скрипта запускається на кожному поштовому сервері (можна як служба, Адм права не потрібні)

Скрипт читає файл Setup%Computername%.List

Де %Computername% — ім'я поточного сервера (Директорія може містити одразу списки всіх серверів.)

Файл %Computername%.List – містить повні шляхи синхронізованих директорій, кожен шлях записаний у новому рядку, порожніх рядків містити не повинен.

Після першого запуску скрипт виконує процедуру індексації, незалежно необхідна вона чи ні, також скрипт створює індекс кількості файлів у кожній із синхронізованої директорії.

Завдання скрипта зводиться до підрахунку всіх файлів у зазначеній директорії.

Після закінчення підрахунку кожної директорії, якщо хоча б в одній директорії поточне значення файлів, не збігається з попереднім, скрипт видаляє файли з кореневої директорії поштового каталогу, що синхронізується: index.fld, indexlog.fld, search.fld та запускає процес індексації – загальних поштових папок.

У директорію LOG звалюється інформація про виконання завдань.

Процес індексації
Процес індексації зводиться до виконання функції API Kerio
Session = callMethod("Domains.checkPublicFoldersIntegrity",{}, token)

Приклад виконання наведено на – 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 можна залишити як є, проте якщо вам потрібно HTTPS - python повинен довіряти сертифікату Kerio.

Також у файлі необхідно вказати обліковий запис із правами на виконання цієї функції (Адм – загальних поштових папок) поштового сервера.

Сподіваюся, що моя стаття буде корисна адміністраторам Kerio Connect.

Джерело: habr.com

Додати коментар або відгук