воскресенье, 5 июня 2016 г.

Перенос системы с mdadm RAID1 на mdadm RAID1+LVM

Ранее я уже писал о том, как перевести установленную на диск систему на два диска, объединённые в программный массив RAID1: Перевод работающей системы Debian на RAID 1. На этот раз я задумался о том, чтобы переделать DOS-разделы диска в логические тома LVM. LVM может пригодиться для размещения виртуальных машин под управлением Xen, для более безболезненного переноса системы на другие физические диски, для изменения размеров разделов, их создания и уничтожения.

Стратегия перехода была такая:
  1. Исключаем из настроенного RAID-массива один из дисков, так что у нас появляется один свободный диск и один деградировавший RAID-массив,
  2. Создаём деградировавший RAID-массив на освободившемся диске, выполняем разбивку, переносим на него данные,
  3. Выполняем загрузку системы с флешки, синхронизируем накопившиеся изменения, настраиваем загрузку системы с нового диска,
  4. Грузим систему с нового диска, удаляем старый RAID-массив, разбиваем его аналогично новому, включаем в новый RAID-массив в качестве второй половинки.
В комментариях к прошлой статье о переходе на RAID1 мне писали, что статья не годится, т.к. кто-то сломал систему и теперь не может её загрузить. Сам я по той статье переводил три системы и с проблемами не сталкивался. Насчёт этой статьи хочу сразу предупредить, что здесь нет готового на 100% работающего рецепта. Мне самому пришлось изрядно помучиться на этапе загрузки системы с флешки и последующей загрузки новой системы, т.к. нужно хорошо разбираться в нюансах ручной сборки RAID-массивов, определения LVM-томов, генерации файлов конфигурации загрузчика GRUB, создания загрузочных образов системы initramfs и работы с режимом восстановления на загрузочной флешке. Для этого этапа я лишь приведу несколько команд, которые наверняка пригодятся вам, если вы всё-таки решите попробовать проделать то же самое.

Приступим.

1. Извлечение одного из дисков из RAID-массива

Посмотрим на разделы одного из двух дисков:
# fdisk -l /dev/sda 

Disk /dev/sda: 931,5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x9a7a0fdb

Device     Boot     Start        End    Sectors   Size Id Type
/dev/sda1            2048    1977979    1975932 964,8M fd Linux raid autodetect
/dev/sda2         1978368   41064512   39086145  18,7G fd Linux raid autodetect
/dev/sda3  *     41066496   62208035   21141540  10,1G  7 HPFS/NTFS/exFAT
/dev/sda4        62210048 1953525167 1891315120 901,9G  5 Extended
/dev/sda5        62212096  140352192   78140097  37,3G  7 HPFS/NTFS/exFAT
/dev/sda6       140355584 1953525167 1813169584 864,6G fd Linux raid autodetect
Разделы sda1, sda2 и sda6 - это половинки RAID-массивов md1, md2, md6. На md1 расположен раздел подкачки, на md2 - корневой раздел Linux, на md6 - раздел home.

Разделы sda3 и sda5 являются разделами NTFS, на первый из которых когда-то был установлен Windows, а второй использовался для хранения данных для Windows. На разделах sdb3 и sdb5 были расположены посекторные резервные копии этих разделов.

Выведем из RAID-массивов диск /dev/sda:
# mdadm --manage /dev/md1 --fail /dev/sda1
# mdadm --manage /dev/md2 --fail /dev/sda2
# mdadm --manage /dev/md6 --fail /dev/sda6
2. Новая разбивка диска

Я решил воспользоваться консервативной схемой разбивки, когда GRUB будет находиться вне логических томов LVM, на отдельном разделе. Мне показалось, что так будет проще его починить, если что-то пойдёт не так. Новая схема разделов стала следующей:
# fdisk -l /dev/sda 

Disk /dev/sda: 931,5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x382c6e6a

