VDSM и перехватчики событий

Применение VDSM

Виртуализированный ЦУ использует службу VDSM (Virtual Desktop and Server Manager) для управления виртуальными и физическими хостами, хранилищами хостов, ресурсами памяти и ресурсами сетей для управления виртуальными и физическими хостами). Кроме этого, VDSM управляет и выполняет наблюдение за хранилищами хостов, ресурсами памяти и ресурсами сетей. Также эта служба участвует в координации создания виртуальных машин, в сборе статистики и в других задачах администрирования хостов. VDSM выполняется в виде демона на каждом из хостов под управлением виртуализированного ЦУ и отвечает на вызовы XML-RPC клиентов. При этом виртуализированный ЦУ работает как клиент VDSM.

Перехватчики событий VDSM

VDSM расширяется с помощью перехватчиков событий (hooks). Перехватчики событий — это сценарии, выполняемые на хосте в момент запуска ключевых событий. При старте поддерживаемого события VDSM запускает на хосте любые выполняемые сценарии перехватчиков событий из /usr/libexec/vdsm/hooks/nn_имя-события/ в алфавитно-цифровом порядке. Обычно каждому из сценариев перехватчика присваивается двузначный номер, включаемый в начало имени файла, для придания порядка, в котором запускаются сценарии. Сценарии перехватчиков событий можно создавать на любом из языков программирования. В примерах, приведенных в настоящем Приложении А, используется Python.

Обратите внимание, что выполняются все сценарии, настроенные для события на хосте. Если необходимо, чтобы указанный перехватчик событий запускался только для определённого набора виртуальных машин, выполняемых на этом хосте, то требуется, чтобы это обеспечивал сам сценарий с помощью оценки настраиваемых пользователем свойств ВМ (см. п. Настройка свойств, указываемых пользователем).

Обратите внимание, что перехватчики событий VDSM могут вмешиваться в работу системы виртуализации ROSA Virtualization. Программная ошибка перехватчика может потенциально привести к фатальному сбою в работе ВМ и к потере данных. Перехватчики событий VDSM должны быть реализованы разработчиками с осторожностью и тщательно тестироваться перед применением.

Расширение VDSM с помощью перехватчиков событий

В Приложении А описывается, как расширить VDSM с помощью перехватчиков, запускаемых при определённых событиях. Расширение VDSM с помощью перехватчиков событий является экспериментальной технологией, поэтому информация в предназначена для опытных разработчиков.

С помощью настраиваемых пользователем свойств ВМ перехватчикам событий можно передавать дополнительные параметры, специфичные для данной ВМ.

Поддерживаемые события VDSM

В таблице 81 описываются поддерживаемые события VDSM.

Окружение VDSM перехватчиков событий

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

Исключениями являются сценарии перехватчиков, запускаемых событиями before_vdsm_start и after_vdsm_stop. Сценарии перехватчиков, запускаемых этими событиями, выполняются от имени суперпользователя root и не наследуют окружение процесса VDSM.

Объект XML домена перехватчиков событий VDSM

При запуске сценариев перехватчиков событий к окружению добавляется переменная _hook_domxml, которая содержит путь до XML-представления домена libvirt соответствующей ВМ.

Исключениями являются следующие перехватчики событий, у которых переменная _hook_domxml содержит XML-представление сетевой карты, а не виртуальной машины:

  • nic_hotplug
  • nic_hotunplug
  • *_update_device
  • *_device_create
  • device_migrate

Примечание — Перехватчики событий before_migration_destination и before_dehibernation на данный момент получают XML домена исходного хоста (XML домена цели будет иметь некоторые отличия).

VDSM использует формат XML домена библиотеки libvirt для описания виртуальных машин. Сведения об этом формате можно найти по ссылке http://libvirt.org/formatdomain.html.

UUID виртуальной машины можно получить с помощью XML домена, а также в виде значения переменной окружения vmId.

Настройка свойств, указываемых пользователем

Настраиваемые пользователем свойства, принимаемые диспетчером виртуализации и, в свою очередь, передаваемые пользовательским перехватчикам событий определяются с помощью команды engine-config. Выполняйте эту команду с правами суперпользователя root на хосте, где установлен диспетчер виртуализации.

Конфигурационные ключи UserDefinedVMProperties и CustomDeviceProperties команды engine-config используются для хранения имён поддерживаемых пользовательских свойств виртуальной машины и устройства соответственно. В этих ключах также присутствуют регулярные выражения, определяющие действительные значения для каждого именованного пользовательского свойства.

Несколько пользовательских свойств разделяются точками с запятой без пробела. Обратите внимание, что при указании конфигурационного ключа все уже содержащиеся в нём существующие значения перезаписываются. При указании новых и уже существующих пользовательских свойств в команду необходимо включать все пользовательские свойства, используемые для указания значения ключа.

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

Настройка пользовательского свойства smartcard (свойство ВМ)

