# Миграция в реальном времени

## Введение

Миграция виртуальной машины в реальном времени — ключевая функция, предоставляемая StratoVirt. Она необходима для выполнения миграции виртуальной машины при возникновении следующих ситуаций:
* перегрузка сервера: когда исходный сервер перегружен, набор виртуальных машин с этого сервера переносится на недогруженный сервер с использованием технологии миграции ВМ;
* обслуживание сервера: если требуется обслуживание сервера, виртуальные машины с исходного сервера переносятся на другой сервер;
* сбой сервера: всякий раз, когда происходит сбой сервера, виртуальные машины переносятся со сбойного сервера на целевой сервер.

## Транспорты

Поток миграции может быть передан через любой из следующих транспортов:
* миграция в режиме TCP: использование TCP-сокетов для выполнения миграции;
* миграция в UNIX-режиме: использование UNIX-соклетов для выполнения миграции.

Примечание: UNIX-режим поддерживает миграцию только двух виртуальных машин на одном хосте ОС. Режим TCP поддерживает миграцию как на одном, так и на разных хостах ОС.

## Миграция

Запустите исходную виртуальную машину:
```shell
./stratovirt \
    -machine q35 \
    -kernel ./vmlinux.bin \
    -append "console=ttyS0 pci=off reboot=k quiet panic=1 root=/dev/vda" \
    -drive file=path/to/rootfs,id=rootfs,readonly=off,direct=off \
    -device virtio-blk-pci,drive=rootfs,id=rootfs,bus=pcie.0,addr=0 \
    -qmp unix:path/to/socket1,server,nowait \
    -serial stdio \
```

Запустите целевую виртуальную машину:
```shell
./stratovirt \
    -machine q35 \
    -kernel ./vmlinux.bin \
    -append "console=ttyS0 pci=off reboot=k quiet panic=1 root=/dev/vda" \
    -drive file=path/to/rootfs,id=rootfs,readonly=off,direct=off \
    -device virtio-blk-pci,drive=rootfs,id=rootfs,bus=pcie.0,addr=0 \
    -qmp unix:path/to/socket2,server,nowait \
    -serial stdio \
    -incoming tcp:192.168.0.1:4446 \
```

Примечание:
* Параметр командной строки целевой виртуальной машины должен соответствовать исходной виртуальной машине.
* Если необходимо изменить передачу данных с сетевого протокола TCP на UNIX-сокет, параметр `-incoming tcp:192.168.0.1:4446` необходимо заменить на `-incoming unix:/tmp/stratovirt-migrate.socket`.
* Протокол UNIX-сокета поддерживает миграцию только двух виртуальных машин на одной хост-ОС.

Начните отправку миграции для исходной виртуальной машины:
```shell
$ ncat -U path/to/socket1
<- {"QMP":{"version":{"StratoVirt":{"micro":1,"minor":0,"major":0},"package":""},"capabilities":[]}}
-> {"execute":"migrate", "arguments":{"uri":"tcp:192.168.0.1:4446"}}
<- {"return":{}}
```

Примечание:
* При использовании протокола UNIX-соклета для миграции виртуальной машины необходимо изменить команду QMP `"uri":"tcp:192.168.0.1:4446"` на `"uri":"unix:/tmp/stratovirt-migrate.socket"`.

После выполнения команды в командной строке начинается миграция в реальном времени. Через некоторое время исходная виртуальная машина должна быть успешно перенесена на целевую виртуальную машину.

## Отмена миграции

Если вы хотите отменить миграцию в реальном времени, выполните следующую команду:
```shell
$ ncat -U path/to/socket1
<- {"QMP":{"version":{"StratoVirt":{"micro":1,"minor":0,"major":0},"package":""},"capabilities":[]}}
-> {"execute":"migrate_cancel"}
<- {"return":{}}
```

## Запрос состояния миграции

Используйте команду QMP `query-migrate`, чтобы проверить состояние миграции:
```shell
$ ncat -U path/to/socket
<- {"QMP":{"version":{"StratoVirt":{"micro":1,"minor":0,"major":0},"package":""},"capabilities":[]}}
-> {"execute":"query-migrate"}
<- {"return":{"status":"completed"}}
```

В настоящее время существует 5 состояний во время миграции:
* `None`: ресурс не подготовлен полностью.
* `Setup`: ресурс настроен, готов к миграции.
* `Active`: в процессе миграции.
* `Completed`: миграция завершена.
* `Failed`: миграция не удалась.
* `Canceled`: миграция отменена.

## Ограничения

Поддержка миграции типов машин:
* `q35` (на платформе x86_64);
* `virt` (на платформе aarch64).

Некоторые устройства и функции пока не поддерживают миграцию:
* `vhost-net`;
* `vhost-user-net`;
* устройства `vfio`;
* `balloon`;
* `mem-shared`,`backend file of memory`;
* `pmu`;
* `sve`;
* `gic-version=2`.

Атрибуты некоторых устройств не могут быть изменены:
* `virtio-net`: mac;
* `virtio-blk`: файл (только обычный файл или копирование файла), serial_num;
* `device`: шина, адрес;
* `smp`;
* m.

При горячем подключении устройства перед миграцией исходной виртуальной машины добавьте вновь заменённое устройство. Команду необходимо добавить на целевую виртуальную машину.

Перед «живой» миграцией:
— исходный и целевой хосты должны использовать одинаковую архитектуру процессоров;
— образ виртуальных машин должен быть общим для исходного и целевого хостов;
— «живая» миграция может завершиться ошибкой, если виртуальная машина выполняет операции жизненного цикла, такие как перезагрузка или выключение.
— команда для запуска виртуальной машины должна быть одинаковой на исходном и целевом хостах.

Во время «живой» миграции:
— нельзя разрывать соединение между исходной и целевой сетями;
— запрещено выполнять операции жизненного цикла виртуальной машины, включая использование команд QMP и выполнение операций внутри виртуальной машины.
— на время «живой» миграции влияют производительность сети, общий объём памяти виртуальной машины и приложений.

После «живой» миграции: 
— необходимо дождаться освобождения ресурсов исходной виртуальной машиной перед тем, как повторить операцию «живой» миграции.