Создание KVM-сценариев на языке Python: Часть 1. Библиотека libvirt

Этот цикл из двух статей посвящен тому, как использовать язык Python для создания сценариев управления виртуальными машинами с помощью технологии Kernel-based Virtual Machine (KVM). Первая статья учит основам использования libvirt и Python-привязок на нескольких простых примерах построения инструментов для определения и отображения состояния.

Пол Феррилл, технический директор, ATAC

Пол Феррилл (Paul Ferrill) уже более 20 лет пишет статьи, посвященные различным аспектам информационных технологий. Пол начинал с написания обзоров сетевых продуктов, таких как LANtastic и ранние версии Novell Netware, для журнала PC Magazine. Пол обладает степенями магистра и бакалавра в области электротехники и имеет опыт разработки ПО для самых разнообразных платформ и архитектур.



22.06.2012

Сегодня средства виртуализации входят в стандартный комплект поставки большинства серверных операционных систем. В мире Linux® существуют два основных способа виртуализации серверов: Kernel-based Virtual Machine (KVM) и Xen. KVM – основная технология, которую используют Red Hat и другие. Xen принадлежит Citrix, однако большая часть основной функциональности остается общественным достоянием.

Проект Virtual Machine Manager (VMM или virt-manager) предоставляет инструмент для управления созданием и исполнением экземпляров виртуальных машин (VM) KVM и Xen. VMM написан на языке Python с применением библиотеки GTK+ для построения графического пользовательского интерфейса. Реальная работа выполняется посредством библиотеки libvirt, которую мы будем использовать в этом цикле статей. Хотя проект libvirt спонсируется Red Hat, он продолжает оставаться проектом ПО с открытым исходным кодом, распространяемым по лицензии GNU Lesser General Public License.

libvirt состоит из нескольких частей, включая библиотеку интерфейса прикладных программ (API), демон (libvirtd) и утилиту командной строки по умолчанию (virsh). Все тестирование для настоящей статьи проводилось с использованием Ubuntu Server версии 11.04. В разделе Установка и настройка описано все, что я сделал, чтобы настроить свой сервер для разработки представленных здесь сценариев. В Части 1 объясняются основы libvirt и виртуализации с применением KVM наряду с несколькими сценариями командной строки, чтобы разжечь аппетит. В Части 2 мы копнем глубже и покажем, как создать свои собственные инструменты управления виртуализацией с помощью libvirt, Python и wxPython.

Начало работы

Прежде чем подробно разбирать примеры кода, познакомимся с некоторыми терминами и понятиями из области виртуализации с помощью KVM. При установке KVM на сервер, такой как Ubuntu Server 11.04, создается хост-компьютер виртуализации, или гипервизор. Это означает, что сервер позволяет разместить несколько гостевых операционных систем, работающих поверх хоста KVM. Каждый уникальный гость называется доменом и функционирует в основном так же, как один экземпляр сервера на отдельной машине. Подключение к серверу осуществляется через Secure Shell (SSH) или Virtual Network Computing точно так же, как при соединении с физической машиной.

Если KVM функционирует как гипервизор или менеджер гостевых ОС, то QEMU обеспечивает фактическую эмуляцию машины, то есть выполняет набор собственных инструкций целевой машины. Для гостевых систем x86 это машинные инструкции, которые непосредственно исполняются оборудованием. Для других архитектур, таких как ARM, выполняется процесс перевода. Сочетание KVM и QEMU обеспечивает все вспомогательные функции, необходимые для виртуализации практически любых существующих операционных систем, а также тех, которые уже не используются.

Гостевой домен состоит из нескольких файлов, включая один или несколько файлов образов диска и XML-файл конфигурации. Это значительно упрощает управление несколькими виртуальными машинами путем создания базового образа системы с последующим изменением файла конфигурации. Одним из методов настройки и соединения с KVM/QEMU является инструментарий libvirt. Несколько поставщиков стандартизировали свои системы управления на базе libvirt.

Вот содержание файла конфигурации типичного домена. В листинге 1 показан файл testdev.xml, взятый из примеров libvirt.

Листинг 1. XML-определение устройства
<device>
   <name>File_test_device</name>
   <capability type='system'>
         <hardware>
               <vendor>Libvirt</vendor>
               <version>Test driver</version>
               <serial>123456</serial>
               <uuid>11111111-2222-3333-4444-555555555555</uuid>
         </hardware>
         <firmware>
               <vendor>Libvirt</vendor>
               <version>Test Driver</version>
               <release_date>01/22/2007</release_date>
         </firmware>
   </capability>
</device>

В тестовом файле domfv0.xml, показанном в листинге 2, видны некоторые детали настройки виртуальных устройств.