Device     Boot  Start        End    Sectors   Size Id Type
/dev/sda1  *      2048     411647     409600   200M fd Linux raid autodetect
/dev/sda2       411648 1953525167 1953113520 931,3G fd Linux raid autodetect
На созданных разделах я создал деградировавшие массивы RAID1, в которых пока что не хватает второй половинки:
# mdadm --create /dev/md11 -l1 -n2 missing /dev/sda1
# mdadm --create /dev/md12 -l1 -n2 missing /dev/sda2
Создадим файловую систему для будущего раздела /boot, на котором будет находиться загрузчик GRUB:
# mkfs.ext4 /dev/md11
Теперь установим менеджер томов, если он ещё не был установлен:
# apt-get install lvm2
Создадим физический том на разделе:
# pvcreate /dev/md12
Создадим группу томов stupin, в котором будет один физический том /dev/md12:
# vgcreate stupin /dev/md12
Создадим логический том размером 1 гигабайт для раздела подкачки:
# lvcreate -n dom0-swap -L 1G stupin
И разметим его как раздел подкачки:
# mkswap /dev/stupin/dom0-swap
Создадим логический том размером в 20 гигабайт для корневого раздела системы:
# lvcreate -n dom0-root -L 20G stupin
И разметим на нём файловую систему ext4:
# mkfs.ext4 /dev/stupin/dom0-root
Создадим логический том для раздела /home и разметим на нём файловую систему ext4:
# lvcreate -n dom0-home -L 800G stupin
# mkfs.ext4 /dev/stupin/dom0-home
3. Копирование разделов ext4

Для копирования ext4 я решил воспользоваться rsync. Создадим точки монтирования будущих разделов /mnt, /mnt/boot, /mnt/home:
# mkdir /mnt
# mount /dev/stupin/dom0-root /mnt/
# mkdir /mnt/boot
# mount /dev/md11 /mnt/boot/
# mkdir /mnt/home
# mount /dev/stupin/dom0-home /mnt/home/
И выполним первоначальное копирование данных на новые разделы:
# rsync -xavv --delete /home/ /mnt/home/
# rsync -xavv --delete / /mnt/
Этот этап копирования имеет целью уменьшить количество файлов, которые нужно будет скопировать во время загрузки системы с флешки. После загрузки системы с флешки копирование будет повторено с тем чтобы скопировать изменившиеся файлы.

4. Копирование NTFS-разделов

Для копирования NTFS-разделов я решил воспользоваться утилитой dd, хотя мог бы воспользоваться и утилитой ntfsclone. Здесь я изначально копировал диски остановленной системы, поскольку она бывает мне нужна лишь иногда и обычно выключена.

Создадим логические тома LVM с размером точно равным количеству секторов на исходных разделах:
# lvcreate -L 21141540S -n winxp-c-disk stupin
# lvcreate -L 78140097S -n winxp-d-disk stupin
И скопируем на них данные посекторно:
# dd if=/dev/sdb3 of=/dev/stupin/winxp-c-disk
# dd if=/dev/sdb5 of=/dev/stupin/winxp-d-disk
5. Загрузка с флешки

Этот момент - самый сложный и ответственный. По идее, если у вас ничего не получится, вы можете загрузить систему со старого диска, переразбить диск, который планировали использовать под LVM, и включить его обратно в зеркало. На этом неудачный опыт будет завершён и система вернётся в то состояние, в котором она находилась изначально.

Я использовал установочную флешку с Debian Jessie. Загрузившись с флешки нужно выбрать режим восстановления (rescue mode), через её меню определить RAID-массивы и логические тома, смонтировать корневой раздел и раздел /boot и перейти в командную строку в среду, где корнем является корневой раздел восстанавливаемой системы.

Попав в оболочку, для начала домонтируем будущий раздел /home:
# mount /dev/stupin/dom0-home /home
Теперь смонтируем разделы исходной системы для того, чтобы синхронизировать накопившиеся на ней изменения в будущую систему:
# mount /dev/sdb2 /mnt
# mount /dev/sdb6 /mnt/home
Скопируем изменения:
# rsync -xavv --delete /mnt/home/ /home/
# rsync -xavv --delete /mnt /
В прошлой статье я не останавливался подробно на моменте правильного переноса данных, поскольку считал, что статьёй воспользуются хорошо подготовленные пользователи, которые проделают ровно то же самое - синхронизируют изменения, загрузившись с флешки. В этот раз загрузка с флешки - необходимый этап, поэтому я решил чуть подробнее описать и момент переноса данных.

