Под капотом · Виртуализация · Хранилища

Горячее подключение диска

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

Команда
virsh attach-disk vm1 /dev/vg_san/vm1 vdb --live --config
virsh domblklist vm1
# если гость не заметил диск на virtio-scsi:
# echo "- - -" > /sys/class/scsi_host/host0/scan
libvirt API virDomainAttachDeviceFlags()

После выполнения команд диск виден в работающей ВМ и записан в определение - перезагрузка не нужна.

  • Команда attach-disk с --live отдаёт устройство работающему QEMU;
  • Флаг --config записывает то же изменение в определение домена;
  • Команда domblklist показывает диск, как только QEMU принял device_add.
  • пользователь 1. Пользователь добавляет диск работающей ВМ
    virsh attach-disk vm1 /dev/vg_san/vm1 vdb --live --config

    Флагов два, и они про разное: --live меняет работающий QEMU, --config пишет определение, иначе диск исчезнет после перезагрузки.

  • libvirt 2. Демон проверяет, что имя устройства свободно
    target dev='vdb' уже занят -> ошибка

    libvirt не перезаписывает существующий target: сначала проверка, и только потом действие.

  • libvirt 3. Демон ищет свободный слот PCI
    q35:  <controller type='pci' model='pcie-root-port'/> × N
    i440fx: pci-root, слотов 31

    libvirt по умолчанию добавляет pcie-root и один pcie-root-port, то есть из коробки горячо подключается одно PCIe-устройство; слоты pcie-root hotplug не поддерживают. Сколько root-port свободно на самом деле, зависит от версии libvirt и занятых устройств - топологию планируют заранее.

  • libvirt 4. Демон назначает адрес и запоминает его
    <address type='pci' domain='0x0000' bus='0x01'
             slot='0x00' function='0x0'/>

    В присланном XML адреса не было - libvirt добавил его сам и сохранил, чтобы detach потом попал в то же устройство.

  • libvirt 5. Демон открывает QEMU доступ к новому пути
    cgroup devices: + /dev/vg_san/vm1
    метка SELinux/AppArmor на устройство

    Без этого QEMU получил бы EACCES при open(), хотя файл или том на месте и права верные.

  • QEMU 6. QEMU добавляет бэкенд и устройство
    blockdev-add (или drive_add) -> device_add
    {"execute":"device_add", ...}  <- {"return": {}}

    Пустой ответ значит «принял», а не «гость увидел»: устройство уже в QEMU, но ещё не в госте.

  • гость 7. Гость замечает новое устройство
    ACPI hotplug event -> /sys/bus/pci/rescan
    dmesg | grep vdb

    Если гость не поддерживает ACPI-подключение или ядро не сканирует шину, диск останется невидимым до перезагрузки.