Листинг 2. Файл определения устройства domfv0.XML
<devices>
  <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
         <interface type='bridge'>
               <source bridge='xenbr0'/>
               <mac address='00:16:3e:5d:c7:9e'/>
               <script path='vif-bridge'/>
         </interface>
         <disk type='file'>
               <source file='/root/fv0'/>
               <target dev='hda'/>
         </disk>
         <disk type='file' device='cdrom'>
               <source file='/root/fc5-x86_64-boot.iso'/>
               <target dev='hdc'/>
               <readonly/>
         </disk>
         <disk type='file' device='floppy'>
               <source file='/root/fd.img'/>
               <target dev='fda'/>
         </disk>
         <graphics type='vnc' port='5904'/>
</devices>

Ключевым моментом здесь является та относительная легкость, с которой можно читать эти файлы и создавать свои собственные. Можно создать сколько угодно файлов конфигурации вручную, но с помощью языка сценариев типа Python этот процесс можно автоматизировать.


Установка и настройка

Так как это статья о написании сценариев KVM, основное предположение заключается в том, что у вас имеется сервер с установленным KVM. Если это Ubuntu Server 11.04, то в процессе установки можно выбрать виртуализацию с помощью параметра Virtual Machine Host на экране Software selection. Если надо подключаться к машине дистанционно, можно также выбрать сервер OpenSSH.

Первым делом необходимо установить последнюю версию libvirt. Для этого придется поработать из командной строки. При установке Ubuntu Server 11.04 вы получаете libvirt версии 0.8.8. На Web-сайте есть новейшая и самая лучшая версия libvirt 0.9.5. Чтобы установить более позднюю версию, необходимо добавить репозиторий Personal Package Archive (PPA) в систему, содержащую одну из последних версий libvirt. Количество потенциальных кандидатов дает быстрый поиск на сайте launchpad.net по ключевому слову libvirt. Перед попыткой обновления важно просмотреть страницу с подробной информацией о репозитории, так как некоторые пакеты могут иметь дефекты. Группа виртуализации Ubuntu ведет репозитории PPA по нескольким пакетам, в том числе libvirt. Последней версией на момент написания этой статьи была версия 0.9.2-4.

Для установки этой версии выполните следующие действия:

  1. Установите пакет python-software-properties следующим образом:
    sudo apt-get install python-software-properties

    Эта команда предоставляет доступ к команде add-apt-repository, которая нужна для обращения к сторонним источникам.

  2. Введите следующие команды:
    sudo add-apt-repository ppa:ubuntu-virt/ppa
    sudo apt-get update
    sudo apt-get install libvirt-bin
  3. Так как мы будем использовать Python для всех сценариев, приведенных в этой статье, установите оболочку IDLE, чтобы упростить их написание и тестирование.

    Этот шаг предполагает, что на вашем сервере Ubuntu установлена среда рабочего стола. Вот самый быстрый способ установить рабочий стол:

    sudo apt-get install ubuntu-desktop

Вы получите доступ к любому числу графических приложений и к установщику программного обеспечения Ubuntu. Для установки инструмента Python IDLE можно использовать Ubuntu Software Center.


Примеры сценариев

Прежде чем углубляться в код, давайте рассмотрим некоторые основы работы с libvirt. Для взаимодействия приложения с библиотекой libvirt используется простой механизм вызова удаленных процедур, позволяющий создавать приложения для связи с удаленными гипервизорами через соединение TCP/IP. Для идентификации конкретного гипервизора, с которым требуется установить соединение, используются универсальные коды ресурсов (URI, определенные в запросе комментариев [RFC] 2396 организации Internet Engineering Task Force [IETF]).

Локальные соединения ― в отличие от некоторых удаленных соединений ― обычно не требуют проверки подлинности. За настройку безопасности отвечает файл libvirt.conf. Сетевой фильтр осуществляет самый широкий контроль над взаимодействием с уникальным доменом. Ниже приведен пример управления сетевым трафиком с помощью этого фильтра.

<devices>
    <interface type='bridge'>
      <mac address='00:16:3e:5d:c7:9e'/>
      <filterref filter='clean-traffic'/>
    </interface>
</devices>

Этот фрагмент кода определяет фильтр с именем clean-traffic, который будет применяться ко всему сетевому трафику через указанный MAC-адрес. XML-файл clean-traffic содержит следующее:

<filter name='clean-traffic' chain='root'>
     <uuid>6f145c54-e3de-4c33-544a-70b69c16d9da</uuid>
     <filterref filter='no-mac-spoofing'/>
     <filterref filter='no-ip-spoofing'/>
     <filterref filter='allow-incoming-ipv4'/>
     <filterref filter='no-arp-spoofing'/>
     <filterref filter='no-other-l2-traffic'/>
     <filterref filter='qemu-announce-self'/>
