среда, 23 января 2013 г.

Клонирование P2V в инфраструктуру VMware без vCenter Converter


Производить миграцию или клонирование P2V серверов в инфраструктуру vmware, конечно удобно проводить при помощи vCenter Converter. Однако, vCenter Converter будет работать только если разделы ОС находятся под управлением LVM, или это должны быть диски с разделами (а не просто диски). Подробнее узнать об ограничениях можно здесь. В случае если условия не удовлетворяют, Вам придется произвести миграцию самостоятельно. В моем случае было 10 серверов, настроенных на загрузку с SAN, LVM на них не используется, в качестве разделов ОС как раз использовались целые диски без партиций (LUN с схд). Операционная система – CentOS 5 x86_64. Сервера располагаются в ЦОД’е в Нью Йорке, виртуальные машины должны быть во Франкфурте. Итак, миграция по шагам, используя примеры команд. Я постарался документировать этот достаточно утомительный процесс и попробовать его автоматизировать:

Создание виртуальной машины
Создайте виртуальную машину с нужными характеристиками. Если хотите что то поменять по сравнению с физической - самое время это сделать. Я изменил количество дисков, т.к. разумно использовать один диск совместно с LVM.
Примонтируте любой live дистрибутив linux, например knoppix, fedora, gentoo и т.д. Обратите внимание на то, что архитектура дистрибутива Live CD должна соответствовать той, которую имеет переносимый сервер. У меня под руками был Gentoo 11.0. После загрузки, назначите IP адрес, шлюз, пароль root, и запустите sshd:

Gentoo-11 ~ # ifconfig eth0 192.168.1.25/24
Gentoo-11 ~ # route add default gw 192.168.1.25
Gentoo-11 ~ # passwd root
Gentoo-11 ~ # /etc/init.d/sshd start

Создание и форматирование разделов:
Поскольку я хотел использовать LVM, то простое копирование структуры дисковой подсистемы не годилось. Выбранная структура – один диск, разделенный на две партиции. Первая партиция - под загрузчик (500МБ), а вторая отдается под управление LVM.

Gentoo-11 ~ # parted -s /dev/sda mklabel msdos
Gentoo-11 ~ # parted -s /dev/sda mkpart primary 1MB 525MB
Gentoo-11 ~ # parted -s /dev/sda toggle 1 boot
Gentoo-11 ~ # parted -s /dev/sda mkpart primary 525MB 53.7GB
Gentoo-11 ~ # parted -s /dev/sda toggle 2 lvm

Создадим тома в LVM, разделы: подкачки, /root и /var/log

Gentoo-11 ~ # pvcreate /dev/sda2
Gentoo-11 ~ # vgcreate vgname /dev/sda2
Gentoo-11 ~ # lvcreate -L 2048 -n swap vgname
Gentoo-11 ~ # lvcreate -L 20480 -n root vgname
Gentoo-11 ~ # lvcreate -l 7042 -n log vgname

Внесите необходимые коррективы, если ваша таблица разделов будет отличаться.
Произведем форматирование:

Gentoo-11 ~ # mkfs.ext3 -L boot /dev/sda1
Gentoo-11 ~ # mkswap -L swap /dev/mapper/vgname-swap
Gentoo-11 ~ # mkfs.ext3 -L root /dev/mapper/vgname-root
Gentoo-11 ~ # mkfs.ext3 -L log /dev/mapper/vgname-log

Создайте папки, в которые затем примонтируем разделы:

Gentoo-11 ~ # mkdir -p /mnt/root
Gentoo-11 ~ # mount /dev/mapper/vgname-root /mnt/root/
Gentoo-11 ~ # mkdir -p /mnt/root/boot /mnt/root/var/log
Gentoo-11 ~ # mount /dev/sda1 /mnt/root/boot
Gentoo-11 ~ # mount /dev/mapper/vgname-log /mnt/root/var/log

Перенос данных.
Переносить данные будем через sftp. Для того, что бы не вводить пароль – скопируйте публичный ключ пользователя root с физического сервера:

root@source:~# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.25