Теперь нужно сделать так, чтобы система загрузилась с нового диска. Сначала посмотрим идентификаторы UUID у имеющихся дисков и разделов:
# blkid
Впишем в файл /etc/fstab раздел подкачки, корневой раздел, разделы /boot и /home, указав их идентификаторы из вывода команды blkid:
# vim /etc/fstab
Обновим список RAID-массивов имеющихся в системе в образе initramfs:
# mdadm --examine --scan > /etc/mdadm/mdadm.conf
# update-initramfs -k all -u
Установим GRUB на новый диск и обновим его конфигурацию:
# grub-install /dev/sda
# update-grub
6. Загрузка новой системы

После этого можно выйти из оболочки и выбрать перезагрузку. В BIOS нужно выбрать загрузку с нового диска, а старый можно вообще для наглядности отсоединить, чтобы точно быть уверенным, что загрузка произошла с нового диска.

Если в процессе загрузки не появилось меню GRUB, то нужно проверить, что GRUB установлен, а его конфигурация обновлена. Для этого нужно снова загрузиться с флешки в режиме восстановления и убедиться, что grub-install сработал.

Если система не загрузилась и остановилась на этапе выполнения меню GRUB, то возможно дело в том, что GRUB не нашёл образ ядра или образ initramfs. В таком случае в загрузочной флешке нужно убедиться, что отработало обновление файла конфигурации GRUB при помощи команды grub-update.

Если система не загрузилась и перешла в оболочку initramfs, то скорее всего ядро не нашло корневой раздел. Нужно проверить, что корневой раздел определился в системе и имеется в каталоге /dev/stupin/ (stupin - имя логической группы) или в /dev/mapper/. Если он на месте, тогда нужно проверить, что он правильно указан в файле /etc/fstab.

В образе initramfs могут пригодиться следующие команды.

Поиск имеющихся RAID-массивов и обновление конфигурации:
# mdadm --examine --scan > /etc/mdadm/mdadm.conf
Сборка RAID-массивов вручную, после которой массивы должны появиться в каталогах /dev и /dev/md:
# mdadm --assemble /dev/md11
# mdadm --assemble /dev/md12
Определение доступных групп томов и логических томов LVM:
# vgchange -ay
Для редактирования файла /etc/fstab в образе initramfs имеется редактор vi.

После того, как вы убедились, что все RAID-массивы и логические тома определились системой, а в /etc/fstab указаны правильные разделы для монтирования, можно попробовать выйти из оболочки initramfs и продолжить загрузку системы.

В загрузившейся системе нужно повторить проделанные манипуляции, а затем обновить образ initramfs и файл конфигурации GRUB. После этого можно попробовать перезагрузить систему и проверить, грузится ли она автоматически, без ручного вмешательства. Когда система будет грузиться с нового раздела автоматически, можно подсоединить отсоединённый диск и продолжить. Если же вы не смогли добиться устойчивой автоматической загрузки системы, можно переключиться на загрузку со старого диска и вернуть всё обратно.

7. Добавление второй половины в новый RAID-массив

Теперь скопируем разбиение с нового диска на старый:
# sfdisk --dump /dev/sda | sfdisk /dev/sdb
И добавим разделы старого диска в зеркало:
# mdadm --manage /dev/md11 --add /dev/sdb1
# mdadm --manage /dev/md12 --add /dev/sdb2
Не забудьте поставить GRUB на второй диск:
# grub-install /dev/sdb
8. Переименование RAID-массивов

Есть ещё один не обязательный момент. Мне хотелось переименовать RAID-массивы так, чтобы они назывались md1 и md2, а не md11 и md12. Для этого я снова загрузился с флешки, разобрал RAID-массивы и собрал их уже под новыми именами:
# mdadm --stop /dev/md11
# mdadm --stop /dev/md12
# mdadm --assemble --update=name --name=1 /dev/md1 /dev/sda1 /dev/sdb1
# mdadm --assemble --update=name --name=2 /dev/md2 /dev/sda2 /dev/sdb2
Осталось обновить конфигурацию mdadm в initramfs:
# mdadm --examine --scan > /etc/mdadm/mdadm.conf
# update-initramfs -k all -u