</filter>

Возможности фильтра весьма обширны и полностью документированы. Локальную копию документации libvirt и примеры файлов можно получить всего одной командой:

sudo apt-get install libvirt-doc

Вся документация оказывается в каталоге /usr/share/doc/libvirt-doc. Примеры сценариев Python вы увидите чуть позже. Для наиболее поздней версии libvirt может потребоваться явная установка привязок Python. Для этого также достаточно одной команды:

sudo apt-get install python-libvirt

С консоли Python IDLE распечатайте код Python и установите связь с локальным экземпляром QEMU, а затем изучите указанные домены. В листинге 3 показано, что вы должны увидеть.

Листинг 3. Код Python в консоли IDLE
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) 
[GCC 4.5.2] on linux2
Type "copyright", "credits" or "license()" for more information.
==== No Subprocess ====
>>> import libvirt
>>> conn=libvirt.open("qemu:///system")
>>> names = conn.listDefinedDomains()
>>> print names
['Test1', 'SBSLite', 'UbuntuServer1104', 'Win7_64-bit']]
>>>

Этот код показывает, как получить список всех определенных доменов. Функция listDefinedDomains() выводит список, содержащий четыре именованных домена. Установив связь с гипервизором, вы получите доступ к списку доступных функций. Следующий короткий сценарий показывает, как получить список всех доступных функций объекта conn.

clist = dir(conn)
for item in clist:
            print item

Используя аналогичный подход, можно просмотреть список определенных фильтров.

filts = conn.listNWFilters()
for item in filts:
            print item

Инструмент IDLE - это отличный способ исследовать различные вызовы API и быстро увидеть результаты их выполнения. Некоторые функции работают только с запущенными доменами. Функция Python dir() возвращает список допустимых атрибутов для указанного объекта. Это удобный инструмент командной строки, позволяющий быстро увидеть, что предоставляет собой конкретный объект. Используя его, как показано выше, можно получить список функций, доступных после установления соединения с гипервизором.

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

