# Перенос облака с Селектела на Vscale

Источник: https://blog.xsk.in/it/perenos-oblaka-s-selektela-na-vscale/846/
Опубликовано: 2016-08-23 · Рубрики: IT, Linux


*Дисклеймер: всё нижеописанное использовать вдумчиво и под свою ответственность! Шпаргалка создана для личных целей, использовать исключительно в качестве инструкции "как делать не надо". Большинство команд восстановлено по памяти, но отражают суть дела. Статья не претендует на уникальность или адекватность, но метод рабочий.*

Краткое содержание:

- Изменяем размер корневой файловой системы на новой виртуалке
- Переносим снапшот LVM со старой
- Заставляем грузиться новое ядро со старой операционкой
- Рихтуем до работоспособного состояния систему в целом

Поехали!

1. Создаем виртуалку в [vscale.io](https://vscale.io/?refcode=wiu1v0ab27) с похожей версией операционной системы. Например, вместо Debian 6 ставим минимальный возможный Debian 7. Диск выбираем из собственных предпочтений с расчетом "чтоб влезло". Как пользоваться панелью нового облачного хостера, можно найти в [официальном блоге на Хабре](https://habrahabr.ru/company/selectel/blog/265411/)
2. Пересобираем на новой виртуалке initrd с выходом в консоль до монтирования разделов. Для этого делаем следующее:

   - Создаем папку и разворачиваем туда текущий initrd:

     ```
     mkdir ~/initrd; cd ~/initrd
     ```

     ```
     gunzip -c /boot/initrd.img-3.2.0-4-amd64 | cpio -i --make-directories
     65923 blocks
     ```

     ```
     ls -l
     total 44
     drwxr-xr-x 2 root root 4096 Aug 22 11:20 bin
     drwxr-xr-x 3 root root 4096 Aug 22 11:19 conf
     drwxr-xr-x 6 root root 4096 Aug 22 11:21 etc
     -rwxr-xr-x 1 root root 6797 Aug 22 11:19 init
     drwxr-xr-x 6 root root 4096 Aug 22 11:19 lib
     drwxr-xr-x 2 root root 4096 Aug 22 11:19 lib64
     drwxr-xr-x 2 root root 4096 Aug 22 11:19 run
     drwxr-xr-x 2 root root 4096 Aug 22 11:19 sbin
     drwxr-xr-x 7 root root 4096 Aug 22 11:21 scripts
     drwxr-xr-x 3 root root 4096 Aug 22 11:19 usr
     ```
   - Кладем необходимые библиотеки и бинарники для работы с файловой системой (нам нужен fdisk, resize2fs и e2fsck):

     ```
     ldd /sbin/fdisk
     	linux-vdso.so.1 =>  (0x00007ffeeb96e000)
     	libblkid.so.1 => /lib/libblkid.so.1 (0x00007fe3ba493000)
     	libuuid.so.1 => /lib/libuuid.so.1 (0x00007fe3ba28f000)
     	libc.so.6 => /lib/libc.so.6 (0x00007fe3b9f2d000)
     	/lib64/ld-linux-x86-64.so.2 (0x00007fe3ba6b2000)
     ldd /sbin/resize2fs
     	linux-vdso.so.1 =>  (0x00007ffd497ee000)
     	libe2p.so.2 => /lib/libe2p.so.2 (0x00007f128b5b6000)
     	libext2fs.so.2 => /lib/libext2fs.so.2 (0x00007f128b388000)
     	libcom_err.so.2 => /lib/libcom_err.so.2 (0x00007f128b185000)
     	libc.so.6 => /lib/libc.so.6 (0x00007f128ae23000)
     	libpthread.so.0 => /lib/libpthread.so.0 (0x00007f128ac07000)
     	/lib64/ld-linux-x86-64.so.2 (0x00007f128b7bd000)
     ldd /sbin/e2fsck
     	linux-vdso.so.1 =>  (0x00007fff949f7000)
     	libext2fs.so.2 => /lib/libext2fs.so.2 (0x00007f24ab49a000)
     	libcom_err.so.2 => /lib/libcom_err.so.2 (0x00007f24ab297000)
     	libblkid.so.1 => /lib/libblkid.so.1 (0x00007f24ab078000)
     	libuuid.so.1 => /lib/libuuid.so.1 (0x00007f24aae74000)
     	libe2p.so.2 => /lib/libe2p.so.2 (0x00007f24aac6d000)
     	libc.so.6 => /lib/libc.so.6 (0x00007f24aa90b000)
     	libpthread.so.0 => /lib/libpthread.so.0 (0x00007f24aa6ef000)
     	/lib64/ld-linux-x86-64.so.2 (0x00007f24ab6c8000)
     ```

     ```
     for i in libext2fs.so.2.4 libcom_err.so.2.1 libe2p.so.2.3; do cp -i /lib/x86_64-linux-gnu/$i lib/x86_64-linux-gnu/; done
     ```

     ```
     cd lib/x86_64-linux-gnu/
     ln -s libcom_err.so.2.1 libcom_err.so.2
     ln -s libext2fs.so.2.4 libext2fs.so.2
     ln -s libe2p.so.2.3 libe2p.so.2cd ~/initrd/
     cp /sbin/e2fsck ~/initrd/bin/
     cp /sbin/resize2fs ~/initrd/bin/
     cp /sbin/fdisk ~/initrd/bin/
     ```
   - Изменяем init скрипт в месте перед монтированием устройств в систему, для этого в файле scripts/local

     ```
     ...
         # FIXME This has no error checking
         # Mount root
         if [ "${FSTYPE}" != "unknown" ]; then
                 mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}
         else
                 mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}
         fi
     ...
     ```

     Делаем примерно так:

     ```
     #RESIZEROOTFS MODIFIED!!! DONT RUN MORE THAN ONCE
     _log_msg "Starting e2fsck"
     /bin/e2fsck -p -f -C 0 /dev/vda1 || true
     _log_msg "Starting shell"
     /bin/sh

         # FIXME This has no error checking
         # Mount root
         if [ "${FSTYPE}" != "unknown" ]; then
                 mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}
         else
                 mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}
         fi
     ```
   - Далее создаем файл etc/mtab, при отстутствии которого утилиты e2fsck и resize2fs отказываются работать

     ```
     touch ~/initrd/etc/mtab
     ```
   - Собираем патченный initrd назад

     ```
     cd ~/initrd/
     find ./ | cpio -H newc -o > /tmp/initrd.cpio
     64097 blocks
     gzip -c /tmp/initrd.cpio > /boot/initrd-resize.img
     ```
   - Теперь добавим в меню GRUB новую строчку для загрузки нашего initrd, для этого не будем хардкодить, а объявим его в файле /etc/grub.d/40\_custom

     ```
     #!/bin/sh
     exec tail -n +3 $0
     # This file provides an easy way to add custom menu entries. Simply type the
     # menu entries you want to add after this comment. Be careful not to change
     # the 'exec tail' line above.
     menuentry 'Our resize initrd' --class debian --class gnu-linux --class gnu --class os {
         load_video
         insmod gzio
         insmod part_msdos
         insmod ext2
         set root='(hd0,msdos1)'
         search --no-floppy --fs-uuid --set=root 89839485-a3d7-4d72-b96d-aba559b16634
         echo	'Loading Linux 3.2.0-4-amd64 ...'
         linux	/boot/vmlinuz-3.2.0-4-amd64 root=UUID=660f79dc-c152-4e15-ad61-7075b42de609 ro quiet
         echo	'Loading initial ramdisk ...'
         initrd	/boot/initrd-resize.img
     }
     ```
   - Обновляем список GRUB и перезагружаемся в патченный inirtd (для выбора нужного пункта в меню GRUB используем панель хостера и кнопку "Открыть консоль")

     ```
     update-grub
     reboot
     ```
3. Пока мы искали как попасть в VNC-консоль в панели vscale, необходимый нам раздел уже был проверен автоматически скриптом, поэтому сразу уменьшаем файловую систему до 1ГБ (системе хватит, она занимает около 800МБ)

   ```
   resize2fs /dev/vda1 1G
   ```
4. Затем с помощью fdisk отрезаем раздел и создаем новый под LVM, оба primary, первый +1G, второй - всё остальное пространство. Не забываем поставить флаг активности на первый раздел
5. На всякий случай проверяем *e2fsck* и подгоняем файловую систему под размер первого раздела
6. Перезагружаемся назад в обычную операционку, первый пункт меню
7. Ставим пакет *lvm2*, создаем физический раздел, группу томов и наконец логический том под систему, которую будем переносить. Размер выбираем исходя из наших нужд

   ```
   apt-get install lvm2
   pvcreate /dev/vda2
   vgcreate vg0 /dev/vda2
   lvcreate -n old_system -L10G vg0
   ```
8. Идем на старый сервер в Селектеле, выключаем там swap и используем освободившееся место на диске для создания снапшота корневой файловой системы. В большинстве случаев этого должно хватить. Если раздел был невообразимо огромен, колдуем с добавлением дополнительных дисков в панели хостера и используем их

   ```
   swapoff /dev/vg/swap
   lvremove /dev/vg/swap
   lvcreate --snapshot --name my_shot --size 1.9G /dev/vg/root
   ```
9. Переносим наш снапшот системы в новую виртуалку

   ```
   dd if=/dev/vg/my_shot bs=4096 | ssh root@new_vscale -C 'dd of=/dev/vg1/old_system bs=4096'
   ```
10. Если у нас отличаются ядра (3.1.0-1.2-xen на старом и 3.2.0-4-amd64 на новом, в моем случае), то маунтим перенесенный снапшот и переносим в раздел старой системы папку /lib/modules/3.2.0-4-amd64 с новой виртуалки. Иначе после ребута в старую систему с новым ядром ничего не заведется
11. При отличии версий операционных систем может вылезти еще косяк с inittab, в 6 и 7 дебианах они отличаются вот этим местом (комментим и добавляем старое поведение, иначе после загрузки системы мы в нее не залогинимся)

    ```
    #new system
    #0:12345:respawn:/sbin/getty xvc0 9600

    #old system
    1:2345:respawn:/sbin/getty 38400 tty1
    2:23:respawn:/sbin/getty 38400 tty2
    3:23:respawn:/sbin/getty 38400 tty3
    4:23:respawn:/sbin/getty 38400 tty4
    5:23:respawn:/sbin/getty 38400 tty5
    6:23:respawn:/sbin/getty 38400 tty6
    ```
12. Теперь пробуем загружаться с этого Франкенштейна, для этого в наш /etc/grub.d/40\_custom прописываем загрузку нового ядра с LVM

    ```
    menuentry 'Debian GNU/Linux Old System' --class debian --class gnu-linux --class gnu --class os {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='(hd0,msdos1)'
        search --no-floppy --fs-uuid --set=root 89839485-a3d7-4d72-b96d-aba559b16634
        echo	'Loading Linux 3.2.0-4-amd64 ...'
        linux	/boot/vmlinuz-3.2.0-4-amd64 root=/dev/mapper/vg0-old_system ro consoleblank=0 panic=15
        echo	'Loading initial ramdisk ...'
        initrd	/boot/initrd.img-3.2.0-4-amd64
    }
    ```
13. Обновляем GRUB, для автоматизации выставляем загрузку с этой строчки всегда по дефолту. Для этого правим строчку GRUB\_DEFAULT="0" в файле /etc/default/grub на ту, которой соответствует наше творчество. Отсчет с нуля
14. Если всё прошло гладко, попадаем внутрь старой системы на новом ядре. Правим сетевые параметры, ищем вхождения старого IP адреса по всей папке /etc и после внесения необходимых изменений удивляемся, что это еще и работает о\_О

*Ссылки:*

- [Howto shrink a remote root ext3 filesystem on Debian wheezy](http://blog.sourcepole.ch/2012/09/11/howto-shrink-a-remote-root-ext3-filesystem-on-debian-wheezy-3/)
- [LVM — это просто!](https://habrahabr.ru/post/67283/)
- [Moving a Logical Volume directly from one server to another over the network?](http://serverfault.com/questions/358228/moving-a-logical-volume-directly-from-one-server-to-another-over-the-network)
- [How do I shrink the root logical volume (LV) on LVM?](http://askubuntu.com/questions/124465/how-do-i-shrink-the-root-logical-volume-lv-on-lvm)
- [How to resize the Root volume on LVM](https://ubuntuforums.org/showthread.php?t=1537569)