воскресенье, 29 мая 2016 г.

Установка Windows XP в Xen

Возникла задача поставить Windows для запуска программы, которая не работает в Wine. Решил попробовать установить Windows под управлением Xen. Ранее я уже писал небольшую заметку о настройке Xen: Памятка по настройке Xen. В той статье для управления Xen использовалась утилита xm, поскольку писалась она применительно к Debian Wheezy. В этот раз будет использоваться утилита xl, поскольку дело происходит в Debian Jessie. Однако, несмотря на это различие, всё написанное в прошлой статье будет работать и сейчас. Надо всего лишь вместо xm использовать xl.

1. Установка операционной системы на виртуальную машину

Создадим LVM-раздел, куда будем устанавливать Windows:
# lvcreate -L10G -n winxp-disk
Создадим файл конфигурации /etc/xen/winxp.cfg, который первоначально будет использоваться для установки системы:
builder = 'hvm'
device_model_version = 'qemu-xen'
memory = 1024
vcpus = 1
pae = 0
acpi = 0
apic = 0
name = 'winxp'
disk = ['phy:/dev/vg0/winxp-disk,ioemu:hda,w',
        'phy:/home/stupin/WindowsXP_SP2.iso,ioemu:hdb:cdrom,r']
boot = 'd'

on_poweroff = 'destroy'
on_reboot = 'destroy'
on_crash = 'destroy'
on_xend_start = 'ignore'
on_xend_stop = 'ignore'

fullscreen = 1
sdl = 0
vnc = 1
vncconsole = 1
vncpasswd = ''
keymap = 'ru'
stdvga = 0
serial = 'pty'

usb = 1
usbdevice = 'tablet'
Особо стоит отметить следующие моменты в этом файле:
  • Опции acpi (интерфейс управления электропитанием) и apic (улучшенный контроллер прерываний) на время установки отключены,
  • В опции disk первым прописан LVM-раздел, в который будем устанавливать систему, а вторым прописан ISO-образ установочного диска с Windows,
  • Опция boot выставлена в значение d - загрузка "с диска D:", то есть - с компакт-диска, в роли которого выступает ISO-образ установочного диска,
  • Опция keymap позволяет в дальнейшем не следить за раскладкой на системе, где запущен VNC-клиент. Без этой опции в сеансе VNC русские буквы удастся ввести только в случае, если на системе с VNC-клиентом включена английская раскладка,
  • Включена поддержка usb, а в списке USB-устройств в опции usbdevice настроен "планшет". Эта настройка позволяет в дальнейшем без проблем манипулировать курсором мыши. Без неё при подключении через VNC будет два курсора мыши, слабо связанных между собой, так что управляться ими будет непросто.
Теперь запустим виртуальную машину:
# xl create /etc/xen/winxp.cfg
На всякий случай, если вдруг виртуальная машина зависнет, приведу команду для её принудительного выключения:
# xl destroy winxp
Напоминаю, что список запущенных виртуальных машин можно посмотреть такой командой:
# xl list
После запуска можно подключиться к виртуальной машине при помощи VNC-клиента на TCP-порт 5900 по IP-адресу 5900. Я воспользовался Remmina, о которой писал в одноимённой заметке - Remmina:

Если Вы хотите подключиться по сети не из домена dom0 или у Вас имеется несколько подобных доменов domU, к которым Вы хотите подключаться по протоколу VNC, можно настроить прослушиваемый адрес и порт при помощи опции vnclisten. Например, значение 192.168.0.1:2 будет соответствовать ожиданию подключений на TCP-порт 5902 и адрес 192.168.0.1.

Настроить переключение раскладки по нажатию Alt+Shift мне не удалось - это сочетание в сеанс VNC не попадало, поэтому пришлось настроить непривычное для меня сочетание Ctrl+Shift.

2. Изменение настроек после установки

После установки Windows нужно выключить виртуальную машину, воспользовавшись пунктом меню "Выключить компьютер", доступным по нажатию кнопки "Пуск":