Листинг 4. Python-распечатка объекта домена
>>> import libvirt
>>> import pprint
>>> conn=libvirt.open("qemu:///system")
>>> p = conn.lookupByName('ubuntu100403')
>>> pprint.pprint(dir(p))
['ID',
 'OSType',
 'UUID',
 'UUIDString',
 'XMLDesc',
 '__del__',
 '__doc__',
 '__init__',
 '__module__',
 '_conn',
 '_o',
 'abortJob',
 'attachDevice',
 'attachDeviceFlags',
 'autostart',
 'blkioParameters',
 'blockInfo',
 'blockPeek',
 'blockStats',
 'connect',
 'coreDump',
 'create',
 'createWithFlags',
 'destroy',
 'detachDevice',
 'detachDeviceFlags',
 'hasCurrentSnapshot',
 'hasManagedSaveImage',
 'info',
 'injectNMI',
 'interfaceStats',
 'isActive',
 'isPersistent',

Этот простой подход можно использовать для создания сценария, который выводит сведения обо всех запущенных доменах. Как показано в листинге 5, большую часть работы выполняют вызовы функций listDomainsID() и lookupByID().

Листинг 5. Python-сценарий для распечатки списка доменов
import libvirt
conn=libvirt.open("qemu:///system")

for id in conn.listDomainsID():
   dom = conn.lookupByID(id)
   infos = dom.info()
   print 'ID = %d' % id
   print 'Name =  %s' % dom.name()
   print 'State = %d' % infos[0]
   print 'Max Memory = %d' % infos[1]
   print 'Number of virt CPUs = %d' % infos[3]
   print 'CPU Time (in ns) = %d' % infos[2]
   print ' '

Выходные данные этого сценария с одним активным и одним приостановленным доменами выглядят следующим образом.

ID = 3
Name =  ubuntu100403
State = 3
Max Memory = 1048576
Number of virt CPUs = 1
CPU Time (in ns) = 1048576

ID = 4
Name =  Win7_64-bit
State = 1
Max Memory = 2097152
Number of virt CPUs = 2
CPU Time (in ns) = 2097152

libvirt реализует также строки Python docstrings для всех классов и методов. Чтобы получить доступ к этой информации, введите help(libvirt) для получения общей справки или help(libvirt.class) для справки по определенному классу. Перед вводом команды help() нужно импортировать модуль libvirt. Версия, которую я тестировал для данного обзора, реализует следующие 11 классов:

  • libvirtError
  • virConnect
  • virDomain
  • virDomainShapshot
  • virInterface
  • virNWFilter
  • virNetwork
  • virSecret
  • virStoragePool
  • virStorageVol
  • virStream

Этот список поможет вам декодировать синтаксис для доступа к функциям libvirt из Python. Кроме того, он дает список всех именованных констант, таких как VIR_DOMAIN_RUNNING, значение которой равно 1. Такие функции, как используемая выше dom.info(), возвращают целое значение и должны декодироваться по этой таблице констант.


Полезные сценарии автоматизации

Для управления установкой KVM можно написать любое число сценариев с использованием libvirt и Python. Возможно, при небольшом количестве доменов это неэффективно, но быстро начинает экономить время, когда счет идет на десятки. Одна простая задача позволяет вносить массовые изменения в статические IP-адреса всех образов доменов. Для этого выполняется перебор всех файлов .conf с внесением соответствующих изменений. Python содержит множество встроенных функций, которые помогают решить эту задачу.

В листинге 6 приведен пример XML-определения сети.

Листинг 6. XML-файл конфигурации сети
<network>
  <name>testnetwork</name>
  <bridge name="virbr1" />
  <forward/>
  <ip address="192.168.100.1" netmask="255.255.255.0">
    <dhcp>
      <range start="192.168.100.2" end="192.168.100.254" />
      <host mac='de:af:de:af:00:02' name='vm-1' ip='192.168.100.2' />
      <host mac='de:af:de:af:00:03' name='vm-2' ip='192.168.100.3' />
      <host mac='de:af:de:af:00:04' name='vm-3' ip='192.168.100.4' />
      <host mac='de:af:de:af:00:05' name='vm-4' ip='192.168.100.5' />
      <host mac='de:af:de:af:00:06' name='vm-5' ip='192.168.100.6' />
      <host mac='de:af:de:af:00:07' name='vm-6' ip='192.168.100.7' />
      <host mac='de:af:de:af:00:08' name='vm-7' ip='192.168.100.8' />
      <host mac='de:af:de:af:00:09' name='vm-8' ip='192.168.100.9' />
      <host mac='de:af:de:af:00:10' name='vm-9' ip='192.168.100.10' />
    </dhcp
  </ip>
</network>

Если нужно изменить маску главной подсети с 192.168.100 на 192.168.200, достаточно открыть файл конфигурации в редакторе и выполнить операцию глобального поиска и замены. Труднее сделать нечто немного более замысловатое, например, увеличить на 10 все IP- и MAC-адреса, начинающиеся с 2. В листинге 7 показано, как это сделать, написав немногим более 20 строк кода Python.

Листинг 7. Сценарий Python для замены MAC- и IP-адресов
#!/usr/bin/env python

from xml.dom.minidom import parseString
import sys

def main():
    target = sys.argv[1]
    number = int(sys.argv[2])

    xml = open(target, 'r').read()
    doc = parseString(xml)
    for host in doc.getElementsByTagName('host'):
        ip = host.getAttribute('ip')
        parts = ip.split('.')
        parts[-1] = str(int(parts[-1]) + number)
        host.setAttribute('ip', '.'.join(parts))

        mac = host.getAttribute('mac')
        parts = mac.split(':')
        parts[-1] = str(int(parts[-1]) + number)
        host.setAttribute('mac', ':'.join(parts))

    f = open(target, 'w')
    f.write(doc.toxml())
    f.close()

if __name__ == '__main__':
    main()

Этот сценарий демонстрирует мощь Python при использовании стандартной библиотеки Python. В данном случае для выполнения тяжелой работы по синтаксическому анализу XML-файла применяется parseString из xml.dom.minidom. Имея определенный XML-атрибут, достаточно разбить его на отдельные части с помощью функции Python string.split. Затем просто выполняем вычисления и вновь собираем строки. Этот подход можно расширить, чтобы вносить массовые изменения в любой XML-файл, включая файлы .conf библиотеки libvirt.

Еще один полезный сценарий делает снимок текущего состояния всех запущенных доменов. Этот сценарий сначала получает список всех запущенных доменов, а затем останавливает каждый из них и создает снимок текущего состояния. Эта операция может показаться непрактичной для рабочей среды, но можно настроить ее запуск на полночь в виде задания CRON. Такой сценарий легко осуществить с помощью уже описанных команд и обращения к snapshotCreateXML().


Заключение

Эта статья лишь приоткрыла возможности технологии libvirt. В разделе Ресурсы есть ссылки на более глубокие обзоры libvirt и виртуализации в целом. Основы KVM станут гораздо понятнее, когда вы начнете самостоятельно создавать код для контроля и управления своей средой. Следующая статья этого цикла посвящена созданию нескольких реальных инструментов управления виртуальной средой с применением полученных здесь знаний.

Ресурсы

Научиться

Получить продукты и технологии

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

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, Linux
ArticleID=822393
ArticleTitle=Создание KVM-сценариев на языке Python: Часть 1. Библиотека libvirt
publish-date=06222012