Для настройки пользовательского свойства smartcard (свойство ВМ):

  1. Выполните следующую команду для проверки уже имеющихся пользовательских свойств ВМ, настроенных ключом конфигурации UserDefinedVMProperties:
engine-config -g UserDefinedVMProperties

Из вывода ниже видно, что уже настроено пользовательское свойство memory (при этом регулярное выражение ^0-9+$ гарантирует, что пользовательское свойство memory будет содержать только числовые символы):

engine-config -g UserDefinedVMProperties
UserDefinedVMProperties:  version: 3.6
UserDefinedVMProperties:  version: 4.0
UserDefinedVMProperties:  memory=^[0-9]+$ version: 4.0
  1. Добавьте новое пользовательское свойство smartcard к уже настроенному пользовательскому свойству memory, при этом укажите, что новое свойство smartcard может принимать значения true или false:
engine-config -s UserDefinedVMProperties='memory=^[0-9]+$; \
smartcard=^(true|false)$' --cver=4.0
  1. Выполните следующую команду для проверки конфигурации пользовательских свойств memory и smartcard:
engine-config -g UserDefinedVMProperties
UserDefinedVMProperties:  version: 3.6
UserDefinedVMProperties:  version: 4.0
UserDefinedVMProperties:  memory=^[0-9]+$;smartcard=^(true|false)$ version: 4.0
  1. Для применения изменений в конфигурации пользовательских свойств ВМ перезапустите службу ovirt-engine:
systemctl restart ovirt-engine.service

Настройка пользовательского свойства interface (свойство устройства)

Для настройки пользовательского свойства interface (свойство устройства):

  1. Выполните следующую команду для проверки уже имеющихся пользовательских свойств устройства, настроенных ключом конфигурации CustomDeviceProperties:
engine-config -g CustomDeviceProperties

Из вывода ниже видно, что пользовательские свойства для устройства ещё не были настроены:

engine-config -g CustomDeviceProperties
CustomDeviceProperties:  version: 3.6
CustomDeviceProperties:  version: 4.0
  1. Добавьте новое пользовательское свойство interface, при этом укажите, что значение параметра prop настраивается в диапазоне от 0 до 99999, а параметр duplex может принимать значения full или half:
engine-config -s CustomDeviceProperties="{type=interface;prop= {speed=^([0-9]{1,5})$;duplex=^(full|half)$}}" --cver=4.0
  1. Выполните следующую команду для проверки конфигурации пользовательского свойства interface:
engine-config -g CustomDeviceProperties
UserDefinedVMProperties:  version: 3.6
UserDefinedVMProperties:  version: 4.0
UserDefinedVMProperties: {type=interface;prop={speed=^([0-9]{1,5})$; duplex=^(full|half)$}} version: 4.0
  1. Для применения изменений в конфигурации пользовательских свойств устройства перезапустите службу ovirt-engine:
systemctl restart ovirt-engine.service

Настраиваемые пользователем свойства ВМ

Как только пользовательские свойства были настроены в виртуализированном ЦУ, можно начинать настраивать их на виртуальных машинах. Пользовательские свойства настраиваются во вкладке "Настраиваемые пользователем свойства" окон "Новая ВМ" и "Параметры виртуальной машины" на Портале администрирования.

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

Вкладка "Настраиваемые пользователем свойства" предоставляет возможность выбора из списка настроенных пользовательских свойств. После выбора ключа пользовательского свойства открывается дополнительное поле, в котором необходимо указать значение выбранного ключа. Добавляйте дополнительные пары "ключ-значение", нажимая на кнопку +, и удаляйте их с помощью кнопки –.

Оценка пользовательских свойств ВМ в перехватчике событий VDSM

Во время вызова сценариев перехватчиков событий каждый ключ, указанный в поле "Настраиваемые пользователем свойства" виртуальной машины, добавляется в качестве переменной окружения. Хотя регулярные выражения, используемые для валидации полей "Настраиваемых пользователем свойств", предоставляют некоторую защиту, необходимо обеспечить также оценку соответствия ввода значениям, ожидаемым регулярными выражениями.

Оценка настраиваемых пользователем свойств

Следующий пример, написанный на Python, проверяет существование пользовательского свойства key1. Если свойство настроено, то его значение выводится в стандартных ошибках. Если пользовательское свойство key1 не настроено, никаких действий не предпринимается.

#!/usr/bin/python
import os
import sys
if os.environ.has_key('key1'):
sys.stderr.write('key1 value was : %s\n' % os.environ['key1'])
else:
sys.exit(0)

Использование модуля перехватчиков событий VDSM

В составе VDSM поставляется модуль перехватчиков событий, написанный на Python, который предоставляет вспомогательные функции для сценариев перехватчиков событий VDSM. Данный модуль поставляется в качестве примера и относится только к перехватчикам VDSM, написанным на Python.