Теперь нужно немного изменить конфигурацию в файле /etc/xen/winxp.cfg. Включим опции acpi и apic, уберём из списка дисков ISO-образ установочного компакт-диска и поменяем значение опции boot на c - загрузка "с диска C:":
acpi = 1
apic = 1
disk = ['phy:/dev/vg0/winxp-disk,ioemu:hda,w']
boot = 'c'
3. Проброс USB-устройств вовнутрь виртуальной машины

Ещё одна вещь, которая мне понадобилась - это пробросить флешку вовнутрь виртуальной машины. Для начала я вставил её в компьютер и нашёл её в списке имеющихся в системе USB-устройств при помощи команды:
$ lsusb -v | less
В несколько сокращённом виде, нужная мне флешка выглядела следующим образом:
Bus 001 Device 005: ID 0930:6534 Toshiba Corp. TravelDrive
Device Descriptor:
  ...
  idVendor           0x0930 Toshiba Corp.
  idProduct          0x6534 TravelDrive
  bcdDevice            1.00
  iManufacturer           1 Kingston
  iProduct                2 DataTraveler 2.0
  iSerial                 3 0201101728450
  bNumConfigurations      1
  Configuration Descriptor:
    ...
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass         8 Mass Storage
Чтобы флешка автоматически пробрасывалась в виртуальную машину, нужно отредактировать список USB-устройств в файле конфигурации /etc/xen/winxp.cfg:
usbdevice = ['tablet', 'host:0930:6534']
Если в системе имеется несколько устройств с одинаковыми идентификаторами производителя и модели, то можно указать номер шины и устройства. В нашем случае это будет выглядеть вот так:
usbdevice = ['tablet', 'host:1.5']
Однако стоит учесть, что при отключении и повторном включении устройство может получить другой номер. Использовать идентификаторы производителя и модели.

В случае с утилитой xm можно было бы вставлять и удалять устройства налету, вот так:
# xm usb-add winxp host:0930:6534
# xm usb-del winxp host:0930:6534
Однако, в утилите xl подобная функциональность пока не реализована и для введения настроек в силу понадобится завершить работу виртуальной машины и запустить её снова, с использованием исправленной конфигурации.

4. Использованные материалы

воскресенье, 22 мая 2016 г.

Мониторинг Asterisk по протоколу SNMP

Меня заинтересовало наличие в Asterisk модуля res_snmp. Я решил попробовать настроить его и узнать, за какими параметрами Asterisk можно наблюдать с его помощью.

1. Установка и настройка SNMP-агента

Устанавливаем SNMP-агента:
# apt-get install snmpd
Нужно заглянуть в файл /etc/default/snmpd и убедиться, что запуск SNMP-агента разрешён:
SNMPDRUN=yes
Редактируем файл конфигурации SNMP-агента /etc/snmp/snmpd.conf, приведя к следующему виду:
agentAddress udp:127.0.0.1:161
  
view asterisk included .1.3.6.1.2.1.1.1
view asterisk included .1.3.6.1.2.1.1.2
view asterisk included .1.3.6.1.2.1.1.4
view asterisk included .1.3.6.1.2.1.1.5
view asterisk included .1.3.6.1.2.1.1.6
view asterisk included .1.3.6.1.4.1.22736

rocommunity public 127.0.0.1 -V asterisk
rwcommunity private 127.0.0.1 -V asterisk

createUser zabbix SHA auth_password AES encryption_password
rouser zabbix priv -V asterisk

sysLocation Ufa
sysContact Vladimir Stupin <vladimir@stupin.su>
sysObjectID .1.3.6.1.4.1.22736.1

