понедельник, 6 октября 2014 г.

Миграция почты с одного сервера на другой

В какой-то момент в нашей организации стал вопрос переноса почты на вновь созданный сервер под управлением Exchange 2010. Исходные условия  -  удаленный почтовый сервер с доступом к нему по imap  и Exchange 2010 SP1 с доступом к нему как угодно.
Вариант 1-й - миграция с помощью pst-файлов(подготовленных при помощи Microsoft Outlook на клиентских машинах)  провалилась практически сразу же, когда оказалось, что Exchnge практически гарантированно выдает ошибку при импорте ящика объемом более 1 Гигабайта. 
Второй вариант - использовать вспомогательный сервер Exchange 2007 и утилиту Microsoft Transporter Suite, специально предназначенную для миграции данных в Exchange(под 2010 сервером она не работает) тоже не сработала. Microsoft Transporter  читал письма по imap группами по 10 писем (команда вида fetch 1,2,..,10), а сервер этого упорно не понимал. При этом fetch с указанием номера одного письма спокойно проходил. Точно так же, как чтение утилитой Microsoft transporter с другого сервера тоже шло на ура.
Временным решением показалась утилита Aid4Mail - как перенос imap-imap, но при объеме в сотню с лишним почтовых ящиков хотелось как-то больше автоматизации. плюс, часто при переносе при помощи Aid4Mail некоторые письма не переносились из-за непонятных ошибок(чем именно были вызваны эти ошибки - я разобрался уже позже).
Итоговое решение пришло не сразу. На утилиту imapsync я обратил внимание еще в самом начале поисков, но отсутствие свободной версии на офсайте как-то отпугнуло(хотя 50 евро за этот продукт - на самом деле очень демократичная цена). Но при более внимательном поиске обнаруживаем, что "все уже украдено до нас" - https://fedorahosted.org/released/imapsync/  .
Сначала я попробовал линуксовую версию - результат удовлетворил более чем. Но так как я все-таки в первую очередь виндузятник, то не мог не попробовать виндовую версию, которой тоже остался доволен  - и скоростью переноса, и соответствием исходного и конечного набора данных.  При использовании этой утилиты благодаря подробным логам и пришло понимание того, почему при помощи Aid4Mail не переносились некоторые письма -  они превышали допустимый размер, указанный на сервере Exchange. 
Вкратце, команда переноса при помощи imapsync выглядела так:

imapsync.exe --host1 imap.server1.ru --user1 username1 --password1 password1 --host2 imap.server2.ru --port2 993 --ssl2 --user2 username2 --password2 password2 --authmech2  PLAIN >>pathtologfile.log 

Здесь несложно догадаться, что исходный сервер работает по стандартному 143 порту без использования SSL, а сервер Exchange настроен на 993 порт с использованием SSL. Также отмечу, что использования механизма аутентификации  PLAIN  было необходимостью в случае авторизации пользователя на imap-сервере Microsoft Exchange.
Теперь же, переходим к самому интересному - к автоматизации процесса. Здесь сразу затрону механизм авторизации. В Exchange есть такая возможность - дать конкретному пользователю права на доступ к любому почтовому ящику. Это свойство можно использовать при входе на imap-сервер. Т.е., если у нас есть пользователь adminuser, с правами доступа к почтовому ящику пользователя user1, то мы можем зайти в почтовый ящик пользователя user1, не указывая его пароль, Получится примерно так --user2 domain/adminuser/username --password2 adminuserpassword --authmech2 LOGIN. Вот тут прокатило только так - с authmech LOGIN, почему  - не знаю, просто сработало эмпирически.
Теперь ,собственно автоматизация на Powershell:
Делаем CSV в формате  user1;password1;user2 (так и пишем в первой строке файла). Здесь user1/password1 - пара логин/пароль на исходном почтовом сервере. User2  - имя пользователя на конечном почтовом сервере Exchange, пароль нам не важен, у нас есть логин/пароль административного пользователя с доступом ко всем почтовым ящикам.
В итоге получается такой скрипт (лог пишется для каждого пользователя в отдельный файл):
$mail=import-csv d:\imapsync\sync.csv -Delimiter ';'
foreach ($stroka in $mail) 
{ $user1=$stroka.user1
$password1=$stroka.password1
$user2=$stroka.user2
& D:\imapsync\imapsync.exe --host1 imap.server1.ru --user1 $user1 --password1 $password1 --host2 imap.server2.ru --port2 993 --ssl2 --user2 domainname/adminuser/$user2 -password2 password2 --authmech2 LOGIN | Out-File -filepath d:\imapsync\logs\$user1.log -Append -NoClobber

}