Данные будем переносить в виде tar архива. Архив можно не создавать на исходном сервере, а сразу передать на целевой с помощью pipe, например:

root@source:~# tar czf - /usr | ssh root@192.168.1.25 "dd of=/mnt/root/var/usr.tgz"

Команде tar так же можно указать, что не нужно помещать в архив. Это можно указать в командной строке через параметр --exclude pattern, или создать файл исключений, который указывается через параметр -X file. В файле исключений можно указать директории /dev, /proc, /var/log и т.д. Но в отличие от данных в нутрии этих директорий – сами директории нужны, поэтому после переноса данных их нужно будет создать.
Перенос данных можно автоматизировать. Я написал скрипт converter.sh. Он создает tar архив и формирует файл скрипта mkdir.sh, которые передаются на целевой сервер. Скрипт mkdir.sh необходим для создания директорий, а так же он монтирует служебные файловые системы, такие как например proc. Файл exclude используется для указания исключений.

root@source:~# cat converter.sh
#!/bin/bash

exclude=./exclude
log=./converter.log

if [ $# -ne 2 ]; then echo "Usage: converter.sh destionation_server destination_directory"; exit 1; fi

cat /dev/null > $log 

ls / | while read dir
  do
    tar -czX $exclude -f - /$dir 2>>$log| ssh root@$1 "dd of=$2/$dir.tgz"
    echo -e "Backup /$dir \e[00;32mcomplete\e[00m"
  done

# Make the file, which makes directories
echo -n "Make and transfer executive file:"
cat /dev/null > ./mkdir.sh
echo -e "#!/bin/sh \n\n#Make directories" >> ./mkdir.sh
echo "if [ \$# -ne 1 ]; then echo \"Usage: mkdir.sh mount_point\"; exit 1; fi" >> ./mkdir.sh

for dir in /dev /proc /selinux /sys /tmp
do
  usrgrp=`stat -c %u:%g $dir`
  perm=`stat -c %a $dir`
  echo -e "mkdir \$1$dir \nchmod $perm \$1$dir \nchown $usrgrp \$1$dir" >> ./mkdir.sh
done

dirs=(`grep -v "$#\|$^\|dev\|proc\|selinux\|lost+found\|sys\|tmp" ./exclude | while read dir
do
  find $dir -type d | grep -v "lost+found"
done`)
element_count=${#dirs[@]}

index=0
while [ "$index" -lt "$element_count" ]
do
  usrgrp=`stat -c %u:%g ${dirs[$index]}`
  perm=`stat -c %a ${dirs[$index]}`
  echo -e "mkdir \$1${dirs[$index]} \nchmod $perm \$1${dirs[$index]} \nchown $usrgrp \$1${dirs[$index]}" >> ./mkdir.sh
  let "index=$index+1"
done

echo -e "mount --bind /dev \$1/dev \nmount --bind /proc \$1/proc \nmount --bind /sys \$1/sys" >> ./mkdir.sh

scp ./mkdir.sh root@$1:$2 2>>$log
echo -e " \e[00;32mcomplete\e[00m"

Для корректной работы скрипта, файл exclude должен быть в той же директории что и скрипт. Содержимое моего exclude:

root@source:~# cat ./exclude
/dev
/lost+found
/proc
/selinux
/sys
/var/log

Входные параметры скрипта converter.sh – dns имя сервера или его ip адрес, а так же директория назначения.
Выполним перенос данных:

root@source:~# ./converter.sh 192.168.1.25 /mnt/root/var/log

Развертывание данных
Теперь перейдем на целевой сервер и развернем данные:

Gentoo-11 ~ # cd /mnt/root
Gentoo-11 root # ls var/log/*.tgz | while read arch; do tar -xf $arch; done

Создадим директории и примонтируем служебные файловые системы при помощи скрипта mkdir.sh. Скрипт имеет входной параметр – место куда примонтирован корневой раздел:

Gentoo-11 root # sh var/log/mkdir.sh /mnt/root

Внесение изменений в конфигурационные файлы, установка grub
Так как, по сравнению с исходной системой, в таблицу разделов внесено изменение, то необходимо внести соответствующие изменения на целевом сервере. Внесите коррективы в fstab. Согласно моему:

Gentoo-11 root # cat /mnt/root/etc/fstab
LABEL=root  /        ext3   defaults 1 1
LABEL=boot  /boot    ext3   defaults 1 2
tmpfs       /dev/shm tmpfs  defaults 0 0
devpts      /dev/pts devpts gid=5,mode=620 0 0
sysfs       /sys     sysfs  defaults 0 0
proc        /proc    proc   defaults 0 0
LABEL=swap  swap     swap   defaults 0 0
tmpfs       /tmp     tmpfs  defaults,size=1G 0 0
LABEL=log   /var/log ext3   defaults 1 3

Теперь нужно войти в созданное окружение:

Gentoo-11 root # chroot /mnt/root

Уберите все лишнее из /etc/modprobe.conf и проверьте есть ли у вас строки:

Gentoo-11 root # cat /etc/modprobe.conf
alias scsi_hostadapter mptbase
alias scsi_hostadapter1 mptspi
alias scsi_hostadapter2 ata_piix

Это позволит включить эти модули ядра в initrd, что позволит в свою очередь корректно произвести загрузку (по умолчанию vmware выбирает адаптер LSI Logic Parallel)

Создадим новый initrd:

Gentoo-11 root # mkinitrd -v /boot/initrd-2.6.18-274-1.el5.img 2.6.18-274.el5

Внесите коррективы в настройки grub, учитывая смену диска root и новый initrd:

Gentoo-11 root # cat boot/grub/menu.lst
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-274.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-274.el5 ro root=/dev/vgname/root
initrd /initrd-2.6.18-274-1.el5.img

Финальная часть, необходимо установить загрузчик:

Gentoo-11 root # grub

grub> root (hd0,0)
root (hd0,0)
Filesystem type is ext2fs, partition type 0x83
grub> setup (hd0)
setup (hd0)
Checking if "/boot/grub/stage1" exists... no
Checking if "/grub/stage1" exists... yes
Checking if "/grub/stage2" exists... yes
Checking if "/grub/e2fs_stage1_5" exists... yes
Running "embed /grub/e2fs_stage1_5 (hd0)"... failed (this is not fatal)
Running "embed /grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)
Running "install /grub/stage1 (hd0) /grub/stage2 p /grub/grub.conf "... succeeded
Done.
grub> quit
quit


Все! Можно перегружать виртуальный сервер и расслабиться после нудной работы.

Напоследок, команды, которые могут понадобиться:

  1. Просмотр таблицы разбиения диска
parted /dev/sda print
  1. Активация lvm
vgchange -a y

суббота, 19 января 2013 г.

Использование записей /etc/hosts в nginx


Недавно столкнулся с интересной особенностью в nginx. У меня возникла необходимость прописать в параметре proxy_path имя сервера, которое в свою очередь определено в /etc/hosts. Не работает! Немного погуглив, я нашел совет. Рекомендации которого заключается в следующем:
Прописать директиву

resolver 127.0.0.1

Которая указывает адрес (можно указать так же и порт) для днс запросов, установить на этот же сервер dnsmasq, который может брать информацию из /etc/hosts (немного о настройке dnsmasq можно прочитать в статье про настройку wi-fi точки доступа). Однако, имена в /etc/hosts все же можно использовать без этих манипуляций. Имя сервера нужно прописать в upstream, которое затем использовать в proxy_path. Все работает! Пример использования:

upstream example {
  server  www.host.local;
}


location = /api/example/ {
  rewrite  ^/api/example(/.*) $1 break;
  access_log  /var/log/nginx/example.access.log main;
  error_log   /var/log/nginx/example.error.log  debug;
  proxy_set_header        Host  dns-name.domain.ru;
  proxy_pass              http://example/$request_uri;
}

В данном примере запросы вида http://nginx_site/api/example/something проксируются на хост dns-name.domain.ru с использованием hosts записи www.host.local. Проксированный урл запроса после обработки будет выглядеть так: http://dns-name.domain.ru/something.

понедельник, 3 декабря 2012 г.

Загрузка серверов из сети хранения данных (SAN)

Данная статья содержит основные рекомендации для планирования инфраструктуры, где загрузочный диск находится на системе хранения данных (СХД). Также статья содержит пошаговую инструкцию по настройке HBA адаптеров Qlogic для обеспечения загрузки из SAN. Статья основывается на "SAN Boot Implementation and Best Practices Guide for IBM System Storage" с дополнениями из личного опыта.

В качестве серверов рассмотрены два лезвия IBM HS21 (c BIOS) и IBM HS22V (с UEFI), производитель HBA адаптера – Qlogic, СХД - IBM DS3512 и EMC CLARIION CX4-480. Статья не ориентирована на конкретную систему хранения, коммутаторы SAN или сервера.

Архитектура SAN, используемая при написании инструкции – dual fabric, представлена на рисунке ниже. Как Вы можете отметить, при данной архитектуре, количество путей от инициатора к СХД составляет не менее четырех.
Рисунок 1
Использование в качестве системного загрузочного диска LUN размещенный на системе хранения данных, предоставляет следующие преимущества:
  1. Взаимозаменяемость серверов: Размещая загрузочный образ на SAN, сервера более не привязаны к их стартовой конфигурации. При отказе сервера становится возможным заменить его на другой в кратчайшее время.
  2. Легкость развертывания: Развертывание дополнительных серверов можно реализовать просто копируя образ.
  3. Надежность: Загрузочные образа находятся на SAN, которая по определению отказоустойчива (несколько путей от инициатора к системе хранения данных, резервирование контроллера СХД, RAID массив на СХД)
  4. Упрощенный процесс аварийного восстановления: При использовании зеркалирования СХД в другой ЦОД, становится возможным быстро восстановить работоспособность инфраструктуры (т.к. в процесс зеркалирования рабочих данных можно включить загрузочные образа)
  5. Снижение затрат: Нет надобности в локальных дисках, снижение затрат на обслуживание и т.д
Перечислим основные шаги, которые необходимо выполнить в процессе настройки загрузки с SAN:
  1. Выполните физическое подключение HBA адаптера, коммутаторов SAN, системы хранения данных.
  2. Создайте LUN на СХД, как минимум один на операционную систему.
  3. Выключите встроенный RAID контроллер в BIOS/UEFI сервера.
  4. Настройте один порт HBA адаптера для загрузки с SAN.
  5. Настройте зонинг на FC коммутаторах.
  6. Настройте маппинг LUN к серверу.
  7. Установите операционную систему.
  8. Установите и настройте драйвер мультипасинга.
  9. Настройте второй порт HBA адаптера.
  10. Настройте зонинг для второго порта HBA адаптера.
  11. Настройте маппинг для второго порта HBA адаптера.
Настройка HBA адаптера для инсталляции ОС
Сначала отключим контроллер Serial Attached SCSI (SAS) для того, чтобы увеличить скорость загрузки сервера. Для этого включите сервер и нажмите F1, для того что бы зайти в меню конфигурирования BIOS или UEFI.
Для серверов с BIOS: выберите Devices and I/O ports”.
Рисунок 2
Далее выключите “Planar SAS”.
Рисунок 3
Для серверов с UEFI: выберите “System Settings”.
Рисунок 4

Далее выберите ”Devices and I/O Ports”.
Рисунок 5
В появившемся меню выключите “Planar SAS”.
Рисунок 6

Чтобы провести установку ОС необходимо подключить LUN по одному пути, т.к. на первом этапе установки ОС не работает драйвер мультипасинга. Однако для RHEL 5 и 6 можно настроить HBA адаптер сразу на все доступные пути (см. замечания по инсталляции ОС).
Перегрузите сервер, в процессе загрузки нажмите ”CTRL+Q” для того, чтобы зайти в меню конфигурирования HBA адаптера.

Рисунок 7

Выберите первый FC адаптер.
Рмсунок 8

Зайдите в ”Configuration Settings”.
Рисунок 9

Выберите “Adapter Settings”.
Рисунок 10

Включите “Host Adapter BIOS" (по умолчанию эта опция отключена), и запишите или запомните WWPN этого HBA адаптера. Это понадобится для того, чтобы идентифицировать данный сервер при настройке СХД.
Рисунок 11

Нажмите ”ESC” два раза и сохраните изменения.
Рисунок 12

Зная WWPN адаптера теперь можно настроить зонинг на свичах, создать LUN на СХД, и настроить маппинг LUN'а к серверу.Выполните эти действия.
Проведем сканирование FC путей. Выберите “Scan Fibre Devices” как на рисунке 9. Если все корректно настроено, то в меню будут отображены пути к СХД.
Рисунок 13

Выйдите из этого пункта меню и зайдите в ”Configuration Settings” как на рисунке 9. Выберите ”Selectable Boot Settings” как на рисунке 10. Включите ”Selectable Boot”, по умолчанию он выключен.
Рисунок 14

Перейдите пунктом ниже для выбора пути загрузки - ”Primary Boot Port Name”.
Рисунок 15

Выберите один путь и нажмите ”Enter”. На этом пункте меню будут перечислены LUN которые доступны серверу. Номера LUN перечисленные здесь будут зависеть от номеров ID, присвоенных LUN на СХД. Выберите LUN с ID 0.
Рисунок 16
 Рисунок 14 примет вид:
Рисунок 17

Нажмите ”ESC” и сохраните внесенные изменения. После перезагрузки LUN будет доступен, его можно увидеть в момент инициализации HBA адаптера, и можно будет осуществить инсталляцию операционной системы.
Рисунок 18
После установки ОС необходимо настроить мультипасинг (см. замечания по инсталляции ОС).
Включим второй FC порт для обеспечения отказоустойчивости. Порядок настройки аналогичен вышеописанному, за исключением того, что нужно выбрать второй порт адаптера.
Рисунок 19

Добавьте все FC пути, доступные по второму порту.
Рисунок 20

Не забудьте добавить также остальные пути для первого порта HBA адаптера.
Настройка FC зон
Настройте FC зоны на коммутаторах SAN. Все хосты которые будут загружаться с SAN, должны находится в соответствующих зонах с СХД. Планирование и корректность реализации зон очень важна для стабильности функционирования SAN.
Создание загрузочного LUN и настройка СХД
Создайте LUN на схд, который будет содержать загрузочный образ операционной системы. Добавьте хост и настройте маппинг с LUN. При добавлении хоста укажите тип хоста, данное значение зависит от операционной системы и драйвера мультипасинга. Доступ к LUN должен иметь только соответствующий сервер, т.е. должен быть гарантирован монопольный доступ. LUN должен обязательно иметь ID 0.
Установка операционной системы
Как уже упоминалось, инсталляцию ОС необходимо проводить при подключенном LUN по одному пути, поскольку на первом этапе установки ОС не работает драйвер мультипасинга. Необходимо отметить - эти рекомендации точны для семейства ОС Windows, для RHEL 5 и 6 можно настроить HBA адаптер сразу на все доступные пути. В этом случае установку RHEL 5 нужно проводить с параметром ”mpath”, а в случае RHEL 6 драйвер мультипасинга загружается штатно при установке ос.
Инструкции по установке ОС Windows 2008 и настройке мультипасинга можно найти здесь и здесь. Инструкции по настройке мультипасинга для Red Hat Enterprise Linux 6.x можно найти здесь.


среда, 3 октября 2012 г.

Удаление писем из очереди postfix


Несомненно, каждый администратор unix подобной операционной системы сталкивался с необходимостью чистить очередь почтовых сообщений. Посмотреть очередь сообщений можно командой:

[root@server ~]# mailq
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
BD65F10DEE4*     4089 Wed Oct   3 00:29:01   sender@domain.ru
                                             resipient@domain.ru



C7D0E10DEE9      4457 Wed Oct   3 00:30:15   sender@domain.ru
(host imx1.rambler.ru[81.19.66.234] said: 452 4.7.1 Try again later (in reply to DATA command))
                                             recipient@rambler.ru


Как можно заметить в выводе команды две или три строки описывают одно письмо, поля вывода:

  1. Идентификатор сообщения в очереди, если после идентификатора стоит знак "*" - письмо находится в активной очереди на доставку, если знак "!" - письмо находится в очереди ожидания и попыток доставки его производится не будет.
  2. Размер сообщения.
  3. Время принятия письма.
  4. Отправитель сообщения.
  5. В выводе команды может быть указана причина по которой письмо не отправлено и осталось в очереди на доставку.
  6. Получатель сообщения.

Удалить письмо можно командой:

[root@server ~]# postsuper -d идентификатор_сообщения

Таким образом, посмотрев вывод mailq можно найти требуемое письмо по отправителю, получателю или по сообщению о не возможности доставки в данный момент (в примере rambler.ru просит нас отправить письмо позже). Все как бы хорошо, но что делать если в организации периодически производят рассылки и писем сотни или даже тысячи?  Достаточно просто сделать выборку по отправителю, т.к. отправитель и нужный нам идентификатор находятся в одной строке.

[root@server ~]# mailq | grep "sender" | awk '{ print $1 }' | sed s/*// | postsuper -d -

А если нужно сделать выборку по получателю или сообщению о не возможности доставки? Какого то готового рецепта я не нашел в интернете, хотя нужно было очень срочно. Итак, нужно все данные по каждому письму объединить в одну строку. Привожу ниже то что получилось у меня:

[root@server ~]# mailq | grep -v "Queue ID" | while read line; do if [ "1" != `echo $line | wc -m` ]; then echo -n " "$line; else echo""; fi ; done | grep "sender or non delivery message" | awk '{ print $1 }' | postsuper -d -

Используя свои данные вместо тех что указаны в примере "sender or non delivery message" можно легко очистить очередь от ненужных писем. 


пятница, 24 февраля 2012 г.

Управление конфигурацией в it инфраструктуре ч.2

Начнем воплощать в жизнь вторую часть. Ранее я писал скрипты которые работают с интерактивными приложениями или устройствами на expect'е. Трудность такой реализации это то что логику скрипта надо будет писать на TCL, или дробить задачу - писать логику на shell и из него вызывать кусочки на expect. Это не самый удобный путь. Ну а второе, почему мне не хотелось писать на expect'е - когда то давно я похвастался одному знакомому java программисту, что я пишу на tcl. На что он мне сказал -  "На нем пишут бородатые дядьки", отчасти это так.
Для python есть модуль реализующий функциональность expect - pyexpect. Соответственно скрипт я написал на python. Скрипт достаточно легко изменить под собственные нужды, используя тот же самый алгоритм. На python я ранее ничего не писал, поэтому буду рад услышать конструктивные замечания. Справедливости ради надо сказать, что для perl тоже есть аналогичный модуль. Ничто не запрещает реализовать все на нем.
Установим модули которые нам понадобятся:

[root@server ~]# yum install pexpect pysvn python-iniparse

Модуль pysvn будет использоваться для работы с репозиторием, а iniparse для разбора конфигурационного файла.
Что бы сократить размер приведенного здесь скрипта, я уменьшил количество видов устройств до двух, обладающих наиболее отличными друг от друга механизмами резервного копирования конфигурации. Это коммутаторы Brocade Silkworm (мне доступны коммутаторы двух моделей Brocade 5380 и входящие в HP C7000 - Brocade 4024) и пара кластеров IBM SAN Volume Controller(сокращенно svc). Опишу как выполняется резервное копирование конфигурации на этих устройствах. Резервирование конфигурации на коммутаторах Brocade можно выполнить командой (для версии Fabric OS: v6.2.2d):

RUMOWDRCENC005_LEFT:admin> configupload -all -scp host,user,path

где host, user, path - сервер, пользователь и путь на файловой системе сервера, на который будет записан конфигурационный файл. Передача конфигурационного файла осуществляется по протоколу scp.
Резервирование конфигурации кластера svc выполняется в два приема. Мне доступны два кластера с разной прошивкой - v5.1.0.1 и v6.3.0.1(один обновил, а второй еще нет). Сначала формируются файлы конфигурации:

IBM_2145:SVCMOS1P1:admin> svcconfig backup

которые затем надо забрать c svc (в отличие от резервирования конфигурации на коммутаторах Brocade):

[root@server ~]# scp -i ~/.ssh/svc.key svc.config.backup.xml admin@svc_ip:/tmp/svc.config.backup.*

Как вы заметили, аутентификация осуществляется по ключу. Конфигурационных файлов у svc -  три: svc.config.backup.sh, svc.config.backup.log и svc.config.backup.xml.
Дополнительно мы будем следующую информацию: состояние портов на свичах:

RUMOWDRCENC005_LEFT:admin> switchshow

и состояние пулов схд на svc:

IBM_2145:SVCMOS1P1:admin> svcinfo lsmdiskgrp

Листинг конфигурационного файла:

[confrepuser@server ~]$ cat config.ini 
[system]
host=192.168.1.100
password = cfgbackup
path = confrepo/devices/

[brocade1]
login = admin
password = password1
RUMOWDRCENC005_LEFT = Yes
RUMOWDRCENC005_RIGHT = yes

[brocade2]
login = admin
password = password2
BDMOS101L01 = True
BDMOS101R01 = 1
BDMOS201L01 = 0
BDMOS201R01 = False

[svc1]
login = admin
key = /home/confrepuser/.ssh/svc.key
svcmos1 = Yes
svcmos2 = No

Конфигурационный файл разбит на секции, обязательная из которых system. Параметры секции  system: host - ip или днс имя сервера на котором содержится рабочая копия репозитория; password - пароль пользователя от имени которого выполняется скрипт; path - путь на файловой системе, куда будут записываться конфигурационные файлы устройств.
Остальные секции именуются в соответствии с классом устройства (секции устройств), т.е. все секции, название которых начинается с "brocade" будут рассматриваться как секции содержащие коммутаторы Brocade. Абсолютно аналогично с svc. Параметры секций устройств логически состоят из двух частей, параметры используемые при аутентификации на устройстве (для примера: login - имя пользователя используемое при входе на устройство) и на параметры, название которых указывает на устройства (к примеру svcmos1 - название кластера svc, которое должно иметь соответствующую запись в днс или запись в файле /etc/hosts). Параметр указывающий на устройство является булевой переменной, положительное значение которого означает то, что с устройства будет выполнятся резервирование конфигурации.
Итак, листинг скрипта:

[confrepuser@server ~]$ cat geconfig.py 
#!/usr/bin/python
#-*- coding: utf-8 -*-

import pexpect,sys,pysvn,re,os
from iniparse import ConfigParser

# Check directory exist, and make if not.
def ensure_dir(dir):
    if not os.path.exists(dir):
       os.makedirs(dir)
       client.add(dir)
       client.checkin(dir, 'Add dir '+dir)

# Get brocade config
def getbrconf(login, password, brocade, dir):
    ssh_newkey = 'Are you sure you want to continue connecting'
    list_files = []
    child = pexpect.spawn("ssh "+login+"@"+brocade)
    #For debug purpose
    #child.logfile = sys.stdout

    i=child.expect([pexpect.EOF,ssh_newkey,'password:'],timeout=60)
    if i==0:
       print "Configuration file from", brocade,"is not received"
       return
    if i==1:
       child.sendline('yes')
       i=child.expect([ssh_newkey,'password:',pexpect.EOF],timeout=60)
    if i==2:
       child.sendline(password)

    child.expect (':'+login+'> ')
    child.sendline('configupload -all -scp '+host+','+username+','+devicepath+dir+'/'+brocade)
    child.expect ('password:')
    child.sendline(userpassword)
    child.expect (':'+login+'> ')
    # Get some state
    f = open(dir+'/'+brocade+'-state', 'w')
    child.sendline ('switchshow')
    child.expect (':'+login+'> ')
    f.write(child.before)
    child.sendline ('exit')
    list_files.extend(['./'+dir+'/'+brocade, './'+dir+'/'+brocade+'-state'])
    for file in list_files:
        if not client.info(file):
           # File added with "segmentation filed" bug!
           #client.add(file)
           child = pexpect.spawn('/usr/bin/svn add '+file)
           child.expect ('\r\n')

# Get ibm svc config
def getsvcconf(login, key, svc, dir):
    ssh_newkey = 'Are you sure you want to continue connecting'
    svc_files = ['svc.config.backup.sh', 'svc.config.backup.log', 'svc.config.backup.xml']
    list_files = []
    child = pexpect.spawn("ssh -i"+key+" "+login+"@"+svc)
    #For debug purpose
    #child.logfile = sys.stdout

    i=child.expect([pexpect.EOF,ssh_newkey,':'+login+'>'],timeout=60)
    if i==0:
       print "Configuration file from", svc,"is not received"
       return
    if i==1:
       child.sendline('yes')
    if i==2:
       child.sendline('svcconfig backup')
       child.expect (':'+login+'>')
       # Get some state
       f = open(dir+'/'+svc+'-state', 'w')
       child.sendline ('svcinfo lsmdiskgrp')
       child.expect (':'+login+'>')
       f.write(child.before)
       child.sendline ('exit')
       list_files.append('./'+dir+'/'+svc+'-state')
    # Get config from svc
    for file in svc_files:
        child = pexpect.spawn('/usr/bin/scp -i'+key+' '+login+'@'+svc+':/tmp/'+file+' '+dir+'/'+svc+'-'+file)
        # Expect new line
        child.expect ('\r\n')
        list_files.append('./'+dir+'/'+svc+'-'+file)
    # Check if file exist in svn and add file if not.
    for file in list_files:
        if not client.info(file):
           # File added with "segmentation filed" bug! 
           #client.add(file)
           child = pexpect.spawn('/usr/bin/svn add '+file)
           child.expect ('\r\n')


# Main program
# Read configuration file
cfgpr = ConfigParser()
cfgpr.read('config.ini')
client = pysvn.Client()

username = os.getenv('LOGNAME')
host = cfgpr.get('system','host')
userpassword = cfgpr.get('system','password')
devicepath = cfgpr.get('system','path')

# Get configurations
for section in cfgpr.sections():
    if re.match("brocade", section):
       ensure_dir(section)
       password = cfgpr.get(section,'password')
       login = cfgpr.get(section,'login')
       for option in cfgpr.options(section):
           if option != "password":
              if option != "login":
                 if cfgpr.getboolean(section, option):
                    getbrconf(login, password, option, section)
    if re.match("svc", section):
       ensure_dir(section)
       key = cfgpr.get(section,'key')
       login = cfgpr.get(section,'login')
       for option in cfgpr.options(section):
           if option != "key":
              if option != "login":
                 if cfgpr.getboolean(section, option):
                    getsvcconf(login, key, option, section)

# Update repo
client.checkin('./', 'Update repository')


В скрипте производится последовательный разбор конфигурационного файла с последующим вызовом соответствующей процедуры (т.е. или забираем конфигурационный файл с коммутатора - процедура getbrconf или с svc - getsvcconf). В целом, исходный текст скрипта достаточно подробно комментирован, так что я думаю разобраться в нем не составит труда. К сожалению модуль pysvn имеет ошибку, добавление файла в репозиторий заканчивается "Segmentation fault", поэтому добавление файлов реализовано средствами команды svn.
Создадим рабочую копию репозитария:

[confrepuser@server ~]$ svn co file:///var/www/svn/confrepo

Теперь для завершения задачи, достаточно поместить файлы config.ini и geconfig.py в ~/confrepo/devices и добавить задание в cron для запуска скрипта. Файл скрипта и конфигурационный файл так же можно поместить в репозиторий. Будьте осторожны, поскольку в config.ini находятся пароли!