master agentx
agentXSocket /var/agentx/master
agentXPerms 0660 0775 nobody asterisk
Указанный выше файл конфигурации является лишь примером. Реально вы можете захотеть поменять часть настроек. Например:
  • agentAddress - прослушиваемый SNMP-агентом IP-адрес,
  • view asterisk included - в этом представлении я ограничил доступ к OID'ам. Доступ разрешён только к OID'ам, содержащим информацию об узле и к дереву OID'ов с состоянием Asterisk,
  • rocommunity - строка сообщества для чтения данных для SNMP версий 1 и 2c,
  • rwcommunity - строка сообщества для записи данных для SNMP версий 1 и 2c,
  • createUser - строка описывает одного пользователя SNMP версии 3 - его имя, пароли и алгоритмы аутентификации и шифрования,
  • rouser - описывает права доступа пользователя SNMP версии 3,
  • sysLocation - строка местонахождения оборудования. Бывает полезно в больших компаниях, когда имеется много оборудования и сотрудников, или оборудование расположено в необычном месте: за фальшь-потолком или на радиомачте,
  • sysContact - строка с контактными данными администратора оборудования. Бывает полезно в больших компаниях, чтобы найти сотрудника, ответственного за оборудование,
  • sysObjectID - идентификатор типа оборудования. Полезно, например, для автоматического обнаружения оборудования и автоматической постановки на контроль с шаблоном, соответствующим этому OID'у,
  • master, agentXSocket, agentXPerms задают настройки Unix-сокета SNMP-агента, к которому будут подключаться субагенты.
Для генерации строк сообщества и паролей я рекомендую воспользоваться, например, программой pwgen, которую можно установить из одноимённого пакета:
# apt-get install pwgen
Сгенерировать 16-символьный пароль можно следующим образом:
$ pwgen 16
Чтобы Asterisk, запущенный от пользователя asterisk, имел доступ к каталогу с Unix-сокету SNMP-агента, меняем права доступа к каталогу /var/agentx:
# chmod o+rx /var/agentx
Перезапускаем SNMP-агента:
# systemctl restart snmpd.service
2. Включение SNMP-модуля в Asterisk

Открываем файл /etc/asterisk/res_snmp.conf и приводим его к следующему виду:
[general]
subagent = yes
enabled = yes
После чего просим Asterisk выгрузить модуль SNMP и загрузить его снова:
# asterisk -rx 'module unload res_snmp.so'
# asterisk -rx 'module load res_snmp.so'
3. Использование MIB-файлов

Посмотреть OID'ы в виде дерева:
$ snmptranslate -M /var/lib/mibs/:/var/lib/mibs/ietf/:/var/lib/mibs/iana/ -m DIGIUM-MIB:ASTERISK-MIB -Tp -Td -Ln 1.3.6.1.4.1.22736 | less
Посмотреть значения OID'ов с их символьными именами по SNMP второй версии можно следующим образом:
$ snmpwalk -v 2c -c public 127.0.0.1 .1.3.6.1.4.1.22736.1 | less
Для SNMP третьей версии то же самое делается так:
$ snmpwalk -v 3 -u zabbix -n '' -l authPriv -a SHA -x AES -A auth_password -X encryption_password 127.0.0.1 .1.3.6.1.2.4.1.22736.1 | less
4. Шаблоны для Zabbix

В качестве основы для шаблона я воспользовался официальными MIB-файлами:
Я подготовил два шаблона для контроля интересующих меня параметров с помощью Zabbix:
Поменять строки сообщества и пароли можно при помощи массового редактирования элементов данных. Из шаблона для второй версии SNMP можно массовым редактированием легко получить и шаблон, использующий первую версию SNMP. Собственно, массовым редактированием можно получить и шаблон, использующий третью версию SNMP.

На снимке экрана ниже показаны имеющиеся в шаблоне элементы данных:

На этом снимке показаны результаты опроса Asterisk по этому шаблону:

К сожалению, SNMP-модуль Asterisk не позволяет узнать состояние регистраций абонентов. Если бы состояние регистраций можно было бы контролировать, я обязательно добавил бы в шаблон низкоуровневое обнаружение регистраций и контроль их состояний. Это позволило бы своевременно обнаруживать проблемы со шлюзами абонентов.

Один из вариантов какого бы то ни было решения этой проблемы может быть следующим. Если VoIP-шлюзы находятся в находятся в отдельной сети, где больше нет никакого оборудования, можно воспользоваться функциями обнаружения Zabbix и автоматически ставить обнаруженные IP-адреса хотя бы на контроль доступности по ICMP.