Преамбула:
Несколько лет назад был настроен почтовый сервер по мотивам этой статьи он постоянно эволюционирует, но в рамках данной темы это не важно. На нем крутятся несколько почтовых доменов и вот, после появления очередного, некий ВЕЛИКИЙ ОПТИМИЗАТОР бизнес процессов заявил, что надо часть пользователей перевести в новый домен, чтобы почта, приходящая в старый продолжала ходить и чтобы пользователи вообще бы ничего не почувствовали при этом.
Как вариант можно бы было создать новых юзеров в новом домене, настроить переадрессацию и не париться. Но так как у нас клиенты работают по протоколу IMAP, почта хранится на сервере и юзеры хотят иметь доступ к своей старой почте а администратор не хочет разводить зверинец на сервере,- какой смысл в мертвых ящиках? Принято решение провести миграцию пользователей из домена в домен.
Исходные данные:
Несколько лет назад был настроен почтовый сервер по мотивам этой статьи он постоянно эволюционирует, но в рамках данной темы это не важно. На нем крутятся несколько почтовых доменов и вот, после появления очередного, некий ВЕЛИКИЙ ОПТИМИЗАТОР бизнес процессов заявил, что надо часть пользователей перевести в новый домен, чтобы почта, приходящая в старый продолжала ходить и чтобы пользователи вообще бы ничего не почувствовали при этом.
Как вариант можно бы было создать новых юзеров в новом домене, настроить переадрессацию и не париться. Но так как у нас клиенты работают по протоколу IMAP, почта хранится на сервере и юзеры хотят иметь доступ к своей старой почте а администратор не хочет разводить зверинец на сервере,- какой смысл в мертвых ящиках? Принято решение провести миграцию пользователей из домена в домен.
Исходные данные:
- Сервер Exim
- Пользователи хранятся в базе postgreSQL
- Почтовые ящики пользователей хранятся внутри папок с названиями доменов, которые в свою очередь хранятся в корневой папке, указанной в настройках юзера(так было у автора статьи - дает гипотетическую гибкость в настройках, которой я не пользуюсь)
Вот схема интересующей нас части базы данных:
Для осуществления миграции учетной записи из домена в домен необходимо:
- В таблице users_tb в записи пользователя изменить значение поля domain_id на id целевого домена.
- В таблице aliases_tb
- Удалить псевдоним для целевой учетной записи, если он существует.
- Создать псевдоним для исходной учетной записи, с указанием на целевую(аналог переадрессации )
- В случае, если на исходную учетную запись указывали другие алиасы, заменить указатели на целевую учетную запись
- Переместить каталог учетной записи из каталога исходного домена в каталог целевого домена.
- Изменить настройки почтового клиента пользователя.
Варианты решения:
- Делать руками для каждого пользователя
- Написать скрипт, который будет переносить одного пользователя
- Написать скрипт, который будет переносить группу/всех пользователей
Так, как ручной работы по настройке клиента все равно не избежать, но делать все чисто руками не хочется остановился на втором варианте (очень не хочется оказаться в ситуации, когда пользователи уже перенесены, а клиенты у них не настроены и что то произошло, требующее немедленного внимания вариант №2 минимизирует головную боль в этом случае).
Собственно получился вот такой скриптик на пайтоне:
#!/usr/bin/env python3.6
# -*- coding: utf8 -*-
import os,sys,postgresql,string
# Строка подключения к БД
db=postgresql.open('pq://dbuser:dbpassword@localhost:5432/basename')
#функция возвращающая пару значений id, domainname или None если нет такого домена
def get_domain(domain,domainList):
for dom in domainList:
if dom[1]==domain:
return dom
#функция возращающая id, homedir(или None если в домене нет такого пользователя)
def get_user(username,domain):
query=db.prepare("Select id,homedir From users_tb Where username=$1 and domain_id=$2")
user=query(username,domain)
if len(user)!=0:
return user[0]
emails = sys.argv
domains=db.query("Select id, domainname from domains_tb order by id")
if len(emails) ==1:
print("Arguments not found! (need email for migration)")
exit()
srcEmail=emails[1].split("@")
curDomain=get_domain(srcEmail[1],domains)
if curDomain==None:
print("The server not support domain "+srcEmail[1])
exit()
curUser=get_user(srcEmail[0],curDomain[0])
if curUser==None:
print("User "+sys.argv[1]+" not found")
exit()
domains.remove(curDomain)
print("Current email "+sys.argv[1])
print("Select index for your target domain: ")
dim=[]
domainDict={a[0]:a[1] for a in domains}
message="Input your index("
for i in domains:
print(i[0],"--->",i[1])
dim.append(i[0])
message+=str(i[0])+","
message+="):"
newDomainId=0
while newDomainId not in dim:
newDomainId=int(input(message))
if get_user(srcEmail[0],newDomainId):
print("User "+srcEmail[0]+"@"+domainDict[newDomainId]+" is exist ")
exit()
userUpdate=db.prepare("Update users_tb set domain_id=$1 where id=$2")
aliasDelete=db.prepare("Delete from aliases_tb where aliasname=$1 and domain_id=$2")
aliasInsert=db.prepare("INSERT INTO aliases_tb VALUES(DEFAULT,$1,$2,$3,'true')")
userUpdate(newDomainId,curUser[0])
aliasDelete(srcEmail[0],newDomainId)
aliasInsert(srcEmail[0],curDomain[0],srcEmail[0]+"@"+domainDict[newDomainId])
curPath=curUser[1]+"/"+curDomain[1]+"/"+srcEmail[0]
targetPuth=curUser[1]+"/"+domainDict[newDomainId]+"/"+srcEmail[0]
os.rename(curPath,targetPuth)
print("OK")
Скрипт запускается с аргументом - адресом мигрируемого пользователя:
./migrate/py user@domain.com
Для универсальности сделал скрипт с некоторой интерактивностью.
Обрабатываются ситуации:
./migrate/py user@domain.com
Для универсальности сделал скрипт с некоторой интерактивностью.
Обрабатываются ситуации:
- Отсутствует аргумент
- Отсутствует исходный домен
- Отсутствует исходный пользователь
- Присутствует целевой пользователь
В случае появления ситуации выдается сообщение и прерывается работа скрипта.
Делать скрипт более навороченым нету смысла.
Сообщения на английском, так как рута не локализую.
В общем как то так.
Комментариев нет:
Отправить комментарий