четверг, 15 мая 2014 г.

Proxmox: загрузка бэкапов через веб-интерфейс

Снова столкнулся с тем, что в достаточно широко распространенном программном продукте не работает из коробки та функция, которая по логике должна бы работать.
На этот раз речь пойдет о среде виртуализации Proxmox и загрузке бэкапов виртуальных машин через веб-интерфейс. Итак, имеем следующие входные данные: на машине свежеустановленный Proxmox версии 3.2, на нем развернуто помимо хранилища Local еще и хранилище Backup с типом контента ISO, Backups, Templates. Задача  - перенести бэкапы виртуальных машин с другого гипервизора. Естественно, руки потянулись для этой цели использовать веб-интерфейс: выбираем наше хранилище Backup, жмем Upload, выбираем тип контента VZDump backup file, выбираем нужный файл, жмем Upload, смотрим на проценты загрузки и по итогу получаем сообщение об ошибке:
 Error 400: Parameter verification failed.
content: upload content type 'backup' not allowed
Собственно, я сразу не стал разбираться, почему так, и воспользовался консолью и самбой для решения этой задачи. Примерно то же самое(пойти обходным путем) рекомендует баг-трекер Proxmox'а(use scp to copy the file to the right directory). Но обсуждение этой проблемы вывело меня на верное решение.
Открываем для редактирования следующий скрипт: /usr/share/perl5/PVE/API2/Storage/Status.pm.
Находим там следующий фрагмент:
if ($content eq 'iso') {
if ($filename !~ m![^/]+\.[Ii][Ss][Oo]$!) {
raise_param_exc({ filename => "missing '.iso' extension" });
}
$path = PVE::Storage::get_iso_dir($cfg, $param->{storage});
} elsif ($content eq 'vztmpl') {
if ($filename !~ m![^/]+\.tar\.gz$!) {
raise_param_exc({ filename => "missing '.tar.gz' extension" });
}
$path = PVE::Storage::get_vztmpl_dir($cfg, $param->{storage});
} else {
raise_param_exc({ content => "upload content type '$content' not allowed" });
}

Как видим, по дефолту доступны для загрузки только ISO образы и шаблоны, при загрузке отличного от этих типов контента получаем знакомое сообщение об ошибке.
Исправляем:

if ($content eq 'iso') {
if ($filename !~ m![^/]+\.[Ii][Ss][Oo]$!) {
raise_param_exc({ filename => "missing '.iso' extension" });
}
$path = PVE::Storage::get_iso_dir($cfg, $param->{storage});
} elsif ($content eq 'vztmpl') {
if ($filename !~ m![^/]+\.tar\.gz$!) {
raise_param_exc({ filename => "missing '.tar
.gz' extension" });
}
$path = PVE::Storage::get_vztmpl_dir($cfg, $param->{storage});
} elsif ($content eq 'backup') {
if ($filename !~ m![^/]+\.vma\.lzo$!) {
raise_param_exc({ filename => "missing '.vma.lzo' extension" });
}
$path = PVE::Storage::get_backup_dir($cfg, $param->{storage});
} else {
raise_param_exc({ content => "upload content type '$content' not allowed" });
}

Я добавил для себя проверку на расширение vma.lzo,  поскольку все мои бэкапы были сделаны именно в этом формате, но при желании можно добавить и  vma.gz, а можно и вообще отказаться от проверки на расширение.
Перезагружаем Proxmox - и таки да, загрузка бэкапов через веб-интерфейс работает.