- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF120:VirtualBox
Материал из Linuxformat.
- Виртуальные машины Автоматизируем рутинные операции через сценарии на Python
Содержание |
VirtualBox: Python управляет
- Графический интерфейс и диалоговые окна – далеко не единственный способ взаимодействия с виртуальными машинами VirtualBox. Николай Иготти покажет, как делать это из программ на Python.
В широком спектре доступных решений для виртуализации продукт VirtualBox (http://www.virtualbox.org) от Sun Microsystems занимает достойное место. Это высокопроизводительное решение с открытым кодом, работающее на Linux, Windows, Mac OS X, Solaris и FreeBSD, позволяет запускать самые различные гостевые ОС со скоростью, близкой к скорости реального оборудования. Одним из интересных свойств данного продукта является полная открытость всех интерфейсов, то есть возможность взаимодействовать с VirtualBox из приложений, написанных на популярных языках программирования. Официально поддерживаются C, C++, Java, Perl и Python, но можно использовать и любой другой язык, для которого реализован вызов SOAP-методов.
Я разрабатывал поддержку Python в VirtualBox, и хотел бы поподробнее рассказать о различных тонких моментах и интересных элементах функциональности. Чтобы разговор был более предметным, рекомендую скачать последнюю версию VirtualBox 2.2 для вашей операционной системы, а также SDK VirtualBox с http://www.virtualbox.org/wiki/Downloads (требуется бесплатная регистрация). Желательно также установить хотя бы одну виртуальную машину, чтобы нам было чем управлять.
Как это работает
Внешние интерфейсы VirtualBox описаны в документации к SDK (на английском языке), а XML-файл bindings/VirtualBox.xidl предоставляет полную информацию об устройстве API. Кроме этого, может быть интересно исследовать исходные коды примеров, поставляемые с SDK.
Доступ к внешним интерфейсам технически осуществляется двумя способами: через непосредственный вызов методов COM, XPCOM (компонентной технологии, происходящей от Mozilla) или через SOAP (то есть специально сформированные HTTP-запросы, обрабатываемые сервером vboxwebsrv). Первый вариант гораздо быстрее, и предоставляет доступ к более широкой функциональности: например, уведомлениям об изменении состояния. К сожалению, он требует, чтобы вызывающий процесс и VirtualBox выполнялись на одной машине, что может быть не всегда удобно. Второй способ позволяет использовать удаленные сервера, но имеет ограничения по функциональности и производительности, а также требует запуска специального приложения на каждом из серверов.
Интерфейсы для Python разрабатывались таким образом, чтобы по возможности скрыть это различие и использовать один и тот же код для различных сценариев доступа. Тем не менее, данная статья будет в основном посвящена Python и XPCOM.
В качестве примера нетривиального приложения, использующего VirtualBox из Python, рассмотрим интерактивную оболочку, поставляемую в комплекте с SDK. Один и тот же сценарий (shellcommon.py) может работать как через SOAP, так и на локальной машине. Вся разница в инициализационном коде (vboxshell.py), который отличается для COM, XPCOM и режима web-сервиса (SOAP). Если вы работаете в Linux или Solaris, перед использованием необходимо установить переменную VBOX_PROGRAM_PATH следующим образом:
export VBOX_PROGRAM_PATH=/opt/VirtualBox
Здесь /opt/VirtualBox – это название директории, в которую установлен VirtualBox в вашей системе. Также, если SDK находится в /opt/VirtualBox-sdk, переменная PYTHONPATH должна быть установлена как
export PYTHONPATH=/opt/VirtualBox-sdk/bindings/xpcom/python:$VBOX_PROGRAM_PATH
чтобы Python мог найти необходимые модули. После настройки окружения можно просто запустить оболочку командой
python /opt/VirtualBox-sdk/bindings/xpcom/python/samples/vboxshell.py
и вы увидите приглашение, как на рисунке. Чтобы получить список команд, известных оболочке, наберите help. Можете поэкспериментировать в свое удовольствие.
Расширяем оболочку
Как можно видеть, сама по себе оболочка достаточно функциональна и полезна, но нам сейчас будет интересна возможность ее расширения. Предположим, к примеру, что вам необходимо написать команду, которая создает виртуальную машину со смонтированным ISO-образом и запускает ее (скажем, для целей автоматизированного тестирования какого-нибудь дистрибутива). Назовем эту команду makevm.
Откроем shellcommon.py в редакторе и добавим строчку
'makevm':['Make VM with given ISO image', makevmCmd],
к массиву commands. Она просто зарегистрирует нашу команду в списке известных оболочке.
Теперь надо реализовать действия, выполняемые при вызове makevm, то есть написать тело функции makevmCmd(), на которую мы ссылаемся выше.
def makevmCmd(ctx, args): # Имя новой машины name=args[1] # Путь к файлу образа (можно сделать частью команды) hddPath= “/tmp/MyUbuntu/hdd.vdi” # Путь к образу ISO содержащему дистрибутив isoPath=args[2]
Переменная ctx содержит контекст исполнения, откуда можно получить объекты класса VirtualBox и Session, а также доступ к константам. Пример использования контекста можно найти в коде shellcommon.py. Для команды makevm нам надо получить доступ к объекту vb, представляющему собой экземпляр запущенной виртуальной машины VirtualBox.
vb=ctx['vb']
Далее следует найти или создать подключить к VirtualBox ISO-образ, а также определить (или, при необходимости, создать) виртуальный жесткий диск, на который мы будем устанавливать нашу гипотетическую систему:
isoImg=vb.findDVDImage(isoPath) if not isoImg: isoImg=vb.openDVDImage(isoPath, None) hddImg=vb.findHardDisk(hddPath) if not hddImg: hddImg=createHardDisk(“VDI”, hddPath) progress=hddImg.createBaseStorage(4*1024, ctx['ifaces'].HardDiskVariant.Standard) progress.waitForCompletion(-1) hddImg=vb.openHardDisk(hddPath, ctx['ifaces'].AccessMode.ReadWrite)
Как можно видеть, генерация образа жесткого диска происходит в несколько этапов: сначала мы создаем устройство вызовом createHardDisk(), указав желаемый тип (VDI, родной для VirtualBox формат) и путь в файловой системе хост-ОС, затем выделяем под него 4 ГБ методом createBaseStorage() и ждем завершения этой операции. Наконец, винчестер регистрируется в системе методом openHardDisk().
Ключ на старт!
Давайте будем для определенности считать, что мы тестируем сборки Ubuntu. Виртуальные машины с предустановками для этого дистрибутива будем создавать в каталоге /tmp/MyUbuntu. Для этих целей нам потребуется сессионный объект – Session.
session = ctx['mgr'].getSessionObject(vb) mach = vb.createMachine(name, “Ubuntu”, “/tmp/MyUbuntu”,“”) vb.registerMachine(mach) # Запоминть уникальный идентификатор машины id=mach.id print “created machine with UUID”,id
Этот код не должен вызывать затруднений. Мы получаем сессионный объект через контекст, создаем виртуальную машину, расположенную в /tmp/MyUbuntu, с указанным пользователем именем и типом гостевой ОС ‘Ubuntu’, и регистрируем ее. Наконец, мы запоминаем уникальный идентификатор машины и выводим его на консоль.
Полученная нами виртуальная машина не имеет нужной периферии – исправим этот факт, смонтировав наш DVD-образ и подключив к ней жесткий диск. Обратите внимание на первую строку – перед изменением виртуальной машины необходимо получить на нее блокировку, чтобы исключить конфликты одновременного обращения.
# Получить блокировку на доступ к машине vb.openSession(session, id) mach=session.machine mach.DVDDrive.mountImage(isoImg.id) mach.attachHardDisk(hddImg.id, “IDE”, 0, 0) # Сохранить внесенные изменения mach.saveSettings() # Закрыть сессию session.close()
В данном случае мы подсоединяем жесткий диск к виртуальному контроллеру IDE. Можете выбрать SATA или SCSI – это непринципиально.
Теперь все готово к работе – осталось только запустить виртуальную машину, терпеливо дождаться ее остановки и завершить сеанс.
progress = vb.openRemoteSession(session, id, “gui”, “”) progress.waitForCompletion(-1) session.close() return 0
Последняя строка уведомляет оболочку, что по завершении команды ей необходимо продолжить свою работу. На первый взгляд выглядит непросто, но если вдуматься, мы только что написали код, который создает виртуальную машину, виртуальный жесткий диск, монтирует образ DVD и запускает ее. И все это – примерно 20 строчек.
И много чего еще
Давайте протестируем созданную нами команду. Запустите оболочку и введите
vbox> makevm Test /ISO/Linux/Ubuntu/ubuntu-8.10-desktop-i386.iso
Вы увидите виртуальную машину, готовую установить новую ОС. Более того, мы можем использовать команду оболочки guest и начать инсталляцию, не переключая окна.
vbox> guest Test console.keyboard.putScancodes([0x5a,0x1c, 0x5a,0x1c])
Здесь мы эмулируем двойное нажатие на клавишу Enter путем отправки гостевой системе соответствующих скан-кодов. Подробнее про скан-коды клавиатуры можно прочесть по адресу: http://www.quadibloc.com/comp/scan.htm. Домашнее задание: измените команду так, чтобы перед установкой автоматически выбирался русский язык.
Вы также можете эмулировать любые движения мыши; например,
vbox> guest Test console.mouse.putMouseEvent(20,20,0,0)
сдвинет мышь на 20 пикселей вправо и вниз. Полный список методов взаимодействия с гостевой ОС можно получить в документации к интерфейсу IСonsole, идущей в комплекте с SDK VirtualBox.
Но и это еще не все. Оболочка позволяет выполнить любой код Python, использующий API VirtualBox: для этих целей предназначена команда eval. Например,
eval for m in getMachines(ctx): print m.name,m.getNetworkAdapter(0).MACAddress
напечатает MAC-адреса первой сетевой карты всех виртуальных машин.
Как можно видеть, достаточно простые и интуитивно понятные вызовы функций позволяют выполнять весьма сложные операции над виртуальными машинами, и использовать все мощь VirtualBox.
На текущий момент управление VirtualBox из Python возможно на хостах Linux, Solaris и Mac OS X; начиная с 3.0, будет реализована поддержка Windows. Еще раз обращаю ваше внимание на то, что аналогичные интерфейсы можно использовать через SOAP на всех платформах, которые поддерживаются VirtualBox.
Полный код примера в формате патча для shellcommon.py вы найдете на прилагаемом к журналу диске. В заключение хочу сообщить, что на все вопросы, связанные с использованием VirtualBox (и, в частности, API Python) вам с удовольствием ответят на форуме http://forums.virtualbox.org. LXF