Модуль перехватчиков событий поддерживает чтение XML-библиотеки libvirt виртуальной машины в объект DOM. Далее сценарии перехватчиков событий управляют объектом с помощью Python, встроенного в библиотеку xml.dom (http://docs.python.org/release/2.6/library/xml.dom.html). Затем с помощью модуля перехватчиков изменённый объект можно снова сохранить в XML-библиотеки libvirt.

В таблице 82 описываются функции модуля перехватчиков событий, предназначенные для поддержки разработки перехватчиков.

Выполнение перехватчиков событий VDSM

Некоторые сценарии перехватчиков событий могут редактировать XML домена и изменять параметры VDSM виртуальной машины. Выполнять эти действия нужно с осторожностью. Сценарии перехватчиков событий потенциально могут нарушить работу VDSM, а сценарии с программными ошибками могут привести к перерывам в работе окружения системы виртуализации ROSA Virtualization. В частности, никогда не изменяйте UUID домена и не пытайтесь удалять устройства из доменов без достаточного понимания процесса и последствий.

Как сценарий before_vdsm_start, так и сценарий after_vdsm_stop выполняются от имени суперпользователя root. Другие сценарии, которым необходим доступ root, должны писаться с использованием команды sudo для повышения привилегий. Для поддержки этого необходимо обновить информацию в файле /etc/sudoers так, чтобы пользователь vdsm мог использовать sudo без повторного введения пароля, так как сценарии перехватчиков событий выполняются без вмешательства со стороны пользователя.

Настройка sudo для сценариев перехватчиков событий VDSM

В следующем примере команда sudo будет настроена так, чтобы разрешить пользователю vdsm выполнять команду /bin/chown от имени суперпользователя root:

  1. Выполните вход в систему хоста виртуализации с правами root.
  2. Откройте файл /etc/sudoers в текстовом редакторе.
  3. Добавьте в файл следующую строку:
vdsm ALL=(ALL) NOPASSWD: /bin/chown

В результате пользователь vdsm может запускать команду /bin/chown от имени суперпользователя root. Параметр NOPASSWD указывает, что при вызове sudo не будет предлагаться пользователю ввести пароль.

Таким образом, после внесения этих изменений в перехватчиках событий VDSM также можно использовать команду sudo для запуска /bin/chown от имени суперпользователя root.

В следующем коде на Python команда sudo используется для выполнения /bin/chown с правами суперпользователя root относительно файла /my_file:

retcode = subprocess.call( ["/usr/bin/sudo", "/bin/chown", "root", "/my_file"] )

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

Коды возврата перехватчиков событий VDSM

В таблице 83 описываются коды возврата сценариев перехватчиков событий. Коды возврата определяют, обрабатывает ли VDSM сценарий.

Примеры перехватчиков событий VDSM

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

Тонкая настройка узла NUMA

Данный сценарий перехватчика событий даёт возможность отрегулировать выделение памяти на хосте NUMA с использованием настроенного пользователем свойства numaset:

numaset=^(interleave|strict|preferred):[\^]?\d+(-\d+)?(,[\^]?\d+(-\d+)?)*$

Используемое регулярное выражение даёт возможность настроенному пользователем свойству numaset конкретной ВМ указать как режим распределения памяти (interleave, strict, preferred), так и используемый узел. При этом два значения разделяются двоеточием (:).

С помощью регулярного выражения можно указать nodeset как:

  • Конкретный узел (например, numaset=strict:1 указывает, что будет использован только узел 1).
  • Диапазон узлов (например, numaset=strict:1-4 указывает, что будут использоваться узлы с 1 по 4).
  • Неиспользуемый узел (например, numaset=strict:3 указывает, что узел 3 не будет использоваться).
  • Любое сочетание вышеуказанных значений, через запятые (например, numaset=strict:1-4,6 указывает, что будут использоваться узлы с 1 по 4, а также узел 6).

Сценарий перехватчика событий /usr/libexec/vdsm/hooks/before_vm_start/50_numa:

#!/usr/bin/python
import os
import sys
import hooking
import traceback
'''
numa hook
=========
add numa support for domain xml:
<numatune>
<memory mode="strict" nodeset="1-4,^3" />
</numatune>
memory=interleave|strict|preferred
numaset="1" (use one NUMA node)
numaset="1-4" (use 1-4 NUMA nodes)
numaset="^3" (don't use NUMA node 3)
numaset="1-4,^3,6" (or combinations)
syntax:
numa=strict:1-4
'''
if os.environ.has_key('numa'):
try:
mode, nodeset = os.environ['numa'].split(':')
domxml = hooking.read_domxml()
domain = domxml.getElementsByTagName('domain')[0]
numas = domxml.getElementsByTagName('numatune')
if not len(numas) > 0:
numatune = domxml.createElement('numatune')
domain.appendChild(numatune)
memory = domxml.createElement('memory')
memory.setAttribute('mode', mode)
memory.setAttribute('nodeset', nodeset)
numatune.appendChild(memory)
hooking.write_domxml(domxml)
else:
sys.stderr.write('numa: numa already exists in domain xml')
sys.exit(2)
except:
sys.stderr.write('numa: [unexpected error]: %s\n' % traceback.format_exc())
sys.exit(2)